From dd3d5da3c7d9d110915c7f7907ce9ffda08e789d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 11:54:30 +0200 Subject: [PATCH 0001/1105] tests: WPS PIN provisioning with per-station PSK preset Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_wps.py | 92 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index b7515937e..dc8635087 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -2245,6 +2245,98 @@ def test_ap_wps_per_station_psk(dev, apdev): dev[1].flush_scan_cache() dev[2].flush_scan_cache() +def test_ap_wps_per_station_psk_preset(dev, apdev): + """WPS PIN provisioning with per-station PSK preset""" + addr0 = dev[0].own_addr() + addr1 = dev[1].own_addr() + addr2 = dev[2].own_addr() + ssid = "wps" + appin = "12345670" + pskfile = "/tmp/ap_wps_per_enrollee_psk_preset.psk_file" + try: + os.remove(pskfile) + except: + pass + + hapd = None + try: + with open(pskfile, "w") as f: + f.write("# WPA PSKs\n") + f.write("wps=1 " + addr0 + " preset-passphrase-0\n") + f.write("wps=1 " + addr2 + " preset-passphrase-2\n") + + params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", + "wpa": "2", "wpa_key_mgmt": "WPA-PSK", + "rsn_pairwise": "CCMP", "ap_pin": appin, + "wpa_psk_file": pskfile} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + logger.info("First enrollee") + pin = dev[0].wps_read_pin() + hapd.request("WPS_PIN any " + pin) + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].request("WPS_PIN %s %s" % (bssid, pin)) + dev[0].wait_connected(timeout=30) + + logger.info("Second enrollee") + pin = dev[1].wps_read_pin() + hapd.request("WPS_PIN any " + pin) + dev[1].scan_for_bss(bssid, freq=2412) + dev[1].request("WPS_PIN %s %s" % (bssid, pin)) + dev[1].wait_connected(timeout=30) + + logger.info("External registrar") + dev[2].scan_for_bss(bssid, freq=2412) + dev[2].wps_reg(bssid, appin) + + logger.info("Verifying PSK results") + psks = get_psk(pskfile) + if addr0 not in psks: + raise Exception("No PSK recorded for sta0") + if addr1 not in psks: + raise Exception("No PSK recorded for sta1") + if addr2 not in psks: + raise Exception("No PSK recorded for sta2") + logger.info("PSK[0]: " + psks[addr0]) + logger.info("PSK[1]: " + psks[addr1]) + logger.info("PSK[2]: " + psks[addr2]) + if psks[addr0] == psks[addr1]: + raise Exception("Same PSK recorded for sta0 and sta1") + if psks[addr0] == psks[addr2]: + raise Exception("Same PSK recorded for sta0 and sta2") + if psks[addr1] == psks[addr2]: + raise Exception("Same PSK recorded for sta1 and sta2") + pmk0 = hapd.request("GET_PMK " + addr0) + pmk1 = hapd.request("GET_PMK " + addr1) + pmk2 = hapd.request("GET_PMK " + addr2) + logger.info("PMK[0]: " + pmk0) + logger.info("PMK[1]: " + pmk1) + logger.info("PMK[2]: " + pmk2) + if pmk0 != "565faec21ff04702d9d17c464e1301efd36c8a3ea46bb866b4bec7fed4384579": + raise Exception("PSK[0] mismatch") + if psks[addr1] != pmk1: + raise Exception("PSK[1] mismatch") + if psks[addr2] != pmk2: + raise Exception("PSK[2] mismatch") + + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + logger.info("First enrollee again") + pin = dev[0].wps_read_pin() + hapd.request("WPS_PIN any " + pin) + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].request("WPS_PIN %s %s" % (bssid, pin)) + dev[0].wait_connected(timeout=30) + psks2 = get_psk(pskfile) + if addr0 not in psks2: + raise Exception("No PSK recorded for sta0 (2)") + if psks[addr0] != psks2[addr0]: + raise Exception("Different PSK recorded for sta0(enrollee) and sta0(enrollee 2)") + finally: + os.remove(pskfile) + def test_ap_wps_per_station_psk_failure(dev, apdev): """WPS PBC provisioning with per-station PSK (file not writable)""" addr0 = dev[0].p2p_dev_addr() From 981b96caa9fc2695f294fd0698c5e81686d0e7d9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 11:54:36 +0200 Subject: [PATCH 0002/1105] WPS: Mark added PSK entry with wps=1 tag for per-Enrollee PSK case Commit 2bab073dfe02 ("WPS: Add new PSK entries with wps=1 tag") added this when writing the new entry into a file, but the in-memory update did not get the tag. Add it there as well. Signed-off-by: Jouni Malinen --- src/ap/wps_hostapd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 7b143b821..5ea206c5e 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -125,6 +125,7 @@ static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, os_memcpy(p->addr, mac_addr, ETH_ALEN); os_memcpy(p->p2p_dev_addr, p2p_dev_addr, ETH_ALEN); os_memcpy(p->psk, psk, PMK_LEN); + p->wps = 1; if (hapd->new_psk_cb) { hapd->new_psk_cb(hapd->new_psk_cb_ctx, mac_addr, p2p_dev_addr, From 458162a271f8240cf1857105231846dbea233a22 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 12:05:43 +0200 Subject: [PATCH 0003/1105] Sync with mac80211-next.git include/uapi/linux/nl80211.h This brings in nl80211 definitions as of 2020-02-07. Signed-off-by: Jouni Malinen --- src/drivers/nl80211_copy.h | 85 +++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index 341e0e8ca..158bccb4a 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -1039,11 +1039,14 @@ * a control port frame and as a notification that a control port frame * has been received. %NL80211_ATTR_FRAME is used to specify the * frame contents. The frame is the raw EAPoL data, without ethernet or - * 802.11 headers. + * 802.11 headers. An optional %NL80211_ATTR_SRC_MAC can be used to send + * pre-auth frames to STAs on behalf of other APs. * When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added * indicating the protocol type of the received frame; whether the frame * was received unencrypted and the MAC address of the peer respectively. + * %NL80211_ATTR_DST_MAC can be used to forward pre-auth frames in + * userspace while using AP mode. * * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. * @@ -2400,6 +2403,18 @@ enum nl80211_commands { * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key * (u16). * + * @NL80211_ATTR_HE_BSS_COLOR: nested attribute for BSS Color Settings. + * + * @NL80211_ATTR_IFTYPE_AKM_SUITES: nested array attribute, with each entry + * using attributes from &enum nl80211_iftype_akm_attributes. This + * attribute is sent in a response to %NL80211_CMD_GET_WIPHY indicating + * supported AKM suites capability per interface. AKMs advertised in + * %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not + * advertised for a specific interface type. + * + * @NL80211_ATTR_SRC_MAC: MAC address used in control port over nl80211 transmit + * @NL80211_ATTR_DST_MAC: MAC address used in control port over nl80211 receive + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2864,6 +2879,13 @@ enum nl80211_attrs { NL80211_ATTR_VLAN_ID, + NL80211_ATTR_HE_BSS_COLOR, + + NL80211_ATTR_IFTYPE_AKM_SUITES, + + NL80211_ATTR_SRC_MAC, + NL80211_ATTR_DST_MAC, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -3583,6 +3605,8 @@ enum nl80211_wmm_rule { * @NL80211_FREQUENCY_ATTR_WMM: this channel has wmm limitations. * This is a nested attribute that contains the wmm limitation per AC. * (see &enum nl80211_wmm_rule) + * @NL80211_FREQUENCY_ATTR_NO_HE: HE operation is not allowed on this channel + * in current regulatory domain. * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number * currently defined * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use @@ -3612,6 +3636,7 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_NO_20MHZ, NL80211_FREQUENCY_ATTR_NO_10MHZ, NL80211_FREQUENCY_ATTR_WMM, + NL80211_FREQUENCY_ATTR_NO_HE, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, @@ -3809,6 +3834,7 @@ enum nl80211_sched_scan_match_attr { * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed + * @NL80211_RRF_NO_HE: HE operation not allowed */ enum nl80211_reg_rule_flags { NL80211_RRF_NO_OFDM = 1<<0, @@ -3826,6 +3852,7 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_HT40PLUS = 1<<14, NL80211_RRF_NO_80MHZ = 1<<15, NL80211_RRF_NO_160MHZ = 1<<16, + NL80211_RRF_NO_HE = 1<<17, }; #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR @@ -5517,6 +5544,14 @@ enum nl80211_feature_flags { * with VLAN tagged frames and separate VLAN-specific netdevs added using * vconfig similarly to the Ethernet case. * + * @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL) + * feature, which prevents bufferbloat by using the expected transmission + * time to limit the amount of data buffered in the hardware. + * + * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS: The driver + * can use src and dst MAC addresses with control port over nl80211 rx + * and tx operations. + * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ @@ -5563,6 +5598,8 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_STA_TX_PWR, NL80211_EXT_FEATURE_SAE_OFFLOAD, NL80211_EXT_FEATURE_VLAN_OFFLOAD, + NL80211_EXT_FEATURE_AQL, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, @@ -6582,5 +6619,51 @@ enum nl80211_obss_pd_attributes { NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_HE_OBSS_PD_ATTR_LAST - 1, }; +/** + * enum nl80211_bss_color_attributes - BSS Color attributes + * @__NL80211_HE_BSS_COLOR_ATTR_INVALID: Invalid + * + * @NL80211_HE_BSS_COLOR_ATTR_COLOR: the current BSS Color. + * @NL80211_HE_BSS_COLOR_ATTR_DISABLED: is BSS coloring disabled. + * @NL80211_HE_BSS_COLOR_ATTR_PARTIAL: the AID equation to be used.. + * + * @__NL80211_HE_BSS_COLOR_ATTR_LAST: Internal + * @NL80211_HE_BSS_COLOR_ATTR_MAX: highest BSS Color attribute. + */ +enum nl80211_bss_color_attributes { + __NL80211_HE_BSS_COLOR_ATTR_INVALID, + + NL80211_HE_BSS_COLOR_ATTR_COLOR, + NL80211_HE_BSS_COLOR_ATTR_DISABLED, + NL80211_HE_BSS_COLOR_ATTR_PARTIAL, + + /* keep last */ + __NL80211_HE_BSS_COLOR_ATTR_LAST, + NL80211_HE_BSS_COLOR_ATTR_MAX = __NL80211_HE_BSS_COLOR_ATTR_LAST - 1, +}; + +/** + * enum nl80211_iftype_akm_attributes - interface type AKM attributes + * @__NL80211_IFTYPE_AKM_ATTR_INVALID: Invalid + * + * @NL80211_IFTYPE_AKM_ATTR_IFTYPES: nested attribute containing a flag + * attribute for each interface type that supports AKM suites specified in + * %NL80211_IFTYPE_AKM_ATTR_SUITES + * @NL80211_IFTYPE_AKM_ATTR_SUITES: an array of u32. Used to indicate supported + * AKM suites for the specified interface types. + * + * @__NL80211_IFTYPE_AKM_ATTR_LAST: Internal + * @NL80211_IFTYPE_AKM_ATTR_MAX: highest interface type AKM attribute. + */ +enum nl80211_iftype_akm_attributes { + __NL80211_IFTYPE_AKM_ATTR_INVALID, + + NL80211_IFTYPE_AKM_ATTR_IFTYPES, + NL80211_IFTYPE_AKM_ATTR_SUITES, + + /* keep last */ + __NL80211_IFTYPE_AKM_ATTR_LAST, + NL80211_IFTYPE_AKM_ATTR_MAX = __NL80211_IFTYPE_AKM_ATTR_LAST - 1, +}; #endif /* __LINUX_NL80211_H */ From 0cb39f4fd5eb96f1c70a53bae460040ecc659212 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 4 Feb 2020 09:04:54 +0100 Subject: [PATCH 0004/1105] HE: Extend BSS color support The HE Operation field for BSS color consists of a disabled, a partial, and 6 color bits. The original commit adding support for BSS color considered this to be a u8. This commit changes this to the actual bits/values. This adds an explicit config parameter for the partial bit. The disabled is set to 0 implicitly if a bss_color is defined. Interoperability testing showed that stations will require a BSS color to be set even if the feature is disabled. Hence the default color is 1 when none is defined inside the config file. Signed-off-by: John Crispin --- hostapd/config_file.c | 5 ++++- hostapd/hostapd.conf | 3 +++ src/ap/ap_config.c | 3 +++ src/ap/ap_config.h | 2 ++ src/ap/ieee802_11_he.c | 9 ++++++--- src/common/ieee802_11_defs.h | 2 +- 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 0169b989d..602c4a2b9 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3474,7 +3474,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "he_mu_beamformer") == 0) { conf->he_phy_capab.he_mu_beamformer = atoi(pos); } else if (os_strcmp(buf, "he_bss_color") == 0) { - conf->he_op.he_bss_color = atoi(pos); + conf->he_op.he_bss_color = atoi(pos) & 0x3f; + conf->he_op.he_bss_color_disabled = 0; + } else if (os_strcmp(buf, "he_bss_color_partial") == 0) { + conf->he_op.he_bss_color_partial = atoi(pos); } else if (os_strcmp(buf, "he_default_pe_duration") == 0) { conf->he_op.he_default_pe_duration = atoi(pos); } else if (os_strcmp(buf, "he_twt_required") == 0) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index f55925afd..eaffed4e6 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -806,6 +806,9 @@ wmm_ac_vo_acm=0 # he_bss_color: BSS color (1-63) #he_bss_color=1 +# he_bss_color_partial: BSS color AID equation +#he_bss_color_partial=0 + #he_default_pe_duration: The duration of PE field in an HE PPDU in us # Possible values are 0 us (default), 4 us, 8 us, 12 us, and 16 us #he_default_pe_duration=0 diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index d4d098b38..b462116af 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -251,6 +251,9 @@ struct hostapd_config * hostapd_config_defaults(void) HE_OPERATION_RTS_THRESHOLD_OFFSET; /* Set default basic MCS/NSS set to single stream MCS 0-7 */ conf->he_op.he_basic_mcs_nss_set = 0xfffc; + conf->he_op.he_bss_color_disabled = 1; + conf->he_op.he_bss_color_partial = 0; + conf->he_op.he_bss_color = 1; #endif /* CONFIG_IEEE80211AX */ /* The third octet of the country string uses an ASCII space character diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index f321017e8..e603605b1 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -854,6 +854,8 @@ struct he_phy_capabilities_info { */ struct he_operation { u8 he_bss_color; + u8 he_bss_color_disabled; + u8 he_bss_color_partial; u8 he_default_pe_duration; u8 he_twt_required; u16 he_rts_threshold; diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 3e22ce412..31cf8d786 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -192,9 +192,12 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid) params |= (hapd->iface->conf->he_op.he_rts_threshold << HE_OPERATION_RTS_THRESHOLD_OFFSET); - if (hapd->iface->conf->he_op.he_bss_color) - params |= (hapd->iface->conf->he_op.he_bss_color << - HE_OPERATION_BSS_COLOR_OFFSET); + if (hapd->iface->conf->he_op.he_bss_color_disabled) + params |= HE_OPERATION_BSS_COLOR_DISABLED; + if (hapd->iface->conf->he_op.he_bss_color_partial) + params |= HE_OPERATION_BSS_COLOR_PARTIAL; + params |= hapd->iface->conf->he_op.he_bss_color << + HE_OPERATION_BSS_COLOR_OFFSET; /* HE minimum required basic MCS and NSS for STAs */ oper->he_mcs_nss_set = diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index ad4ef1a33..748106a9c 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2198,7 +2198,7 @@ struct ieee80211_spatial_reuse { #define HE_OPERATION_BSS_COLOR_MASK ((u32) (BIT(24) | BIT(25) | \ BIT(26) | BIT(27) | \ BIT(28) | BIT(29))) -#define HE_OPERATION_PARTIAL_BSS_COLOR ((u32) BIT(30)) +#define HE_OPERATION_BSS_COLOR_PARTIAL ((u32) BIT(30)) #define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(31)) #define HE_OPERATION_BSS_COLOR_OFFSET 24 From ab8c55358e10ed1492bd37bee8f1c6898382fed6 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 4 Feb 2020 09:05:40 +0100 Subject: [PATCH 0005/1105] HE: Dynamically turn on TWT responder support This allows us to dynamically turn on TWT responder support using an nl80211 attribute. Signed-off-by: John Crispin --- src/ap/beacon.c | 2 ++ src/ap/ieee802_11.h | 2 ++ src/ap/ieee802_11_he.c | 15 +++++++++++++++ src/common/ieee802_11_defs.h | 2 ++ src/drivers/driver.h | 6 ++++++ src/drivers/driver_nl80211.c | 7 +++++++ 6 files changed, 34 insertions(+) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index ecee27aa6..3646245c0 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1422,6 +1422,8 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd) hapd->iface->conf->spr.srg_obss_pd_min_offset; params.he_spr_srg_obss_pd_max_offset = hapd->iface->conf->spr.srg_obss_pd_max_offset; + params.twt_responder = hostapd_get_he_twt_responder(hapd, + IEEE80211_MODE_AP); #endif /* CONFIG_IEEE80211AX */ hapd->reenable_beacon = 0; diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 0a035c564..ab61eca9d 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -96,6 +96,8 @@ u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, enum ieee80211_op_mode opmode, const u8 *he_capab, size_t he_capab_len); +int hostapd_get_he_twt_responder(struct hostapd_data *hapd, + enum ieee80211_op_mode mode); void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, const u8 *buf, size_t len, int ack); void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 31cf8d786..4b23e48c7 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -413,3 +413,18 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, return WLAN_STATUS_SUCCESS; } + + +int hostapd_get_he_twt_responder(struct hostapd_data *hapd, + enum ieee80211_op_mode mode) +{ + u8 *mac_cap; + + if (!hapd->iface->current_mode || + !hapd->iface->current_mode->he_capab) + return 0; + + mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap; + + return mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER; +} diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 748106a9c..f71927053 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2156,6 +2156,8 @@ struct ieee80211_spatial_reuse { /* HE Capabilities Information defines */ +#define HE_MACCAP_TWT_RESPONDER ((u8) BIT(2)) + #define HE_PHYCAP_CHANNEL_WIDTH_SET_IDX 0 #define HE_PHYCAP_CHANNEL_WIDTH_MASK ((u8) (BIT(1) | BIT(2) | \ BIT(3) | BIT(4))) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index d23e436be..caa555bb7 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -182,6 +182,7 @@ struct hostapd_channel_data { struct hostapd_wmm_rule wmm_rules[WMM_AC_NUM]; }; +#define HE_MAC_CAPAB_0 0 #define HE_MAX_MAC_CAPAB_SIZE 6 #define HE_MAX_PHY_CAPAB_SIZE 11 #define HE_MAX_MCS_CAPAB_SIZE 12 @@ -1487,6 +1488,11 @@ struct wpa_driver_ap_params { * he_spr_srg_obss_pd_max_offset - Maximum TX power offset */ int he_spr_srg_obss_pd_max_offset; + + /** + * twt_responder - Whether Target Wait Time responder is enabled + */ + int twt_responder; }; struct wpa_driver_mesh_bss_params { diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 7305ed60b..f1c98b90b 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4348,6 +4348,13 @@ static int wpa_driver_nl80211_set_ap(void *priv, nla_nest_end(msg, spr); } + + if (params->twt_responder) { + wpa_printf(MSG_DEBUG, "nl80211: twt_responder=%d", + params->twt_responder); + if (nla_put_flag(msg, NL80211_ATTR_TWT_RESPONDER)) + goto fail; + } #endif /* CONFIG_IEEE80211AX */ ret = send_and_recv_msgs(drv, msg, NULL, NULL); From 8de0ff0fa1decabfe990017c3ce9892bc5911b8d Mon Sep 17 00:00:00 2001 From: Mikhail Karpenko Date: Tue, 4 Feb 2020 09:05:41 +0100 Subject: [PATCH 0006/1105] HE: Add TWT responder extended capabilities field Set the proper bits inside the extended capabilities field to indicate support for TWT responder. Tested-by: John Crispin Signed-off-by: Mikhail Karpenko --- src/ap/ieee802_11_shared.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index a947bd9d1..4f7a9706a 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -377,6 +377,11 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) *pos |= 0x01; #endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211AX + if (hapd->iconf->ieee80211ax && + hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP)) + *pos |= 0x40; /* Bit 78 - TWT responder */ +#endif /* CONFIG_IEEE80211AX */ break; case 10: /* Bits 80-87 */ #ifdef CONFIG_SAE @@ -440,6 +445,11 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10) len = 10; #endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211AX + if (len < 10 && hapd->iconf->ieee80211ax && + hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP)) + len = 10; +#endif /* CONFIG_IEEE80211AX */ #ifdef CONFIG_SAE if (len < 11 && hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && From 91ea29a79ec9ff336b89be9e9cbcae9a7e99e70a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 13:48:39 +0200 Subject: [PATCH 0007/1105] tests: Remove ap_ht_smps AP using SMPS mode locally is about to be removed from hostapd, so remove the test case that was using it. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ht.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py index dc4c5b9d7..66d30b4b7 100644 --- a/tests/hwsim/test_ap_ht.py +++ b/tests/hwsim/test_ap_ht.py @@ -1165,22 +1165,6 @@ def test_ap_ht40_csa3(dev, apdev): set_world_reg(apdev[0], None, dev[0]) dev[0].flush_scan_cache() -@remote_compatible -def test_ap_ht_smps(dev, apdev): - """SMPS AP configuration options""" - params = {"ssid": "ht1", "ht_capab": "[SMPS-STATIC]"} - try: - hapd = hostapd.add_ap(apdev[0], params) - except: - raise HwsimSkip("Assume mac80211_hwsim was not recent enough to support SMPS") - params = {"ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]"} - hapd2 = hostapd.add_ap(apdev[1], params) - - dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412") - dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412") - hwsim_utils.test_connectivity(dev[0], hapd) - hwsim_utils.test_connectivity(dev[1], hapd2) - @remote_compatible def test_prefer_ht20(dev, apdev): """Preference on HT20 over no-HT""" From 466e48dcd75f67889bc7ffbbda01adbc86ac8eaf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 13:58:54 +0200 Subject: [PATCH 0008/1105] HT: Remove SMPS in AP mode SM Power Save was described in somewhat unclear manner in IEEE Std 802.11n-2009 as far the use of it locally in an AP to save power. That was clarified in IEEE Std 802.11-2016 to allow only a non-AP STA to use SMPS while the AP is required to support an associated STA doing so. The AP itself cannot use SMPS locally and the HT Capability advertisement for this is not appropriate. Remove the parts of SMPS support that involve the AP using it locally. In practice, this reverts the following commits: 04ee647d58a2 ("HT: Let the driver advertise its supported SMPS modes for AP mode") 8f461b50cfe4 ("HT: Pass the smps_mode in AP parameters") da1080d7215f ("nl80211: Advertise and configure SMPS modes") Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 8 -------- hostapd/hostapd.conf | 2 -- hostapd/main.c | 1 - src/ap/beacon.c | 1 - src/ap/hostapd.h | 3 --- src/ap/hw_features.c | 20 -------------------- src/drivers/driver.h | 12 ------------ src/drivers/driver_nl80211.c | 22 ---------------------- src/drivers/driver_nl80211_capa.c | 6 ------ wpa_supplicant/ap.c | 1 - wpa_supplicant/wpa_supplicant.c | 1 - wpa_supplicant/wpa_supplicant_i.h | 1 - 12 files changed, 78 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 602c4a2b9..3d7c3ced7 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1171,14 +1171,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf, } if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]")) conf->secondary_channel = 0; - if (os_strstr(capab, "[SMPS-STATIC]")) { - conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; - conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC; - } - if (os_strstr(capab, "[SMPS-DYNAMIC]")) { - conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; - conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC; - } if (os_strstr(capab, "[GF]")) conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD; if (os_strstr(capab, "[SHORT-GI-20]")) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index eaffed4e6..395ddfa00 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -598,8 +598,6 @@ wmm_ac_vo_acm=0 # channels if needed or creation of 40 MHz channel maybe rejected based # on overlapping BSSes. These changes are done automatically when hostapd # is setting up the 40 MHz channel. -# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC] -# (SMPS disabled if neither is set) # HT-greenfield: [GF] (disabled if not set) # Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set) # Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set) diff --git a/hostapd/main.c b/hostapd/main.c index 9bca26e35..d3657fcfa 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -218,7 +218,6 @@ static int hostapd_driver_init(struct hostapd_iface *iface) struct wowlan_triggers *triggs; iface->drv_flags = capa.flags; - iface->smps_modes = capa.smps_modes; iface->probe_resp_offloads = capa.probe_resp_offloads; /* * Use default extended capa values from per-radio information diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 3646245c0..0bab464c2 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1326,7 +1326,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, break; } params->isolate = hapd->conf->isolate; - params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK; #ifdef NEED_AP_MLME params->cts_protect = !!(ieee802_11_erp_info(hapd) & ERP_INFO_USE_PROTECTION); diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 2358d1664..7605041d1 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -463,9 +463,6 @@ struct hostapd_iface { u64 drv_flags; - /* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */ - unsigned int smps_modes; - /* * A bitmap of supported protocols for probe response offload. See * struct wpa_driver_capa in driver.h diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 0d856d572..83aecade3 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -561,26 +561,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) return 0; } - switch (conf & HT_CAP_INFO_SMPS_MASK) { - case HT_CAP_INFO_SMPS_STATIC: - if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) { - wpa_printf(MSG_ERROR, - "Driver does not support configured HT capability [SMPS-STATIC]"); - return 0; - } - break; - case HT_CAP_INFO_SMPS_DYNAMIC: - if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) { - wpa_printf(MSG_ERROR, - "Driver does not support configured HT capability [SMPS-DYNAMIC]"); - return 0; - } - break; - case HT_CAP_INFO_SMPS_DISABLED: - default: - break; - } - if ((conf & HT_CAP_INFO_GREEN_FIELD) && !(hw & HT_CAP_INFO_GREEN_FIELD)) { wpa_printf(MSG_ERROR, "Driver does not support configured " diff --git a/src/drivers/driver.h b/src/drivers/driver.h index caa555bb7..148e4999d 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1402,14 +1402,6 @@ struct wpa_driver_ap_params { */ u8 p2p_go_ctwindow; - /** - * smps_mode - SMPS mode - * - * SMPS mode to be used by the AP, specified as the relevant bits of - * ht_capab (i.e. HT_CAP_INFO_SMPS_*). - */ - unsigned int smps_mode; - /** * disable_dgaf - Whether group-addressed frames are disabled */ @@ -1836,10 +1828,6 @@ struct wpa_driver_capa { #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ (drv_flags & WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE) -#define WPA_DRIVER_SMPS_MODE_STATIC 0x00000001 -#define WPA_DRIVER_SMPS_MODE_DYNAMIC 0x00000002 - unsigned int smps_modes; - unsigned int wmm_ac_supported:1; unsigned int mac_addr_rand_scan_supported:1; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index f1c98b90b..6c26e8ba8 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4102,7 +4102,6 @@ static int wpa_driver_nl80211_set_ap(void *priv, int ret = -ENOBUFS; int beacon_set; int num_suites; - int smps_mode; u32 suites[10], suite; u32 ver; #ifdef CONFIG_MESH @@ -4235,27 +4234,6 @@ static int wpa_driver_nl80211_set_ap(void *priv, nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite)) goto fail; - if (params->ht_opmode != -1) { - switch (params->smps_mode) { - case HT_CAP_INFO_SMPS_DYNAMIC: - wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - dynamic"); - smps_mode = NL80211_SMPS_DYNAMIC; - break; - case HT_CAP_INFO_SMPS_STATIC: - wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - static"); - smps_mode = NL80211_SMPS_STATIC; - break; - default: - /* invalid - fallback to smps off */ - case HT_CAP_INFO_SMPS_DISABLED: - wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - off"); - smps_mode = NL80211_SMPS_OFF; - break; - } - if (nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, smps_mode)) - goto fail; - } - if (params->beacon_ies) { wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies", params->beacon_ies); diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 6968e8e2a..a0f6e52ea 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -491,12 +491,6 @@ static void wiphy_info_feature_flags(struct wiphy_info_data *info, if (flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR) info->mac_addr_rand_sched_scan_supported = 1; - if (flags & NL80211_FEATURE_STATIC_SMPS) - capa->smps_modes |= WPA_DRIVER_SMPS_MODE_STATIC; - - if (flags & NL80211_FEATURE_DYNAMIC_SMPS) - capa->smps_modes |= WPA_DRIVER_SMPS_MODE_DYNAMIC; - if (flags & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION) info->wmm_ac_supported = 1; diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index e552306d7..76607e121 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -839,7 +839,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, return -1; hapd_iface->owner = wpa_s; hapd_iface->drv_flags = wpa_s->drv_flags; - hapd_iface->smps_modes = wpa_s->drv_smps_modes; hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads; hapd_iface->extended_capa = wpa_s->extended_capa; hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 24a7a28e2..e4449d4da 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6137,7 +6137,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, wpa_s->drv_capa_known = 1; wpa_s->drv_flags = capa.flags; wpa_s->drv_enc = capa.enc; - wpa_s->drv_smps_modes = capa.smps_modes; wpa_s->drv_rrm_flags = capa.rrm_flags; wpa_s->probe_resp_offloads = capa.probe_resp_offloads; wpa_s->max_scan_ssids = capa.max_scan_ssids; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index ac4a1ba4e..219568a7f 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -724,7 +724,6 @@ struct wpa_supplicant { u64 drv_flags; unsigned int drv_enc; - unsigned int drv_smps_modes; unsigned int drv_rrm_flags; /* From b4b1b122e84989d55b23010574011e0eb6ab658c Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 7 Feb 2020 01:10:13 -0800 Subject: [PATCH 0009/1105] hs20-osu-client: Enable webkit2 support This is my mostly-ignorant attempt to port hs20-osu-client to webkit2 API. Signed-off-by: Ben Greear --- hs20/client/Makefile | 9 +++++ src/utils/browser.c | 89 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/hs20/client/Makefile b/hs20/client/Makefile index 67f6f55c5..cc2af03f4 100644 --- a/hs20/client/Makefile +++ b/hs20/client/Makefile @@ -30,8 +30,17 @@ CFLAGS += -I../../src ifndef CONFIG_NO_BROWSER ifndef CONFIG_BROWSER_SYSTEM +TEST_WK := $(shell pkg-config --silence-errors --cflags webkitgtk-3.0) +ifeq ($(TEST_WK),) +# Try webkit2 +GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkit2gtk-4.0) +GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkit2gtk-4.0) +CFLAGS += -DUSE_WEBKIT2 +else GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0) GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0) +endif + CFLAGS += $(GTKCFLAGS) LIBS += $(GTKLIBS) endif diff --git a/src/utils/browser.c b/src/utils/browser.c index ad0b382fb..43d47dca3 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -7,7 +7,11 @@ */ #include "includes.h" +#ifdef USE_WEBKIT2 +#include +#else /* USE_WEBKIT2 */ #include +#endif /* USE_WEBKIT2 */ #include "common.h" #include "browser.h" @@ -53,7 +57,11 @@ static void browser_update_title(struct browser_context *ctx) static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec, struct browser_context *ctx) { +#ifdef USE_WEBKIT2 + ctx->progress = 100 * webkit_web_view_get_estimated_load_progress(view); +#else /* USE_WEBKIT2 */ ctx->progress = 100 * webkit_web_view_get_progress(view); +#endif /* USE_WEBKIT2 */ wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__, ctx->progress); browser_update_title(ctx); @@ -63,23 +71,43 @@ static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec, static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec, struct browser_context *ctx) { +#ifdef USE_WEBKIT2 + int status = webkit_web_view_get_estimated_load_progress(view); +#else /* USE_WEBKIT2 */ int status = webkit_web_view_get_load_status(view); +#endif /* USE_WEBKIT2 */ wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s", __func__, status, webkit_web_view_get_uri(view)); } static void view_cb_resource_request_starting(WebKitWebView *view, +#ifndef USE_WEBKIT2 WebKitWebFrame *frame, +#endif /* USE_WEBKIT2 */ WebKitWebResource *res, +#ifdef USE_WEBKIT2 + WebKitURIRequest *req, +#else /* USE_WEBKIT2 */ WebKitNetworkRequest *req, WebKitNetworkResponse *resp, +#endif /* USE_WEBKIT2 */ struct browser_context *ctx) { +#ifdef USE_WEBKIT2 + const gchar *uri = webkit_uri_request_get_uri(req); +#else /* USE_WEBKIT2 */ const gchar *uri = webkit_network_request_get_uri(req); +#endif /* USE_WEBKIT2 */ wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); - if (g_str_has_suffix(uri, "/favicon.ico")) + if (g_str_has_suffix(uri, "/favicon.ico")) { +#ifdef USE_WEBKIT2 + webkit_uri_request_set_uri(req, "about:blank"); +#else /* USE_WEBKIT2 */ webkit_network_request_set_uri(req, "about:blank"); +#endif /* USE_WEBKIT2 */ + } + if (g_str_has_prefix(uri, "osu://")) { ctx->success = atoi(uri + 6); gtk_main_quit(); @@ -96,21 +124,49 @@ static void view_cb_resource_request_starting(WebKitWebView *view, static gboolean view_cb_mime_type_policy_decision( - WebKitWebView *view, WebKitWebFrame *frame, WebKitNetworkRequest *req, + WebKitWebView *view, +#ifndef USE_WEBKIT2 + WebKitWebFrame *frame, WebKitNetworkRequest *req, gchar *mime, WebKitWebPolicyDecision *policy, +#else /* USE_WEBKIT2 */ + WebKitPolicyDecision *policy, + WebKitPolicyDecisionType type, +#endif /* USE_WEBKIT2 */ struct browser_context *ctx) { +#ifdef USE_WEBKIT2 + wpa_printf(MSG_DEBUG, "BROWSER:%s type=%d", __func__, type); + switch (type) { + case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: { + /* This function makes webkit send a download signal for all + * unknown mime types. */ + WebKitResponsePolicyDecision *response; + + response = WEBKIT_RESPONSE_POLICY_DECISION(policy); + if (!webkit_response_policy_decision_is_mime_type_supported( + response)) { + webkit_policy_decision_download(policy); + return TRUE; + } + break; + } + default: + break; + } +#else /* USE_WEBKIT2 */ wpa_printf(MSG_DEBUG, "BROWSER:%s mime=%s", __func__, mime); if (!webkit_web_view_can_show_mime_type(view, mime)) { webkit_web_policy_decision_download(policy); return TRUE; } +#endif /* USE_WEBKIT2 */ return FALSE; } +#ifndef USE_WEBKIT2 static gboolean view_cb_download_requested(WebKitWebView *view, WebKitDownload *dl, struct browser_context *ctx) @@ -120,6 +176,7 @@ static gboolean view_cb_download_requested(WebKitWebView *view, wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); return FALSE; } +#endif /* USE_WEBKIT2 */ static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title, @@ -137,6 +194,7 @@ static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title, } +#ifndef USE_WEBKIT2 static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame, const char *title, struct browser_context *ctx) @@ -146,24 +204,31 @@ static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame, ctx->title = os_strdup(title); browser_update_title(ctx); } +#endif /* USE_WEBKIT2 */ int hs20_web_browser(const char *url) { GtkWidget *scroll; - SoupSession *s; WebKitWebView *view; +#ifdef USE_WEBKIT2 + WebKitSettings *settings; +#else /* USE_WEBKIT2 */ WebKitWebSettings *settings; + SoupSession *s; +#endif /* USE_WEBKIT2 */ struct browser_context ctx; memset(&ctx, 0, sizeof(ctx)); if (!gtk_init_check(NULL, NULL)) return -1; +#ifndef USE_WEBKIT2 s = webkit_get_default_session(); g_object_set(G_OBJECT(s), "ssl-ca-file", "/etc/ssl/certs/ca-certificates.crt", NULL); g_object_set(G_OBJECT(s), "ssl-strict", FALSE, NULL); +#endif /* USE_WEBKIT2 */ ctx.win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_role(GTK_WINDOW(ctx.win), "Hotspot 2.0 client"); @@ -181,16 +246,30 @@ int hs20_web_browser(const char *url) G_CALLBACK(view_cb_notify_progress), &ctx); g_signal_connect(G_OBJECT(view), "notify::load-status", G_CALLBACK(view_cb_notify_load_status), &ctx); +#ifdef USE_WEBKIT2 + g_signal_connect(G_OBJECT(view), "resource-load-started", + G_CALLBACK(view_cb_resource_request_starting), &ctx); + g_signal_connect(G_OBJECT(view), "decide-policy", + G_CALLBACK(view_cb_mime_type_policy_decision), &ctx); + /* TODO: Implement these? + g_signal_connect(G_OBJECT(view), "download-started", + G_CALLBACK(view_cb_download_requested), &ctx); + g_signal_connect(G_OBJECT(view), "notify::title", + G_CALLBACK(view_cb_title_changed), &ctx); + */ +#else /* USE_WEBKIT2 */ g_signal_connect(G_OBJECT(view), "resource-request-starting", G_CALLBACK(view_cb_resource_request_starting), &ctx); g_signal_connect(G_OBJECT(view), "mime-type-policy-decision-requested", G_CALLBACK(view_cb_mime_type_policy_decision), &ctx); g_signal_connect(G_OBJECT(view), "download-requested", G_CALLBACK(view_cb_download_requested), &ctx); - g_signal_connect(G_OBJECT(view), "hovering-over-link", - G_CALLBACK(view_cb_hovering_over_link), &ctx); g_signal_connect(G_OBJECT(view), "title-changed", G_CALLBACK(view_cb_title_changed), &ctx); +#endif /* USE_WEBKIT2 */ + + g_signal_connect(G_OBJECT(view), "hovering-over-link", + G_CALLBACK(view_cb_hovering_over_link), &ctx); gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(ctx.win), GTK_WIDGET(scroll)); From 921ea4962ea41e9db456a044733e5be1676d128a Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 7 Feb 2020 01:10:16 -0800 Subject: [PATCH 0010/1105] hs20-osu-client: Ignore TLS errors with webkit2 Hopefully this helps with self-signed certificates. This matches the older behavior with webkit. Signed-off-by: Ben Greear --- src/utils/browser.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/utils/browser.c b/src/utils/browser.c index 43d47dca3..504523625 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -213,6 +213,7 @@ int hs20_web_browser(const char *url) WebKitWebView *view; #ifdef USE_WEBKIT2 WebKitSettings *settings; + WebKitWebContext *wkctx; #else /* USE_WEBKIT2 */ WebKitWebSettings *settings; SoupSession *s; @@ -284,6 +285,12 @@ int hs20_web_browser(const char *url) "hs20-client/1.0", NULL); g_object_set(G_OBJECT(settings), "auto-load-images", TRUE, NULL); +#ifdef USE_WEBKIT2 + wkctx = webkit_web_context_get_default(); + webkit_web_context_set_tls_errors_policy( + wkctx, WEBKIT_TLS_ERRORS_POLICY_IGNORE); +#endif /* USE_WEBKIT2 */ + webkit_web_view_load_uri(view, url); gtk_main(); From 61bf9819c1b6f88807b1cc7bb77e1614e798a939 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 17:28:58 +0200 Subject: [PATCH 0011/1105] hs20_web_browser() to allow TLS server validation to be enabled hs20_web_browser() was previously hardcoded to not perform strict TLS server validation. Add an argument to this function to allow that behavior to be configured. The hs20-osu-client users are still using the old behavior, i.e., not validating server certificates, to be usable for testing purposes. Signed-off-by: Jouni Malinen --- hs20/client/oma_dm_client.c | 2 +- hs20/client/osu_client.c | 4 ++-- hs20/client/spp_client.c | 2 +- src/utils/browser-android.c | 2 +- src/utils/browser-system.c | 2 +- src/utils/browser-wpadebug.c | 2 +- src/utils/browser.c | 16 ++++++++++------ src/utils/browser.h | 4 ++-- 8 files changed, 19 insertions(+), 15 deletions(-) diff --git a/hs20/client/oma_dm_client.c b/hs20/client/oma_dm_client.c index d75c84562..bcd68b877 100644 --- a/hs20/client/oma_dm_client.c +++ b/hs20/client/oma_dm_client.c @@ -407,7 +407,7 @@ static int oma_dm_exec_browser(struct hs20_osu_client *ctx, xml_node_t *exec) wpa_printf(MSG_INFO, "Data: %s", data); wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data); write_summary(ctx, "Launch browser to URI '%s'", data); - res = hs20_web_browser(data); + res = hs20_web_browser(data, 1); xml_node_get_text_free(ctx->xml, data); if (res > 0) { wpa_printf(MSG_INFO, "User response in browser completed successfully"); diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c index a94f40c51..b9849cad5 100644 --- a/hs20/client/osu_client.c +++ b/hs20/client/osu_client.c @@ -2406,7 +2406,7 @@ static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir, snprintf(fname, sizeof(fname), "file://%s/osu-providers.html", dir); write_summary(ctx, "Start web browser with OSU provider selection page"); - ret = hs20_web_browser(fname); + ret = hs20_web_browser(fname, 0); selected: if (ret > 0 && (size_t) ret <= osu_count) { @@ -3403,7 +3403,7 @@ int main(int argc, char *argv[]) wpa_printf(MSG_INFO, "Launch web browser to URL %s", argv[optind + 1]); - ret = hs20_web_browser(argv[optind + 1]); + ret = hs20_web_browser(argv[optind + 1], 1); wpa_printf(MSG_INFO, "Web browser result: %d", ret); } else if (strcmp(argv[optind], "parse_cert") == 0) { if (argc - optind < 2) { diff --git a/hs20/client/spp_client.c b/hs20/client/spp_client.c index c619541ae..39d10e036 100644 --- a/hs20/client/spp_client.c +++ b/hs20/client/spp_client.c @@ -547,7 +547,7 @@ static int hs20_spp_exec(struct hs20_osu_client *ctx, xml_node_t *exec, } wpa_printf(MSG_INFO, "Launch browser to URI '%s'", uri); write_summary(ctx, "Launch browser to URI '%s'", uri); - res = hs20_web_browser(uri); + res = hs20_web_browser(uri, 1); xml_node_get_text_free(ctx->xml, uri); if (res > 0) { wpa_printf(MSG_INFO, "User response in browser completed successfully - sessionid='%s'", diff --git a/src/utils/browser-android.c b/src/utils/browser-android.c index 71a165269..26c83d630 100644 --- a/src/utils/browser-android.c +++ b/src/utils/browser-android.c @@ -62,7 +62,7 @@ static void http_req(void *ctx, struct http_request *req) } -int hs20_web_browser(const char *url) +int hs20_web_browser(const char *url, int ignore_tls) { struct http_server *http; struct in_addr addr; diff --git a/src/utils/browser-system.c b/src/utils/browser-system.c index aed39706c..d87d97b5a 100644 --- a/src/utils/browser-system.c +++ b/src/utils/browser-system.c @@ -62,7 +62,7 @@ static void http_req(void *ctx, struct http_request *req) } -int hs20_web_browser(const char *url) +int hs20_web_browser(const char *url, int ignore_tls) { struct http_server *http; struct in_addr addr; diff --git a/src/utils/browser-wpadebug.c b/src/utils/browser-wpadebug.c index dfb4b6797..d32a85bdf 100644 --- a/src/utils/browser-wpadebug.c +++ b/src/utils/browser-wpadebug.c @@ -63,7 +63,7 @@ static void http_req(void *ctx, struct http_request *req) } -int hs20_web_browser(const char *url) +int hs20_web_browser(const char *url, int ignore_tls) { struct http_server *http; struct in_addr addr; diff --git a/src/utils/browser.c b/src/utils/browser.c index 504523625..6d59cf740 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -207,13 +207,12 @@ static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame, #endif /* USE_WEBKIT2 */ -int hs20_web_browser(const char *url) +int hs20_web_browser(const char *url, int ignore_tls) { GtkWidget *scroll; WebKitWebView *view; #ifdef USE_WEBKIT2 WebKitSettings *settings; - WebKitWebContext *wkctx; #else /* USE_WEBKIT2 */ WebKitWebSettings *settings; SoupSession *s; @@ -228,7 +227,8 @@ int hs20_web_browser(const char *url) s = webkit_get_default_session(); g_object_set(G_OBJECT(s), "ssl-ca-file", "/etc/ssl/certs/ca-certificates.crt", NULL); - g_object_set(G_OBJECT(s), "ssl-strict", FALSE, NULL); + if (ignore_tls) + g_object_set(G_OBJECT(s), "ssl-strict", FALSE, NULL); #endif /* USE_WEBKIT2 */ ctx.win = gtk_window_new(GTK_WINDOW_TOPLEVEL); @@ -286,9 +286,13 @@ int hs20_web_browser(const char *url) g_object_set(G_OBJECT(settings), "auto-load-images", TRUE, NULL); #ifdef USE_WEBKIT2 - wkctx = webkit_web_context_get_default(); - webkit_web_context_set_tls_errors_policy( - wkctx, WEBKIT_TLS_ERRORS_POLICY_IGNORE); + if (ignore_tls) { + WebKitWebContext *wkctx; + + wkctx = webkit_web_context_get_default(); + webkit_web_context_set_tls_errors_policy( + wkctx, WEBKIT_TLS_ERRORS_POLICY_IGNORE); + } #endif /* USE_WEBKIT2 */ webkit_web_view_load_uri(view, url); diff --git a/src/utils/browser.h b/src/utils/browser.h index aaa0eed26..3af13b9a1 100644 --- a/src/utils/browser.h +++ b/src/utils/browser.h @@ -10,12 +10,12 @@ #define BROWSER_H #ifdef CONFIG_NO_BROWSER -static inline int hs20_web_browser(const char *url) +static inline int hs20_web_browser(const char *url, int ignore_tls) { return -1; } #else /* CONFIG_NO_BROWSER */ -int hs20_web_browser(const char *url); +int hs20_web_browser(const char *url, int ignore_tls); #endif /* CONFIG_NO_BROWSER */ #endif /* BROWSER_H */ From e33a0eecece8799306652ca50d3c5f1c3b3b4fff Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 17:33:58 +0200 Subject: [PATCH 0012/1105] hs20-osu-client: Validate HTTPS server certificate by default (browser) This changes "hs20-osu-client browser " behavior to validate the HTTPS server certificate against the system trust roots. The new command line argument -T can be used to disable this validation. This does not change behavior for SPP/OMA-DM triggered OSU operation, i.e., they continue to not mandate server certificate validation for now to avoid breaking existing test cases. Signed-off-by: Jouni Malinen --- hs20/client/osu_client.c | 9 ++++++--- hs20/client/osu_client.h | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c index b9849cad5..f1b078b1a 100644 --- a/hs20/client/osu_client.c +++ b/hs20/client/osu_client.c @@ -3152,7 +3152,7 @@ static void check_workarounds(struct hs20_osu_client *ctx) static void usage(void) { - printf("usage: hs20-osu-client [-dddqqKt] [-S] \\\n" + printf("usage: hs20-osu-client [-dddqqKtT] [-S] \\\n" " [-w] " "[-r] [-f] \\\n" " [-s] \\\n" @@ -3198,7 +3198,7 @@ int main(int argc, char *argv[]) return -1; for (;;) { - c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tw:x:"); + c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tTw:x:"); if (c < 0) break; switch (c) { @@ -3236,6 +3236,9 @@ int main(int argc, char *argv[]) case 't': wpa_debug_timestamp++; break; + case 'T': + ctx.ignore_tls = 1; + break; case 'w': wpas_ctrl_path = optarg; break; @@ -3403,7 +3406,7 @@ int main(int argc, char *argv[]) wpa_printf(MSG_INFO, "Launch web browser to URL %s", argv[optind + 1]); - ret = hs20_web_browser(argv[optind + 1], 1); + ret = hs20_web_browser(argv[optind + 1], ctx.ignore_tls); wpa_printf(MSG_INFO, "Web browser result: %d", ret); } else if (strcmp(argv[optind], "parse_cert") == 0) { if (argc - optind < 2) { diff --git a/hs20/client/osu_client.h b/hs20/client/osu_client.h index 5c8e6d00b..9b45b03fe 100644 --- a/hs20/client/osu_client.h +++ b/hs20/client/osu_client.h @@ -50,6 +50,8 @@ struct hs20_osu_client { const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */ #define WORKAROUND_OCSP_OPTIONAL 0x00000001 unsigned long int workarounds; + int ignore_tls; /* whether to ignore TLS validation issues with HTTPS + * server certificate */ }; From ffeafc087207117f8bd509104cf99d242f5d1bff Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:00:49 +0200 Subject: [PATCH 0013/1105] webkit2: Use mouse-target-changed to replace hovering-over-link The previous implementation of hovering-over-link signal handler did not really work with webkit2, so replace this with mouse-target-changed handler. Signed-off-by: Jouni Malinen --- src/utils/browser.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index 6d59cf740..51a1a29a1 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -179,6 +179,32 @@ static gboolean view_cb_download_requested(WebKitWebView *view, #endif /* USE_WEBKIT2 */ +#ifdef USE_WEBKIT2 +static void view_cb_mouse_target_changed(WebKitWebView *view, + WebKitHitTestResult *h, + guint modifiers, + struct browser_context *ctx) +{ + WebKitHitTestResultContext hc = webkit_hit_test_result_get_context(h); + const char *uri = NULL; + + if (hc & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) + uri = webkit_hit_test_result_get_link_uri(h); + else if (hc & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE) + uri = webkit_hit_test_result_get_image_uri(h); + else if (hc & WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA) + uri = webkit_hit_test_result_get_media_uri(h); + + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri ? uri : "N/A"); + os_free(ctx->hover_link); + if (uri) + ctx->hover_link = os_strdup(uri); + else + ctx->hover_link = NULL; + + browser_update_title(ctx); +} +#else /* USE_WEBKIT2 */ static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title, gchar *uri, struct browser_context *ctx) { @@ -192,6 +218,7 @@ static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title, browser_update_title(ctx); } +#endif /* USE_WEBKIT2 */ #ifndef USE_WEBKIT2 @@ -252,6 +279,8 @@ int hs20_web_browser(const char *url, int ignore_tls) G_CALLBACK(view_cb_resource_request_starting), &ctx); g_signal_connect(G_OBJECT(view), "decide-policy", G_CALLBACK(view_cb_mime_type_policy_decision), &ctx); + g_signal_connect(G_OBJECT(view), "mouse-target-changed", + G_CALLBACK(view_cb_mouse_target_changed), &ctx); /* TODO: Implement these? g_signal_connect(G_OBJECT(view), "download-started", G_CALLBACK(view_cb_download_requested), &ctx); @@ -265,13 +294,12 @@ int hs20_web_browser(const char *url, int ignore_tls) G_CALLBACK(view_cb_mime_type_policy_decision), &ctx); g_signal_connect(G_OBJECT(view), "download-requested", G_CALLBACK(view_cb_download_requested), &ctx); + g_signal_connect(G_OBJECT(view), "hovering-over-link", + G_CALLBACK(view_cb_hovering_over_link), &ctx); g_signal_connect(G_OBJECT(view), "title-changed", G_CALLBACK(view_cb_title_changed), &ctx); #endif /* USE_WEBKIT2 */ - g_signal_connect(G_OBJECT(view), "hovering-over-link", - G_CALLBACK(view_cb_hovering_over_link), &ctx); - gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(ctx.win), GTK_WIDGET(scroll)); From c0c4685d50f6f64990126da5ccf82f8d66a71466 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:06:20 +0200 Subject: [PATCH 0014/1105] webkit2: Implement notify::title handler Signed-off-by: Jouni Malinen --- src/utils/browser.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index 51a1a29a1..d8f19b3d7 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -19,6 +19,7 @@ struct browser_context { GtkWidget *win; + WebKitWebView *view; int success; int progress; char *hover_link; @@ -221,7 +222,19 @@ static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title, #endif /* USE_WEBKIT2 */ -#ifndef USE_WEBKIT2 +#ifdef USE_WEBKIT2 +static void view_cb_notify_title(WebKitWebView *view, GParamSpec *ps, + struct browser_context *ctx) +{ + const char *title; + + title = webkit_web_view_get_title(ctx->view); + wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s", __func__, title); + os_free(ctx->title); + ctx->title = os_strdup(title); + browser_update_title(ctx); +} +#else /* USE_WEBKIT2 */ static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame, const char *title, struct browser_context *ctx) @@ -270,6 +283,7 @@ int hs20_web_browser(const char *url, int ignore_tls) G_CALLBACK(win_cb_destroy), &ctx); view = WEBKIT_WEB_VIEW(webkit_web_view_new()); + ctx.view = view; g_signal_connect(G_OBJECT(view), "notify::progress", G_CALLBACK(view_cb_notify_progress), &ctx); g_signal_connect(G_OBJECT(view), "notify::load-status", @@ -281,11 +295,11 @@ int hs20_web_browser(const char *url, int ignore_tls) G_CALLBACK(view_cb_mime_type_policy_decision), &ctx); g_signal_connect(G_OBJECT(view), "mouse-target-changed", G_CALLBACK(view_cb_mouse_target_changed), &ctx); + g_signal_connect(G_OBJECT(view), "notify::title", + G_CALLBACK(view_cb_notify_title), &ctx); /* TODO: Implement these? g_signal_connect(G_OBJECT(view), "download-started", G_CALLBACK(view_cb_download_requested), &ctx); - g_signal_connect(G_OBJECT(view), "notify::title", - G_CALLBACK(view_cb_title_changed), &ctx); */ #else /* USE_WEBKIT2 */ g_signal_connect(G_OBJECT(view), "resource-request-starting", From 9ea9d18de713dad217dbbef19555f61966526583 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:11:42 +0200 Subject: [PATCH 0015/1105] webkit2: Replace notfy::progress with notify::estimated-load-progress The older signal handler for notify::progress did not really work with webkit2. Signed-off-by: Jouni Malinen --- src/utils/browser.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index d8f19b3d7..59582e8f3 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -55,18 +55,26 @@ static void browser_update_title(struct browser_context *ctx) } -static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec, - struct browser_context *ctx) -{ #ifdef USE_WEBKIT2 +static void view_cb_notify_estimated_load_progress(WebKitWebView *view, + GParamSpec *pspec, + struct browser_context *ctx) +{ ctx->progress = 100 * webkit_web_view_get_estimated_load_progress(view); -#else /* USE_WEBKIT2 */ - ctx->progress = 100 * webkit_web_view_get_progress(view); -#endif /* USE_WEBKIT2 */ wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__, ctx->progress); browser_update_title(ctx); } +#else /* USE_WEBKIT2 */ +static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec, + struct browser_context *ctx) +{ + ctx->progress = 100 * webkit_web_view_get_progress(view); + wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__, + ctx->progress); + browser_update_title(ctx); +} +#endif /* USE_WEBKIT2 */ static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec, @@ -284,11 +292,12 @@ int hs20_web_browser(const char *url, int ignore_tls) view = WEBKIT_WEB_VIEW(webkit_web_view_new()); ctx.view = view; - g_signal_connect(G_OBJECT(view), "notify::progress", - G_CALLBACK(view_cb_notify_progress), &ctx); g_signal_connect(G_OBJECT(view), "notify::load-status", G_CALLBACK(view_cb_notify_load_status), &ctx); #ifdef USE_WEBKIT2 + g_signal_connect(G_OBJECT(view), "notify::estimated-load-progress", + G_CALLBACK(view_cb_notify_estimated_load_progress), + &ctx); g_signal_connect(G_OBJECT(view), "resource-load-started", G_CALLBACK(view_cb_resource_request_starting), &ctx); g_signal_connect(G_OBJECT(view), "decide-policy", @@ -302,6 +311,8 @@ int hs20_web_browser(const char *url, int ignore_tls) G_CALLBACK(view_cb_download_requested), &ctx); */ #else /* USE_WEBKIT2 */ + g_signal_connect(G_OBJECT(view), "notify::progress", + G_CALLBACK(view_cb_notify_progress), &ctx); g_signal_connect(G_OBJECT(view), "resource-request-starting", G_CALLBACK(view_cb_resource_request_starting), &ctx); g_signal_connect(G_OBJECT(view), "mime-type-policy-decision-requested", From ae07bc46cef3249cb8685c3f88f6476c3680da03 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:16:13 +0200 Subject: [PATCH 0016/1105] webkit2: Do not register notify::load-status handler This did not seem to do anything with webkit2, so do not bother registering the handler. Signed-off-by: Jouni Malinen --- src/utils/browser.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index 59582e8f3..c6bb53ebe 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -77,17 +77,15 @@ static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec, #endif /* USE_WEBKIT2 */ +#ifndef USE_WEBKIT2 static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec, struct browser_context *ctx) { -#ifdef USE_WEBKIT2 - int status = webkit_web_view_get_estimated_load_progress(view); -#else /* USE_WEBKIT2 */ int status = webkit_web_view_get_load_status(view); -#endif /* USE_WEBKIT2 */ wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s", __func__, status, webkit_web_view_get_uri(view)); } +#endif /* USE_WEBKIT2 */ static void view_cb_resource_request_starting(WebKitWebView *view, @@ -292,8 +290,6 @@ int hs20_web_browser(const char *url, int ignore_tls) view = WEBKIT_WEB_VIEW(webkit_web_view_new()); ctx.view = view; - g_signal_connect(G_OBJECT(view), "notify::load-status", - G_CALLBACK(view_cb_notify_load_status), &ctx); #ifdef USE_WEBKIT2 g_signal_connect(G_OBJECT(view), "notify::estimated-load-progress", G_CALLBACK(view_cb_notify_estimated_load_progress), @@ -311,6 +307,8 @@ int hs20_web_browser(const char *url, int ignore_tls) G_CALLBACK(view_cb_download_requested), &ctx); */ #else /* USE_WEBKIT2 */ + g_signal_connect(G_OBJECT(view), "notify::load-status", + G_CALLBACK(view_cb_notify_load_status), &ctx); g_signal_connect(G_OBJECT(view), "notify::progress", G_CALLBACK(view_cb_notify_progress), &ctx); g_signal_connect(G_OBJECT(view), "resource-request-starting", From de0a8906f21299cfbdfd1dbe218a3a898e4390a6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:18:07 +0200 Subject: [PATCH 0017/1105] webkit2: Remove TODO not for download-started It does not look like this signal handler would be needed. Signed-off-by: Jouni Malinen --- src/utils/browser.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index c6bb53ebe..d0f2dbf31 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -302,10 +302,6 @@ int hs20_web_browser(const char *url, int ignore_tls) G_CALLBACK(view_cb_mouse_target_changed), &ctx); g_signal_connect(G_OBJECT(view), "notify::title", G_CALLBACK(view_cb_notify_title), &ctx); - /* TODO: Implement these? - g_signal_connect(G_OBJECT(view), "download-started", - G_CALLBACK(view_cb_download_requested), &ctx); - */ #else /* USE_WEBKIT2 */ g_signal_connect(G_OBJECT(view), "notify::load-status", G_CALLBACK(view_cb_notify_load_status), &ctx); From 7de8bd508f3831b5f8abe48d4ef2c25b8d1b2e39 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:31:31 +0200 Subject: [PATCH 0018/1105] webkit: Track gtk_main()/gtk_main_quit() calls Avoid unnecessary warnings from webkit on calling gtk_main_quit() more than once for a single gtk_main() call. This is also fixing an issue for a corner case where the very first URL has special purpose (osu:// or http://localhost:12345). Signed-off-by: Jouni Malinen --- src/utils/browser.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index d0f2dbf31..b5793627f 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -24,12 +24,15 @@ struct browser_context { int progress; char *hover_link; char *title; + int gtk_main_started; + int quit_gtk_main; }; static void win_cb_destroy(GtkWidget *win, struct browser_context *ctx) { wpa_printf(MSG_DEBUG, "BROWSER:%s", __func__); - gtk_main_quit(); + if (ctx->gtk_main_started) + gtk_main_quit(); } @@ -84,6 +87,10 @@ static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec, int status = webkit_web_view_get_load_status(view); wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s", __func__, status, webkit_web_view_get_uri(view)); + if (ctx->quit_gtk_main) { + gtk_main_quit(); + ctx->gtk_main_started = 0; + } } #endif /* USE_WEBKIT2 */ @@ -106,6 +113,8 @@ static void view_cb_resource_request_starting(WebKitWebView *view, #else /* USE_WEBKIT2 */ const gchar *uri = webkit_network_request_get_uri(req); #endif /* USE_WEBKIT2 */ + int quit = 0; + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); if (g_str_has_suffix(uri, "/favicon.ico")) { #ifdef USE_WEBKIT2 @@ -117,15 +126,23 @@ static void view_cb_resource_request_starting(WebKitWebView *view, if (g_str_has_prefix(uri, "osu://")) { ctx->success = atoi(uri + 6); - gtk_main_quit(); - } - if (g_str_has_prefix(uri, "http://localhost:12345")) { + quit = 1; + } else if (g_str_has_prefix(uri, "http://localhost:12345")) { /* * This is used as a special trigger to indicate that the * user exchange has been completed. */ ctx->success = 1; - gtk_main_quit(); + quit = 1; + } + + if (quit) { + if (ctx->gtk_main_started) { + gtk_main_quit(); + ctx->gtk_main_started = 0; + } else { + ctx->quit_gtk_main = 1; + } } } @@ -344,6 +361,7 @@ int hs20_web_browser(const char *url, int ignore_tls) webkit_web_view_load_uri(view, url); + ctx.gtk_main_started = 1; gtk_main(); gtk_widget_destroy(ctx.win); while (gtk_events_pending()) From 02ed737eee51333be461d17afa5c45f75c43e8c8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:37:02 +0200 Subject: [PATCH 0019/1105] webkit2: Split resource-load-started handler into a separate function This cleans up the #ifdef/#else/#endif mess in the function for webkit vs. webkit2 API. Signed-off-by: Jouni Malinen --- src/utils/browser.c | 63 ++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index b5793627f..8cee320c1 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -95,35 +95,11 @@ static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec, #endif /* USE_WEBKIT2 */ -static void view_cb_resource_request_starting(WebKitWebView *view, -#ifndef USE_WEBKIT2 - WebKitWebFrame *frame, -#endif /* USE_WEBKIT2 */ - WebKitWebResource *res, -#ifdef USE_WEBKIT2 - WebKitURIRequest *req, -#else /* USE_WEBKIT2 */ - WebKitNetworkRequest *req, - WebKitNetworkResponse *resp, -#endif /* USE_WEBKIT2 */ - struct browser_context *ctx) +static void process_request_starting_uri(struct browser_context *ctx, + const char *uri) { -#ifdef USE_WEBKIT2 - const gchar *uri = webkit_uri_request_get_uri(req); -#else /* USE_WEBKIT2 */ - const gchar *uri = webkit_network_request_get_uri(req); -#endif /* USE_WEBKIT2 */ int quit = 0; - wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); - if (g_str_has_suffix(uri, "/favicon.ico")) { -#ifdef USE_WEBKIT2 - webkit_uri_request_set_uri(req, "about:blank"); -#else /* USE_WEBKIT2 */ - webkit_network_request_set_uri(req, "about:blank"); -#endif /* USE_WEBKIT2 */ - } - if (g_str_has_prefix(uri, "osu://")) { ctx->success = atoi(uri + 6); quit = 1; @@ -147,6 +123,39 @@ static void view_cb_resource_request_starting(WebKitWebView *view, } +#ifdef USE_WEBKIT2 +static void view_cb_resource_load_starting(WebKitWebView *view, + WebKitWebResource *res, + WebKitURIRequest *req, + struct browser_context *ctx) +{ + const gchar *uri = webkit_uri_request_get_uri(req); + + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); + if (g_str_has_suffix(uri, "/favicon.ico")) + webkit_uri_request_set_uri(req, "about:blank"); + + process_request_starting_uri(ctx, uri); +} +#else /* USE_WEBKIT2 */ +static void view_cb_resource_request_starting(WebKitWebView *view, + WebKitWebFrame *frame, + WebKitWebResource *res, + WebKitNetworkRequest *req, + WebKitNetworkResponse *resp, + struct browser_context *ctx) +{ + const gchar *uri = webkit_network_request_get_uri(req); + + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); + if (g_str_has_suffix(uri, "/favicon.ico")) + webkit_network_request_set_uri(req, "about:blank"); + + process_request_starting_uri(ctx, uri); +} +#endif /* USE_WEBKIT2 */ + + static gboolean view_cb_mime_type_policy_decision( WebKitWebView *view, #ifndef USE_WEBKIT2 @@ -312,7 +321,7 @@ int hs20_web_browser(const char *url, int ignore_tls) G_CALLBACK(view_cb_notify_estimated_load_progress), &ctx); g_signal_connect(G_OBJECT(view), "resource-load-started", - G_CALLBACK(view_cb_resource_request_starting), &ctx); + G_CALLBACK(view_cb_resource_load_starting), &ctx); g_signal_connect(G_OBJECT(view), "decide-policy", G_CALLBACK(view_cb_mime_type_policy_decision), &ctx); g_signal_connect(G_OBJECT(view), "mouse-target-changed", From 26ad26c8cfb83bf63b3599e907880572af145a06 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:40:42 +0200 Subject: [PATCH 0020/1105] webkit2: Split decide-policy into a separate function This cleans up the #ifdef/#else/#endif mess in the function for webkit vs. webkit2 API. Signed-off-by: Jouni Malinen --- src/utils/browser.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index 8cee320c1..72746881a 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -156,18 +156,12 @@ static void view_cb_resource_request_starting(WebKitWebView *view, #endif /* USE_WEBKIT2 */ -static gboolean view_cb_mime_type_policy_decision( - WebKitWebView *view, -#ifndef USE_WEBKIT2 - WebKitWebFrame *frame, WebKitNetworkRequest *req, - gchar *mime, WebKitWebPolicyDecision *policy, -#else /* USE_WEBKIT2 */ - WebKitPolicyDecision *policy, - WebKitPolicyDecisionType type, -#endif /* USE_WEBKIT2 */ - struct browser_context *ctx) -{ #ifdef USE_WEBKIT2 +static gboolean view_cb_decide_policy(WebKitWebView *view, + WebKitPolicyDecision *policy, + WebKitPolicyDecisionType type, + struct browser_context *ctx) +{ wpa_printf(MSG_DEBUG, "BROWSER:%s type=%d", __func__, type); switch (type) { case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: { @@ -186,17 +180,25 @@ static gboolean view_cb_mime_type_policy_decision( default: break; } + + return FALSE; +} #else /* USE_WEBKIT2 */ +static gboolean view_cb_mime_type_policy_decision( + WebKitWebView *view, WebKitWebFrame *frame, WebKitNetworkRequest *req, + gchar *mime, WebKitWebPolicyDecision *policy, + struct browser_context *ctx) +{ wpa_printf(MSG_DEBUG, "BROWSER:%s mime=%s", __func__, mime); if (!webkit_web_view_can_show_mime_type(view, mime)) { webkit_web_policy_decision_download(policy); return TRUE; } -#endif /* USE_WEBKIT2 */ return FALSE; } +#endif /* USE_WEBKIT2 */ #ifndef USE_WEBKIT2 @@ -323,7 +325,7 @@ int hs20_web_browser(const char *url, int ignore_tls) g_signal_connect(G_OBJECT(view), "resource-load-started", G_CALLBACK(view_cb_resource_load_starting), &ctx); g_signal_connect(G_OBJECT(view), "decide-policy", - G_CALLBACK(view_cb_mime_type_policy_decision), &ctx); + G_CALLBACK(view_cb_decide_policy), &ctx); g_signal_connect(G_OBJECT(view), "mouse-target-changed", G_CALLBACK(view_cb_mouse_target_changed), &ctx); g_signal_connect(G_OBJECT(view), "notify::title", From 5db5290ab472c3ea050ceef251678b76665ea225 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Feb 2020 18:45:12 +0200 Subject: [PATCH 0021/1105] webkit: Clean up USE_WEBKIT2 blocks Use a single block each for webkit and webkit2 signal handlers. This cleans up browser.c to have clear sections for each webkit API version. Signed-off-by: Jouni Malinen --- src/utils/browser.c | 194 ++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 99 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index 72746881a..f864fbf0e 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -58,43 +58,6 @@ static void browser_update_title(struct browser_context *ctx) } -#ifdef USE_WEBKIT2 -static void view_cb_notify_estimated_load_progress(WebKitWebView *view, - GParamSpec *pspec, - struct browser_context *ctx) -{ - ctx->progress = 100 * webkit_web_view_get_estimated_load_progress(view); - wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__, - ctx->progress); - browser_update_title(ctx); -} -#else /* USE_WEBKIT2 */ -static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec, - struct browser_context *ctx) -{ - ctx->progress = 100 * webkit_web_view_get_progress(view); - wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__, - ctx->progress); - browser_update_title(ctx); -} -#endif /* USE_WEBKIT2 */ - - -#ifndef USE_WEBKIT2 -static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec, - struct browser_context *ctx) -{ - int status = webkit_web_view_get_load_status(view); - wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s", - __func__, status, webkit_web_view_get_uri(view)); - if (ctx->quit_gtk_main) { - gtk_main_quit(); - ctx->gtk_main_started = 0; - } -} -#endif /* USE_WEBKIT2 */ - - static void process_request_starting_uri(struct browser_context *ctx, const char *uri) { @@ -124,6 +87,18 @@ static void process_request_starting_uri(struct browser_context *ctx, #ifdef USE_WEBKIT2 + +static void view_cb_notify_estimated_load_progress(WebKitWebView *view, + GParamSpec *pspec, + struct browser_context *ctx) +{ + ctx->progress = 100 * webkit_web_view_get_estimated_load_progress(view); + wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__, + ctx->progress); + browser_update_title(ctx); +} + + static void view_cb_resource_load_starting(WebKitWebView *view, WebKitWebResource *res, WebKitURIRequest *req, @@ -137,26 +112,8 @@ static void view_cb_resource_load_starting(WebKitWebView *view, process_request_starting_uri(ctx, uri); } -#else /* USE_WEBKIT2 */ -static void view_cb_resource_request_starting(WebKitWebView *view, - WebKitWebFrame *frame, - WebKitWebResource *res, - WebKitNetworkRequest *req, - WebKitNetworkResponse *resp, - struct browser_context *ctx) -{ - const gchar *uri = webkit_network_request_get_uri(req); - - wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); - if (g_str_has_suffix(uri, "/favicon.ico")) - webkit_network_request_set_uri(req, "about:blank"); - - process_request_starting_uri(ctx, uri); -} -#endif /* USE_WEBKIT2 */ -#ifdef USE_WEBKIT2 static gboolean view_cb_decide_policy(WebKitWebView *view, WebKitPolicyDecision *policy, WebKitPolicyDecisionType type, @@ -183,38 +140,8 @@ static gboolean view_cb_decide_policy(WebKitWebView *view, return FALSE; } -#else /* USE_WEBKIT2 */ -static gboolean view_cb_mime_type_policy_decision( - WebKitWebView *view, WebKitWebFrame *frame, WebKitNetworkRequest *req, - gchar *mime, WebKitWebPolicyDecision *policy, - struct browser_context *ctx) -{ - wpa_printf(MSG_DEBUG, "BROWSER:%s mime=%s", __func__, mime); - - if (!webkit_web_view_can_show_mime_type(view, mime)) { - webkit_web_policy_decision_download(policy); - return TRUE; - } - - return FALSE; -} -#endif /* USE_WEBKIT2 */ -#ifndef USE_WEBKIT2 -static gboolean view_cb_download_requested(WebKitWebView *view, - WebKitDownload *dl, - struct browser_context *ctx) -{ - const gchar *uri; - uri = webkit_download_get_uri(dl); - wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); - return FALSE; -} -#endif /* USE_WEBKIT2 */ - - -#ifdef USE_WEBKIT2 static void view_cb_mouse_target_changed(WebKitWebView *view, WebKitHitTestResult *h, guint modifiers, @@ -239,7 +166,89 @@ static void view_cb_mouse_target_changed(WebKitWebView *view, browser_update_title(ctx); } + + +static void view_cb_notify_title(WebKitWebView *view, GParamSpec *ps, + struct browser_context *ctx) +{ + const char *title; + + title = webkit_web_view_get_title(ctx->view); + wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s", __func__, title); + os_free(ctx->title); + ctx->title = os_strdup(title); + browser_update_title(ctx); +} + #else /* USE_WEBKIT2 */ + +static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec, + struct browser_context *ctx) +{ + ctx->progress = 100 * webkit_web_view_get_progress(view); + wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__, + ctx->progress); + browser_update_title(ctx); +} + + +static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec, + struct browser_context *ctx) +{ + int status = webkit_web_view_get_load_status(view); + wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s", + __func__, status, webkit_web_view_get_uri(view)); + if (ctx->quit_gtk_main) { + gtk_main_quit(); + ctx->gtk_main_started = 0; + } +} + + +static void view_cb_resource_request_starting(WebKitWebView *view, + WebKitWebFrame *frame, + WebKitWebResource *res, + WebKitNetworkRequest *req, + WebKitNetworkResponse *resp, + struct browser_context *ctx) +{ + const gchar *uri = webkit_network_request_get_uri(req); + + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); + if (g_str_has_suffix(uri, "/favicon.ico")) + webkit_network_request_set_uri(req, "about:blank"); + + process_request_starting_uri(ctx, uri); +} + + +static gboolean view_cb_mime_type_policy_decision( + WebKitWebView *view, WebKitWebFrame *frame, WebKitNetworkRequest *req, + gchar *mime, WebKitWebPolicyDecision *policy, + struct browser_context *ctx) +{ + wpa_printf(MSG_DEBUG, "BROWSER:%s mime=%s", __func__, mime); + + if (!webkit_web_view_can_show_mime_type(view, mime)) { + webkit_web_policy_decision_download(policy); + return TRUE; + } + + return FALSE; +} + + +static gboolean view_cb_download_requested(WebKitWebView *view, + WebKitDownload *dl, + struct browser_context *ctx) +{ + const gchar *uri; + uri = webkit_download_get_uri(dl); + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); + return FALSE; +} + + static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title, gchar *uri, struct browser_context *ctx) { @@ -253,22 +262,8 @@ static void view_cb_hovering_over_link(WebKitWebView *view, gchar *title, browser_update_title(ctx); } -#endif /* USE_WEBKIT2 */ -#ifdef USE_WEBKIT2 -static void view_cb_notify_title(WebKitWebView *view, GParamSpec *ps, - struct browser_context *ctx) -{ - const char *title; - - title = webkit_web_view_get_title(ctx->view); - wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s", __func__, title); - os_free(ctx->title); - ctx->title = os_strdup(title); - browser_update_title(ctx); -} -#else /* USE_WEBKIT2 */ static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame, const char *title, struct browser_context *ctx) @@ -278,6 +273,7 @@ static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame, ctx->title = os_strdup(title); browser_update_title(ctx); } + #endif /* USE_WEBKIT2 */ From 10655d1bc24ab9297b677da73dff76b46f97d258 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 17:25:05 +0200 Subject: [PATCH 0022/1105] nl80211: Add NLA_F_NESTED to nla_nest_start() with older libnl versions This is needed to work around a missing attribute that would cause cfg80211 to reject some nl80211 commands (e.g., NL80211_ATTR_VENDOR_DATA) with new kernel versions that enforce netlink attribute policy validation. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index e4d81b125..6e6c87247 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -17,6 +17,11 @@ #include "utils/list.h" #include "driver.h" +#ifndef NL_CAPABILITY_VERSION_3_5_0 +#define nla_nest_start(msg, attrtype) \ + nla_nest_start(msg, NLA_F_NESTED | (attrtype)) +#endif + struct nl80211_global { void *ctx; struct dl_list interfaces; From 139f6deaff6546c97dbb7a943bf71ea04b76be70 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 17:41:51 +0200 Subject: [PATCH 0023/1105] Remove duplicated wpa_akm_to_suite() entry This was unreachable code due to the previous WPA_KEY_MGTM_OWE case returning from the function. Signed-off-by: Jouni Malinen --- src/common/wpa_common.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 5ecb1eceb..83bac5489 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2100,8 +2100,6 @@ u32 wpa_akm_to_suite(int akm) return RSN_AUTH_KEY_MGMT_OWE; if (akm & WPA_KEY_MGMT_DPP) return RSN_AUTH_KEY_MGMT_DPP; - if (akm & WPA_KEY_MGMT_OSEN) - return RSN_AUTH_KEY_MGMT_OSEN; return 0; } From dd74ddd0dff67c59e416bee9f764b27044a2ade5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 17:43:11 +0200 Subject: [PATCH 0024/1105] nl80211: Handle AKM suite selectors for AP configuration Previously only couple of AKM suite selectors were converted into NL80211_ATTR_AKM_SUITES. Add rest of the AKM suites here. However, since the current kernel interface has a very small limit (NL80211_MAX_NR_AKM_SUITES = 2), add the attribute only when no more than that limit entries are included. cfg80211 would reject the command with any more entries listed. This needs to be extended in cfg80211/nl80211 in a backwards compatible manner, so this seems to be the best that can be done for now in user space. Many drivers do not use this attribute, so must not reject the configuration completely when larger number of AKM suites is configured. Such cases may not work properly with drivers that depend on NL80211_ATTR_AKM_SUITES value. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 53 ++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 6c26e8ba8..d55d8e8f5 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2942,6 +2942,40 @@ static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[], } +static int wpa_key_mgmt_to_suites(unsigned int key_mgmt_suites, u32 suites[], + int max_suites) +{ + int num_suites = 0; + +#define __AKM(a, b) \ + if (num_suites < max_suites && \ + (key_mgmt_suites & (WPA_KEY_MGMT_ ## a))) \ + suites[num_suites++] = (RSN_AUTH_KEY_MGMT_ ## b) + __AKM(IEEE8021X, UNSPEC_802_1X); + __AKM(PSK, PSK_OVER_802_1X); + __AKM(FT_IEEE8021X, FT_802_1X); + __AKM(FT_PSK, FT_PSK); + __AKM(IEEE8021X_SHA256, 802_1X_SHA256); + __AKM(PSK_SHA256, PSK_SHA256); + __AKM(SAE, SAE); + __AKM(FT_SAE, FT_SAE); + __AKM(CCKM, CCKM); + __AKM(OSEN, OSEN); + __AKM(IEEE8021X_SUITE_B, 802_1X_SUITE_B); + __AKM(IEEE8021X_SUITE_B_192, 802_1X_SUITE_B_192); + __AKM(FILS_SHA256, FILS_SHA256); + __AKM(FILS_SHA384, FILS_SHA384); + __AKM(FT_FILS_SHA256, FT_FILS_SHA256); + __AKM(FT_FILS_SHA384, FT_FILS_SHA384); + __AKM(OWE, OWE); + __AKM(DPP, DPP); + __AKM(FT_IEEE8021X_SHA384, FT_802_1X_SHA384); +#undef __AKM + + return num_suites; +} + + #ifdef CONFIG_DRIVER_NL80211_QCA static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv, const u8 *key, size_t key_len) @@ -4102,7 +4136,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, int ret = -ENOBUFS; int beacon_set; int num_suites; - u32 suites[10], suite; + u32 suites[20], suite; u32 ver; #ifdef CONFIG_MESH struct wpa_driver_mesh_bss_params mesh_params; @@ -4196,14 +4230,15 @@ static int wpa_driver_nl80211_set_ap(void *priv, wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x", params->key_mgmt_suites); - num_suites = 0; - if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X) - suites[num_suites++] = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; - if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK) - suites[num_suites++] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; - if (num_suites && - nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), - suites)) + num_suites = wpa_key_mgmt_to_suites(params->key_mgmt_suites, + suites, ARRAY_SIZE(suites)); + if (num_suites > NL80211_MAX_NR_AKM_SUITES) + wpa_printf(MSG_WARNING, + "nl80211: Not enough room for all AKM suites (num_suites=%d > NL80211_MAX_NR_AKM_SUITES)", + num_suites); + else if (num_suites && + nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), + suites)) goto fail; if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA && From 8155b36fae793266fc3a990c30bbf6b72a1b0a1d Mon Sep 17 00:00:00 2001 From: Didier Raboud Date: Sun, 16 Feb 2020 16:14:54 +0100 Subject: [PATCH 0025/1105] Fix VERSION_STR printf() calls in case the postfix strings include % Do not use VERSION_STR directly as the format string to printf() since it is possible for that string to contain '%'. Signed-off-by: Didier Raboud --- hostapd/main.c | 5 +++-- hs20/server/hs20_spp_server.c | 2 +- wpa_supplicant/eapol_test.c | 2 +- wpa_supplicant/wpa_priv.c | 5 +++-- wpa_supplicant/wpa_supplicant.c | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/hostapd/main.c b/hostapd/main.c index d3657fcfa..4af8e8f9c 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -450,11 +450,12 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, static void show_version(void) { fprintf(stderr, - "hostapd v" VERSION_STR "\n" + "hostapd v%s\n" "User space daemon for IEEE 802.11 AP management,\n" "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" "Copyright (c) 2002-2019, Jouni Malinen " - "and contributors\n"); + "and contributors\n", + VERSION_STR); } diff --git a/hs20/server/hs20_spp_server.c b/hs20/server/hs20_spp_server.c index 6c74f541d..347c40a73 100644 --- a/hs20/server/hs20_spp_server.c +++ b/hs20/server/hs20_spp_server.c @@ -176,7 +176,7 @@ int main(int argc, char *argv[]) ctx.root_dir = optarg; break; case 'v': - printf("hs20_spp_server v" VERSION_STR "\n"); + printf("hs20_spp_server v%s\n", VERSION_STR); return 0; default: usage(); diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c index 53d75853b..2fa496813 100644 --- a/wpa_supplicant/eapol_test.c +++ b/wpa_supplicant/eapol_test.c @@ -1390,7 +1390,7 @@ int main(int argc, char *argv[]) eapol_test.ctrl_iface = 1; break; case 'v': - printf("eapol_test v" VERSION_STR "\n"); + printf("eapol_test v%s\n", VERSION_STR); return 0; case 'W': wait_for_monitor++; diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c index f42840610..c9bcf13fe 100644 --- a/wpa_supplicant/wpa_priv.c +++ b/wpa_supplicant/wpa_priv.c @@ -1189,14 +1189,15 @@ static void wpa_priv_fd_workaround(void) static void usage(void) { - printf("wpa_priv v" VERSION_STR "\n" + printf("wpa_priv v%s\n" "Copyright (c) 2007-2017, Jouni Malinen and " "contributors\n" "\n" "usage:\n" " wpa_priv [-Bdd] [-c] [-P] " " \\\n" - " [driver:ifname ...]\n"); + " [driver:ifname ...]\n", + VERSION_STR); } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index e4449d4da..7e06a22f6 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6817,7 +6817,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) wpa_debug_timestamp = global->params.wpa_debug_timestamp = params->wpa_debug_timestamp; - wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR); + wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR); if (eloop_init()) { wpa_printf(MSG_ERROR, "Failed to initialize event loop"); From 0b0ee0f15e9d9084910fb6ef6edcfd8268b40f09 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 4 Feb 2020 09:04:55 +0100 Subject: [PATCH 0026/1105] HE: Propagate BSS color settings to nl80211 Add the code required to send the BSS color settings to the kernel. Signed-off-by: John Crispin --- src/ap/beacon.c | 5 +++++ src/drivers/driver.h | 15 +++++++++++++++ src/drivers/driver_nl80211.c | 15 +++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 0bab464c2..e5e81e78c 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1421,6 +1421,11 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd) hapd->iface->conf->spr.srg_obss_pd_min_offset; params.he_spr_srg_obss_pd_max_offset = hapd->iface->conf->spr.srg_obss_pd_max_offset; + params.he_bss_color_disabled = + hapd->iface->conf->he_op.he_bss_color_disabled; + params.he_bss_color_partial = + hapd->iface->conf->he_op.he_bss_color_partial; + params.he_bss_color = hapd->iface->conf->he_op.he_bss_color; params.twt_responder = hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP); #endif /* CONFIG_IEEE80211AX */ diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 148e4999d..e0cf8d122 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1481,6 +1481,21 @@ struct wpa_driver_ap_params { */ int he_spr_srg_obss_pd_max_offset; + /** + * he_bss_color - Whether the BSS Color is disabled + */ + int he_bss_color_disabled; + + /** + * he_bss_color_partial - The BSS Color AID equation + */ + int he_bss_color_partial; + + /** + * he_bss_color - The BSS Color of the AP + */ + int he_bss_color; + /** * twt_responder - Whether Target Wait Time responder is enabled */ diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index d55d8e8f5..1421aff45 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4362,6 +4362,21 @@ static int wpa_driver_nl80211_set_ap(void *priv, nla_nest_end(msg, spr); } + if (params->freq && params->freq->he_enabled) { + struct nlattr *bss_color; + + bss_color = nla_nest_start(msg, NL80211_ATTR_HE_BSS_COLOR); + if (!bss_color || + (params->he_bss_color_disabled && + nla_put_flag(msg, NL80211_HE_BSS_COLOR_ATTR_DISABLED)) || + (params->he_bss_color_partial && + nla_put_flag(msg, NL80211_HE_BSS_COLOR_ATTR_PARTIAL)) || + nla_put_u8(msg, NL80211_HE_BSS_COLOR_ATTR_COLOR, + params->he_bss_color)) + goto fail; + nla_nest_end(msg, bss_color); + } + if (params->twt_responder) { wpa_printf(MSG_DEBUG, "nl80211: twt_responder=%d", params->twt_responder); From 46cb046500e417a033001975661524f110d725eb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 19:30:47 +0200 Subject: [PATCH 0027/1105] nl80211: Check nla_nest_start() result for NL80211_ATTR_HE_OBSS_PD nla_nest_start() might fail, so need to check its return value similarly to all the other callers. Fixes: a84bf443887d ("HE: Send the AP's OBSS PD settings to the kernel") Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 1421aff45..37933ae9a 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4353,7 +4353,8 @@ static int wpa_driver_nl80211_set_ap(void *priv, spr = nla_nest_start(msg, NL80211_ATTR_HE_OBSS_PD); wpa_printf(MSG_DEBUG, "nl80211: he_spr=%d", params->he_spr); - if (nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, + if (!spr || + nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, params->he_spr_srg_obss_pd_min_offset) || nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, params->he_spr_srg_obss_pd_max_offset)) From cb86e8bac80c69f4f6e115b8de85ea9fca8d3eb2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 23:44:26 +0200 Subject: [PATCH 0028/1105] nl80211: Remove an extra closing parenthesis from a debug message Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 37933ae9a..659f6584d 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3163,7 +3163,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE) ret = 0; if (ret) - wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)", + wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s", ret, strerror(-ret)); /* @@ -3227,8 +3227,9 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, if (ret == -ENOENT) ret = 0; if (ret) - wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; " - "err=%d %s)", ret, strerror(-ret)); + wpa_printf(MSG_DEBUG, + "nl80211: set_key default failed; err=%d %s", + ret, strerror(-ret)); return ret; fail: From 92d407dbd6bdccad266413a9f9da266a30446197 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 22:54:23 +0200 Subject: [PATCH 0029/1105] hostapd configuration for Beacon protection Add a new hostapd configuration parameter beacon_prot=<0/1> to allow Beacon protection to be enabled. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 ++ hostapd/hostapd.conf | 6 ++++++ src/ap/ap_config.h | 1 + src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 1 + 5 files changed, 11 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 3d7c3ced7..3e9f17bf4 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3400,6 +3400,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, pos); return 1; } + } else if (os_strcmp(buf, "beacon_prot") == 0) { + bss->beacon_prot = atoi(pos); } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) { bss->assoc_sa_query_max_timeout = atoi(pos); if (bss->assoc_sa_query_max_timeout == 0) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 395ddfa00..0433fed8a 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1678,6 +1678,12 @@ own_ip_addr=127.0.0.1 # available in deployed devices. #group_mgmt_cipher=AES-128-CMAC +# Beacon Protection (management frame protection for Beacon frames) +# This depends on management frame protection being enabled (ieee80211w != 0). +# 0 = disabled (default) +# 1 = enabled +#beacon_prot=0 + # Association SA Query maximum timeout (in TU = 1.024 ms; for MFP) # (maximum time to wait for a SA Query response) # dot11AssociationSAQueryMaximumTimeout, 1...4294967295 diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index e603605b1..ca9ae14cd 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -349,6 +349,7 @@ struct hostapd_bss_config { int wpa_key_mgmt; enum mfp_options ieee80211w; int group_mgmt_cipher; + int beacon_prot; /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ unsigned int assoc_sa_query_max_timeout; /* dot11AssociationSAQueryRetryTimeout (in TUs) */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 437719b17..c066d9979 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -188,6 +188,7 @@ struct wpa_auth_config { int okc; int tx_status; enum mfp_options ieee80211w; + int beacon_prot; int group_mgmt_cipher; int sae_require_mfp; #ifdef CONFIG_OCV diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 894c1a1b2..7dc4c8e6b 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -67,6 +67,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, #endif /* CONFIG_OCV */ wconf->okc = conf->okc; wconf->ieee80211w = conf->ieee80211w; + wconf->beacon_prot = conf->beacon_prot; wconf->group_mgmt_cipher = conf->group_mgmt_cipher; wconf->sae_require_mfp = conf->sae_require_mfp; #ifdef CONFIG_IEEE80211R_AP From c1df321b6c8e6fd3317337d3cc5c6914328311da Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 22:55:12 +0200 Subject: [PATCH 0030/1105] AP mode indication of Beacon protection being enabled Add the new Extended Capability bit for indicating Beacon protection. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11_shared.c | 4 ++++ src/common/ieee802_11_defs.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 4f7a9706a..a225639a9 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -397,6 +397,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) * Identifiers Used Exclusively */ } #endif /* CONFIG_SAE */ + if (hapd->conf->beacon_prot) + *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */ break; } } @@ -456,6 +458,8 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) hostapd_sae_pw_id_in_use(hapd->conf)) len = 11; #endif /* CONFIG_SAE */ + if (len < 11 && hapd->conf->beacon_prot) + len = 11; if (len < hapd->iface->extended_capa_len) len = hapd->iface->extended_capa_len; if (len == 0) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index f71927053..23e739d0e 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -558,6 +558,7 @@ #define WLAN_EXT_CAPAB_COMPLETE_NON_TX_BSSID_PROFILE 80 #define WLAN_EXT_CAPAB_SAE_PW_ID 81 #define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82 +#define WLAN_EXT_CAPAB_BEACON_PROTECTION 84 /* Extended RSN Capabilities */ /* bits 0-3: Field length (n-1) */ From d2e77310dcb97ce86377acb5b5407bce1710ff3e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 22:58:52 +0200 Subject: [PATCH 0031/1105] driver: Document use of set_key() for BIGTK Also update the comment to match the current IGTK KeyID range. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index e0cf8d122..64fc0fd90 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1565,7 +1565,7 @@ struct wpa_driver_set_key_params { /** * key_idx - Key index * - * (0..3), usually 0 for unicast keys; 0..4095 for IGTK */ + * (0..3), usually 0 for unicast keys; 4..5 for IGTK; 6..7 for BIGTK */ int key_idx; /** From 3937378abec3cb0ab7285754a371911d8bb64362 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 23:01:59 +0200 Subject: [PATCH 0032/1105] Parsing of BIGTK subelement in FTE Signed-off-by: Jouni Malinen --- src/common/wpa_common.c | 4 ++++ src/common/wpa_common.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 83bac5489..f7366faca 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -925,6 +925,10 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, parse->oci_len = len; break; #endif /* CONFIG_OCV */ + case FTIE_SUBELEM_BIGTK: + parse->bigtk = pos; + parse->bigtk_len = len; + break; default: wpa_printf(MSG_DEBUG, "FT: Unknown subelem id %u", id); break; diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index beb1ecd5e..2c9e29ef2 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -321,6 +321,7 @@ struct rsn_ftie_sha384 { #define FTIE_SUBELEM_R0KH_ID 3 #define FTIE_SUBELEM_IGTK 4 #define FTIE_SUBELEM_OCI 5 +#define FTIE_SUBELEM_BIGTK 6 struct rsn_rdie { u8 id; @@ -455,6 +456,8 @@ struct wpa_ft_ies { size_t tie_len; const u8 *igtk; size_t igtk_len; + const u8 *bigtk; + size_t bigtk_len; #ifdef CONFIG_OCV const u8 *oci; size_t oci_len; From 323d06187acd483dffeb695b7770339ee9dc39e9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 23:03:40 +0200 Subject: [PATCH 0033/1105] Parsing of BIGTK KDE in EAPOL-Key frames Signed-off-by: Jouni Malinen --- src/common/wpa_common.c | 9 +++++++++ src/common/wpa_common.h | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index f7366faca..6cb9180ee 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2731,6 +2731,15 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_BIGTK) { + ie->bigtk = pos + 2 + RSN_SELECTOR_LEN; + ie->bigtk_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump_key(MSG_DEBUG, "WPA: BIGTK in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + if (pos[1] >= RSN_SELECTOR_LEN + 1 && RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 2c9e29ef2..7850c878e 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -109,6 +109,7 @@ WPA_CIPHER_BIP_CMAC_256) #define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11) #define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12) #define RSN_KEY_DATA_OCI RSN_SELECTOR(0x00, 0x0f, 0xac, 13) +#define RSN_KEY_DATA_BIGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 14) #define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4) #define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5) @@ -130,6 +131,8 @@ WPA_CIPHER_BIP_CMAC_256) #define WPA_IGTK_LEN 16 #define WPA_IGTK_MAX_LEN 32 +#define WPA_BIGTK_LEN 16 +#define WPA_BIGTK_MAX_LEN 32 /* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */ @@ -227,6 +230,11 @@ struct wpa_igtk { size_t igtk_len; }; +struct wpa_bigtk { + u8 bigtk[WPA_BIGTK_MAX_LEN]; + size_t bigtk_len; +}; + /* WPA IE version 1 * 00-50-f2:1 (OUI:OUI type) * 0x01 0x00 (version; little endian) @@ -292,6 +300,13 @@ struct wpa_igtk_kde { u8 igtk[WPA_IGTK_MAX_LEN]; } STRUCT_PACKED; +#define WPA_BIGTK_KDE_PREFIX_LEN (2 + 6) +struct wpa_bigtk_kde { + u8 keyid[2]; + u8 pn[6]; + u8 bigtk[WPA_BIGTK_MAX_LEN]; +} STRUCT_PACKED; + struct rsn_mdie { u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; u8 ft_capab; @@ -485,6 +500,8 @@ struct wpa_eapol_ie_parse { size_t mac_addr_len; const u8 *igtk; size_t igtk_len; + const u8 *bigtk; + size_t bigtk_len; const u8 *mdie; size_t mdie_len; const u8 *ftie; From 555dcd75ce1ffcb70b55f2f502e951f8cc7bf3fe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 23:08:05 +0200 Subject: [PATCH 0034/1105] Generate BIGTK and rekey it with IGTK Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 30 +++++++++++++++++++++++++++++- src/ap/wpa_auth_i.h | 2 ++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 0a807a3c6..ee75837db 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3805,6 +3805,7 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { int ret = 0; + size_t len; os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); @@ -3816,7 +3817,6 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, group->GTK[group->GN - 1], group->GTK_len); if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { - size_t len; len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); @@ -3828,6 +3828,19 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, group->IGTK[group->GN_igtk - 4], len); } + if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION && + wpa_auth->conf.beacon_prot) { + len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); + inc_byte_array(group->Counter, WPA_NONCE_LEN); + if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion", + wpa_auth->addr, group->GNonce, + group->BIGTK[group->GN_bigtk - 6], len) < 0) + ret = -1; + wpa_hexdump_key(MSG_DEBUG, "BIGTK", + group->BIGTK[group->GN_bigtk - 6], len); + } + return ret; } @@ -3846,6 +3859,8 @@ static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, group->GM = 2; group->GN_igtk = 4; group->GM_igtk = 5; + group->GN_bigtk = 6; + group->GM_bigtk = 7; /* GTK[GN] = CalcGTK() */ wpa_gtk_update(wpa_auth, group); } @@ -3982,6 +3997,9 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, tmp = group->GM_igtk; group->GM_igtk = group->GN_igtk; group->GN_igtk = tmp; + tmp = group->GM_bigtk; + group->GM_bigtk = group->GN_bigtk; + group->GN_bigtk = tmp; /* "GKeyDoneStations = GNoStations" is done in more robust way by * counting the STAs that are marked with GUpdateStationKeys instead of * including all STAs that could be in not-yet-completed state. */ @@ -4024,6 +4042,13 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, group->IGTK[group->GN_igtk - 4], len, KEY_FLAG_GROUP_TX_DEFAULT) < 0) ret = -1; + + if (ret == 0 && wpa_auth->conf.beacon_prot && + wpa_auth_set_key(wpa_auth, group->vlan_id, alg, + broadcast_ether_addr, group->GN_bigtk, + group->BIGTK[group->GN_bigtk - 6], len, + KEY_FLAG_GROUP_TX_DEFAULT) < 0) + ret = -1; } return ret; @@ -4165,6 +4190,9 @@ void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) tmp = group->GM_igtk; group->GM_igtk = group->GN_igtk; group->GN_igtk = tmp; + tmp = group->GM_bigtk; + group->GM_bigtk = group->GN_bigtk; + group->GN_bigtk = tmp; wpa_gtk_update(wpa_auth, group); wpa_group_config_group_keys(wpa_auth, group); } diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index a993f5008..c2b22eba1 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -193,7 +193,9 @@ struct wpa_group { Boolean first_sta_seen; Boolean reject_4way_hs_for_entropy; u8 IGTK[2][WPA_IGTK_MAX_LEN]; + u8 BIGTK[2][WPA_IGTK_MAX_LEN]; int GN_igtk, GM_igtk; + int GN_bigtk, GM_bigtk; /* Number of references except those in struct wpa_group->next */ unsigned int references; unsigned int num_setup_iface; From 16889aff408ec585af64d10fc6adc3a7588a2585 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 23:08:05 +0200 Subject: [PATCH 0035/1105] Add BIGTK KDE and subelement similarly to IGTK This provides the BIGTK updates to associated stations similarly to IGTK. Signed-off-by: Jouni Malinen --- src/ap/wnm_ap.c | 24 +++++++++--- src/ap/wpa_auth.c | 68 ++++++++++++++++++++++++++++++---- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_ft.c | 71 ++++++++++++++++++++++++++++++++++++ src/common/ieee802_11_defs.h | 3 +- 5 files changed, 153 insertions(+), 14 deletions(-) diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 29ca95092..891f90f29 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -54,6 +54,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, size_t len; size_t gtk_elem_len = 0; size_t igtk_elem_len = 0; + size_t bigtk_elem_len = 0; struct wnm_sleep_element wnmsleep_ie; u8 *wnmtfs_ie, *oci_ie; u8 wnmsleep_ie_len, oci_ie_len; @@ -122,8 +123,10 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, #define MAX_GTK_SUBELEM_LEN 45 #define MAX_IGTK_SUBELEM_LEN 26 +#define MAX_BIGTK_SUBELEM_LEN 26 mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN + + MAX_BIGTK_SUBELEM_LEN + oci_ie_len); if (mgmt == NULL) { wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for " @@ -157,10 +160,19 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, pos += igtk_elem_len; wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d", (int) igtk_elem_len); + if (hapd->conf->beacon_prot) { + res = wpa_wnmsleep_bigtk_subelem(sta->wpa_sm, pos); + if (res < 0) + goto fail; + bigtk_elem_len = res; + pos += bigtk_elem_len; + wpa_printf(MSG_DEBUG, "Pass 4 bigtk_len = %d", + (int) bigtk_elem_len); + } WPA_PUT_LE16((u8 *) &mgmt->u.action.u.wnm_sleep_resp.keydata_len, - gtk_elem_len + igtk_elem_len); + gtk_elem_len + igtk_elem_len + bigtk_elem_len); } os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len); /* copy TFS IE here */ @@ -176,7 +188,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, #endif /* CONFIG_OCV */ len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len + - igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len; + igtk_elem_len + bigtk_elem_len + + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len; /* In driver, response frame should be forced to sent when STA is in * PS mode */ @@ -189,8 +202,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, /* when entering wnmsleep * 1. pause the node in driver - * 2. mark the node so that AP won't update GTK/IGTK during - * WNM Sleep + * 2. mark the node so that AP won't update GTK/IGTK/BIGTK + * during WNM Sleep */ if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT && wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) { @@ -201,7 +214,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, } /* when exiting wnmsleep * 1. unmark the node - * 2. start GTK/IGTK update if MFP is not used + * 2. start GTK/IGTK/BIGTK update if MFP is not used * 3. unpause the node in driver */ if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT || @@ -221,6 +234,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, #undef MAX_GTK_SUBELEM_LEN #undef MAX_IGTK_SUBELEM_LEN +#undef MAX_BIGTK_SUBELEM_LEN fail: os_free(wnmtfs_ie); os_free(oci_ie); diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index ee75837db..1f835d80a 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -63,6 +63,7 @@ static void wpa_group_get(struct wpa_authenticator *wpa_auth, struct wpa_group *group); static void wpa_group_put(struct wpa_authenticator *wpa_auth, struct wpa_group *group); +static int ieee80211w_kde_len(struct wpa_state_machine *sm); static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos); static const u32 eapol_key_timeout_first = 100; /* ms */ @@ -2679,7 +2680,7 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, size_t gtk_len; struct wpa_group *gsm; - plain = wpabuf_alloc(1000); + plain = wpabuf_alloc(1000 + ieee80211w_kde_len(sm)); if (!plain) return NULL; @@ -2727,7 +2728,7 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, gtk, gtk_len); wpabuf_put(plain, tmp2 - tmp); - /* IGTK KDE */ + /* IGTK KDE and BIGTK KDE */ tmp = wpabuf_put(plain, 0); tmp2 = ieee80211w_kde_add(sm, tmp); wpabuf_put(plain, tmp2 - tmp); @@ -3105,19 +3106,25 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) static int ieee80211w_kde_len(struct wpa_state_machine *sm) { + size_t len = 0; + if (sm->mgmt_frame_prot) { - size_t len; - len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); - return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len; + len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN; + len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + } + if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) { + len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN; + len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); } - return 0; + return len; } static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) { struct wpa_igtk_kde igtk; + struct wpa_bigtk_kde bigtk; struct wpa_group *gsm = sm->group; u8 rsc[WPA_KEY_RSC_LEN]; size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); @@ -3146,6 +3153,21 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, NULL, 0); + if (!sm->wpa_auth->conf.beacon_prot) + return pos; + + bigtk.keyid[0] = gsm->GN_bigtk; + bigtk.keyid[1] = 0; + if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0) + os_memset(bigtk.pn, 0, sizeof(bigtk.pn)); + else + os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn)); + os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len); + pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK, + (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len, + NULL, 0); + return pos; } @@ -3205,7 +3227,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], - GTK[GN], IGTK, [FTIE], [TIE * 2]) + GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2]) */ os_memset(rsc, 0, WPA_KEY_RSC_LEN); wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); @@ -3978,6 +4000,36 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) return pos - start; } + +int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos) +{ + struct wpa_group *gsm = sm->group; + u8 *start = pos; + size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + + /* + * BIGTK subelement: + * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] + */ + *pos++ = WNM_SLEEP_SUBELEM_BIGTK; + *pos++ = 2 + 6 + len; + WPA_PUT_LE16(pos, gsm->GN_bigtk); + pos += 2; + if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0) + return 0; + pos += 6; + + os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len); + pos += len; + + wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit", + gsm->GN_bigtk); + wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit", + gsm->IGTK[gsm->GN_bigtk - 6], len); + + return pos - start; +} + #endif /* CONFIG_WNM_AP */ @@ -5074,7 +5126,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, int wpa_ie_len, secure, gtkidx, encr = 0; /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], - GTK[GN], IGTK, [FTIE], [TIE * 2]) + GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2]) */ /* Use 0 RSC */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index c066d9979..93e0c745d 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -438,6 +438,7 @@ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm); void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag); int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos); int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos); +int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos); int wpa_auth_uses_sae(struct wpa_state_machine *sm); int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 462876195..c0b462558 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2282,6 +2282,54 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) } +static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len) +{ + u8 *subelem, *pos; + struct wpa_group *gsm = sm->group; + size_t subelem_len; + const u8 *kek; + size_t kek_len; + size_t bigtk_len; + + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + kek = sm->PTK.kek2; + kek_len = sm->PTK.kek2_len; + } else { + kek = sm->PTK.kek; + kek_len = sm->PTK.kek_len; + } + + bigtk_len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + + /* Sub-elem ID[1] | Length[1] | KeyID[2] | BIPN[6] | Key Length[1] | + * Key[16+8] */ + subelem_len = 1 + 1 + 2 + 6 + 1 + bigtk_len + 8; + subelem = os_zalloc(subelem_len); + if (subelem == NULL) + return NULL; + + pos = subelem; + *pos++ = FTIE_SUBELEM_BIGTK; + *pos++ = subelem_len - 2; + WPA_PUT_LE16(pos, gsm->GN_bigtk); + pos += 2; + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos); + pos += 6; + *pos++ = bigtk_len; + if (aes_wrap(kek, kek_len, bigtk_len / 8, + gsm->IGTK[gsm->GN_bigtk - 6], pos)) { + wpa_printf(MSG_DEBUG, + "FT: BIGTK subelem encryption failed: kek_len=%d", + (int) kek_len); + os_free(subelem); + return NULL; + } + + *len = subelem_len; + return subelem; +} + + static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm, u8 *pos, u8 *end, u8 id, u8 descr_count, const u8 *ies, size_t ies_len) @@ -2511,6 +2559,29 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, subelem_len += igtk_len; os_free(igtk); } + if (sm->mgmt_frame_prot && conf->beacon_prot) { + u8 *bigtk; + size_t bigtk_len; + u8 *nbuf; + + bigtk = wpa_ft_bigtk_subelem(sm, &bigtk_len); + if (!bigtk) { + wpa_printf(MSG_DEBUG, + "FT: Failed to add BIGTK subelement"); + os_free(subelem); + return NULL; + } + nbuf = os_realloc(subelem, subelem_len + bigtk_len); + if (!nbuf) { + os_free(subelem); + os_free(bigtk); + return NULL; + } + subelem = nbuf; + os_memcpy(subelem + subelem_len, bigtk, bigtk_len); + subelem_len += bigtk_len; + os_free(bigtk); + } #ifdef CONFIG_OCV if (wpa_auth_uses_ocv(sm)) { struct wpa_channel_info ci; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 23e739d0e..a78ed0a12 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1875,7 +1875,8 @@ enum wnm_sleep_mode_response_status { /* WNM-Sleep Mode subelement IDs */ enum wnm_sleep_mode_subelement_id { WNM_SLEEP_SUBELEM_GTK = 0, - WNM_SLEEP_SUBELEM_IGTK = 1 + WNM_SLEEP_SUBELEM_IGTK = 1, + WNM_SLEEP_SUBELEM_BIGTK = 2, }; /* Channel Switch modes (802.11h) */ From ecbf59e6931f304801fa728b191b2b7506908059 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 18 Feb 2020 00:16:55 +0200 Subject: [PATCH 0036/1105] wpa_supplicant configuration for Beacon protection Add a new wpa_supplicant network profile configuration parameter beacon_prot=<0/1> to allow Beacon protection to be enabled. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 2 ++ src/rsn_supp/wpa.h | 1 + src/rsn_supp/wpa_i.h | 1 + wpa_supplicant/config.c | 1 + wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 8 ++++++++ wpa_supplicant/wpas_glue.c | 1 + 7 files changed, 15 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 039f076fa..981602c5d 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2959,6 +2959,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) } else { sm->fils_cache_id_set = 0; } + sm->beacon_prot = config->beacon_prot; #endif /* CONFIG_FILS */ } else { sm->network_ctx = NULL; @@ -2971,6 +2972,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) sm->p2p = 0; sm->wpa_rsc_relaxation = 0; sm->owe_ptk_workaround = 0; + sm->beacon_prot = 0; } } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index ceae721aa..e14f26e01 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -115,6 +115,7 @@ struct rsn_supp_config { int wpa_rsc_relaxation; int owe_ptk_workaround; const u8 *fils_cache_id; + int beacon_prot; }; #ifndef CONFIG_NO_WPA diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index e088a5aa7..164adfbc0 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -64,6 +64,7 @@ struct wpa_sm { int p2p; int wpa_rsc_relaxation; int owe_ptk_workaround; + int beacon_prot; u8 own_addr[ETH_ALEN]; const char *ifname; diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index b83c36ae9..9dad4ff72 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2569,6 +2569,7 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(owe_ptk_workaround, 0, 1) }, { INT_RANGE(multi_ap_backhaul_sta, 0, 1) }, { INT_RANGE(ft_eap_pmksa_caching, 0, 1) }, + { INT_RANGE(beacon_prot, 0, 1) }, }; #undef OFFSET diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index fd2bdff48..29bd81f0a 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -913,6 +913,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(owe_ptk_workaround); INT(multi_ap_backhaul_sta); INT(ft_eap_pmksa_caching); + INT(beacon_prot); #ifdef CONFIG_HT_OVERRIDES INT_DEF(disable_ht, DEFAULT_DISABLE_HT); INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index b752dfdda..5642d0ddf 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -1047,6 +1047,14 @@ struct wpa_ssid { * FT initial mobility domain association. */ int ft_eap_pmksa_caching; + + /** + * beacon_prot - Whether Beacon protection is enabled + * + * This depends on management frame protection (ieee80211w) being + * enabled. + */ + int beacon_prot; }; #endif /* CONFIG_SSID_H */ diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index f113bfe29..e8747e613 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1309,6 +1309,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, conf.fils_cache_id = wpa_bss_get_fils_cache_id(wpa_s->current_bss); #endif /* CONFIG_FILS */ + conf.beacon_prot = ssid->beacon_prot; } wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); } From 2d4c78aef718b9a3e5947c4fad4bbd634b6eab9d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 18 Feb 2020 00:06:26 +0200 Subject: [PATCH 0037/1105] Configure received BIGTK on station/supplicant side Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 73 +++++++++++++++++++++++++++++++++++++- src/rsn_supp/wpa_ft.c | 75 +++++++++++++++++++++++++++++++++++++--- src/rsn_supp/wpa_i.h | 2 ++ wpa_supplicant/wnm_sta.c | 9 +++++ 4 files changed, 154 insertions(+), 5 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 981602c5d..1e209ada5 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1140,14 +1140,66 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm, } +static int wpa_supplicant_install_bigtk(struct wpa_sm *sm, + const struct wpa_bigtk_kde *bigtk, + int wnm_sleep) +{ + size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher); + u16 keyidx = WPA_GET_LE16(bigtk->keyid); + + /* Detect possible key reinstallation */ + if ((sm->bigtk.bigtk_len == len && + os_memcmp(sm->bigtk.bigtk, bigtk->bigtk, + sm->bigtk.bigtk_len) == 0) || + (sm->bigtk_wnm_sleep.bigtk_len == len && + os_memcmp(sm->bigtk_wnm_sleep.bigtk, bigtk->bigtk, + sm->bigtk_wnm_sleep.bigtk_len) == 0)) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Not reinstalling already in-use BIGTK to the driver (keyidx=%d)", + keyidx); + return 0; + } + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: BIGTK keyid %d pn " COMPACT_MACSTR, + keyidx, MAC2STR(bigtk->pn)); + wpa_hexdump_key(MSG_DEBUG, "WPA: BIGTK", bigtk->bigtk, len); + if (keyidx < 6 || keyidx > 7) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Invalid BIGTK KeyID %d", keyidx); + return -1; + } + if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher), + broadcast_ether_addr, + keyidx, 0, bigtk->pn, sizeof(bigtk->pn), + bigtk->bigtk, len, KEY_FLAG_GROUP_RX) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to configure BIGTK to the driver"); + return -1; + } + + if (wnm_sleep) { + sm->bigtk_wnm_sleep.bigtk_len = len; + os_memcpy(sm->bigtk_wnm_sleep.bigtk, bigtk->bigtk, + sm->bigtk_wnm_sleep.bigtk_len); + } else { + sm->bigtk.bigtk_len = len; + os_memcpy(sm->bigtk.bigtk, bigtk->bigtk, sm->bigtk.bigtk_len); + } + + return 0; +} + + static int ieee80211w_set_keys(struct wpa_sm *sm, struct wpa_eapol_ie_parse *ie) { + size_t len; + if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher)) return 0; if (ie->igtk) { - size_t len; const struct wpa_igtk_kde *igtk; len = wpa_cipher_key_len(sm->mgmt_group_cipher); @@ -1159,6 +1211,18 @@ static int ieee80211w_set_keys(struct wpa_sm *sm, return -1; } + if (ie->bigtk && sm->beacon_prot) { + const struct wpa_bigtk_kde *bigtk; + + len = wpa_cipher_key_len(sm->mgmt_group_cipher); + if (ie->bigtk_len != WPA_BIGTK_KDE_PREFIX_LEN + len) + return -1; + + bigtk = (const struct wpa_bigtk_kde *) ie->bigtk; + if (wpa_supplicant_install_bigtk(sm, bigtk, 0) < 0) + return -1; + } + return 0; } @@ -3595,6 +3659,13 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) igtk = (const struct wpa_igtk_kde *) (buf + 2); if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0) return -1; + } else if (subelem_id == WNM_SLEEP_SUBELEM_BIGTK) { + const struct wpa_bigtk_kde *bigtk; + + bigtk = (const struct wpa_bigtk_kde *) (buf + 2); + if (sm->beacon_prot && + wpa_supplicant_install_bigtk(sm, bigtk, 1) < 0) + return -1; } else { wpa_printf(MSG_DEBUG, "Unknown element id"); return -1; diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 8a8c545d3..046bdfd16 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -855,6 +855,74 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, } +static int wpa_ft_process_bigtk_subelem(struct wpa_sm *sm, const u8 *bigtk_elem, + size_t bigtk_elem_len) +{ + u8 bigtk[WPA_BIGTK_MAX_LEN]; + size_t bigtk_len; + u16 keyidx; + const u8 *kek; + size_t kek_len; + + if (!sm->beacon_prot || !bigtk_elem || + (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256)) + return 0; + + if (wpa_key_mgmt_fils(sm->key_mgmt)) { + kek = sm->ptk.kek2; + kek_len = sm->ptk.kek2_len; + } else { + kek = sm->ptk.kek; + kek_len = sm->ptk.kek_len; + } + + wpa_hexdump_key(MSG_DEBUG, "FT: Received BIGTK in Reassoc Resp", + bigtk_elem, bigtk_elem_len); + + bigtk_len = wpa_cipher_key_len(sm->mgmt_group_cipher); + if (bigtk_elem_len != 2 + 6 + 1 + bigtk_len + 8) { + wpa_printf(MSG_DEBUG, + "FT: Invalid BIGTK sub-elem length %lu", + (unsigned long) bigtk_elem_len); + return -1; + } + if (bigtk_elem[8] != bigtk_len) { + wpa_printf(MSG_DEBUG, + "FT: Invalid BIGTK sub-elem Key Length %d", + bigtk_elem[8]); + return -1; + } + + if (aes_unwrap(kek, kek_len, bigtk_len / 8, bigtk_elem + 9, bigtk)) { + wpa_printf(MSG_WARNING, + "FT: AES unwrap failed - could not decrypt BIGTK"); + return -1; + } + + /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ + + keyidx = WPA_GET_LE16(bigtk_elem); + + wpa_hexdump_key(MSG_DEBUG, "FT: BIGTK from Reassoc Resp", bigtk, + bigtk_len); + if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher), + broadcast_ether_addr, keyidx, 0, + bigtk_elem + 2, 6, bigtk, bigtk_len, + KEY_FLAG_GROUP_RX) < 0) { + wpa_printf(MSG_WARNING, + "WPA: Failed to set BIGTK to the driver"); + forced_memzero(bigtk, sizeof(bigtk)); + return -1; + } + forced_memzero(bigtk, sizeof(bigtk)); + + return 0; +} + + int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len, const u8 *src_addr) { @@ -1036,10 +1104,9 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, sm->ft_reassoc_completed = 1; - if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) - return -1; - - if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0) + if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0 || + wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0 || + wpa_ft_process_bigtk_subelem(sm, parse.bigtk, parse.bigtk_len) < 0) return -1; if (sm->set_ptk_after_assoc) { diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 164adfbc0..bd4446402 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -33,6 +33,8 @@ struct wpa_sm { struct wpa_gtk gtk_wnm_sleep; struct wpa_igtk igtk; struct wpa_igtk igtk_wnm_sleep; + struct wpa_bigtk bigtk; + struct wpa_bigtk bigtk_wnm_sleep; struct eapol_sm *eapol; /* EAPOL state machine from upper level code */ diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 270be9e2e..06cb70fe5 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -280,6 +280,15 @@ static void wnm_sleep_mode_exit_success(struct wpa_supplicant *wpa_s, wpa_wnmsleep_install_key(wpa_s->wpa, WNM_SLEEP_SUBELEM_IGTK, ptr); ptr += 10 + WPA_IGTK_LEN; + } else if (*ptr == WNM_SLEEP_SUBELEM_BIGTK) { + if (ptr[1] < 2 + 6 + WPA_BIGTK_LEN) { + wpa_printf(MSG_DEBUG, + "WNM: Too short BIGTK subelem"); + break; + } + wpa_wnmsleep_install_key(wpa_s->wpa, + WNM_SLEEP_SUBELEM_BIGTK, ptr); + ptr += 10 + WPA_BIGTK_LEN; } else break; /* skip the loop */ } From faf6894f35f6f2592ff05324db9e6e6184ebc041 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 21 Feb 2020 19:40:32 +0200 Subject: [PATCH 0038/1105] wlantest: BIGTK fetching and Beacon protection validation Fetch the BIGTK from EAPOL-Key msg 3/4 and use it to validate MME in Beacon frames when the AP uses Beacon protection. Signed-off-by: Jouni Malinen --- wlantest/rx_eapol.c | 59 ++++++++++++++++++++++++++++++++++++++ wlantest/rx_mgmt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ wlantest/wlantest.h | 7 +++-- 3 files changed, 132 insertions(+), 3 deletions(-) diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index e18449542..e4fe7e23e 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -548,6 +548,65 @@ static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss, (unsigned) ie.igtk_len); } } + + if (ie.bigtk) { + wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - BIGTK KDE", + ie.bigtk, ie.bigtk_len); + if (ie.bigtk_len == 24) { + u16 id; + + id = WPA_GET_LE16(ie.bigtk); + if (id < 6 || id > 7) { + add_note(wt, MSG_INFO, + "Unexpected BIGTK KeyID %u", id); + } else { + const u8 *ipn; + + add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", id); + wpa_hexdump(MSG_DEBUG, "BIPN", ie.bigtk + 2, 6); + wpa_hexdump(MSG_DEBUG, "BIGTK", ie.bigtk + 8, + 16); + os_memcpy(bss->igtk[id], ie.bigtk + 8, 16); + bss->igtk_len[id] = 16; + ipn = ie.bigtk + 2; + bss->ipn[id][0] = ipn[5]; + bss->ipn[id][1] = ipn[4]; + bss->ipn[id][2] = ipn[3]; + bss->ipn[id][3] = ipn[2]; + bss->ipn[id][4] = ipn[1]; + bss->ipn[id][5] = ipn[0]; + bss->bigtk_idx = id; + } + } else if (ie.bigtk_len == 40) { + u16 id; + + id = WPA_GET_LE16(ie.bigtk); + if (id < 6 || id > 7) { + add_note(wt, MSG_INFO, + "Unexpected BIGTK KeyID %u", id); + } else { + const u8 *ipn; + + add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", id); + wpa_hexdump(MSG_DEBUG, "BIPN", ie.bigtk + 2, 6); + wpa_hexdump(MSG_DEBUG, "BIGTK", ie.bigtk + 8, + 32); + os_memcpy(bss->igtk[id], ie.bigtk + 8, 32); + bss->igtk_len[id] = 32; + ipn = ie.bigtk + 2; + bss->ipn[id][0] = ipn[5]; + bss->ipn[id][1] = ipn[4]; + bss->ipn[id][2] = ipn[3]; + bss->ipn[id][3] = ipn[2]; + bss->ipn[id][4] = ipn[1]; + bss->ipn[id][5] = ipn[0]; + bss->bigtk_idx = id; + } + } else { + add_note(wt, MSG_INFO, "Invalid BIGTK KDE length %u", + (unsigned) ie.bigtk_len); + } + } } diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 39b23b27c..92762b8f0 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -19,6 +19,11 @@ #include "wlantest.h" +static int check_mmie_mic(unsigned int mgmt_group_cipher, + const u8 *igtk, size_t igtk_len, + const u8 *data, size_t len); + + static const char * mgmt_stype(u16 stype) { switch (stype) { @@ -57,6 +62,9 @@ static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len) struct wlantest_bss *bss; struct ieee802_11_elems elems; size_t offset; + const u8 *mme; + size_t mic_len; + u16 keyid; mgmt = (const struct ieee80211_mgmt *) data; offset = mgmt->u.beacon.variable - data; @@ -79,6 +87,62 @@ static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len) } bss_update(wt, bss, &elems); + + mme = get_ie(mgmt->u.beacon.variable, len - offset, WLAN_EID_MMIE); + if (!mme) { + if (bss->bigtk_idx) { + add_note(wt, MSG_INFO, + "Unexpected unprotected Beacon frame from " + MACSTR, MAC2STR(mgmt->sa)); + bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++; + } + return; + } + + mic_len = bss->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ? 8 : 16; + if (len < 24 + 10 + mic_len || + data[len - (10 + mic_len)] != WLAN_EID_MMIE || + data[len - (10 + mic_len - 1)] != 8 + mic_len) { + add_note(wt, MSG_INFO, "Invalid MME in a Beacon frame from " + MACSTR, MAC2STR(mgmt->sa)); + return; + } + + mme += 2; + keyid = WPA_GET_LE16(mme); + if (keyid < 6 || keyid > 7) { + add_note(wt, MSG_INFO, "Unexpected MME KeyID %u from " MACSTR, + keyid, MAC2STR(mgmt->sa)); + bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++; + return; + } + + wpa_printf(MSG_DEBUG, "Beacon frame MME KeyID %u", keyid); + wpa_hexdump(MSG_MSGDUMP, "MME IPN", mme + 2, 6); + wpa_hexdump(MSG_MSGDUMP, "MME MIC", mme + 8, mic_len); + + if (!bss->igtk_len[keyid]) { + add_note(wt, MSG_DEBUG, "No BIGTK known to validate BIP frame"); + return; + } + + if (os_memcmp(mme + 2, bss->ipn[keyid], 6) <= 0) { + add_note(wt, MSG_INFO, "BIP replay detected: SA=" MACSTR, + MAC2STR(mgmt->sa)); + wpa_hexdump(MSG_INFO, "RX IPN", mme + 2, 6); + wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6); + } + + if (check_mmie_mic(bss->mgmt_group_cipher, bss->igtk[keyid], + bss->igtk_len[keyid], data, len) < 0) { + add_note(wt, MSG_INFO, "Invalid MME MIC in a Beacon frame from " + MACSTR, MAC2STR(mgmt->sa)); + bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++; + return; + } + + add_note(wt, MSG_DEBUG, "Valid MME MIC in Beacon frame"); + os_memcpy(bss->ipn[keyid], mme + 2, 6); } @@ -1329,6 +1393,11 @@ static int check_mmie_mic(unsigned int mgmt_group_cipher, os_memcpy(buf + 20, data + 24, len - 24 - mic_len); os_memset(buf + 20 + len - 24 - mic_len, 0, mic_len); + if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) { + /* Timestamp field masked to zero */ + os_memset(buf + 20, 0, 8); + } + wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24); /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */ if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 4f90b20e2..82eddc11c 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -150,10 +150,11 @@ struct wlantest_bss { size_t gtk_len[4]; int gtk_idx; u8 rsc[4][6]; - u8 igtk[6][32]; - size_t igtk_len[6]; + u8 igtk[8][32]; + size_t igtk_len[8]; int igtk_idx; - u8 ipn[6][6]; + u8 ipn[8][6]; + int bigtk_idx; u32 counters[NUM_WLANTEST_BSS_COUNTER]; struct dl_list tdls; /* struct wlantest_tdls */ u8 mdid[2]; From f65da0ca4b5ab5b8811b62b680446022d5ca0a07 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 17 Feb 2020 23:45:18 +0200 Subject: [PATCH 0039/1105] tests: Beacon protection Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_pmf.py | 125 +++++++++++++++++++++++++++++++++++ tests/hwsim/wpasupplicant.py | 2 +- 2 files changed, 126 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index 0a3645731..3913c5ce7 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -6,6 +6,7 @@ from remotehost import remote_compatible import binascii +import os import time import logging logger = logging.getLogger() @@ -915,3 +916,127 @@ def test_ap_pmf_sa_query_timeout(dev, apdev): ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1.5) if ev is not None: raise Exception("Unexpected disconnection after reconnection seen") + +def mac80211_read_key(keydir): + vals = {} + for name in os.listdir(keydir): + try: + with open(os.path.join(keydir, name)) as f: + vals[name] = f.read().strip() + except OSError as e: + pass + return vals + +def test_ap_pmf_beacon_protection_bip(dev, apdev): + """WPA2-PSK Beacon protection (BIP)""" + """WPA2-PSK AP with PMF required and Beacon protection enabled (BIP)""" + run_ap_pmf_beacon_protection(dev, apdev, "AES-128-CMAC") + +def test_ap_pmf_beacon_protection_bip_cmac_256(dev, apdev): + """WPA2-PSK Beacon protection (BIP-CMAC-256)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-CMAC-256") + +def test_ap_pmf_beacon_protection_bip_gmac_128(dev, apdev): + """WPA2-PSK Beacon protection (BIP-GMAC-128)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-128") + +def test_ap_pmf_beacon_protection_bip_gmac_256(dev, apdev): + """WPA2-PSK Beacon protection (BIP-GMAC-256)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-256") + +def run_ap_pmf_beacon_protection(dev, apdev, cipher): + ssid = "test-beacon-prot" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["beacon_prot"] = "1" + params["group_mgmt_cipher"] = cipher + try: + hapd = hostapd.add_ap(apdev[0], params) + except Exception as e: + if "Failed to enable hostapd interface" in str(e): + raise HwsimSkip("Beacon protection not supported") + raise + + bssid = hapd.own_addr() + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + # STA with Beacon protection enabled + dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1", + key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") + + # STA with Beacon protection disabled + dev[1].connect(ssid, psk="12345678", ieee80211w="2", + key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") + + time.sleep(1) + + sta_key = None + ap_key = None + + phy = dev[0].get_driver_status_field("phyname") + keys = "/sys/kernel/debug/ieee80211/%s/keys" % phy + try: + for key in os.listdir(keys): + keydir = os.path.join(keys, key) + vals = mac80211_read_key(keydir) + keyidx = int(vals['keyidx']) + if keyidx == 6 or keyidx == 7: + sta_key = vals; + break + except OSError as e: + raise HwsimSkip("debugfs not supported in mac80211 (STA)") + + phy = hapd.get_driver_status_field("phyname") + keys = "/sys/kernel/debug/ieee80211/%s/keys" % phy + try: + for key in os.listdir(keys): + keydir = os.path.join(keys, key) + vals = mac80211_read_key(keydir) + keyidx = int(vals['keyidx']) + if keyidx == 6 or keyidx == 7: + ap_key = vals; + break + except OSError as e: + raise HwsimSkip("debugfs not supported in mac80211 (AP)") + + if not sta_key: + raise Exception("Could not find STA key information from debugfs") + logger.info("STA key: " + str(sta_key)) + + if not ap_key: + raise Exception("Could not find AP key information from debugfs") + logger.info("AP key: " + str(ap_key)) + + if sta_key['key'] != ap_key['key']: + raise Exception("AP and STA BIGTK mismatch") + + if sta_key['keyidx'] != ap_key['keyidx']: + raise Exception("AP and STA BIGTK keyidx mismatch") + + if sta_key['algorithm'] != ap_key['algorithm']: + raise Exception("AP and STA BIGTK algorithm mismatch") + + replays = int(sta_key['replays']) + icverrors = int(sta_key['icverrors']) + if replays > 0 or icverrors > 0: + raise Exception("STA reported errors: replays=%d icverrors=%d" % replays, icverrors) + + rx_spec = int(sta_key['rx_spec'], base=16) + if rx_spec < 3: + raise Exception("STA did not update BIGTK receive counter sufficiently") + + tx_spec = int(ap_key['tx_spec'], base=16) + if tx_spec < 3: + raise Exception("AP did not update BIGTK BIPN sufficiently") + + valid_bip = wt.get_bss_counter('valid_bip_mmie', bssid) + invalid_bip = wt.get_bss_counter('invalid_bip_mmie', bssid) + missing_bip = wt.get_bss_counter('missing_bip_mmie', bssid) + logger.info("wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) + if valid_bip < 0 or invalid_bip > 0 or missing_bip > 0: + raise Exception("Unexpected wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 2283fa99c..0f3bb1866 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1104,7 +1104,7 @@ class WpaSupplicant: "owe_ptk_workaround", "roaming_consortium_selection", "ocv", "multi_ap_backhaul_sta", "rx_stbc", "tx_stbc", - "ft_eap_pmksa_caching"] + "ft_eap_pmksa_caching", "beacon_prot"] for field in not_quoted: if field in kwargs and kwargs[field]: self.set_network(id, field, kwargs[field]) From 640d59942bfe8742b288f3330d2ba21ee1c171b8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Feb 2020 16:07:17 +0200 Subject: [PATCH 0040/1105] Fix location of MDE and RSNXE in Beacon and Probe Response frames Split the IEs from WPA authenticator state machine into separately added IEs so that the exact location between these and other elements can be controlled. This fixes the location of MDE and RSNXE in Beacon and Probe Response frames. In addition, this swaps the order of BSS Load and RM Enabled Capabilities elements in Beacon frames to get them into the correct order (which was already used for Probe Response frames). Furthermore, this fixes the buffer end checks for couple of elements to make the implementation more consistent (though, in practice, there is no impact from this since the old size limit was smaller than needed, but still sufficiently large to have room for these). Signed-off-by: Jouni Malinen --- src/ap/beacon.c | 140 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 102 insertions(+), 38 deletions(-) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index e5e81e78c..41d03bc01 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -266,17 +266,95 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, } -static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len) +static const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid) +{ + const u8 *ies; + size_t ies_len; + + ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len); + if (!ies) + return NULL; + + return get_ie(ies, ies_len, eid); +} + + +static const u8 * hostapd_vendor_wpa_ie(struct hostapd_data *hapd, + u32 vendor_type) +{ + const u8 *ies; + size_t ies_len; + + ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len); + if (!ies) + return NULL; + + return get_vendor_ie(ies, ies_len, vendor_type); +} + + +static u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len) { const u8 *ie; - size_t ielen; - ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen); - if (ie == NULL || ielen > len) - return eid; + ie = hostapd_wpa_ie(hapd, WLAN_EID_RSN); + if (!ie || 2U + ie[1] > len) + return pos; - os_memcpy(eid, ie, ielen); - return eid + ielen; + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; +} + + +static u8 * hostapd_get_mde(struct hostapd_data *hapd, u8 *pos, size_t len) +{ + const u8 *ie; + + ie = hostapd_wpa_ie(hapd, WLAN_EID_MOBILITY_DOMAIN); + if (!ie || 2U + ie[1] > len) + return pos; + + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; +} + + +static u8 * hostapd_get_rsnxe(struct hostapd_data *hapd, u8 *pos, size_t len) +{ + const u8 *ie; + + ie = hostapd_wpa_ie(hapd, WLAN_EID_RSNX); + if (!ie || 2U + ie[1] > len) + return pos; + + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; +} + + +static u8 * hostapd_get_wpa_ie(struct hostapd_data *hapd, u8 *pos, size_t len) +{ + const u8 *ie; + + ie = hostapd_vendor_wpa_ie(hapd, WPA_IE_VENDOR_TYPE); + if (!ie || 2U + ie[1] > len) + return pos; + + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; +} + + +static u8 * hostapd_get_osen_ie(struct hostapd_data *hapd, u8 *pos, size_t len) +{ + const u8 *ie; + + ie = hostapd_vendor_wpa_ie(hapd, OSEN_IE_VENDOR_TYPE); + if (!ie || 2U + ie[1] > len) + return pos; + + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; } @@ -434,14 +512,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, /* Extended supported rates */ pos = hostapd_eid_ext_supp_rates(hapd, pos); - /* RSN, MDIE */ - if (!(hapd->conf->wpa == WPA_PROTO_WPA || - (hapd->conf->osen && !hapd->conf->wpa))) - pos = hostapd_eid_wpa(hapd, pos, epos - pos); - + pos = hostapd_get_rsne(hapd, pos, epos - pos); pos = hostapd_eid_bss_load(hapd, pos, epos - pos); - pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos); + pos = hostapd_get_mde(hapd, pos, epos - pos); /* eCSA IE */ csa_pos = hostapd_eid_ecsa(hapd, pos); @@ -488,6 +562,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ pos = hostapd_eid_fils_indic(hapd, pos, 0); + pos = hostapd_get_rsnxe(hapd, pos, epos - pos); #ifdef CONFIG_IEEE80211AX if (hapd->iconf->ieee80211ax) { @@ -503,10 +578,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_vendor_vht(hapd, pos); #endif /* CONFIG_IEEE80211AC */ - /* WPA */ - if (hapd->conf->wpa == WPA_PROTO_WPA || - (hapd->conf->osen && !hapd->conf->wpa)) - pos = hostapd_eid_wpa(hapd, pos, epos - pos); + /* WPA / OSEN */ + pos = hostapd_get_wpa_ie(hapd, pos, epos - pos); + pos = hostapd_get_osen_ie(hapd, pos, epos - pos); /* Wi-Fi Alliance WMM */ pos = hostapd_eid_wmm(hapd, pos); @@ -1052,7 +1126,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, size_t resp_len = 0; #ifdef NEED_AP_MLME u16 capab_info; - u8 *pos, *tailpos, *csa_pos; + u8 *pos, *tailpos, *tailend, *csa_pos; #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 @@ -1099,6 +1173,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, os_free(tail); return -1; } + tailend = tail + tail_len; head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON); @@ -1139,8 +1214,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, head_len = pos - (u8 *) head; - tailpos = hostapd_eid_country(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - tailpos); + tailpos = hostapd_eid_country(hapd, tailpos, tailend - tailpos); /* Power Constraint element */ tailpos = hostapd_eid_pwr_constraint(hapd, tailpos); @@ -1157,19 +1231,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, /* Extended supported rates */ tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); - /* RSN, MDIE */ - if (!(hapd->conf->wpa == WPA_PROTO_WPA || - (hapd->conf->osen && !hapd->conf->wpa))) - tailpos = hostapd_eid_wpa(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - - tailpos); - + tailpos = hostapd_get_rsne(hapd, tailpos, tailend - tailpos); + tailpos = hostapd_eid_bss_load(hapd, tailpos, tailend - tailpos); tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - - tailpos); - - tailpos = hostapd_eid_bss_load(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - tailpos); + tailend - tailpos); + tailpos = hostapd_get_mde(hapd, tailpos, tailend - tailpos); /* eCSA IE */ csa_pos = hostapd_eid_ecsa(hapd, tailpos); @@ -1218,6 +1284,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0); + tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos); #ifdef CONFIG_IEEE80211AX if (hapd->iconf->ieee80211ax) { @@ -1234,12 +1301,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_vendor_vht(hapd, tailpos); #endif /* CONFIG_IEEE80211AC */ - /* WPA */ - if (hapd->conf->wpa == WPA_PROTO_WPA || - (hapd->conf->osen && !hapd->conf->wpa)) - tailpos = hostapd_eid_wpa(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - - tailpos); + /* WPA / OSEN */ + tailpos = hostapd_get_wpa_ie(hapd, tailpos, tailend - tailpos); + tailpos = hostapd_get_osen_ie(hapd, tailpos, tailend - tailpos); /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); From f3bcd696034683f94300dd971865af7ed86aa180 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Feb 2020 16:22:18 +0200 Subject: [PATCH 0041/1105] Remove CONFIG_IEEE80211N build option Hardcoded CONFIG_IEEE80211N to be included to clean up implementation. More or less all new devices support IEEE 802.11n (HT) and there is not much need for being able to remove that functionality from the build. Included this unconditionally to get rid of one more build options and to keep things simpler. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 6 ------ hostapd/Makefile | 6 ------ hostapd/android.config | 3 --- hostapd/config_file.c | 4 ---- hostapd/defconfig | 3 --- src/ap/ap_config.c | 2 -- src/ap/ap_list.c | 4 ---- src/ap/beacon.c | 4 ---- src/ap/ctrl_iface_ap.c | 2 -- src/ap/drv_callbacks.c | 2 -- src/ap/hostapd.c | 4 ---- src/ap/hw_features.c | 5 ----- src/ap/ieee802_11.c | 12 ------------ src/ap/sta_info.c | 6 ++---- src/drivers/driver_bsd.c | 6 +----- tests/build/build-hostapd-internal.config | 1 - tests/build/build-hostapd-minimal.config | 2 -- tests/build/build-wpa_supplicant-internal.config | 1 - tests/hwsim/example-hostapd.config | 1 - tests/hwsim/example-wpa_supplicant.config | 1 - wpa_supplicant/Android.mk | 5 ----- wpa_supplicant/Makefile | 5 ----- wpa_supplicant/android.config | 4 ---- wpa_supplicant/ap.c | 4 ---- wpa_supplicant/defconfig | 4 ---- wpa_supplicant/mesh_mpm.c | 8 -------- 26 files changed, 3 insertions(+), 102 deletions(-) diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 258c5ad9c..662a6cd18 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -281,10 +281,6 @@ L_CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP OBJS += src/ap/wnm_ap.c endif -ifdef CONFIG_IEEE80211N -L_CFLAGS += -DCONFIG_IEEE80211N -endif - ifdef CONFIG_IEEE80211AC L_CFLAGS += -DCONFIG_IEEE80211AC endif @@ -999,9 +995,7 @@ OBJS += src/ap/hw_features.c OBJS += src/ap/dfs.c L_CFLAGS += -DNEED_AP_MLME endif -ifdef CONFIG_IEEE80211N OBJS += src/ap/ieee802_11_ht.c -endif ifdef CONFIG_IEEE80211AC OBJS += src/ap/ieee802_11_vht.c diff --git a/hostapd/Makefile b/hostapd/Makefile index 8666763a0..dbe0403a1 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -331,10 +331,6 @@ CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP OBJS += ../src/ap/wnm_ap.o endif -ifdef CONFIG_IEEE80211N -CFLAGS += -DCONFIG_IEEE80211N -endif - ifdef CONFIG_IEEE80211AC CFLAGS += -DCONFIG_IEEE80211AC endif @@ -1155,9 +1151,7 @@ OBJS += ../src/ap/hw_features.o OBJS += ../src/ap/dfs.o CFLAGS += -DNEED_AP_MLME endif -ifdef CONFIG_IEEE80211N OBJS += ../src/ap/ieee802_11_ht.o -endif ifdef CONFIG_IEEE80211AC OBJS += ../src/ap/ieee802_11_vht.o diff --git a/hostapd/android.config b/hostapd/android.config index e2e6c7821..d9200beea 100644 --- a/hostapd/android.config +++ b/hostapd/android.config @@ -125,9 +125,6 @@ CONFIG_IPV6=y # the IEEE 802.11 Management capability (e.g., FreeBSD/net80211) #CONFIG_DRIVER_RADIUS_ACL=y -# IEEE 802.11n (High Throughput) support -CONFIG_IEEE80211N=y - # Remove debugging code that is printing out debug messages to stdout. # This can be used to reduce the size of the hostapd considerably if debugging # code is not needed. diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 3e9f17bf4..f77651a7b 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1151,7 +1151,6 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value) #endif /* CONFIG_IEEE80211R_AP */ -#ifdef CONFIG_IEEE80211N static int hostapd_config_ht_capab(struct hostapd_config *conf, const char *capab) { @@ -1204,7 +1203,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf, return 0; } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC @@ -3422,7 +3420,6 @@ static int hostapd_config_fill(struct hostapd_config *conf, if (bss->ocv && !bss->ieee80211w) bss->ieee80211w = 1; #endif /* CONFIG_OCV */ -#ifdef CONFIG_IEEE80211N } else if (os_strcmp(buf, "ieee80211n") == 0) { conf->ieee80211n = atoi(pos); } else if (os_strcmp(buf, "ht_capab") == 0) { @@ -3435,7 +3432,6 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->require_ht = atoi(pos); } else if (os_strcmp(buf, "obss_interval") == 0) { conf->obss_interval = atoi(pos); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC } else if (os_strcmp(buf, "ieee80211ac") == 0) { conf->ieee80211ac = atoi(pos); diff --git a/hostapd/defconfig b/hostapd/defconfig index 1a3d9f9ba..e12260f4a 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -148,9 +148,6 @@ CONFIG_IPV6=y # the IEEE 802.11 Management capability (e.g., FreeBSD/net80211) #CONFIG_DRIVER_RADIUS_ACL=y -# IEEE 802.11n (High Throughput) support -#CONFIG_IEEE80211N=y - # Wireless Network Management (IEEE Std 802.11v-2011) # Note: This is experimental and not complete implementation. #CONFIG_WNM=y diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index b462116af..b63c64bb6 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -1169,7 +1169,6 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } #endif /* CONFIG_IEEE80211R_AP */ -#ifdef CONFIG_IEEE80211N if (full_config && conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { bss->disable_11n = 1; @@ -1194,7 +1193,6 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, "requires CCMP/GCMP to be enabled, disabling HT " "capabilities"); } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (full_config && conf->ieee80211ac && diff --git a/src/ap/ap_list.c b/src/ap/ap_list.c index 8bf6ddec8..20be7f8f8 100644 --- a/src/ap/ap_list.c +++ b/src/ap/ap_list.c @@ -228,7 +228,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface, set_beacon++; } -#ifdef CONFIG_IEEE80211N if (!iface->olbc_ht && !ap->ht_support && (ap->channel == 0 || ap->channel == iface->conf->channel || @@ -241,7 +240,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface, MAC2STR(ap->addr), ap->channel); set_beacon++; } -#endif /* CONFIG_IEEE80211N */ if (set_beacon) ieee802_11_update_beacons(iface); @@ -285,14 +283,12 @@ void ap_list_timer(struct hostapd_iface *iface) iface->olbc = 0; set_beacon++; } -#ifdef CONFIG_IEEE80211N if (!olbc_ht && iface->olbc_ht) { wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); iface->olbc_ht = 0; hostapd_ht_operation_update(iface); set_beacon++; } -#endif /* CONFIG_IEEE80211N */ } if (set_beacon) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 41d03bc01..56220d93d 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -525,14 +525,12 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_supported_op_classes(hapd, pos); -#ifdef CONFIG_IEEE80211N /* Secondary Channel Offset element */ /* TODO: The standard doesn't specify a position for this element. */ pos = hostapd_eid_secondary_channel(hapd, pos); pos = hostapd_eid_ht_capabilities(hapd, pos); pos = hostapd_eid_ht_operation(hapd, pos); -#endif /* CONFIG_IEEE80211N */ pos = hostapd_eid_ext_capab(hapd, pos); @@ -1245,14 +1243,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_supported_op_classes(hapd, tailpos); -#ifdef CONFIG_IEEE80211N /* Secondary Channel Offset element */ /* TODO: The standard doesn't specify a position for this element. */ tailpos = hostapd_eid_secondary_channel(hapd, tailpos); tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); tailpos = hostapd_eid_ht_operation(hapd, tailpos); -#endif /* CONFIG_IEEE80211N */ tailpos = hostapd_eid_ext_capab(hapd, tailpos); diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index a54b0ca2c..ef53a8254 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -345,7 +345,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, } #endif /* CONFIG_IEEE80211AC */ -#ifdef CONFIG_IEEE80211N if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) { res = os_snprintf(buf + len, buflen - len, "ht_caps_info=0x%04x\n", @@ -354,7 +353,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, if (!os_snprintf_error(buflen - len, res)) len += res; } -#endif /* CONFIG_IEEE80211N */ if (sta->ext_capability && buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) { diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 38506a097..a3a4f3ec3 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -220,7 +220,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, } #endif /* CONFIG_P2P */ -#ifdef CONFIG_IEEE80211N #ifdef NEED_AP_MLME if (elems.ht_capabilities && (hapd->iface->conf->ht_capab & @@ -234,7 +233,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, ht40_intolerant_add(hapd->iface, sta); } #endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_INTERWORKING if (elems.ext_capab && elems.ext_capab_len > 4) { diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index b87663fe9..ccf3f88f2 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -481,11 +481,9 @@ static void sta_track_deinit(struct hostapd_iface *iface) static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) { wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); -#ifdef CONFIG_IEEE80211N #ifdef NEED_AP_MLME hostapd_stop_setup_timers(iface); #endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211N */ if (iface->current_mode) acs_cleanup(iface); hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); @@ -2349,12 +2347,10 @@ void hostapd_interface_deinit(struct hostapd_iface *iface) hostapd_bss_deinit(iface->bss[j]); } -#ifdef CONFIG_IEEE80211N #ifdef NEED_AP_MLME hostapd_stop_setup_timers(iface); eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); #endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211N */ } diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 83aecade3..0b922b9c3 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -224,7 +224,6 @@ int hostapd_prepare_rates(struct hostapd_iface *iface, } -#ifdef CONFIG_IEEE80211N static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) { int pri_freq, sec_freq; @@ -667,12 +666,9 @@ static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface) } #endif /* CONFIG_IEEE80211AX */ -#endif /* CONFIG_IEEE80211N */ - int hostapd_check_ht_capab(struct hostapd_iface *iface) { -#ifdef CONFIG_IEEE80211N int ret; if (is_6ghz_freq(iface->freq)) @@ -705,7 +701,6 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface) return ret; if (!ieee80211n_allowed_ht40_channel_pair(iface)) return -1; -#endif /* CONFIG_IEEE80211N */ return 0; } diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 68fdba4e0..03810de4e 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3136,7 +3136,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (resp != WLAN_STATUS_SUCCESS) return resp; -#ifdef CONFIG_IEEE80211N resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities); if (resp != WLAN_STATUS_SUCCESS) return resp; @@ -3147,7 +3146,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, "mandatory HT PHY - reject association"); return WLAN_STATUS_ASSOC_DENIED_NO_HT; } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (hapd->iconf->ieee80211ac) { @@ -3392,7 +3390,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, pfs_fail: #endif /* CONFIG_DPP2 */ -#ifdef CONFIG_IEEE80211N if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) && wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { hostapd_logger(hapd, sta->addr, @@ -3402,7 +3399,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, "association"); return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_HS20 } else if (hapd->conf->osen) { if (elems.osen == NULL) { @@ -3603,10 +3599,8 @@ static int add_associated_sta(struct hostapd_data *hapd, sta->ft_over_ds = 0; } -#ifdef CONFIG_IEEE80211N if (sta->flags & WLAN_STA_HT) hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (sta->flags & WLAN_STA_VHT) hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap); @@ -3754,10 +3748,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) p = hostapd_eid_assoc_comeback_time(hapd, sta, p); -#ifdef CONFIG_IEEE80211N p = hostapd_eid_ht_capabilities(hapd, p); p = hostapd_eid_ht_operation(hapd, p); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac && @@ -4335,9 +4327,7 @@ static void handle_assoc(struct hostapd_data *hapd, ieee802_11_set_beacons(hapd->iface); } -#ifdef CONFIG_IEEE80211N update_ht_state(hapd, sta); -#endif /* CONFIG_IEEE80211N */ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, @@ -4676,14 +4666,12 @@ static int handle_action(struct hostapd_data *hapd, #endif /* CONFIG_FST */ case WLAN_ACTION_PUBLIC: case WLAN_ACTION_PROTECTED_DUAL: -#ifdef CONFIG_IEEE80211N if (len >= IEEE80211_HDRLEN + 2 && mgmt->u.action.u.public_action.action == WLAN_PA_20_40_BSS_COEX) { hostapd_2040_coex_action(hapd, mgmt, len); return 1; } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_DPP if (len >= IEEE80211_HDRLEN + 6 && mgmt->u.action.u.vs_public_action.action == diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index c0503f6c5..87a9fd409 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -233,9 +233,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) sta->assoc_ie_taxonomy = NULL; #endif /* CONFIG_TAXONOMY */ -#ifdef CONFIG_IEEE80211N ht40_intolerant_remove(hapd->iface, sta); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_P2P if (sta->no_p2p_set) { @@ -246,10 +244,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) } #endif /* CONFIG_P2P */ -#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) +#ifdef NEED_AP_MLME if (hostapd_ht_operation_update(hapd->iface) > 0) set_beacon++; -#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ +#endif /* NEED_AP_MLME */ #ifdef CONFIG_MESH if (hapd->mesh_sta_free_cb) diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c index 1fcafedae..b4400d7bf 100644 --- a/src/drivers/driver_bsd.c +++ b/src/drivers/driver_bsd.c @@ -576,17 +576,13 @@ bsd_set_freq(void *priv, struct hostapd_freq_params *freq) if (channel < 14) { mode = -#ifdef CONFIG_IEEE80211N freq->ht_enabled ? IFM_IEEE80211_11NG : -#endif /* CONFIG_IEEE80211N */ - IFM_IEEE80211_11G; + IFM_IEEE80211_11G; } else if (channel == 14) { mode = IFM_IEEE80211_11B; } else { mode = -#ifdef CONFIG_IEEE80211N freq->ht_enabled ? IFM_IEEE80211_11NA : -#endif /* CONFIG_IEEE80211N */ IFM_IEEE80211_11A; } if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) { diff --git a/tests/build/build-hostapd-internal.config b/tests/build/build-hostapd-internal.config index 33a2f5bd2..421977eed 100644 --- a/tests/build/build-hostapd-internal.config +++ b/tests/build/build-hostapd-internal.config @@ -43,7 +43,6 @@ CONFIG_VLAN_NETLINK=y CONFIG_LIBNL32=y CONFIG_LIBNL3_ROUTE=y CONFIG_IEEE80211R=y -CONFIG_IEEE80211N=y CONFIG_IEEE80211AC=y CONFIG_WPS=y diff --git a/tests/build/build-hostapd-minimal.config b/tests/build/build-hostapd-minimal.config index bd7e1847c..b62857b79 100644 --- a/tests/build/build-hostapd-minimal.config +++ b/tests/build/build-hostapd-minimal.config @@ -13,5 +13,3 @@ CFLAGS += -DCONFIG_NO_HOSTAPD_LOGGER CONFIG_NO_AES_EXTRAS=y CFLAGS += -Os - -CONFIG_IEEE80211N=y diff --git a/tests/build/build-wpa_supplicant-internal.config b/tests/build/build-wpa_supplicant-internal.config index ba55e8ffe..574fb4b18 100644 --- a/tests/build/build-wpa_supplicant-internal.config +++ b/tests/build/build-wpa_supplicant-internal.config @@ -47,7 +47,6 @@ CONFIG_OCSP=y #CONFIG_CTRL_IFACE_DBUS_INTRO=y CONFIG_IEEE80211R=y -CONFIG_IEEE80211N=y CONFIG_IEEE80211AC=y CONFIG_DEBUG_FILE=y diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config index d93c4d252..942134a51 100644 --- a/tests/hwsim/example-hostapd.config +++ b/tests/hwsim/example-hostapd.config @@ -48,7 +48,6 @@ CONFIG_VLAN_NETLINK=y CONFIG_LIBNL32=y CONFIG_LIBNL3_ROUTE=y CONFIG_IEEE80211R=y -CONFIG_IEEE80211N=y CONFIG_IEEE80211AC=y CONFIG_IEEE80211AX=y diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config index 397a6f173..d494caf86 100644 --- a/tests/hwsim/example-wpa_supplicant.config +++ b/tests/hwsim/example-wpa_supplicant.config @@ -58,7 +58,6 @@ CONFIG_CTRL_IFACE_DBUS_NEW=y CONFIG_CTRL_IFACE_DBUS_INTRO=y CONFIG_IEEE80211R=y -CONFIG_IEEE80211N=y CONFIG_IEEE80211AC=y CONFIG_IEEE80211AX=y diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index e6c4e18ba..0883e749c 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -858,7 +858,6 @@ OBJS += src/ap/bss_load.c OBJS += src/ap/eap_user_db.c OBJS += src/ap/neighbor_db.c OBJS += src/ap/rrm.c -ifdef CONFIG_IEEE80211N OBJS += src/ap/ieee802_11_ht.c ifdef CONFIG_IEEE80211AC OBJS += src/ap/ieee802_11_vht.c @@ -866,7 +865,6 @@ endif ifdef CONFIG_IEEE80211AX OBJS += src/ap/ieee802_11_he.c endif -endif ifdef CONFIG_WNM_AP L_CFLAGS += -DCONFIG_WNM_AP OBJS += src/ap/wnm_ap.c @@ -886,15 +884,12 @@ OBJS += src/eap_server/eap_server.c OBJS += src/eap_server/eap_server_identity.c OBJS += src/eap_server/eap_server_methods.c -ifdef CONFIG_IEEE80211N -L_CFLAGS += -DCONFIG_IEEE80211N ifdef CONFIG_IEEE80211AC L_CFLAGS += -DCONFIG_IEEE80211AC endif ifdef CONFIG_IEEE80211AX L_CFLAGS += -DCONFIG_IEEE80211AX endif -endif ifdef NEED_AP_MLME OBJS += src/ap/wmm.c diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 0c54077b8..e41464f4d 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -904,7 +904,6 @@ OBJS += ../src/ap/bss_load.o OBJS += ../src/ap/eap_user_db.o OBJS += ../src/ap/neighbor_db.o OBJS += ../src/ap/rrm.o -ifdef CONFIG_IEEE80211N OBJS += ../src/ap/ieee802_11_ht.o ifdef CONFIG_IEEE80211AC OBJS += ../src/ap/ieee802_11_vht.o @@ -912,7 +911,6 @@ endif ifdef CONFIG_IEEE80211AX OBJS += ../src/ap/ieee802_11_he.o endif -endif ifdef CONFIG_WNM_AP CFLAGS += -DCONFIG_WNM_AP OBJS += ../src/ap/wnm_ap.o @@ -932,15 +930,12 @@ OBJS += ../src/eap_server/eap_server.o OBJS += ../src/eap_server/eap_server_identity.o OBJS += ../src/eap_server/eap_server_methods.o -ifdef CONFIG_IEEE80211N -CFLAGS += -DCONFIG_IEEE80211N ifdef CONFIG_IEEE80211AC CFLAGS += -DCONFIG_IEEE80211AC endif ifdef CONFIG_IEEE80211AX CFLAGS += -DCONFIG_IEEE80211AX endif -endif ifdef NEED_AP_MLME OBJS += ../src/ap/wmm.o diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config index f9d3712a8..69dc7127f 100644 --- a/wpa_supplicant/android.config +++ b/wpa_supplicant/android.config @@ -438,11 +438,7 @@ CONFIG_ANDROID_LOG=y # either wpa_supplicant or hostapd are run. CONFIG_NO_RANDOM_POOL=y -# IEEE 802.11n (High Throughput) support (mainly for AP mode) -CONFIG_IEEE80211N=y - # IEEE 802.11ac (Very High Throughput) support (mainly for AP mode) -# (depends on CONFIG_IEEE80211N) #CONFIG_IEEE80211AC=y # Wireless Network Management (IEEE Std 802.11v-2011) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 76607e121..d1002d225 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -44,7 +44,6 @@ static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); #endif /* CONFIG_WPS */ -#ifdef CONFIG_IEEE80211N static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_config *conf, @@ -130,7 +129,6 @@ no_vht: conf->channel + conf->secondary_channel * 2; conf->vht_oper_chwidth = CHANWIDTH_USE_HT; } -#endif /* CONFIG_IEEE80211N */ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, @@ -149,7 +147,6 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, /* TODO: enable HT40 if driver supports it; * drop to 11b if driver does not support 11g */ -#ifdef CONFIG_IEEE80211N /* * Enable HT20 if the driver supports it, by setting conf->ieee80211n * and a mask of allowed capabilities within conf->ht_capab. @@ -269,7 +266,6 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, conf->no_pri_sec_switch = 1; } } -#endif /* CONFIG_IEEE80211N */ return 0; } diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index c8091fee9..09145f2de 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -471,11 +471,7 @@ CONFIG_DEBUG_SYSLOG=y # Requires glibc 2.25 to build, falls back to /dev/random if unavailable. #CONFIG_GETRANDOM=y -# IEEE 802.11n (High Throughput) support (mainly for AP mode) -CONFIG_IEEE80211N=y - # IEEE 802.11ac (Very High Throughput) support (mainly for AP mode) -# (depends on CONFIG_IEEE80211N) CONFIG_IEEE80211AC=y # Wireless Network Management (IEEE Std 802.11v-2011) diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 31dd1d3c6..4925b5cde 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -233,12 +233,10 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, 2 + 24 + /* peering management */ 2 + 96 + 32 + 32 + /* AMPE (96 + max GTKlen + max IGTKlen) */ 2 + 16; /* MIC */ -#ifdef CONFIG_IEEE80211N if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) { buf_len += 2 + 26 + /* HT capabilities */ 2 + 22; /* HT operation */ } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) { buf_len += 2 + 12 + /* VHT Capabilities */ @@ -354,7 +352,6 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, wpabuf_put(buf, PMKID_LEN)); } -#ifdef CONFIG_IEEE80211N if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) { u8 ht_capa_oper[2 + 26 + 2 + 22]; @@ -362,7 +359,6 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, pos = hostapd_eid_ht_operation(bss, pos); wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper); } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) { u8 vht_capa_oper[2 + 12 + 2 + 5]; @@ -696,9 +692,7 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, struct mesh_conf *conf = wpa_s->ifmsh->mconf; struct hostapd_data *data = wpa_s->ifmsh->bss[0]; struct sta_info *sta; -#ifdef CONFIG_IEEE80211N struct ieee80211_ht_operation *oper; -#endif /* CONFIG_IEEE80211N */ int ret; if (elems->mesh_config_len >= 7 && @@ -729,7 +723,6 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, if (!sta->my_lid) mesh_mpm_init_link(wpa_s, sta); -#ifdef CONFIG_IEEE80211N copy_sta_ht_capab(data, sta, elems->ht_capabilities); oper = (struct ieee80211_ht_operation *) elems->ht_operation; @@ -743,7 +736,6 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, } update_ht_state(data, sta); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC copy_sta_vht_capab(data, sta, elems->vht_capabilities); From 7f1529d2a5c399920aca4c7185dd7daea3e06e30 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Feb 2020 16:50:10 +0200 Subject: [PATCH 0042/1105] Fix HE element order in Beacon and Probe Response frames Spatial Reuse Parameter Set element is before MU EDCA Parameter Set element. Signed-off-by: Jouni Malinen --- src/ap/beacon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 56220d93d..990a38ad4 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -566,8 +566,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, if (hapd->iconf->ieee80211ax) { pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP); pos = hostapd_eid_he_operation(hapd, pos); - pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); pos = hostapd_eid_spatial_reuse(hapd, pos); + pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); } #endif /* CONFIG_IEEE80211AX */ @@ -1287,8 +1287,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_he_capab(hapd, tailpos, IEEE80211_MODE_AP); tailpos = hostapd_eid_he_operation(hapd, tailpos); - tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); tailpos = hostapd_eid_spatial_reuse(hapd, tailpos); + tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); } #endif /* CONFIG_IEEE80211AX */ From 8fe7ec664082e88447d31ca9b2b31873f2c93b3f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Feb 2020 17:05:20 +0200 Subject: [PATCH 0043/1105] Remove Secondary Channel Offset element from Beacon/Probe Response frames This element is not used in Beacon or Probe Response frames (which is the reason why the standard does not indicate where exactly it would be in those frames..); HT Operation element has this information and so does Extended CSA element. In practice, this reverts the functionality added in commit 76aab0305c1f ("Add secondary channel IE for CSA"). Signed-off-by: Jouni Malinen --- src/ap/beacon.c | 10 ---------- src/ap/ieee802_11.h | 1 - src/ap/ieee802_11_ht.c | 24 ------------------------ 3 files changed, 35 deletions(-) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 990a38ad4..f5de17747 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -524,11 +524,6 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = csa_pos; pos = hostapd_eid_supported_op_classes(hapd, pos); - - /* Secondary Channel Offset element */ - /* TODO: The standard doesn't specify a position for this element. */ - pos = hostapd_eid_secondary_channel(hapd, pos); - pos = hostapd_eid_ht_capabilities(hapd, pos); pos = hostapd_eid_ht_operation(hapd, pos); @@ -1242,11 +1237,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = csa_pos; tailpos = hostapd_eid_supported_op_classes(hapd, tailpos); - - /* Secondary Channel Offset element */ - /* TODO: The standard doesn't specify a position for this element. */ - tailpos = hostapd_eid_secondary_channel(hapd, tailpos); - tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); tailpos = hostapd_eid_ht_operation(hapd, tailpos); diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index ab61eca9d..181cfaf0a 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -53,7 +53,6 @@ u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid, size_t len); u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts); u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid); diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c index 6db93658c..26076d12b 100644 --- a/src/ap/ieee802_11_ht.c +++ b/src/ap/ieee802_11_ht.c @@ -109,30 +109,6 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) } -u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid) -{ - u8 sec_ch; - - if (!hapd->cs_freq_params.channel || - !hapd->cs_freq_params.sec_channel_offset || - is_6ghz_op_class(hapd->iconf->op_class)) - return eid; - - if (hapd->cs_freq_params.sec_channel_offset == -1) - sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW; - else if (hapd->cs_freq_params.sec_channel_offset == 1) - sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE; - else - return eid; - - *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; - *eid++ = 1; - *eid++ = sec_ch; - - return eid; -} - - /* op_mode Set to 0 (HT pure) under the followign conditions From 1074d42416508b606bdfa5e322bea0603edee44d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Feb 2020 17:08:19 +0200 Subject: [PATCH 0044/1105] Fix a typo in a comment Signed-off-by: Jouni Malinen --- src/ap/ieee802_11_ht.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c index 26076d12b..59ecbdce7 100644 --- a/src/ap/ieee802_11_ht.c +++ b/src/ap/ieee802_11_ht.c @@ -111,7 +111,7 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) /* op_mode -Set to 0 (HT pure) under the followign conditions +Set to 0 (HT pure) under the following conditions - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - all STAs in the BSS are 20 MHz HT in 20 MHz BSS Set to 1 (HT non-member protection) if there may be non-HT STAs From e9ac44fcbc891455e34dbce73efd8b3141b86285 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Feb 2020 18:49:01 +0200 Subject: [PATCH 0045/1105] Make INTERWORKING_CONNECT more reliable in testing environment Pick the most recently added BSS entry based on BSSID matching to avoid issues in testing environment where the SSID of the AP may have changed and both the old and new BSS is still present in the scan results. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 8d75c80b2..c9074a239 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -7196,7 +7196,7 @@ static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst, return -1; } - bss = wpa_bss_get_bssid(wpa_s, bssid); + bss = wpa_bss_get_bssid_latest(wpa_s, bssid); if (bss == NULL) { wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, MAC2STR(bssid)); From fae7e64aa3ecf317d15beb799fcc6865a55b1bd3 Mon Sep 17 00:00:00 2001 From: Ouden Date: Fri, 21 Feb 2020 09:39:46 +0800 Subject: [PATCH 0046/1105] Save RM enabled capability of station with AP SME Save RM enabled capability element of an associating station when hostapd use the device AP SME similarly to how this information is saved with SME-on-hostapd cases. This allows radio measurement operations (e.g., REQ_BEACON) to be used. Signed-off-by: Ouden --- src/ap/drv_callbacks.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index a3a4f3ec3..9ed131cfd 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -623,6 +623,11 @@ skip_wpa_check: pfs_fail: #endif /* CONFIG_DPP2 */ + if (elems.rrm_enabled && + elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa)) + os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled, + sizeof(sta->rrm_enabled_capa)); + #if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE) hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); From 7b26238d460d1e2daaa8e5e5eaf0d1b64aaef6b4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Feb 2020 19:07:11 +0200 Subject: [PATCH 0047/1105] Do not skip MBO PMF check with the WPS special case WPA check exception The MBO PMF check for AP SME in the driver case was added into a location that is skipped for WPS processing. That was not really the correct place for this since the skip_wpa_check label was supposed to remain immediately following the WPA checks. While this does not really have much of a practical impact, move the check around so that the skip_wpa_check label remains where it is supposed to be. Fixes: 4c572281edaa ("MBO: Mandate use of PMF for WPA2+MBO association (AP)") Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 9ed131cfd..61e56b6e5 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -467,6 +467,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, return WLAN_STATUS_INVALID_IE; #endif /* CONFIG_HS20 */ } +#ifdef CONFIG_WPS +skip_wpa_check: +#endif /* CONFIG_WPS */ #ifdef CONFIG_MBO if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) && @@ -478,10 +481,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, } #endif /* CONFIG_MBO */ -#ifdef CONFIG_WPS -skip_wpa_check: -#endif /* CONFIG_WPS */ - #ifdef CONFIG_IEEE80211R_AP p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), sta->auth_alg, req_ies, req_ies_len); From 35da7c20acec5d0c447d2f3eb219f4fb2a2683d9 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sat, 4 Jan 2020 23:10:00 +0100 Subject: [PATCH 0048/1105] nl80211: Add driver capability flag for CAN_REPLACE_PTK0 The CAN_REPLACE_PTK0 flag provided by nl80211 can be used to detect if the card/driver is explicitly indicating capability to rekey STA PTK keys using only keyid 0 correctly. Check if the card/driver supports it and make the status available as a driver flag. Signed-off-by: Alexander Wetzel --- src/drivers/driver.h | 2 ++ src/drivers/driver_nl80211_capa.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 64fc0fd90..48dd3fe52 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1838,6 +1838,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_VLAN_OFFLOAD 0x0800000000000000ULL /** Driver supports UPDATE_FT_IES command */ #define WPA_DRIVER_FLAGS_UPDATE_FT_IES 0x1000000000000000ULL +/** Driver can correctly rekey PTKs without Extended Key ID */ +#define WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS 0x2000000000000000ULL u64 flags; #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index a0f6e52ea..61c8c2556 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -445,6 +445,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_VLAN_OFFLOAD)) capa->flags |= WPA_DRIVER_FLAGS_VLAN_OFFLOAD; + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_CAN_REPLACE_PTK0)) + capa->flags |= WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS; } From 1a7963e36fa67b865fd1486ce863e612e6b6a052 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Fri, 10 Jan 2020 23:19:08 +0100 Subject: [PATCH 0049/1105] AP: Allow PTK rekeying without Ext KeyID to be disabled as a workaround Rekeying a pairwise key using only keyid 0 (PTK0 rekey) has many broken implementations and should be avoided when using or interacting with one. The effects can be triggered by either end of the connection and range from hardly noticeable disconnects over long connection freezes up to leaking clear text MPDUs. To allow affected users to mitigate the issues, add a new hostapd configuration option "wpa_deny_ptk0_rekey" to replace all PTK0 rekeys with disconnection. This requires the station to reassociate to get connected again and as such, can result in connectivity issues as well. Signed-off-by: Alexander Wetzel --- hostapd/config_file.c | 9 +++++++++ hostapd/hostapd.conf | 34 ++++++++++++++++++++++++++++++++++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 1 + src/ap/wpa_auth.c | 23 +++++++++++++++++++++-- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 10 ++++++++++ src/common/defs.h | 6 ++++++ 8 files changed, 83 insertions(+), 2 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index f77651a7b..6dde59a5a 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2874,6 +2874,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->wpa_gmk_rekey = atoi(pos); } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { bss->wpa_ptk_rekey = atoi(pos); + } else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) { + bss->wpa_deny_ptk0_rekey = atoi(pos); + if (bss->wpa_deny_ptk0_rekey < 0 || + bss->wpa_deny_ptk0_rekey > 2) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2", + line, bss->wpa_deny_ptk0_rekey); + return 1; + } } else if (os_strcmp(buf, "wpa_group_update_count") == 0) { char *endp; unsigned long val = strtoul(pos, &endp, 0); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 0433fed8a..0f8461d49 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -904,6 +904,8 @@ eapol_key_index_workaround=0 # EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable # reauthentication). +# Note: Reauthentications may enforce a disconnection, check the related +# parameter wpa_deny_ptk0_rekey for details. #eap_reauth_period=3600 # Use PAE group address (01:80:c2:00:00:03) instead of individual target @@ -1608,8 +1610,40 @@ own_ip_addr=127.0.0.1 # Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of # PTK to mitigate some attacks against TKIP deficiencies. +# Warning: PTK rekeying is buggy with many drivers/devices and with such +# devices, the only secure method to rekey the PTK without Extended Key ID +# support requires a disconnection. Check the related parameter +# wpa_deny_ptk0_rekey for details. #wpa_ptk_rekey=600 +# Workaround for PTK rekey issues +# +# Rekeying the PTK without using "Extended Key ID for Individually Addressed +# Frames" (two different Key ID values for pairwise keys) can, depending on the +# used cards/drivers, impact the security and stability of connections. Both +# ends can accidentally trick one end to drop all packets send by it until the +# connection is torn down or rekeyed again. Additionally, some drivers may +# skip/break the encryption for the time window the key is updated (normally a +# few milliseconds). +# +# To avoid such issues, hostapd can now replace all PTK rekeys using only keyid +# 0 (PTK0 rekeys) with disconnection that forces the remote stations to +# reconnect instead. +# +# EAP reauthentication depends on replacing the PTK and is therefore just +# another way to rekey the PTK and is affected by this parameter, too. +# +# "Extended Key ID for Individually Addressed Frames" is avoiding the issues +# using two separate keys and this parameter will be ignored when using it +# (i.e., PTK rekeying is allowed regardless of this parameter value). +# +# Available options: +# 0 = always rekey when configured/instructed (default) +# 1 = only rekey when the local driver is explicitly indicating it can perform +# this operation without issues +# 2 = never allow PTK0 rekeys +#wpa_deny_ptk0_rekey=0 + # The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way # Handshake are retried per 4-Way Handshake attempt. # (dot11RSNAConfigPairwiseUpdateCount) diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index b63c64bb6..fddc8ca44 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -64,6 +64,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) bss->wpa_group_rekey = 600; bss->wpa_gmk_rekey = 86400; + bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS; bss->wpa_group_update_count = 4; bss->wpa_pairwise_update_count = 4; bss->wpa_disable_eapol_key_retries = diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index ca9ae14cd..b6e11f25f 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -370,6 +370,7 @@ struct hostapd_bss_config { int wpa_strict_rekey; int wpa_gmk_rekey; int wpa_ptk_rekey; + enum ptk0_rekey_handling wpa_deny_ptk0_rekey; u32 wpa_group_update_count; u32 wpa_pairwise_update_count; int wpa_disable_eapol_key_retries; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 1f835d80a..e67c34498 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -781,8 +781,18 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm) if (sm == NULL) return; - sm->PTKRequest = TRUE; - sm->PTK_valid = 0; + if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { + wpa_printf(MSG_INFO, + "WPA: PTK0 rekey not allowed, disconnect " MACSTR, + MAC2STR(sm->addr)); + sm->Disconnect = TRUE; + /* Try to encourage the STA to reconnect */ + sm->disconnect_reason = + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; + } else { + sm->PTKRequest = TRUE; + sm->PTK_valid = 0; + } } @@ -1802,6 +1812,15 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) sm->Init = FALSE; sm->AuthenticationRequest = TRUE; break; + } else if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { + wpa_printf(MSG_INFO, + "WPA: PTK0 rekey not allowed, disconnect " + MACSTR, MAC2STR(sm->addr)); + sm->Disconnect = TRUE; + /* Try to encourage the STA reconnect */ + sm->disconnect_reason = + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; + break; } if (sm->GUpdateStationKeys) { /* diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 93e0c745d..1f7ba4899 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -176,6 +176,7 @@ struct wpa_auth_config { int wpa_strict_rekey; int wpa_gmk_rekey; int wpa_ptk_rekey; + int wpa_deny_ptk0_rekey; u32 wpa_group_update_count; u32 wpa_pairwise_update_count; int wpa_disable_eapol_key_retries; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 7dc4c8e6b..82e82a7d2 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1381,6 +1381,16 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) _conf.tx_status = 1; if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) _conf.ap_mlme = 1; + + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) && + (hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER || + (hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK && + !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) { + wpa_msg(hapd->msg_ctx, MSG_INFO, + "Disable PTK0 rekey support - replaced with disconnect"); + _conf.wpa_deny_ptk0_rekey = 1; + } + hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd); if (hapd->wpa_auth == NULL) { wpa_printf(MSG_ERROR, "WPA initialization failed."); diff --git a/src/common/defs.h b/src/common/defs.h index 5e22278e6..1e21ec2de 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -445,4 +445,10 @@ enum key_flag { KEY_FLAG_MODIFY, }; +enum ptk0_rekey_handling { + PTK0_REKEY_ALLOW_ALWAYS, + PTK0_REKEY_ALLOW_LOCAL_OK, + PTK0_REKEY_ALLOW_NEVER +}; + #endif /* DEFS_H */ From 1f90a49d028debceb748ab91b7685ae774451e8f Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Fri, 10 Jan 2020 23:19:09 +0100 Subject: [PATCH 0050/1105] STA: Allow PTK rekeying without Ext KeyID to be disabled as a workaround Rekeying a pairwise key using only keyid 0 (PTK0 rekey) has many broken implementations and should be avoided when using or interacting with one. The effects can be triggered by either end of the connection and range from hardly noticeable disconnects over long connection freezes up to leaking clear text MPDUs. To allow affected users to mitigate the issues, add a new configuration option "wpa_deny_ptk0_rekey" to replace all PTK0 rekeys with fast reconnects. Signed-off-by: Alexander Wetzel --- src/eapol_supp/eapol_supp_sm.c | 14 ++++++++++++++ src/eapol_supp/eapol_supp_sm.h | 9 +++++++++ src/rsn_supp/wpa.c | 18 ++++++++++++++++++ src/rsn_supp/wpa.h | 3 +++ src/rsn_supp/wpa_i.h | 7 +++++++ wpa_supplicant/ap.c | 1 + wpa_supplicant/config.c | 2 ++ wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 13 +++++++++++++ wpa_supplicant/ctrl_iface.c | 2 ++ wpa_supplicant/events.c | 19 ++++++++++++------- wpa_supplicant/ibss_rsn.c | 7 +++++++ wpa_supplicant/preauth_test.c | 7 +++++++ wpa_supplicant/wpa_cli.c | 1 + wpa_supplicant/wpa_supplicant.c | 26 +++++++++++++++++++++++++- wpa_supplicant/wpa_supplicant.conf | 26 ++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ wpa_supplicant/wpas_glue.c | 23 +++++++++++++++++++++++ 18 files changed, 174 insertions(+), 8 deletions(-) diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index f1ca0a859..a34cc0be2 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -200,6 +200,15 @@ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) } +static int eapol_sm_confirm_auth(struct eapol_sm *sm) +{ + if (!sm->ctx->confirm_auth_cb) + return 0; + + return sm->ctx->confirm_auth_cb(sm->ctx->ctx); +} + + static void eapol_enable_timer_tick(struct eapol_sm *sm) { if (sm->timer_tick_enabled) @@ -316,6 +325,11 @@ SM_STATE(SUPP_PAE, AUTHENTICATED) SM_STATE(SUPP_PAE, RESTART) { + if (eapol_sm_confirm_auth(sm)) { + /* Don't process restart, we are already reconnecting */ + return; + } + SM_ENTRY(SUPP_PAE, RESTART); sm->eapRestart = TRUE; if (sm->altAccept) { diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h index c9d7522d5..67f82c60a 100644 --- a/src/eapol_supp/eapol_supp_sm.h +++ b/src/eapol_supp/eapol_supp_sm.h @@ -298,6 +298,15 @@ struct eapol_ctx { * @len: Length of anonymous identity in octets */ void (*set_anon_id)(void *ctx, const u8 *id, size_t len); + + /** + * confirm_auth_cb - Callback confirming if we can install a new PTK + * @ctx: eapol_ctx from eap_peer_sm_init() call + * Returns: 0 when authentication can continue, -1 when reconnecting + * + * Automatically triggers a reconnect when not. + */ + int (*confirm_auth_cb)(void *ctx); }; diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 1e209ada5..263e2108a 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -183,6 +183,14 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) int key_info, ver; u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic; + if (pairwise && sm->wpa_deny_ptk0_rekey && + wpa_sm_get_state(sm) == WPA_COMPLETED) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: PTK0 rekey not allowed, reconnecting"); + wpa_sm_reconnect(sm); + return; + } + if (wpa_use_akm_defined(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AKM_DEFINED; else if (wpa_key_mgmt_ft(sm->key_mgmt) || @@ -618,6 +626,13 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, return; } + if (sm->wpa_deny_ptk0_rekey && wpa_sm_get_state(sm) == WPA_COMPLETED) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: PTK0 rekey not allowed, reconnecting"); + wpa_sm_reconnect(sm); + return; + } + wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way " "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); @@ -3142,6 +3157,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_SAE_PWE: sm->sae_pwe = value; break; + case WPA_PARAM_DENY_PTK0_REKEY: + sm->wpa_deny_ptk0_rekey = value; + break; default: break; } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index e14f26e01..0bd14495a 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -27,6 +27,7 @@ struct wpa_sm_ctx { void (*set_state)(void *ctx, enum wpa_states state); enum wpa_states (*get_state)(void *ctx); void (*deauthenticate)(void * ctx, u16 reason_code); + void (*reconnect)(void *ctx); int (*set_key)(void *ctx, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, @@ -100,6 +101,7 @@ enum wpa_sm_conf_params { WPA_PARAM_MFP, WPA_PARAM_OCV, WPA_PARAM_SAE_PWE, + WPA_PARAM_DENY_PTK0_REKEY, }; struct rsn_supp_config { @@ -111,6 +113,7 @@ struct rsn_supp_config { const u8 *ssid; size_t ssid_len; int wpa_ptk_rekey; + int wpa_deny_ptk0_rekey; int p2p; int wpa_rsc_relaxation; int owe_ptk_workaround; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index bd4446402..7af678dcd 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -63,6 +63,7 @@ struct wpa_sm { u8 ssid[32]; size_t ssid_len; int wpa_ptk_rekey; + int wpa_deny_ptk0_rekey:1; int p2p; int wpa_rsc_relaxation; int owe_ptk_workaround; @@ -210,6 +211,12 @@ static inline int wpa_sm_set_key(struct wpa_sm *sm, enum wpa_alg alg, seq, seq_len, key, key_len, key_flag); } +static inline void wpa_sm_reconnect(struct wpa_sm *sm) +{ + WPA_ASSERT(sm->ctx->reconnect); + sm->ctx->reconnect(sm->ctx->ctx); +} + static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm) { WPA_ASSERT(sm->ctx->get_network_ctx); diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index d1002d225..bbd8f05fd 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -345,6 +345,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->isolate = !wpa_s->conf->p2p_intra_bss; bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; + bss->wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey; if (ssid->p2p_group) { os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4); diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 9dad4ff72..938165465 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2495,6 +2495,7 @@ static const struct parse_data ssid_fields[] = { { INT(dot11MeshHoldingTimeout) }, #endif /* CONFIG_MESH */ { INT(wpa_ptk_rekey) }, + { INT_RANGE(wpa_deny_ptk0_rekey, 0, 2) }, { INT(group_rekey) }, { STR(bgscan) }, { INT_RANGE(ignore_broadcast_ssid, 0, 2) }, @@ -3020,6 +3021,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->pairwise_cipher = DEFAULT_PAIRWISE; ssid->group_cipher = DEFAULT_GROUP; ssid->key_mgmt = DEFAULT_KEY_MGMT; + ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS; ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; ssid->ht = 1; #ifdef IEEE8021X_EAPOL diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 29bd81f0a..d453ca541 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -900,6 +900,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD); #endif /* CONFIG_MESH */ INT(wpa_ptk_rekey); + INT(wpa_deny_ptk0_rekey); INT(group_rekey); INT(ignore_broadcast_ssid); #ifdef CONFIG_DPP diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 5642d0ddf..ac08ad863 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -553,6 +553,19 @@ struct wpa_ssid { */ int wpa_ptk_rekey; + /** wpa_deny_ptk0_rekey - Control PTK0 rekeying + * + * Rekeying a pairwise key using only keyid 0 (PTK0 rekey) has many + * broken implementations and should be avoided when using or + * interacting with one. + * + * 0 = always rekey when configured/instructed + * 1 = only rekey when the local driver is explicitly indicating it can + * perform this operation without issues + * 2 = never allow PTK0 rekeys + */ + enum ptk0_rekey_handling wpa_deny_ptk0_rekey; + /** * group_rekey - Group rekeying time in seconds * diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index c9074a239..10c096129 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8108,6 +8108,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->no_keep_alive = 0; wpa_s->own_disconnect_req = 0; + wpa_s->own_reconnect_req = 0; + wpa_s->deny_ptk0_rekey = 0; os_free(wpa_s->disallow_aps_bssid); wpa_s->disallow_aps_bssid = NULL; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e3fce8f72..2851ffc81 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2895,6 +2895,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, #endif /* CONFIG_AP */ eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + wpa_s->own_reconnect_req = 0; ft_completed = wpa_ft_is_completed(wpa_s->wpa); if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0) @@ -3255,21 +3256,25 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s, if (wpa_s->wpa_state == WPA_COMPLETED && wpa_s->current_ssid && wpa_s->current_ssid->mode == WPAS_MODE_INFRA && - !locally_generated && - disconnect_reason_recoverable(reason_code)) { + (wpa_s->own_reconnect_req || + (!locally_generated && + disconnect_reason_recoverable(reason_code)))) { /* * It looks like the AP has dropped association with - * us, but could allow us to get back in. Try to - * reconnect to the same BSS without full scan to save - * time for some common cases. + * us, but could allow us to get back in. This is also + * triggered for cases where local reconnection request + * is used to force reassociation with the same BSS. + * Try to reconnect to the same BSS without a full scan + * to save time for some common cases. */ fast_reconnect = wpa_s->current_bss; fast_reconnect_ssid = wpa_s->current_ssid; - } else if (wpa_s->wpa_state >= WPA_ASSOCIATING) + } else if (wpa_s->wpa_state >= WPA_ASSOCIATING) { wpa_supplicant_req_scan(wpa_s, 0, 100000); - else + } else { wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new " "immediate scan"); + } } else { wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not " "try to re-connect"); diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index 37368c4cb..d14304011 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -206,6 +206,12 @@ static void supp_deauthenticate(void * ctx, u16 reason_code) } +static void supp_reconnect(void *ctx) +{ + wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__); +} + + static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, const u8 *psk) { @@ -225,6 +231,7 @@ static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, ctx->mlme_setprotection = supp_mlme_setprotection; ctx->cancel_auth_timeout = supp_cancel_auth_timeout; ctx->deauthenticate = supp_deauthenticate; + ctx->reconnect = supp_reconnect; peer->supp = wpa_sm_init(ctx); if (peer->supp == NULL) { wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c index a73282841..7ed5860f0 100644 --- a/wpa_supplicant/preauth_test.c +++ b/wpa_supplicant/preauth_test.c @@ -41,6 +41,12 @@ static void _wpa_supplicant_deauthenticate(void *wpa_s, u16 reason_code) } +static void _wpa_supplicant_reconnect(void *wpa_s) +{ + wpa_supplicant_reconnect(wpa_s); +} + + static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, const void *data, u16 data_len, size_t *msg_len, void **data_pos) @@ -245,6 +251,7 @@ static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *ifname) ctx->set_config_blob = wpa_supplicant_set_config_blob; ctx->get_config_blob = wpa_supplicant_get_config_blob; ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; + ctx->reconnect = _wpa_supplicant_reconnect; wpa_s->wpa = wpa_sm_init(ctx); assert(wpa_s->wpa != NULL); diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 6d3f56a87..490e77c96 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1441,6 +1441,7 @@ static const char *network_fields[] = { "dot11MeshHoldingTimeout", #endif /* CONFIG_MESH */ "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid", + "wpa_deny_ptk0_rekey", "enable_edmg", "edmg_channel", #ifdef CONFIG_P2P "go_p2p_dev_addr", "p2p_client_list", "psk_list", diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 7e06a22f6..634fb290e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1760,6 +1760,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } else wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); + if (ssid->mode != WPAS_MODE_IBSS && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) && + (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER || + (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) { + wpa_msg(wpa_s, MSG_INFO, + "Disable PTK0 rekey support - replaced with reconnect"); + wpa_s->deny_ptk0_rekey = 1; + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1); + } else { + wpa_s->deny_ptk0_rekey = 0; + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0); + } + return 0; } @@ -2057,6 +2071,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, int rand_style; wpa_s->own_disconnect_req = 0; + wpa_s->own_reconnect_req = 0; /* * If we are starting a new connection, any previously pending EAPOL @@ -3843,6 +3858,15 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, wpa_supplicant_clear_connection(wpa_s, addr); } + +void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s) +{ + wpa_s->own_reconnect_req = 1; + wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED); + +} + + static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { @@ -7081,7 +7105,7 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) * There is no point in blacklisting the AP if this event is * generated based on local request to disconnect. */ - if (wpa_s->own_disconnect_req) { + if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) { wpa_s->own_disconnect_req = 0; wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure due to local request to disconnect"); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index d587bd340..15121c386 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1101,6 +1101,32 @@ fast_reauth=1 # wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to # enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies. # +# wpa_deny_ptk0_rekey: Control PTK0 rekeying +# +# Rekeying the PTK without using "Extended Key ID for Individually Addressed +# Frames" (two different Key ID values for pairwise keys) can, depending on the +# used cards/drivers, impact the security and stability of connections. Both +# ends can accidentally trick one end to drop all packets send by it until the +# connection is torn down or rekeyed again. Additionally, some drivers may +# skip/break the encryption for the time window the key is updated (normally a +# few milliseconds). +# +# To avoid such issues, wpa_supplicant can now replace all PTK rekeys using only +# keyid 0 (PTK0 rekeys) with fast reconnects. +# +# EAP reauthentication depends on replacing the PTK and is therefore just +# another way to rekey the PTK and is affected by the parameter, too. +# +# "Extended Key ID for Individually Addressed Frames" is avoiding the issues +# using two separate keys and this parameter will be ignored when using it +# (i.e., PTK rekeying is allowed regardless of this parameter value). +# +# Available options: +# 0 = always rekey when configured/instructed (default) +# 1 = only rekey when the local driver is explicitly indicating it can perform +# this operation without issues +# 2 = never allow problematic PTK0 rekeys +# # group_rekey: Group rekeying time in seconds. This value, if non-zero, is used # as the dot11RSNAConfigGroupRekeyTime parameter when operating in # Authenticator role in IBSS, or in AP and mesh modes. diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 219568a7f..de2e6350b 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -554,6 +554,7 @@ struct wpa_supplicant { /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ int pairwise_cipher; + int deny_ptk0_rekey; int group_cipher; int key_mgmt; int wpa_proto; @@ -1071,6 +1072,7 @@ struct wpa_supplicant { unsigned int wmm_ac_supported:1; unsigned int ext_work_in_progress:1; unsigned int own_disconnect_req:1; + unsigned int own_reconnect_req:1; unsigned int ignore_post_flush_scan_res:1; #define MAC_ADDR_RAND_SCAN BIT(0) @@ -1325,6 +1327,7 @@ const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s); void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s); void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, u16 reason_code); +void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s); struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s); int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id); diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index e8747e613..5ddefce08 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -486,6 +486,12 @@ static void _wpa_supplicant_deauthenticate(void *wpa_s, u16 reason_code) } +static void _wpa_supplicant_reconnect(void *wpa_s) +{ + wpa_supplicant_reconnect(wpa_s); +} + + static void * wpa_supplicant_get_network_ctx(void *wpa_s) { return wpa_supplicant_get_ssid(wpa_s); @@ -1058,6 +1064,20 @@ static void wpa_supplicant_eap_error_cb(void *ctx, int error_code) } +static int wpa_supplicant_eap_auth_start_cb(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + + if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey) { + wpa_msg(wpa_s, MSG_INFO, + "WPA: PTK0 rekey not allowed, reconnecting"); + wpa_supplicant_reconnect(wpa_s); + return -1; + } + return 0; +} + + static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) { struct wpa_supplicant *wpa_s = ctx; @@ -1136,6 +1156,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) ctx->cert_in_cb = wpa_s->conf->cert_in_cb; ctx->status_cb = wpa_supplicant_status_cb; ctx->eap_error_cb = wpa_supplicant_eap_error_cb; + ctx->confirm_auth_cb = wpa_supplicant_eap_auth_start_cb; ctx->set_anon_id = wpa_supplicant_set_anon_id; ctx->cb_ctx = wpa_s; wpa_s->eapol = eapol_sm_init(ctx); @@ -1222,6 +1243,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) ctx->set_state = _wpa_supplicant_set_state; ctx->get_state = _wpa_supplicant_get_state; ctx->deauthenticate = _wpa_supplicant_deauthenticate; + ctx->reconnect = _wpa_supplicant_reconnect; ctx->set_key = wpa_supplicant_set_key; ctx->get_network_ctx = wpa_supplicant_get_network_ctx; ctx->get_bssid = wpa_supplicant_get_bssid; @@ -1286,6 +1308,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, conf.ssid = ssid->ssid; conf.ssid_len = ssid->ssid_len; conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; + conf.wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey; conf.owe_ptk_workaround = ssid->owe_ptk_workaround; #ifdef CONFIG_P2P if (ssid->p2p_group && wpa_s->current_bss && From 5742d12d4a02bda14f33c2ff9771d26b89832227 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Fri, 10 Jan 2020 23:19:10 +0100 Subject: [PATCH 0051/1105] tests: Allow PTK0 rekey for tests Verify PTK0 rekey blocking is working as intended. Signed-off-by: Alexander Wetzel --- tests/hwsim/hostapd.py | 2 +- tests/hwsim/test_ap_eap.py | 40 +++++++++++++++++++++++++++++++++++ tests/hwsim/test_ap_psk.py | 41 +++++++++++++++++++++++++++++++++++- tests/hwsim/wpasupplicant.py | 3 ++- 4 files changed, 83 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index fac287e99..7a52ebea3 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -551,7 +551,7 @@ def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30, raise Exception("Could not ping hostapd") hapd.set_defaults() fields = ["ssid", "wpa_passphrase", "nas_identifier", "wpa_key_mgmt", - "wpa", + "wpa", "wpa_deny_ptk0_rekey", "wpa_pairwise", "rsn_pairwise", "auth_server_addr", "acct_server_addr", "osu_server_uri"] for field in fields: diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 913132275..bdfe96111 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -5131,6 +5131,46 @@ def test_ap_wpa2_eap_reauth(dev, apdev): if state != "COMPLETED": raise Exception("Reauthentication did not complete") +def test_ap_wpa2_eap_reauth_ptk_rekey_blocked_ap(dev, apdev): + """WPA2-Enterprise and Authenticator forcing reauthentication with PTK rekey blocked on AP""" + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + params['eap_reauth_period'] = '2' + params['wpa_deny_ptk0_rekey'] = '2' + hapd = hostapd.add_ap(apdev[0], params) + eap_connect(dev[0], hapd, "PAX", "pax.user@example.com", + password_hex="0123456789abcdef0123456789abcdef") + logger.info("Wait for disconnect due to reauth") + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-DISCONNECTED"], timeout=10) + if ev is None: + raise Exception("Timeout on reauthentication") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Reauthentication without disconnect") + + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=1) + if ev is None: + raise Exception("Timeout on reconnect") + +def test_ap_wpa2_eap_reauth_ptk_rekey_blocked_sta(dev, apdev): + """WPA2-Enterprise and Authenticator forcing reauthentication with PTK rekey blocked on station""" + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + params['eap_reauth_period'] = '2' + hapd = hostapd.add_ap(apdev[0], params) + eap_connect(dev[0], hapd, "PAX", "pax.user@example.com", + password_hex="0123456789abcdef0123456789abcdef", + wpa_deny_ptk0_rekey="2") + logger.info("Wait for disconnect due to reauth") + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-DISCONNECTED"], timeout=10) + if ev is None: + raise Exception("Timeout on reauthentication") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Reauthentication without disconnect") + + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=1) + if ev is None: + raise Exception("Timeout on reconnect") + def test_ap_wpa2_eap_request_identity_message(dev, apdev): """Optional displayable message in EAP Request-Identity""" params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index ac0fabc5d..2f2a354a5 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -211,11 +211,50 @@ def test_ap_wpa2_ptk_rekey(dev, apdev): params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) hapd = hostapd.add_ap(apdev[0], params) dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412") - ev = dev[0].wait_event(["WPA: Key negotiation completed"]) + ev = dev[0].wait_event(["WPA: Key negotiation completed", + "CTRL-EVENT-DISCONNECTED"]) if ev is None: raise Exception("PTK rekey timed out") + if "CTRL-EVENT-DISCONNECTED" in ev: + raise Exception("Disconnect instead of rekey") hwsim_utils.test_connectivity(dev[0], hapd) +def test_ap_wpa2_ptk_rekey_blocked_ap(dev, apdev): + """WPA2-PSK AP and PTK rekey enforced by station and AP blocking it""" + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params['wpa_deny_ptk0_rekey'] = "2" + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412") + ev = dev[0].wait_event(["WPA: Key negotiation completed", + "CTRL-EVENT-DISCONNECTED"]) + if ev is None: + raise Exception("PTK rekey timed out") + if "WPA: Key negotiation completed" in ev: + raise Exception("No disconnect, PTK rekey succeeded") + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=1) + if ev is None: + raise Exception("Reconnect too slow") + +def test_ap_wpa2_ptk_rekey_blocked_sta(dev, apdev): + """WPA2-PSK AP and PTK rekey enforced by station while also blocking it""" + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412", + wpa_deny_ptk0_rekey="2") + ev = dev[0].wait_event(["WPA: Key negotiation completed", + "CTRL-EVENT-DISCONNECTED"]) + if ev is None: + raise Exception("PTK rekey timed out") + if "WPA: Key negotiation completed" in ev: + raise Exception("No disconnect, PTK rekey succeeded") + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=1) + if ev is None: + raise Exception("Reconnect too slow") + def test_ap_wpa2_ptk_rekey_anonce(dev, apdev): """WPA2-PSK AP and PTK rekey enforced by station and ANonce change""" ssid = "test-wpa2-psk" diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 0f3bb1866..d1c249328 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1104,7 +1104,8 @@ class WpaSupplicant: "owe_ptk_workaround", "roaming_consortium_selection", "ocv", "multi_ap_backhaul_sta", "rx_stbc", "tx_stbc", - "ft_eap_pmksa_caching", "beacon_prot"] + "ft_eap_pmksa_caching", "beacon_prot", + "wpa_deny_ptk0_rekey"] for field in not_quoted: if field in kwargs and kwargs[field]: self.set_network(id, field, kwargs[field]) From 293631f177b6477d7f2d1a595f7a2cd6facc1674 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Fri, 10 Jan 2020 23:19:10 +0100 Subject: [PATCH 0052/1105] IBSS RSN: Coding style cleanup Use consistent style for pointers. Signed-off-by: Alexander Wetzel --- wpa_supplicant/ibss_rsn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index d14304011..ea909a91c 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -200,7 +200,7 @@ static void supp_cancel_auth_timeout(void *ctx) } -static void supp_deauthenticate(void * ctx, u16 reason_code) +static void supp_deauthenticate(void *ctx, u16 reason_code) { wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__); } From ec5de19549474906ed830baa6adf6159b9ffc8c2 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:15 +0100 Subject: [PATCH 0053/1105] tests: remote: Switch to python3 Signed-off-by: Janusz Dziedzic --- tests/remote/run-tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py index 550071253..b93ea9b18 100755 --- a/tests/remote/run-tests.py +++ b/tests/remote/run-tests.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # # Remote test case executor # Copyright (c) 2016, Tieto Corporation From 0de85869a8e2a7d9b872d035d810d2bebbc366fc Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:16 +0100 Subject: [PATCH 0054/1105] tests: remote: Kill correct hostapd/wpa_supplicant process Kill hostapd and wpa_supplicant based on the configuration parameters. Previously, we could have killed wrong processes. Signed-off-by: Janusz Dziedzic --- tests/remote/config.py | 4 ++-- tests/remote/hwsim_wrapper.py | 8 ++++---- tests/remote/rutils.py | 6 ++++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/remote/config.py b/tests/remote/config.py index 55c601316..5a6b728ac 100644 --- a/tests/remote/config.py +++ b/tests/remote/config.py @@ -17,8 +17,8 @@ logger = logging.getLogger() # definitions in the format as below. In other case HWSIM cfg will be used. # setup_params = {"setup_hw" : "./tests/setup_hw.sh", - "hostapd" : "./tests/hostapd", - "wpa_supplicant" : "./tests/wpa_supplicant", + "hostapd" : "./tests/hostapd-rt", + "wpa_supplicant" : "./tests/wpa_supplicant-rt", "iperf" : "iperf", "wlantest" : "./tests/wlantest", "wlantest_cli" : "./tests/wlantest_cli", diff --git a/tests/remote/hwsim_wrapper.py b/tests/remote/hwsim_wrapper.py index c1bbb27d7..36df8d7a8 100644 --- a/tests/remote/hwsim_wrapper.py +++ b/tests/remote/hwsim_wrapper.py @@ -88,10 +88,10 @@ def run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test): monitor.remove(dut_host) for ref_host in ref_hosts: - ref_host.execute(["killall", "wpa_supplicant"]) + rutils.kill_wpasupplicant(ref_host, setup_params) ref_host.get_logs(local_log_dir) for dut_host in dut_hosts: - dut_host.execute(["killall", "hostapd"]) + rutils.kill_hostapd(dut_host, setup_params) dut_host.get_logs(local_log_dir) if mon is not None: wlantest.Wlantest.reset_remote_wlantest() @@ -113,10 +113,10 @@ def run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test): monitor.remove(dut_host) for ref_host in ref_hosts: - ref_host.execute(["killall", "wpa_supplicant"]) + rutils.kill_wpasupplicant(ref_host, setup_params) ref_host.get_logs(local_log_dir) for dut_host in dut_hosts: - dut_host.execute(["killall", "hostapd"]) + rutils.kill_hostapd(dut_host, setup_params) dut_host.get_logs(local_log_dir) if mon is not None: wlantest.Wlantest.reset_remote_wlantest() diff --git a/tests/remote/rutils.py b/tests/remote/rutils.py index e80d7dc0e..70ad82c87 100644 --- a/tests/remote/rutils.py +++ b/tests/remote/rutils.py @@ -138,6 +138,12 @@ def run_wpasupplicant(host, setup_params): if status != 0: raise Exception("Could not run wpa_supplicant: " + buf) +def kill_wpasupplicant(host, setup_params): + host.execute(['killall', setup_params['wpa_supplicant']]) + +def kill_hostapd(host, setup_params): + host.execute(['killall', setup_params['hostapd']]) + def get_ap_params(channel="1", bw="HT20", country="US", security="open", ht_capab=None, vht_capab=None): ssid = "test_" + channel + "_" + security + "_" + bw From 876785aeba4efa11470f9eedba77969877aafdf6 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:17 +0100 Subject: [PATCH 0055/1105] tests: remote: Show dev/apdev for hwsim In case the hwsim wrapper is used in remote tests, show also which device will be used as apdev - hostapd dev - wpa_supplicant Signed-off-by: Janusz Dziedzic --- tests/remote/run-tests.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py index b93ea9b18..b68610816 100755 --- a/tests/remote/run-tests.py +++ b/tests/remote/run-tests.py @@ -278,9 +278,15 @@ def main(): # now run test cases for dut in duts: - logger.warning("DUT: " + str(dut)) + if len(requested_hwsim_tests) > 0: + logger.warning("DUT (apdev): " + str(dut)) + else: + logger.warning("DUT: " + str(dut)) for ref in refs: - logger.warning("REF: " + str(ref)) + if len(requested_hwsim_tests) > 0: + logger.warning("REF (dev): " + str(ref)) + else: + logger.warning("REF: " + str(ref)) for monitor in monitors: logger.warning("MON: " + str(monitor)) From f8b26af7415c1c295aa9415861c7402c6da54e25 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:18 +0100 Subject: [PATCH 0056/1105] tests: remote: Allow hwsim test cases with more than two arguments This allows more test cases to be run in remote setup. Previously, we used to block all test cases that required more than two arguments (i.e., that needed the params argument). Signed-off-by: Janusz Dziedzic --- tests/remote/hwsim_wrapper.py | 6 ++++-- tests/remote/run-tests.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/remote/hwsim_wrapper.py b/tests/remote/hwsim_wrapper.py index 36df8d7a8..38f927f6e 100644 --- a/tests/remote/hwsim_wrapper.py +++ b/tests/remote/hwsim_wrapper.py @@ -67,13 +67,15 @@ def run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test): dut_host.dev['bssid'] = rutils.get_mac_addr(dut_host) apdev.append(dut_host.dev) - # run hwsim test/currently only 2 params tests if hwsim_test.__code__.co_argcount == 1: hwsim_test(dev) elif hwsim_test.__code__.co_argcount == 2: hwsim_test(dev, apdev) else: - raise Exception("more than 2 arguments required") + params = {} + params['long'] = 1 + params['logdir'] = local_log_dir + hwsim_test(dev, apdev, params) # hostapd/wpa_supplicant cleanup for wpas in dev: diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py index b68610816..8c5d02b44 100755 --- a/tests/remote/run-tests.py +++ b/tests/remote/run-tests.py @@ -200,7 +200,7 @@ def main(): t = None for tt in hwsim_tests: name = tt.__name__.replace('test_', '', 1) - if name == test and tt.__code__.co_argcount <= 2: + if name == test: t = tt break if not t: From 7a934fe72a61163448022026feb058484d5f290c Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:19 +0100 Subject: [PATCH 0057/1105] tests: remote: Handle different ifconfig output formats We could have different ifconfig output formats on the remote devices, so make the parser more flexible to handle such cases. Signed-off-by: Janusz Dziedzic --- tests/remote/rutils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/remote/rutils.py b/tests/remote/rutils.py index 70ad82c87..0acef42d1 100644 --- a/tests/remote/rutils.py +++ b/tests/remote/rutils.py @@ -239,6 +239,8 @@ def get_ipv6(client, ifname=None): for line in lines: res = line.find("Scope:Link") + if res == -1: + res = line.find("") if res != -1: break @@ -248,6 +250,8 @@ def get_ipv6(client, ifname=None): addr_mask = words[2] addr = addr_mask.split("/") return addr[0] + if words[0] == "inet6": + return words[1] return "unknown" @@ -281,7 +285,7 @@ def get_mac_addr(host, iface=None): for word in words: if found == 1: return word - if word == "HWaddr": + if word == "HWaddr" or word == "ether": found = 1 raise Exception("Could not find HWaddr") From 12fb9698ab7c640fce3f73ab2c5bf5ad5f886ddf Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:20 +0100 Subject: [PATCH 0058/1105] Use IFNAME= prefix for global UDP control interface events There does not seem to be a good reason for using the different IFACE= prefix on the UDP control interface. This got added when the UDP interface in wpa_supplicant was extended in commit f0e5d3b5c6c7 ("wpa_supplicant: Share attach/detach/send UDP ctrl_iface functions") and that was then extended to hostapd in commit e9208056856c ("hostapd: Extend global control interface notifications"). Replace the IFACE= prefix in UDP case with IFNAME= to be consistent with the UNIX domain socket based control interface. This fixes a problem when at least one test case fail (hapd_ctrl_sta) when remote/udp used. This also fixes test_connectivity(). Signed-off-by: Janusz Dziedzic --- hostapd/ctrl_iface.c | 5 ----- wpa_supplicant/ctrl_iface_udp.c | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index a1e4abd3c..18cbc76e5 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -4689,13 +4689,8 @@ static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst, return; idx = 0; if (ifname) { -#ifdef CONFIG_CTRL_IFACE_UDP - io[idx].iov_base = "IFACE="; - io[idx].iov_len = 6; -#else /* CONFIG_CTRL_IFACE_UDP */ io[idx].iov_base = "IFNAME="; io[idx].iov_len = 7; -#endif /* CONFIG_CTRL_IFACE_UDP */ idx++; io[idx].iov_base = (char *) ifname; io[idx].iov_len = os_strlen(ifname); diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c index 8a6057a82..1e92b9752 100644 --- a/wpa_supplicant/ctrl_iface_udp.c +++ b/wpa_supplicant/ctrl_iface_udp.c @@ -516,7 +516,7 @@ static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, return; if (ifname) - os_snprintf(levelstr, sizeof(levelstr), "IFACE=%s <%d>", + os_snprintf(levelstr, sizeof(levelstr), "IFNAME=%s <%d>", ifname, level); else os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); From 16f18b2ca74c75900b1d26a71486c1a0e5e5282e Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:21 +0100 Subject: [PATCH 0059/1105] tests: remotehost: Add send_file() Some hostapd test cases use configuration files, e.g., ACLs in BSS configuration. When executing remote tests (udp), we have to first send these configuration files to the appropriate remote device. The new send_file() helper can be used for that. Signed-off-by: Janusz Dziedzic --- tests/hwsim/hostapd.py | 10 ++++++++++ tests/hwsim/remotehost.py | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index 7a52ebea3..3e5e68fa2 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -135,6 +135,9 @@ class HostapdGlobal: self.ctrl.terminate() self.ctrl = None + def send_file(self, src, dst): + self.host.send_file(src, dst) + class Hostapd: def __init__(self, ifname, bssidx=0, hostname=None, port=8877): self.hostname = hostname @@ -524,6 +527,9 @@ class Hostapd: def note(self, txt): self.request("NOTE " + txt) + def send_file(self, src, dst): + self.host.send_file(src, dst) + def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30, global_ctrl_override=None, driver=False): if isinstance(apdev, dict): @@ -747,3 +753,7 @@ def ht40_minus_params(channel="1", ssid=None, country=None): def cmd_execute(apdev, cmd, shell=False): hapd_global = HostapdGlobal(apdev) return hapd_global.cmd_execute(cmd, shell=shell) + +def send_file(apdev, src, dst): + hapd_global = HostapdGlobal(apdev) + return hapd_global.send_file(src, dst) diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py index 50f46c310..8e121538a 100644 --- a/tests/hwsim/remotehost.py +++ b/tests/hwsim/remotehost.py @@ -106,3 +106,9 @@ class Host(): self.local_execute(["scp", self.user + "@[" + self.host + "]:" + log, local_log_dir]) self.execute(["rm", log]) del self.logs[:] + + def send_file(self, src, dst): + if self.host is None: + return + self.local_execute(["scp", src, + self.user + "@[" + self.host + "]:" + dst]) From 4d14838421eda7a54f3ab051f296af5be5f0f93a Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:22 +0100 Subject: [PATCH 0060/1105] tests: Generate ACL files Generate ACL files instead of using files with hardcoded values for the STA MAC addresses. Send the generated files also to the remote client if required. Signed-off-by: Janusz Dziedzic --- tests/hwsim/hostapd.accept | 2 -- tests/hwsim/hostapd.accept2 | 3 --- tests/hwsim/hostapd.macaddr | 7 ------ tests/hwsim/hostapd.py | 32 ++++++++++++++++++++++++ tests/hwsim/test_ap_ft.py | 46 +++++++++++++++++++++++++---------- tests/hwsim/test_ap_params.py | 12 ++++++--- tests/hwsim/test_ap_vlan.py | 32 ++++++++++++++++++------ tests/hwsim/test_hapd_ctrl.py | 12 ++++++--- 8 files changed, 107 insertions(+), 39 deletions(-) delete mode 100644 tests/hwsim/hostapd.accept delete mode 100644 tests/hwsim/hostapd.accept2 delete mode 100644 tests/hwsim/hostapd.macaddr diff --git a/tests/hwsim/hostapd.accept b/tests/hwsim/hostapd.accept deleted file mode 100644 index ce455b1a2..000000000 --- a/tests/hwsim/hostapd.accept +++ /dev/null @@ -1,2 +0,0 @@ -02:00:00:00:00:00 1 -02:00:00:00:01:00 2 diff --git a/tests/hwsim/hostapd.accept2 b/tests/hwsim/hostapd.accept2 deleted file mode 100644 index 3d41e348a..000000000 --- a/tests/hwsim/hostapd.accept2 +++ /dev/null @@ -1,3 +0,0 @@ -02:00:00:00:00:00 1 -02:00:00:00:01:00 2 -02:00:00:00:02:00 3 diff --git a/tests/hwsim/hostapd.macaddr b/tests/hwsim/hostapd.macaddr deleted file mode 100644 index a3b7878b5..000000000 --- a/tests/hwsim/hostapd.macaddr +++ /dev/null @@ -1,7 +0,0 @@ -02:00:00:00:00:00 -02:00:00:00:00:12 -02:00:00:00:00:34 --02:00:00:00:00:12 --02:00:00:00:00:34 -01:01:01:01:01:01 -03:01:01:01:01:03 diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index 3e5e68fa2..b96775fec 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -757,3 +757,35 @@ def cmd_execute(apdev, cmd, shell=False): def send_file(apdev, src, dst): hapd_global = HostapdGlobal(apdev) return hapd_global.send_file(src, dst) + +def acl_file(dev, apdev, conf): + filename = os.path.join("/tmp", conf) + + if conf == 'hostapd.macaddr': + with open(filename, 'w') as f: + mac0 = dev[0].get_status_field("address") + f.write(mac0 + '\n') + f.write("02:00:00:00:00:12\n") + f.write("02:00:00:00:00:34\n") + f.write("-02:00:00:00:00:12\n") + f.write("-02:00:00:00:00:34\n") + f.write("01:01:01:01:01:01\n") + f.write("03:01:01:01:01:03\n") + elif conf == 'hostapd.accept': + with open(filename, 'w') as f: + mac0 = dev[0].get_status_field("address") + mac1 = dev[1].get_status_field("address") + f.write(mac0 + " 1\n") + f.write(mac1 + " 2\n") + elif conf == 'hostapd.accept2': + with open(filename, 'w') as f: + mac0 = dev[0].get_status_field("address") + mac1 = dev[1].get_status_field("address") + mac2 = dev[2].get_status_field("address") + f.write(mac0 + " 1\n") + f.write(mac1 + " 2\n") + f.write(mac2 + " 3\n") + else: + return conf + + return filename diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 8efdc5e54..d5721f415 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -336,15 +336,18 @@ def test_ap_ft_vlan(dev, apdev): """WPA2-PSK-FT AP with VLAN""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1") @@ -355,16 +358,19 @@ def test_ap_ft_vlan_disconnected(dev, apdev): """WPA2-PSK-FT AP with VLAN and local key generation""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1a(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename params['ft_psk_generate_local'] = "1" hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2a(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename params['ft_psk_generate_local'] = "1" hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) @@ -376,10 +382,12 @@ def test_ap_ft_vlan_2(dev, apdev): """WPA2-PSK-FT AP with VLAN and dest-AP does not have VLAN info locally""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) @@ -407,15 +415,18 @@ def test_ap_ft_many_vlan(dev, apdev): """WPA2-PSK-FT AP with VLAN multiple times""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50, @@ -707,14 +718,17 @@ def test_ap_ft_vlan_over_ds(dev, apdev): """WPA2-PSK-FT AP over DS with VLAN""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, @@ -739,14 +753,17 @@ def test_ap_ft_vlan_over_ds_many(dev, apdev): """WPA2-PSK-FT AP over DS with VLAN multiple times""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, @@ -944,16 +961,19 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): """WPA2-PSK-FT AP over DS (pull PMK) with VLAN""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params["pmk_r1_push"] = "0" params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params["pmk_r1_push"] = "0" params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py index 8e4ab8e3b..84debc13f 100644 --- a/tests/hwsim/test_ap_params.py +++ b/tests/hwsim/test_ap_params.py @@ -140,8 +140,10 @@ def test_ap_acl_accept(dev, apdev): """MAC ACL accept list""" ssid = "acl" params = {} + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') + hostapd.send_file(apdev[0], filename, filename) params['ssid'] = ssid - params['accept_mac_file'] = "hostapd.macaddr" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") @@ -161,8 +163,10 @@ def test_ap_acl_deny(dev, apdev): """MAC ACL deny list""" ssid = "acl" params = {} + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') + hostapd.send_file(apdev[0], filename, filename) params['ssid'] = ssid - params['deny_mac_file'] = "hostapd.macaddr" + params['deny_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", passive=True) dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412", wait_connect=False) @@ -176,8 +180,10 @@ def test_ap_acl_mgmt(dev, apdev): """MAC ACL accept/deny management""" ssid = "acl" params = {} + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') + hostapd.send_file(apdev[0], filename, filename) params['ssid'] = ssid - params['deny_mac_file'] = "hostapd.macaddr" + params['deny_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) accept = hapd.request("ACCEPT_ACL SHOW").splitlines() diff --git a/tests/hwsim/test_ap_vlan.py b/tests/hwsim/test_ap_vlan.py index 305889aa1..7fe9107f4 100644 --- a/tests/hwsim/test_ap_vlan.py +++ b/tests/hwsim/test_ap_vlan.py @@ -26,9 +26,11 @@ from tshark import run_tshark def test_ap_vlan_open(dev, apdev): """AP VLAN with open network""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = {"ssid": "test-vlan-open", "dynamic_vlan": "1", - "accept_mac_file": "hostapd.accept"} + "accept_mac_file": filename} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") @@ -40,10 +42,12 @@ def test_ap_vlan_open(dev, apdev): def test_ap_vlan_file_open(dev, apdev): """AP VLAN with open network and vlan_file mapping""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = {"ssid": "test-vlan-open", "dynamic_vlan": "1", "vlan_file": "hostapd.vlan", - "accept_mac_file": "hostapd.accept"} + "accept_mac_file": filename} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") @@ -55,10 +59,12 @@ def test_ap_vlan_file_open(dev, apdev): def test_ap_vlan_file_open2(dev, apdev): """AP VLAN with open network and vlan_file mapping (2)""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept2') + hostapd.send_file(apdev[0], filename, filename) params = {"ssid": "test-vlan-open", "dynamic_vlan": "1", "vlan_file": "hostapd.vlan2", - "accept_mac_file": "hostapd.accept2"} + "accept_mac_file": filename} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") @@ -109,10 +115,12 @@ def test_ap_vlan_file_parsing(dev, apdev, params): def test_ap_vlan_wpa2(dev, apdev): """AP VLAN with WPA2-PSK""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = hostapd.wpa2_params(ssid="test-vlan", passphrase="12345678") params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan", psk="12345678", scan_freq="2412") @@ -166,11 +174,13 @@ def test_ap_vlan_wpa2_radius_2(dev, apdev): def test_ap_vlan_wpa2_radius_local(dev, apdev): """AP VLAN with WPA2-Enterprise and local file setting VLAN IDs""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = hostapd.wpa2_eap_params(ssid="test-vlan") params['dynamic_vlan'] = "0" params['vlan_file'] = "hostapd.vlan" params['vlan_bridge'] = "test_br_vlan" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", @@ -340,10 +350,12 @@ def test_ap_vlan_wpa2_radius_required(dev, apdev): def test_ap_vlan_tagged(dev, apdev): """AP VLAN with tagged interface""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = {"ssid": "test-vlan-open", "dynamic_vlan": "1", "vlan_tagged_interface": "lo", - "accept_mac_file": "hostapd.accept"} + "accept_mac_file": filename} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") @@ -546,6 +558,8 @@ def test_ap_vlan_iface_cleanup_multibss_per_sta_vif(dev, apdev): def test_ap_vlan_without_station(dev, apdev, p): """AP VLAN with WPA2-PSK and no station""" try: + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) subprocess.call(['brctl', 'addbr', 'brvlan1']) subprocess.call(['brctl', 'setfd', 'brvlan1', '0']) subprocess.call(['ifconfig', 'brvlan1', 'up']) @@ -555,7 +569,7 @@ def test_ap_vlan_without_station(dev, apdev, p): passphrase="12345678x") params['dynamic_vlan'] = "1" params['vlan_file'] = 'hostapd.wlan3.vlan' - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) # inject some traffic @@ -707,10 +721,12 @@ def test_ap_vlan_wpa2_radius_mixed(dev, apdev): def test_ap_vlan_reconnect(dev, apdev): """AP VLAN with WPA2-PSK connect, disconnect, connect""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = hostapd.wpa2_params(ssid="test-vlan", passphrase="12345678") params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) logger.info("connect sta") diff --git a/tests/hwsim/test_hapd_ctrl.py b/tests/hwsim/test_hapd_ctrl.py index 5b802e478..c61f4ef3d 100644 --- a/tests/hwsim/test_hapd_ctrl.py +++ b/tests/hwsim/test_hapd_ctrl.py @@ -283,11 +283,13 @@ def test_hapd_ctrl_ess_disassoc(dev, apdev): def test_hapd_ctrl_set_deny_mac_file(dev, apdev): """hostapd and SET deny_mac_file ctrl_iface command""" ssid = "hapd-ctrl" + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') params = {"ssid": ssid} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412") - if "OK" not in hapd.request("SET deny_mac_file hostapd.macaddr"): + hapd.send_file(filename, filename) + if "OK" not in hapd.request("SET deny_mac_file " + filename): raise Exception("Unexpected SET failure") dev[0].wait_disconnected(timeout=15) ev = dev[1].wait_event(["CTRL-EVENT-DISCONNECTED"], 1) @@ -297,12 +299,14 @@ def test_hapd_ctrl_set_deny_mac_file(dev, apdev): def test_hapd_ctrl_set_accept_mac_file(dev, apdev): """hostapd and SET accept_mac_file ctrl_iface command""" ssid = "hapd-ctrl" + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') params = {"ssid": ssid} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412") + hapd.send_file(filename, filename) hapd.request("SET macaddr_acl 1") - if "OK" not in hapd.request("SET accept_mac_file hostapd.macaddr"): + if "OK" not in hapd.request("SET accept_mac_file " + filename): raise Exception("Unexpected SET failure") dev[1].wait_disconnected(timeout=15) ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], 1) @@ -312,12 +316,14 @@ def test_hapd_ctrl_set_accept_mac_file(dev, apdev): def test_hapd_ctrl_set_accept_mac_file_vlan(dev, apdev): """hostapd and SET accept_mac_file ctrl_iface command (VLAN ID)""" ssid = "hapd-ctrl" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') params = {"ssid": ssid} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412") + hapd.send_file(filename, filename) hapd.request("SET macaddr_acl 1") - if "OK" not in hapd.request("SET accept_mac_file hostapd.accept"): + if "OK" not in hapd.request("SET accept_mac_file " + filename): raise Exception("Unexpected SET failure") dev[1].wait_disconnected(timeout=15) dev[0].wait_disconnected(timeout=15) From 4b04223f249ee44b563a051dd8af98011aaaf9fa Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:23 +0100 Subject: [PATCH 0061/1105] hostapd: Replace UDP ctrl_iface global cookies with per-instance ones The cookie values for UDP control interface commands was defined as a static global array. This did not allow multi-BSS test cases to be executed with UDP control interface. For example, after hapd1 = hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') hapd2 = hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') hapd1->ping() did not work. Move those cookie values to per-instance location in struct hapd_interfaces and struct hostapd_data to fix this. Signed-off-by: Janusz Dziedzic --- hostapd/ctrl_iface.c | 41 +++++++++++++++++++++-------------------- src/ap/hostapd.h | 13 +++++++++++++ 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 18cbc76e5..f380926b3 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -69,9 +69,6 @@ #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256 #ifdef CONFIG_CTRL_IFACE_UDP -#define COOKIE_LEN 8 -static unsigned char cookie[COOKIE_LEN]; -static unsigned char gcookie[COOKIE_LEN]; #define HOSTAPD_CTRL_IFACE_PORT 8877 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878 @@ -3529,7 +3526,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, int reply_len; int level = MSG_DEBUG; #ifdef CONFIG_CTRL_IFACE_UDP - unsigned char lcookie[COOKIE_LEN]; + unsigned char lcookie[CTRL_IFACE_COOKIE_LEN]; #endif /* CONFIG_CTRL_IFACE_UDP */ res = recvfrom(sock, buf, sizeof(buf) - 1, 0, @@ -3554,28 +3551,30 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, #ifdef CONFIG_CTRL_IFACE_UDP if (os_strcmp(buf, "GET_COOKIE") == 0) { os_memcpy(reply, "COOKIE=", 7); - wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, - cookie, COOKIE_LEN); - reply_len = 7 + 2 * COOKIE_LEN; + wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1, + hapd->ctrl_iface_cookie, + CTRL_IFACE_COOKIE_LEN); + reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN; goto done; } if (os_strncmp(buf, "COOKIE=", 7) != 0 || - hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) { + hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTRL: No cookie in the request - drop request"); os_free(reply); return; } - if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) { + if (os_memcmp(hapd->ctrl_iface_cookie, lcookie, + CTRL_IFACE_COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTRL: Invalid cookie in the request - drop request"); os_free(reply); return; } - pos = buf + 7 + 2 * COOKIE_LEN; + pos = buf + 7 + 2 * CTRL_IFACE_COOKIE_LEN; while (*pos == ' ') pos++; #endif /* CONFIG_CTRL_IFACE_UDP */ @@ -3664,7 +3663,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd) dl_list_init(&hapd->ctrl_dst); hapd->ctrl_sock = -1; - os_get_random(cookie, COOKIE_LEN); + os_get_random(hapd->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN); #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE hints.ai_flags = AI_PASSIVE; @@ -4243,7 +4242,7 @@ static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces, static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, void *sock_ctx) { - void *interfaces = eloop_ctx; + struct hapd_interfaces *interfaces = eloop_ctx; char buffer[256], *buf = buffer; int res; struct sockaddr_storage from; @@ -4252,7 +4251,7 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, int reply_len; const int reply_size = 4096; #ifdef CONFIG_CTRL_IFACE_UDP - unsigned char lcookie[COOKIE_LEN]; + unsigned char lcookie[CTRL_IFACE_COOKIE_LEN]; #endif /* CONFIG_CTRL_IFACE_UDP */ res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, @@ -4281,28 +4280,30 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, #ifdef CONFIG_CTRL_IFACE_UDP if (os_strcmp(buf, "GET_COOKIE") == 0) { os_memcpy(reply, "COOKIE=", 7); - wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, - gcookie, COOKIE_LEN); - reply_len = 7 + 2 * COOKIE_LEN; + wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1, + interfaces->ctrl_iface_cookie, + CTRL_IFACE_COOKIE_LEN); + reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN; goto send_reply; } if (os_strncmp(buf, "COOKIE=", 7) != 0 || - hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) { + hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTRL: No cookie in the request - drop request"); os_free(reply); return; } - if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) { + if (os_memcmp(interfaces->ctrl_iface_cookie, lcookie, + CTRL_IFACE_COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTRL: Invalid cookie in the request - drop request"); os_free(reply); return; } - buf += 7 + 2 * COOKIE_LEN; + buf += 7 + 2 * CTRL_IFACE_COOKIE_LEN; while (*buf == ' ') buf++; #endif /* CONFIG_CTRL_IFACE_UDP */ @@ -4446,7 +4447,7 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) } } - os_get_random(gcookie, COOKIE_LEN); + os_get_random(interface->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN); #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE hints.ai_flags = AI_PASSIVE; diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 7605041d1..ec5b9d57f 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -38,6 +38,10 @@ union wps_event_data; struct mesh_conf; #endif /* CONFIG_MESH */ +#ifdef CONFIG_CTRL_IFACE_UDP +#define CTRL_IFACE_COOKIE_LEN 8 +#endif /* CONFIG_CTRL_IFACE_UDP */ + struct hostapd_iface; struct hapd_interfaces { @@ -72,6 +76,11 @@ struct hapd_interfaces { #ifdef CONFIG_DPP struct dpp_global *dpp; #endif /* CONFIG_DPP */ + +#ifdef CONFIG_CTRL_IFACE_UDP + unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; +#endif /* CONFIG_CTRL_IFACE_UDP */ + }; enum hostapd_chan_status { @@ -395,6 +404,10 @@ struct hostapd_data { #ifdef CONFIG_SQLITE sqlite3 *rad_attr_db; #endif /* CONFIG_SQLITE */ + +#ifdef CONFIG_CTRL_IFACE_UDP + unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; +#endif /* CONFIG_CTRL_IFACE_UDP */ }; From ba1ff57ad21edf859290eab4799c1965cdc536de Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:24 +0100 Subject: [PATCH 0062/1105] tests: remote: Generate and send BSS configuration files Instead of hardcoded bss-[1-6]*.conf files, generate them using the correct BSSID for each AP device and send/install them on the remote client as well if needed. Signed-off-by: Janusz Dziedzic --- tests/hwsim/hostapd.py | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index b96775fec..04e460c1d 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -5,6 +5,7 @@ # See README for more details. import os +import re import time import logging import binascii @@ -593,6 +594,8 @@ def add_bss(apdev, ifname, confname, ignore_error=False): hostname = None port = 8878 hapd_global = HostapdGlobal(apdev) + confname = cfg_file(apdev, confname, ifname) + hapd_global.send_file(confname, confname) hapd_global.add_bss(phy, confname, ignore_error) port = hapd_global.get_ctrl_iface_port(ifname) hapd = Hostapd(ifname, hostname=hostname, port=port) @@ -611,6 +614,8 @@ def add_iface(apdev, confname): hostname = None port = 8878 hapd_global = HostapdGlobal(apdev) + confname = cfg_file(apdev, confname, ifname) + hapd_global.send_file(confname, confname) hapd_global.add_iface(ifname, confname) port = hapd_global.get_ctrl_iface_port(ifname) hapd = Hostapd(ifname, hostname=hostname, port=port) @@ -789,3 +794,41 @@ def acl_file(dev, apdev, conf): return conf return filename + +def bssid_inc(apdev, inc=1): + parts = apdev['bssid'].split(':') + parts[5] = '%02x' % (int(parts[5], 16) + int(inc)) + bssid = '%s:%s:%s:%s:%s:%s' % (parts[0], parts[1], parts[2], + parts[3], parts[4], parts[5]) + return bssid + +def cfg_file(apdev, conf, ifname=None): + # put cfg file in /tmp directory + fname = os.path.join("/tmp", conf) + + match = re.search(r'^bss-\d+', conf) + if match: + with open(fname, 'w') as f: + idx = ''.join(filter(str.isdigit, conf)) + if ifname is None: + ifname = apdev['ifname'] + if idx != '1': + ifname = ifname + '-' + idx + + f.write("driver=nl80211\n") + f.write("ctrl_interface=/var/run/hostapd\n") + f.write("hw_mode=g\n") + f.write("channel=1\n") + f.write("ieee80211n=1\n") + f.write("interface=%s\n" % ifname) + + f.write("ssid=bss-%s\n" % idx) + if conf == 'bss-2-dup.conf': + bssid = apdev['bssid'] + else: + bssid = bssid_inc(apdev, int(idx) - 1) + f.write("bssid=%s\n" % bssid) + else: + return conf + + return fname From e206c93f31ef089c5b8307bbb8753bfb8b952708 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:25 +0100 Subject: [PATCH 0063/1105] tests: Fix multi_check() for remote testing Don't use hardcoded BSSID; instead use the real BSSID from the device. Signed-off-by: Janusz Dziedzic --- tests/hwsim/test_ap_dynamic.py | 62 +++++++++++++++++----------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index 7a2ddcc7d..9a70776cc 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -37,7 +37,7 @@ def test_ap_change_ssid(dev, apdev): dev[0].set_network_quoted(id, "ssid", "test-wpa2-psk-new") dev[0].connect_network(id) -def multi_check(dev, check, scan_opt=True): +def multi_check(apdev, dev, check, scan_opt=True): id = [] num_bss = len(check) for i in range(0, num_bss): @@ -51,7 +51,7 @@ def multi_check(dev, check, scan_opt=True): for i in range(num_bss): if not check[i]: continue - bssid = '02:00:00:00:03:0' + str(i) + bssid = hostapd.bssid_inc(apdev, i) if scan_opt: dev[i].scan_for_bss(bssid, freq=2412) id.append(dev[i].connect("bss-" + str(i + 1), key_mgmt="NONE", @@ -98,59 +98,59 @@ def _test_ap_bss_add_remove(dev, apdev): ifname3 = apdev[0]['ifname'] + '-3' logger.info("Set up three BSSes one by one") hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove the last BSS and re-add it") hostapd.remove_bss(apdev[0], ifname3) - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove the middle BSS and re-add it") hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False, True]) + multi_check(apdev[0], dev, [True, False, True]) hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove the first BSS and re-add it and other BSSs") hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False, False]) + multi_check(apdev[0], dev, [False, False, False]) hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove two BSSes and re-add them") hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False, True]) + multi_check(apdev[0], dev, [True, False, True]) hostapd.remove_bss(apdev[0], ifname3) - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove three BSSes in and re-add them") hostapd.remove_bss(apdev[0], ifname3) - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False, False]) + multi_check(apdev[0], dev, [False, False, False]) hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Test error handling if a duplicate ifname is tried") hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf', ignore_error=True) - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) def test_ap_bss_add_remove_during_ht_scan(dev, apdev): """Dynamic BSS add during HT40 co-ex scan""" @@ -160,20 +160,20 @@ def test_ap_bss_add_remove_during_ht_scan(dev, apdev): ifname2 = apdev[0]['ifname'] + '-2' hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') - multi_check(dev, [True, True], scan_opt=False) + multi_check(apdev[0], dev, [True, True], scan_opt=False) hostapd.remove_bss(apdev[0], ifname2) hostapd.remove_bss(apdev[0], ifname1) hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False], scan_opt=False) + multi_check(apdev[0], dev, [True, False], scan_opt=False) hostapd.remove_bss(apdev[0], ifname1) hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False]) + multi_check(apdev[0], dev, [False, False]) def test_ap_multi_bss_config(dev, apdev): """hostapd start with a multi-BSS configuration file""" @@ -185,18 +185,18 @@ def test_ap_multi_bss_config(dev, apdev): logger.info("Set up three BSSes with one configuration file") hapd = hostapd.add_iface(apdev[0], 'multi-bss.conf') hapd.enable() - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False, True]) + multi_check(apdev[0], dev, [True, False, True]) hostapd.remove_bss(apdev[0], ifname3) - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False, False]) + multi_check(apdev[0], dev, [False, False, False]) hapd = hostapd.add_iface(apdev[0], 'multi-bss.conf') hapd.enable() hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False, False]) + multi_check(apdev[0], dev, [False, False, False]) def invalid_ap(ap): logger.info("Trying to start AP " + ap['ifname'] + " with invalid configuration") @@ -507,7 +507,7 @@ def test_ap_bss_config_file(dev, apdev, params): res = subprocess.check_call(cmd) if res != 0: raise Exception("Could not start hostapd: %s" % str(res)) - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) for i in range(0, 3): dev[i].request("DISCONNECT") From bdff1be152f039f5833586191498f2f10bffeda0 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 12 Jan 2020 23:02:26 +0100 Subject: [PATCH 0064/1105] tests: Extend wpas_ctrl_bssid_filter for remote testing When this test case is ran in remote test environment, there could be additional APs in scan results after bssid_filter has been disabled. That breaks the check on SCAN_RESULTS output. Extend this to cover the remote testing case by using bssid_filter with both known APs listed instead of full wildcard. Signed-off-by: Janusz Dziedzic --- tests/hwsim/test_wpas_ctrl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py index bac373f2f..91f440191 100644 --- a/tests/hwsim/test_wpas_ctrl.py +++ b/tests/hwsim/test_wpas_ctrl.py @@ -802,6 +802,7 @@ def test_wpas_ctrl_level(dev): finally: dev[2].mon.request("LEVEL 3") +@remote_compatible def test_wpas_ctrl_bssid_filter(dev, apdev): """wpa_supplicant bssid_filter""" try: @@ -818,7 +819,8 @@ def test_wpas_ctrl_bssid_filter(dev, apdev): bss = dev[2].get_bss(apdev[1]['bssid']) if bss and len(bss) != 0: raise Exception("Unexpected BSS data") - dev[2].request("SET bssid_filter ") + dev[2].request("SET bssid_filter " + apdev[0]['bssid'] + " " + \ + apdev[1]['bssid']) dev[2].scan(freq="2412") bss = dev[2].get_bss(apdev[0]['bssid']) if bss is None or len(bss) == 0: From 387d96f7c5604f6a52ff2791e199ca55dffdeff5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 23 Feb 2020 15:19:59 +0200 Subject: [PATCH 0065/1105] tests: remove: Fix a typo in a comment Signed-off-by: Jouni Malinen --- tests/remote/run-tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py index 8c5d02b44..e1ff98977 100755 --- a/tests/remote/run-tests.py +++ b/tests/remote/run-tests.py @@ -290,7 +290,7 @@ def main(): for monitor in monitors: logger.warning("MON: " + str(monitor)) - # run check_devices at begining + # run check_devices at beginning logger.warning("RUN check_devices") try: check_devices(devices, setup_params, refs, duts, monitors) From 791acc676ce3551e4f9d8652d9e4bc31fa11129e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 23 Feb 2020 16:58:43 +0200 Subject: [PATCH 0066/1105] tests: Generate BSS configuration files in ap_bss_config_file Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_dynamic.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index 9a70776cc..a0f9ac603 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -501,9 +501,13 @@ def test_ap_bss_config_file(dev, apdev, params): if not os.path.exists(prg): prg = '../../hostapd/hostapd' phy = get_phy(apdev[0]) + confname1 = hostapd.cfg_file(apdev[0], "bss-1.conf") + confname2 = hostapd.cfg_file(apdev[0], "bss-2.conf") + confname3 = hostapd.cfg_file(apdev[0], "bss-3.conf") + cmd = [prg, '-B', '-dddt', '-P', pidfile, '-f', logfile, '-S', '-T', - '-b', phy + ':bss-1.conf', '-b', phy + ':bss-2.conf', - '-b', phy + ':bss-3.conf'] + '-b', phy + ':' + confname1, '-b', phy + ':' + confname2, + '-b', phy + ':' + confname3] res = subprocess.check_call(cmd) if res != 0: raise Exception("Could not start hostapd: %s" % str(res)) From a066644fcb0d533e8f8aea174d8f9dcf845c73e7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 23 Feb 2020 17:05:43 +0200 Subject: [PATCH 0067/1105] tests: Generate BSS configuration files in ap_bss_add_out_of_memory Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_dynamic.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index a0f9ac603..9a7d2f4af 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -404,21 +404,23 @@ def test_ap_bss_add_out_of_memory(dev, apdev): ifname1 = apdev[0]['ifname'] ifname2 = apdev[0]['ifname'] + '-2' - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-1.conf', 1, 'hostapd_add_iface') + confname1 = hostapd.cfg_file(apdev[0], "bss-1.conf") + confname2 = hostapd.cfg_file(apdev[0], "bss-2.conf") + hapd_bss_out_of_mem(hapd2, 'phy3', confname1, 1, 'hostapd_add_iface') for i in range(1, 3): - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-1.conf', + hapd_bss_out_of_mem(hapd2, 'phy3', confname1, i, 'hostapd_interface_init_bss') - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-1.conf', + hapd_bss_out_of_mem(hapd2, 'phy3', confname1, 1, 'ieee802_11_build_ap_params') - hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') + hostapd.add_bss(apdev[0], ifname1, confname1) - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-2.conf', + hapd_bss_out_of_mem(hapd2, 'phy3', confname2, 1, 'hostapd_interface_init_bss') - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-2.conf', + hapd_bss_out_of_mem(hapd2, 'phy3', confname2, 1, 'ieee802_11_build_ap_params') - hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') + hostapd.add_bss(apdev[0], ifname2, confname2) hostapd.remove_bss(apdev[0], ifname2) hostapd.remove_bss(apdev[0], ifname1) From 92f08a3ccd64780bb1781574d6f07937a770a4ba Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 23 Feb 2020 17:13:04 +0200 Subject: [PATCH 0068/1105] tests: Generate BSS config files in ap_bss_add_remove_during_ht_scan Signed-off-by: Jouni Malinen --- tests/hwsim/hostapd.py | 6 ++++-- tests/hwsim/test_ap_dynamic.py | 17 +++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index 04e460c1d..d179fd045 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -806,10 +806,10 @@ def cfg_file(apdev, conf, ifname=None): # put cfg file in /tmp directory fname = os.path.join("/tmp", conf) - match = re.search(r'^bss-\d+', conf) + match = re.search(r'^bss-.+', conf) if match: with open(fname, 'w') as f: - idx = ''.join(filter(str.isdigit, conf)) + idx = ''.join(filter(str.isdigit, conf.split('-')[-1])) if ifname is None: ifname = apdev['ifname'] if idx != '1': @@ -820,6 +820,8 @@ def cfg_file(apdev, conf, ifname=None): f.write("hw_mode=g\n") f.write("channel=1\n") f.write("ieee80211n=1\n") + if conf.startswith('bss-ht40-'): + f.write("ht_capab=[HT40+]\n") f.write("interface=%s\n" % ifname) f.write("ssid=bss-%s\n" % idx) diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index 9a7d2f4af..aab59f4ef 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -158,20 +158,25 @@ def test_ap_bss_add_remove_during_ht_scan(dev, apdev): dev[i].flush_scan_cache() ifname1 = apdev[0]['ifname'] ifname2 = apdev[0]['ifname'] + '-2' - hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') - hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') + confname1 = hostapd.cfg_file(apdev[0], "bss-ht40-1.conf") + confname2 = hostapd.cfg_file(apdev[0], "bss-ht40-2.conf") + hapd_global = hostapd.HostapdGlobal(apdev) + hapd_global.send_file(confname1, confname1) + hapd_global.send_file(confname2, confname2) + hostapd.add_bss(apdev[0], ifname1, confname1) + hostapd.add_bss(apdev[0], ifname2, confname2) multi_check(apdev[0], dev, [True, True], scan_opt=False) hostapd.remove_bss(apdev[0], ifname2) hostapd.remove_bss(apdev[0], ifname1) - hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') - hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') + hostapd.add_bss(apdev[0], ifname1, confname1) + hostapd.add_bss(apdev[0], ifname2, confname2) hostapd.remove_bss(apdev[0], ifname2) multi_check(apdev[0], dev, [True, False], scan_opt=False) hostapd.remove_bss(apdev[0], ifname1) - hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') - hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') + hostapd.add_bss(apdev[0], ifname1, confname1) + hostapd.add_bss(apdev[0], ifname2, confname2) hostapd.remove_bss(apdev[0], ifname1) multi_check(apdev[0], dev, [False, False]) From 6998ef48c803bef309bc93fa01566d4137cfd13a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 23 Feb 2020 17:00:25 +0200 Subject: [PATCH 0069/1105] tests: Remove unused BSS configuration files These are now generated dynamically. Signed-off-by: Jouni Malinen --- tests/hwsim/bss-1.conf | 11 ----------- tests/hwsim/bss-2-dup.conf | 11 ----------- tests/hwsim/bss-2.conf | 11 ----------- tests/hwsim/bss-3.conf | 11 ----------- tests/hwsim/bss-4.conf | 11 ----------- tests/hwsim/bss-5.conf | 11 ----------- tests/hwsim/bss-6.conf | 11 ----------- tests/hwsim/bss-ht40-1.conf | 12 ------------ tests/hwsim/bss-ht40-2.conf | 12 ------------ 9 files changed, 101 deletions(-) delete mode 100644 tests/hwsim/bss-1.conf delete mode 100644 tests/hwsim/bss-2-dup.conf delete mode 100644 tests/hwsim/bss-2.conf delete mode 100644 tests/hwsim/bss-3.conf delete mode 100644 tests/hwsim/bss-4.conf delete mode 100644 tests/hwsim/bss-5.conf delete mode 100644 tests/hwsim/bss-6.conf delete mode 100644 tests/hwsim/bss-ht40-1.conf delete mode 100644 tests/hwsim/bss-ht40-2.conf diff --git a/tests/hwsim/bss-1.conf b/tests/hwsim/bss-1.conf deleted file mode 100644 index b465dcbbd..000000000 --- a/tests/hwsim/bss-1.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3 -bssid=02:00:00:00:03:00 -ctrl_interface=/var/run/hostapd - -ssid=bss-1 diff --git a/tests/hwsim/bss-2-dup.conf b/tests/hwsim/bss-2-dup.conf deleted file mode 100644 index 9f63c9ddc..000000000 --- a/tests/hwsim/bss-2-dup.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-2 -bssid=02:00:00:00:03:00 -ctrl_interface=/var/run/hostapd - -ssid=bss-2 diff --git a/tests/hwsim/bss-2.conf b/tests/hwsim/bss-2.conf deleted file mode 100644 index 7a8c64c15..000000000 --- a/tests/hwsim/bss-2.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-2 -bssid=02:00:00:00:03:01 -ctrl_interface=/var/run/hostapd - -ssid=bss-2 diff --git a/tests/hwsim/bss-3.conf b/tests/hwsim/bss-3.conf deleted file mode 100644 index fe671def4..000000000 --- a/tests/hwsim/bss-3.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-3 -bssid=02:00:00:00:03:02 -ctrl_interface=/var/run/hostapd - -ssid=bss-3 diff --git a/tests/hwsim/bss-4.conf b/tests/hwsim/bss-4.conf deleted file mode 100644 index 4028794cc..000000000 --- a/tests/hwsim/bss-4.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-4 -bssid=02:00:00:00:03:03 -ctrl_interface=/var/run/hostapd - -ssid=bss-4 diff --git a/tests/hwsim/bss-5.conf b/tests/hwsim/bss-5.conf deleted file mode 100644 index 8b8836812..000000000 --- a/tests/hwsim/bss-5.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-5 -bssid=02:00:00:00:03:04 -ctrl_interface=/var/run/hostapd - -ssid=bss-5 diff --git a/tests/hwsim/bss-6.conf b/tests/hwsim/bss-6.conf deleted file mode 100644 index 66a0d0c5e..000000000 --- a/tests/hwsim/bss-6.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-6 -bssid=02:00:00:00:03:05 -ctrl_interface=/var/run/hostapd - -ssid=bss-6 diff --git a/tests/hwsim/bss-ht40-1.conf b/tests/hwsim/bss-ht40-1.conf deleted file mode 100644 index a338c6b66..000000000 --- a/tests/hwsim/bss-ht40-1.conf +++ /dev/null @@ -1,12 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 -ht_capab=[HT40+] - -interface=wlan3 -bssid=02:00:00:00:03:00 -ctrl_interface=/var/run/hostapd - -ssid=bss-1 diff --git a/tests/hwsim/bss-ht40-2.conf b/tests/hwsim/bss-ht40-2.conf deleted file mode 100644 index c7e27ce3d..000000000 --- a/tests/hwsim/bss-ht40-2.conf +++ /dev/null @@ -1,12 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 -ht_capab=[HT40+] - -interface=wlan3-2 -bssid=02:00:00:00:03:01 -ctrl_interface=/var/run/hostapd - -ssid=bss-2 From af9d8c758d9e8a5dab83e11822263fbd4c54eadd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 23 Feb 2020 17:38:23 +0200 Subject: [PATCH 0070/1105] tests: Use proper temp files for dynamically created config Replace the hardcoded /tmp filenames for generated ACL and BSS configuration files with proper temporary files from tempfile.mkstemp() to avoid conflicts with existing files or with parallel uses. Remove ACL files from the local directory at the end of each test case. BSS files are currently left behind, but can be cleaned up separately if needed for non-VM testing (VM testing has those on ramdrive so they get dropped automatically at the end) and for remote devices. Signed-off-by: Jouni Malinen --- tests/hwsim/hostapd.py | 96 +++++++++++++++++------------------ tests/hwsim/test_ap_ft.py | 14 +++++ tests/hwsim/test_ap_params.py | 6 +++ tests/hwsim/test_ap_vlan.py | 16 ++++++ tests/hwsim/test_hapd_ctrl.py | 7 +++ 5 files changed, 91 insertions(+), 48 deletions(-) diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index d179fd045..62b3302be 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -10,6 +10,7 @@ import time import logging import binascii import struct +import tempfile import wpaspy import remotehost import utils @@ -764,33 +765,33 @@ def send_file(apdev, src, dst): return hapd_global.send_file(src, dst) def acl_file(dev, apdev, conf): - filename = os.path.join("/tmp", conf) + fd, filename = tempfile.mkstemp(dir='/tmp', prefix=conf + '-') + f = os.fdopen(fd, 'w') if conf == 'hostapd.macaddr': - with open(filename, 'w') as f: - mac0 = dev[0].get_status_field("address") - f.write(mac0 + '\n') - f.write("02:00:00:00:00:12\n") - f.write("02:00:00:00:00:34\n") - f.write("-02:00:00:00:00:12\n") - f.write("-02:00:00:00:00:34\n") - f.write("01:01:01:01:01:01\n") - f.write("03:01:01:01:01:03\n") + mac0 = dev[0].get_status_field("address") + f.write(mac0 + '\n') + f.write("02:00:00:00:00:12\n") + f.write("02:00:00:00:00:34\n") + f.write("-02:00:00:00:00:12\n") + f.write("-02:00:00:00:00:34\n") + f.write("01:01:01:01:01:01\n") + f.write("03:01:01:01:01:03\n") elif conf == 'hostapd.accept': - with open(filename, 'w') as f: - mac0 = dev[0].get_status_field("address") - mac1 = dev[1].get_status_field("address") - f.write(mac0 + " 1\n") - f.write(mac1 + " 2\n") + mac0 = dev[0].get_status_field("address") + mac1 = dev[1].get_status_field("address") + f.write(mac0 + " 1\n") + f.write(mac1 + " 2\n") elif conf == 'hostapd.accept2': - with open(filename, 'w') as f: - mac0 = dev[0].get_status_field("address") - mac1 = dev[1].get_status_field("address") - mac2 = dev[2].get_status_field("address") - f.write(mac0 + " 1\n") - f.write(mac1 + " 2\n") - f.write(mac2 + " 3\n") + mac0 = dev[0].get_status_field("address") + mac1 = dev[1].get_status_field("address") + mac2 = dev[2].get_status_field("address") + f.write(mac0 + " 1\n") + f.write(mac1 + " 2\n") + f.write(mac2 + " 3\n") else: + f.close() + os.unlink(filename) return conf return filename @@ -803,34 +804,33 @@ def bssid_inc(apdev, inc=1): return bssid def cfg_file(apdev, conf, ifname=None): - # put cfg file in /tmp directory - fname = os.path.join("/tmp", conf) - match = re.search(r'^bss-.+', conf) if match: - with open(fname, 'w') as f: - idx = ''.join(filter(str.isdigit, conf.split('-')[-1])) - if ifname is None: - ifname = apdev['ifname'] - if idx != '1': - ifname = ifname + '-' + idx + # put cfg file in /tmp directory + fd, fname = tempfile.mkstemp(dir='/tmp', prefix=conf + '-') + f = os.fdopen(fd, 'w') + idx = ''.join(filter(str.isdigit, conf.split('-')[-1])) + if ifname is None: + ifname = apdev['ifname'] + if idx != '1': + ifname = ifname + '-' + idx - f.write("driver=nl80211\n") - f.write("ctrl_interface=/var/run/hostapd\n") - f.write("hw_mode=g\n") - f.write("channel=1\n") - f.write("ieee80211n=1\n") - if conf.startswith('bss-ht40-'): - f.write("ht_capab=[HT40+]\n") - f.write("interface=%s\n" % ifname) + f.write("driver=nl80211\n") + f.write("ctrl_interface=/var/run/hostapd\n") + f.write("hw_mode=g\n") + f.write("channel=1\n") + f.write("ieee80211n=1\n") + if conf.startswith('bss-ht40-'): + f.write("ht_capab=[HT40+]\n") + f.write("interface=%s\n" % ifname) - f.write("ssid=bss-%s\n" % idx) - if conf == 'bss-2-dup.conf': - bssid = apdev['bssid'] - else: - bssid = bssid_inc(apdev, int(idx) - 1) - f.write("bssid=%s\n" % bssid) - else: - return conf + f.write("ssid=bss-%s\n" % idx) + if conf == 'bss-2-dup.conf': + bssid = apdev['bssid'] + else: + bssid = bssid_inc(apdev, int(idx) - 1) + f.write("bssid=%s\n" % bssid) - return fname + return fname + + return conf diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index d5721f415..e28ddd57a 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -353,6 +353,8 @@ def test_ap_ft_vlan(dev, apdev): run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1") if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"): raise Exception("Scan results missing RSN element info") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_vlan_disconnected(dev, apdev): """WPA2-PSK-FT AP with VLAN and local key generation""" @@ -377,6 +379,8 @@ def test_ap_ft_vlan_disconnected(dev, apdev): run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1") if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"): raise Exception("Scan results missing RSN element info") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_vlan_2(dev, apdev): """WPA2-PSK-FT AP with VLAN and dest-AP does not have VLAN info locally""" @@ -398,6 +402,8 @@ def test_ap_ft_vlan_2(dev, apdev): force_initial_conn_to_first_ap=True) if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"): raise Exception("Scan results missing RSN element info") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_many(dev, apdev): """WPA2-PSK-FT AP multiple times""" @@ -431,6 +437,8 @@ def test_ap_ft_many_vlan(dev, apdev): run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50, conndev="brvlan1") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_mixed(dev, apdev): """WPA2-PSK-FT mixed-mode AP""" @@ -735,6 +743,8 @@ def test_ap_ft_vlan_over_ds(dev, apdev): conndev="brvlan1") check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"), ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4")]) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_over_ds_many(dev, apdev): """WPA2-PSK-FT AP over DS multiple times""" @@ -768,6 +778,8 @@ def test_ap_ft_vlan_over_ds_many(dev, apdev): run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, roams=50, conndev="brvlan1") + if filename.startswith('/tmp/'): + os.unlink(filename) @remote_compatible def test_ap_ft_over_ds_unknown_target(dev, apdev): @@ -978,6 +990,8 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, conndev="brvlan1") + if filename.startswith('/tmp/'): + os.unlink(filename) def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None): if "SAE" not in dev.get_capability("auth_alg"): diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py index 84debc13f..aa0b28128 100644 --- a/tests/hwsim/test_ap_params.py +++ b/tests/hwsim/test_ap_params.py @@ -158,6 +158,8 @@ def test_ap_acl_accept(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected association") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_acl_deny(dev, apdev): """MAC ACL deny list""" @@ -175,6 +177,8 @@ def test_ap_acl_deny(dev, apdev): ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected association") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_acl_mgmt(dev, apdev): """MAC ACL accept/deny management""" @@ -247,6 +251,8 @@ def test_ap_acl_mgmt(dev, apdev): hapd.request("DENY_ACL ADD_MAC " + dev[0].own_addr()) dev[0].wait_disconnected() dev[0].request("DISCONNECT") + if filename.startswith('/tmp/'): + os.unlink(filename) @remote_compatible def test_ap_wds_sta(dev, apdev): diff --git a/tests/hwsim/test_ap_vlan.py b/tests/hwsim/test_ap_vlan.py index 7fe9107f4..29f8f5322 100644 --- a/tests/hwsim/test_ap_vlan.py +++ b/tests/hwsim/test_ap_vlan.py @@ -39,6 +39,8 @@ def test_ap_vlan_open(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_file_open(dev, apdev): """AP VLAN with open network and vlan_file mapping""" @@ -56,6 +58,8 @@ def test_ap_vlan_file_open(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_file_open2(dev, apdev): """AP VLAN with open network and vlan_file mapping (2)""" @@ -73,6 +77,8 @@ def test_ap_vlan_file_open2(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") hwsim_utils.test_connectivity_iface(dev[2], hapd, "hwsimbr3") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_file_parsing(dev, apdev, params): """hostapd vlan_file/mac_file parsing""" @@ -132,6 +138,8 @@ def test_ap_vlan_wpa2(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_wpa2_radius(dev, apdev): """AP VLAN with WPA2-Enterprise and RADIUS attributes""" @@ -201,6 +209,8 @@ def test_ap_vlan_wpa2_radius_local(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "test_br_vlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "test_br_vlan2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_wpa2_radius_id_change(dev, apdev): """AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID""" @@ -364,6 +374,8 @@ def test_ap_vlan_tagged(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brlo.1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brlo.2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def ap_vlan_iface_cleanup_multibss_cleanup(): subprocess.call(['ifconfig', 'dummy0', 'down'], @@ -632,6 +644,8 @@ def test_ap_vlan_without_station(dev, apdev, p): dev[0].request("DISCONNECT") dev[0].wait_disconnected() + if filename.startswith('/tmp/'): + os.unlink(filename) finally: subprocess.call(['ip', 'link', 'set', 'dev', 'brvlan1', 'down']) @@ -741,6 +755,8 @@ def test_ap_vlan_reconnect(dev, apdev): dev[0].connect("test-vlan", psk="12345678", scan_freq="2412") hapd.wait_sta() hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_psk(dev, apdev, params): """AP VLAN based on PSK/passphrase""" diff --git a/tests/hwsim/test_hapd_ctrl.py b/tests/hwsim/test_hapd_ctrl.py index c61f4ef3d..a83b570ef 100644 --- a/tests/hwsim/test_hapd_ctrl.py +++ b/tests/hwsim/test_hapd_ctrl.py @@ -6,6 +6,7 @@ import logging logger = logging.getLogger() +import os from remotehost import remote_compatible import hostapd import hwsim_utils @@ -295,6 +296,8 @@ def test_hapd_ctrl_set_deny_mac_file(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-DISCONNECTED"], 1) if ev is not None: raise Exception("Unexpected disconnection") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_hapd_ctrl_set_accept_mac_file(dev, apdev): """hostapd and SET accept_mac_file ctrl_iface command""" @@ -312,6 +315,8 @@ def test_hapd_ctrl_set_accept_mac_file(dev, apdev): ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], 1) if ev is not None: raise Exception("Unexpected disconnection") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_hapd_ctrl_set_accept_mac_file_vlan(dev, apdev): """hostapd and SET accept_mac_file ctrl_iface command (VLAN ID)""" @@ -327,6 +332,8 @@ def test_hapd_ctrl_set_accept_mac_file_vlan(dev, apdev): raise Exception("Unexpected SET failure") dev[1].wait_disconnected(timeout=15) dev[0].wait_disconnected(timeout=15) + if filename.startswith('/tmp/'): + os.unlink(filename) @remote_compatible def test_hapd_ctrl_set_error_cases(dev, apdev): From 8a1660b607294899a58af42b1bd14f21ee2915db Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sun, 23 Feb 2020 22:15:53 +0100 Subject: [PATCH 0071/1105] common: Add missing driver flag strings Add SAFE_PTK0_REKEYS and some other missing strings. Signed-off-by: Alexander Wetzel --- src/drivers/driver_common.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 731c6a3b1..bdb5c50da 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -308,6 +308,12 @@ const char * driver_flag_to_string(u64 flag) DF2S(OCE_AP); DF2S(OCE_STA_CFON); DF2S(MFP_OPTIONAL); + DF2S(SELF_MANAGED_REGULATORY); + DF2S(FTM_RESPONDER); + DF2S(CONTROL_PORT); + DF2S(VLAN_OFFLOAD); + DF2S(UPDATE_FT_IES); + DF2S(SAFE_PTK0_REKEYS); } return "UNKNOWN"; #undef DF2S From a5944db04a9454862d3e427fc2a5d1f69b12f61f Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sun, 23 Feb 2020 22:15:52 +0100 Subject: [PATCH 0072/1105] Add wpa_deny_ptk0_rekey to AP get_config() output Signed-off-by: Alexander Wetzel --- hostapd/ctrl_iface.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index f380926b3..6d2ecbc9c 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1287,6 +1287,14 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, pos += ret; } + if (hapd->conf->wpa && hapd->conf->wpa_deny_ptk0_rekey) { + ret = os_snprintf(pos, end - pos, "wpa_deny_ptk0_rekey=%d\n", + hapd->conf->wpa_deny_ptk0_rekey); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + return pos - buf; } From 0e05e8781aac6d7ac588188f4116e118288992eb Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sun, 23 Feb 2020 22:15:52 +0100 Subject: [PATCH 0073/1105] Simplify wpa_deny_ptk0_rekey documentation Signed-off-by: Alexander Wetzel --- hostapd/hostapd.conf | 22 ++++------------------ wpa_supplicant/wpa_supplicant.conf | 24 +++++------------------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 0f8461d49..bc5d1a7f6 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1618,24 +1618,10 @@ own_ip_addr=127.0.0.1 # Workaround for PTK rekey issues # -# Rekeying the PTK without using "Extended Key ID for Individually Addressed -# Frames" (two different Key ID values for pairwise keys) can, depending on the -# used cards/drivers, impact the security and stability of connections. Both -# ends can accidentally trick one end to drop all packets send by it until the -# connection is torn down or rekeyed again. Additionally, some drivers may -# skip/break the encryption for the time window the key is updated (normally a -# few milliseconds). -# -# To avoid such issues, hostapd can now replace all PTK rekeys using only keyid -# 0 (PTK0 rekeys) with disconnection that forces the remote stations to -# reconnect instead. -# -# EAP reauthentication depends on replacing the PTK and is therefore just -# another way to rekey the PTK and is affected by this parameter, too. -# -# "Extended Key ID for Individually Addressed Frames" is avoiding the issues -# using two separate keys and this parameter will be ignored when using it -# (i.e., PTK rekeying is allowed regardless of this parameter value). +# PTK0 rekeys (rekeying the PTK without "Extended Key ID for Individually +# Addressed Frames") can degrade the security and stability with some cards. +# To avoid such issues hostapd can replace those PTK rekeys (including EAP +# reauthentications) with disconnects. # # Available options: # 0 = always rekey when configured/instructed (default) diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 15121c386..f3a750e3c 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1101,25 +1101,11 @@ fast_reauth=1 # wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to # enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies. # -# wpa_deny_ptk0_rekey: Control PTK0 rekeying -# -# Rekeying the PTK without using "Extended Key ID for Individually Addressed -# Frames" (two different Key ID values for pairwise keys) can, depending on the -# used cards/drivers, impact the security and stability of connections. Both -# ends can accidentally trick one end to drop all packets send by it until the -# connection is torn down or rekeyed again. Additionally, some drivers may -# skip/break the encryption for the time window the key is updated (normally a -# few milliseconds). -# -# To avoid such issues, wpa_supplicant can now replace all PTK rekeys using only -# keyid 0 (PTK0 rekeys) with fast reconnects. -# -# EAP reauthentication depends on replacing the PTK and is therefore just -# another way to rekey the PTK and is affected by the parameter, too. -# -# "Extended Key ID for Individually Addressed Frames" is avoiding the issues -# using two separate keys and this parameter will be ignored when using it -# (i.e., PTK rekeying is allowed regardless of this parameter value). +# wpa_deny_ptk0_rekey: Workaround for PTK rekey issues +# PTK0 rekeys (using only one Key ID value for pairwise keys) can degrade the +# security and stability with some cards. +# To avoid the issues wpa_supplicant can replace those PTK rekeys (including +# EAP reauthentications) with fast reconnects. # # Available options: # 0 = always rekey when configured/instructed (default) From 0f84a93f651b3dbe2bdd5c914c7e8f55be08a878 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 24 Feb 2020 00:05:20 +0200 Subject: [PATCH 0074/1105] Fix a type in wpa_supplicant defconfig ap_mode=1 explanation in CONFIG_NO_SCAN_PROCESSING=y was really supposed to be talking about ap_scan=1. Signed-off-by: Jouni Malinen --- wpa_supplicant/defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index 09145f2de..5308b494b 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -248,7 +248,7 @@ CONFIG_CTRL_IFACE=y # Simultaneous Authentication of Equals (SAE), WPA3-Personal CONFIG_SAE=y -# Disable scan result processing (ap_mode=1) to save code size by about 1 kB. +# Disable scan result processing (ap_scan=1) to save code size by about 1 kB. # This can be used if ap_scan=1 mode is never enabled. #CONFIG_NO_SCAN_PROCESSING=y From 2e34f6a53f312aa98e08b6cbdc2b7f4c4f85ca0e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 24 Feb 2020 12:20:05 +0200 Subject: [PATCH 0075/1105] Sync with mac80211-next.git include/uapi/linux/nl80211.h This brings in nl80211 definitions as of 2020-02-24. Signed-off-by: Jouni Malinen --- src/drivers/nl80211_copy.h | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index 158bccb4a..934e62fe8 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -1039,14 +1039,11 @@ * a control port frame and as a notification that a control port frame * has been received. %NL80211_ATTR_FRAME is used to specify the * frame contents. The frame is the raw EAPoL data, without ethernet or - * 802.11 headers. An optional %NL80211_ATTR_SRC_MAC can be used to send - * pre-auth frames to STAs on behalf of other APs. + * 802.11 headers. * When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added * indicating the protocol type of the received frame; whether the frame * was received unencrypted and the MAC address of the peer respectively. - * %NL80211_ATTR_DST_MAC can be used to forward pre-auth frames in - * userspace while using AP mode. * * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded. * @@ -2412,9 +2409,6 @@ enum nl80211_commands { * %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not * advertised for a specific interface type. * - * @NL80211_ATTR_SRC_MAC: MAC address used in control port over nl80211 transmit - * @NL80211_ATTR_DST_MAC: MAC address used in control port over nl80211 receive - * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2883,9 +2877,6 @@ enum nl80211_attrs { NL80211_ATTR_IFTYPE_AKM_SUITES, - NL80211_ATTR_SRC_MAC, - NL80211_ATTR_DST_MAC, - /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -4559,6 +4550,7 @@ enum nl80211_key_default_types { * See &enum nl80211_key_default_types. * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode. * Defaults to @NL80211_KEY_RX_TX. + * @NL80211_KEY_DEFAULT_BEACON: flag indicating default Beacon frame key * * @__NL80211_KEY_AFTER_LAST: internal * @NL80211_KEY_MAX: highest key attribute @@ -4574,6 +4566,7 @@ enum nl80211_key_attributes { NL80211_KEY_TYPE, NL80211_KEY_DEFAULT_TYPES, NL80211_KEY_MODE, + NL80211_KEY_DEFAULT_BEACON, /* keep last */ __NL80211_KEY_AFTER_LAST, @@ -5548,9 +5541,8 @@ enum nl80211_feature_flags { * feature, which prevents bufferbloat by using the expected transmission * time to limit the amount of data buffered in the hardware. * - * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS: The driver - * can use src and dst MAC addresses with control port over nl80211 rx - * and tx operations. + * @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection + * and can receive key configuration for BIGTK using key indexes 6 and 7. * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. @@ -5599,7 +5591,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_SAE_OFFLOAD, NL80211_EXT_FEATURE_VLAN_OFFLOAD, NL80211_EXT_FEATURE_AQL, - NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS, + NL80211_EXT_FEATURE_BEACON_PROTECTION, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, From f1d385609009985de8a6ab8a8bbf46b672b93c3d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 21 Feb 2020 18:19:04 +0200 Subject: [PATCH 0076/1105] nl80211: Beacon protection capability flag and default key type Add a new capability flag based on the nl80211 feature advertisement and start using the new default key type for Beacon protection. This enables AP mode functionality to allow Beacon protection to be enabled. This is also enabling the previously added ap_pmf_beacon_protection_* hwsim test cases. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 2 ++ src/drivers/driver_common.c | 1 + src/drivers/driver_nl80211.c | 6 ++++-- src/drivers/driver_nl80211_capa.c | 4 ++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 48dd3fe52..cd1ec31a1 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1840,6 +1840,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_UPDATE_FT_IES 0x1000000000000000ULL /** Driver can correctly rekey PTKs without Extended Key ID */ #define WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS 0x2000000000000000ULL +/** Driver supports Beacon protection */ +#define WPA_DRIVER_FLAGS_BEACON_PROTECTION 0x4000000000000000ULL u64 flags; #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index bdb5c50da..f4d06e438 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -314,6 +314,7 @@ const char * driver_flag_to_string(u64 flag) DF2S(VLAN_OFFLOAD); DF2S(UPDATE_FT_IES); DF2S(SAFE_PTK0_REKEYS); + DF2S(BEACON_PROTECTION); } return "UNKNOWN"; #undef DF2S diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 659f6584d..18e4b8eef 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3189,8 +3189,10 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, alg == WPA_ALG_BIP_GMAC_128 || alg == WPA_ALG_BIP_GMAC_256 || alg == WPA_ALG_BIP_CMAC_256) ? - NL80211_KEY_DEFAULT_MGMT : - NL80211_KEY_DEFAULT)) + (key_idx == 6 || key_idx == 7 ? + NL80211_KEY_DEFAULT_BEACON : + NL80211_KEY_DEFAULT_MGMT) : + NL80211_KEY_DEFAULT)) goto fail; if (addr && is_broadcast_ether_addr(addr)) { struct nlattr *types; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 61c8c2556..ea1ab8a2f 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -449,6 +449,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0)) capa->flags |= WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS; + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_BEACON_PROTECTION)) + capa->flags |= WPA_DRIVER_FLAGS_BEACON_PROTECTION; } From 3fadb1dcc083430fe8cbe9891ddb28cd8c023e25 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 24 Feb 2020 19:53:49 +0200 Subject: [PATCH 0077/1105] WPS: Ignore other APs if PBC is used with a specific BSSID While the WSC specification requires the Enrollee to stop PBC provisioning if the scan sees multiple APs in active PBC mode, this is problematic due to some deployed devices continuing to advertise PBC mode for extended duration (or even permanently). Such an environment will still need to prevent wildcard AP selection with PBC since an incorrect device could be selected. However, if the Enrollee device has been explicitly requested to connect to a specific AP based on its BSSID, the other APs in scan results can be ignored without affecting which AP would be selected (only the one matching the specified BSSID is acceptable). Start filtering scan results for PBC session overlap check based on the locally specified constraint on the BSSID, if one is set. This allows PBC to be used with "WPS_PBC " command in environment where another AP device is claiming to be in active PBC mode while "WPS_PBC" command will still continue to reject provisioning since the correct AP cannot be selected. This will also cover the P2P cases where P2P_CONNECT is used to start or authorize GO Negotiation and joining-a-GO with a specific P2P GO Interface Address (BSSID). Signed-off-by: Jouni Malinen --- wpa_supplicant/wps_supplicant.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 99ddd26ca..063b4e69f 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1829,6 +1829,10 @@ int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "WPS: Check whether PBC session overlap is " "present in scan results; selected BSSID " MACSTR, MAC2STR(selected->bssid)); + if (!is_zero_ether_addr(ssid->bssid)) + wpa_printf(MSG_DEBUG, + "WPS: Network profile limited to accept only a single BSSID " MACSTR, + MAC2STR(ssid->bssid)); /* Make sure that only one AP is in active PBC mode */ wps_ie = wpa_bss_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE); @@ -1849,6 +1853,14 @@ int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, os_memcmp(selected->bssid, ap->bssid, ETH_ALEN) == 0) continue; + if (!is_zero_ether_addr(ssid->bssid) && + os_memcmp(ap->bssid, ssid->bssid, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Ignore another BSS " MACSTR + " in active PBC mode due to local BSSID limitation", + MAC2STR(ap->bssid)); + continue; + } + wpa_printf(MSG_DEBUG, "WPS: Another BSS in active PBC mode: " MACSTR, MAC2STR(ap->bssid)); wpa_hexdump(MSG_DEBUG, "WPS: UUID of the other BSS", From ae750570b6f8d9d2b723eefd136896a2dbdfa0d2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 24 Feb 2020 20:04:21 +0200 Subject: [PATCH 0078/1105] tests: WPS PBC session overlap detection with single BSSID selected Update grpform_pbc_overlap not to require PBC session overlap to be detected since in this sequence a single BSSID is specified and other APs can be ignored while checking for session overlap. Add other test cases to explicitly check for the PBC session overlap detection in non-P2P and P2P cases when the BSSID is specified. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_wps.py | 33 ++++++++++++++++++++++++++++----- tests/hwsim/test_p2p_autogo.py | 23 +++++++++++++++++++++++ tests/hwsim/test_p2p_grpform.py | 22 +++++++++------------- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index dc8635087..958341667 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -956,9 +956,7 @@ def test_ap_wps_setup_locked_2(dev, apdev): dev[0].request("WPS_CANCEL") dev[0].wait_disconnected() -@remote_compatible -def test_ap_wps_pbc_overlap_2ap(dev, apdev): - """WPS PBC session overlap with two active APs""" +def setup_ap_wps_pbc_overlap_2ap(apdev): params = {"ssid": "wps1", "eap_server": "1", "wps_state": "2", "wpa_passphrase": "12345678", "wpa": "2", "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP", @@ -971,16 +969,41 @@ def test_ap_wps_pbc_overlap_2ap(dev, apdev): hapd2 = hostapd.add_ap(apdev[1], params) hapd.request("WPS_PBC") hapd2.request("WPS_PBC") + return hapd, hapd2 + +@remote_compatible +def test_ap_wps_pbc_overlap_2ap(dev, apdev): + """WPS PBC session overlap with two active APs""" + hapd, hapd2 = setup_ap_wps_pbc_overlap_2ap(apdev) logger.info("WPS provisioning step") dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412") dev[0].request("WPS_PBC") ev = dev[0].wait_event(["WPS-OVERLAP-DETECTED"], timeout=15) - if ev is None: - raise Exception("PBC session overlap not detected") hapd.request("DISABLE") hapd2.request("DISABLE") dev[0].flush_scan_cache() + if ev is None: + raise Exception("PBC session overlap not detected") + +@remote_compatible +def test_ap_wps_pbc_overlap_2ap_specific_bssid(dev, apdev): + """WPS PBC session overlap with two active APs (specific BSSID selected)""" + hapd, hapd2 = setup_ap_wps_pbc_overlap_2ap(apdev) + logger.info("WPS provisioning step") + dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) + dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412") + dev[0].request("WPS_PBC " + apdev[0]['bssid']) + ev = dev[0].wait_event(["WPS-OVERLAP-DETECTED", + "CTRL-EVENT-CONNECTED"], timeout=15) + dev[0].request("DISCONNECT") + hapd.request("DISABLE") + hapd2.request("DISABLE") + dev[0].flush_scan_cache() + if ev is None: + raise Exception("PBC session overlap result not reported") + if "CTRL-EVENT-CONNECTED" not in ev: + raise Exception("Connection did not complete") @remote_compatible def test_ap_wps_pbc_overlap_2sta(dev, apdev): diff --git a/tests/hwsim/test_p2p_autogo.py b/tests/hwsim/test_p2p_autogo.py index e896323f1..f0e861e2f 100644 --- a/tests/hwsim/test_p2p_autogo.py +++ b/tests/hwsim/test_p2p_autogo.py @@ -10,6 +10,7 @@ import subprocess import logging logger = logging.getLogger() +import hostapd import hwsim_utils import utils from utils import HwsimSkip @@ -231,6 +232,28 @@ def test_autogo_pbc(dev): dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), "pbc", timeout=15, social=True) +def test_autogo_pbc_session_overlap(dev, apdev): + """P2P autonomous GO and PBC session overlap""" + params = {"ssid": "wps", "eap_server": "1", "wps_state": "1"} + hapd = hostapd.add_ap(apdev[0], params) + hapd.request("WPS_PBC") + bssid = hapd.own_addr() + time.sleep(0.1) + + dev[0].scan_for_bss(bssid, freq=2412) + dev[1].scan_for_bss(bssid, freq=2412) + + dev[1].global_request("SET p2p_no_group_iface 0") + autogo(dev[0], freq=2412) + if "OK" not in dev[0].group_request("WPS_PBC p2p_dev_addr=" + dev[1].p2p_dev_addr()): + raise Exception("WPS_PBC failed") + dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), "pbc", timeout=15, + social=True) + hapd.disable() + remove_group(dev[0], dev[1]) + dev[0].flush_scan_cache() + dev[1].flush_scan_cache() + def test_autogo_tdls(dev): """P2P autonomous GO and two clients using TDLS""" go = dev[0] diff --git a/tests/hwsim/test_p2p_grpform.py b/tests/hwsim/test_p2p_grpform.py index 47882cce2..88c7d7e93 100644 --- a/tests/hwsim/test_p2p_grpform.py +++ b/tests/hwsim/test_p2p_grpform.py @@ -638,6 +638,7 @@ def clear_pbc_overlap(dev, ap): dev[1].request("P2P_CANCEL") dev[0].p2p_stop_find() dev[1].p2p_stop_find() + remove_group(dev[0], dev[1], allow_failure=True) dev[0].dump_monitor() dev[1].dump_monitor() time.sleep(0.1) @@ -653,9 +654,9 @@ def test_grpform_pbc_overlap(dev, apdev): hapd.request("WPS_PBC") time.sleep(0.1) - # Since P2P Client scan case is now optimzied to use a specific SSID, the + # Since P2P Client scan case is now optimized to use a specific SSID, the # WPS AP will not reply to that and the scan after GO Negotiation can quite - # likely miss the AP due to dwell time being short enoguh to miss the Beacon + # likely miss the AP due to dwell time being short enough to miss the Beacon # frame. This has made the test case somewhat pointless, but keep it here # for now with an additional scan to confirm that PBC detection works if # there is a BSS entry for a overlapping AP. @@ -677,11 +678,11 @@ def test_grpform_pbc_overlap(dev, apdev): raise Exception("Failed to authorize GO Neg") if "OK" not in dev[1].global_request("P2P_CONNECT " + addr0 + " pbc go_intent=15 freq=2412"): raise Exception("Failed to initiate GO Neg") - ev = dev[0].wait_global_event(["WPS-OVERLAP-DETECTED"], timeout=15) - if ev is None: - raise Exception("PBC overlap not reported") - + ev = dev[0].wait_global_event(["WPS-OVERLAP-DETECTED", + "P2P-GROUP-FORMATION-SUCCESS"], timeout=15) clear_pbc_overlap(dev, apdev[0]) + if ev is None or "P2P-GROUP-FORMATION-SUCCESS" not in ev: + raise Exception("P2P group formation did not complete") @remote_compatible def test_grpform_pbc_overlap_group_iface(dev, apdev): @@ -713,14 +714,9 @@ def test_grpform_pbc_overlap_group_iface(dev, apdev): raise Exception("Failed to initiate GO Neg") ev = dev[0].wait_global_event(["WPS-OVERLAP-DETECTED", "P2P-GROUP-FORMATION-SUCCESS"], timeout=15) - if ev is None or "WPS-OVERLAP-DETECTED" not in ev: - # Do not report this as failure since the P2P group formation case - # using a separate group interface has limited chances of "seeing" the - # overlapping AP due to a per-SSID scan and no prior scan operations on - # the group interface. - logger.info("PBC overlap not reported") - clear_pbc_overlap(dev, apdev[0]) + if ev is None or "P2P-GROUP-FORMATION-SUCCESS" not in ev: + raise Exception("P2P group formation did not complete") @remote_compatible def test_grpform_goneg_fail_with_group_iface(dev): From 34640a88d877b5f2bbb1d5bd6dff7d1d78730f3d Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Thu, 20 Feb 2020 15:09:38 +0530 Subject: [PATCH 0079/1105] Fix enum qca_wlan_vendor_attr_config value prefix Couple of the attributes were defined with inconsistent prefix in the name (missing "CONFIG_"). Fix these to use the common prefix for all enum qca_wlan_vendor_attr_config values. Add defined values for the incorrect names to avoid issues with existing users. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 44d4e6902..516f53296 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2084,7 +2084,7 @@ enum qca_wlan_vendor_attr_config { * take the union of IEs from both of these interfaces and send in * further disassoc/deauth frames. */ - QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES = 58, + QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES = 58, /* 8-bit unsigned value for ELNA bypass. * 1-Enable, 0-Disable @@ -2096,7 +2096,7 @@ enum qca_wlan_vendor_attr_config { * scenarios where STA cannot honor the Beacon Report Request from AP. * 1-Enable, 0-Disable. */ - QCA_WLAN_VENDOR_ATTR_BEACON_REPORT_FAIL = 60, + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL = 60, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, @@ -2104,6 +2104,14 @@ enum qca_wlan_vendor_attr_config { QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1, }; +/* Compatibility defines for previously used incorrect enum + * qca_wlan_vendor_attr_config names. These values should not be used in any + * new implementation. */ +#define QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES \ + QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES +#define QCA_WLAN_VENDOR_ATTR_BEACON_REPORT_FAIL \ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL + /** * enum qca_wlan_vendor_attr_sap_config - Parameters for AP configuration * From ec303e2cb16c7034f2634f14e41929c4e8708b93 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Thu, 20 Feb 2020 15:09:38 +0530 Subject: [PATCH 0080/1105] Introduce QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON This attribute enables/disables the host driver to send roam reason information in the Reassociation Request frame to the AP in the same ESS. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 516f53296..1f2233d7a 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2098,6 +2098,13 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL = 60, + /* 8-bit unsigned value. This attribute enables/disables the host driver + * to send roam reason information in the Reassociation Request frame to + * the target AP when roaming within the same ESS. + * 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON = 61, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = From e55dedbf6ecbf2e42a8c90c77afbaa8bbabe3a4d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 25 Feb 2020 13:08:00 +0200 Subject: [PATCH 0081/1105] tests/fuzzing: Fix build after CONFIG_IEEE80211N=y removal Commit f3bcd6960346 ("Remove CONFIG_IEEE80211N build option") broke couple of fuzzing test tools due to missing wpa_scan_results_free(). Fix that by pulling in driver_common.o. Signed-off-by: Jouni Malinen --- tests/fuzzing/ap-mgmt/Makefile | 2 ++ tests/fuzzing/eapol-key-auth/Makefile | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/fuzzing/ap-mgmt/Makefile b/tests/fuzzing/ap-mgmt/Makefile index af5fd4f4d..192ae723e 100644 --- a/tests/fuzzing/ap-mgmt/Makefile +++ b/tests/fuzzing/ap-mgmt/Makefile @@ -24,6 +24,8 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a +OBJS += $(SRC)/drivers/driver_common.o + ap-mgmt: ap-mgmt.o $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) diff --git a/tests/fuzzing/eapol-key-auth/Makefile b/tests/fuzzing/eapol-key-auth/Makefile index 4dca10264..bd2b27566 100644 --- a/tests/fuzzing/eapol-key-auth/Makefile +++ b/tests/fuzzing/eapol-key-auth/Makefile @@ -17,6 +17,8 @@ LIBS += $(SRC)/eap_server/libeap_server.a LIBS += $(SRC)/ap/libap.a LIBS += $(SRC)/radius/libradius.a +OBJS += $(SRC)/drivers/driver_common.o + eapol-key-auth: eapol-key-auth.o $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group From 5f11739d58f5a405915d67c5df0eeb89b6fdecc0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 25 Feb 2020 13:13:06 +0200 Subject: [PATCH 0082/1105] tests/fuzzing: Update WPA set_key() handler prototype Update the fizzing test tools to use the new set_key() prototype, i.e., add the new key_flag argument, to get rid of compiler warnings. Signed-off-by: Jouni Malinen --- tests/fuzzing/eapol-key-auth/eapol-key-auth.c | 7 ++++--- tests/fuzzing/eapol-key-supp/eapol-key-supp.c | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/fuzzing/eapol-key-auth/eapol-key-auth.c b/tests/fuzzing/eapol-key-auth/eapol-key-auth.c index a909114a4..bb46422c6 100644 --- a/tests/fuzzing/eapol-key-auth/eapol-key-auth.c +++ b/tests/fuzzing/eapol-key-auth/eapol-key-auth.c @@ -169,12 +169,13 @@ static void supp_eapol_key_request(void *eloop_data, void *user_ctx) static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, const u8 *addr, int idx, u8 *key, - size_t key_len) + size_t key_len, enum key_flag key_flag) { struct wpa *wpa = ctx; - wpa_printf(MSG_DEBUG, "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d)", - __func__, vlan_id, alg, idx, (int) key_len); + wpa_printf(MSG_DEBUG, + "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d key_flag=0x%x)", + __func__, vlan_id, alg, idx, (int) key_len, key_flag); if (addr) wpa_printf(MSG_DEBUG, "AUTH: addr=" MACSTR, MAC2STR(addr)); diff --git a/tests/fuzzing/eapol-key-supp/eapol-key-supp.c b/tests/fuzzing/eapol-key-supp/eapol-key-supp.c index eb565d7cf..487c889d7 100644 --- a/tests/fuzzing/eapol-key-supp/eapol-key-supp.c +++ b/tests/fuzzing/eapol-key-supp/eapol-key-supp.c @@ -175,11 +175,11 @@ static int supp_get_beacon_ie(void *ctx) static int supp_set_key(void *ctx, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) + const u8 *key, size_t key_len, enum key_flag key_flag) { wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " - "set_tx=%d)", - __func__, alg, MAC2STR(addr), key_idx, set_tx); + "set_tx=%d key_flag=0x%x)", + __func__, alg, MAC2STR(addr), key_idx, set_tx, key_flag); wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len); return 0; From b8f6b0713a61e3d9c60161405e025a99021af98f Mon Sep 17 00:00:00 2001 From: Krishna Rao Date: Fri, 14 Feb 2020 17:55:40 +0530 Subject: [PATCH 0083/1105] Add attribute for dwell time in QCA vendor scan Add an attribute QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME for specifying dwell time in the QCA vendor scan command. This is a common value which applies across all frequencies requested in the scan. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 1f2233d7a..8a56ab7bf 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -1716,6 +1716,9 @@ enum qca_vendor_element_id { * randomisation * @QCA_WLAN_VENDOR_ATTR_SCAN_BSSID: 6-byte MAC address representing the * specific BSSID to scan for. + * @QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME: Unsigned 64-bit dwell time in + * microseconds. This is a common value which applies across all + * frequencies specified by QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES. */ enum qca_wlan_vendor_attr_scan { QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0, @@ -1730,6 +1733,7 @@ enum qca_wlan_vendor_attr_scan { QCA_WLAN_VENDOR_ATTR_SCAN_MAC = 9, QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10, QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11, + QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12, QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SCAN_MAX = QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1 From a8a277c169bef628ff6a76573b058ebd0914ff3d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 00:31:33 +0200 Subject: [PATCH 0084/1105] wlantest: Get STA IEs based on EAPOL-Key msg 2/4 before PTK derivation The previous implementation tried to update STA IE information based on EAPOL-Key msg 2/4 to be able to handle captures that do not include the (Re)Association Request frame. This was not sufficient (OSEN was not included) and was done too late (the parsed information is needed for PMK-to-PTK derivation). Move the IE update step to happen before trying to derive the PTK if no (Re)Association Request frame has been seen. Signed-off-by: Jouni Malinen --- wlantest/rx_eapol.c | 59 +++++++++++++++++++++------------------------ wlantest/rx_mgmt.c | 2 ++ wlantest/wlantest.h | 1 + 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index e4fe7e23e..c58b82c16 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -257,7 +257,35 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, } os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN); key_info = WPA_GET_BE16(hdr->key_info); + key_data = mic + mic_len + 2; key_data_len = WPA_GET_BE16(mic + mic_len); + + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { + add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data"); + return; + } + + if (!sta->assocreq_seen) { + struct ieee802_11_elems elems; + + os_memset(&elems, 0, sizeof(elems)); + if (ie.wpa_ie) { + elems.wpa_ie = ie.wpa_ie + 2; + elems.wpa_ie_len = ie.wpa_ie_len - 2; + } + if (ie.rsn_ie) { + elems.rsn_ie = ie.rsn_ie + 2; + elems.rsn_ie_len = ie.rsn_ie_len - 2; + } + if (ie.osen) { + elems.osen = ie.osen + 2; + elems.osen_len = ie.osen_len - 2; + } + wpa_printf(MSG_DEBUG, + "Update STA data based on IEs in EAPOL-Key 2/4"); + sta_update_assoc(sta, &elems); + } + derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len); if (!sta->ptk_set && !sta->tptk_set) { @@ -281,18 +309,10 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, } add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/4"); - key_data = mic + mic_len + 2; - - if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { - add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data"); - return; - } - if (ie.wpa_ie) { wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE", ie.wpa_ie, ie.wpa_ie_len); if (os_memcmp(ie.wpa_ie, sta->rsnie, ie.wpa_ie_len) != 0) { - struct ieee802_11_elems elems; add_note(wt, MSG_INFO, "Mismatch in WPA IE between EAPOL-Key 2/4 " "and (Re)Association Request from " MACSTR, @@ -303,17 +323,6 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, "Request", sta->rsnie, sta->rsnie[0] ? 2 + sta->rsnie[1] : 0); - /* - * The sniffer may have missed (Re)Association - * Request, so try to survive with the information from - * EAPOL-Key. - */ - os_memset(&elems, 0, sizeof(elems)); - elems.wpa_ie = ie.wpa_ie + 2; - elems.wpa_ie_len = ie.wpa_ie_len - 2; - wpa_printf(MSG_DEBUG, "Update STA data based on WPA " - "IE in EAPOL-Key 2/4"); - sta_update_assoc(sta, &elems); } } @@ -321,7 +330,6 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE", ie.rsn_ie, ie.rsn_ie_len); if (os_memcmp(ie.rsn_ie, sta->rsnie, ie.rsn_ie_len) != 0) { - struct ieee802_11_elems elems; add_note(wt, MSG_INFO, "Mismatch in RSN IE between EAPOL-Key 2/4 " "and (Re)Association Request from " MACSTR, @@ -332,17 +340,6 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, "Request", sta->rsnie, sta->rsnie[0] ? 2 + sta->rsnie[1] : 0); - /* - * The sniffer may have missed (Re)Association - * Request, so try to survive with the information from - * EAPOL-Key. - */ - os_memset(&elems, 0, sizeof(elems)); - elems.rsn_ie = ie.rsn_ie + 2; - elems.rsn_ie_len = ie.rsn_ie_len - 2; - wpa_printf(MSG_DEBUG, "Update STA data based on RSN " - "IE in EAPOL-Key 2/4"); - sta_update_assoc(sta, &elems); } } } diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 92762b8f0..086db4a66 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -640,6 +640,7 @@ static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len) os_memcpy(sta->assocreq_ies, mgmt->u.assoc_req.variable, sta->assocreq_ies_len); + sta->assocreq_seen = 1; sta_update_assoc(sta, &elems); } @@ -875,6 +876,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, os_memcpy(sta->assocreq_ies, mgmt->u.reassoc_req.variable, sta->assocreq_ies_len); + sta->assocreq_seen = 1; sta_update_assoc(sta, &elems); /* TODO: FT protocol: verify FTE MIC and update GTK/IGTK for the BSS */ diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 82eddc11c..69aa155d1 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -82,6 +82,7 @@ struct wlantest_sta { u8 ap_sa_query_tr[2]; u8 sta_sa_query_tr[2]; u32 counters[NUM_WLANTEST_STA_COUNTER]; + int assocreq_seen; u16 assocreq_capab_info; u16 assocreq_listen_int; u8 *assocreq_ies; From 0e3e3a9ab54428310236248cc1b8cf77d5337073 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 00:51:07 +0200 Subject: [PATCH 0085/1105] wlantest: Update BSS IEs based on EAPOL-Key msg 3/4 If no Beacon or Probe Response frame has been seen in the capture, use the IEs from EAPOL-Key msg 3/4 to set up BSS information. Signed-off-by: Jouni Malinen --- wlantest/bss.c | 21 ++++++++++++++------- wlantest/rx_eapol.c | 42 +++++++++++++++++++++++++++++------------- wlantest/rx_mgmt.c | 4 ++-- wlantest/sta.c | 3 ++- wlantest/wlantest.h | 3 ++- 5 files changed, 49 insertions(+), 24 deletions(-) diff --git a/wlantest/bss.c b/wlantest/bss.c index 298a902c7..0556c72e2 100644 --- a/wlantest/bss.c +++ b/wlantest/bss.c @@ -129,7 +129,7 @@ static void bss_add_pmk(struct wlantest *wt, struct wlantest_bss *bss) void bss_update(struct wlantest *wt, struct wlantest_bss *bss, - struct ieee802_11_elems *elems) + struct ieee802_11_elems *elems, int beacon) { struct wpa_ie_data data; int update = 0; @@ -137,15 +137,18 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, if (bss->capab_info != bss->prev_capab_info) update = 1; - if (elems->ssid == NULL || elems->ssid_len > 32) { - wpa_printf(MSG_INFO, "Invalid or missing SSID in a Beacon " - "frame for " MACSTR, MAC2STR(bss->bssid)); + if (beacon && (!elems->ssid || elems->ssid_len > 32)) { + wpa_printf(MSG_INFO, + "Invalid or missing SSID in a %s frame for " MACSTR, + beacon == 1 ? "Beacon" : "Probe Response", + MAC2STR(bss->bssid)); bss->parse_error_reported = 1; return; } - if (bss->ssid_len != elems->ssid_len || - os_memcmp(bss->ssid, elems->ssid, bss->ssid_len) != 0) { + if (beacon && + (bss->ssid_len != elems->ssid_len || + os_memcmp(bss->ssid, elems->ssid, bss->ssid_len) != 0)) { wpa_printf(MSG_DEBUG, "Store SSID '%s' for BSSID " MACSTR, wpa_ssid_txt(elems->ssid, elems->ssid_len), MAC2STR(bss->bssid)); @@ -223,7 +226,11 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, if (!update) return; - bss->beacon_seen = 1; + if (beacon == 1) + bss->beacon_seen = 1; + else if (beacon == 2) + bss->proberesp_seen = 1; + bss->ies_set = 1; bss->prev_capab_info = bss->capab_info; bss->proto = 0; bss->pairwise_cipher = 0; diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index c58b82c16..2e49929c1 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -222,6 +222,25 @@ static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss, } +static void elems_from_eapol_ie(struct ieee802_11_elems *elems, + struct wpa_eapol_ie_parse *ie) +{ + os_memset(elems, 0, sizeof(*elems)); + if (ie->wpa_ie) { + elems->wpa_ie = ie->wpa_ie + 2; + elems->wpa_ie_len = ie->wpa_ie_len - 2; + } + if (ie->rsn_ie) { + elems->rsn_ie = ie->rsn_ie + 2; + elems->rsn_ie_len = ie->rsn_ie_len - 2; + } + if (ie->osen) { + elems->osen = ie->osen + 2; + elems->osen_len = ie->osen_len - 2; + } +} + + static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, const u8 *src, const u8 *data, size_t len) { @@ -268,19 +287,7 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, if (!sta->assocreq_seen) { struct ieee802_11_elems elems; - os_memset(&elems, 0, sizeof(elems)); - if (ie.wpa_ie) { - elems.wpa_ie = ie.wpa_ie + 2; - elems.wpa_ie_len = ie.wpa_ie_len - 2; - } - if (ie.rsn_ie) { - elems.rsn_ie = ie.rsn_ie + 2; - elems.rsn_ie_len = ie.rsn_ie_len - 2; - } - if (ie.osen) { - elems.osen = ie.osen + 2; - elems.osen_len = ie.osen_len - 2; - } + elems_from_eapol_ie(&elems, &ie); wpa_printf(MSG_DEBUG, "Update STA data based on IEs in EAPOL-Key 2/4"); sta_update_assoc(sta, &elems); @@ -750,6 +757,15 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, return; } + if (!bss->ies_set) { + struct ieee802_11_elems elems; + + elems_from_eapol_ie(&elems, &ie); + wpa_printf(MSG_DEBUG, + "Update BSS data based on IEs in EAPOL-Key 3/4"); + bss_update(wt, bss, &elems, 0); + } + if ((ie.wpa_ie && os_memcmp(ie.wpa_ie, bss->wpaie, ie.wpa_ie_len) != 0) || (ie.wpa_ie == NULL && bss->wpaie[0])) { diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 086db4a66..78fd3c80a 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -86,7 +86,7 @@ static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len) return; } - bss_update(wt, bss, &elems); + bss_update(wt, bss, &elems, 1); mme = get_ie(mgmt->u.beacon.variable, len - offset, WLAN_EID_MMIE); if (!mme) { @@ -173,7 +173,7 @@ static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len) return; } - bss_update(wt, bss, &elems); + bss_update(wt, bss, &elems, 2); } diff --git a/wlantest/sta.c b/wlantest/sta.c index 3e5ff51b6..62dae0790 100644 --- a/wlantest/sta.c +++ b/wlantest/sta.c @@ -156,7 +156,8 @@ void sta_update_assoc(struct wlantest_sta *sta, struct ieee802_11_elems *elems) MAC2STR(sta->addr), sta->pairwise_cipher, MAC2STR(bss->bssid), bss->pairwise_cipher); } - if (sta->proto && data.group_cipher != bss->group_cipher) { + if (sta->proto && data.group_cipher != bss->group_cipher && + bss->ies_set) { wpa_printf(MSG_INFO, "Mismatch in group cipher: STA " MACSTR " 0x%x != BSS " MACSTR " 0x%x", MAC2STR(sta->addr), data.group_cipher, diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 69aa155d1..2cf51966a 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -135,6 +135,7 @@ struct wlantest_bss { size_t ssid_len; int beacon_seen; int proberesp_seen; + int ies_set; int parse_error_reported; u8 wpaie[257]; u8 rsnie[257]; @@ -265,7 +266,7 @@ struct wlantest_bss * bss_find(struct wlantest *wt, const u8 *bssid); struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid); void bss_deinit(struct wlantest_bss *bss); void bss_update(struct wlantest *wt, struct wlantest_bss *bss, - struct ieee802_11_elems *elems); + struct ieee802_11_elems *elems, int beacon); void bss_flush(struct wlantest *wt); int bss_add_pmk_from_passphrase(struct wlantest_bss *bss, const char *passphrase); From f5849f1c7ce03f7429189af105a8439e56076757 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 01:30:00 +0200 Subject: [PATCH 0086/1105] wlantest: Add more notes about decryption into pcapng Note the used TK/GTK and KeyID in frame notes when writing decrypted frames to a PCAPNG file. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 73 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index d6c7a54c7..63da868d3 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -119,8 +119,21 @@ static void rx_data_process(struct wlantest *wt, const u8 *bssid, } +static void write_decrypted_note(struct wlantest *wt, const u8 *decrypted, + const u8 *tk, size_t tk_len, int keyid) +{ + char tk_hex[65]; + + if (!decrypted) + return; + + wpa_snprintf_hex(tk_hex, sizeof(tk_hex), tk, tk_len); + add_note(wt, MSG_EXCESSIVE, "TK[%d] %s", keyid, tk_hex); +} + + static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, - const struct ieee80211_hdr *hdr, + const struct ieee80211_hdr *hdr, int keyid, const u8 *data, size_t data_len, size_t *decrypted_len) { struct wlantest_ptk *ptk; @@ -152,7 +165,10 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, } if (decrypted) { wpa_debug_level = prev_level; - add_note(wt, MSG_DEBUG, "Found PTK match from list of all known PTKs"); + add_note(wt, MSG_DEBUG, + "Found PTK match from list of all known PTKs"); + write_decrypted_note(wt, decrypted, ptk->ptk.tk, + ptk->ptk.tk_len, keyid); return decrypted; } } @@ -229,14 +245,20 @@ static void rx_data_bss_prot_group(struct wlantest *wt, ccmp_get_pn(pn, data); if (os_memcmp(pn, bss->rsc[keyid], 6) <= 0) { u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - add_note(wt, MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR - " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u%s", + char pn_hex[6 * 2 + 1], rsc_hex[6 * 2 + 1]; + + wpa_snprintf_hex(pn_hex, sizeof(pn_hex), pn, 6); + wpa_snprintf_hex(rsc_hex, sizeof(rsc_hex), bss->rsc[keyid], 6); + add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR + " A2=" MACSTR " A3=" MACSTR + " seq=%u frag=%u%s keyid=%d %s<=%s", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl), (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ? - " Retry" : ""); + " Retry" : "", + keyid, pn_hex, rsc_hex); wpa_hexdump(MSG_INFO, "RX PN", pn, 6); wpa_hexdump(MSG_INFO, "RSC", bss->rsc[keyid], 6); replay = 1; @@ -260,6 +282,11 @@ skip_replay_det: hdr, data, len, &dlen); if (decrypted) { + char gtk[65]; + + wpa_snprintf_hex(gtk, sizeof(gtk), bss->gtk[keyid], + bss->gtk_len[keyid]); + add_note(wt, MSG_EXCESSIVE, "GTK[%d] %s", keyid, gtk); rx_data_process(wt, bss->bssid, NULL, dst, src, decrypted, dlen, 1, NULL); if (!replay) @@ -451,14 +478,20 @@ static void rx_data_bss_prot(struct wlantest *wt, ccmp_get_pn(pn, data); if (os_memcmp(pn, rsc, 6) <= 0) { u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - add_note(wt, MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR - " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u%s", + char pn_hex[6 * 2 + 1], rsc_hex[6 * 2 + 1]; + + wpa_snprintf_hex(pn_hex, sizeof(pn_hex), pn, 6); + wpa_snprintf_hex(rsc_hex, sizeof(rsc_hex), rsc, 6); + add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR + " A2=" MACSTR " A3=" MACSTR + " seq=%u frag=%u%s keyid=%d tid=%d %s<=%s", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl), (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ? - " Retry" : ""); + " Retry" : "", + keyid, tid, pn_hex, rsc_hex); wpa_hexdump(MSG_INFO, "RX PN", pn, 6); wpa_hexdump(MSG_INFO, "RSC", rsc, 6); replay = 1; @@ -466,16 +499,22 @@ static void rx_data_bss_prot(struct wlantest *wt, skip_replay_det: if (tk) { - if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) + if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) { decrypted = ccmp_256_decrypt(tk, hdr, data, len, &dlen); - else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || - sta->pairwise_cipher == WPA_CIPHER_GCMP_256) + write_decrypted_note(wt, decrypted, tk, 32, keyid); + } else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || + sta->pairwise_cipher == WPA_CIPHER_GCMP_256) { decrypted = gcmp_decrypt(tk, sta->ptk.tk_len, hdr, data, len, &dlen); - else + write_decrypted_note(wt, decrypted, tk, sta->ptk.tk_len, + keyid); + } else { decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen); + write_decrypted_note(wt, decrypted, tk, 16, keyid); + } } else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) { decrypted = tkip_decrypt(sta->ptk.tk, hdr, data, len, &dlen); + write_decrypted_note(wt, decrypted, sta->ptk.tk, 32, keyid); } else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) { decrypted = wep_decrypt(wt, hdr, data, len, &dlen); } else if (sta->ptk_set) { @@ -489,14 +528,16 @@ skip_replay_det: else decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data, len, &dlen); + write_decrypted_note(wt, decrypted, sta->ptk.tk, + sta->ptk.tk_len, keyid); } else { - decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, - len, &dlen); + decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, keyid, + data, len, &dlen); ptk_iter_done = 1; } if (!decrypted && !ptk_iter_done) { - decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, - len, &dlen); + decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, keyid, + data, len, &dlen); if (decrypted) { add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs"); } From 3f10f716af1d0954f5955552c946137f7494a90c Mon Sep 17 00:00:00 2001 From: Andrej Shadura Date: Tue, 25 Feb 2020 17:08:32 +0100 Subject: [PATCH 0087/1105] common: Provide the BIT() macro locally wpa_ctrl.h can be installed separately with libwpa_client, so utils/common.h won't be available to its users. Signed-off-by: Andrej Shadura --- src/common/wpa_ctrl.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 48002be6c..12906708a 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -380,6 +380,10 @@ extern "C" { #define WDS_STA_INTERFACE_ADDED "WDS-STA-INTERFACE-ADDED " #define WDS_STA_INTERFACE_REMOVED "WDS-STA-INTERFACE-REMOVED " +#ifndef BIT +#define BIT(x) (1U << (x)) +#endif + /* BSS command information masks */ #define WPA_BSS_MASK_ALL 0xFFFDFFFF From 114d124186f652b3eb55d7dc00da740e4df756e0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 16:37:28 +0200 Subject: [PATCH 0088/1105] SAE: Fix PMKID derivation for OKC SAE authentication derives PMKID differently from the EAP cases. The value comes from information exchanged during SAE authentication and does not bind in the MAC addresses of the STAs. As such, the same PMKID is used with different BSSIDs. Fix both the hostapd and wpa_supplicant to use the previous PMKID as is for OKC instead of deriving a new PMKID using an incorrect derivation method when using an SAE AKM. This fixes use of opportunistic key caching with SAE. Signed-off-by: Jouni Malinen --- src/ap/pmksa_cache_auth.c | 5 +++++ src/rsn_supp/pmksa_cache.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c index 15e2c4943..fe5f81717 100644 --- a/src/ap/pmksa_cache_auth.c +++ b/src/ap/pmksa_cache_auth.c @@ -516,6 +516,11 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( for (entry = pmksa->pmksa; entry; entry = entry->next) { if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) continue; + if (wpa_key_mgmt_sae(entry->akmp)) { + if (os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) + return entry; + continue; + } rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, entry->akmp); if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index cd4b0508f..862fdec02 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -371,9 +371,12 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, { struct rsn_pmksa_cache_entry *new_entry; os_time_t old_expiration = old_entry->expiration; + const u8 *pmkid = NULL; + if (wpa_key_mgmt_sae(old_entry->akmp)) + pmkid = old_entry->pmkid; new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, - NULL, NULL, 0, + pmkid, NULL, 0, aa, pmksa->sm->own_addr, old_entry->network_ctx, old_entry->akmp, old_entry->fils_cache_id_set ? From bb93ea234e4bfb3589c0b79d60e56c76ae56fb13 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 17:26:36 +0200 Subject: [PATCH 0089/1105] SAE: Do not clone PMKSA entry for OKC after its reauth threshold Since SAE PMK can be updated only by going through a new SAE authentication instead of being able to update it during an association like EAP authentication, do not allow PMKSA entries to be used for OKC after the reauthentication threshold has been reached. This allows the PMK to be updated without having to force a disassociation when the PMK expires if the station roams between the reauthentication threshold and expiration timeout. Signed-off-by: Jouni Malinen --- src/rsn_supp/pmksa_cache.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index 862fdec02..c48cd318d 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -416,6 +416,20 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, while (entry) { if (entry->network_ctx == network_ctx && (!akmp || entry->akmp == akmp)) { + struct os_reltime now; + + if (wpa_key_mgmt_sae(entry->akmp) && + os_get_reltime(&now) == 0 && + entry->reauth_time < now.sec) { + wpa_printf(MSG_DEBUG, + "RSN: Do not clone PMKSA cache entry for " + MACSTR + " since its reauth threshold has passed", + MAC2STR(entry->aa)); + entry = entry->next; + continue; + } + entry = pmksa_cache_clone_entry(pmksa, entry, aa); if (entry) { wpa_printf(MSG_DEBUG, "RSN: added " From 74db49d74c4b6481b42c48e7a0577fa8087ccf3b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 17:41:07 +0200 Subject: [PATCH 0090/1105] SAE: Do not use PMKSA entry after its reauth threshold Since SAE PMK can be updated only by going through a new SAE authentication instead of being able to update it during an association like EAP authentication, do not allow PMKSA entries to be used for caching after the reauthentication threshold has been reached. This allows the PMK to be updated without having to force a disassociation when the PMK expires if the station roams between the reauthentication threshold and expiration timeout. Signed-off-by: Jouni Malinen --- src/rsn_supp/pmksa_cache.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index c48cd318d..9c970f811 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -533,6 +533,20 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, network_ctx, fils_cache_id); if (sm->cur_pmksa) { + struct os_reltime now; + + if (wpa_key_mgmt_sae(sm->cur_pmksa->akmp) && + os_get_reltime(&now) == 0 && + sm->cur_pmksa->reauth_time < now.sec) { + wpa_printf(MSG_DEBUG, + "RSN: Do not allow PMKSA cache entry for " + MACSTR + " to be used for SAE since its reauth threshold has passed", + MAC2STR(sm->cur_pmksa->aa)); + sm->cur_pmksa = NULL; + return -1; + } + wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID", sm->cur_pmksa->pmkid, PMKID_LEN); return 0; From fd1892885b3caef6108d52e738c20054bcb4d32a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 16:45:36 +0200 Subject: [PATCH 0091/1105] tests: SAE and opportunistic key caching and PMK lifetime Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 24 +++--- tests/hwsim/test_sae.py | 148 +++++++++++++++++++++++++++++++++++ tests/hwsim/wpasupplicant.py | 12 ++- 3 files changed, 169 insertions(+), 15 deletions(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index e28ddd57a..3153bff93 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -1906,7 +1906,7 @@ def test_ap_ft_oom(dev, apdev): """WPA2-PSK-FT and OOM""" dst = setup_ap_ft_oom(dev, apdev) with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"): - dev[0].roam(dst) + dev[0].roam(dst, check_bssid=False) def test_ap_ft_oom2(dev, apdev): """WPA2-PSK-FT and OOM (2)""" @@ -1949,7 +1949,7 @@ def test_ap_ft_ap_oom(dev, apdev): bssid1 = hapd1.own_addr() dev[0].scan_for_bss(bssid1, freq="2412") # This roam will fail due to missing PMK-R0 (OOM prevented storing it) - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) def test_ap_ft_ap_oom2(dev, apdev): """WPA2-PSK-FT and AP OOM 2""" @@ -1994,15 +1994,15 @@ def test_ap_ft_ap_oom3(dev, apdev): dev[0].scan_for_bss(bssid1, freq="2412") with alloc_fail(hapd1, 1, "wpa_ft_pull_pmk_r1"): # This will fail due to not being able to send out PMK-R1 pull request - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 2, "os_get_random;wpa_ft_pull_pmk_r1"): # This will fail due to not being able to send out PMK-R1 pull request - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 2, "aes_siv_encrypt;wpa_ft_pull_pmk_r1"): # This will fail due to not being able to send out PMK-R1 pull request - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) def test_ap_ft_ap_oom3b(dev, apdev): """WPA2-PSK-FT and AP OOM 3b""" @@ -2076,23 +2076,23 @@ def test_ap_ft_ap_oom5(dev, apdev): dev[0].scan_for_bss(bssid1, freq="2412") with alloc_fail(hapd1, 1, "=wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 1, "os_get_random;wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 1, "sha256_prf_bits;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 1, "wpa_derive_pmk_r1_name;wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) def test_ap_ft_ap_oom6(dev, apdev): """WPA2-PSK-FT and AP OOM 6""" @@ -2231,10 +2231,10 @@ def test_ap_ft_ap_oom8(dev, apdev): dev[0].scan_for_bss(bssid1, freq="2412") with fail_test(hapd1, 1, "wpa_derive_pmk_r0;wpa_ft_psk_pmk_r1"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 1, "wpa_derive_pmk_r1;wpa_ft_psk_pmk_r1"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) def test_ap_ft_ap_oom9(dev, apdev): """WPA2-PSK-FT and AP OOM 9""" diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index a55bd07ef..f6dff7314 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -2318,3 +2318,151 @@ def test_sae_forced_anti_clogging_h2e_loop(dev, apdev): finally: for i in range(2): dev[i].set("sae_pwe", "0") + +def test_sae_okc(dev, apdev): + """SAE and opportunistic key caching""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params['okc'] = '1' + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + dev[0].set("sae_groups", "") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", + okc=True, scan_freq="2412") + dev[0].dump_monitor() + hapd.wait_sta() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used") + + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid2, freq=2412) + dev[0].roam(bssid2) + dev[0].dump_monitor() + hapd2.wait_sta() + if "sae_group" in dev[0].get_status(): + raise Exception("SAE authentication used during roam to AP2") + + dev[0].roam(bssid) + dev[0].dump_monitor() + hapd.wait_sta() + if "sae_group" in dev[0].get_status(): + raise Exception("SAE authentication used during roam to AP1") + +def test_sae_okc_sta_only(dev, apdev): + """SAE and opportunistic key caching only on STA""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + dev[0].set("sae_groups", "") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", + okc=True, scan_freq="2412") + dev[0].dump_monitor() + hapd.wait_sta() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used") + + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid2, freq=2412) + dev[0].roam(bssid2, assoc_reject_ok=True) + dev[0].dump_monitor() + hapd2.wait_sta() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used during roam to AP2") + +def test_sae_okc_pmk_lifetime(dev, apdev): + """SAE and opportunistic key caching and PMK lifetime""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params['okc'] = '1' + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + dev[0].set("sae_groups", "") + dev[0].set("dot11RSNAConfigPMKLifetime", "10") + dev[0].set("dot11RSNAConfigPMKReauthThreshold", "30") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", + okc=True, scan_freq="2412") + dev[0].dump_monitor() + hapd.wait_sta() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used") + + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + time.sleep(5) + dev[0].scan_for_bss(bssid2, freq=2412) + dev[0].roam(bssid2) + dev[0].dump_monitor() + hapd2.wait_sta() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used during roam to AP2 after reauth threshold") + +def test_sae_pmk_lifetime(dev, apdev): + """SAE and opportunistic key caching and PMK lifetime""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + dev[0].set("sae_groups", "") + dev[0].set("dot11RSNAConfigPMKLifetime", "10") + dev[0].set("dot11RSNAConfigPMKReauthThreshold", "50") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", + scan_freq="2412") + dev[0].dump_monitor() + hapd.wait_sta() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used") + + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid2, freq=2412) + dev[0].roam(bssid2) + dev[0].dump_monitor() + hapd2.wait_sta() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used during roam to AP2") + + dev[0].roam(bssid) + dev[0].dump_monitor() + hapd.wait_sta() + if "sae_group" in dev[0].get_status(): + raise Exception("SAE authentication used during roam to AP1") + + time.sleep(6) + dev[0].scan_for_bss(bssid2, freq=2412) + dev[0].roam(bssid2) + dev[0].dump_monitor() + hapd2.wait_sta() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used during roam to AP2 after reauth threshold") + + ev = dev[0].wait_event(["PMKSA-CACHE-REMOVED"], 11) + if ev is None: + raise Exception("PMKSA cache entry did not expire") + if bssid2 not in ev: + ev = dev[0].wait_event(["PMKSA-CACHE-REMOVED"], 11) + if ev is None: + raise Exception("PMKSA cache entry did not expire") + if bssid2 not in ev: + raise Exception("PMKSA cache entry for the current AP did not expire") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], 1) + if ev is None: + raise Exception("Disconnection not reported after PMKSA cache entry expiration") + + dev[0].wait_connected() + if "sae_group" not in dev[0].get_status(): + raise Exception("SAE authentication not used after PMKSA cache entry expiration") diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index d1c249328..227cf72a4 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1191,7 +1191,8 @@ class WpaSupplicant: "CTRL-EVENT-SCAN-RESULTS"], timeout=0.5) self.dump_monitor() - def roam(self, bssid, fail_test=False, assoc_reject_ok=False): + def roam(self, bssid, fail_test=False, assoc_reject_ok=False, + check_bssid=True): self.dump_monitor() if "OK" not in self.request("ROAM " + bssid): raise Exception("ROAM failed") @@ -1205,13 +1206,18 @@ class WpaSupplicant: raise Exception("Unexpected connection") self.dump_monitor() return - ev = self.wait_event(["CTRL-EVENT-CONNECTED", - "CTRL-EVENT-ASSOC-REJECT"], timeout=10) + if assoc_reject_ok: + ev = self.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10) + else: + ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-ASSOC-REJECT"], timeout=10) if ev is None: raise Exception("Roaming with the AP timed out") if "CTRL-EVENT-ASSOC-REJECT" in ev: raise Exception("Roaming association rejected") self.dump_monitor() + if check_bssid and self.get_status_field('bssid') != bssid: + raise Exception("Did not roam to correct BSSID") def roam_over_ds(self, bssid, fail_test=False): self.dump_monitor() From 54bc5db16e8dfc99ebb4b97391324cfec72ba997 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 19:53:45 +0200 Subject: [PATCH 0092/1105] tests: sigma_dut controlled AP with SAE H2E and anti-clogging token Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 89d96d164..0e6dc6fbf 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3809,3 +3809,27 @@ def test_sigma_dut_ap_sae_h2e_group_rejection(dev, apdev, params): finally: stop_sigma_dut(sigma) dev[0].set("sae_pwe", "0") + +def test_sigma_dut_ap_sae_h2e_anti_clogging(dev, apdev, params): + """sigma_dut controlled AP with SAE H2E and anti-clogging token""" + logdir = os.path.join(params['logdir'], + "sigma_dut_ap_sae_h2e_anti_clogging.sigma-hostapd") + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, sae_h2e=True, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,SAE,PSK,12345678,AntiCloggingThreshold,0") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + dev[0].set("sae_groups", "") + dev[0].set("sae_pwe", "2") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", scan_freq="2412") + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + dev[0].set("sae_pwe", "0") From 167205d455cef9832c5dfc887afb22a7f2f2d8a8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 22:54:36 +0200 Subject: [PATCH 0093/1105] os_unix: Seed random() for os_random() While the users of os_random() do not really need strong pseudo random numebrs, there is no significant harm in seeding random() with data from os_get_random(), i.e., /dev/urandom, to get different sequence of not so strong pseudo random values from os_random() for each time the process is started. Signed-off-by: Jouni Malinen --- src/utils/os_unix.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c index dd504f3ab..fc1110b3c 100644 --- a/src/utils/os_unix.c +++ b/src/utils/os_unix.c @@ -337,6 +337,8 @@ char * os_rel2abs_path(const char *rel_path) int os_program_init(void) { + unsigned int seed; + #ifdef ANDROID /* * We ignore errors here since errors are normal if we @@ -365,6 +367,9 @@ int os_program_init(void) capset(&header, &cap); #endif /* ANDROID */ + os_get_random((unsigned char *) &seed, sizeof(seed)); + srandom(seed); + return 0; } From f5f7286ba594d2cf8c18184363d580ea95f63230 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 23:18:59 +0200 Subject: [PATCH 0094/1105] wlantest: Try to decrypt frame with zero TK If none of the known PTKs have a working TK, check whether an encrypted frame is encrypted with all zeros TK. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 69 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index 63da868d3..f0f0df95c 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -132,6 +132,38 @@ static void write_decrypted_note(struct wlantest *wt, const u8 *decrypted, } +static u8 * try_ptk(int pairwise_cipher, struct wpa_ptk *ptk, + const struct ieee80211_hdr *hdr, + const u8 *data, size_t data_len, size_t *decrypted_len) +{ + u8 *decrypted; + unsigned int tk_len = ptk->tk_len; + + decrypted = NULL; + if ((pairwise_cipher == WPA_CIPHER_CCMP || + pairwise_cipher == 0) && tk_len == 16) { + decrypted = ccmp_decrypt(ptk->tk, hdr, data, + data_len, decrypted_len); + } else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 || + pairwise_cipher == 0) && tk_len == 32) { + decrypted = ccmp_256_decrypt(ptk->tk, hdr, data, + data_len, decrypted_len); + } else if ((pairwise_cipher == WPA_CIPHER_GCMP || + pairwise_cipher == WPA_CIPHER_GCMP_256 || + pairwise_cipher == 0) && + (tk_len == 16 || tk_len == 32)) { + decrypted = gcmp_decrypt(ptk->tk, tk_len, hdr, + data, data_len, decrypted_len); + } else if ((pairwise_cipher == WPA_CIPHER_TKIP || + pairwise_cipher == 0) && tk_len == 32) { + decrypted = tkip_decrypt(ptk->tk, hdr, data, data_len, + decrypted_len); + } + + return decrypted; +} + + static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, const struct ieee80211_hdr *hdr, int keyid, const u8 *data, size_t data_len, size_t *decrypted_len) @@ -142,27 +174,8 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, wpa_debug_level = MSG_WARNING; dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) { - unsigned int tk_len = ptk->ptk_len - 32; - decrypted = NULL; - if ((pairwise_cipher == WPA_CIPHER_CCMP || - pairwise_cipher == 0) && tk_len == 16) { - decrypted = ccmp_decrypt(ptk->ptk.tk, hdr, data, - data_len, decrypted_len); - } else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 || - pairwise_cipher == 0) && tk_len == 32) { - decrypted = ccmp_256_decrypt(ptk->ptk.tk, hdr, data, - data_len, decrypted_len); - } else if ((pairwise_cipher == WPA_CIPHER_GCMP || - pairwise_cipher == WPA_CIPHER_GCMP_256 || - pairwise_cipher == 0) && - (tk_len == 16 || tk_len == 32)) { - decrypted = gcmp_decrypt(ptk->ptk.tk, tk_len, hdr, - data, data_len, decrypted_len); - } else if ((pairwise_cipher == WPA_CIPHER_TKIP || - pairwise_cipher == 0) && tk_len == 32) { - decrypted = tkip_decrypt(ptk->ptk.tk, hdr, data, - data_len, decrypted_len); - } + decrypted = try_ptk(pairwise_cipher, &ptk->ptk, hdr, + data, data_len, decrypted_len); if (decrypted) { wpa_debug_level = prev_level; add_note(wt, MSG_DEBUG, @@ -542,6 +555,20 @@ skip_replay_det: add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs"); } } + if (!decrypted) { + struct wpa_ptk zero_ptk; + + os_memset(&zero_ptk, 0, sizeof(zero_ptk)); + zero_ptk.tk_len = wpa_cipher_key_len(sta->pairwise_cipher); + decrypted = try_ptk(sta->pairwise_cipher, &zero_ptk, hdr, + data, len, &dlen); + if (decrypted) { + add_note(wt, MSG_DEBUG, + "Frame was encrypted with zero TK"); + write_decrypted_note(wt, decrypted, zero_ptk.tk, + zero_ptk.tk_len, keyid); + } + } if (decrypted) { u16 fc = le_to_host16(hdr->frame_control); const u8 *peer_addr = NULL; From 9551930f1eef45dfbc4303b338f4690314867ee1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 23:19:52 +0200 Subject: [PATCH 0095/1105] tests: Initialize wlantest with passphrase for ap_wpa2_ptk_rekey Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_psk.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index 2f2a354a5..12274fdd0 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -23,7 +23,7 @@ from utils import HwsimSkip, fail_test, skip_with_fips, start_monitor, stop_moni import hwsim_utils from wpasupplicant import WpaSupplicant from tshark import run_tshark -from wlantest import WlantestCapture +from wlantest import WlantestCapture, Wlantest def check_mib(dev, vals): mib = dev.get_mib() @@ -210,6 +210,12 @@ def test_ap_wpa2_ptk_rekey(dev, apdev): passphrase = 'qwertyuiop' params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) hapd = hostapd.add_ap(apdev[0], params) + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase(passphrase) + dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412") ev = dev[0].wait_event(["WPA: Key negotiation completed", "CTRL-EVENT-DISCONNECTED"]) From a62d7618566e5ddc5db3d5d588de8ab96d666852 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 29 Feb 2020 00:32:13 +0200 Subject: [PATCH 0096/1105] ACS: Fix spelling of "interference" Signed-off-by: Jouni Malinen --- src/ap/acs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index 232afa890..52e8f2cc4 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -489,7 +489,7 @@ static int is_in_chanlist(struct hostapd_iface *iface, } -static void acs_survey_all_chans_intereference_factor( +static void acs_survey_all_chans_interference_factor( struct hostapd_iface *iface) { int i; @@ -566,7 +566,7 @@ static int is_common_24ghz_chan(int chan) #endif /* ACS_24GHZ_PREFER_1_6_11 */ /* - * At this point it's assumed chan->interface_factor has been computed. + * At this point it's assumed chan->interference_factor has been computed. * This function should be reusable regardless of interference computation * option (survey, BSS, spectral, ...). chan->interference factor must be * summable (i.e., must be always greater than zero). @@ -826,7 +826,7 @@ static int acs_study_survey_based(struct hostapd_iface *iface) return -1; } - acs_survey_all_chans_intereference_factor(iface); + acs_survey_all_chans_interference_factor(iface); return 0; } From 499c37b7295a8da90b82fb4dcf0c80012058b5b9 Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0097/1105] ACS: Extend hostapd_get_mode_channel() to find from any mode This is preparation for being able to support hw_mode=any to select the best channel from any supported mode. Signed-off-by: Neo Jou --- src/ap/drv_callbacks.c | 24 +++++++++++++++++++++--- src/ap/hw_features.c | 17 +++++++++++++++++ src/ap/hw_features.h | 8 ++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 61e56b6e5..bde2d9302 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1429,15 +1429,33 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, #endif /* HOSTAPD */ +static struct hostapd_channel_data * +hostapd_get_mode_chan(struct hostapd_hw_modes *mode, unsigned int freq) +{ + int i; + struct hostapd_channel_data *chan; + + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; + if ((unsigned int) chan->freq == freq) + return chan; + } + + return NULL; +} + + static struct hostapd_channel_data * hostapd_get_mode_channel( struct hostapd_iface *iface, unsigned int freq) { int i; struct hostapd_channel_data *chan; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; - if ((unsigned int) chan->freq == freq) + for (i = 0; i < iface->num_hw_features; i++) { + if (hostapd_hw_skip_mode(iface, &iface->hw_features[i])) + continue; + chan = hostapd_get_mode_chan(&iface->hw_features[i], freq); + if (chan) return chan; } diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 0b922b9c3..f550bfe5e 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -1085,3 +1085,20 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) } return 0; } + + +int hostapd_hw_skip_mode(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode) +{ + int i; + + if (iface->current_mode) + return mode != iface->current_mode; + if (mode->mode != HOSTAPD_MODE_IEEE80211B) + return 0; + for (i = 0; i < iface->num_hw_features; i++) { + if (iface->hw_features[i].mode == HOSTAPD_MODE_IEEE80211G) + return 1; + } + return 0; +} diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h index 67493193a..dd24f95b2 100644 --- a/src/ap/hw_features.h +++ b/src/ap/hw_features.h @@ -25,6 +25,8 @@ int hostapd_check_edmg_capab(struct hostapd_iface *iface); int hostapd_prepare_rates(struct hostapd_iface *iface, struct hostapd_hw_modes *mode); void hostapd_stop_setup_timers(struct hostapd_iface *iface); +int hostapd_hw_skip_mode(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode); #else /* NEED_AP_MLME */ static inline void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, @@ -77,6 +79,12 @@ static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface) { } +static inline int hostapd_hw_skip_mode(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode) +{ + return 0; +} + #endif /* NEED_AP_MLME */ #endif /* HW_FEATURES_H */ From 3d09be41a893e185e6aff7577e646310a7988a68 Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0098/1105] ACS: Clear all modes in acs_cleanup() This is preparation for being able to support hw_mode=any to select the best channel from any supported mode. Signed-off-by: Neo Jou --- src/ap/acs.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index 52e8f2cc4..ab3f17ea2 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -261,13 +261,13 @@ static void acs_clean_chan_surveys(struct hostapd_channel_data *chan) } -void acs_cleanup(struct hostapd_iface *iface) +static void acs_cleanup_mode(struct hostapd_hw_modes *mode) { int i; struct hostapd_channel_data *chan; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED) acs_clean_chan_surveys(chan); @@ -276,6 +276,15 @@ void acs_cleanup(struct hostapd_iface *iface) chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED; chan->min_nf = 0; } +} + + +void acs_cleanup(struct hostapd_iface *iface) +{ + int i; + + for (i = 0; i < iface->num_hw_features; i++) + acs_cleanup_mode(&iface->hw_features[i]); iface->chans_surveyed = 0; iface->acs_num_completed_scans = 0; From 4c1ffb45e48296bcf1151888ff4d7c8f0f666a2b Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0099/1105] ACS: Extend acs_surveys_are_sufficient() for all modes This is preparation for being able to support hw_mode=any to select the best channel from any supported mode. Signed-off-by: Neo Jou --- src/ap/acs.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index ab3f17ea2..8b6686e85 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -462,21 +462,35 @@ static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan) } -static int acs_surveys_are_sufficient(struct hostapd_iface *iface) +static int acs_surveys_are_sufficient_mode(struct hostapd_hw_modes *mode) { int i; struct hostapd_channel_data *chan; - int valid = 0; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && acs_survey_list_is_sufficient(chan)) - valid++; + return 1; } - /* We need at least survey data for one channel */ - return !!valid; + return 0; +} + + +static int acs_surveys_are_sufficient(struct hostapd_iface *iface) +{ + int i; + struct hostapd_hw_modes *mode; + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode) && + acs_surveys_are_sufficient_mode(mode)) + return 1; + } + + return 0; } From 070522e5b2b596ab443e60f06cd85b0d9b40872e Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0100/1105] ACS: Extend acs_find_chan() for all modes This is preparation for being able to support hw_mode=any to select the best channel from any supported mode. Signed-off-by: Neo Jou --- src/ap/acs.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index 8b6686e85..2a1876936 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -538,14 +538,14 @@ static void acs_survey_all_chans_interference_factor( } -static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, - int freq) +static struct hostapd_channel_data * +acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq) { struct hostapd_channel_data *chan; int i; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; @@ -558,6 +558,26 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, } +static struct hostapd_channel_data * +acs_find_chan(struct hostapd_iface *iface, int freq) +{ + int i; + struct hostapd_hw_modes *mode; + struct hostapd_channel_data *chan; + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) { + chan = acs_find_chan_mode(mode, freq); + if (chan) + return chan; + } + } + + return NULL; +} + + static int is_24ghz_mode(enum hostapd_hw_mode mode) { return mode == HOSTAPD_MODE_IEEE80211B || From f3c44a196ff7455e3f4671a4f674b9fe26d5fd24 Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0101/1105] ACS: Extend interference factor calculation for all modes This is preparation for being able to support hw_mode=any to select the best channel from any supported mode. Signed-off-by: Neo Jou --- src/ap/acs.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index 2a1876936..6554ec239 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -512,14 +512,14 @@ static int is_in_chanlist(struct hostapd_iface *iface, } -static void acs_survey_all_chans_interference_factor( - struct hostapd_iface *iface) +static void acs_survey_mode_interference_factor( + struct hostapd_iface *iface, struct hostapd_hw_modes *mode) { int i; struct hostapd_channel_data *chan; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (!acs_usable_chan(chan)) continue; @@ -538,6 +538,20 @@ static void acs_survey_all_chans_interference_factor( } +static void acs_survey_all_chans_interference_factor( + struct hostapd_iface *iface) +{ + int i; + struct hostapd_hw_modes *mode; + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) + acs_survey_mode_interference_factor(iface, mode); + } +} + + static struct hostapd_channel_data * acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq) { From 141a8815e71ba52543cead6523213880fc42ba05 Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0102/1105] ACS: Extend acs_request_scan() to support multiple modes Add suitable channel frequencies from all modes into the scan parameters when a single mode is not specified for ACS. This is preparation for being able to support hw_mode=any to select the best channel from any supported mode. Signed-off-by: Neo Jou --- src/ap/acs.c | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index 6554ec239..7357a4154 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -975,21 +975,15 @@ fail: } -static int acs_request_scan(struct hostapd_iface *iface) +static int * acs_request_scan_add_freqs(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode, + int *freq) { - struct wpa_driver_scan_params params; struct hostapd_channel_data *chan; - int i, *freq; + int i; - os_memset(¶ms, 0, sizeof(params)); - params.freqs = os_calloc(iface->current_mode->num_channels + 1, - sizeof(params.freqs[0])); - if (params.freqs == NULL) - return -1; - - freq = params.freqs; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; @@ -998,6 +992,39 @@ static int acs_request_scan(struct hostapd_iface *iface) *freq++ = chan->freq; } + + return freq; +} + + +static int acs_request_scan(struct hostapd_iface *iface) +{ + struct wpa_driver_scan_params params; + int i, *freq; + int num_channels; + struct hostapd_hw_modes *mode; + + os_memset(¶ms, 0, sizeof(params)); + + num_channels = 0; + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) + num_channels += mode->num_channels; + } + + params.freqs = os_calloc(num_channels + 1, sizeof(params.freqs[0])); + if (params.freqs == NULL) + return -1; + + freq = params.freqs; + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) + freq = acs_request_scan_add_freqs(iface, mode, freq); + } + *freq = 0; if (params.freqs == freq) { From c60362e6e8409d9530efdf17392f3125db066e28 Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0103/1105] ACS: Extend acs_find_ideal_chan() to support multiple modes This is preparation for being able to support hw_mode=any to select the best channel from any supported mode. Signed-off-by: Neo Jou --- src/ap/acs.c | 131 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 54 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index 7357a4154..ecd42d877 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -622,58 +622,24 @@ static int is_common_24ghz_chan(int chan) #define ACS_24GHZ_PREFER_1_6_11 0.8 #endif /* ACS_24GHZ_PREFER_1_6_11 */ -/* - * At this point it's assumed chan->interference_factor has been computed. - * This function should be reusable regardless of interference computation - * option (survey, BSS, spectral, ...). chan->interference factor must be - * summable (i.e., must be always greater than zero). - */ -static struct hostapd_channel_data * -acs_find_ideal_chan(struct hostapd_iface *iface) +static void +acs_find_ideal_chan_mode(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode, + int n_chans, u32 bw, + struct hostapd_channel_data **rand_chan, + struct hostapd_channel_data **ideal_chan, + long double *ideal_factor) { - struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL, - *rand_chan = NULL; - long double factor, ideal_factor = 0; + struct hostapd_channel_data *chan, *adj_chan = NULL; + long double factor; int i, j; - int n_chans = 1; - u32 bw; unsigned int k; - /* TODO: HT40- support */ - - if (iface->conf->ieee80211n && - iface->conf->secondary_channel == -1) { - wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+"); - return NULL; - } - - if (iface->conf->ieee80211n && - iface->conf->secondary_channel) - n_chans = 2; - - if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { - switch (hostapd_get_oper_chwidth(iface->conf)) { - case CHANWIDTH_80MHZ: - n_chans = 4; - break; - case CHANWIDTH_160MHZ: - n_chans = 8; - break; - } - } - - bw = num_chan_to_bw(n_chans); - - /* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */ - - wpa_printf(MSG_DEBUG, - "ACS: Survey analysis for selected bandwidth %d MHz", bw); - - for (i = 0; i < iface->current_mode->num_channels; i++) { + for (i = 0; i < mode->num_channels; i++) { double total_weight; struct acs_bias *bias, tmp_bias; - chan = &iface->current_mode->channels[i]; + chan = &mode->channels[i]; /* Since in the current ACS implementation the first channel is * always a primary channel, skip channels not available as @@ -694,7 +660,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) /* HT40 on 5 GHz has a limited set of primary channels as per * 11n Annex J */ - if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && + if (mode->mode == HOSTAPD_MODE_IEEE80211A && iface->conf->ieee80211n && iface->conf->secondary_channel && !acs_usable_ht40_chan(chan)) { @@ -703,7 +669,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) continue; } - if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && + if (mode->mode == HOSTAPD_MODE_IEEE80211A && (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) { if (hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80MHZ && @@ -755,7 +721,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent * channel interference factor. */ - if (is_24ghz_mode(iface->current_mode->mode)) { + if (is_24ghz_mode(mode->mode)) { for (j = 0; j < n_chans; j++) { adj_chan = acs_find_chan(iface, chan->freq + (j * 20) - 5); @@ -801,7 +767,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) break; bias = NULL; } - } else if (is_24ghz_mode(iface->current_mode->mode) && + } else if (is_24ghz_mode(mode->mode) && is_common_24ghz_chan(chan->chan)) { tmp_bias.channel = chan->chan; tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11; @@ -820,14 +786,71 @@ acs_find_ideal_chan(struct hostapd_iface *iface) } if (acs_usable_chan(chan) && - (!ideal_chan || factor < ideal_factor)) { - ideal_factor = factor; - ideal_chan = chan; + (!*ideal_chan || factor < *ideal_factor)) { + *ideal_factor = factor; + *ideal_chan = chan; } /* This channel would at least be usable */ - if (!rand_chan) - rand_chan = chan; + if (!(*rand_chan)) + *rand_chan = chan; + } +} + + +/* + * At this point it's assumed chan->interference_factor has been computed. + * This function should be reusable regardless of interference computation + * option (survey, BSS, spectral, ...). chan->interference factor must be + * summable (i.e., must be always greater than zero). + */ +static struct hostapd_channel_data * +acs_find_ideal_chan(struct hostapd_iface *iface) +{ + struct hostapd_channel_data *ideal_chan = NULL, + *rand_chan = NULL; + long double ideal_factor = 0; + int i; + int n_chans = 1; + u32 bw; + struct hostapd_hw_modes *mode; + + /* TODO: HT40- support */ + + if (iface->conf->ieee80211n && + iface->conf->secondary_channel == -1) { + wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+"); + return NULL; + } + + if (iface->conf->ieee80211n && + iface->conf->secondary_channel) + n_chans = 2; + + if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { + switch (hostapd_get_oper_chwidth(iface->conf)) { + case CHANWIDTH_80MHZ: + n_chans = 4; + break; + case CHANWIDTH_160MHZ: + n_chans = 8; + break; + } + } + + bw = num_chan_to_bw(n_chans); + + /* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */ + + wpa_printf(MSG_DEBUG, + "ACS: Survey analysis for selected bandwidth %d MHz", bw); + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) + acs_find_ideal_chan_mode(iface, mode, n_chans, bw, + &rand_chan, &ideal_chan, + &ideal_factor); } if (ideal_chan) { From d07f1ade9001239cb8fdb6153e6bd524234bea83 Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0104/1105] ACS: Determine mode when using hw_mode=any Set iface->current_mode and iface->conf->hw_mode when completing ACS based on the selected channel in the hw_mode=any case. Signed-off-by: Neo Jou --- src/ap/hw_features.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index f550bfe5e..72de45cac 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -879,10 +879,43 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface) } +static void hostapd_determine_mode(struct hostapd_iface *iface) +{ + int i; + enum hostapd_hw_mode target_mode; + + if (iface->current_mode || + iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY) + return; + + if (iface->freq < 4000) + target_mode = HOSTAPD_MODE_IEEE80211G; + else if (iface->freq > 50000) + target_mode = HOSTAPD_MODE_IEEE80211AD; + else + target_mode = HOSTAPD_MODE_IEEE80211A; + + for (i = 0; i < iface->num_hw_features; i++) { + struct hostapd_hw_modes *mode; + + mode = &iface->hw_features[i]; + if (mode->mode == target_mode) { + iface->current_mode = mode; + iface->conf->hw_mode = mode->mode; + break; + } + } + + if (!iface->current_mode) + wpa_printf(MSG_ERROR, "ACS: Cannot decide mode"); +} + + static enum hostapd_chan_status hostapd_check_chans(struct hostapd_iface *iface) { if (iface->freq) { + hostapd_determine_mode(iface); if (hostapd_is_usable_chans(iface)) return HOSTAPD_CHAN_VALID; else From b7f1d4f4d63b9a94daa31b01e4688400136e8bf4 Mon Sep 17 00:00:00 2001 From: Neo Jou Date: Mon, 13 Jan 2020 16:31:28 +0800 Subject: [PATCH 0105/1105] ACS: Allow hw_mode=any to be used with internal ACS algorithm This was already supported in the offload ACS case and this commit completes support for this with the internal ACS algorithm. Signed-off-by: Neo Jou --- src/ap/acs.c | 3 ++- src/ap/hw_features.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index ecd42d877..5c0161070 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -1085,7 +1085,8 @@ enum hostapd_chan_status acs_init(struct hostapd_iface *iface) return HOSTAPD_CHAN_ACS; } - if (!iface->current_mode) + if (!iface->current_mode && + iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY) return HOSTAPD_CHAN_INVALID; acs_cleanup(iface); diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 72de45cac..b73cc88e0 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -1041,9 +1041,15 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface) } if (iface->current_mode == NULL) { - if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) || - !(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) - { + if ((iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && + (iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) { + wpa_printf(MSG_DEBUG, + "Using offloaded hw_mode=any ACS"); + } else if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && + iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211ANY) { + wpa_printf(MSG_DEBUG, + "Using internal ACS for hw_mode=any"); + } else { wpa_printf(MSG_ERROR, "Hardware does not support configured mode"); hostapd_logger(iface->bss[0], NULL, From 886ee6775ff16d1aced46b4aeeb4684627c016d4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 28 Feb 2020 16:15:24 +0200 Subject: [PATCH 0106/1105] tests: Automatic channel selection with hw_mode=any Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_acs.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index fe88d0171..866fd725c 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -515,3 +515,39 @@ def test_ap_acs_vht160_dfs(dev, apdev, params): hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', '00']) dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) dev[0].flush_scan_cache() + +def test_ap_acs_hw_mode_any(dev, apdev): + """Automatic channel selection with hw_mode=any""" + force_prev_ap_on_24g(apdev[0]) + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['channel'] = '0' + params['hw_mode'] = 'any' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + wait_acs(hapd) + + freq = hapd.get_status_field("freq") + if int(freq) < 2400: + raise Exception("Unexpected frequency") + + dev[0].connect("test-acs", psk="12345678", scan_freq=freq) + +def test_ap_acs_hw_mode_any_5ghz(dev, apdev): + """Automatic channel selection with hw_mode=any and 5 GHz""" + try: + hapd = None + force_prev_ap_on_5g(apdev[0]) + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['hw_mode'] = 'any' + params['channel'] = '0' + params['country_code'] = 'US' + params['acs_chan_bias'] = '36:0.7 40:0.7 44:0.7 48:0.7' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + wait_acs(hapd) + freq = hapd.get_status_field("freq") + if int(freq) < 5000: + raise Exception("Unexpected frequency") + + dev[0].connect("test-acs", psk="12345678", scan_freq=freq) + dev[0].wait_regdom(country_ie=True) + finally: + clear_regdom(hapd, dev) From bca44f4e4ed5a3c63cc5cebd9c85ffe4299f6db6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 29 Feb 2020 16:56:01 +0200 Subject: [PATCH 0107/1105] WPS: Remove static-WEP-only workaround WEP provisioning was removed from WPS v2, so this workaround functionality has not been applicable. Remove it completely. Signed-off-by: Jouni Malinen --- src/ap/wps_hostapd.c | 2 -- src/wps/wps.h | 5 ----- src/wps/wps_registrar.c | 24 ------------------------ 3 files changed, 31 deletions(-) diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 5ea206c5e..165d0de9e 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -1260,8 +1260,6 @@ int hostapd_init_wps(struct hostapd_data *hapd, cfg.extra_cred_len = conf->extra_cred_len; cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) && conf->skip_cred_build; - if (conf->ssid.security_policy == SECURITY_STATIC_WEP) - cfg.static_wep_only = 1; cfg.dualband = interface_count(hapd->iface) > 1; if ((wps->dev.rf_bands & (WPS_RF_50GHZ | WPS_RF_24GHZ)) == (WPS_RF_50GHZ | WPS_RF_24GHZ)) diff --git a/src/wps/wps.h b/src/wps/wps.h index 3b56da74d..93888b011 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -394,11 +394,6 @@ struct wps_registrar_config { */ int disable_auto_conf; - /** - * static_wep_only - Whether the BSS supports only static WEP - */ - int static_wep_only; - /** * dualband - Whether this is a concurrent dualband AP */ diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index fb6c71d7e..d71a54315 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -173,7 +173,6 @@ struct wps_registrar { int sel_reg_union; int sel_reg_dev_password_id_override; int sel_reg_config_methods_override; - int static_wep_only; int dualband; int force_per_enrollee_psk; @@ -697,7 +696,6 @@ wps_registrar_init(struct wps_context *wps, reg->disable_auto_conf = cfg->disable_auto_conf; reg->sel_reg_dev_password_id_override = -1; reg->sel_reg_config_methods_override = -1; - reg->static_wep_only = cfg->static_wep_only; reg->dualband = cfg->dualband; reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk; @@ -1390,28 +1388,6 @@ static int wps_set_ie(struct wps_registrar *reg) return -1; } - if (reg->static_wep_only) { - /* - * Windows XP and Vista clients can get confused about - * EAP-Identity/Request when they probe the network with - * EAPOL-Start. In such a case, they may assume the network is - * using IEEE 802.1X and prompt user for a certificate while - * the correct (non-WPS) behavior would be to ask for the - * static WEP key. As a workaround, use Microsoft Provisioning - * IE to advertise that legacy 802.1X is not supported. - */ - const u8 ms_wps[7] = { - WLAN_EID_VENDOR_SPECIFIC, 5, - /* Microsoft Provisioning IE (00:50:f2:5) */ - 0x00, 0x50, 0xf2, 5, - 0x00 /* no legacy 802.1X or MS WPS */ - }; - wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE " - "into Beacon/Probe Response frames"); - wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps)); - wpabuf_put_data(probe, ms_wps, sizeof(ms_wps)); - } - return wps_cb_set_ie(reg, beacon, probe); } From 200c7693c9a145508b1850befb200430c1c6a984 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 29 Feb 2020 16:52:39 +0200 Subject: [PATCH 0108/1105] Make WEP functionality an optional build parameter WEP should not be used for anything anymore. As a step towards removing it completely, move all WEP related functionality to be within CONFIG_WEP blocks. This will be included in builds only if CONFIG_WEP=y is explicitly set in build configuration. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 4 +++ hostapd/Makefile | 4 +++ hostapd/android.config | 8 ++++++ hostapd/config_file.c | 6 +++++ hostapd/defconfig | 8 ++++++ src/ap/ap_config.c | 22 ++++++++++++++++ src/ap/ap_config.h | 8 ++++++ src/ap/beacon.c | 5 +++- src/ap/hostapd.c | 20 ++++++++++++++ src/ap/ieee802_11.c | 10 ++++++- src/ap/ieee802_1x.c | 19 +++++++++++++- src/ap/vlan_init.c | 5 +++- src/ap/wps_hostapd.c | 4 +++ src/common/wpa_common.c | 4 +++ src/eapol_auth/eapol_auth_sm.c | 14 ++++++++++ src/eapol_supp/eapol_supp_sm.c | 2 ++ tests/hwsim/example-hostapd.config | 1 + tests/hwsim/example-wpa_supplicant.config | 1 + tests/hwsim/test_ap_config.py | 22 +++++++++------- tests/hwsim/test_ap_hs20.py | 5 ++-- tests/hwsim/test_ap_params.py | 3 +++ tests/hwsim/test_ap_tdls.py | 3 +++ tests/hwsim/test_ap_wps.py | 2 ++ tests/hwsim/test_cfg80211.py | 2 ++ tests/hwsim/test_connect_cmd.py | 13 ++++++--- tests/hwsim/test_ibss.py | 4 +++ tests/hwsim/test_ieee8021x.py | 8 ++++++ tests/hwsim/test_radius.py | 2 ++ tests/hwsim/test_scan.py | 2 ++ tests/hwsim/test_wep.py | 15 ++++++++++- tests/hwsim/test_wext.py | 3 +++ tests/hwsim/test_wpas_ap.py | 25 ++++++++++-------- tests/hwsim/test_wpas_ctrl.py | 22 +++++++++------- wpa_supplicant/Android.mk | 4 +++ wpa_supplicant/Makefile | 4 +++ wpa_supplicant/android.config | 8 ++++++ wpa_supplicant/ap.c | 10 ++++--- wpa_supplicant/config.c | 6 +++++ wpa_supplicant/config_file.c | 32 ++++++++++++++++++----- wpa_supplicant/config_ssid.h | 2 ++ wpa_supplicant/config_winreg.c | 16 +++++++++--- wpa_supplicant/ctrl_iface.c | 6 +++++ wpa_supplicant/dbus/dbus_new_handlers.c | 15 ++++++++--- wpa_supplicant/defconfig | 8 ++++++ wpa_supplicant/events.c | 16 ++++++++++++ wpa_supplicant/sme.c | 18 ++++++++----- wpa_supplicant/wpa_supplicant.c | 32 ++++++++++++++++++----- wpa_supplicant/wpas_glue.c | 4 +++ 48 files changed, 386 insertions(+), 71 deletions(-) diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 662a6cd18..fce40620f 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -309,6 +309,10 @@ OBJS += src/fst/fst_ctrl_iface.c endif endif +ifdef CONFIG_WEP +L_CFLAGS += -DCONFIG_WEP +endif + include $(LOCAL_PATH)/src/drivers/drivers.mk diff --git a/hostapd/Makefile b/hostapd/Makefile index dbe0403a1..0a3b8dde7 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -1238,6 +1238,10 @@ OBJS += ../src/fst/fst_ctrl_iface.o endif endif +ifdef CONFIG_WEP +CFLAGS += -DCONFIG_WEP +endif + ALL=hostapd hostapd_cli all: verify_config $(ALL) diff --git a/hostapd/android.config b/hostapd/android.config index d9200beea..94a9bb47b 100644 --- a/hostapd/android.config +++ b/hostapd/android.config @@ -201,3 +201,11 @@ CONFIG_WPA_CLI_EDIT=y # /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before # either wpa_supplicant or hostapd are run. CONFIG_NO_RANDOM_POOL=y + +# Wired equivalent privacy (WEP) +# WEP is an obsolete cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used for anything anymore. The +# functionality needed to use WEP is available in the current hostapd +# release under this optional build parameter. This functionality is subject to +# be completely removed in a future release. +CONFIG_WEP=y diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 6dde59a5a..269f9f3cd 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -793,6 +793,7 @@ static int hostapd_config_parse_cipher(int line, const char *value) } +#ifdef CONFIG_WEP static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, char *val) { @@ -843,6 +844,7 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, return 0; } +#endif /* CONFIG_WEP */ static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val) @@ -2664,6 +2666,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "erp_domain") == 0) { os_free(bss->erp_domain); bss->erp_domain = os_strdup(pos); +#ifdef CONFIG_WEP } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { int val = atoi(pos); @@ -2691,6 +2694,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, bss->wep_rekeying_period); return 1; } +#endif /* CONFIG_WEP */ } else if (os_strcmp(buf, "eap_reauth_period") == 0) { bss->eap_reauth_period = atoi(pos); if (bss->eap_reauth_period < 0) { @@ -3311,6 +3315,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->ignore_broadcast_ssid = atoi(pos); } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) { bss->no_probe_resp_if_max_sta = atoi(pos); +#ifdef CONFIG_WEP } else if (os_strcmp(buf, "wep_default_key") == 0) { bss->ssid.wep.idx = atoi(pos); if (bss->ssid.wep.idx > 3) { @@ -3329,6 +3334,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, buf); return 1; } +#endif /* CONFIG_WEP */ #ifndef CONFIG_NO_VLAN } else if (os_strcmp(buf, "dynamic_vlan") == 0) { bss->ssid.dynamic_vlan = atoi(pos); diff --git a/hostapd/defconfig b/hostapd/defconfig index e12260f4a..5133db26b 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -380,3 +380,11 @@ CONFIG_IPV6=y # Override default value for the wpa_disable_eapol_key_retries configuration # parameter. See that parameter in hostapd.conf for more details. #CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1 + +# Wired equivalent privacy (WEP) +# WEP is an obsolete cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used for anything anymore. The +# functionality needed to use WEP is available in the current hostapd +# release under this optional build parameter. This functionality is subject to +# be completely removed in a future release. +#CONFIG_WEP=y diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index fddc8ca44..50974094a 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -54,12 +54,16 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) bss->logger_syslog = (unsigned int) -1; bss->logger_stdout = (unsigned int) -1; +#ifdef CONFIG_WEP bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED; bss->wep_rekeying_period = 300; /* use key0 in individual key and key1 in broadcast key */ bss->broadcast_key_idx_min = 1; bss->broadcast_key_idx_max = 2; +#else /* CONFIG_WEP */ + bss->auth_algs = WPA_AUTH_ALG_OPEN; +#endif /* CONFIG_WEP */ bss->eap_reauth_period = 3600; bss->wpa_group_rekey = 600; @@ -636,6 +640,7 @@ void hostapd_config_free_eap_users(struct hostapd_eap_user *user) } +#ifdef CONFIG_WEP static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) { int i; @@ -644,6 +649,7 @@ static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) keys->key[i] = NULL; } } +#endif /* CONFIG_WEP */ void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l) @@ -732,7 +738,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) str_clear_free(conf->ssid.wpa_passphrase); os_free(conf->ssid.wpa_psk_file); +#ifdef CONFIG_WEP hostapd_config_free_wep(&conf->ssid.wep); +#endif /* CONFIG_WEP */ #ifdef CONFIG_FULL_DYNAMIC_VLAN os_free(conf->ssid.vlan_tagged_interface); #endif /* CONFIG_FULL_DYNAMIC_VLAN */ @@ -1106,6 +1114,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, return -1; } +#ifdef CONFIG_WEP if (bss->wpa) { int wep, i; @@ -1123,6 +1132,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, return -1; } } +#endif /* CONFIG_WEP */ if (full_config && bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED && @@ -1177,12 +1187,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, "allowed, disabling HT capabilities"); } +#ifdef CONFIG_WEP if (full_config && conf->ieee80211n && bss->ssid.security_policy == SECURITY_STATIC_WEP) { bss->disable_11n = 1; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " "allowed, disabling HT capabilities"); } +#endif /* CONFIG_WEP */ if (full_config && conf->ieee80211n && bss->wpa && !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && @@ -1196,12 +1208,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } #ifdef CONFIG_IEEE80211AC +#ifdef CONFIG_WEP if (full_config && conf->ieee80211ac && bss->ssid.security_policy == SECURITY_STATIC_WEP) { bss->disable_11ac = 1; wpa_printf(MSG_ERROR, "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities"); } +#endif /* CONFIG_WEP */ if (full_config && conf->ieee80211ac && bss->wpa && !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && @@ -1221,12 +1235,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, bss->wps_state = 0; } +#ifdef CONFIG_WEP if (full_config && bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) { wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be " "disabled"); bss->wps_state = 0; } +#endif /* CONFIG_WEP */ if (full_config && bss->wps_state && bss->wpa && (!(bss->wpa & 2) || @@ -1350,11 +1366,13 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config) void hostapd_set_security_params(struct hostapd_bss_config *bss, int full_config) { +#ifdef CONFIG_WEP if (bss->individual_wep_key_len == 0) { /* individual keys are not use; can use key idx0 for * broadcast keys */ bss->broadcast_key_idx_min = 0; } +#endif /* CONFIG_WEP */ if ((bss->wpa & 2) && bss->rsn_pairwise == 0) bss->rsn_pairwise = bss->wpa_pairwise; @@ -1380,6 +1398,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss, } else if (bss->ieee802_1x) { int cipher = WPA_CIPHER_NONE; bss->ssid.security_policy = SECURITY_IEEE_802_1X; +#ifdef CONFIG_WEP bss->ssid.wep.default_len = bss->default_wep_key_len; if (full_config && bss->default_wep_key_len) { cipher = bss->default_wep_key_len >= 13 ? @@ -1390,11 +1409,13 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss, else cipher = WPA_CIPHER_WEP40; } +#endif /* CONFIG_WEP */ bss->wpa_group = cipher; bss->wpa_pairwise = cipher; bss->rsn_pairwise = cipher; if (full_config) bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; +#ifdef CONFIG_WEP } else if (bss->ssid.wep.keys_set) { int cipher = WPA_CIPHER_WEP40; if (bss->ssid.wep.len[0] >= 13) @@ -1405,6 +1426,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss, bss->rsn_pairwise = cipher; if (full_config) bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE; +#endif /* CONFIG_WEP */ } else if (bss->osen) { bss->ssid.security_policy = SECURITY_OSEN; bss->wpa_group = WPA_CIPHER_CCMP; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index b6e11f25f..5d86a332a 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -67,6 +67,7 @@ struct hostapd_radius_servers; struct ft_remote_r0kh; struct ft_remote_r1kh; +#ifdef CONFIG_WEP #define NUM_WEP_KEYS 4 struct hostapd_wep_keys { u8 idx; @@ -75,10 +76,13 @@ struct hostapd_wep_keys { int keys_set; size_t default_len; /* key length used for dynamic key generation */ }; +#endif /* CONFIG_WEP */ typedef enum hostap_security_policy { SECURITY_PLAINTEXT = 0, +#ifdef CONFIG_WEP SECURITY_STATIC_WEP = 1, +#endif /* CONFIG_WEP */ SECURITY_IEEE_802_1X = 2, SECURITY_WPA_PSK = 3, SECURITY_WPA = 4, @@ -102,7 +106,9 @@ struct hostapd_ssid { char *wpa_psk_file; struct sae_pt *pt; +#ifdef CONFIG_WEP struct hostapd_wep_keys wep; +#endif /* CONFIG_WEP */ #define DYNAMIC_VLAN_DISABLED 0 #define DYNAMIC_VLAN_OPTIONAL 1 @@ -321,10 +327,12 @@ struct hostapd_bss_config { size_t eap_req_id_text_len; int eapol_key_index_workaround; +#ifdef CONFIG_WEP size_t default_wep_key_len; int individual_wep_key_len; int wep_rekeying_period; int broadcast_key_idx_min, broadcast_key_idx_max; +#endif /* CONFIG_WEP */ int eap_reauth_period; int erp_send_reauth_start; char *erp_domain; diff --git a/src/ap/beacon.c b/src/ap/beacon.c index f5de17747..53e35492d 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1360,10 +1360,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, params->key_mgmt_suites = hapd->conf->wpa_key_mgmt; params->auth_algs = hapd->conf->auth_algs; params->wpa_version = hapd->conf->wpa; - params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa || + params->privacy = hapd->conf->wpa; +#ifdef CONFIG_WEP + params->privacy |= hapd->conf->ssid.wep.keys_set || (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)); +#endif /* CONFIG_WEP */ switch (hapd->conf->ignore_broadcast_ssid) { case 0: params->hide_ssid = NO_SSID_HIDING; diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index ccf3f88f2..a6a95debf 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -58,8 +58,10 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason); +#ifdef CONFIG_WEP static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd); +#endif /* CONFIG_WEP */ static int setup_interface2(struct hostapd_iface *iface); static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx); static void hostapd_interface_setup_failure_handler(void *eloop_ctx, @@ -89,7 +91,9 @@ void hostapd_reconfig_encryption(struct hostapd_data *hapd) return; hostapd_set_privacy(hapd, 0); +#ifdef CONFIG_WEP hostapd_setup_encryption(hapd->conf->iface, hapd); +#endif /* CONFIG_WEP */ } @@ -142,7 +146,9 @@ static void hostapd_reload_bss(struct hostapd_data *hapd) wpa_deinit(hapd->wpa_auth); hapd->wpa_auth = NULL; hostapd_set_privacy(hapd, 0); +#ifdef CONFIG_WEP hostapd_setup_encryption(hapd->conf->iface, hapd); +#endif /* CONFIG_WEP */ hostapd_set_generic_elem(hapd, (u8 *) "", 0); } @@ -170,7 +176,9 @@ static void hostapd_clear_old(struct hostapd_iface *iface) for (j = 0; j < iface->num_bss; j++) { hostapd_flush_old_stations(iface->bss[j], WLAN_REASON_PREV_AUTH_NOT_VALID); +#ifdef CONFIG_WEP hostapd_broadcast_wep_clear(iface->bss[j]); +#endif /* CONFIG_WEP */ #ifndef CONFIG_NO_RADIUS /* TODO: update dynamic data based on changed configuration @@ -284,6 +292,8 @@ int hostapd_reload_config(struct hostapd_iface *iface) } +#ifdef CONFIG_WEP + static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, const char *ifname) { @@ -339,6 +349,8 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) return errors; } +#endif /* CONFIG_WEP */ + static void hostapd_free_hapd_data(struct hostapd_data *hapd) { @@ -524,6 +536,8 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface) } +#ifdef CONFIG_WEP + static void hostapd_clear_wep(struct hostapd_data *hapd) { if (hapd->drv_priv && !hapd->iface->driver_ap_teardown && hapd->conf) { @@ -571,6 +585,8 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) return 0; } +#endif /* CONFIG_WEP */ + static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) { @@ -606,7 +622,9 @@ static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd) { hostapd_free_stas(hapd); hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); +#ifdef CONFIG_WEP hostapd_clear_wep(hapd); +#endif /* CONFIG_WEP */ } @@ -1161,9 +1179,11 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) WLAN_REASON_PREV_AUTH_NOT_VALID); hostapd_set_privacy(hapd, 0); +#ifdef CONFIG_WEP hostapd_broadcast_wep_clear(hapd); if (hostapd_setup_encryption(conf->iface, hapd)) return -1; +#endif /* CONFIG_WEP */ /* * Fetch the SSID from the system and use it or, diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 03810de4e..47beaa15b 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -223,7 +223,7 @@ u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid, u16 hostapd_own_capab_info(struct hostapd_data *hapd) { int capab = WLAN_CAPABILITY_ESS; - int privacy; + int privacy = 0; int dfs; int i; @@ -239,12 +239,14 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd) hapd->iconf->preamble == SHORT_PREAMBLE) capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; +#ifdef CONFIG_WEP privacy = hapd->conf->ssid.wep.keys_set; if (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)) privacy = 1; +#endif /* CONFIG_WEP */ if (hapd->conf->wpa) privacy = 1; @@ -284,6 +286,7 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd) } +#ifdef CONFIG_WEP #ifndef CONFIG_NO_RC4 static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, u16 auth_transaction, const u8 *challenge, @@ -340,6 +343,7 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, return 0; } #endif /* CONFIG_NO_RC4 */ +#endif /* CONFIG_WEP */ static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta, @@ -2543,6 +2547,7 @@ static void handle_auth(struct hostapd_data *hapd, sta->auth_alg = WLAN_AUTH_OPEN; mlme_authenticate_indication(hapd, sta); break; +#ifdef CONFIG_WEP #ifndef CONFIG_NO_RC4 case WLAN_AUTH_SHARED_KEY: resp = auth_shared_key(hapd, sta, auth_transaction, challenge, @@ -2561,6 +2566,7 @@ static void handle_auth(struct hostapd_data *hapd, } break; #endif /* CONFIG_NO_RC4 */ +#endif /* CONFIG_WEP */ #ifdef CONFIG_IEEE80211R_AP case WLAN_AUTH_FT: sta->auth_alg = WLAN_AUTH_FT; @@ -4946,6 +4952,7 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd, struct sta_info *sta, char *ifname_wds) { +#ifdef CONFIG_WEP int i; struct hostapd_ssid *ssid = &hapd->conf->ssid; @@ -4966,6 +4973,7 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd, break; } } +#endif /* CONFIG_WEP */ } diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 001b26109..c8e5fb395 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -137,6 +137,7 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, } +#ifdef CONFIG_WEP #ifndef CONFIG_FIPS #ifndef CONFIG_NO_RC4 @@ -297,6 +298,7 @@ static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) #endif /* CONFIG_NO_RC4 */ #endif /* CONFIG_FIPS */ +#endif /* CONFIG_WEP */ const char *radius_mode_txt(struct hostapd_data *hapd) @@ -2114,6 +2116,8 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) } +#ifdef CONFIG_WEP + static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) { struct eapol_authenticator *eapol = hapd->eapol_auth; @@ -2198,6 +2202,8 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) } } +#endif /* CONFIG_WEP */ + static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, const u8 *data, size_t datalen) @@ -2361,6 +2367,7 @@ static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx) } +#ifdef CONFIG_WEP static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) { #ifndef CONFIG_FIPS @@ -2372,6 +2379,7 @@ static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) #endif /* CONFIG_NO_RC4 */ #endif /* CONFIG_FIPS */ } +#endif /* CONFIG_WEP */ static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx, @@ -2422,7 +2430,6 @@ static int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp) int ieee802_1x_init(struct hostapd_data *hapd) { - int i; struct eapol_auth_config conf; struct eapol_auth_cb cb; @@ -2433,7 +2440,9 @@ int ieee802_1x_init(struct hostapd_data *hapd) conf.ctx = hapd; conf.eap_reauth_period = hapd->conf->eap_reauth_period; conf.wpa = hapd->conf->wpa; +#ifdef CONFIG_WEP conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; +#endif /* CONFIG_WEP */ conf.eap_req_id_text = hapd->conf->eap_req_id_text; conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start; @@ -2448,7 +2457,9 @@ int ieee802_1x_init(struct hostapd_data *hapd) cb.logger = ieee802_1x_logger; cb.set_port_authorized = ieee802_1x_set_port_authorized; cb.abort_auth = _ieee802_1x_abort_auth; +#ifdef CONFIG_WEP cb.tx_key = _ieee802_1x_tx_key; +#endif /* CONFIG_WEP */ cb.eapol_event = ieee802_1x_eapol_event; #ifdef CONFIG_ERP cb.erp_get_key = ieee802_1x_erp_get_key; @@ -2469,7 +2480,10 @@ int ieee802_1x_init(struct hostapd_data *hapd) return -1; #endif /* CONFIG_NO_RADIUS */ +#ifdef CONFIG_WEP if (hapd->conf->default_wep_key_len) { + int i; + for (i = 0; i < 4; i++) hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, NULL, i, 0, 0, NULL, @@ -2480,6 +2494,7 @@ int ieee802_1x_init(struct hostapd_data *hapd) if (!hapd->eapol_auth->default_wep_key) return -1; } +#endif /* CONFIG_WEP */ return 0; } @@ -2499,7 +2514,9 @@ void ieee802_1x_erp_flush(struct hostapd_data *hapd) void ieee802_1x_deinit(struct hostapd_data *hapd) { +#ifdef CONFIG_WEP eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); +#endif /* CONFIG_WEP */ if (hapd->driver && hapd->drv_priv && (hapd->conf->ieee802_1x || hapd->conf->wpa)) diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c index e293a0033..53eacfb45 100644 --- a/src/ap/vlan_init.c +++ b/src/ap/vlan_init.c @@ -22,7 +22,9 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan, int existsok) { - int ret, i; + int ret; +#ifdef CONFIG_WEP + int i; for (i = 0; i < NUM_WEP_KEYS; i++) { if (!hapd->conf->ssid.wep.key[i]) @@ -32,6 +34,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan, vlan->ifname); return -1; } +#endif /* CONFIG_WEP */ if (!iface_exists(vlan->ifname)) ret = hostapd_vlan_if_add(hapd, vlan->ifname); diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 165d0de9e..1d77b946e 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -651,8 +651,10 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) (str_starts(buf, "ssid=") || str_starts(buf, "ssid2=") || str_starts(buf, "auth_algs=") || +#ifdef CONFIG_WEP str_starts(buf, "wep_default_key=") || str_starts(buf, "wep_key") || +#endif /* CONFIG_WEP */ str_starts(buf, "wps_state=") || (pmf_changed && str_starts(buf, "ieee80211w=")) || str_starts(buf, "wpa=") || @@ -1196,6 +1198,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1, conf->ssid.wpa_psk->psk, PMK_LEN); wps->network_key_len = 2 * PMK_LEN; +#ifdef CONFIG_WEP } else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) { wps->network_key = os_malloc(conf->ssid.wep.len[0]); if (wps->network_key == NULL) @@ -1203,6 +1206,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, os_memcpy(wps->network_key, conf->ssid.wep.key[0], conf->ssid.wep.len[0]); wps->network_key_len = conf->ssid.wep.len[0]; +#endif /* CONFIG_WEP */ } if (conf->ssid.wpa_psk) { diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 6cb9180ee..ee306ff50 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -1965,10 +1965,12 @@ const char * wpa_cipher_txt(int cipher) switch (cipher) { case WPA_CIPHER_NONE: return "NONE"; +#ifdef CONFIG_WEP case WPA_CIPHER_WEP40: return "WEP-40"; case WPA_CIPHER_WEP104: return "WEP-104"; +#endif /* CONFIG_WEP */ case WPA_CIPHER_TKIP: return "TKIP"; case WPA_CIPHER_CCMP: @@ -2467,10 +2469,12 @@ int wpa_parse_cipher(const char *value) val |= WPA_CIPHER_GCMP; else if (os_strcmp(start, "TKIP") == 0) val |= WPA_CIPHER_TKIP; +#ifdef CONFIG_WEP else if (os_strcmp(start, "WEP104") == 0) val |= WPA_CIPHER_WEP104; else if (os_strcmp(start, "WEP40") == 0) val |= WPA_CIPHER_WEP40; +#endif /* CONFIG_WEP */ else if (os_strcmp(start, "NONE") == 0) val |= WPA_CIPHER_NONE; else if (os_strcmp(start, "GTK_NOT_USED") == 0) diff --git a/src/eapol_auth/eapol_auth_sm.c b/src/eapol_auth/eapol_auth_sm.c index 5a2ba261d..2e79614fd 100644 --- a/src/eapol_auth/eapol_auth_sm.c +++ b/src/eapol_auth/eapol_auth_sm.c @@ -648,6 +648,8 @@ SM_STEP(REAUTH_TIMER) +#ifdef CONFIG_WEP + /* Authenticator Key Transmit state machine */ SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT) @@ -726,6 +728,8 @@ SM_STEP(KEY_RX) } } +#endif /* CONFIG_WEP */ + /* Controlled Directions state machine */ @@ -813,10 +817,12 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, sm->portControl = Auto; +#ifdef CONFIG_WEP if (!eapol->conf.wpa && (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0)) sm->keyTxEnabled = TRUE; else +#endif /* CONFIG_WEP */ sm->keyTxEnabled = FALSE; if (eapol->conf.wpa) sm->portValid = FALSE; @@ -910,10 +916,12 @@ restart: SM_STEP_RUN(BE_AUTH); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(REAUTH_TIMER); +#ifdef CONFIG_WEP if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(AUTH_KEY_TX); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(KEY_RX); +#endif /* CONFIG_WEP */ if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(CTRL_DIR); @@ -1167,7 +1175,9 @@ static int eapol_auth_conf_clone(struct eapol_auth_config *dst, dst->ctx = src->ctx; dst->eap_reauth_period = src->eap_reauth_period; dst->wpa = src->wpa; +#ifdef CONFIG_WEP dst->individual_wep_key_len = src->individual_wep_key_len; +#endif /* CONFIG_WEP */ os_free(dst->eap_req_id_text); if (src->eap_req_id_text) { dst->eap_req_id_text = os_memdup(src->eap_req_id_text, @@ -1221,10 +1231,12 @@ struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, return NULL; } +#ifdef CONFIG_WEP if (conf->individual_wep_key_len > 0) { /* use key0 in individual key and key1 in broadcast key */ eapol->default_wep_key_idx = 1; } +#endif /* CONFIG_WEP */ eapol->cb.eapol_send = cb->eapol_send; eapol->cb.aaa_send = cb->aaa_send; @@ -1249,6 +1261,8 @@ void eapol_auth_deinit(struct eapol_authenticator *eapol) return; eapol_auth_conf_free(&eapol->conf); +#ifdef CONFIG_WEP os_free(eapol->default_wep_key); +#endif /* CONFIG_WEP */ os_free(eapol); } diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index a34cc0be2..1734d6efb 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -692,6 +692,7 @@ struct eap_key_data { static void eapol_sm_processKey(struct eapol_sm *sm) { +#ifdef CONFIG_WEP #ifndef CONFIG_FIPS struct ieee802_1x_hdr *hdr; struct ieee802_1x_eapol_key *key; @@ -866,6 +867,7 @@ static void eapol_sm_processKey(struct eapol_sm *sm) } } #endif /* CONFIG_FIPS */ +#endif /* CONFIG_WEP */ } diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config index 942134a51..f1a9adf7b 100644 --- a/tests/hwsim/example-hostapd.config +++ b/tests/hwsim/example-hostapd.config @@ -110,3 +110,4 @@ CONFIG_FILS_SK_PFS=y CONFIG_OWE=y CONFIG_DPP=y CONFIG_DPP2=y +CONFIG_WEP=y diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config index d494caf86..253f329bb 100644 --- a/tests/hwsim/example-wpa_supplicant.config +++ b/tests/hwsim/example-wpa_supplicant.config @@ -153,3 +153,4 @@ CONFIG_PMKSA_CACHE_EXTERNAL=y CONFIG_OWE=y CONFIG_DPP=y CONFIG_DPP2=y +CONFIG_WEP=y diff --git a/tests/hwsim/test_ap_config.py b/tests/hwsim/test_ap_config.py index dc05a4854..e93c91477 100644 --- a/tests/hwsim/test_ap_config.py +++ b/tests/hwsim/test_ap_config.py @@ -429,8 +429,6 @@ def test_ap_config_set_oom(dev, apdev): tests = [(1, "hostapd_parse_das_client", "SET radius_das_client 192.168.1.123 pw"), - (1, "hostapd_config_read_wep", "SET wep_key0 \"hello\""), - (1, "hostapd_config_read_wep", "SET wep_key0 0102030405"), (1, "hostapd_parse_chanlist", "SET chanlist 1 6 11-13"), (1, "hostapd_config_bss", "SET bss foo"), (2, "hostapd_config_bss", "SET bss foo"), @@ -486,6 +484,9 @@ def test_ap_config_set_oom(dev, apdev): (1, "hostapd_parse_intlist", "SET sae_groups 19 25"), (1, "hostapd_parse_intlist", "SET basic_rates 10 20 55 110"), (1, "hostapd_parse_intlist", "SET supported_rates 10 20 55 110")] + if "WEP40" in dev[0].get_capability("group"): + tests += [(1, "hostapd_config_read_wep", "SET wep_key0 \"hello\""), + (1, "hostapd_config_read_wep", "SET wep_key0 0102030405")] for count, func, cmd in tests: with alloc_fail(hapd, count, func): if "FAIL" not in hapd.request(cmd): @@ -533,14 +534,15 @@ def test_ap_config_set_oom(dev, apdev): def test_ap_config_set_errors(dev, apdev): """hostapd configuration parsing errors""" hapd = hostapd.add_ap(apdev[0], {"ssid": "foobar"}) - hapd.set("wep_key0", '"hello"') - hapd.set("wep_key1", '"hello"') - hapd.set("wep_key0", '') - hapd.set("wep_key0", '"hello"') - if "FAIL" not in hapd.request("SET wep_key1 \"hello\""): - raise Exception("SET wep_key1 allowed to override existing key") - hapd.set("wep_key1", '') - hapd.set("wep_key1", '"hello"') + if "WEP40" in dev[0].get_capability("group"): + hapd.set("wep_key0", '"hello"') + hapd.set("wep_key1", '"hello"') + hapd.set("wep_key0", '') + hapd.set("wep_key0", '"hello"') + if "FAIL" not in hapd.request("SET wep_key1 \"hello\""): + raise Exception("SET wep_key1 allowed to override existing key") + hapd.set("wep_key1", '') + hapd.set("wep_key1", '"hello"') hapd.set("auth_server_addr", "127.0.0.1") hapd.set("acct_server_addr", "127.0.0.1") diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index 374ba2278..a8dac6b70 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -2662,8 +2662,9 @@ def test_ap_hs20_osen(dev, apdev): dev[1].connect("osen", key_mgmt="NONE", scan_freq="2412", wait_connect=False) - dev[2].connect("osen", key_mgmt="NONE", wep_key0='"hello"', - scan_freq="2412", wait_connect=False) + if "WEP40" in dev[2].get_capability("group"): + dev[2].connect("osen", key_mgmt="NONE", wep_key0='"hello"', + scan_freq="2412", wait_connect=False) dev[0].flush_scan_cache() dev[0].connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP", group="GTK_NOT_USED CCMP", diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py index aa0b28128..d72e64ab2 100644 --- a/tests/hwsim/test_ap_params.py +++ b/tests/hwsim/test_ap_params.py @@ -16,6 +16,7 @@ import hwsim_utils import hostapd from tshark import run_tshark from utils import alloc_fail, HwsimSkip, parse_ie +from test_wep import check_wep_capa @remote_compatible def test_ap_fragmentation_rts_set_high(dev, apdev): @@ -334,6 +335,7 @@ def test_ap_wds_sta_open(dev, apdev): def test_ap_wds_sta_wep(dev, apdev): """WEP AP with STA using 4addr mode""" + check_wep_capa(dev[0]) ssid = "test-wds-wep" params = {} params['ssid'] = ssid @@ -658,6 +660,7 @@ def test_ap_beacon_rate_vht(dev, apdev): def test_ap_wep_to_wpa(dev, apdev): """WEP to WPA2-PSK configuration change in hostapd""" + check_wep_capa(dev[0]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-to-wpa", "wep_key0": '"hello"'}) diff --git a/tests/hwsim/test_ap_tdls.py b/tests/hwsim/test_ap_tdls.py index caba13df9..31d581516 100644 --- a/tests/hwsim/test_ap_tdls.py +++ b/tests/hwsim/test_ap_tdls.py @@ -17,6 +17,7 @@ import hostapd from utils import HwsimSkip, skip_with_fips from wlantest import Wlantest from test_ap_vht import vht_supported +from test_wep import check_wep_capa def start_ap_wpa2_psk(ap): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") @@ -313,6 +314,8 @@ def test_ap_wpa_mixed_tdls(dev, apdev): def test_ap_wep_tdls(dev, apdev): """WEP AP and two stations using TDLS""" + check_wep_capa(dev[0]) + check_wep_capa(dev[1]) hapd = hostapd.add_ap(apdev[0], {"ssid": "test-wep", "wep_key0": '"hello"'}) wlantest_setup(hapd) diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index 958341667..234531c5d 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -45,6 +45,7 @@ from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips from utils import wait_fail_trigger, clear_regdom from test_ap_eap import int_eap_server_params from test_sae import check_sae_capab +from test_wep import check_wep_capa def wps_start_ap(apdev, ssid="test-wps-conf"): params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", @@ -10036,6 +10037,7 @@ def test_ap_wps_ignore_broadcast_ssid(dev, apdev): def test_ap_wps_wep(dev, apdev): """WPS AP trying to enable WEP""" + check_wep_capa(dev[0]) ssid = "test-wps" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1", diff --git a/tests/hwsim/test_cfg80211.py b/tests/hwsim/test_cfg80211.py index a461fe0ce..9c7935e70 100644 --- a/tests/hwsim/test_cfg80211.py +++ b/tests/hwsim/test_cfg80211.py @@ -16,6 +16,7 @@ import hwsim_utils from tshark import run_tshark from nl80211 import * from wpasupplicant import WpaSupplicant +from test_wep import check_wep_capa def nl80211_command(dev, cmd, attr): res = dev.request("VENDOR ffffffff {} {}".format(nl80211_cmd[cmd], @@ -101,6 +102,7 @@ def test_cfg80211_tx_frame(dev, apdev, params): @remote_compatible def test_cfg80211_wep_key_idx_change(dev, apdev): """WEP Shared Key authentication and key index change without deauth""" + check_wep_capa(dev[0]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", "wep_key0": '"hello12345678"', diff --git a/tests/hwsim/test_connect_cmd.py b/tests/hwsim/test_connect_cmd.py index 87122aa32..07a9ab651 100644 --- a/tests/hwsim/test_connect_cmd.py +++ b/tests/hwsim/test_connect_cmd.py @@ -12,6 +12,7 @@ import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant from p2p_utils import * +from test_wep import check_wep_capa def test_connect_cmd_open(dev, apdev): """Open connection using cfg80211 connect command""" @@ -31,11 +32,13 @@ def test_connect_cmd_open(dev, apdev): def test_connect_cmd_wep(dev, apdev): """WEP Open System using cfg80211 connect command""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + check_wep_capa(wpas) + params = {"ssid": "sta-connect-wep", "wep_key0": '"hello"'} hapd = hostapd.add_ap(apdev[0], params) - wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') - wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") wpas.connect("sta-connect-wep", key_mgmt="NONE", scan_freq="2412", wep_key0='"hello"') wpas.dump_monitor() @@ -46,12 +49,14 @@ def test_connect_cmd_wep(dev, apdev): def test_connect_cmd_wep_shared(dev, apdev): """WEP Shared key using cfg80211 connect command""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + check_wep_capa(wpas) + params = {"ssid": "sta-connect-wep", "wep_key0": '"hello"', "auth_algs": "2"} hapd = hostapd.add_ap(apdev[0], params) - wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') - wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") id = wpas.connect("sta-connect-wep", key_mgmt="NONE", scan_freq="2412", auth_alg="SHARED", wep_key0='"hello"') wpas.dump_monitor() diff --git a/tests/hwsim/test_ibss.py b/tests/hwsim/test_ibss.py index a9b7e11b0..ce7e5eda3 100644 --- a/tests/hwsim/test_ibss.py +++ b/tests/hwsim/test_ibss.py @@ -13,6 +13,7 @@ import subprocess import hwsim_utils from utils import alloc_fail, wait_fail_trigger +from test_wep import check_wep_capa def connect_ibss_cmd(dev, id, freq=2412): dev.dump_monitor() @@ -395,6 +396,9 @@ def test_ibss_rsn_tkip(dev): def test_ibss_wep(dev): """IBSS with WEP""" + check_wep_capa(dev[0]) + check_wep_capa(dev[1]) + ssid = "ibss-wep" id = add_ibss(dev[0], ssid, key_mgmt="NONE", wep_key0='"hello"') diff --git a/tests/hwsim/test_ieee8021x.py b/tests/hwsim/test_ieee8021x.py index bc1c3c939..194694819 100644 --- a/tests/hwsim/test_ieee8021x.py +++ b/tests/hwsim/test_ieee8021x.py @@ -15,11 +15,13 @@ import hostapd import hwsim_utils from utils import skip_with_fips from tshark import run_tshark +from test_wep import check_wep_capa logger = logging.getLogger() def test_ieee8021x_wep104(dev, apdev): """IEEE 802.1X connection using dynamic WEP104""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" @@ -36,6 +38,7 @@ def test_ieee8021x_wep104(dev, apdev): def test_ieee8021x_wep40(dev, apdev): """IEEE 802.1X connection using dynamic WEP40""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" @@ -52,6 +55,7 @@ def test_ieee8021x_wep40(dev, apdev): def test_ieee8021x_wep_index_workaround(dev, apdev): """IEEE 802.1X and EAPOL-Key index workaround""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" @@ -100,6 +104,7 @@ def test_ieee8021x_static_wep104(dev, apdev): run_static_wep(dev, apdev, '"hello-there-/"') def run_static_wep(dev, apdev, key): + check_wep_capa(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" params["ieee8021x"] = "1" @@ -252,6 +257,7 @@ def send_eapol_key(dev, bssid, signkey, frame_start, frame_end): def test_ieee8021x_eapol_key(dev, apdev): """IEEE 802.1X connection and EAPOL-Key protocol tests""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" @@ -317,6 +323,7 @@ def test_ieee8021x_reauth(dev, apdev): def test_ieee8021x_reauth_wep(dev, apdev, params): """IEEE 802.1X and EAPOL_REAUTH request with WEP""" + check_wep_capa(dev[0]) logdir = params['logdir'] params = hostapd.radius_params() @@ -492,6 +499,7 @@ def test_ieee8021x_open_leap(dev, apdev): def test_ieee8021x_and_wpa_enabled(dev, apdev): """IEEE 802.1X connection using dynamic WEP104 when WPA enabled""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" diff --git a/tests/hwsim/test_radius.py b/tests/hwsim/test_radius.py index fde5650de..6729f372d 100644 --- a/tests/hwsim/test_radius.py +++ b/tests/hwsim/test_radius.py @@ -21,6 +21,7 @@ import hostapd from utils import HwsimSkip, require_under_vm, skip_with_fips, alloc_fail, fail_test, wait_fail_trigger from test_ap_hs20 import build_dhcp_ack from test_ap_ft import ft_params1 +from test_wep import check_wep_capa def connect(dev, ssid, wait_connect=True): dev.connect(ssid, key_mgmt="WPA-EAP", scan_freq="2412", @@ -442,6 +443,7 @@ def test_radius_acct_ft_psk(dev, apdev): def test_radius_acct_ieee8021x(dev, apdev): """RADIUS Accounting - IEEE 802.1X""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) as_hapd = hostapd.Hostapd("as") params = hostapd.radius_params() diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index 682f427d1..0b7eca882 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -19,6 +19,7 @@ from utils import HwsimSkip, fail_test, alloc_fail, wait_fail_trigger, parse_ie from utils import clear_regdom_dev from tshark import run_tshark from test_ap_csa import switch_channel, wait_channel_switch, csa_supported +from test_wep import check_wep_capa def check_scan(dev, params, other_started=False, test_busy=False): if not other_started: @@ -434,6 +435,7 @@ def test_scan_for_auth_fail(dev, apdev): @remote_compatible def test_scan_for_auth_wep(dev, apdev): """cfg80211 scan-for-auth workaround with WEP keys""" + check_wep_capa(dev[0]) dev[0].flush_scan_cache() hapd = hostapd.add_ap(apdev[0], {"ssid": "wep", "wep_key0": '"abcde"', diff --git a/tests/hwsim/test_wep.py b/tests/hwsim/test_wep.py index d6af730ae..38e34964a 100644 --- a/tests/hwsim/test_wep.py +++ b/tests/hwsim/test_wep.py @@ -11,11 +11,16 @@ import subprocess from remotehost import remote_compatible import hostapd import hwsim_utils -from utils import clear_regdom +from utils import clear_regdom, HwsimSkip + +def check_wep_capa(dev): + if "WEP40" not in dev.get_capability("group"): + raise HwsimSkip("WEP not supported") @remote_compatible def test_wep_open_auth(dev, apdev): """WEP Open System authentication""" + check_wep_capa(dev[0]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-open", "wep_key0": '"hello"'}) @@ -35,6 +40,8 @@ def test_wep_open_auth(dev, apdev): @remote_compatible def test_wep_shared_key_auth(dev, apdev): """WEP Shared Key authentication""" + check_wep_capa(dev[0]) + check_wep_capa(dev[1]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", "wep_key0": '"hello12345678"', @@ -50,6 +57,7 @@ def test_wep_shared_key_auth(dev, apdev): @remote_compatible def test_wep_shared_key_auth_not_allowed(dev, apdev): """WEP Shared Key authentication not allowed""" + check_wep_capa(dev[0]) hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", "wep_key0": '"hello12345678"', @@ -63,6 +71,9 @@ def test_wep_shared_key_auth_not_allowed(dev, apdev): def test_wep_shared_key_auth_multi_key(dev, apdev): """WEP Shared Key authentication with multiple keys""" + check_wep_capa(dev[0]) + check_wep_capa(dev[1]) + check_wep_capa(dev[2]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", "wep_key0": '"hello12345678"', @@ -92,6 +103,7 @@ def test_wep_shared_key_auth_multi_key(dev, apdev): def test_wep_ht_vht(dev, apdev): """WEP and HT/VHT""" + check_wep_capa(dev[0]) dev[0].flush_scan_cache() try: hapd = None @@ -124,6 +136,7 @@ def test_wep_ht_vht(dev, apdev): def test_wep_ifdown(dev, apdev): """AP with WEP and external ifconfig down""" + check_wep_capa(dev[0]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-open", "wep_key0": '"hello"'}) diff --git a/tests/hwsim/test_wext.py b/tests/hwsim/test_wext.py index 1668ccd69..8e1ed7159 100644 --- a/tests/hwsim/test_wext.py +++ b/tests/hwsim/test_wext.py @@ -13,6 +13,7 @@ import hwsim_utils from wpasupplicant import WpaSupplicant from utils import HwsimSkip, skip_with_fips from test_rfkill import get_rfkill +from test_wep import check_wep_capa def get_wext_interface(): if not os.path.exists("/proc/net/wireless"): @@ -149,6 +150,7 @@ def test_wext_pmksa_cache(dev, apdev): def test_wext_wep_open_auth(dev, apdev): """WEP Open System authentication""" wpas = get_wext_interface() + check_wep_capa(wpas) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-open", @@ -162,6 +164,7 @@ def test_wext_wep_open_auth(dev, apdev): def test_wext_wep_shared_key_auth(dev, apdev): """WEP Shared Key authentication""" wpas = get_wext_interface() + check_wep_capa(wpas) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", diff --git a/tests/hwsim/test_wpas_ap.py b/tests/hwsim/test_wpas_ap.py index 5d6dfedde..29005f48e 100644 --- a/tests/hwsim/test_wpas_ap.py +++ b/tests/hwsim/test_wpas_ap.py @@ -13,6 +13,7 @@ import hwsim_utils from utils import HwsimSkip, alloc_fail, clear_regdom_dev from wpasupplicant import WpaSupplicant from test_p2p_channel import set_country +from test_wep import check_wep_capa def wait_ap_ready(dev): ev = dev.wait_event(["CTRL-EVENT-CONNECTED"]) @@ -103,6 +104,7 @@ def test_wpas_ap_open_isolate(dev): @remote_compatible def test_wpas_ap_wep(dev): """wpa_supplicant AP mode - WEP""" + check_wep_capa(dev[0]) id = dev[0].add_network() dev[0].set_network(id, "mode", "2") dev[0].set_network_quoted(id, "ssid", "wpas-ap-wep") @@ -540,17 +542,18 @@ def test_wpas_ap_oom(dev): dev[0].wait_disconnected() dev[0].request("REMOVE_NETWORK all") - id = dev[0].add_network() - dev[0].set_network(id, "mode", "2") - dev[0].set_network_quoted(id, "ssid", "wpas-ap") - dev[0].set_network(id, "key_mgmt", "NONE") - dev[0].set_network_quoted(id, "wep_key0", "hello") - dev[0].set_network(id, "frequency", "2412") - dev[0].set_network(id, "scan_freq", "2412") - with alloc_fail(dev[0], 1, "=wpa_supplicant_conf_ap"): - dev[0].select_network(id) - dev[0].wait_disconnected() - dev[0].request("REMOVE_NETWORK all") + if "WEP40" in dev[0].get_capability("group"): + id = dev[0].add_network() + dev[0].set_network(id, "mode", "2") + dev[0].set_network_quoted(id, "ssid", "wpas-ap") + dev[0].set_network(id, "key_mgmt", "NONE") + dev[0].set_network_quoted(id, "wep_key0", "hello") + dev[0].set_network(id, "frequency", "2412") + dev[0].set_network(id, "scan_freq", "2412") + with alloc_fail(dev[0], 1, "=wpa_supplicant_conf_ap"): + dev[0].select_network(id) + dev[0].wait_disconnected() + dev[0].request("REMOVE_NETWORK all") wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5") diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py index 91f440191..cd3053460 100644 --- a/tests/hwsim/test_wpas_ctrl.py +++ b/tests/hwsim/test_wpas_ctrl.py @@ -145,11 +145,12 @@ def test_wpas_ctrl_network(dev): if "FAIL" not in dev[0].request("SET_NETWORK " + str(id) + ' identity 12x3'): raise Exception("Unexpected success for invalid identity string") - for i in range(0, 4): - if "FAIL" in dev[0].request("SET_NETWORK " + str(id) + ' wep_key' + str(i) + ' aabbccddee'): - raise Exception("Unexpected wep_key set failure") - if dev[0].get_network(id, "wep_key" + str(i)) != '*': - raise Exception("Unexpected wep_key get failure") + if "WEP40" in dev[0].get_capability("group"): + for i in range(0, 4): + if "FAIL" in dev[0].request("SET_NETWORK " + str(id) + ' wep_key' + str(i) + ' aabbccddee'): + raise Exception("Unexpected wep_key set failure") + if dev[0].get_network(id, "wep_key" + str(i)) != '*': + raise Exception("Unexpected wep_key get failure") if "FAIL" in dev[0].request("SET_NETWORK " + str(id) + ' psk_list P2P-00:11:22:33:44:55-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'): raise Exception("Unexpected failure for psk_list string") @@ -205,11 +206,12 @@ def test_wpas_ctrl_network(dev): raise Exception("Invalid WEP key accepted") if "FAIL" not in dev[0].request('SET_NETWORK ' + str(id) + ' wep_key0 "12345678901234567"'): raise Exception("Too long WEP key accepted") - # too short WEP key is ignored - dev[0].set_network_quoted(id, "wep_key0", "1234") - dev[0].set_network_quoted(id, "wep_key1", "12345") - dev[0].set_network_quoted(id, "wep_key2", "1234567890123") - dev[0].set_network_quoted(id, "wep_key3", "1234567890123456") + if "WEP40" in dev[0].get_capability("group"): + # too short WEP key is ignored + dev[0].set_network_quoted(id, "wep_key0", "1234") + dev[0].set_network_quoted(id, "wep_key1", "12345") + dev[0].set_network_quoted(id, "wep_key2", "1234567890123") + dev[0].set_network_quoted(id, "wep_key3", "1234567890123456") dev[0].set_network(id, "go_p2p_dev_addr", "any") if dev[0].get_network(id, "go_p2p_dev_addr") is not None: diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 0883e749c..c348766ca 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -378,6 +378,10 @@ OBJS += src/fst/fst_ctrl_iface.c endif endif +ifdef CONFIG_WEP +L_CFLAGS += -DCONFIG_WEP +endif + include $(LOCAL_PATH)/src/drivers/drivers.mk diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index e41464f4d..88f688b62 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1843,6 +1843,10 @@ OBJS_t2 += $(FST_OBJS) OBJS_nfc += $(FST_OBJS) endif +ifdef CONFIG_WEP +CFLAGS += -DCONFIG_WEP +endif + ifndef LDO LDO=$(CC) endif diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config index 69dc7127f..283f8eb0a 100644 --- a/wpa_supplicant/android.config +++ b/wpa_supplicant/android.config @@ -534,4 +534,12 @@ CONFIG_WIFI_DISPLAY=y # Experimental implementation of draft-harkins-owe-07.txt #CONFIG_OWE=y +# Wired equivalent privacy (WEP) +# WEP is an obsolete cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used for anything anymore. The +# functionality needed to use WEP is available in the current wpa_supplicant +# release under this optional build parameter. This functionality is subject to +# be completely removed in a future release. +CONFIG_WEP=y + include $(wildcard $(LOCAL_PATH)/android_config_*.inc) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index bbd8f05fd..87573ef10 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -390,6 +390,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->ssid.wpa_psk_set = 1; } else if (ssid->passphrase) { bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase); +#ifdef CONFIG_WEP } else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] || ssid->wep_key_len[2] || ssid->wep_key_len[3]) { struct hostapd_wep_keys *wep = &bss->ssid.wep; @@ -405,6 +406,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, } wep->idx = ssid->wep_tx_keyidx; wep->keys_set = 1; +#endif /* CONFIG_WEP */ } #ifdef CONFIG_SAE if (ssid->sae_password) { @@ -486,11 +488,12 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, bss->rsn_pairwise); - if (bss->wpa && bss->ieee802_1x) + if (bss->wpa && bss->ieee802_1x) { bss->ssid.security_policy = SECURITY_WPA; - else if (bss->wpa) + } else if (bss->wpa) { bss->ssid.security_policy = SECURITY_WPA_PSK; - else if (bss->ieee802_1x) { +#ifdef CONFIG_WEP + } else if (bss->ieee802_1x) { int cipher = WPA_CIPHER_NONE; bss->ssid.security_policy = SECURITY_IEEE_802_1X; bss->ssid.wep.default_len = bss->default_wep_key_len; @@ -508,6 +511,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->wpa_group = cipher; bss->wpa_pairwise = cipher; bss->rsn_pairwise = cipher; +#endif /* CONFIG_WEP */ } else { bss->ssid.security_policy = SECURITY_PLAINTEXT; bss->wpa_group = WPA_CIPHER_NONE; diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 938165465..2b9c3f53e 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1856,6 +1856,8 @@ static char * wpa_config_write_machine_password(const struct parse_data *data, #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP + static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, const char *value, int idx) { @@ -1966,6 +1968,8 @@ static char * wpa_config_write_wep_key3(const struct parse_data *data, } #endif /* NO_CONFIG_WRITE */ +#endif /* CONFIG_WEP */ + #ifdef CONFIG_P2P @@ -2451,11 +2455,13 @@ static const struct parse_data ssid_fields[] = { { STRe(openssl_ciphers, openssl_ciphers) }, { INTe(erp, erp) }, #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP { FUNC_KEY(wep_key0) }, { FUNC_KEY(wep_key1) }, { FUNC_KEY(wep_key2) }, { FUNC_KEY(wep_key3) }, { INT(wep_tx_keyidx) }, +#endif /* CONFIG_WEP */ { INT(priority) }, #ifdef IEEE8021X_EAPOL { INT(eap_workaround) }, diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index d453ca541..d100d74cb 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -213,8 +213,22 @@ static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) } } - if (wpa_config_set(ssid, pos, pos2, *line) < 0) + if (wpa_config_set(ssid, pos, pos2, *line) < 0) { +#ifndef CONFIG_WEP + if (os_strcmp(pos, "wep_key0") == 0 || + os_strcmp(pos, "wep_key1") == 0 || + os_strcmp(pos, "wep_key2") == 0 || + os_strcmp(pos, "wep_key3") == 0 || + os_strcmp(pos, "wep_tx_keyidx") == 0) { + wpa_printf(MSG_ERROR, + "Line %d: unsupported WEP parameter", + *line); + ssid->disabled = 1; + continue; + } +#endif /* CONFIG_WEP */ errors++; + } } if (!end) { @@ -653,6 +667,7 @@ static void write_eap(FILE *f, struct wpa_ssid *ssid) #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) { char field[20], *value; @@ -667,6 +682,7 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) os_free(value); } } +#endif /* CONFIG_WEP */ #ifdef CONFIG_P2P @@ -741,8 +757,6 @@ static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid) static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) { - int i; - #define STR(t) write_str(f, #t, ssid) #define INT(t) write_int(f, #t, ssid->t, 0) #define INTe(t, m) write_int(f, #t, ssid->eap.m, 0) @@ -831,9 +845,15 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(openssl_ciphers); INTe(erp, erp); #endif /* IEEE8021X_EAPOL */ - for (i = 0; i < 4; i++) - write_wep_key(f, i, ssid); - INT(wep_tx_keyidx); +#ifdef CONFIG_WEP + { + int i; + + for (i = 0; i < 4; i++) + write_wep_key(f, i, ssid); + INT(wep_tx_keyidx); + } +#endif /* CONFIG_WEP */ INT(priority); #ifdef IEEE8021X_EAPOL INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index ac08ad863..24c7a3d9b 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -300,6 +300,7 @@ struct wpa_ssid { struct eap_peer_config eap; #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP #define NUM_WEP_KEYS 4 #define MAX_WEP_KEY_LEN 16 /** @@ -316,6 +317,7 @@ struct wpa_ssid { * wep_tx_keyidx - Default key index for TX frames using WEP */ int wep_tx_keyidx; +#endif /* CONFIG_WEP */ /** * proactive_key_caching - Enable proactive key caching diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index 0f2a30a46..598bc7790 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -823,6 +823,7 @@ static void write_eap(HKEY hk, struct wpa_ssid *ssid) #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid) { char field[20], *value; @@ -834,11 +835,12 @@ static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid) os_free(value); } } +#endif /* CONFIG_WEP */ static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) { - int i, errors = 0; + int errors = 0; HKEY nhk, netw; LONG ret; TCHAR name[5]; @@ -924,9 +926,15 @@ static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) INTe(engine2, phase2_cert.engine); INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); #endif /* IEEE8021X_EAPOL */ - for (i = 0; i < 4; i++) - write_wep_key(netw, i, ssid); - INT(wep_tx_keyidx); +#ifdef CONFIG_WEP + { + int i; + + for (i = 0; i < 4; i++) + write_wep_key(netw, i, ssid); + INT(wep_tx_keyidx); + } +#endif /* CONFIG_WEP */ INT(priority); #ifdef IEEE8021X_EAPOL INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 10c096129..2c540457b 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -3949,8 +3949,10 @@ static const struct cipher_info ciphers[] = { { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 }, { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 }, { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 }, +#ifdef CONFIG_WEP { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 }, { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 } +#endif /* CONFIG_WEP */ }; static const struct cipher_info ciphers_group_mgmt[] = { @@ -4012,7 +4014,11 @@ static int ctrl_iface_get_capability_group(int res, char *strict, if (res < 0) { if (strict) return 0; +#ifdef CONFIG_WEP len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); +#else /* CONFIG_WEP */ + len = os_strlcpy(buf, "CCMP TKIP", buflen); +#endif /* CONFIG_WEP */ if (len >= buflen) return -1; return len; diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 4b6dabcc9..55c5dbc99 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -2664,7 +2664,10 @@ dbus_bool_t wpas_dbus_getter_capabilities( /***** group cipher */ if (res < 0) { const char *args[] = { - "ccmp", "tkip", "wep104", "wep40" + "ccmp", "tkip", +#ifdef CONFIG_WEP + "wep104", "wep40" +#endif /* CONFIG_WEP */ }; if (!wpa_dbus_dict_append_string_array( @@ -2691,12 +2694,14 @@ dbus_bool_t wpas_dbus_getter_capabilities( ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "tkip")) || +#ifdef CONFIG_WEP ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) && !wpa_dbus_dict_string_array_add_element( &iter_array, "wep104")) || ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) && !wpa_dbus_dict_string_array_add_element( &iter_array, "wep40")) || +#endif /* CONFIG_WEP */ !wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, @@ -4733,9 +4738,14 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop( /* Group */ switch (ie_data->group_cipher) { +#ifdef CONFIG_WEP case WPA_CIPHER_WEP40: group = "wep40"; break; + case WPA_CIPHER_WEP104: + group = "wep104"; + break; +#endif /* CONFIG_WEP */ case WPA_CIPHER_TKIP: group = "tkip"; break; @@ -4745,9 +4755,6 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop( case WPA_CIPHER_GCMP: group = "gcmp"; break; - case WPA_CIPHER_WEP104: - group = "wep104"; - break; case WPA_CIPHER_CCMP_256: group = "ccmp-256"; break; diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index 5308b494b..a87b58620 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -603,3 +603,11 @@ CONFIG_BGSCAN_SIMPLE=y # Device Provisioning Protocol (DPP) CONFIG_DPP=y + +# Wired equivalent privacy (WEP) +# WEP is an obsolete cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used for anything anymore. The +# functionality needed to use WEP is available in the current wpa_supplicant +# release under this optional build parameter. This functionality is subject to +# be completely removed in a future release. +#CONFIG_WEP=y diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 2851ffc81..37ae306bb 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -479,6 +479,7 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, #ifndef CONFIG_NO_SCAN_PROCESSING +#ifdef CONFIG_WEP static int has_wep_key(struct wpa_ssid *ssid) { int i; @@ -490,6 +491,7 @@ static int has_wep_key(struct wpa_ssid *ssid) return 0; } +#endif /* CONFIG_WEP */ static int wpa_supplicant_match_privacy(struct wpa_bss *bss, @@ -510,8 +512,10 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss, return 1; #endif /* CONFIG_OWE */ +#ifdef CONFIG_WEP if (has_wep_key(ssid)) privacy = 1; +#endif /* CONFIG_WEP */ #ifdef IEEE8021X_EAPOL if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && @@ -540,17 +544,21 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, int proto_match = 0; const u8 *rsn_ie, *wpa_ie; int ret; +#ifdef CONFIG_WEP int wep_ok; +#endif /* CONFIG_WEP */ ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss); if (ret >= 0) return ret; +#ifdef CONFIG_WEP /* Allow TSN if local configuration accepts WEP use without WPA/WPA2 */ wep_ok = !wpa_key_mgmt_wpa(ssid->key_mgmt) && (((ssid->key_mgmt & WPA_KEY_MGMT_NONE) && ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) || (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)); +#endif /* CONFIG_WEP */ rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); while ((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) && rsn_ie) { @@ -567,6 +575,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, if (!ie.has_group) ie.group_cipher = wpa_default_rsn_cipher(bss->freq); +#ifdef CONFIG_WEP if (wep_ok && (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) { @@ -575,6 +584,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, " selected based on TSN in RSN IE"); return 1; } +#endif /* CONFIG_WEP */ if (!(ie.proto & ssid->proto) && !(ssid->proto & WPA_PROTO_OSEN)) { @@ -655,6 +665,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, break; } +#ifdef CONFIG_WEP if (wep_ok && (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) { @@ -663,6 +674,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, " selected based on TSN in WPA IE"); return 1; } +#endif /* CONFIG_WEP */ if (!(ie.proto & ssid->proto)) { if (debug_print) @@ -1236,6 +1248,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, continue; } +#ifdef CONFIG_WEP if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) && has_wep_key(ssid)) { if (debug_print) @@ -1243,6 +1256,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, " skip - ignore WPA/WPA2 AP for WEP network block"); continue; } +#endif /* CONFIG_WEP */ if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen && !rsn_osen) { @@ -3077,6 +3091,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, wpa_s->pending_eapol_rx = NULL; } +#ifdef CONFIG_WEP if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_s->current_ssid && @@ -3084,6 +3099,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, /* Set static WEP keys again */ wpa_set_wep_keys(wpa_s, wpa_s->current_ssid); } +#endif /* CONFIG_WEP */ #ifdef CONFIG_IBSS_RSN if (wpa_s->current_ssid && diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 81151a7fb..c320c249b 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -286,7 +286,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS) const u8 *md = NULL; #endif /* CONFIG_IEEE80211R || CONFIG_FILS */ - int i, bssid_changed; + int bssid_changed; struct wpabuf *resp = NULL; u8 ext_capab[18]; int ext_capab_len; @@ -370,12 +370,18 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_SAE */ - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) - params.wep_key[i] = ssid->wep_key[i]; - params.wep_key_len[i] = ssid->wep_key_len[i]; +#ifdef CONFIG_WEP + { + int i; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (ssid->wep_key_len[i]) + params.wep_key[i] = ssid->wep_key[i]; + params.wep_key_len[i] = ssid->wep_key_len[i]; + } + params.wep_tx_keyidx = ssid->wep_tx_keyidx; } - params.wep_tx_keyidx = ssid->wep_tx_keyidx; +#endif /* CONFIG_WEP */ if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 634fb290e..9d77efd4e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -130,6 +130,7 @@ static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s); #endif /* CONFIG_OWE */ +#ifdef CONFIG_WEP /* Configure default/group WEP keys for static WEP */ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { @@ -150,6 +151,7 @@ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) return set; } +#endif /* CONFIG_WEP */ int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, @@ -396,7 +398,9 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { +#ifdef CONFIG_WEP int i; +#endif /* CONFIG_WEP */ if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) wpa_s->key_mgmt = WPA_KEY_MGMT_WPS; @@ -414,6 +418,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, wpa_s->group_cipher = WPA_CIPHER_NONE; wpa_s->mgmt_group_cipher = 0; +#ifdef CONFIG_WEP for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i] > 5) { wpa_s->pairwise_cipher = WPA_CIPHER_WEP104; @@ -425,6 +430,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, break; } } +#endif /* CONFIG_WEP */ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0); wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); @@ -3319,7 +3325,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) struct wpa_supplicant *wpa_s = work->wpa_s; u8 *wpa_ie; const u8 *edmg_ie_oper; - int use_crypt, ret, i, bssid_changed; + int use_crypt, ret, bssid_changed; unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt; struct wpa_driver_associate_params params; int wep_keys_set = 0; @@ -3429,10 +3435,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) use_crypt = 0; +#ifdef CONFIG_WEP if (wpa_set_wep_keys(wpa_s, ssid)) { use_crypt = 1; wep_keys_set = 1; } +#endif /* CONFIG_WEP */ } if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) use_crypt = 0; @@ -3577,12 +3585,18 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_s->auth_alg = params.auth_alg; params.mode = ssid->mode; params.bg_scan_period = ssid->bg_scan_period; - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) - params.wep_key[i] = ssid->wep_key[i]; - params.wep_key_len[i] = ssid->wep_key_len[i]; +#ifdef CONFIG_WEP + { + int i; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (ssid->wep_key_len[i]) + params.wep_key[i] = ssid->wep_key[i]; + params.wep_key_len[i] = ssid->wep_key_len[i]; + } + params.wep_tx_keyidx = ssid->wep_tx_keyidx; } - params.wep_tx_keyidx = ssid->wep_tx_keyidx; +#endif /* CONFIG_WEP */ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) && (params.key_mgmt_suite == WPA_KEY_MGMT_PSK || @@ -3740,11 +3754,13 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0); } +#ifdef CONFIG_WEP if (wep_keys_set && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) { /* Set static WEP keys again */ wpa_set_wep_keys(wpa_s, ssid); } +#endif /* CONFIG_WEP */ if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) { /* @@ -7330,8 +7346,10 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s, int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { +#ifdef CONFIG_WEP int i; unsigned int drv_enc; +#endif /* CONFIG_WEP */ if (wpa_s->p2p_mgmt) return 1; /* no normal network profiles on p2p_mgmt interface */ @@ -7342,6 +7360,7 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) if (ssid->disabled) return 1; +#ifdef CONFIG_WEP if (wpa_s->drv_capa_known) drv_enc = wpa_s->drv_enc; else @@ -7359,6 +7378,7 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) continue; return 1; /* invalid WEP key */ } +#endif /* CONFIG_WEP */ if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk && diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 5ddefce08..cef70a6f5 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -227,6 +227,7 @@ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, } +#ifdef CONFIG_WEP /** * wpa_eapol_set_wep_key - set WEP key for the driver * @ctx: Pointer to wpa_supplicant data (wpa_s) @@ -254,6 +255,7 @@ static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx, unicast ? KEY_FLAG_PAIRWISE_RX_TX : KEY_FLAG_GROUP_RX_TX_DEFAULT); } +#endif /* CONFIG_WEP */ static void wpa_supplicant_aborted_cached(void *ctx) @@ -1133,7 +1135,9 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) ctx->preauth = 0; ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; ctx->eapol_send = wpa_supplicant_eapol_send; +#ifdef CONFIG_WEP ctx->set_wep_key = wpa_eapol_set_wep_key; +#endif /* CONFIG_WEP */ #ifndef CONFIG_NO_CONFIG_BLOBS ctx->set_config_blob = wpa_supplicant_set_config_blob; ctx->get_config_blob = wpa_supplicant_get_config_blob; From 7a9c36722511ce4df88b76cceceb241d6c6a151e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 28 Feb 2020 15:50:47 -0800 Subject: [PATCH 0109/1105] DBus: Add "sae" to interface key_mgmt capabilities This will be present when the driver supports SAE and it's included in the wpa_supplicant build. Signed-off-by: Brian Norris --- doc/dbus.doxygen | 2 +- wpa_supplicant/dbus/dbus_new_handlers.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen index b2b4389c9..a2e5de262 100644 --- a/doc/dbus.doxygen +++ b/doc/dbus.doxygen @@ -651,7 +651,7 @@ fi.w1.wpa_supplicant1.CreateInterface. PairwiseasPossible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "none" GroupasPossible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "wep104", "wep40" GroupMgmtasPossible array elements: "aes-128-cmac", "bip-gmac-128", "bip-gmac-256", "bip-cmac-256" - KeyMgmtasPossible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "ieee8021x", "wpa-none", "wps", "none" + KeyMgmtasPossible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "sae", "ieee8021x", "wpa-none", "wps", "none" ProtocolasPossible array elements: "rsn", "wpa" AuthAlgasPossible array elements: "open", "shared", "leap" ScanasPossible array elements: "active", "passive", "ssid" diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 55c5dbc99..c842c50e9 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -2798,6 +2798,12 @@ dbus_bool_t wpas_dbus_getter_capabilities( goto nomem; #endif /* CONFIG_WPS */ +#ifdef CONFIG_SAE + if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) && + !wpa_dbus_dict_string_array_add_element(&iter_array, "sae")) + goto nomem; +#endif /* CONFIG_SAE */ + if (!wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, From d046f2a9f93691215ed112080abd0954557cd90c Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Mon, 24 Feb 2020 11:14:26 +0200 Subject: [PATCH 0110/1105] nl80211: Register for SAE Authentication frames more strictly If the driver requires external SAE authentication, it would result in registration for all Authentication frames, so even non-SAE Authentication frames might be forwarded to user space instead of being handled internally. Fix this by using a more strict match pattern, limiting the registration to the SAE authentication algorithm only. Signed-off-by: Andrei Otcheretianski --- src/drivers/driver_nl80211.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 18e4b8eef..c29142f0f 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2182,6 +2182,7 @@ static int nl80211_init_connect_handle(struct i802_bss *bss) static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) { struct wpa_driver_nl80211_data *drv = bss->drv; + u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4); int ret = 0; if (nl80211_alloc_mgmt_handle(bss)) @@ -2189,13 +2190,14 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP " "handle %p", bss->nl_mgmt); - if (drv->nlmode == NL80211_IFTYPE_ADHOC || - ((drv->capa.flags & WPA_DRIVER_FLAGS_SAE) && - !(drv->capa.flags & WPA_DRIVER_FLAGS_SME))) { - u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4); - + if (drv->nlmode == NL80211_IFTYPE_ADHOC) { /* register for any AUTH message */ nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0); + } else if ((drv->capa.flags & WPA_DRIVER_FLAGS_SAE) && + !(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { + /* register for SAE Authentication frames */ + nl80211_register_frame(bss, bss->nl_mgmt, type, + (u8 *) "\x03\x00", 2); } #ifdef CONFIG_INTERWORKING From c4988e73c09be168c060eec75e5a6834c89dcf58 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 24 Feb 2020 11:14:27 +0200 Subject: [PATCH 0111/1105] driver: Extend send_mlme() with wait option PASN authentication can be performed while a station interface is connected to an AP. To allow sending PASN frames while connected, extend the send_mlme() driver callback to also allow a wait option. Update the relevant drivers and wpa_supplicant accordingly. hostapd calls for send_mlme() are left unchanged, since the wait option is not required there. Signed-off-by: Ilan Peer --- src/ap/ap_drv_ops.c | 2 +- src/drivers/driver.h | 4 +++- src/drivers/driver_atheros.c | 2 +- src/drivers/driver_hostap.c | 10 +++++----- src/drivers/driver_nl80211.c | 4 ++-- wpa_supplicant/driver_i.h | 4 ++-- wpa_supplicant/ibss_rsn.c | 2 +- wpa_supplicant/p2p_supplicant.c | 2 +- wpa_supplicant/sme.c | 4 ++-- 9 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index c217d9b24..0f5e829ff 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -714,7 +714,7 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd, if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv) return 0; return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, - csa_offs, csa_offs_len, no_encrypt); + csa_offs, csa_offs_len, no_encrypt, 0); } diff --git a/src/drivers/driver.h b/src/drivers/driver.h index cd1ec31a1..bb187b8bf 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2715,11 +2715,13 @@ struct wpa_driver_ops { * @csa_offs_len: Number of elements in csa_offs * @no_encrypt: Do not encrypt frame even if appropriate key exists * (used only for testing purposes) + * @wait: Time to wait off-channel for a response (in ms), or zero * Returns: 0 on success, -1 on failure */ int (*send_mlme)(void *priv, const u8 *data, size_t data_len, int noack, unsigned int freq, const u16 *csa_offs, - size_t csa_offs_len, int no_encrypt); + size_t csa_offs_len, int no_encrypt, + unsigned int wait); /** * update_ft_ies - Update FT (IEEE 802.11r) IEs diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c index 2014f9db4..d630c3dc4 100644 --- a/src/drivers/driver_atheros.c +++ b/src/drivers/driver_atheros.c @@ -1965,7 +1965,7 @@ static int atheros_set_ap(void *priv, struct wpa_driver_ap_params *params) static int atheros_send_mgmt(void *priv, const u8 *frm, size_t data_len, int noack, unsigned int freq, const u16 *csa_offs, size_t csa_offs_len, - int no_encrypt) + int no_encrypt, unsigned int wait) { struct atheros_driver_data *drv = priv; u8 buf[1510]; diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c index cfc52c7f3..b9c42e4db 100644 --- a/src/drivers/driver_hostap.c +++ b/src/drivers/driver_hostap.c @@ -264,7 +264,7 @@ static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr) static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack, unsigned int freq, const u16 *csa_offs, size_t csa_offs_len, - int no_encrypt) + int no_encrypt, unsigned int wait) { struct hostap_driver_data *drv = priv; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg; @@ -313,7 +313,7 @@ static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data, pos += 2; memcpy(pos, data, data_len); - res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0, NULL, 0, 0); + res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0, NULL, 0, 0, 0); if (res < 0) { wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - " "failed: %d (%s)", @@ -1055,7 +1055,7 @@ static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, memcpy(mgmt.bssid, own_addr, ETH_ALEN); mgmt.u.deauth.reason_code = host_to_le16(reason); return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0, 0, NULL, 0, 0); + sizeof(mgmt.u.deauth), 0, 0, NULL, 0, 0, 0); } @@ -1093,7 +1093,7 @@ static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, memcpy(mgmt.bssid, own_addr, ETH_ALEN); mgmt.u.disassoc.reason_code = host_to_le16(reason); return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc), 0, 0, NULL, 0, 0); + sizeof(mgmt.u.disassoc), 0, 0, NULL, 0, 0, 0); } @@ -1173,7 +1173,7 @@ static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr, os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - hostap_send_mlme(priv, (u8 *) &hdr, sizeof(hdr), 0, 0, NULL, 0, 0); + hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0, NULL, 0, 0, 0); } diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index c29142f0f..ecedc40f5 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8846,11 +8846,11 @@ static int driver_nl80211_send_mlme(void *priv, const u8 *data, size_t data_len, int noack, unsigned int freq, const u16 *csa_offs, size_t csa_offs_len, - int no_encrypt) + int no_encrypt, unsigned int wait) { struct i802_bss *bss = priv; return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack, - freq, 0, 0, 0, csa_offs, + freq, 0, 0, wait, csa_offs, csa_offs_len, no_encrypt); } diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 45b62bdea..d3fb58707 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -312,12 +312,12 @@ static inline int wpa_drv_set_country(struct wpa_supplicant *wpa_s, static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s, const u8 *data, size_t data_len, int noack, - unsigned int freq) + unsigned int freq, unsigned int wait) { if (wpa_s->driver->send_mlme) return wpa_s->driver->send_mlme(wpa_s->drv_priv, data, data_len, noack, - freq, NULL, 0, 0); + freq, NULL, 0, 0, wait); return -1; } diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index ea909a91c..02e63904c 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -520,7 +520,7 @@ static int ibss_rsn_send_auth(struct ibss_rsn *ibss_rsn, const u8 *da, int seq) wpa_printf(MSG_DEBUG, "RSN: IBSS TX Auth frame (SEQ %d) to " MACSTR, seq, MAC2STR(da)); - return wpa_drv_send_mlme(wpa_s, (u8 *) &auth, auth_length, 0, 0); + return wpa_drv_send_mlme(wpa_s, (u8 *) &auth, auth_length, 0, 0, 0); } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 41d50f397..e86c082b3 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2691,7 +2691,7 @@ static int wpas_send_probe_resp(void *ctx, const struct wpabuf *buf, { struct wpa_supplicant *wpa_s = ctx; return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, - freq); + freq, 0); } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index c320c249b..d0088f9f4 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1021,7 +1021,7 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s, bssid, 1, wpa_s->sme.seq_num, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS); - wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0); + wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0); wpabuf_free(resp); wpabuf_free(buf); @@ -1091,7 +1091,7 @@ static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s, sme_external_auth_build_buf(buf, resp, wpa_s->own_addr, da, 2, wpa_s->sme.seq_num, WLAN_STATUS_SUCCESS); - wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0); + wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0); wpabuf_free(resp); wpabuf_free(buf); } From e8ae97aebe71cf02e0aa480bfdaa6a3520ee5d74 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 24 Feb 2020 11:14:29 +0200 Subject: [PATCH 0112/1105] nl80211: Allow TX status for Authentication frames To support PASN authentication flow, where Authentication frames are sent by wpa_supplicant using the send_mlme() callback, modify the logic to also send EVENT_TX_STATUS for Authentication frames. Signed-off-by: Ilan Peer --- src/drivers/driver_nl80211_event.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 8327644fb..f4b0580f4 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -683,11 +683,16 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv, size_t len, struct nlattr *ack) { union wpa_event_data event; - const struct ieee80211_hdr *hdr; - u16 fc; + const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame; + u16 fc = le_to_host16(hdr->frame_control); wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event"); - if (!is_ap_interface(drv->nlmode)) { + + if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) + return; + + if (!is_ap_interface(drv->nlmode) && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { u64 cookie_val; if (!cookie) @@ -701,11 +706,13 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv, " (match)" : " (unknown)", ack != NULL); if (cookie_val != drv->send_frame_cookie) return; + } else if (!is_ap_interface(drv->nlmode) && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) { + wpa_printf(MSG_DEBUG, + "nl80211: Authentication frame TX status: ack=%d", + !!ack); } - hdr = (const struct ieee80211_hdr *) frame; - fc = le_to_host16(hdr->frame_control); - os_memset(&event, 0, sizeof(event)); event.tx_status.type = WLAN_FC_GET_TYPE(fc); event.tx_status.stype = WLAN_FC_GET_STYPE(fc); From 94773d40fa95a25e03eb73f339d4f76956ce1054 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 24 Feb 2020 11:14:31 +0200 Subject: [PATCH 0113/1105] crypto: Add a function to get the ECDH prime length crypto_ecdh_prime_len() can now be used to fetch the length (in octets) of the prime used in ECDH. Signed-off-by: Ilan Peer --- src/crypto/crypto.h | 1 + src/crypto/crypto_openssl.c | 6 ++++++ src/crypto/crypto_wolfssl.c | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 440da0302..7c7515f6b 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -916,5 +916,6 @@ struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y); struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, const u8 *key, size_t len); void crypto_ecdh_deinit(struct crypto_ecdh *ecdh); +size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh); #endif /* CRYPTO_H */ diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index 783b293e9..47b6ebbd6 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -2168,4 +2168,10 @@ void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) } } + +size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) +{ + return crypto_ec_prime_len(ecdh->ec); +} + #endif /* CONFIG_ECC */ diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c index 85ce565bd..dc68bd651 100644 --- a/src/crypto/crypto_wolfssl.c +++ b/src/crypto/crypto_wolfssl.c @@ -1834,4 +1834,10 @@ fail: goto done; } + +size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) +{ + return crypto_ec_prime_len(ecdh->ec); +} + #endif /* CONFIG_ECC */ From e636bc855f0982009d00bfb890b3841bcb9d53cc Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 24 Feb 2020 11:14:32 +0200 Subject: [PATCH 0114/1105] WPA: Rename FILS wrapped data IEEE P802.11az/D2.0 renamed the FILS Wrapped Data element, removing the FILS prefix. Change the code accordingly. Signed-off-by: Ilan Peer --- src/ap/ieee802_11.c | 20 ++++++++++---------- src/common/ieee802_11_common.c | 6 +++--- src/common/ieee802_11_common.h | 4 ++-- src/common/ieee802_11_defs.h | 2 +- src/rsn_supp/wpa.c | 16 ++++++++-------- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 47beaa15b..70de7d856 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1820,11 +1820,11 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, FILS_SESSION_LEN); os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN); - /* FILS Wrapped Data */ - if (elems.fils_wrapped_data) { + /* Wrapped Data */ + if (elems.wrapped_data) { wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data", - elems.fils_wrapped_data, - elems.fils_wrapped_data_len); + elems.wrapped_data, + elems.wrapped_data_len); if (!pmksa) { #ifndef CONFIG_NO_RADIUS if (!sta->eapol_sm) { @@ -1834,8 +1834,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, wpa_printf(MSG_DEBUG, "FILS: Forward EAP-Initiate/Re-auth to authentication server"); ieee802_1x_encapsulate_radius( - hapd, sta, elems.fils_wrapped_data, - elems.fils_wrapped_data_len); + hapd, sta, elems.wrapped_data, + elems.wrapped_data_len); sta->fils_pending_cb = cb; wpa_printf(MSG_DEBUG, "FILS: Will send Authentication frame once the response from authentication server is available"); @@ -1844,8 +1844,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, * to maintain a copy of the EAP-Initiate/Reauth * message. */ if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm), - elems.fils_wrapped_data, - elems.fils_wrapped_data_len, + elems.wrapped_data, + elems.wrapped_data_len, sta->fils_erp_pmkid) == 0) sta->fils_erp_pmkid_set = 1; return; @@ -1988,12 +1988,12 @@ prepare_auth_resp_fils(struct hostapd_data *hapd, wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION); wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN); - /* FILS Wrapped Data */ + /* Wrapped Data */ if (!pmksa && erp_resp) { wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */ wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */ /* Element ID Extension */ - wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA); + wpabuf_put_u8(data, WLAN_EID_EXT_WRAPPED_DATA); wpabuf_put_buf(data, erp_resp); if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm), diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 36005d75f..679170d49 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -245,9 +245,9 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, elems->key_delivery = pos; elems->key_delivery_len = elen; break; - case WLAN_EID_EXT_FILS_WRAPPED_DATA: - elems->fils_wrapped_data = pos; - elems->fils_wrapped_data_len = elen; + case WLAN_EID_EXT_WRAPPED_DATA: + elems->wrapped_data = pos; + elems->wrapped_data_len = elen; break; case WLAN_EID_EXT_FILS_PUBLIC_KEY: if (elen < 1) diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index d13316969..bb2793d08 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -85,7 +85,7 @@ struct ieee802_11_elems { const u8 *fils_hlp; const u8 *fils_ip_addr_assign; const u8 *key_delivery; - const u8 *fils_wrapped_data; + const u8 *wrapped_data; const u8 *fils_pk; const u8 *fils_nonce; const u8 *owe_dh; @@ -138,7 +138,7 @@ struct ieee802_11_elems { u8 fils_hlp_len; u8 fils_ip_addr_assign_len; u8 key_delivery_len; - u8 fils_wrapped_data_len; + u8 wrapped_data_len; u8 fils_pk_len; u8 owe_dh_len; u8 power_capab_len; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index a78ed0a12..7c51574b5 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -458,7 +458,7 @@ #define WLAN_EID_EXT_FILS_HLP_CONTAINER 5 #define WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN 6 #define WLAN_EID_EXT_KEY_DELIVERY 7 -#define WLAN_EID_EXT_FILS_WRAPPED_DATA 8 +#define WLAN_EID_EXT_WRAPPED_DATA 8 #define WLAN_EID_EXT_FTM_SYNC_INFO 9 #define WLAN_EID_EXT_EXTENDED_REQUEST 10 #define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11 diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 263e2108a..4ead4c516 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3867,13 +3867,13 @@ struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md) wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION); wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN); - /* FILS Wrapped Data */ + /* Wrapped Data */ sm->fils_erp_pmkid_set = 0; if (erp_msg) { wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */ /* Element ID Extension */ - wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_WRAPPED_DATA); + wpabuf_put_u8(buf, WLAN_EID_EXT_WRAPPED_DATA); wpabuf_put_buf(buf, erp_msg); /* Calculate pending PMKID here so that we do not need to * maintain a copy of the EAP-Initiate/Reauth message. */ @@ -4078,16 +4078,16 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, goto fail; } - /* FILS Wrapped Data */ - if (!sm->cur_pmksa && elems.fils_wrapped_data) { + /* Wrapped Data */ + if (!sm->cur_pmksa && elems.wrapped_data) { u8 rmsk[ERP_MAX_KEY_LEN]; size_t rmsk_len; wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data", - elems.fils_wrapped_data, - elems.fils_wrapped_data_len); - eapol_sm_process_erp_finish(sm->eapol, elems.fils_wrapped_data, - elems.fils_wrapped_data_len); + elems.wrapped_data, + elems.wrapped_data_len); + eapol_sm_process_erp_finish(sm->eapol, elems.wrapped_data, + elems.wrapped_data_len); if (eapol_sm_failed(sm->eapol)) goto fail; From 101da59aa2115350b9ebfb592856600ed959ea8d Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 24 Feb 2020 11:14:33 +0200 Subject: [PATCH 0115/1105] common: Add support for element defragmentation Add support for element defragmentation as defined in IEEE P802.11-REVmd/D3.0, 10.28.12 (Element defragmentation). Signed-off-by: Ilan Peer --- src/common/ieee802_11_common.c | 114 ++++++++++++++++++++++++++++++++- src/common/ieee802_11_common.h | 23 +++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 679170d49..71876c084 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -206,6 +206,8 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, ext_id = *pos++; elen--; + elems->frag_ies.last_eid_ext = 0; + switch (ext_id) { case WLAN_EID_EXT_ASSOC_DELAY_INFO: if (elen != 1) @@ -295,10 +297,39 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, return -1; } + if (elen == 254) + elems->frag_ies.last_eid_ext = ext_id; + return 0; } +static void ieee802_11_parse_fragment(struct frag_ies_info *frag_ies, + const u8 *pos, u8 elen) +{ + if (frag_ies->n_frags >= MAX_NUM_FRAG_IES_SUPPORTED) { + wpa_printf(MSG_MSGDUMP, "Too many element fragments - skip"); + return; + } + + /* + * Note: while EID == 0 is a valid ID (SSID IE), it should not be + * fragmented. + */ + if (!frag_ies->last_eid) { + wpa_printf(MSG_MSGDUMP, + "Fragment without a valid last element - skip"); + return; + } + + frag_ies->frags[frag_ies->n_frags].ie = pos; + frag_ies->frags[frag_ies->n_frags].ie_len = elen; + frag_ies->frags[frag_ies->n_frags].eid = frag_ies->last_eid; + frag_ies->frags[frag_ies->n_frags].eid_ext = frag_ies->last_eid_ext; + frag_ies->n_frags++; +} + + /** * ieee802_11_parse_elems - Parse information elements in management frames * @start: Pointer to the start of IEs @@ -516,7 +547,7 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->dils_len = elen; break; case WLAN_EID_FRAGMENT: - /* TODO */ + ieee802_11_parse_fragment(&elems->frag_ies, pos, elen); break; case WLAN_EID_EXTENSION: if (ieee802_11_parse_extension(pos, elen, elems, @@ -532,6 +563,12 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, id, elen); break; } + + if (id != WLAN_EID_FRAGMENT && elen == 255) + elems->frag_ies.last_eid = id; + + if (id == WLAN_EID_EXTENSION && !elems->frag_ies.last_eid_ext) + elems->frag_ies.last_eid = 0; } if (!for_each_element_completed(elem, start, len)) { @@ -2391,3 +2428,78 @@ int op_class_to_ch_width(u8 op_class) } return CHANWIDTH_USE_HT; } + + +struct wpabuf * ieee802_11_defrag_data(struct ieee802_11_elems *elems, + u8 eid, u8 eid_ext, + const u8 *data, u8 len) +{ + struct frag_ies_info *frag_ies = &elems->frag_ies; + struct wpabuf *buf; + unsigned int i; + + if (!elems || !data || !len) + return NULL; + + buf = wpabuf_alloc_copy(data, len); + if (!buf) + return NULL; + + for (i = 0; i < frag_ies->n_frags; i++) { + int ret; + + if (frag_ies->frags[i].eid != eid || + frag_ies->frags[i].eid_ext != eid_ext) + continue; + + ret = wpabuf_resize(&buf, frag_ies->frags[i].ie_len); + if (ret < 0) { + wpabuf_free(buf); + return NULL; + } + + /* Copy only the fragment data (without the EID and length) */ + wpabuf_put_data(buf, frag_ies->frags[i].ie, + frag_ies->frags[i].ie_len); + } + + return buf; +} + + +struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems, + u8 eid, u8 eid_ext) +{ + const u8 *data; + u8 len; + + /* + * TODO: Defragmentation mechanism can be supported for all IEs. For now + * handle only those that are used (or use ieee802_11_defrag_data()). + */ + switch (eid) { + case WLAN_EID_EXTENSION: + switch (eid_ext) { + case WLAN_EID_EXT_FILS_HLP_CONTAINER: + data = elems->fils_hlp; + len = elems->fils_hlp_len; + break; + case WLAN_EID_EXT_WRAPPED_DATA: + data = elems->wrapped_data; + len = elems->wrapped_data_len; + break; + default: + wpa_printf(MSG_DEBUG, + "Defragmentation not supported. eid_ext=%u", + eid_ext); + return NULL; + } + break; + default: + wpa_printf(MSG_DEBUG, + "Defragmentation not supported. eid=%u", eid); + return NULL; + } + + return ieee802_11_defrag_data(elems, eid, eid_ext, data, len); +} diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index bb2793d08..7994cd7d6 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -21,6 +21,7 @@ struct element { struct hostapd_hw_modes; #define MAX_NOF_MB_IES_SUPPORTED 5 +#define MAX_NUM_FRAG_IES_SUPPORTED 3 struct mb_ies_info { struct { @@ -30,6 +31,21 @@ struct mb_ies_info { u8 nof_ies; }; +struct frag_ies_info { + struct { + u8 eid; + u8 eid_ext; + const u8 *ie; + u8 ie_len; + } frags[MAX_NUM_FRAG_IES_SUPPORTED]; + + u8 n_frags; + + /* the last parsed element ID and element extension ID */ + u8 last_eid; + u8 last_eid_ext; +}; + /* Parsed Information Elements */ struct ieee802_11_elems { const u8 *ssid; @@ -151,6 +167,7 @@ struct ieee802_11_elems { u8 short_ssid_list_len; struct mb_ies_info mb_ies; + struct frag_ies_info frag_ies; }; typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; @@ -293,4 +310,10 @@ void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel, int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed, struct ieee80211_edmg_config requested); +struct wpabuf * ieee802_11_defrag_data(struct ieee802_11_elems *elems, + u8 eid, u8 eid_ext, + const u8 *data, u8 len); +struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems, + u8 eid, u8 eid_ext); + #endif /* IEEE802_11_COMMON_H */ From d9aafb75f122cecfbefda0f4d17c6d3b7a0c32ec Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 1 Mar 2020 19:53:16 +0200 Subject: [PATCH 0116/1105] tests: SAE and PSK with multiple passwords/passphrases Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index f6dff7314..37a3f8838 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -2466,3 +2466,41 @@ def test_sae_pmk_lifetime(dev, apdev): dev[0].wait_connected() if "sae_group" not in dev[0].get_status(): raise Exception("SAE authentication not used after PMKSA cache entry expiration") + +def test_sae_and_psk_multiple_passwords(dev, apdev, params): + """SAE and PSK with multiple passwords/passphrases""" + check_sae_capab(dev[0]) + check_sae_capab(dev[1]) + addr0 = dev[0].own_addr() + addr1 = dev[1].own_addr() + psk_file = os.path.join(params['logdir'], + 'sae_and_psk_multiple_passwords.wpa_psk') + with open(psk_file, 'w') as f: + f.write(addr0 + ' passphrase0\n') + f.write(addr1 + ' passphrase1\n') + params = hostapd.wpa2_params(ssid="test-sae") + params['wpa_key_mgmt'] = 'SAE WPA-PSK' + params['sae_password'] = ['passphrase0|mac=' + addr0, + 'passphrase1|mac=' + addr1] + params['wpa_psk_file'] = psk_file + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", sae_password="passphrase0", + key_mgmt="SAE", scan_freq="2412") + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + + dev[0].connect("test-sae", psk="passphrase0", scan_freq="2412") + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + + dev[1].set("sae_groups", "") + dev[1].connect("test-sae", sae_password="passphrase1", + key_mgmt="SAE", scan_freq="2412") + dev[1].request("REMOVE_NETWORK all") + dev[1].wait_disconnected() + + dev[1].connect("test-sae", psk="passphrase1", scan_freq="2412") + dev[1].request("REMOVE_NETWORK all") + dev[1].wait_disconnected() From 852d370f6568c647330b492242e5377fb7bd24c6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 1 Mar 2020 20:57:14 +0200 Subject: [PATCH 0117/1105] Silence a compiler warning in no-WEP and no-EAP builds wep_keys_set was not used in wpas_start_assoc_cb() without IEEE8021X_EAPOL, so need to make this local variable conditional on build options. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 9d77efd4e..81ffa7264 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3328,7 +3328,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) int use_crypt, ret, bssid_changed; unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt; struct wpa_driver_associate_params params; +#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL) int wep_keys_set = 0; +#endif /* CONFIG_WEP || IEEE8021X_EAPOL */ int assoc_failed = 0; struct wpa_ssid *old_ssid; u8 prev_bssid[ETH_ALEN]; From c1a6b1e47e8fe9ef86f2aeb2a37c1955d27b17d2 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Fri, 10 Jan 2020 00:04:59 +0100 Subject: [PATCH 0118/1105] privsep: Add key_flag to set_key() Pass through the new key_flag to wpa_priv. Signed-off-by: Alexander Wetzel --- src/common/privsep_commands.h | 1 + src/drivers/driver_privsep.c | 1 + wpa_supplicant/wpa_priv.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/common/privsep_commands.h b/src/common/privsep_commands.h index b85c6c347..d2c4bbd5e 100644 --- a/src/common/privsep_commands.h +++ b/src/common/privsep_commands.h @@ -82,6 +82,7 @@ struct privsep_cmd_set_key { size_t seq_len; u8 key[32]; size_t key_len; + enum key_flag key_flag; }; enum privsep_event { diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c index 807657ebc..6d05ff551 100644 --- a/src/drivers/driver_privsep.c +++ b/src/drivers/driver_privsep.c @@ -230,6 +230,7 @@ static int wpa_driver_privsep_set_key(void *priv, os_memset(cmd.addr, 0xff, ETH_ALEN); cmd.key_idx = key_idx; cmd.set_tx = set_tx; + cmd.key_flag = params->key_flag; if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) { os_memcpy(cmd.seq, seq, seq_len); cmd.seq_len = seq_len; diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c index c9bcf13fe..c5d716869 100644 --- a/wpa_supplicant/wpa_priv.c +++ b/wpa_supplicant/wpa_priv.c @@ -413,6 +413,7 @@ static void wpa_priv_cmd_set_key(struct wpa_priv_interface *iface, p.seq_len = params->seq_len; p.key = params->key_len ? params->key : NULL; p.key_len = params->key_len; + p.key_flag = params->key_flag; res = iface->driver->set_key(iface->drv_priv, &p); wpa_printf(MSG_DEBUG, "drv->set_key: res=%d", res); From 5bad300565c51a8aa68d510ac731891c357965e8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 1 Mar 2020 21:31:07 +0200 Subject: [PATCH 0119/1105] privsep: Mask out control port capability flag There is no support for using the control port for sending out EAPOL frames through privsep yet, so mask out this capability to fall back to the l2_packet based design. Signed-off-by: Jouni Malinen --- src/drivers/driver_privsep.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c index 6d05ff551..d6735b49c 100644 --- a/src/drivers/driver_privsep.c +++ b/src/drivers/driver_privsep.c @@ -797,6 +797,8 @@ static int wpa_driver_privsep_get_capa(void *priv, capa->extended_capa = NULL; capa->extended_capa_mask = NULL; capa->extended_capa_len = 0; + /* Control port is not yet supported */ + capa->flags &= ~WPA_DRIVER_FLAGS_CONTROL_PORT; return 0; } From 21f835e6406425267f5a677107f7dcf31862e4a0 Mon Sep 17 00:00:00 2001 From: Sachin Shelke Date: Mon, 2 Mar 2020 05:18:41 +0530 Subject: [PATCH 0120/1105] SAE: Allow SAE-only network profile with sae_password to be written The commit a34ca59e (SAE: Allow SAE password to be configured separately (STA)) added sae_password configuration option. We should also consider sae_password in the wpa_config_write() function which stores the valid network block details to an external database. Fixes: a34ca59e4db0 ("SAE: Allow SAE password to be configured separately (STA)") Signed-off-by: Sachin Shelke Signed-off-by: Cathy Luo Signed-off-by: Ganapathi Bhat --- src/common/defs.h | 7 +++++++ wpa_supplicant/config_file.c | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/common/defs.h b/src/common/defs.h index 1e21ec2de..6358c3158 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -82,6 +82,13 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) WPA_KEY_MGMT_FT_FILS_SHA384)); } +static inline int wpa_key_mgmt_wpa_psk_no_sae(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_PSK | + WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256)); +} + static inline int wpa_key_mgmt_wpa_psk(int akm) { return !!(akm & (WPA_KEY_MGMT_PSK | diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index d100d74cb..4c37b61a0 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1642,8 +1642,11 @@ int wpa_config_write(const char *name, struct wpa_config *config) for (ssid = config->ssid; ssid; ssid = ssid->next) { if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary) continue; /* do not save temporary networks */ - if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && - !ssid->passphrase) + if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt) && + !ssid->psk_set && !ssid->passphrase) + continue; /* do not save invalid network */ + if (wpa_key_mgmt_sae(ssid->key_mgmt) && + !ssid->passphrase && !ssid->sae_password) continue; /* do not save invalid network */ fprintf(f, "\nnetwork={\n"); wpa_config_write_network(f, ssid); From 8b077a42e569533459ae529da21a9be91d4166d9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Mar 2020 11:51:38 +0200 Subject: [PATCH 0121/1105] tests: wpa_supplicant config file writing with SAE Signed-off-by: Jouni Malinen --- tests/hwsim/test_wpas_config.py | 50 +++++++++++++++++++++++++++++++++ tests/hwsim/wpasupplicant.py | 4 +++ 2 files changed, 54 insertions(+) diff --git a/tests/hwsim/test_wpas_config.py b/tests/hwsim/test_wpas_config.py index ba408252a..acf19594e 100644 --- a/tests/hwsim/test_wpas_config.py +++ b/tests/hwsim/test_wpas_config.py @@ -10,6 +10,7 @@ import os from wpasupplicant import WpaSupplicant import hostapd +from test_sae import check_sae_capab config_checks = [("ap_scan", "0"), ("update_config", "1"), @@ -594,3 +595,52 @@ def test_wpas_config_file_key_mgmt(dev, apdev, params): wpas.interface_remove("wlan5") wpas.interface_add("wlan5", config=config) + +def check_network_config(config, network_expected, check=None): + with open(config, "r") as f: + data = f.read() + logger.info("Configuration file contents:\n" + data.rstrip()) + if network_expected and "network=" not in data: + raise Exception("Missing network block in configuration data") + if not network_expected and "network=" in data: + raise Exception("Unexpected network block in configuration data") + if check and check not in data: + raise Exception("Missing " + check) + +def test_wpas_config_file_sae(dev, apdev, params): + """wpa_supplicant config file writing with SAE""" + config = os.path.join(params['logdir'], 'wpas_config_file_sae.conf') + with open(config, "w") as f: + f.write("update_config=1\n") + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", config=config) + check_sae_capab(wpas) + + # Valid SAE configuration with sae_password + wpas.connect("test-sae", sae_password="sae-password", key_mgmt="SAE", + only_add_network=True) + wpas.save_config() + check_network_config(config, True, check="key_mgmt=SAE") + + wpas.request("REMOVE_NETWORK all") + wpas.save_config() + check_network_config(config, False) + + # Valid SAE configuration with psk + wpas.connect("test-sae", psk="sae-password", key_mgmt="SAE", + only_add_network=True) + wpas.save_config() + check_network_config(config, True, check="key_mgmt=SAE") + wpas.request("REMOVE_NETWORK all") + + # Invalid PSK configuration with sae_password + wpas.connect("test-psk", sae_password="sae-password", key_mgmt="WPA-PSK", + only_add_network=True) + wpas.save_config() + check_network_config(config, False) + + # Invalid SAE configuration with raw_psk + wpas.connect("test-sae", raw_psk=32*"00", key_mgmt="SAE", + only_add_network=True) + wpas.save_config() + check_network_config(config, False) diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 227cf72a4..e245c3a93 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1434,6 +1434,10 @@ class WpaSupplicant: def note(self, txt): self.request("NOTE " + txt) + def save_config(self): + if "OK" not in self.request("SAVE_CONFIG"): + raise Exception("Failed to save configuration file") + def wait_regdom(self, country_ie=False): for i in range(5): ev = self.wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1) From 43282f73299a3271273a39223429dcd91da950fe Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Chitrapu Date: Thu, 5 Dec 2019 02:57:28 +0000 Subject: [PATCH 0122/1105] mesh: Fix HE enablement on 5 GHz with VHT Incorrect he_enabled parameter was being passed to hostapd_set_freq_params() in mesh which caused HE to be not fully enabled on the 5 GHz band. Fix this by setting freq->he_enabled instead of vht_freq.he_enabled so that the hostapd_set_freq_params() uses the correct he_enabled value (and then ends up copying this to vht_freq.he_enabled in the success case). Fixes: 6e711e7ab32 ("mesh: Do not enable HE on 5 GHz without VHT") Signed-off-by: Pradeep Kumar Chitrapu --- wpa_supplicant/wpa_supplicant.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 81ffa7264..839afe32d 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2494,8 +2494,8 @@ skip_ht40: if (!vht_freq.vht_enabled) return; - /* Enable HE for VHT */ - vht_freq.he_enabled = mode->he_capab[ieee80211_mode].he_supported; + /* Enable HE with VHT for 5 GHz */ + freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; /* setup center_freq1, bandwidth */ for (j = 0; j < ARRAY_SIZE(vht80); j++) { From 97de4a0f9be61c905c3d4c6a83ce969d364c9120 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Mar 2020 19:56:27 +0200 Subject: [PATCH 0123/1105] tests: Verify that HE gets fully enabled for mesh Signed-off-by: Jouni Malinen --- tests/hwsim/test_wpas_mesh.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 85dd384e2..ed38ac129 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -219,6 +219,16 @@ def test_wpas_mesh_open(dev, apdev): if mode != "mesh": raise Exception("Unexpected mode: " + mode) + dev[0].scan(freq="2462") + bss = dev[0].get_bss(dev[1].own_addr()) + if bss and 'ie' in bss and "ff0724" in bss['ie']: + sta = dev[0].request("STA " + dev[1].own_addr()) + logger.info("STA info:\n" + sta.rstrip()) + if "[HE]" not in sta: + raise Exception("Missing STA HE flag") + if "[VHT]" in sta: + raise Exception("Unexpected STA VHT flag") + def test_wpas_mesh_open_no_auto(dev, apdev): """wpa_supplicant open MESH network connectivity""" check_mesh_support(dev[0]) @@ -1059,6 +1069,14 @@ def _test_wpas_mesh_open_vht40(dev, apdev): if "CENTER_FRQ1=5190" not in sig: raise Exception("Unexpected SIGNAL_POLL value(3b): " + str(sig)) + dev[0].scan(freq="5180") + bss = dev[0].get_bss(dev[1].own_addr()) + if bss and 'ie' in bss and "ff0724" in bss['ie']: + sta = dev[0].request("STA " + dev[1].own_addr()) + logger.info("STA info:\n" + sta.rstrip()) + if "[HT][VHT][HE]" not in sta: + raise Exception("Missing STA flags") + dev[0].mesh_group_remove() dev[1].mesh_group_remove() check_mesh_group_removed(dev[0]) From 5fdacce46599fd1a56e7938919b4d80461b02fd1 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Sat, 29 Feb 2020 12:26:36 +0530 Subject: [PATCH 0124/1105] Allow wildcard SSID to be enforced for a specific BSSID scan Specific BSSID scan was replacing wildcard SSID with the known SSID if any BSS with the specified BSSID is available in the known BSSes list. Add control interface support to force use of a wildcard SSID in a specific BSSID scan by user with the new "wildcard_ssid=1" argument to the SCAN command. Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/ctrl_iface.c | 5 +++++ wpa_supplicant/scan.c | 4 +++- wpa_supplicant/wpa_supplicant_i.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 2c540457b..077bd6449 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8193,6 +8193,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->disconnected = 0; os_free(wpa_s->next_scan_freqs); wpa_s->next_scan_freqs = NULL; + os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN); + wpa_s->next_scan_bssid_wildcard_ssid = 0; os_free(wpa_s->select_network_scan_freqs); wpa_s->select_network_scan_freqs = NULL; @@ -8528,6 +8530,9 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, goto done; } os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN); + + wpa_s->next_scan_bssid_wildcard_ssid = + os_strstr(params, "wildcard_ssid=1") != NULL; } pos = params; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 17636e3b6..db1f6e1fa 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1251,7 +1251,8 @@ ssid_list_set: params.bssid = wpa_s->next_scan_bssid; bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid); - if (bss && bss->ssid_len && params.num_ssids == 1 && + if (!wpa_s->next_scan_bssid_wildcard_ssid && + bss && bss->ssid_len && params.num_ssids == 1 && params.ssids[0].ssid_len == 0) { params.ssids[0].ssid = bss->ssid; params.ssids[0].ssid_len = bss->ssid_len; @@ -1328,6 +1329,7 @@ scan: #ifdef CONFIG_INTERWORKING wpa_s->interworking_fast_assoc_tried = 0; #endif /* CONFIG_INTERWORKING */ + wpa_s->next_scan_bssid_wildcard_ssid = 0; if (params.bssid) os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN); } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index de2e6350b..eac7cad2d 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -715,6 +715,7 @@ struct wpa_supplicant { int scan_id[MAX_SCAN_ID]; unsigned int scan_id_count; u8 next_scan_bssid[ETH_ALEN]; + unsigned int next_scan_bssid_wildcard_ssid:1; struct wpa_ssid_value *ssids_from_scan_req; unsigned int num_ssids_from_scan_req; From 744a2f9846c08bddab2a9730c24d8715d6338400 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Mar 2020 20:44:23 +0200 Subject: [PATCH 0125/1105] tests: Specific vs. wildcard SSID in Probe Request frame in BSSID-scan Signed-off-by: Jouni Malinen --- tests/hwsim/test_scan.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index 0b7eca882..56ab9c57d 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -1456,6 +1456,17 @@ def test_scan_parsing(dev, apdev): res = dev[0].request("BSS 02:ff:00:00:00:09") logger.info("Updated BSS:\n" + res) +def get_probe_req_ies(hapd): + for i in range(10): + msg = hapd.mgmt_rx() + if msg is None: + break + if msg['subtype'] != 4: + continue + return parse_ie(binascii.hexlify(msg['payload']).decode()) + + raise Exception("Probe Request not seen") + def test_scan_specific_bssid(dev, apdev): """Scan for a specific BSSID""" dev[0].flush_scan_cache() @@ -1486,6 +1497,29 @@ def test_scan_specific_bssid(dev, apdev): if bss2 and 'beacon_ie' in bss2 and 'ie' in bss2 and bss2['beacon_ie'] == bss2['ie']: raise Exception("Second scan did find Probe Response frame") + hapd.dump_monitor() + hapd.set("ext_mgmt_frame_handling", "1") + + # With specific SSID in the Probe Request frame + dev[0].request("SCAN TYPE=ONLY freq=2412 bssid=" + bssid) + ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10) + if ev is None: + raise Exception("Scan did not complete") + ie = get_probe_req_ies(hapd) + if ie[0] != b"test-scan": + raise Exception("Specific SSID not seen in Probe Request frame") + + hapd.dump_monitor() + + # Without specific SSID in the Probe Request frame + dev[0].request("SCAN TYPE=ONLY freq=2412 wildcard_ssid=1 bssid=" + bssid) + ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10) + if ev is None: + raise Exception("Scan did not complete") + ie = get_probe_req_ies(hapd) + if len(ie[0]) != 0: + raise Exception("Wildcard SSID not seen in Probe Request frame") + def test_scan_probe_req_events(dev, apdev): """Probe Request frame RX events from hostapd""" hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) From 7242087d1c04c6647f22facd6958af7a63f617e2 Mon Sep 17 00:00:00 2001 From: Seevalamuthu Mariappan Date: Fri, 13 Dec 2019 15:46:41 +0530 Subject: [PATCH 0126/1105] DFS: Do not process radar event while disabling an interface In the normal case hostapd_disable_iface() and hostapd_enable_iface() will be done while switching to another DFS channel upon radar detection. In certain scenarios radar detected event can come while hostapd_disable_iface() is in progress and iface->current_mode will be NULL in that scenario. Previously, we did not check for this scenario and proceeded with the radar detection logic which can trigger a segmentation fault. To fix this, avoid proceeding the radar detection event if iface->current_mode is NULL. Signed-off-by: Seevalamuthu Mariappan --- src/ap/dfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index f70ecc946..554231e18 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -1040,8 +1040,10 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, return 0; /* mark radar frequency as invalid */ - set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, - cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE); + res = set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, + cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE); + if (!res) + return 0; /* Skip if reported radar event not overlapped our channels */ res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2); From 4b37d242857d7e5825faa26b09017b64beb230fb Mon Sep 17 00:00:00 2001 From: Seevalamuthu Mariappan Date: Fri, 13 Dec 2019 15:46:41 +0530 Subject: [PATCH 0127/1105] hostapd: Fix to downgrade bandwidth in radar detection Upon radar detection we used to search channels with the same bandwidth. This way we might not find any other channels. If there are no channels available with that bandwidth the AP service will be stopped. To avoid this problem, also search a suitable channel by downgrading the bandwidth. This scenario is applicable during CAC as well. Signed-off-by: Seevalamuthu Mariappan --- src/ap/dfs.c | 90 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 23 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 554231e18..d0b448e29 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -851,6 +851,41 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq, } +static struct hostapd_channel_data * +dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel, + u8 *oper_centr_freq_seg0_idx, + u8 *oper_centr_freq_seg1_idx, int *skip_radar) +{ + struct hostapd_channel_data *channel; + + for (;;) { + channel = dfs_get_valid_channel(iface, secondary_channel, + oper_centr_freq_seg0_idx, + oper_centr_freq_seg1_idx, + *skip_radar); + if (channel) { + wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d", + channel->chan); + return channel; + } + + if (*skip_radar) { + *skip_radar = 0; + } else { + if (iface->conf->vht_oper_chwidth == CHANWIDTH_USE_HT) + break; + *skip_radar = 1; + iface->conf->vht_oper_chwidth--; + } + } + + wpa_printf(MSG_INFO, + "%s: no DFS channels left, waiting for NOP to finish", + __func__); + return NULL; +} + + static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) { struct hostapd_channel_data *channel; @@ -868,8 +903,14 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) skip_radar); if (!channel) { - wpa_printf(MSG_ERROR, "No valid channel available"); - return err; + channel = dfs_downgrade_bandwidth(iface, &secondary_channel, + &oper_centr_freq_seg0_idx, + &oper_centr_freq_seg1_idx, + &skip_radar); + if (!channel) { + wpa_printf(MSG_ERROR, "No valid channel available"); + return err; + } } wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", @@ -898,11 +939,13 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) int secondary_channel; u8 oper_centr_freq_seg0_idx; u8 oper_centr_freq_seg1_idx; + u8 new_vht_oper_chwidth; int skip_radar = 1; struct csa_settings csa_settings; unsigned int i; int err = 1; struct hostapd_hw_modes *cmode = iface->current_mode; + u8 current_vht_oper_chwidth = iface->conf->vht_oper_chwidth; wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", __func__, iface->cac_started ? "yes" : "no", @@ -936,28 +979,25 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) * requires to perform a CAC first. */ skip_radar = 0; - channel = dfs_get_valid_channel(iface, &secondary_channel, - &oper_centr_freq_seg0_idx, - &oper_centr_freq_seg1_idx, - skip_radar); - if (!channel) { - wpa_printf(MSG_INFO, - "%s: no DFS channels left, waiting for NOP to finish", - __func__); + channel = dfs_downgrade_bandwidth(iface, &secondary_channel, + &oper_centr_freq_seg0_idx, + &oper_centr_freq_seg1_idx, + &skip_radar); + if (!channel) return err; + if (!skip_radar) { + iface->freq = channel->freq; + iface->conf->channel = channel->chan; + iface->conf->secondary_channel = secondary_channel; + hostapd_set_oper_centr_freq_seg0_idx( + iface->conf, oper_centr_freq_seg0_idx); + hostapd_set_oper_centr_freq_seg1_idx( + iface->conf, oper_centr_freq_seg1_idx); + + hostapd_disable_iface(iface); + hostapd_enable_iface(iface); + return 0; } - - iface->freq = channel->freq; - iface->conf->channel = channel->chan; - iface->conf->secondary_channel = secondary_channel; - hostapd_set_oper_centr_freq_seg0_idx(iface->conf, - oper_centr_freq_seg0_idx); - hostapd_set_oper_centr_freq_seg1_idx(iface->conf, - oper_centr_freq_seg1_idx); - - hostapd_disable_iface(iface); - hostapd_enable_iface(iface); - return 0; } wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", @@ -966,6 +1006,9 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) "freq=%d chan=%d sec_chan=%d", channel->freq, channel->chan, secondary_channel); + new_vht_oper_chwidth = iface->conf->vht_oper_chwidth; + iface->conf->vht_oper_chwidth = current_vht_oper_chwidth; + /* Setup CSA request */ os_memset(&csa_settings, 0, sizeof(csa_settings)); csa_settings.cs_count = 5; @@ -980,7 +1023,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) iface->conf->ieee80211ac, iface->conf->ieee80211ax, secondary_channel, - hostapd_get_oper_chwidth(iface->conf), + new_vht_oper_chwidth, oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx, cmode->vht_capab, @@ -1004,6 +1047,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) iface->freq = channel->freq; iface->conf->channel = channel->chan; iface->conf->secondary_channel = secondary_channel; + iface->conf->vht_oper_chwidth = new_vht_oper_chwidth; hostapd_set_oper_centr_freq_seg0_idx(iface->conf, oper_centr_freq_seg0_idx); hostapd_set_oper_centr_freq_seg1_idx(iface->conf, From 9c244b542ec7c9ee51c536bed270486d41fbb568 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Mar 2020 18:36:10 +0200 Subject: [PATCH 0128/1105] tests: DFS channel bandwidth downgrade from VHT80 to VHT40 Signed-off-by: Jouni Malinen --- tests/hwsim/test_dfs.py | 88 +++++++++++++++++++++++++++++++++-- tests/hwsim/vm/parallel-vm.py | 1 + 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_dfs.py b/tests/hwsim/test_dfs.py index a10d32b87..2b7fc4a85 100644 --- a/tests/hwsim/test_dfs.py +++ b/tests/hwsim/test_dfs.py @@ -28,7 +28,8 @@ def wait_dfs_event(hapd, event, timeout): def start_dfs_ap(ap, ssid="dfs", ht=True, ht40=False, ht40minus=False, vht80=False, vht20=False, chanlist=None, - channel=None, country="FI", rrm_beacon_report=False): + channel=None, country="FI", rrm_beacon_report=False, + chan100=False): ifname = ap['ifname'] logger.info("Starting AP " + ifname + " on DFS channel") hapd = hostapd.add_ap(ap, {}, no_enable=True) @@ -37,7 +38,10 @@ def start_dfs_ap(ap, ssid="dfs", ht=True, ht40=False, hapd.set("ieee80211d", "1") hapd.set("ieee80211h", "1") hapd.set("hw_mode", "a") - hapd.set("channel", "52") + if chan100: + hapd.set("channel", "100") + else: + hapd.set("channel", "52") if not ht: hapd.set("ieee80211n", "0") if ht40: @@ -48,7 +52,10 @@ def start_dfs_ap(ap, ssid="dfs", ht=True, ht40=False, if vht80: hapd.set("ieee80211ac", "1") hapd.set("vht_oper_chwidth", "1") - hapd.set("vht_oper_centr_freq_seg0_idx", "58") + if chan100: + hapd.set("vht_oper_centr_freq_seg0_idx", "106") + else: + hapd.set("vht_oper_centr_freq_seg0_idx", "58") if vht20: hapd.set("ieee80211ac", "1") hapd.set("vht_oper_chwidth", "0") @@ -526,3 +533,78 @@ def test_dfs_rrm(dev, apdev, params): raise Exception("Beacon report response not received") finally: clear_regdom(hapd, dev) + +def test_dfs_radar_vht80_downgrade(dev, apdev, params): + """DFS channel bandwidth downgrade from VHT80 to VHT40 [long]""" + if not params['long']: + raise HwsimSkip("Skip test case with long duration due to --long not specified") + try: + # Start with 80 MHz channel 100 (5500 MHz) to find a radar + hapd = None + hapd = start_dfs_ap(apdev[0], chanlist="100-140", + ht40=True, vht80=True, chan100=True) + time.sleep(1) + dfs_simulate_radar(hapd) + + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5) + if ev is None: + raise Exception("Timeout on DFS aborted event") + if "success=0 freq=5500" not in ev: + raise Exception("Unexpected DFS aborted event contents: " + ev) + + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5500" not in ev: + raise Exception("Unexpected DFS radar detection freq: " + ev) + + # The only other available 80 MHz channel in the chanlist is + # 116 (5580 MHz), so that will be selected next. + ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5) + if "freq=5580 chan=116 sec_chan=1" not in ev: + raise Exception("Unexpected DFS new freq: " + ev) + + ev = wait_dfs_event(hapd, None, 5) + if "DFS-CAC-START" not in ev: + raise Exception("Unexpected DFS event: " + ev) + if "freq=5580" not in ev: + raise Exception("Unexpected DFS CAC freq: " + ev) + + time.sleep(1) + dfs_simulate_radar(hapd) + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5) + if ev is None: + raise Exception("Timeout on DFS aborted event (2)") + if "success=0 freq=5580" not in ev: + raise Exception("Unexpected DFS aborted event (2) contents: " + ev) + + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5580" not in ev: + raise Exception("Unexpected DFS radar detection (2) freq: " + ev) + + # No more 80 MHz channels are available, so have to downgrade to 40 MHz + # channels and the only remaining one is channel 132 (5660 MHz). + ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5) + if "freq=5660 chan=132 sec_chan=1" not in ev: + raise Exception("Unexpected DFS new freq (2): " + ev) + + ev = wait_dfs_event(hapd, None, 5) + if "DFS-CAC-START" not in ev: + raise Exception("Unexpected DFS event: " + ev) + if "freq=5660" not in ev: + raise Exception("Unexpected DFS CAC freq (2): " + ev) + + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5660" not in ev: + raise Exception("Unexpected DFS freq result: " + ev) + + ev = wait_dfs_event(hapd, None, 5) + if "AP-ENABLED" not in ev: + raise Exception("Unexpected DFS event: " + ev) + dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5660") + dev[0].wait_regdom(country_ie=True) + sig = dev[0].request("SIGNAL_POLL").splitlines() + if "FREQUENCY=5660" not in sig or "WIDTH=40 MHz" not in sig: + raise Exception("Unexpected SIGNAL_POLL value: " + str(sig)) + finally: + clear_regdom(hapd, dev) diff --git a/tests/hwsim/vm/parallel-vm.py b/tests/hwsim/vm/parallel-vm.py index 714b8746c..3dd09584f 100755 --- a/tests/hwsim/vm/parallel-vm.py +++ b/tests/hwsim/vm/parallel-vm.py @@ -58,6 +58,7 @@ long_tests = ["ap_roam_open", "dfs", "dfs_ht40_minus", "dfs_etsi", + "dfs_radar_vht80_downgrade", "ap_acs_dfs", "grpform_cred_ready_timeout", "hostapd_oom_wpa2_eap_connect", From 8f89e57ab5f29ef8765c84b05a7935aa7f23bf50 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Mar 2020 18:45:42 +0200 Subject: [PATCH 0129/1105] DFS: More debug prints on channel selection after radar detection This makes it easier to understand what is happening when a new channel needs to be selected based on a radar detection event. Signed-off-by: Jouni Malinen --- src/ap/dfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index d0b448e29..6c8cd6cac 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -144,30 +144,44 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode, int i; u32 bw = num_chan_to_bw(num_chans); - if (first_chan_idx + num_chans > mode->num_channels) + if (first_chan_idx + num_chans > mode->num_channels) { + wpa_printf(MSG_DEBUG, + "DFS: some channels in range not defined"); return 0; + } first_chan = &mode->channels[first_chan_idx]; /* hostapd DFS implementation assumes the first channel as primary. * If it's not allowed to use the first channel as primary, decline the * whole channel range. */ - if (!chan_pri_allowed(first_chan)) + if (!chan_pri_allowed(first_chan)) { + wpa_printf(MSG_DEBUG, "DFS: primary chanenl not allowed"); return 0; + } for (i = 0; i < num_chans; i++) { chan = dfs_get_chan_data(mode, first_chan->freq + i * 20, first_chan_idx); - if (!chan) + if (!chan) { + wpa_printf(MSG_DEBUG, "DFS: no channel data for %d", + first_chan->freq + i * 20); return 0; + } /* HT 40 MHz secondary channel availability checked only for * primary channel */ - if (!chan_bw_allowed(chan, bw, 1, !i)) + if (!chan_bw_allowed(chan, bw, 1, !i)) { + wpa_printf(MSG_DEBUG, "DFS: bw now allowed for %d", + first_chan->freq + i * 20); return 0; + } - if (!dfs_channel_available(chan, skip_radar)) + if (!dfs_channel_available(chan, skip_radar)) { + wpa_printf(MSG_DEBUG, "DFS: channel not available %d", + first_chan->freq + i * 20); return 0; + } } return 1; @@ -210,22 +224,36 @@ static int dfs_find_channel(struct hostapd_iface *iface, if (iface->conf->ieee80211n && iface->conf->secondary_channel && (!dfs_is_chan_allowed(chan, n_chans) || - !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))) + !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))) { + wpa_printf(MSG_DEBUG, + "DFS: channel %d (%d) is incompatible", + chan->freq, chan->chan); continue; + } /* Skip incompatible chandefs */ - if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) + if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) { + wpa_printf(MSG_DEBUG, + "DFS: range not available for %d (%d)", + chan->freq, chan->chan); continue; + } - if (!is_in_chanlist(iface, chan)) + if (!is_in_chanlist(iface, chan)) { + wpa_printf(MSG_DEBUG, + "DFS: channel %d (%d) not in chanlist", + chan->freq, chan->chan); continue; + } if (ret_chan && idx == channel_idx) { - wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan); + wpa_printf(MSG_DEBUG, "Selected channel %d (%d)", + chan->freq, chan->chan); *ret_chan = chan; return idx; } - wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan); + wpa_printf(MSG_DEBUG, "Adding channel %d (%d)", + chan->freq, chan->chan); channel_idx++; } return channel_idx; @@ -459,6 +487,8 @@ dfs_get_valid_channel(struct hostapd_iface *iface, /* Get the count first */ num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar); + wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d", + num_available_chandefs); if (num_available_chandefs == 0) return NULL; @@ -466,6 +496,11 @@ dfs_get_valid_channel(struct hostapd_iface *iface, return NULL; chan_idx = _rand % num_available_chandefs; dfs_find_channel(iface, &chan, chan_idx, skip_radar); + if (chan) + wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)", + chan->freq, chan->chan); + else + wpa_printf(MSG_DEBUG, "DFS: no random channel found"); /* dfs_find_channel() calculations assume HT40+ */ if (iface->conf->secondary_channel) From dc054892a2138ffacde697304539be653d5fbec7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 4 Mar 2020 21:23:43 +0200 Subject: [PATCH 0130/1105] tests: sigma_dut special case for SAE Password Identifier with PWE looping Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 0e6dc6fbf..a3af1d4c6 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -468,6 +468,42 @@ def test_sigma_dut_sae_pw_id(dev, apdev): finally: stop_sigma_dut(sigma) +def test_sigma_dut_sae_pw_id_pwe_loop(dev, apdev): + """sigma_dut controlled SAE association with Password Identifier and forced PWE looping""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params['sae_password'] = 'secret|id=pw id' + params['sae_groups'] = '19' + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,AKMSuiteType,8;9,PasswordID,pw id,sae_pwe,looping" % (ifname, "test-sae", "secret")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + for i in range(3): + ev = dev[0].wait_event(["SME: Trying to authenticate", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev is None: + raise Exception("Network selection result not indicated") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + res = sigma_dut_cmd("sta_is_connected,interface," + ifname) + if "connected,1" in res: + raise Exception("Connection reported") + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + def test_sigma_dut_sae_pw_id_ft(dev, apdev): """sigma_dut controlled SAE association with Password Identifier and FT""" run_sigma_dut_sae_pw_id_ft(dev, apdev) @@ -1059,6 +1095,42 @@ def test_sigma_dut_ap_sae_pw_id(dev, apdev, params): finally: stop_sigma_dut(sigma) +def test_sigma_dut_ap_sae_pw_id_pwe_loop(dev, apdev, params): + """sigma_dut controlled AP with SAE Password Identifier and forced PWE looping""" + logdir = os.path.join(params['logdir'], + "sigma_dut_ap_sae_pw_id_pwe_loop.sigma-hostapd") + conffile = os.path.join(params['logdir'], + "sigma_dut_ap_sae_pw_id_pwe_loop.sigma-conf") + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,AKMSuiteType,8,SAEPasswords,12345678:pwid,PMF,Required,sae_pwe,looping") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "wb") as f2: + f2.write(f.read()) + + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", sae_password="12345678", + sae_password_id="pwid", + ieee80211w="2", scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev is None: + raise Exception("Network selection result not indicated") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + dev[0].request("REMOVE_NETWORK all") + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + def test_sigma_dut_ap_sae_pw_id_ft(dev, apdev, params): """sigma_dut controlled AP with SAE Password Identifier and FT""" logdir = os.path.join(params['logdir'], From 11dab0f37f19659cb8587b032ded553e42d98142 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 4 Mar 2020 23:26:02 +0200 Subject: [PATCH 0131/1105] WPS: Remove expired PINs on Selected Registrar timeout This clears the AuthorizedMACs advertisement immediately when the Selected Registrar timeout is hit and no more active PINs are present. Previously, the AuthorizedMACs advertisement could remain in place indefinitely since expired PINs were removed only when actually trying to find a PIN for a new WPS exchange. Signed-off-by: Jouni Malinen --- src/wps/wps_registrar.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index d71a54315..9ee89ae34 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -3478,6 +3478,7 @@ static void wps_registrar_set_selected_timeout(void *eloop_ctx, "unselect internal Registrar"); reg->selected_registrar = 0; reg->pbc = 0; + wps_registrar_expire_pins(reg); wps_registrar_selected_registrar_changed(reg, 0); } From 72fd30c4b942dd47c4861f903e8deabacc3d49ca Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 4 Mar 2020 23:28:45 +0200 Subject: [PATCH 0132/1105] tests: WPS PBC/PIN timeout on AP Verify that AuthorizedMACs advertisement is removed when a PBC session or a PIN times out. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_wps.py | 37 +++++++++++++++++++++++++++++++++++ tests/hwsim/vm/parallel-vm.py | 2 ++ 2 files changed, 39 insertions(+) diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index 234531c5d..b4dacf280 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -10397,3 +10397,40 @@ def test_ap_wps_appl_ext(dev, apdev): dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin)) dev[0].wait_connected(timeout=30) + +def test_ap_wps_pbc_ap_timeout(dev, apdev, params): + """WPS PBC timeout on AP [long]""" + if not params['long']: + raise HwsimSkip("Skip test case with long duration due to --long not specified") + run_ap_wps_ap_timeout(dev, apdev, "WPS_PBC") + +def test_ap_wps_pin_ap_timeout(dev, apdev, params): + """WPS PIN timeout on AP [long]""" + if not params['long']: + raise HwsimSkip("Skip test case with long duration due to --long not specified") + run_ap_wps_ap_timeout(dev, apdev, "WPS_PIN any 12345670 10") + +def run_ap_wps_ap_timeout(dev, apdev, cmd): + ssid = "test-wps-conf" + hapd = hostapd.add_ap(apdev[0], + {"ssid": ssid, "eap_server": "1", "wps_state": "2", + "wpa_passphrase": "12345678", "wpa": "2", + "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}) + bssid = hapd.own_addr() + hapd.request(cmd) + time.sleep(1) + dev[0].scan_for_bss(bssid, freq="2412") + bss = dev[0].get_bss(bssid) + logger.info("BSS during active Registrar: " + str(bss)) + if not bss['ie'].endswith("0106ffffffffffff"): + raise Exception("Authorized MAC not included") + ev = hapd.wait_event(["WPS-TIMEOUT"], timeout=130) + if ev is None and "PBC" in cmd: + raise Exception("WPS-TIMEOUT not reported") + time.sleep(5) + dev[0].flush_scan_cache() + dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) + bss = dev[0].get_bss(bssid) + logger.info("BSS after timeout: " + str(bss)) + if bss['ie'].endswith("0106ffffffffffff"): + raise Exception("Authorized MAC not removed") diff --git a/tests/hwsim/vm/parallel-vm.py b/tests/hwsim/vm/parallel-vm.py index 3dd09584f..c451e8ab6 100755 --- a/tests/hwsim/vm/parallel-vm.py +++ b/tests/hwsim/vm/parallel-vm.py @@ -76,6 +76,8 @@ long_tests = ["ap_roam_open", "ap_wps_iteration", "ap_wps_iteration_error", "ap_wps_pbc_timeout", + "ap_wps_pbc_ap_timeout", + "ap_wps_pin_ap_timeout", "ap_wps_http_timeout", "p2p_go_move_reg_change", "p2p_go_move_active", From fa1a6aff223aebf8c74d34e32e1bb3e42b28aeab Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:49 +0100 Subject: [PATCH 0133/1105] Fix unicast argument for set_wep_key() from EAPOL supplicant The unicast parameter in set_wep_key() is only expected to be set to 0 or 1. Without this patch we set unicast to 0x80 instead of 1. Since unicast is used as boolean that is working fine but violates the documented API. Signed-off-by: Alexander Wetzel --- src/eapol_supp/eapol_supp_sm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index 1734d6efb..7f04b0107 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -843,7 +843,7 @@ static void eapol_sm_processKey(struct eapol_sm *sm) if (sm->ctx->set_wep_key && sm->ctx->set_wep_key(sm->ctx->ctx, - key->key_index & IEEE8021X_KEY_INDEX_FLAG, + !!(key->key_index & IEEE8021X_KEY_INDEX_FLAG), key->key_index & IEEE8021X_KEY_INDEX_MASK, datakey, key_len) < 0) { wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the " From d37c05e5b5bf239d4405f73e079f82bd3166df37 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:50 +0100 Subject: [PATCH 0134/1105] AP: Don't try to set NULL WEP default key hostapd_broadcast_wep_set() can be called without a WEP key set. Don't try to install a default key in that case. This patch is not critical for the new API. With key_flag we just would report an (ignored) error and do nothing. With the patch we simply do nothing. Signed-off-by: Alexander Wetzel --- src/ap/hostapd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index a6a95debf..f2e964ac0 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -336,7 +336,7 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) struct hostapd_ssid *ssid = &hapd->conf->ssid; idx = ssid->wep.idx; - if (ssid->wep.default_len && + if (ssid->wep.default_len && ssid->wep.key[idx] && hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 0, 1, NULL, 0, ssid->wep.key[idx], From 982b9cf02941fee91a449c348d60db4d01a478bf Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:51 +0100 Subject: [PATCH 0135/1105] Fix a wrong key_flag when deleting 802.1X WEP keys Signed-off-by: Alexander Wetzel --- src/ap/ieee802_1x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index c8e5fb395..6d4d43554 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -2487,7 +2487,7 @@ int ieee802_1x_init(struct hostapd_data *hapd) for (i = 0; i < 4; i++) hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, NULL, i, 0, 0, NULL, - 0, NULL, 0, KEY_FLAG_GROUP_RX_TX); + 0, NULL, 0, KEY_FLAG_GROUP); ieee802_1x_rekey(hapd, NULL); From 82eaa3e6882f6e4e0b260f9b6ba9169fbfa3a7b1 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:51 +0100 Subject: [PATCH 0136/1105] Remove the not yet needed KEY_FLAG_MODIFY I decided to drop KEY_FLAG_MODIFY instead of allowing flag combinations not yet used in the code and will simply recreate it with the Extended Key ID patches once we get there. For that reason I also did not renumber the flags. Signed-off-by: Alexander Wetzel --- src/common/defs.h | 3 --- src/drivers/driver.h | 7 ------- 2 files changed, 10 deletions(-) diff --git a/src/common/defs.h b/src/common/defs.h index 6358c3158..66c9b1f84 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -431,7 +431,6 @@ enum chan_width { }; enum key_flag { - KEY_FLAG_MODIFY = BIT(0), KEY_FLAG_DEFAULT = BIT(1), KEY_FLAG_RX = BIT(2), KEY_FLAG_TX = BIT(3), @@ -448,8 +447,6 @@ enum key_flag { KEY_FLAG_DEFAULT, KEY_FLAG_PAIRWISE_RX_TX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX_TX, KEY_FLAG_PAIRWISE_RX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX, - KEY_FLAG_PAIRWISE_RX_TX_MODIFY = KEY_FLAG_PAIRWISE_RX_TX | - KEY_FLAG_MODIFY, }; enum ptk0_rekey_handling { diff --git a/src/drivers/driver.h b/src/drivers/driver.h index bb187b8bf..04a453ea8 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1609,10 +1609,6 @@ struct wpa_driver_set_key_params { /** * key_flag - Additional key flags * - * %KEY_FLAG_MODIFY - * Set when an already installed key must be updated. - * So far the only use-case is changing RX/TX status of - * installed keys. Must not be set when deleting a key. * %KEY_FLAG_DEFAULT * Set when the key is also a default key. Must not be set when * deleting a key. @@ -1641,9 +1637,6 @@ struct wpa_driver_set_key_params { * %KEY_FLAG_PAIRWISE_RX * Pairwise key not yet valid for TX. (Only usable when Extended * Key ID is supported by the driver.) - * %KEY_FLAG_PAIRWISE_RX_TX_MODIFY - * Enable TX for a pairwise key installed with - * KEY_FLAG_PAIRWISE_RX. * * Not a valid standalone key type but pre-defined to be combined * with other key_flags: From 5eb16325693bbf43732d9935c7f8322dfeb1d0c6 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:51 +0100 Subject: [PATCH 0137/1105] nl80211: Add a missing key_flag for WEP shared key authentication Signed-off-by: Alexander Wetzel --- src/drivers/driver_nl80211.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index ecedc40f5..8066059db 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3556,6 +3556,9 @@ retry: p.set_tx = i == params->wep_tx_keyidx; p.key = params->wep_key[i]; p.key_len = params->wep_key_len[i]; + p.key_flag = i == params->wep_tx_keyidx ? + KEY_FLAG_GROUP_RX_TX_DEFAULT : + KEY_FLAG_GROUP_RX_TX; wpa_driver_nl80211_set_key(bss, &p); if (params->wep_tx_keyidx != i) continue; From e9e69221c1d164beabdcad58f7cc1c9f02a07929 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:51 +0100 Subject: [PATCH 0138/1105] Validity checking function for key_flag API Add masks for each key type to define which flags can be combined and add a helper function to validate key_flag values. Signed-off-by: Alexander Wetzel --- src/common/defs.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/common/defs.h b/src/common/defs.h index 66c9b1f84..bd16feb8a 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -447,8 +447,23 @@ enum key_flag { KEY_FLAG_DEFAULT, KEY_FLAG_PAIRWISE_RX_TX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX_TX, KEY_FLAG_PAIRWISE_RX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX, + /* Max allowed flags for each key type */ + KEY_FLAG_PAIRWISE_MASK = KEY_FLAG_PAIRWISE_RX_TX, + KEY_FLAG_GROUP_MASK = KEY_FLAG_GROUP_RX_TX_DEFAULT, + KEY_FLAG_PMK_MASK = KEY_FLAG_PMK, }; +static inline int check_key_flag(enum key_flag key_flag) +{ + return !!(!key_flag || + ((key_flag & KEY_FLAG_PAIRWISE) && + (key_flag & ~KEY_FLAG_PAIRWISE_MASK)) || + ((key_flag & KEY_FLAG_GROUP) && + (key_flag & ~KEY_FLAG_GROUP_MASK)) || + ((key_flag & KEY_FLAG_PMK) && + (key_flag & ~KEY_FLAG_PMK_MASK))); +} + enum ptk0_rekey_handling { PTK0_REKEY_ALLOW_ALWAYS, PTK0_REKEY_ALLOW_LOCAL_OK, From adf550ee4b9a277d278294d40623eaba54b24999 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:52 +0100 Subject: [PATCH 0139/1105] nl80211: Ignore seq number for key deletion Turns out we are sometime providing a seq when deleting the key. Since that makes no sense on key deletion let's stop forwarding that to the driver at least. Signed-off-by: Alexander Wetzel --- src/drivers/driver_nl80211.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 8066059db..019923130 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3118,12 +3118,13 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, nla_put_u32(key_msg, NL80211_KEY_CIPHER, suite)) goto fail; wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len); - } - if (seq && seq_len) { - if (nla_put(key_msg, NL80211_KEY_SEQ, seq_len, seq)) - goto fail; - wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len); + if (seq && seq_len) { + if (nla_put(key_msg, NL80211_KEY_SEQ, seq_len, seq)) + goto fail; + wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", + seq, seq_len); + } } if (addr && !is_broadcast_ether_addr(addr)) { From 8563f6f564461d494b06141b56d9628934153cbb Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:53 +0100 Subject: [PATCH 0140/1105] nl80211: Fix wrong return code in set_key error path Allow to abort key installations with different error codes and fix one misleading return code. Signed-off-by: Alexander Wetzel --- src/drivers/driver_nl80211.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 019923130..2e61eb7e1 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3097,9 +3097,10 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) return nl80211_set_pmk(drv, key, key_len, addr); + ret = -ENOBUFS; key_msg = nlmsg_alloc(); if (!key_msg) - return -ENOBUFS; + return ret; if (alg == WPA_ALG_NONE) { msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY); @@ -3109,8 +3110,10 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, u32 suite; suite = wpa_alg_to_cipher_suite(alg, key_len); - if (!suite) + if (!suite) { + ret = -EINVAL; goto fail2; + } msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY); if (!msg) goto fail2; @@ -3179,9 +3182,10 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, !is_broadcast_ether_addr(addr)) return ret; + ret = -ENOBUFS; key_msg = nlmsg_alloc(); if (!key_msg) - return -ENOBUFS; + return ret; msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY); if (!msg) @@ -3243,7 +3247,7 @@ fail: fail2: nl80211_nlmsg_clear(key_msg); nlmsg_free(key_msg); - return -ENOBUFS; + return ret; } From 98b8275d92bcefaed8b14a990b33555d61c1796e Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:54 +0100 Subject: [PATCH 0141/1105] nl80211: Remove not needed netlink key attribute Calling NL80211_CMD_NEW_KEY with NL80211_KEY_DEFAULT_TYPES attributes is pointless. The information is not expected and therefore the kernel never forwards it to the drivers. That attribute is used with NL80211_CMD_SET_KEY. Signed-off-by: Alexander Wetzel --- src/drivers/driver_nl80211.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 2e61eb7e1..94c56d007 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3142,15 +3142,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, goto fail; } } else if (addr && is_broadcast_ether_addr(addr)) { - struct nlattr *types; - wpa_printf(MSG_DEBUG, " broadcast key"); - - types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES); - if (!types || - nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST)) - goto fail; - nla_nest_end(key_msg, types); } if (nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) || nla_put_nested(msg, NL80211_ATTR_KEY, key_msg)) From 9757f18db41dd8504361e141050b7b59c4803413 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:55 +0100 Subject: [PATCH 0142/1105] nl80211: Don't ignore when SET_KEY returns ENOENT Always report an error when NL80211_CMD_SET_KEY can't set a key to default. The old ioctl-based design used a single command to add, set, and delete a key and had to ignore ENOENT for key deletions. It looks like that special handling was also ported for NL80211_CMD_NEW_KEY and NL80211_CMD_SET_KEY instead only for NL80211_CMD_DEL_KEY. Signed-off-by: Alexander Wetzel --- src/drivers/driver_nl80211.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 94c56d007..8b0e76f13 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3225,8 +3225,6 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, } ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == -ENOENT) - ret = 0; if (ret) wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; err=%d %s", From 81621eab7cd09da023ee745bffafb1ee4170777e Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Wed, 4 Mar 2020 18:16:56 +0100 Subject: [PATCH 0143/1105] nl80211: Migrate from set_tx to key_flag API Migrate nl80211 driver to key_flag API and add additional sanity checks. I'm still not sure why we install unicast WEP keys also as default unicast keys. Based on how I understand how mac80211 handles that it should be pointless. I just stuck to how we do things prior to the patch for WEP keys to not break anything. After all other drivers may need it. Signed-off-by: Alexander Wetzel --- src/drivers/driver_nl80211.c | 58 +++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 8b0e76f13..e56ae9fca 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3055,7 +3055,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, struct nl_msg *msg; struct nl_msg *key_msg; int ret; - int tdls = 0; + int skip_set_key = 1; const char *ifname = params->ifname; enum wpa_alg alg = params->alg; const u8 *addr = params->addr; @@ -3066,6 +3066,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, const u8 *key = params->key; size_t key_len = params->key_len; int vlan_id = params->vlan_id; + enum key_flag key_flag = params->key_flag; /* Ignore for P2P Device */ if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) @@ -3073,15 +3074,17 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, ifindex = if_nametoindex(ifname); wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d " - "set_tx=%d seq_len=%lu key_len=%lu", + "set_tx=%d seq_len=%lu key_len=%lu key_flag=0x%x", __func__, ifindex, ifname, alg, addr, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); + (unsigned long) seq_len, (unsigned long) key_len, key_flag); #ifdef CONFIG_TDLS - if (key_idx == -1) { + if (key_idx == -1) key_idx = 0; - tdls = 1; - } #endif /* CONFIG_TDLS */ + if (check_key_flag(key_flag)) { + wpa_printf(MSG_DEBUG, "%s: invalid key_flag", __func__); + return -EINVAL; + } #ifdef CONFIG_DRIVER_NL80211_QCA if (alg == WPA_ALG_PMK && @@ -3096,13 +3099,23 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, if (alg == WPA_ALG_PMK && (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) return nl80211_set_pmk(drv, key, key_len, addr); + if (key_flag & KEY_FLAG_PMK) { + /* The driver does not have any offload mechanism for PMK, so + * there is no need to configure this key. */ + return 0; + } ret = -ENOBUFS; key_msg = nlmsg_alloc(); if (!key_msg) return ret; - if (alg == WPA_ALG_NONE) { + if (alg == WPA_ALG_NONE && (key_flag & KEY_FLAG_RX_TX)) { + wpa_printf(MSG_DEBUG, "%s: invalid key_flag to delete key", + __func__); + ret = -EINVAL; + goto fail2; + } else if (alg == WPA_ALG_NONE) { msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY); if (!msg) goto fail2; @@ -3135,14 +3148,33 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) goto fail; - if (alg != WPA_ALG_WEP && key_idx && !set_tx) { + if ((key_flag & KEY_FLAG_GROUP_MASK) == KEY_FLAG_GROUP_RX) { wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK"); if (nla_put_u32(key_msg, NL80211_KEY_TYPE, NL80211_KEYTYPE_GROUP)) goto fail; + } else if (!(key_flag & KEY_FLAG_PAIRWISE)) { + wpa_printf(MSG_DEBUG, + " key_flag missing PAIRWISE when setting a pairwise key"); + ret = -EINVAL; + goto fail; + } else if (alg == WPA_ALG_WEP && + (key_flag & KEY_FLAG_RX_TX) == KEY_FLAG_RX_TX) { + wpa_printf(MSG_DEBUG, " unicast WEP key"); + skip_set_key = 0; + } else { + wpa_printf(MSG_DEBUG, " pairwise key"); } - } else if (addr && is_broadcast_ether_addr(addr)) { + } else if ((key_flag & KEY_FLAG_PAIRWISE) || + !(key_flag & KEY_FLAG_GROUP)) { + wpa_printf(MSG_DEBUG, + " invalid key_flag for a broadcast key"); + ret = -EINVAL; + goto fail; + } else { wpa_printf(MSG_DEBUG, " broadcast key"); + if (key_flag & KEY_FLAG_DEFAULT) + skip_set_key = 0; } if (nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) || nla_put_nested(msg, NL80211_ATTR_KEY, key_msg)) @@ -3165,14 +3197,12 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, ret, strerror(-ret)); /* - * If we failed or don't need to set the default TX key (below), + * If we failed or don't need to set the key as default (below), * we're done here. */ - if (ret || !set_tx || alg == WPA_ALG_NONE || tdls) - return ret; - if (is_ap_interface(drv->nlmode) && addr && - !is_broadcast_ether_addr(addr)) + if (ret || skip_set_key) return ret; + wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_SET_KEY - default key"); ret = -ENOBUFS; key_msg = nlmsg_alloc(); From 87775e32f684ece761d7c927ffeae1ab7295ce89 Mon Sep 17 00:00:00 2001 From: Zhaoyang Liu Date: Thu, 5 Mar 2020 11:25:00 +0800 Subject: [PATCH 0144/1105] Fix segmentation fault for NULL confname in SAVE_CONFIG When wpa_supplicant interface is added without a configuration file, the SAVE_CONFIG command causes a segmentation fault due to referencing a NULL pointer if the update_config parameter is first explicitly enabled. Fix the issue by checking the confname for NULL before saving configuration. Signed-off-by: Jouni Malinen --- wpa_supplicant/config_file.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 4c37b61a0..b8e56f5b2 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1612,9 +1612,16 @@ int wpa_config_write(const char *name, struct wpa_config *config) #endif /* CONFIG_NO_CONFIG_BLOBS */ int ret = 0; const char *orig_name = name; - int tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */ - char *tmp_name = os_malloc(tmp_len); + int tmp_len; + char *tmp_name; + if (!name) { + wpa_printf(MSG_ERROR, "No configuration file for writing"); + return -1; + } + + tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */ + tmp_name = os_malloc(tmp_len); if (tmp_name) { os_snprintf(tmp_name, tmp_len, "%s.tmp", name); name = tmp_name; From b27c7ac0ebb8d814060c0c00b28c5efdb1a32cd1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 6 Mar 2020 11:24:28 +0200 Subject: [PATCH 0145/1105] tests: wpa_supplicant SAVE_CONFIG without config file Signed-off-by: Jouni Malinen --- tests/hwsim/test_wpas_config.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/hwsim/test_wpas_config.py b/tests/hwsim/test_wpas_config.py index acf19594e..14816a0e1 100644 --- a/tests/hwsim/test_wpas_config.py +++ b/tests/hwsim/test_wpas_config.py @@ -644,3 +644,11 @@ def test_wpas_config_file_sae(dev, apdev, params): only_add_network=True) wpas.save_config() check_network_config(config, False) + +def test_wpas_config_update_without_file(dev, apdev): + """wpa_supplicant SAVE_CONFIG without config file""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5") + wpas.set("update_config", "1") + if "FAIL" not in wpas.request("SAVE_CONFIG"): + raise Exception("SAVE_CONFIG accepted unexpectedly") From 0a76a0b96557a129fb11f17f84fdb6d7418dbe32 Mon Sep 17 00:00:00 2001 From: Hu Wang Date: Thu, 5 Mar 2020 19:20:38 +0800 Subject: [PATCH 0146/1105] OWE: Fix PTK derivation workaround for interoperability The initial implementation of the PTK derivation workaround for interoperability with older OWE implementations forced WPA_KEY_MGMT_PSK_SHA256 to be used for all of PTK derivation. While that is needed for selecting which hash algorithm to use, this was also changing the length of the PTK components and by doing so, did not actually address the backwards compatibility issue. Fix this by forcing SHA256 as the hash algorithm in PTK derivation without changing the PTK length calculation for OWE when owe_ptk_workaround is enabled. Fixes: 65a44e849af9 ("OWE: PTK derivation workaround in AP mode") Fixes: 8b138d28264e ("OWE: PTK derivation workaround in STA mode") Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 2 +- src/common/wpa_common.c | 11 ++++++++++- src/rsn_supp/wpa.c | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index e67c34498..07cc514d9 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2286,7 +2286,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, akmp = sm->wpa_key_mgmt; if (force_sha256) - akmp = WPA_KEY_MGMT_PSK_SHA256; + akmp |= WPA_KEY_MGMT_PSK_SHA256; return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, ptk, akmp, sm->pairwise, z, z_len); diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index ee306ff50..c63d7bce1 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -355,6 +355,14 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, size_t data_len = 2 * ETH_ALEN + 2 * WPA_NONCE_LEN; u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; size_t ptk_len; +#ifdef CONFIG_OWE + int owe_ptk_workaround = 0; + + if (akmp == (WPA_KEY_MGMT_OWE | WPA_KEY_MGMT_PSK_SHA256)) { + owe_ptk_workaround = 1; + akmp = WPA_KEY_MGMT_OWE; + } +#endif /* CONFIG_OWE */ if (pmk_len == 0) { wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation"); @@ -413,7 +421,8 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, tmp, ptk_len) < 0) return -1; #ifdef CONFIG_OWE - } else if (akmp == WPA_KEY_MGMT_OWE && pmk_len == 32) { + } else if (akmp == WPA_KEY_MGMT_OWE && (pmk_len == 32 || + owe_ptk_workaround)) { wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)"); if (sha256_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 4ead4c516..548da45f6 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -598,7 +598,7 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, sm->pmk_len > 32) { wpa_printf(MSG_DEBUG, "OWE: Force SHA256 for PTK derivation"); - akmp = WPA_KEY_MGMT_PSK_SHA256; + akmp |= WPA_KEY_MGMT_PSK_SHA256; } #endif /* CONFIG_OWE */ return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", From 154722e5b1ada4d79ffdb3a342831d0bbd17b7b5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 6 Mar 2020 17:27:40 +0200 Subject: [PATCH 0147/1105] tests: Make ap_ht_40mhz_intolerant_ap more robust Some test case sequences seemed to prevent the station from completing the first OBSS scan (that scan was aborted) and that resulted in failing the test case because the AP had not received any report in time. Wait for scan completion and allow additional scans before timing out to avoid indicating incorrect AP behavior in cases where the report was not even received. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ht.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py index 66d30b4b7..79b15e09d 100644 --- a/tests/hwsim/test_ap_ht.py +++ b/tests/hwsim/test_ap_ht.py @@ -1005,7 +1005,10 @@ def test_ap_ht_40mhz_intolerant_ap(dev, apdev): logger.info("Waiting for co-ex report from STA") ok = False - for i in range(0, 20): + for i in range(4): + ev = dev[0].wait_event(['CTRL-EVENT-SCAN-RESULTS'], timeout=20) + if ev is None: + raise Exception("No OBSS scan seen") time.sleep(1) if hapd.get_status_field("secondary_channel") == "0": logger.info("AP moved to 20 MHz channel") From 2fb59e77b5ff047283a0a3b7a3a47296de168f34 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 6 Mar 2020 20:21:27 +0200 Subject: [PATCH 0148/1105] tests: HT with 20 MHz channel width doing CSA to 40 MHz Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ht.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py index 79b15e09d..bb942bfff 100644 --- a/tests/hwsim/test_ap_ht.py +++ b/tests/hwsim/test_ap_ht.py @@ -1168,6 +1168,38 @@ def test_ap_ht40_csa3(dev, apdev): set_world_reg(apdev[0], None, dev[0]) dev[0].flush_scan_cache() +def test_ap_ht_20_to_40_csa(dev, apdev): + """HT with 20 MHz channel width doing CSA to 40 MHz""" + csa_supported(dev[0]) + + params = {"ssid": "ht", + "channel": "1", + "ieee80211n": "1"} + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect("ht", key_mgmt="NONE", scan_freq="2412") + hapd.wait_sta() + res = dev[0].request("SIGNAL_POLL") + logger.info("SIGNAL_POLL:\n" + res) + sig = res.splitlines() + if 'WIDTH=20 MHz' not in sig: + raise Exception("20 MHz channel bandwidth not used on the original channel") + + hapd.request("CHAN_SWITCH 5 2462 ht sec_channel_offset=-1 bandwidth=40") + ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) + if ev is None: + raise Exception("CSA finished event timed out") + if "freq=2462" not in ev: + raise Exception("Unexpected channel in CSA finished event") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) + if ev is not None: + raise Exception("Unexpected STA disconnection during CSA") + res = dev[0].request("SIGNAL_POLL") + logger.info("SIGNAL_POLL:\n" + res) + sig = res.splitlines() + if 'WIDTH=40 MHz' not in sig: + raise Exception("40 MHz channel bandwidth not used on the new channel") + @remote_compatible def test_prefer_ht20(dev, apdev): """Preference on HT20 over no-HT""" From 72c34d23a44f46a664f118a8011b0cb793119b70 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 6 Mar 2020 20:50:21 +0200 Subject: [PATCH 0149/1105] tests: Automatic channel selection with fallback to 20 MHz Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_acs.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index 866fd725c..ed05c903a 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -551,3 +551,26 @@ def test_ap_acs_hw_mode_any_5ghz(dev, apdev): dev[0].wait_regdom(country_ie=True) finally: clear_regdom(hapd, dev) + +def test_ap_acs_with_fallback_to_20(dev, apdev): + """Automatic channel selection with fallback to 20 MHz""" + force_prev_ap_on_24g(apdev[0]) + params = {"ssid": "legacy-20", + "channel": "7", "ieee80211n": "0"} + hostapd.add_ap(apdev[1], params) + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['channel'] = '0' + params['acs_chan_bias'] = '6:0.1' + params['ht_capab'] = '[HT40+]' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + wait_acs(hapd) + + freq = hapd.get_status_field("freq") + if int(freq) < 2400: + raise Exception("Unexpected frequency") + + dev[0].connect("test-acs", psk="12345678", scan_freq=freq) + sig = dev[0].request("SIGNAL_POLL").splitlines() + logger.info("SIGNAL_POLL: " + str(sig)) + if "WIDTH=20 MHz" not in sig: + raise Exception("Station did not report 20 MHz bandwidth") From f64b601c47d37d58bc5e7c32b40c801d528c5d5d Mon Sep 17 00:00:00 2001 From: Pravas Kumar Panda Date: Fri, 6 Mar 2020 15:06:42 +0530 Subject: [PATCH 0150/1105] DFS: Add support for 80+80 MHz when going through channel switch After a radar signal is detected, the AP should switch to another channel, but in the case of 80+80 MHz, channel switch failed because hostapd did not select the secondary channel in the process. Fix this by selecting a secondary channel in the case of 80+80 MHz. Signed-off-by: Xin Wang Signed-off-by: Pravas Kumar Panda --- src/ap/dfs.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 6c8cd6cac..6fc806d7b 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -263,6 +263,7 @@ static int dfs_find_channel(struct hostapd_iface *iface, static void dfs_adjust_center_freq(struct hostapd_iface *iface, struct hostapd_channel_data *chan, int secondary_channel, + int sec_chan_idx_80p80, u8 *oper_centr_freq_seg0_idx, u8 *oper_centr_freq_seg1_idx) { @@ -289,8 +290,14 @@ static void dfs_adjust_center_freq(struct hostapd_iface *iface, case CHANWIDTH_160MHZ: *oper_centr_freq_seg0_idx = chan->chan + 14; break; + case CHANWIDTH_80P80MHZ: + *oper_centr_freq_seg0_idx = chan->chan + 6; + *oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6; + break; + default: - wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now"); + wpa_printf(MSG_INFO, + "DFS: Unsupported channel width configuration"); *oper_centr_freq_seg0_idx = 0; break; } @@ -469,8 +476,11 @@ dfs_get_valid_channel(struct hostapd_iface *iface, { struct hostapd_hw_modes *mode; struct hostapd_channel_data *chan = NULL; + struct hostapd_channel_data *chan2 = NULL; int num_available_chandefs; - int chan_idx; + int chan_idx, chan_idx2; + int sec_chan_idx_80p80 = -1; + int i; u32 _rand; wpa_printf(MSG_DEBUG, "DFS: Selecting random channel"); @@ -496,11 +506,12 @@ dfs_get_valid_channel(struct hostapd_iface *iface, return NULL; chan_idx = _rand % num_available_chandefs; dfs_find_channel(iface, &chan, chan_idx, skip_radar); - if (chan) - wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)", - chan->freq, chan->chan); - else + if (!chan) { wpa_printf(MSG_DEBUG, "DFS: no random channel found"); + return NULL; + } + wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)", + chan->freq, chan->chan); /* dfs_find_channel() calculations assume HT40+ */ if (iface->conf->secondary_channel) @@ -508,8 +519,45 @@ dfs_get_valid_channel(struct hostapd_iface *iface, else *secondary_channel = 0; + /* Get secondary channel for HT80P80 */ + if (hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80P80MHZ) { + if (num_available_chandefs <= 1) { + wpa_printf(MSG_ERROR, + "only 1 valid chan, can't support 80+80"); + return NULL; + } + + /* + * Loop all channels except channel1 to find a valid channel2 + * that is not adjacent to channel1. + */ + for (i = 0; i < num_available_chandefs - 1; i++) { + /* start from chan_idx + 1, end when chan_idx - 1 */ + chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs; + dfs_find_channel(iface, &chan2, chan_idx2, skip_radar); + if (chan2 && abs(chan2->chan - chan->chan) > 12) { + /* two channels are not adjacent */ + sec_chan_idx_80p80 = chan2->chan; + wpa_printf(MSG_DEBUG, + "DFS: got second chan: %d (%d)", + chan2->freq, chan2->chan); + break; + } + } + + /* Check if we got a valid secondary channel which is not + * adjacent to the first channel. + */ + if (sec_chan_idx_80p80 == -1) { + wpa_printf(MSG_INFO, + "DFS: failed to get chan2 for 80+80"); + return NULL; + } + } + dfs_adjust_center_freq(iface, chan, *secondary_channel, + sec_chan_idx_80p80, oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx); From 2dd72315d97bbaba14d2c9fa54dda298f5d957d7 Mon Sep 17 00:00:00 2001 From: Andrew Siplas Date: Wed, 4 Mar 2020 20:55:18 -0500 Subject: [PATCH 0151/1105] wpa_cli: Add missing quote around interface name There was only an open quote present. Signed-off-by: Andrew Siplas --- wpa_supplicant/wpa_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 490e77c96..22885e646 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1783,7 +1783,7 @@ static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) } if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) { - printf("Connected to interface '%s.\n", ctrl_ifname); + printf("Connected to interface '%s'.\n", ctrl_ifname); } else { printf("Could not connect to interface '%s' - re-trying\n", ctrl_ifname); From 11b1fcd6cae142a644b593eaf476765e10109538 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Thu, 5 Mar 2020 22:06:45 +0100 Subject: [PATCH 0152/1105] nl80211: Drop outdated TDLS set_key() hack wpa_tdls_set_key() did set the key_id to -1 to avoid a useless NL80211_CMD_SET_KEY call that the updated nl80211 driver no longer carries out. Remove the no longer required workaround. Signed-off-by: Alexander Wetzel --- src/drivers/driver_nl80211.c | 5 +---- src/rsn_supp/tdls.c | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index e56ae9fca..f44209db0 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3077,10 +3077,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, "set_tx=%d seq_len=%lu key_len=%lu key_flag=0x%x", __func__, ifindex, ifname, alg, addr, key_idx, set_tx, (unsigned long) seq_len, (unsigned long) key_len, key_flag); -#ifdef CONFIG_TDLS - if (key_idx == -1) - key_idx = 0; -#endif /* CONFIG_TDLS */ + if (check_key_flag(key_flag)) { wpa_printf(MSG_DEBUG, "%s: invalid key_flag", __func__); return -EINVAL; diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index bb8973942..7b47e3ac5 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -227,7 +227,7 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR, MAC2STR(peer->addr)); - if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1, rsc, sizeof(rsc), + if (wpa_sm_set_key(sm, alg, peer->addr, 0, 1, rsc, sizeof(rsc), peer->tpk.tk, key_len, KEY_FLAG_PAIRWISE_RX_TX) < 0) { wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the " From be15f33d0716ff4b5bac0f81b31e2018cd14c707 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Thu, 5 Mar 2020 22:06:46 +0100 Subject: [PATCH 0153/1105] Replace WPA_ALG_PMK with KEY_FLAG_PMK Drop the no longer needed internal alg WPA_ALG_PMK and use KEY_FLAG_PMK as replacement. Signed-off-by: Alexander Wetzel --- src/common/defs.h | 1 - src/drivers/driver.h | 7 ++--- src/drivers/driver_nl80211.c | 8 ++---- src/drivers/driver_openbsd.c | 5 ++-- src/drivers/driver_wext.c | 53 +++++++++++++++++++----------------- wpa_supplicant/wpas_glue.c | 4 +-- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/common/defs.h b/src/common/defs.h index bd16feb8a..077d6399a 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -200,7 +200,6 @@ enum wpa_alg { WPA_ALG_TKIP, WPA_ALG_CCMP, WPA_ALG_IGTK, - WPA_ALG_PMK, WPA_ALG_GCMP, WPA_ALG_SMS4, WPA_ALG_KRK, diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 04a453ea8..642230ec3 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1546,9 +1546,8 @@ struct wpa_driver_set_key_params { * alg - Encryption algorithm * * (%WPA_ALG_NONE, %WPA_ALG_WEP, %WPA_ALG_TKIP, %WPA_ALG_CCMP, - * %WPA_ALG_IGTK, %WPA_ALG_PMK, %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, - * %WPA_ALG_CCMP_256, %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256, - * %WPA_ALG_BIP_CMAC_256); + * %WPA_ALG_IGTK, %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, %WPA_ALG_CCMP_256, + * %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256, %WPA_ALG_BIP_CMAC_256); * %WPA_ALG_NONE clears the key. */ enum wpa_alg alg; @@ -1698,7 +1697,7 @@ struct wpa_driver_capa { /** Driver takes care of all DFS operations */ #define WPA_DRIVER_FLAGS_DFS_OFFLOAD 0x00000004 /** Driver takes care of RSN 4-way handshake internally; PMK is configured with - * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */ + * struct wpa_driver_ops::set_key using key_flag = KEY_FLAG_PMK */ #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X 0x00000008 /** Driver is for a wired Ethernet interface */ #define WPA_DRIVER_FLAGS_WIRED 0x00000010 diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index f44209db0..93aa5d702 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2883,7 +2883,6 @@ static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len) case WPA_ALG_KRK: return RSN_CIPHER_SUITE_KRK; case WPA_ALG_NONE: - case WPA_ALG_PMK: wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d", alg); return 0; @@ -3084,7 +3083,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, } #ifdef CONFIG_DRIVER_NL80211_QCA - if (alg == WPA_ALG_PMK && + if ((key_flag & KEY_FLAG_PMK) && (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) { wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key", __func__); @@ -3093,10 +3092,9 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, } #endif /* CONFIG_DRIVER_NL80211_QCA */ - if (alg == WPA_ALG_PMK && - (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) - return nl80211_set_pmk(drv, key, key_len, addr); if (key_flag & KEY_FLAG_PMK) { + if (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) + return nl80211_set_pmk(drv, key, key_len, addr); /* The driver does not have any offload mechanism for PMK, so * there is no need to configure this key. */ return 0; diff --git a/src/drivers/driver_openbsd.c b/src/drivers/driver_openbsd.c index e0eede96b..bfc231178 100644 --- a/src/drivers/driver_openbsd.c +++ b/src/drivers/driver_openbsd.c @@ -73,11 +73,12 @@ wpa_driver_openbsd_set_key(void *priv, struct wpa_driver_set_key_params *params) { struct openbsd_driver_data *drv = priv; struct ieee80211_keyavail keyavail; - enum wpa_alg alg = params->alg; + enum key_flag key_flag = params->key_flag; const u8 *key = params->key; size_t key_len = params->key_len; - if (alg != WPA_ALG_PMK || key_len > IEEE80211_PMK_LEN) + if (key_len > IEEE80211_PMK_LEN || + (key_flag & KEY_FLAG_PMK_MASK) != KEY_FLAG_PMK) { return -1; memset(&keyavail, 0, sizeof(keyavail)); diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index 776eff72d..978e1cf43 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -1712,7 +1712,8 @@ static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) + const u8 *key, size_t key_len, + enum key_flag key_flag) { struct wpa_driver_wext_data *drv = priv; struct iwreq iwr; @@ -1751,30 +1752,31 @@ static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, os_memcpy(ext + 1, key, key_len); ext->key_len = key_len; } - switch (alg) { - case WPA_ALG_NONE: - ext->alg = IW_ENCODE_ALG_NONE; - break; - case WPA_ALG_WEP: - ext->alg = IW_ENCODE_ALG_WEP; - break; - case WPA_ALG_TKIP: - ext->alg = IW_ENCODE_ALG_TKIP; - break; - case WPA_ALG_CCMP: - ext->alg = IW_ENCODE_ALG_CCMP; - break; - case WPA_ALG_PMK: + if (key_flag & KEY_FLAG_PMK) { ext->alg = IW_ENCODE_ALG_PMK; - break; - case WPA_ALG_IGTK: - ext->alg = IW_ENCODE_ALG_AES_CMAC; - break; - default: - wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", - __FUNCTION__, alg); - os_free(ext); - return -1; + } else { + switch (alg) { + case WPA_ALG_NONE: + ext->alg = IW_ENCODE_ALG_NONE; + break; + case WPA_ALG_WEP: + ext->alg = IW_ENCODE_ALG_WEP; + break; + case WPA_ALG_TKIP: + ext->alg = IW_ENCODE_ALG_TKIP; + break; + case WPA_ALG_CCMP: + ext->alg = IW_ENCODE_ALG_CCMP; + break; + case WPA_ALG_IGTK: + ext->alg = IW_ENCODE_ALG_AES_CMAC; + break; + default: + wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", + __FUNCTION__, alg); + os_free(ext); + return -1; + } } if (seq && seq_len) { @@ -1816,6 +1818,7 @@ static int wpa_driver_wext_set_key(void *priv, struct iwreq iwr; int ret = 0; enum wpa_alg alg = params->alg; + enum key_flag key_flag = params->key_flag; const u8 *addr = params->addr; int key_idx = params->key_idx; int set_tx = params->set_tx; @@ -1830,7 +1833,7 @@ static int wpa_driver_wext_set_key(void *priv, (unsigned long) seq_len, (unsigned long) key_len); ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx, - seq, seq_len, key, key_len); + seq, seq_len, key, key_len, key_flag); if (ret == 0) return 0; diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index cef70a6f5..7162f8f1f 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -352,7 +352,7 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way " "handshake", pmk, pmk_len); - if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk, + if (wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, NULL, 0, pmk, pmk_len, KEY_FLAG_PMK)) { wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver"); } @@ -1196,7 +1196,7 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk, if (wpa_s->conf->key_mgmt_offload && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) - return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, + return wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, NULL, 0, pmk, pmk_len, KEY_FLAG_PMK); else return 0; From bdb2eaf87688015631042edac42dcbc9350d287c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 6 Mar 2020 21:38:01 +0200 Subject: [PATCH 0154/1105] tests: sigma_dut with OWE PTK workaround Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 52 ++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index a3af1d4c6..54c2a57ab 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -96,7 +96,7 @@ def sigma_dut_cmd_check(cmd, port=9000, timeout=2): return res def start_sigma_dut(ifname, hostapd_logdir=None, cert_path=None, - bridge=None, sae_h2e=False): + bridge=None, sae_h2e=False, owe_ptk_workaround=False): check_sigma_dut() cmd = ['./sigma_dut', '-d', @@ -114,6 +114,8 @@ def start_sigma_dut(ifname, hostapd_logdir=None, cert_path=None, cmd += ['-b', bridge] if sae_h2e: cmd += ['-2'] + if owe_ptk_workaround: + cmd += ['-3'] sigma = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for stream in [sigma.stdout, sigma.stderr]: @@ -1327,6 +1329,35 @@ def run_sigma_dut_owe(dev, apdev): finally: stop_sigma_dut(sigma) +def test_sigma_dut_owe_ptk_workaround(dev, apdev): + """sigma_dut controlled OWE station with PTK workaround""" + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + + params = {"ssid": "owe", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "owe_ptk_workaround": "1", + "owe_groups": "20", + "ieee80211w": "2", + "rsn_pairwise": "CCMP"} + hapd = hostapd.add_ap(apdev[0], params) + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname, owe_ptk_workaround=True) + + try: + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,owe,Type,OWE,ECGroupID,20" % ifname) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,owe,channel,1" % ifname, + timeout=10) + sigma_dut_wait_connected(ifname) + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + dev[0].set("ignore_old_scan_res", "0") + def test_sigma_dut_ap_owe(dev, apdev, params): """sigma_dut controlled AP with OWE""" logdir = os.path.join(params['logdir'], @@ -1391,6 +1422,25 @@ def test_sigma_dut_ap_owe_ecgroupid(dev, apdev): finally: stop_sigma_dut(sigma) +def test_sigma_dut_ap_owe_ptk_workaround(dev, apdev): + """sigma_dut controlled AP with OWE PTK workaround""" + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, owe_ptk_workaround=True) + try: + sigma_dut_cmd_check("ap_reset_default,NAME,AP,Program,WPA3") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,owe,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,OWE,ECGroupID,20,PMF,Required") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + dev[0].connect("owe", key_mgmt="OWE", ieee80211w="2", + owe_group="20", owe_ptk_workaround="1", + scan_freq="2412") + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + def test_sigma_dut_ap_owe_transition_mode(dev, apdev, params): """sigma_dut controlled AP with OWE and transition mode""" if "OWE" not in dev[0].get_capability("key_mgmt"): From ca8a51c4bbb7709aee429a980313a19ec34bf942 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 11:51:23 +0200 Subject: [PATCH 0155/1105] webkit2: Fix http://localhost:12345/ redirect handling The resource-load-started cannot be used to replace the older resource-request-starting signal and as such, the final redirect to the special http://localhost:12345/ URL did not work. Use the decide-policy signal for navigation action instead. Also remove the attempt to modify the request URI from resource-load-started since that is not going to work either. This is not really critical for functionality, but could eventually be replaced with a handler for the WebKitWebPage send-request signal. Signed-off-by: Jouni Malinen --- src/utils/browser.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/utils/browser.c b/src/utils/browser.c index f864fbf0e..c0f4380c4 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -107,9 +107,6 @@ static void view_cb_resource_load_starting(WebKitWebView *view, const gchar *uri = webkit_uri_request_get_uri(req); wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); - if (g_str_has_suffix(uri, "/favicon.ico")) - webkit_uri_request_set_uri(req, "about:blank"); - process_request_starting_uri(ctx, uri); } @@ -134,6 +131,21 @@ static gboolean view_cb_decide_policy(WebKitWebView *view, } break; } + case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: { + WebKitNavigationPolicyDecision *d; + WebKitNavigationAction *a; + WebKitURIRequest *req; + const gchar *uri; + + d = WEBKIT_NAVIGATION_POLICY_DECISION(policy); + a = webkit_navigation_policy_decision_get_navigation_action(d); + req = webkit_navigation_action_get_request(a); + uri = webkit_uri_request_get_uri(req); + wpa_printf(MSG_DEBUG, "BROWSER:%s navigation action: uri=%s", + __func__, uri); + process_request_starting_uri(ctx, uri); + break; + } default: break; } From 87998f80e7d05e0ad846bcf5152e4d5065dde49b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 13:26:56 +0200 Subject: [PATCH 0156/1105] HS 2.0 server: Allow OCSP responder to continue running after errors By default, 'openssl ocsp' exits upon receiving a malformed request. That's not really ideal for a server, so configure openssl to not do that and instead, continue running to process other requests. Signed-off-by: Jouni Malinen --- hs20/server/ca/ocsp-responder.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hs20/server/ca/ocsp-responder.sh b/hs20/server/ca/ocsp-responder.sh index 8cebd7453..620947d01 100755 --- a/hs20/server/ca/ocsp-responder.sh +++ b/hs20/server/ca/ocsp-responder.sh @@ -1,3 +1,3 @@ #!/bin/sh -openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text +openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text -ignore_err From 43ededa9c74e3762bcf2f78841790eeecfa8ad56 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 13:56:56 +0200 Subject: [PATCH 0157/1105] Do not override WDS VLAN assignment for STA The 4-address frames WDS design in mac80211 uses VLAN interfaces similarly to the way VLAN interfaces based on VLAN IDs are used. The EAP authentication case ended up overriding the WDS specific assignment even when the RADIUS server did not assign any specific VLAN for the STA. This broke WDS traffic. Fix this by skipping VLAN assignment to VLAN ID 0 for STAs that have been detected to use 4-address frames. Signed-off-by: Jouni Malinen --- src/ap/sta_info.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 87a9fd409..26885ea49 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -1027,6 +1027,13 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta) int ret; int old_vlanid = sta->vlan_id_bound; + if ((sta->flags & WLAN_STA_WDS) && sta->vlan_id == 0) { + wpa_printf(MSG_DEBUG, + "Do not override WDS VLAN assignment for STA " + MACSTR, MAC2STR(sta->addr)); + return 0; + } + iface = hapd->conf->iface; if (hapd->conf->ssid.vlan[0]) iface = hapd->conf->ssid.vlan; From 20cace9014c253a99ac9bba31c972d68d39331f5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 13:59:17 +0200 Subject: [PATCH 0158/1105] tests: WPA2-EAP AP with STA using 4addr mode Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_params.py | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py index d72e64ab2..4c5deb8d5 100644 --- a/tests/hwsim/test_ap_params.py +++ b/tests/hwsim/test_ap_params.py @@ -301,6 +301,43 @@ def test_ap_wds_sta(dev, apdev): dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'wds-br0', 'down']) dev[0].cmd_execute(['brctl', 'delbr', 'wds-br0']) +def test_ap_wds_sta_eap(dev, apdev): + """WPA2-EAP AP with STA using 4addr mode""" + ssid = "test-wpa2-eap" + params = hostapd.wpa2_eap_params(ssid=ssid) + params['wds_sta'] = "1" + params['wds_bridge'] = "wds-br0" + hapd = hostapd.add_ap(apdev[0], params) + + try: + dev[0].cmd_execute(['brctl', 'addbr', 'wds-br0']) + dev[0].cmd_execute(['brctl', 'setfd', 'wds-br0', '0']) + dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'wds-br0', 'up']) + dev[0].cmd_execute(['iw', dev[0].ifname, 'set', '4addr', 'on']) + dev[0].connect(ssid, key_mgmt="WPA-EAP", eap="GPSK", + identity="gpsk user", + password="abcdefghijklmnop0123456789abcdef", + scan_freq="2412") + ev = hapd.wait_event(["WDS-STA-INTERFACE-ADDED"], timeout=10) + if ev is None: + raise Exception("No WDS-STA-INTERFACE-ADDED event seen") + if "sta_addr=" + dev[0].own_addr() not in ev: + raise Exception("No sta_addr match in " + ev) + if "ifname=" + hapd.ifname + ".sta" not in ev: + raise Exception("No ifname match in " + ev) + sta = hapd.get_sta(dev[0].own_addr()) + if "wds_sta_ifname" not in sta: + raise Exception("Missing wds_sta_ifname in STA data") + if "ifname=" + sta['wds_sta_ifname'] not in ev: + raise Exception("wds_sta_ifname %s not in event: %s" % + (sta['wds_sta_ifname'], ev)) + hwsim_utils.test_connectivity_iface(dev[0], hapd, "wds-br0", + max_tries=15) + finally: + dev[0].cmd_execute(['iw', dev[0].ifname, 'set', '4addr', 'off']) + dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'wds-br0', 'down']) + dev[0].cmd_execute(['brctl', 'delbr', 'wds-br0']) + def test_ap_wds_sta_open(dev, apdev): """Open AP with STA using 4addr mode""" ssid = "test-wds-open" From 9128b67269c4072d7a9c01570811d9c3e9bbf00d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 16:39:36 +0200 Subject: [PATCH 0159/1105] Extend hostapd rsnxe_override_eapol to allow IE removal Previous implementation was determining whether the override value was set based on its length being larger than zero. Replace this with an explicit indication of whether the parameter is set to allow zero length replacement, i.e., remove of RSNXE from EAPOL-Key msg 3/4. In addition, move IE replacement into a more generic helper function to allow this to be used with other IEs as well. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 68 +++++++++++++++++++++++++----------------- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 1 + 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 07cc514d9..f914875fe 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3221,13 +3221,45 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) } +#ifdef CONFIG_TESTING_OPTIONS +static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid, + const u8 *ie, size_t ie_len) +{ + const u8 *elem; + u8 *buf; + + wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name); + wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override", + old_buf, *len); + buf = os_malloc(*len + ie_len); + if (!buf) + return NULL; + os_memcpy(buf, old_buf, *len); + elem = get_ie(buf, *len, eid); + if (elem) { + u8 elem_len = 2 + elem[1]; + + os_memmove((void *) elem, elem + elem_len, + *len - (elem - buf) - elem_len); + *len -= elem_len; + } + os_memcpy(buf + *len, ie, ie_len); + *len += ie_len; + wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override", + buf, *len); + + return buf; +} +#endif /* CONFIG_TESTING_OPTIONS */ + + SM_STATE(WPA_PTK, PTKINITNEGOTIATING) { u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32]; - size_t gtk_len, kde_len; + size_t gtk_len, kde_len, wpa_ie_len; struct wpa_group *gsm = sm->group; u8 *wpa_ie; - int wpa_ie_len, secure, gtkidx, encr = 0; + int secure, gtkidx, encr = 0; u8 *wpa_ie_buf = NULL; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); @@ -3255,7 +3287,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie_len = sm->wpa_auth->wpa_ie_len; if (sm->wpa == WPA_VERSION_WPA && (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && - wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { + wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) { /* WPA-only STA, remove RSN IE and possible MDIE */ wpa_ie = wpa_ie + wpa_ie[1] + 2; if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) @@ -3263,32 +3295,14 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie_len = wpa_ie[1] + 2; } #ifdef CONFIG_TESTING_OPTIONS - if (sm->wpa_auth->conf.rsnxe_override_eapol_len) { - u8 *obuf = sm->wpa_auth->conf.rsnxe_override_eapol; - size_t olen = sm->wpa_auth->conf.rsnxe_override_eapol_len; - const u8 *rsnxe; - - wpa_hexdump(MSG_DEBUG, - "TESTING: wpa_ie before RSNXE EAPOL override", - wpa_ie, wpa_ie_len); - wpa_ie_buf = os_malloc(wpa_ie_len + olen); + if (sm->wpa_auth->conf.rsnxe_override_eapol_set) { + wpa_ie_buf = replace_ie( + "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX, + sm->wpa_auth->conf.rsnxe_override_eapol, + sm->wpa_auth->conf.rsnxe_override_eapol_len); if (!wpa_ie_buf) - return; - os_memcpy(wpa_ie_buf, wpa_ie, wpa_ie_len); + goto done; wpa_ie = wpa_ie_buf; - rsnxe = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_RSNX); - if (rsnxe) { - u8 rsnxe_len = 2 + rsnxe[1]; - - os_memmove((void *) rsnxe, rsnxe + rsnxe_len, - wpa_ie_len - (rsnxe - wpa_ie) - rsnxe_len); - wpa_ie_len -= rsnxe_len; - } - os_memcpy(wpa_ie + wpa_ie_len, obuf, olen); - wpa_ie_len += olen; - wpa_hexdump(MSG_DEBUG, - "TESTING: wpa_ie after RSNXE EAPOL override", - wpa_ie, wpa_ie_len); } #endif /* CONFIG_TESTING_OPTIONS */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 1f7ba4899..93d7f74f2 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -225,6 +225,7 @@ struct wpa_auth_config { size_t rsnxe_override_eapol_len; u8 gtk_rsc_override[WPA_KEY_RSC_LEN]; u8 igtk_rsc_override[WPA_KEY_RSC_LEN]; + unsigned int rsnxe_override_eapol_set:1; unsigned int gtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1; #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 82e82a7d2..4a303b039 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -123,6 +123,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, } if (conf->rsnxe_override_eapol && wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsnxe_override_eapol_set = 1; wconf->rsnxe_override_eapol_len = wpabuf_len(conf->rsnxe_override_eapol); os_memcpy(wconf->rsnxe_override_eapol, From 3396a4529cf27f51bf0f30965cd37a4dac6e0550 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 16:42:47 +0200 Subject: [PATCH 0160/1105] tests: RSNXE missing from EAPOL-Key msg 3/4 Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index 37a3f8838..fff4f49ae 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -2253,6 +2253,10 @@ def test_sae_h2e_rsnxe_mismatch_ap2(dev, apdev): """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F400") +def test_sae_h2e_rsnxe_mismatch_ap3(dev, apdev): + """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" + run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "") + def run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, rsnxe): check_sae_capab(dev[0]) params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") From 4d64fd37b742cc1da84b2d0488c4ac3270be4b4c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 16:45:52 +0200 Subject: [PATCH 0161/1105] Allow RSNE in EAPOL-Key msg 3/4 to be replaced for testing purposes The new hostapd configuration parameter rsne_override_eapol can now be used similarly to the previously added rsnxe_override_eapol to override (replace contents or remove) RSNE in EAPOL-Key msg 3/4. This can be used for station protocol testing to verify sufficient checks for RSNE modification between the Beacon/Probe Response frames and EAPOL-Key msg 3/4. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 3 +++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 1 + src/ap/wpa_auth.c | 12 +++++++++++- src/ap/wpa_auth.h | 3 +++ src/ap/wpa_auth_glue.c | 9 +++++++++ 6 files changed, 28 insertions(+), 1 deletion(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 269f9f3cd..98e9fd21b 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4176,6 +4176,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "sae_commit_override") == 0) { wpabuf_free(bss->sae_commit_override); bss->sae_commit_override = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "rsne_override_eapol") == 0) { + wpabuf_free(bss->rsne_override_eapol); + bss->rsne_override_eapol = wpabuf_parse_bin(pos); } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) { wpabuf_free(bss->rsnxe_override_eapol); bss->rsnxe_override_eapol = wpabuf_parse_bin(pos); diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 50974094a..0166c3164 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -902,6 +902,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) #ifdef CONFIG_TESTING_OPTIONS wpabuf_free(conf->own_ie_override); wpabuf_free(conf->sae_commit_override); + wpabuf_free(conf->rsne_override_eapol); wpabuf_free(conf->rsnxe_override_eapol); wpabuf_free(conf->gtk_rsc_override); wpabuf_free(conf->igtk_rsc_override); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 5d86a332a..8b57500ce 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -677,6 +677,7 @@ struct hostapd_bss_config { struct wpabuf *own_ie_override; int sae_reflection_attack; struct wpabuf *sae_commit_override; + struct wpabuf *rsne_override_eapol; struct wpabuf *rsnxe_override_eapol; struct wpabuf *gtk_rsc_override; struct wpabuf *igtk_rsc_override; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index f914875fe..ab20705f0 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3260,7 +3260,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) struct wpa_group *gsm = sm->group; u8 *wpa_ie; int secure, gtkidx, encr = 0; - u8 *wpa_ie_buf = NULL; + u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; @@ -3295,6 +3295,15 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie_len = wpa_ie[1] + 2; } #ifdef CONFIG_TESTING_OPTIONS + if (sm->wpa_auth->conf.rsne_override_eapol_set) { + wpa_ie_buf2 = replace_ie( + "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN, + sm->wpa_auth->conf.rsne_override_eapol, + sm->wpa_auth->conf.rsne_override_eapol_len); + if (!wpa_ie_buf2) + goto done; + wpa_ie = wpa_ie_buf2; + } if (sm->wpa_auth->conf.rsnxe_override_eapol_set) { wpa_ie_buf = replace_ie( "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX, @@ -3458,6 +3467,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) done: os_free(kde); os_free(wpa_ie_buf); + os_free(wpa_ie_buf2); } diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 93d7f74f2..d1324d501 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -221,10 +221,13 @@ struct wpa_auth_config { double corrupt_gtk_rekey_mic_probability; u8 own_ie_override[MAX_OWN_IE_OVERRIDE]; size_t own_ie_override_len; + u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE]; + size_t rsne_override_eapol_len; u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE]; size_t rsnxe_override_eapol_len; u8 gtk_rsc_override[WPA_KEY_RSC_LEN]; u8 igtk_rsc_override[WPA_KEY_RSC_LEN]; + unsigned int rsne_override_eapol_set:1; unsigned int rsnxe_override_eapol_set:1; unsigned int gtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 4a303b039..ff2302cd2 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -121,6 +121,15 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wpabuf_head(conf->own_ie_override), wconf->own_ie_override_len); } + if (conf->rsne_override_eapol && + wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsne_override_eapol_set = 1; + wconf->rsne_override_eapol_len = + wpabuf_len(conf->rsne_override_eapol); + os_memcpy(wconf->rsne_override_eapol, + wpabuf_head(conf->rsne_override_eapol), + wconf->rsne_override_eapol_len); + } if (conf->rsnxe_override_eapol && wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) { wconf->rsnxe_override_eapol_set = 1; From 9108e396a7cabc1655940d503f0237868b3024c6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 16:57:08 +0200 Subject: [PATCH 0162/1105] tests: RSNE mismatch in EAPOL-Key msg 3/4 Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_psk.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index 12274fdd0..ae7fe92c7 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -3351,3 +3351,36 @@ def test_ap_wpa2_psk_no_control_port(dev, apdev): wpas.request("DISCONNECT") wpas.wait_disconnected() wpas.dump_monitor() + +def test_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev): + """RSNE mismatch in EAPOL-Key msg 3/4""" + ie = "30140100000fac040100000fac040100000fac020c80" + run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, ie) + +def test_ap_wpa2_psk_rsne_mismatch_ap2(dev, apdev): + """RSNE mismatch in EAPOL-Key msg 3/4""" + ie = "30150100000fac040100000fac040100000fac020c0000" + run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, ie) + +def test_ap_wpa2_psk_rsne_mismatch_ap3(dev, apdev): + """RSNE mismatch in EAPOL-Key msg 3/4""" + run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, "") + +def run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, rsne): + params = hostapd.wpa2_params(ssid="psk", passphrase="12345678") + params['rsne_override_eapol'] = rsne + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect("psk", psk="12345678", scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["Associated with"], timeout=10) + if ev is None: + raise Exception("No indication of association seen") + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=5) + dev[0].request("REMOVE_NETWORK all") + if ev is None: + raise Exception("No disconnection seen") + if "CTRL-EVENT-DISCONNECTED" not in ev: + raise Exception("Unexpected connection") + if "reason=17 locally_generated=1" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) From fad0449438a5ecb8a2bc92e16e39124866f307a6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 17:05:01 +0200 Subject: [PATCH 0163/1105] Report RSNXE mismatch in EAPOL-Key msg 3/4 more consistently with RSNE Use the same reason code to indicate that IE different in 4-way handshake and also print a hexdump of RSNXE in both Beacon/ProbeResp and EAPOL-Key msg 3/4 in the log. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 548da45f6..39bc13d71 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1472,6 +1472,11 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0))) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4"); + wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp", + sm->ap_rsnxe, sm->ap_rsnxe_len); + wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4", + ie->rsnxe, ie->rsnxe_len); + wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); return -1; } From 7e43b6cbcf8ad5f9ba405a927ac3d6cea2e84ee6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 17:06:12 +0200 Subject: [PATCH 0164/1105] tests: RSNXE mismatch in EAPOL-Key msg 3/4 Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_psk.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index ae7fe92c7..febbc07fe 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -3384,3 +3384,23 @@ def run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, rsne): raise Exception("Unexpected connection") if "reason=17 locally_generated=1" not in ev: raise Exception("Unexpected disconnection reason: " + ev) + +def test_ap_wpa2_psk_rsnxe_mismatch_ap(dev, apdev): + """RSNXE mismatch in EAPOL-Key msg 3/4""" + params = hostapd.wpa2_params(ssid="psk", passphrase="12345678") + params['rsnxe_override_eapol'] = "F40100" + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect("psk", psk="12345678", scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["Associated with"], timeout=10) + if ev is None: + raise Exception("No indication of association seen") + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=5) + dev[0].request("REMOVE_NETWORK all") + if ev is None: + raise Exception("No disconnection seen") + if "CTRL-EVENT-DISCONNECTED" not in ev: + raise Exception("Unexpected connection") + if "reason=17 locally_generated=1" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) From 33a28170a33fb73ac8dbbb74fdf52cd4b65382fc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 17:27:32 +0200 Subject: [PATCH 0165/1105] Recognize OWE Transition Mode element in IE parser This silences the debug log entry on unknown WFA IE being ignored. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 71876c084..5da92eaef 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -130,6 +130,9 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->multi_ap = pos; elems->multi_ap_len = elen; break; + case OWE_OUI_TYPE: + /* OWE Transition Mode element */ + break; default: wpa_printf(MSG_MSGDUMP, "Unknown WFA " "information element ignored " From 785f99b6809527f44948ed98e0fd4a78e5373f68 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 17:42:50 +0200 Subject: [PATCH 0166/1105] FT: Silence debug prints when FT is not actually used Avoid printing confusing FT debug entries from wpa_sm_set_ft_params() when FT is not actually used for the connection. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa_ft.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 046bdfd16..6d627b78f 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -82,23 +82,30 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) if (sm == NULL) return 0; + if (!get_ie(ies, ies_len, WLAN_EID_MOBILITY_DOMAIN)) { + os_free(sm->assoc_resp_ies); + sm->assoc_resp_ies = NULL; + sm->assoc_resp_ies_len = 0; + os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN); + os_memset(sm->r0kh_id, 0, FT_R0KH_ID_MAX_LEN); + sm->r0kh_id_len = 0; + os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN); + return 0; + } + use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); if (wpa_ft_parse_ies(ies, ies_len, &ft, use_sha384) < 0) return -1; - if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) + if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) return -1; - if (ft.mdie) { - wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", - ft.mdie, MOBILITY_DOMAIN_ID_LEN); - os_memcpy(sm->mobility_domain, ft.mdie, - MOBILITY_DOMAIN_ID_LEN); - sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN]; - wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x", - sm->mdie_ft_capab); - } else - os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", + ft.mdie, MOBILITY_DOMAIN_ID_LEN); + os_memcpy(sm->mobility_domain, ft.mdie, MOBILITY_DOMAIN_ID_LEN); + sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN]; + wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x", + sm->mdie_ft_capab); if (ft.r0kh_id) { wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", @@ -125,10 +132,10 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) sm->assoc_resp_ies = os_malloc(ft.mdie_len + 2 + ft.ftie_len + 2); if (sm->assoc_resp_ies) { u8 *pos = sm->assoc_resp_ies; - if (ft.mdie) { - os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2); - pos += ft.mdie_len + 2; - } + + os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2); + pos += ft.mdie_len + 2; + if (ft.ftie) { os_memcpy(pos, ft.ftie - 2, ft.ftie_len + 2); pos += ft.ftie_len + 2; From ecb5219d8cd069283118bac3012b3bc838afe922 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 7 Mar 2020 18:03:32 +0200 Subject: [PATCH 0167/1105] OWE: Avoid incorrect profile update in transition mode The "unexpected" change of SSID between the current network profile (which uses the SSID from the open BSS in OWE transition mode) and the association with the OWE BSS (which uses a random, hidden SSID) resulted in wpa_supplicant incorrectly determining that this was a driver-initiated BSS selection ("Driver-initiated BSS selection changed the SSID to " in debug log). This ended up with updating security parameters based on the network profile inwpa_supplicant_set_suites() instead of using the already discovered information from scan results. In particular, this cleared the RSN supplicant state machine information of AP RSNE and resulted in having to fetch the scan results for the current BSS when processing EAPOL-Key msg 3/4. Fix this by recognizing the special case for OWE transition mode where the SSID for the associated AP does not actually match the SSID in the network profile. Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.h | 1 + wpa_supplicant/events.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 3ce8cd3f4..071676174 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -18,6 +18,7 @@ struct wpa_scan_res; #define WPA_BSS_AUTHENTICATED BIT(4) #define WPA_BSS_ASSOCIATED BIT(5) #define WPA_BSS_ANQP_FETCH_TRIED BIT(6) +#define WPA_BSS_OWE_TRANSITION BIT(7) struct wpa_bss_anqp_elem { struct dl_list list; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 37ae306bb..1149aa90b 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -188,6 +188,16 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) drv_ssid_len) == 0) return 0; /* current profile still in use */ +#ifdef CONFIG_OWE + if ((wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + wpa_s->current_bss && + (wpa_s->current_bss->flags & WPA_BSS_OWE_TRANSITION) && + drv_ssid_len == wpa_s->current_bss->ssid_len && + os_memcmp(drv_ssid, wpa_s->current_bss->ssid, + drv_ssid_len) == 0) + return 0; /* current profile still in use */ +#endif /* CONFIG_OWE */ + wpa_msg(wpa_s, MSG_DEBUG, "Driver-initiated BSS selection changed the SSID to %s", wpa_ssid_txt(drv_ssid, drv_ssid_len)); @@ -1025,6 +1035,7 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, wpa_ssid_txt(pos, ssid_len)); os_memcpy(bss->ssid, pos, ssid_len); bss->ssid_len = ssid_len; + bss->flags |= WPA_BSS_OWE_TRANSITION; #endif /* CONFIG_OWE */ } From 3c738115077a5531400fad80e44f9882e4bb5ca7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:13:35 +0200 Subject: [PATCH 0168/1105] OWE: Mark BSS for transition mode based on active OWE network profiles It is possible for the hidden OWE BSS to be found based on SSID-specific scan (e.g., from the special OWE scan mechanism). In that sequence, the previously used learning of OWE BSS was skipped since the SSID was already present in the BSS entry. This could result in not being able to find a matching BSS entry for the OWE BSS in transition mode. Fix this by adding the BSS flag for transition mode based on SSID matching against currently enabled OWE network profiles in addition to the previous mechanism. Signed-off-by: Jouni Malinen --- wpa_supplicant/events.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 1149aa90b..06c422968 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -995,6 +995,24 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, *ret_ssid = pos; *ret_ssid_len = ssid_len; + if (!(bss->flags & WPA_BSS_OWE_TRANSITION)) { + struct wpa_ssid *ssid; + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (wpas_network_disabled(wpa_s, ssid)) + continue; + if (ssid->ssid_len == ssid_len && + os_memcmp(ssid->ssid, pos, ssid_len) == 0) { + /* OWE BSS in transition mode for a currently + * enabled OWE network. */ + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: transition mode OWE SSID for active OWE profile"); + bss->flags |= WPA_BSS_OWE_TRANSITION; + break; + } + } + } + if (bss->ssid_len > 0) return; From f4bf6a5d44b3ea989f6f72de3520a3e814024330 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 11:29:45 +0200 Subject: [PATCH 0169/1105] OWE: Allow BSS entry with different SSID to be used in transition mode Similarly to the wpa_supplicant_select_config() case, wpa_get_beacon_ie() needs to handle the special case for OWE transition mode where the SSID in the network profile does not match the SSID of the OWE BSS (that has a hidden, random SSID). Accept such a BSS in case the current scan results needs to be fetched for verifying EAPOL-Key msg 3/4 IEs. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpas_glue.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 7162f8f1f..39b05b2b9 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -398,6 +398,13 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) curr = bss; break; } +#ifdef CONFIG_OWE + if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + (bss->flags & WPA_BSS_OWE_TRANSITION)) { + curr = bss; + break; + } +#endif /* CONFIG_OWE */ } if (curr) { From c7d293024b8f122fcfc7d0474730299b98c1087e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 13:11:50 +0200 Subject: [PATCH 0170/1105] RSN: Stop 4-way handshake if scan results are not available While there may have initially been cases where the RSNE from Beacon/Probe Response frames was not available from some drivers, it is now more valuable to notice if such a case were to be hit with drivers that are always expected to have such information available. As such, make it a fatal error if the scan results for the current AP are not available to check the RSNE/RSNXE in EAPOL-Key msg 3/4. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 39bc13d71..5bb47bcbe 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1424,11 +1424,10 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Could not find AP from " "the scan results"); - } else { - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: Found the current AP from " - "updated scan results"); + return -1; } + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Found the current AP from updated scan results"); } if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && From 023441c102dfb80185aa81f7158fffc95c86fe3e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 13:21:11 +0200 Subject: [PATCH 0171/1105] tests: Opportunistic Wireless Encryption transition mode and RSNE mismatch Signed-off-by: Jouni Malinen --- tests/hwsim/test_owe.py | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/hwsim/test_owe.py b/tests/hwsim/test_owe.py index 645e8d4dc..7750173c8 100644 --- a/tests/hwsim/test_owe.py +++ b/tests/hwsim/test_owe.py @@ -329,6 +329,51 @@ def run_owe_transition_mode_multi_bss(dev, apdev): raise Exception("Unexpected key_mgmt: " + val) hwsim_utils.test_connectivity(dev[0], hapd2) +def test_owe_transition_mode_rsne_mismatch(dev, apdev): + """Opportunistic Wireless Encryption transition mode and RSNE mismatch""" + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + dev[0].flush_scan_cache() + params = {"ssid": "owe-random", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "rsn_pairwise": "CCMP", + "ieee80211w": "2", + "rsne_override_eapol": "30140100000fac040100000fac040100000fac020c00", + "owe_transition_bssid": apdev[1]['bssid'], + "owe_transition_ssid": '"owe-test"', + "ignore_broadcast_ssid": "1"} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + params = {"ssid": "owe-test", + "owe_transition_bssid": apdev[0]['bssid'], + "owe_transition_ssid": '"owe-random"'} + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid, freq="2412") + dev[0].scan_for_bss(bssid2, freq="2412") + + id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2", + scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["PMKSA-CACHE-ADDED"], timeout=5) + if ev is None: + raise Exception("OWE PMKSA not created") + ev = dev[0].wait_event(["WPA: IE in 3/4 msg does not match with IE in Beacon/ProbeResp"], + timeout=5) + if ev is None: + raise Exception("RSNE mismatch not reported") + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=5) + dev[0].request("REMOVE_NETWORK all") + if ev is None: + raise Exception("No disconnection seen") + if "CTRL-EVENT-DISCONNECTED" not in ev: + raise Exception("Unexpected connection") + if "reason=17 locally_generated=1" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + def test_owe_unsupported_group(dev, apdev): """Opportunistic Wireless Encryption and unsupported group""" try: From 9bf306f57d2582a3103d8271a8c8ee475a42db2b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 13:49:22 +0200 Subject: [PATCH 0172/1105] tests: Fix sigma_dut_sae_pw_id_pwe_loop to clear sae_pwe setting Leaving out the special sae_pwe value was causing failures for following test cases, e.g., in the following sequence: sigma_dut_sae_pw_id_pwe_loop sae_password_id_only Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 54c2a57ab..3edcf2159 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -505,6 +505,7 @@ def test_sigma_dut_sae_pw_id_pwe_loop(dev, apdev): sigma_dut_cmd_check("sta_reset_default,interface," + ifname) finally: stop_sigma_dut(sigma) + dev[0].set("sae_pwe", "0") def test_sigma_dut_sae_pw_id_ft(dev, apdev): """sigma_dut controlled SAE association with Password Identifier and FT""" From fe0429a5897bbf78f0e8ae65efd31f1695f8a93f Mon Sep 17 00:00:00 2001 From: Joshua DeWeese Date: Mon, 4 Feb 2019 15:43:29 -0500 Subject: [PATCH 0173/1105] Replace systemd install Alias with WantedBy According to the systemd documentation "WantedBy=foo.service in a service bar.service is mostly equivalent to Alias=foo.service.wants/bar.service in the same file." However, this is not really the intended purpose of install Aliases. Signed-off-by: Joshua DeWeese --- wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in | 2 +- wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in | 2 +- wpa_supplicant/systemd/wpa_supplicant.service.arg.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in index 03ac50705..da69a8705 100644 --- a/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in +++ b/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in @@ -12,4 +12,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-nl80211-%I.conf -Dnl80211 -i%I [Install] -Alias=multi-user.target.wants/wpa_supplicant-nl80211@%i.service +WantedBy=multi-user.target diff --git a/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in index c8a744d6e..ca3054bc6 100644 --- a/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in +++ b/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in @@ -12,4 +12,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-wired-%I.conf -Dwired -i%I [Install] -Alias=multi-user.target.wants/wpa_supplicant-wired@%i.service +WantedBy=multi-user.target diff --git a/wpa_supplicant/systemd/wpa_supplicant.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant.service.arg.in index 7788b380c..55d2b9c81 100644 --- a/wpa_supplicant/systemd/wpa_supplicant.service.arg.in +++ b/wpa_supplicant/systemd/wpa_supplicant.service.arg.in @@ -12,4 +12,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I [Install] -Alias=multi-user.target.wants/wpa_supplicant@%i.service +WantedBy=multi-user.target From 7aa47fe5fc9660c280f3afb65fa7cfac83106fcd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:18:22 +0200 Subject: [PATCH 0174/1105] DPP: Fix connectorTemplate addition There was a copy-paste error in this code that would be adding the connectorTemplate once that becomes available. In practice, this was not reachable code, but anyway, this should be ready for potential addition of connectorTemplate in the future. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index b200d00da..c1ebae1bd 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -5230,7 +5230,7 @@ static struct wpabuf * dpp_build_conf_params(void) asn1_put_utf8string(buf, conf_template); if (connector_template) - asn1_put_utf8string(buf, conf_template); + asn1_put_utf8string(buf, connector_template); return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); } From 15d63c6043f6e30b73054510ce22343783b895fb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:28:03 +0200 Subject: [PATCH 0175/1105] Clean up hostapd_get_he_twt_responder() processing mode->he_capab is an array and as such, there is no point in checking whether it is NULL since that cannot be the case. Check for the he_supported flag instead. In addition, convert the TWT responder capability bit into a fixed value 1 to avoid any surprising to the callers. In practice, neither of these changes results in different behavior in the current implementation, but this is more robust. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11_he.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 4b23e48c7..57c6b18f4 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -421,10 +421,10 @@ int hostapd_get_he_twt_responder(struct hostapd_data *hapd, u8 *mac_cap; if (!hapd->iface->current_mode || - !hapd->iface->current_mode->he_capab) + !hapd->iface->current_mode->he_capab[mode].he_supported) return 0; mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap; - return mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER; + return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER); } From 7dcc5f7febfb3d96a1a543a539c6a8e892d5b5e6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:32:47 +0200 Subject: [PATCH 0176/1105] SAE: Check sta pointer more consistently in testing code send_auth_reply() could be called with sta == NULL in certain error conditions. While that is not applicable for this special test functionality for SAE, the inconsistent checks for the sta pointer could result in warnings from static analyzers. Address this by explicitly checking the sta pointer here. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 70de7d856..89c15b8e6 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -383,7 +383,7 @@ static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta, #ifdef CONFIG_SAE if (hapd->conf->sae_confirm_immediate == 2 && auth_alg == WLAN_AUTH_SAE) { - if (auth_transaction == 1 && + if (auth_transaction == 1 && sta && (resp == WLAN_STATUS_SUCCESS || resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT)) { wpa_printf(MSG_DEBUG, From bb2ea8e5e3a4cabf7c8959abc67a12a1bf2d1044 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:35:45 +0200 Subject: [PATCH 0177/1105] DPP: Remove unreachable return statement This was forgotten from an earlier development version. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index c1ebae1bd..012956b3e 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -5375,7 +5375,6 @@ fail: return asn1_encaps(asn1_encaps(key, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE), ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); - return key; } From 17ba51b14dc19c0e1ec86888ff6a010479c25fdf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:38:57 +0200 Subject: [PATCH 0178/1105] nl80211: Fix tx_control_port error print send_and_recv_msgs() returns a negative number as the error code and that needs to be negated for strerror(). Fixes: 8759e9116aa6 ("nl80211: Control port over nl80211 helpers") Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 93aa5d702..254a47a7f 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5219,7 +5219,7 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest, if (ret) wpa_printf(MSG_DEBUG, "nl80211: tx_control_port failed: ret=%d (%s)", - ret, strerror(ret)); + ret, strerror(-ret)); return ret; } From a17cbcd698d53cbf3dece9c7b71f0f77afd19ee9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:43:09 +0200 Subject: [PATCH 0179/1105] os_unix: Call srandom() only if os_get_random() succeeds Don't use uninitialized stack memory if /dev/urandom is not available. Signed-off-by: Jouni Malinen --- src/utils/os_unix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c index fc1110b3c..6f0c17756 100644 --- a/src/utils/os_unix.c +++ b/src/utils/os_unix.c @@ -367,8 +367,8 @@ int os_program_init(void) capset(&header, &cap); #endif /* ANDROID */ - os_get_random((unsigned char *) &seed, sizeof(seed)); - srandom(seed); + if (os_get_random((unsigned char *) &seed, sizeof(seed)) == 0) + srandom(seed); return 0; } From b0927e5d06eed02e4746f4ad5e710f84a2c1718a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:48:00 +0200 Subject: [PATCH 0180/1105] nl80211: Fix error print for hapd_send_eapol() The return value from nl80211_send_monitor() is not suitable for use with strerror(). Furthermore, nl80211_send_monitor() itself is printing out a more detailed error reason. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 254a47a7f..5b312502b 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5313,9 +5313,9 @@ static int wpa_driver_nl80211_hapd_send_eapol( res = nl80211_send_monitor(drv, hdr, len, encrypt, 0); if (res < 0) { - wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - " - "failed: %d (%s)", - (unsigned long) len, res, strerror(res)); + wpa_printf(MSG_ERROR, + "hapd_send_eapol - packet len: %lu - failed", + (unsigned long) len); } os_free(hdr); From 7f1f69e897563bca562cd4820dcb69fec47bc1e4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:51:30 +0200 Subject: [PATCH 0181/1105] SAE: Check hmac_sha256() result in sae_token_hash() In theory, hmac_sha256() might fail, so check for that possibility instead of continuing with undetermined index value that could point to an arbitrary token entry. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 89c15b8e6..e3daee2c9 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -639,13 +639,15 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd) } -static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr) +static int sae_token_hash(struct hostapd_data *hapd, const u8 *addr, u8 *idx) { u8 hash[SHA256_MAC_LEN]; - hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key), - addr, ETH_ALEN, hash); - return hash[0]; + if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key), + addr, ETH_ALEN, hash) < 0) + return -1; + *idx = hash[0]; + return 0; } @@ -658,9 +660,8 @@ static int check_sae_token(struct hostapd_data *hapd, const u8 *addr, u16 token_idx; u8 idx; - if (token_len != SHA256_MAC_LEN) + if (token_len != SHA256_MAC_LEN || sae_token_hash(hapd, addr, &idx) < 0) return -1; - idx = sae_token_hash(hapd, addr); token_idx = hapd->sae_pending_token_idx[idx]; if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) { wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from " @@ -724,7 +725,10 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd, wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN); } - p_idx = sae_token_hash(hapd, addr); + if (sae_token_hash(hapd, addr, &p_idx) < 0) { + wpabuf_free(buf); + return NULL; + } token_idx = hapd->sae_pending_token_idx[p_idx]; if (!token_idx) { hapd->sae_token_idx++; From 10223b501b4f576a570d977a9560c753d658e0c3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Mar 2020 16:59:42 +0200 Subject: [PATCH 0182/1105] SAE: Expose sae_write_commit() error cases to callers Check whether an error is reported from any of the functions that could in theory fail and if so, do not proceed with the partially filled SAE commit buffer. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 11 +++++++---- src/common/common_module_tests.c | 3 ++- src/common/sae.c | 26 ++++++++++++++++---------- src/common/sae.h | 4 ++-- wpa_supplicant/sme.c | 7 +++++-- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index e3daee2c9..7937b8120 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -536,10 +536,13 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN + (rx_id ? 3 + os_strlen(rx_id) : 0)); - if (buf == NULL) - return NULL; - sae_write_commit(sta->sae, buf, sta->sae->tmp ? - sta->sae->tmp->anti_clogging_token : NULL, rx_id); + if (buf && + sae_write_commit(sta->sae, buf, sta->sae->tmp ? + sta->sae->tmp->anti_clogging_token : NULL, + rx_id) < 0) { + wpabuf_free(buf); + buf = NULL; + } return buf; } diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c index 7694c96b4..a58bf666a 100644 --- a/src/common/common_module_tests.c +++ b/src/common/common_module_tests.c @@ -434,7 +434,8 @@ static int sae_tests(void) goto fail; /* Check that output matches the test vector */ - sae_write_commit(&sae, buf, NULL, pwid); + if (sae_write_commit(&sae, buf, NULL, pwid) < 0) + goto fail; wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf); if (wpabuf_len(buf) != sizeof(local_commit) || diff --git a/src/common/sae.c b/src/common/sae.c index 7ed53be1c..543640de3 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -1623,13 +1623,13 @@ int sae_process_commit(struct sae_data *sae) } -void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, - const struct wpabuf *token, const char *identifier) +int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, + const struct wpabuf *token, const char *identifier) { u8 *pos; if (sae->tmp == NULL) - return; + return -1; wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ if (!sae->tmp->h2e && token) { @@ -1638,23 +1638,27 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, 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); + if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos, + sae->tmp->prime_len, sae->tmp->prime_len) < 0) + return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar", pos, sae->tmp->prime_len); if (sae->tmp->ec) { pos = wpabuf_put(buf, 2 * sae->tmp->prime_len); - crypto_ec_point_to_bin(sae->tmp->ec, - sae->tmp->own_commit_element_ecc, - pos, pos + sae->tmp->prime_len); + if (crypto_ec_point_to_bin(sae->tmp->ec, + sae->tmp->own_commit_element_ecc, + pos, pos + sae->tmp->prime_len) < 0) + return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)", pos, sae->tmp->prime_len); wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)", pos + sae->tmp->prime_len, sae->tmp->prime_len); } else { pos = wpabuf_put(buf, sae->tmp->prime_len); - crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, - sae->tmp->prime_len, sae->tmp->prime_len); + if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, + sae->tmp->prime_len, + sae->tmp->prime_len) < 0) + return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-element", pos, sae->tmp->prime_len); } @@ -1688,6 +1692,8 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, "SAE: Anti-clogging token (in container)", token); } + + return 0; } diff --git a/src/common/sae.h b/src/common/sae.h index e3e7d0eec..7966d70e4 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -88,8 +88,8 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, const u8 *addr1, const u8 *addr2, int *rejected_groups); int sae_process_commit(struct sae_data *sae); -void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, - const struct wpabuf *token, const char *identifier); +int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, + const struct wpabuf *token, const char *identifier); u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, const u8 **token, size_t *token_len, int *allowed_groups, int h2e); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index d0088f9f4..aa59f151a 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -182,8 +182,11 @@ reuse_data: wpabuf_put_le16(buf, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS); } - sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token, - ssid->sae_password_id); + if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token, + ssid->sae_password_id) < 0) { + wpabuf_free(buf); + return NULL; + } if (ret_use_pt) *ret_use_pt = use_pt; From 12a508a11f50ca6ca6ba12ca9143f590221c0ba1 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 8 Mar 2020 14:27:02 +0100 Subject: [PATCH 0183/1105] tests: remote: Allow to run module tests Add a new command line option -f (--modules) that will run all test cases from the specified module(s). Signed-off-by: Janusz Dziedzic --- tests/remote/run-tests.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py index e1ff98977..95c8ab65d 100755 --- a/tests/remote/run-tests.py +++ b/tests/remote/run-tests.py @@ -32,7 +32,7 @@ from hwsim_wrapper import run_hwsim_test def usage(): print("USAGE: " + sys.argv[0] + " -t devices") print("USAGE: " + sys.argv[0] + " -t check_devices") - print("USAGE: " + sys.argv[0] + " -d -t [-r ] [-c ] [-m ] [-h hwsim_tests][-R][-T][-P][-v]") + print("USAGE: " + sys.argv[0] + " -d -t [-r ] [-c ] [-m ] [-h hwsim_tests] [-f hwsim_modules][-R][-T][-P][-v]") print("USAGE: " + sys.argv[0]) def get_devices(devices, duts, refs, monitors): @@ -71,6 +71,8 @@ def main(): requested_tests = ["help"] requested_hwsim_tests = [] hwsim_tests = [] + requested_modules = [] + modules_tests = [] cfg_file = "cfg.py" log_dir = "./logs/" verbose = False @@ -80,8 +82,9 @@ def main(): # parse input parameters try: - opts, args = getopt.getopt(sys.argv[1:], "d:r:t:l:k:c:m:h:vRPT", - ["dut=", "ref=", "tests=", "log-dir=", + opts, args = getopt.getopt(sys.argv[1:], "d:f:r:t:l:k:c:m:h:vRPT", + ["dut=", "modules=", "ref=", "tests=", + "log-dir=", "cfg=", "key=", "monitor=", "hwsim="]) except getopt.GetoptError as err: print(err) @@ -113,6 +116,8 @@ def main(): cfg_file = argument elif option in ("-h", "--hwsim"): requested_hwsim_tests = re.split('; | |, ', argument) + elif option in ("-f", "--modules"): + requested_modules = re.split('; | |, ', argument) else: assert False, "unhandled option" @@ -208,6 +213,22 @@ def main(): continue hwsim_tests_to_run.append(t) + # import test_* from modules + files = os.listdir("../hwsim/") + for t in files: + m = re.match(r'(test_.*)\.py$', t) + if m: + mod = __import__(m.group(1)) + if mod.__name__.replace('test_', '', 1) not in requested_modules: + continue + for key, val in mod.__dict__.items(): + if key.startswith("test_"): + modules_tests.append(val) + + if len(requested_modules) > 0: + requested_hwsim_tests = modules_tests + hwsim_tests_to_run = modules_tests + # sort the list test_names.sort() tests.sort() From fbf877b012b159abfb8454973f221e556c145429 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 8 Mar 2020 14:27:03 +0100 Subject: [PATCH 0184/1105] tests: Clear regulatory domain on the correct remote device In case we run remote tests we need to clear/set regulatory domain on the correct device. Signed-off-by: Janusz Dziedzic --- tests/hwsim/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index b3a883131..fdd95eebf 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -162,7 +162,7 @@ def clear_regdom_dev(dev, count=1): dev[i].request("DISCONNECT") for i in range(count): dev[i].disconnect_and_stop_scan() - subprocess.call(['iw', 'reg', 'set', '00']) + dev[0].cmd_execute(['iw', 'reg', 'set', '00']) wait_regdom_changes(dev[0]) country = dev[0].get_driver_status_field("country") logger.info("Country code at the end: " + country) From 60b06d8750ee3547e51d78ae47100e6d3ecbb435 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sun, 8 Mar 2020 14:27:04 +0100 Subject: [PATCH 0185/1105] tests: Set device_name for WPS test cases Set device_name in the test cases instead of relying on the wpa_supplicant configuration file. This fixes problems when we run WPS test cases in remote test environment. Signed-off-by: Janusz Dziedzic --- tests/hwsim/test_ap_wps.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index b4dacf280..b1b0331c4 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -230,6 +230,7 @@ def test_ap_wps_conf(dev, apdev): "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}) logger.info("WPS provisioning step") hapd.request("WPS_PBC") + dev[0].set("device_name", "Device A") dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") dev[0].dump_monitor() dev[0].request("WPS_PBC " + apdev[0]['bssid']) @@ -262,6 +263,7 @@ def test_ap_wps_conf_5ghz(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) logger.info("WPS provisioning step") hapd.request("WPS_PBC") + dev[0].set("device_name", "Device A") dev[0].scan_for_bss(apdev[0]['bssid'], freq="5180") dev[0].request("WPS_PBC " + apdev[0]['bssid']) dev[0].wait_connected(timeout=30) @@ -285,6 +287,7 @@ def test_ap_wps_conf_chan14(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) logger.info("WPS provisioning step") hapd.request("WPS_PBC") + dev[0].set("device_name", "Device A") dev[0].request("WPS_PBC") dev[0].wait_connected(timeout=30) From 52efde2aaa3f40808a7a179ce7b61b365bce2c4c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 10 Mar 2020 20:48:15 +0200 Subject: [PATCH 0186/1105] WPS: Do not set auth_alg=OPEN for PSK+SAE case When wps_cred_add_sae=1 is used, WPS_AUTH_WPA2PSK credential gets converted to enabling both PSK and SAE AKMs. However, this case was still hardcoded auth_alg=OPEN which is not really correct for SAE. While the SME-in-wpa_supplicant case can handle that, the SME-in-driver case might not. Remove the unnecessary auth_alg=OPEN configuration to get the normal PSK+SAE configuration enabled for the network profile. Signed-off-by: Jouni Malinen --- wpa_supplicant/wps_supplicant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 063b4e69f..a10c34cf0 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -532,6 +532,7 @@ static int wpa_supplicant_wps_cred(void *ctx, ssid->key_mgmt = WPA_KEY_MGMT_PSK; if (wpa_s->conf->wps_cred_add_sae && cred->key_len != 2 * PMK_LEN) { + ssid->auth_alg = 0; ssid->key_mgmt |= WPA_KEY_MGMT_SAE; ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; } From 1f13c1393c350bf70cbf107d2ae4529a9c6ff9fa Mon Sep 17 00:00:00 2001 From: Arturo Buzarra Date: Mon, 9 Mar 2020 18:18:16 +0100 Subject: [PATCH 0187/1105] mesh: Fix CONFIG_HT_OVERRIDES build without CONFIG_VHT_OVERRIDES Commit e5a9b1e8a3 ("mesh: Implement use of VHT20 config in mesh mode") introduced the possibility to check the disable_vht param. However, this entry is only available when CONFIG_VHT_OVERRIDES is enabled and as such, this broke the build for some cases. Fix this by encapsulating VHT property with the proper CONFIG entry. Fixes: e5a9b1e8a3a5 ("mesh: Implement use of VHT20 config in mesh mode") Signed-off-by: Arturo Buzarra --- wpa_supplicant/wpa_supplicant.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 839afe32d..ba8ae65ae 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2396,8 +2396,10 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, #ifdef CONFIG_HT_OVERRIDES if (ssid->disable_ht40) { +#ifdef CONFIG_VHT_OVERRIDES if (ssid->disable_vht) return; +#endif /* CONFIG_VHT_OVERRIDES */ goto skip_ht40; } #endif /* CONFIG_HT_OVERRIDES */ From d9a7b71a78524bb56bcd3f341c97c398e2966725 Mon Sep 17 00:00:00 2001 From: Hrishikesh Vidwans Date: Fri, 6 Mar 2020 10:57:58 -0800 Subject: [PATCH 0188/1105] AP: Fix regression in frequency check for a usable EDMG channel Commit 5f9b4afd ("Use frequency in HT/VHT validation steps done before starting AP") modified hostapd_is_usable_edmg() to use freq instead of channel numbers. Unfortunately, it did not convert the frequency calculation correctly and this broke EDMG functionality. Fix the frequency calculation so that EDMG channel 9 works again. Fixes: 5f9b4afdfaf5 ("Use frequency in HT/VHT validation steps done before starting AP") Signed-off-by: Hrishikesh Vidwans --- src/ap/hw_features.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index b73cc88e0..f6e69030d 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -785,7 +785,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface) /* 60 GHz channels 1..6 */ for (i = 0; i < 6; i++) { - int freq = 56160 + 2160 * i; + int freq = 56160 + 2160 * (i + 1); if (edmg.channels & BIT(i)) { contiguous++; From 2b9713d61611c946e3e41a135e7aafb146f8a61f Mon Sep 17 00:00:00 2001 From: Ananya Barat Date: Tue, 10 Mar 2020 12:07:33 +0530 Subject: [PATCH 0189/1105] Fill the current opclass in (Re)AssocRequest depending on HT/VHT IEs The previous implementation was assuming a fixed 20 MHz channel bandwidth when determining which operating class value to indicate as the Current Operating Class in the Supported Operating Classes element. This is not accurate for many HT/VHT cases. Fix this by determining the current operating class (i.e., the operating class used for the requested association) based on the HT/VHT operation elements from scan results. Signed-off-by: Jouni Malinen --- wpa_supplicant/op_classes.c | 29 ++++++++++++++++++++++++----- wpa_supplicant/rrm.c | 4 ++-- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wpa_supplicant.c | 2 +- wpa_supplicant/wpa_supplicant_i.h | 4 +++- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c index f49bdb094..983801faa 100644 --- a/wpa_supplicant/op_classes.c +++ b/wpa_supplicant/op_classes.c @@ -14,6 +14,7 @@ #include "utils/common.h" #include "common/ieee802_11_common.h" #include "wpa_supplicant_i.h" +#include "bss.h" static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, @@ -356,9 +357,25 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s, } +static int wpas_sta_secondary_channel_offset(struct wpa_bss *bss, u8 *current, + u8 *channel) +{ + + u8 *ies, phy_type; + size_t ies_len; + + if (!bss) + return -1; + ies = (u8 *) (bss + 1); + ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; + return wpas_get_op_chan_phy(bss->freq, ies, ies_len, current, + channel, &phy_type); +} + + size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, - int freq, u8 *pos, size_t len) + struct wpa_bss *bss, u8 *pos, size_t len) { struct wpabuf *buf; u8 op, current, chan; @@ -366,11 +383,13 @@ size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, size_t res; /* - * Assume 20 MHz channel for now. - * TODO: Use the secondary channel and VHT channel width that will be - * used after association. + * Determine the current operating class correct mode based on + * advertised BSS capabilities, if available. Fall back to a less + * accurate guess based on frequency if the needed IEs are not available + * or used. */ - if (ieee80211_freq_to_channel_ext(freq, 0, CHANWIDTH_USE_HT, + if (wpas_sta_secondary_channel_offset(bss, ¤t, &chan) < 0 && + ieee80211_freq_to_channel_ext(bss->freq, 0, CHANWIDTH_USE_HT, ¤t, &chan) == NUM_HOSTAPD_MODES) return 0; diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c index 66855b877..afc117275 100644 --- a/wpa_supplicant/rrm.c +++ b/wpa_supplicant/rrm.c @@ -695,8 +695,8 @@ static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s, } -static int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, - u8 *op_class, u8 *chan, u8 *phy_type) +int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, + u8 *op_class, u8 *chan, u8 *phy_type) { const u8 *ie; int sec_chan = 0, vht = 0; diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index aa59f151a..d4c12d1e3 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -578,7 +578,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, sme_auth_handle_rrm(wpa_s, bss); wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie( - wpa_s, ssid, bss->freq, + wpa_s, ssid, bss, wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ba8ae65ae..584ca3b91 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2890,7 +2890,7 @@ static u8 * wpas_populate_assoc_ies( #endif /* CONFIG_P2P */ if (bss) { - wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq, + wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss, wpa_ie + wpa_ie_len, max_wpa_ie_len - wpa_ie_len); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index eac7cad2d..383bf8e69 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1394,6 +1394,8 @@ int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style); int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s); void add_freq(int *freqs, int *num_freqs, int freq); +int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, + u8 *op_class, u8 *chan, u8 *phy_type); void wpas_rrm_reset(struct wpa_supplicant *wpa_s); void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, const u8 *report, size_t report_len); @@ -1453,7 +1455,7 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class, u8 channel, u8 bw); size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, - int freq, u8 *pos, size_t len); + struct wpa_bss *bss, u8 *pos, size_t len); int * wpas_supp_op_classes(struct wpa_supplicant *wpa_s); int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s, From 55093c80149ff49a3874ecedf87ffc9df75445b7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 11 Mar 2020 18:30:51 +0200 Subject: [PATCH 0190/1105] tests: Current Operating Class value from STA Verify Supported Operating Classes element contents from STA in various HT and VHT cases. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ht.py | 19 +++++++++++++++++++ tests/hwsim/test_ap_vht.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py index bb942bfff..c2b032c11 100644 --- a/tests/hwsim/test_ap_ht.py +++ b/tests/hwsim/test_ap_ht.py @@ -73,6 +73,18 @@ def test_ap_ht40_scan(dev, apdev): sta = hapd.get_sta(dev[0].own_addr()) logger.info("hostapd STA: " + str(sta)) + res = dev[0].request("SIGNAL_POLL") + logger.info("STA SIGNAL_POLL:\n" + res.strip()) + sig = res.splitlines() + if "WIDTH=40 MHz" not in sig: + raise Exception("Not a 40 MHz connection") + + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 84: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) + def test_ap_ht_wifi_generation(dev, apdev): """HT and wifi_generation""" clear_scan_cache(apdev[0]) @@ -892,6 +904,13 @@ def test_ap_require_ht(dev, apdev): ampdu_density="1", disable_ht40="1", disable_sgi="1", disable_ldpc="1", rx_stbc="2", tx_stbc="1") + sta = hapd.get_sta(dev[0].own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 81: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) + def test_ap_ht_stbc(dev, apdev): """HT STBC overrides""" params = {"ssid": "ht"} diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index ece0efda3..76257c79b 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -75,6 +75,11 @@ def test_ap_vht80(dev, apdev): raise Exception("Missing STA flag: HT") if "[VHT]" not in sta['flags']: raise Exception("Missing STA flag: VHT") + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 128: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) except Exception as e: if isinstance(e, Exception) and str(e) == "AP startup failed": if not vht_supported(): @@ -290,6 +295,13 @@ def test_ap_vht_20(devs, apdevs): hapd = hostapd.add_ap(ap, params) dev.connect("test-vht20", scan_freq="5180", key_mgmt="NONE") hwsim_utils.test_connectivity(dev, hapd) + + sta = hapd.get_sta(dev.own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 115: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) finally: dev.request("DISCONNECT") clear_regdom(hapd, devs) @@ -313,6 +325,13 @@ def test_ap_vht_40(devs, apdevs): hapd = hostapd.add_ap(ap, params) dev.connect("test-vht40", scan_freq="5180", key_mgmt="NONE") hwsim_utils.test_connectivity(dev, hapd) + + sta = hapd.get_sta(dev.own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 116: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) finally: dev.request("DISCONNECT") clear_regdom(hapd, devs) @@ -395,6 +414,13 @@ def test_ap_vht160(dev, apdev): raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) if "WIDTH=160 MHz" not in sig: raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) + + sta = hapd.get_sta(dev[0].own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 129: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) except Exception as e: if isinstance(e, Exception) and str(e) == "AP startup failed": if not vht_supported(): @@ -644,6 +670,13 @@ def test_ap_vht80plus80(dev, apdev): raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig)) if "CENTER_FRQ2=5775" not in sig: raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig)) + + sta = hapd2.get_sta(dev[1].own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 130: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) except Exception as e: if isinstance(e, Exception) and str(e) == "AP startup failed": if not vht_supported(): From 440dac755822c1ee6a415d1f1f77e4938ae52a73 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 6 Mar 2020 14:58:11 -0800 Subject: [PATCH 0191/1105] hs20-osu-client: Use more specific debug message on OSU connection Signed-off-by: Ben Greear --- hs20/client/osu_client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c index f1b078b1a..1bf1a0e1a 100644 --- a/hs20/client/osu_client.c +++ b/hs20/client/osu_client.c @@ -2233,7 +2233,7 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid, wpa_ctrl_close(mon); if (res < 0) { - wpa_printf(MSG_INFO, "Could not connect"); + wpa_printf(MSG_INFO, "Could not connect to OSU network"); write_summary(ctx, "Could not connect to OSU network"); wpa_printf(MSG_INFO, "Remove OSU network connection"); snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id); From e0fb468a7d697ad361a7934bb55167199eb2b556 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 6 Mar 2020 14:58:11 -0800 Subject: [PATCH 0192/1105] HS 2.0 server: Add a note on OCSP server hostname Signed-off-by: Ben Greear --- hs20/server/ca/ocsp-update-cache.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/hs20/server/ca/ocsp-update-cache.sh b/hs20/server/ca/ocsp-update-cache.sh index 8ddef9b9c..f2b23250c 100755 --- a/hs20/server/ca/ocsp-update-cache.sh +++ b/hs20/server/ca/ocsp-update-cache.sh @@ -1,5 +1,6 @@ #!/bin/sh +# NOTE: You may need to replace 'localhost' with your OCSP server hostname. openssl ocsp \ -no_nonce \ -CAfile ca.pem \ From 1d9cff86bd04c52fb448a4a83ee18a094613abff Mon Sep 17 00:00:00 2001 From: Gurumoorthi Gnanasambandhan Date: Wed, 11 Mar 2020 16:11:54 +0530 Subject: [PATCH 0193/1105] Multi-AP: Set 4-address mode after network selection Split multi_ap_process_assoc_resp() to set 4-address mode after network selection. Previously, wpa_s->current_ssid might have been NULL in some cases and that would have resulted in 4-address mode not getting enabled properly. Signed-off-by: Gurumoorthi Gnanasambandhan --- wpa_supplicant/events.c | 41 +++++++++++++++++++++---------- wpa_supplicant/wpa_supplicant.c | 1 + wpa_supplicant/wpa_supplicant_i.h | 3 +++ 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 06c422968..15f7ae82e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2465,28 +2465,41 @@ static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s, const u8 *map_sub_elem, *pos; size_t len; - if (!wpa_s->current_ssid || - !wpa_s->current_ssid->multi_ap_backhaul_sta || - !ies || - ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) - return; + wpa_s->multi_ap_ie = 0; - if (!elems.multi_ap || elems.multi_ap_len < 7) { - wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol"); - goto fail; - } + if (!ies || + ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed || + !elems.multi_ap || elems.multi_ap_len < 7) + return; pos = elems.multi_ap + 4; len = elems.multi_ap_len - 4; map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE); - if (!map_sub_elem || map_sub_elem[1] < 1) { - wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type"); + if (!map_sub_elem || map_sub_elem[1] < 1) + return; + + wpa_s->multi_ap_backhaul = !!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS); + wpa_s->multi_ap_fronthaul = !!(map_sub_elem[2] & + MULTI_AP_FRONTHAUL_BSS); + wpa_s->multi_ap_ie = 1; +} + + +static void multi_ap_set_4addr_mode(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->current_ssid || + !wpa_s->current_ssid->multi_ap_backhaul_sta) + return; + + if (!wpa_s->multi_ap_ie) { + wpa_printf(MSG_INFO, + "AP does not include valid Multi-AP element"); goto fail; } - if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) { - if ((map_sub_elem[2] & MULTI_AP_FRONTHAUL_BSS) && + if (!wpa_s->multi_ap_backhaul) { + if (wpa_s->multi_ap_fronthaul && wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) { wpa_printf(MSG_INFO, "WPS active, accepting fronthaul-only BSS"); @@ -2988,6 +3001,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, } } + multi_ap_set_4addr_mode(wpa_s); + if (wpa_s->conf->ap_scan == 1 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION) { if (wpa_supplicant_assoc_update_ie(wpa_s) < 0 && new_bss) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 584ca3b91..44c34f041 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2091,6 +2091,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, else rand_style = ssid->mac_addr; + wpa_s->multi_ap_ie = 0; wmm_ac_clear_saved_tspecs(wpa_s); wpa_s->reassoc_same_bss = 0; wpa_s->reassoc_same_ess = 0; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 383bf8e69..a6ec3f37e 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1287,6 +1287,9 @@ struct wpa_supplicant { unsigned int enabled_4addr_mode:1; unsigned int multi_bss_support:1; unsigned int drv_authorized_port:1; + unsigned int multi_ap_ie:1; + unsigned int multi_ap_backhaul:1; + unsigned int multi_ap_fronthaul:1; }; From e861fa1f6b6cdfc7cf6f4ada0decb0e2a185b7f0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 13 Mar 2020 20:01:53 +0200 Subject: [PATCH 0194/1105] Move the "WPA: AP key_mgmt" debug print to be after final changes Driver capabilities may end up masking out some WPA_KEY_MGMT_* bits, so debug print the outcome only after having performed all these steps. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 44c34f041..02895054f 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1457,9 +1457,6 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, #endif /* CONFIG_NO_WPA */ sel = ie.key_mgmt & ssid->key_mgmt; - wpa_dbg(wpa_s, MSG_DEBUG, - "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x", - ie.key_mgmt, ssid->key_mgmt, sel); #ifdef CONFIG_SAE if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE); @@ -1469,6 +1466,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, WPA_DRIVER_FLAGS_UPDATE_FT_IES))) sel &= ~WPA_KEY_MGMT_FT; #endif /* CONFIG_IEEE80211R */ + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x", + ie.key_mgmt, ssid->key_mgmt, sel); if (0) { #ifdef CONFIG_IEEE80211R #ifdef CONFIG_SHA384 From 839bab785ba251ee4327a3f80d27e5c48fb5551c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 13 Mar 2020 20:03:14 +0200 Subject: [PATCH 0195/1105] nl80211: Debug print driver capabilities This can be helpful in understanding driver behavior. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211_capa.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index ea1ab8a2f..5a51b429d 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1311,6 +1311,12 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS; #endif /* CONFIG_DRIVER_NL80211_QCA */ + wpa_printf(MSG_DEBUG, + "nl80211: key_mgmt=0x%x enc=0x%x auth=0x%x flags=0x%llx rrm_flags=0x%x probe_resp_offloads=0x%x max_stations=%u max_remain_on_chan=%u max_scan_ssids=%d", + drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth, + (unsigned long long) drv->capa.flags, drv->capa.rrm_flags, + drv->capa.probe_resp_offloads, drv->capa.max_stations, + drv->capa.max_remain_on_chan, drv->capa.max_scan_ssids); return 0; } From 80d41221599b9bcf21dddbd1573ea7e84ae0c913 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 14 Mar 2020 17:31:57 +0200 Subject: [PATCH 0196/1105] wlantest: Detect and report plaintext payload in protected frames Signed-off-by: Jouni Malinen --- wlantest/readpcap.c | 1 + wlantest/rx_data.c | 19 +++++++++++++++++++ wlantest/wlantest.h | 1 + 3 files changed, 21 insertions(+) diff --git a/wlantest/readpcap.c b/wlantest/readpcap.c index 6c3853b05..1e7e66260 100644 --- a/wlantest/readpcap.c +++ b/wlantest/readpcap.c @@ -92,6 +92,7 @@ int read_cap_file(struct wlantest *wt, const char *fname) } /* Packet was read without problems */ + wt->frame_num++; wpa_printf(MSG_EXCESSIVE, "pcap hdr: ts=%d.%06d " "len=%u/%u", (int) hdr->ts.tv_sec, (int) hdr->ts.tv_usec, diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index f0f0df95c..d86a5886c 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -191,6 +191,23 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, } +static void check_plaintext_prot(struct wlantest *wt, + const struct ieee80211_hdr *hdr, + const u8 *data, size_t len) +{ + if (len < 8 + 3 || data[8] != 0xaa || data[9] != 0xaa || + data[10] != 0x03) + return; + + add_note(wt, MSG_DEBUG, + "Plaintext payload in protected frame"); + wpa_printf(MSG_INFO, "Plaintext payload in protected frame #%u: A2=" + MACSTR " seq=%u", + wt->frame_num, MAC2STR(hdr->addr2), + WLAN_GET_SEQ_SEQ(le_to_host16(hdr->seq_ctrl))); +} + + static void rx_data_bss_prot_group(struct wlantest *wt, const struct ieee80211_hdr *hdr, size_t hdrlen, @@ -241,6 +258,7 @@ static void rx_data_bss_prot_group(struct wlantest *wt, } } + check_plaintext_prot(wt, hdr, data, len); keyid = data[3] >> 6; if (bss->gtk_len[keyid] == 0 && bss->group_cipher != WPA_CIPHER_WEP40) { @@ -401,6 +419,7 @@ static void rx_data_bss_prot(struct wlantest *wt, tdls = found; } } + check_plaintext_prot(wt, hdr, data, len); if ((sta == NULL || (!sta->ptk_set && sta->pairwise_cipher != WPA_CIPHER_WEP40)) && tk == NULL) { diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 2cf51966a..e2395d033 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -195,6 +195,7 @@ struct wlantest { unsigned int rx_ctrl; unsigned int rx_data; unsigned int fcs_error; + unsigned int frame_num; void *write_pcap; /* pcap_t* */ void *write_pcap_dumper; /* pcpa_dumper_t */ From a8d2ca9e23a6855fb6910de8491fc599e6f4bc48 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 14 Mar 2020 18:20:31 +0200 Subject: [PATCH 0197/1105] wlantest: Do not report PMF failure without BSS supporting PMF Previously, missing CCMP protection on Robust Management frames was reported based on the STA having indicated MFPC=1. That is not accurate since the AP/BSS may have MFPC=0. Report this failure only if both the AP and STA have indicated MFPC=1, i.e., when PMF has been negotiated for the association. Signed-off-by: Jouni Malinen --- wlantest/rx_mgmt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 78fd3c80a..ad388e122 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -1646,7 +1646,8 @@ static int check_mgmt_ccmp(struct wlantest *wt, const u8 *data, size_t len) if (sta == NULL) return 0; - if ((sta->rsn_capab & WPA_CAPABILITY_MFPC) && + if ((bss->rsn_capab & WPA_CAPABILITY_MFPC) && + (sta->rsn_capab & WPA_CAPABILITY_MFPC) && (sta->state == STATE3 || WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION)) { add_note(wt, MSG_INFO, "Robust individually-addressed " From 1a8e9334c0736344f27e90cc175e07e0912cb60e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 14 Mar 2020 23:57:39 +0200 Subject: [PATCH 0198/1105] FT: Check RSNE/RSNXE match in FT protocol Reassociation Response frame While 13.7.1 (FT reassociation in an RSN) in P802.11-REVmd/D3.0 did not explicitly require this to be done, this is implied when describing the contents of the fourth message in the FT authentication sequence (see 13.8.5). Furthermore, 20/332r2 is proposing an explicit validation step to be added into 13.7.1. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa_ft.c | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 6d627b78f..baa185ffe 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -1090,6 +1090,50 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return -1; } + if (!sm->ap_rsn_ie) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "FT: No RSNE for this AP known - trying to get from scan results"); + if (wpa_sm_get_beacon_ie(sm) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "FT: Could not find AP from the scan results"); + return -1; + } + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, + "FT: Found the current AP from updated scan results"); + } + + if (sm->ap_rsn_ie && + wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), + sm->ap_rsn_ie, sm->ap_rsn_ie_len, + parse.rsn - 2, parse.rsn_len + 2)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "FT: RSNE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame"); + wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp", + sm->ap_rsn_ie, sm->ap_rsn_ie_len); + wpa_hexdump(MSG_INFO, + "RSNE in FT protocol Reassociation Response frame", + parse.rsn ? parse.rsn - 2 : NULL, + parse.rsn ? parse.rsn_len + 2 : 0); + return -1; + } + + if ((sm->ap_rsnxe && !parse.rsnxe) || + (!sm->ap_rsnxe && parse.rsnxe) || + (sm->ap_rsnxe && parse.rsnxe && + (sm->ap_rsnxe_len != 2 + parse.rsnxe_len || + os_memcmp(sm->ap_rsnxe, parse.rsnxe - 2, + sm->ap_rsnxe_len) != 0))) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "FT: RSNXE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame"); + wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp", + sm->ap_rsnxe, sm->ap_rsnxe_len); + wpa_hexdump(MSG_INFO, + "RSNXE in FT protocol Reassociation Response frame", + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0); + return -1; + } + #ifdef CONFIG_OCV if (wpa_sm_ocv_enabled(sm)) { struct wpa_channel_info ci; From 46e147fcdc5fe6ad2077c235763afeca0498ae70 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 14 Mar 2020 23:30:27 +0200 Subject: [PATCH 0199/1105] Allow RSNE/RSNXE to be replaced in FT protocol Reassocation Response frame This can be used to test station side behavior for FT protocol validation steps. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 6 ++++++ src/ap/ap_config.c | 2 ++ src/ap/ap_config.h | 2 ++ src/ap/ieee802_11.c | 15 +++++++++++++++ src/ap/wpa_auth.h | 6 ++++++ src/ap/wpa_auth_ft.c | 39 +++++++++++++++++++++++++++++++++++++-- src/ap/wpa_auth_glue.c | 18 ++++++++++++++++++ 7 files changed, 86 insertions(+), 2 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 98e9fd21b..1a5b742b2 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4182,6 +4182,12 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) { wpabuf_free(bss->rsnxe_override_eapol); bss->rsnxe_override_eapol = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "rsne_override_ft") == 0) { + wpabuf_free(bss->rsne_override_ft); + bss->rsne_override_ft = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "rsnxe_override_ft") == 0) { + wpabuf_free(bss->rsnxe_override_ft); + bss->rsnxe_override_ft = wpabuf_parse_bin(pos); } else if (os_strcmp(buf, "gtk_rsc_override") == 0) { wpabuf_free(bss->gtk_rsc_override); bss->gtk_rsc_override = wpabuf_parse_bin(pos); diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 0166c3164..5bf4502b0 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -904,6 +904,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) wpabuf_free(conf->sae_commit_override); wpabuf_free(conf->rsne_override_eapol); wpabuf_free(conf->rsnxe_override_eapol); + wpabuf_free(conf->rsne_override_ft); + wpabuf_free(conf->rsnxe_override_ft); wpabuf_free(conf->gtk_rsc_override); wpabuf_free(conf->igtk_rsc_override); #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 8b57500ce..0cb10c118 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -679,6 +679,8 @@ struct hostapd_bss_config { struct wpabuf *sae_commit_override; struct wpabuf *rsne_override_eapol; struct wpabuf *rsnxe_override_eapol; + struct wpabuf *rsne_override_ft; + struct wpabuf *rsnxe_override_ft; struct wpabuf *gtk_rsc_override; struct wpabuf *igtk_rsc_override; #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 7937b8120..46cc7fae7 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3810,7 +3810,22 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_FST */ +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->rsnxe_override_ft && + buf + buflen - p >= + (long int) wpabuf_len(hapd->conf->rsnxe_override_ft) && + sta && sta->auth_alg == WLAN_AUTH_FT) { + wpa_printf(MSG_DEBUG, "TESTING: RSNXE FT override"); + os_memcpy(p, wpabuf_head(hapd->conf->rsnxe_override_ft), + wpabuf_len(hapd->conf->rsnxe_override_ft)); + p += wpabuf_len(hapd->conf->rsnxe_override_ft); + goto rsnxe_done; + } +#endif /* CONFIG_TESTING_OPTIONS */ p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p); +#ifdef CONFIG_TESTING_OPTIONS +rsnxe_done: +#endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_OWE if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index d1324d501..4edeea151 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -225,10 +225,16 @@ struct wpa_auth_config { size_t rsne_override_eapol_len; u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE]; size_t rsnxe_override_eapol_len; + u8 rsne_override_ft[MAX_OWN_IE_OVERRIDE]; + size_t rsne_override_ft_len; + u8 rsnxe_override_ft[MAX_OWN_IE_OVERRIDE]; + size_t rsnxe_override_ft_len; u8 gtk_rsc_override[WPA_KEY_RSC_LEN]; u8 igtk_rsc_override[WPA_KEY_RSC_LEN]; unsigned int rsne_override_eapol_set:1; unsigned int rsnxe_override_eapol_set:1; + unsigned int rsne_override_ft_set:1; + unsigned int rsnxe_override_ft_set:1; unsigned int gtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1; #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index c0b462558..1795848e1 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2468,7 +2468,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; u8 *fte_mic, *elem_count; size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0; - u8 rsnxe[10]; + u8 rsnxe_buf[10], *rsnxe = rsnxe_buf; size_t rsnxe_len; int res; struct wpa_auth_config *conf; @@ -2490,6 +2490,32 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, end = pos + max_len; +#ifdef CONFIG_TESTING_OPTIONS + if (auth_alg == WLAN_AUTH_FT && + sm->wpa_auth->conf.rsne_override_ft_set) { + wpa_printf(MSG_DEBUG, + "TESTING: RSNE FT override for MIC calculation"); + rsnie = sm->wpa_auth->conf.rsne_override_ft; + rsnie_len = sm->wpa_auth->conf.rsne_override_ft_len; + if (end - pos < (long int) rsnie_len) + return pos; + os_memcpy(pos, rsnie, rsnie_len); + rsnie = pos; + pos += rsnie_len; + if (rsnie_len > PMKID_LEN && sm->pmk_r1_name_valid) { + int idx; + + /* Replace all 0xff PMKID with the valid PMKR1Name */ + for (idx = 0; idx < PMKID_LEN; idx++) { + if (rsnie[rsnie_len - 1 - idx] != 0xff) + break; + } + if (idx == PMKID_LEN) + os_memcpy(&rsnie[rsnie_len - PMKID_LEN], + sm->pmk_r1_name, WPA_PMK_NAME_LEN); + } + } else +#endif /* CONFIG_TESTING_OPTIONS */ if (auth_alg == WLAN_AUTH_FT || ((auth_alg == WLAN_AUTH_FILS_SK || auth_alg == WLAN_AUTH_FILS_SK_PFS || @@ -2655,10 +2681,19 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, if (ric_start == pos) ric_start = NULL; - res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, sizeof(rsnxe)); + res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, sizeof(rsnxe_buf)); if (res < 0) return NULL; rsnxe_len = res; +#ifdef CONFIG_TESTING_OPTIONS + if (auth_alg == WLAN_AUTH_FT && + sm->wpa_auth->conf.rsnxe_override_ft_set) { + wpa_printf(MSG_DEBUG, + "TESTING: RSNXE FT override for MIC calculation"); + rsnxe = sm->wpa_auth->conf.rsnxe_override_ft; + rsnxe_len = sm->wpa_auth->conf.rsnxe_override_ft_len; + } +#endif /* CONFIG_TESTING_OPTIONS */ if (auth_alg == WLAN_AUTH_FT && rsnxe_len) *elem_count += 1; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index ff2302cd2..926ff455f 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -139,6 +139,24 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wpabuf_head(conf->rsnxe_override_eapol), wconf->rsnxe_override_eapol_len); } + if (conf->rsne_override_ft && + wpabuf_len(conf->rsne_override_ft) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsne_override_ft_set = 1; + wconf->rsne_override_ft_len = + wpabuf_len(conf->rsne_override_ft); + os_memcpy(wconf->rsne_override_ft, + wpabuf_head(conf->rsne_override_ft), + wconf->rsne_override_ft_len); + } + if (conf->rsnxe_override_ft && + wpabuf_len(conf->rsnxe_override_ft) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsnxe_override_ft_set = 1; + wconf->rsnxe_override_ft_len = + wpabuf_len(conf->rsnxe_override_ft); + os_memcpy(wconf->rsnxe_override_ft, + wpabuf_head(conf->rsnxe_override_ft), + wconf->rsnxe_override_ft_len); + } if (conf->gtk_rsc_override && wpabuf_len(conf->gtk_rsc_override) > 0 && wpabuf_len(conf->gtk_rsc_override) <= WPA_KEY_RSC_LEN) { From 2b8f8a47212e5d06d19854dbbdcf45b758503bcf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 14 Mar 2020 23:31:13 +0200 Subject: [PATCH 0200/1105] tests: FT protocol RSNE/RSNXE mismatch in Reassociation Response frame Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 66 ++++++++++++++++++++++++++++++++++-- tests/hwsim/wpasupplicant.py | 13 +++++-- 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 3153bff93..1dc75a344 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -993,7 +993,8 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): if filename.startswith('/tmp/'): os.unlink(filename) -def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None): +def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, + rsne_override=None, rsnxe_override=None): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") ssid = "test-ft" @@ -1005,6 +1006,10 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None): params['wpa_ptk_rekey'] = str(wpa_ptk_rekey) if sae_pwe is not None: params['sae_pwe'] = sae_pwe + if rsne_override: + params['rsne_override_ft'] = rsne_override + if rsnxe_override: + params['rsnxe_override_ft'] = rsnxe_override hapd0 = hostapd.add_ap(apdev[0], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['wpa_key_mgmt'] = "FT-SAE" @@ -1012,6 +1017,10 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None): params['wpa_ptk_rekey'] = str(wpa_ptk_rekey) if sae_pwe is not None: params['sae_pwe'] = sae_pwe + if rsne_override: + params['rsne_override_ft'] = rsne_override + if rsnxe_override: + params['rsnxe_override_ft'] = rsnxe_override hapd1 = hostapd.add_ap(apdev[1], params) key_mgmt = hapd1.get_config()['key_mgmt'] if key_mgmt.split(' ')[0] != "FT-SAE": @@ -1088,6 +1097,59 @@ def test_ap_ft_sae_over_ds_ptk_rekey_ap(dev, apdev): over_ds=True, only_one_way=True) check_ptk_rekey(dev[0], hapd0, hapd1) +def test_ap_ft_sae_h2e_rsne_override(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNE override (same value)""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"ff") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_rsnxe_override(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNXE override (same value)""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsnxe_override="F40120") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_rsne_mismatch(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsne_override="30260100000fac040100000fac040100000fac090c010100" + 16*"ff") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + fail_test=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_rsne_mismatch_pmkr1name(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch in PMKR1Name""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"00") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + fail_test=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_rsnxe_mismatch(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNXE mismatch""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsnxe_override="F40160") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + fail_test=True) + finally: + dev[0].set("sae_pwe", "0") + def test_ap_ft_sae_pw_id(dev, apdev): """FT-SAE with Password Identifier""" if "SAE" not in dev[0].get_capability("auth_alg"): @@ -1906,7 +1968,7 @@ def test_ap_ft_oom(dev, apdev): """WPA2-PSK-FT and OOM""" dst = setup_ap_ft_oom(dev, apdev) with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"): - dev[0].roam(dst, check_bssid=False) + dev[0].roam(dst, check_bssid=False, fail_test=True) def test_ap_ft_oom2(dev, apdev): """WPA2-PSK-FT and OOM (2)""" diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index e245c3a93..d99e6889d 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1199,22 +1199,31 @@ class WpaSupplicant: if fail_test: if assoc_reject_ok: ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED", "CTRL-EVENT-ASSOC-REJECT"], timeout=1) else: - ev = self.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) + ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=1) + if ev and "CTRL-EVENT-DISCONNECTED" in ev: + self.dump_monitor() + return if ev is not None and "CTRL-EVENT-ASSOC-REJECT" not in ev: raise Exception("Unexpected connection") self.dump_monitor() return if assoc_reject_ok: - ev = self.wait_event(["CTRL-EVENT-CONNECTED"], timeout=10) + ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=10) else: ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED", "CTRL-EVENT-ASSOC-REJECT"], timeout=10) if ev is None: raise Exception("Roaming with the AP timed out") if "CTRL-EVENT-ASSOC-REJECT" in ev: raise Exception("Roaming association rejected") + if "CTRL-EVENT-DISCONNECTED" in ev: + raise Exception("Unexpected disconnection when waiting for roam to complete") self.dump_monitor() if check_bssid and self.get_status_field('bssid') != bssid: raise Exception("Did not roam to correct BSSID") From f21fbfb9778026bf665914ed8f163a3d534497bb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 11:11:38 +0200 Subject: [PATCH 0201/1105] Allow RSNE in EAPOL-Key msg 2/4 to be overridden for testing purposes The new wpa_supplicant control interface parameter rsne_override_eapol can be used similarly to the earlier rsnxe_override_eapol to override the RSNE value added into EAPOL-Key msg 2/4. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 8 ++++++++ wpa_supplicant/events.c | 7 +++++++ wpa_supplicant/wpa_supplicant.c | 2 ++ wpa_supplicant/wpa_supplicant_i.h | 1 + 4 files changed, 18 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 077bd6449..2321fc358 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -745,6 +745,12 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, break; pos++; } + } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) { + wpabuf_free(wpa_s->rsne_override_eapol); + if (os_strcmp(value, "NULL") == 0) + wpa_s->rsne_override_eapol = NULL; + else + wpa_s->rsne_override_eapol = wpabuf_parse_bin(value); } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) { wpabuf_free(wpa_s->rsnxe_override_assoc); if (os_strcmp(value, "NULL") == 0) @@ -8174,6 +8180,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->sae_commit_override = NULL; os_free(wpa_s->extra_sae_rejected_groups); wpa_s->extra_sae_rejected_groups = NULL; + wpabuf_free(wpa_s->rsne_override_eapol); + wpa_s->rsne_override_eapol = NULL; wpabuf_free(wpa_s->rsnxe_override_assoc); wpa_s->rsnxe_override_assoc = NULL; wpabuf_free(wpa_s->rsnxe_override_eapol); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 15f7ae82e..6ec0da1f7 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3107,6 +3107,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, wpa_s->last_eapol_matches_bssid = 0; #ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->rsne_override_eapol) { + wpa_printf(MSG_DEBUG, + "TESTING: RSNE EAPOL-Key msg 2/4 override"); + wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, + wpabuf_head(wpa_s->rsne_override_eapol), + wpabuf_len(wpa_s->rsne_override_eapol)); + } if (wpa_s->rsnxe_override_eapol) { wpa_printf(MSG_DEBUG, "TESTING: RSNXE EAPOL-Key msg 2/4 override"); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 02895054f..c638fe535 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -536,6 +536,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) wpa_s->last_assoc_req_wpa_ie = NULL; os_free(wpa_s->extra_sae_rejected_groups); wpa_s->extra_sae_rejected_groups = NULL; + wpabuf_free(wpa_s->rsne_override_eapol); + wpa_s->rsne_override_eapol = NULL; wpabuf_free(wpa_s->rsnxe_override_assoc); wpa_s->rsnxe_override_assoc = NULL; wpabuf_free(wpa_s->rsnxe_override_eapol); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index a6ec3f37e..0de0382dc 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1142,6 +1142,7 @@ struct wpa_supplicant { size_t last_tk_len; struct wpabuf *last_assoc_req_wpa_ie; int *extra_sae_rejected_groups; + struct wpabuf *rsne_override_eapol; struct wpabuf *rsnxe_override_assoc; struct wpabuf *rsnxe_override_eapol; struct dl_list drv_signal_override; From 60c435493de3d82f5d9e39cf73548611eba34883 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 11:16:22 +0200 Subject: [PATCH 0202/1105] tests: SAE and RSNE mismatch in EAPOL-Key msg 2/4 Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index fff4f49ae..255d42c48 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -2150,6 +2150,42 @@ def test_sae_auth_restart(dev, apdev): dev[0].set("sae_groups", "") dev[0].set("sae_pwe", "0") +def test_sae_rsne_mismatch(dev, apdev): + """SAE and RSNE mismatch in EAPOL-Key msg 2/4""" + check_sae_capab(dev[0]) + dev[0].set("sae_groups", "") + + params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + hapd = hostapd.add_ap(apdev[0], params) + + # First, test with matching RSNE to confirm testing capability + dev[0].set("rsne_override_eapol", + "30140100000fac040100000fac040100000fac080000") + dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", + scan_freq="2412") + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + # Then, test with modified RSNE + tests = ["30140100000fac040100000fac040100000fac080010", "0000"] + for ie in tests: + dev[0].set("rsne_override_eapol", ie) + dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", + scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["Associated with"], timeout=10) + if ev is None: + raise Exception("No indication of association seen") + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=5) + dev[0].request("REMOVE_NETWORK all") + if ev is None: + raise Exception("No disconnection seen") + if "CTRL-EVENT-DISCONNECTED" not in ev: + raise Exception("Unexpected connection") + dev[0].dump_monitor() + def test_sae_h2e_rsnxe_mismatch(dev, apdev): """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4""" check_sae_capab(dev[0]) From 81fa7730d3ee1eb89c404f16a7e7b571284a2b10 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 17:06:35 +0200 Subject: [PATCH 0203/1105] nl80211: Add more TX status details in debug log in AP mode The actual TX status (whether ACK frame was received) was not included in the debug log in AP mode. Add that for all cases. In addition, add some more details in the debug log to make the log more helpful in debugging issues related to frame delivery. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211_event.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index f4b0580f4..b634a2d12 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -685,20 +685,26 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv, union wpa_event_data event; const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame; u16 fc = le_to_host16(hdr->frame_control); + u64 cookie_val = 0; - wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event"); + if (cookie) + cookie_val = nla_get_u64(cookie); + wpa_printf(MSG_DEBUG, + "nl80211: Frame TX status event A1=" MACSTR + " %sstype=%d cookie=0x%llx%s ack=%d", + MAC2STR(hdr->addr1), + WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT ? "not-mgmt " : "", + WLAN_FC_GET_STYPE(fc), (long long unsigned int) cookie_val, + cookie ? "" : "(N/A)", ack != NULL); if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) return; if (!is_ap_interface(drv->nlmode) && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { - u64 cookie_val; - if (!cookie) return; - cookie_val = nla_get_u64(cookie); wpa_printf(MSG_DEBUG, "nl80211: Frame TX status: cookie=0x%llx%s (ack=%d)", (long long unsigned int) cookie_val, From 2e22f3e82e3a2840f53985b01c0e2bba8434ee54 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 17:07:52 +0200 Subject: [PATCH 0204/1105] tests: Check more details in pmksa_cache_ap_expiration It looks like this test case can fail if the STA goes to power save mode and the Deauthentication frame from the AP after session timeout is not actually sent at all. Check more details to make it clear that this is indeed the reason behind the failure. Signed-off-by: Jouni Malinen --- tests/hwsim/test_pmksa_cache.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_pmksa_cache.py b/tests/hwsim/test_pmksa_cache.py index 11daaaa67..c334b48dd 100644 --- a/tests/hwsim/test_pmksa_cache.py +++ b/tests/hwsim/test_pmksa_cache.py @@ -662,6 +662,7 @@ def test_pmksa_cache_ap_expiration(dev, apdev): params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache") hapd = hostapd.add_ap(apdev[0], params) bssid = apdev[0]['bssid'] + dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP", eap="GPSK", identity="gpsk-user-session-timeout", password="abcdefghijklmnop0123456789abcdef", @@ -669,20 +670,44 @@ def test_pmksa_cache_ap_expiration(dev, apdev): ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) if ev is None: raise Exception("No connection event received from hostapd") + hapd.dump_monitor() + dev[0].request("DISCONNECT") + ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=5) + if ev is None: + raise Exception("No disconnection event received from hostapd") + dev[0].wait_disconnected() + + # Wait for session timeout to remove PMKSA cache entry time.sleep(5) dev[0].dump_monitor() + hapd.dump_monitor() + dev[0].request("RECONNECT") ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", "CTRL-EVENT-CONNECTED"], timeout=20) if ev is None: - raise Exception("Roaming with the AP timed out") + raise Exception("Reconnection with the AP timed out") if "CTRL-EVENT-CONNECTED" in ev: raise Exception("EAP exchange missing") dev[0].wait_connected(timeout=20, error="Reconnect timed out") dev[0].dump_monitor() + ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) + if ev is None: + raise Exception("No connection event received from hostapd [2]") + hapd.dump_monitor() + + # Wait for session timeout + ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=10) + if ev is None: + raise Exception("No disconnection event received from hostapd [2]") dev[0].wait_disconnected(timeout=20) dev[0].wait_connected(timeout=20, error="Reassociation timed out") + ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) + if ev is None: + raise Exception("No connection event received from hostapd [3]") + hapd.dump_monitor() + dev[0].dump_monitor() def test_pmksa_cache_multiple_sta(dev, apdev): """PMKSA cache with multiple stations""" From 037e004c1600ff4d00bf7d1ac1ba4a6f9ea5d649 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 17:09:27 +0200 Subject: [PATCH 0205/1105] nl80211: Remove extraneous space from send_mlme debug print Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 5b312502b..4c686d076 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3758,7 +3758,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, mgmt = (struct ieee80211_mgmt *) data; fc = le_to_host16(mgmt->frame_control); - wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR + wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da=" MACSTR " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u no_encrypt=%d fc=0x%x (%s) nlmode=%d", MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time, no_encrypt, fc, fc2str(fc), drv->nlmode); From fab94f16e6588d8f0b5b09d7b822ad7ad0d87331 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 21:18:16 +0200 Subject: [PATCH 0206/1105] Indicate scan completion in active AP mode even when ignoring results This is needed to avoid leaving external components (through control interface or D-Bus) timing out while waiting for the scan completion events. This was already taken care of for the scan-only case ("TYPE=only"), but the scan-and-allow-roaming case did not report the scan completion event when operating in AP mode. Signed-off-by: Jouni Malinen --- wpa_supplicant/events.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 6ec0da1f7..2fc49932b 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2024,15 +2024,6 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, goto scan_work_done; } - if (ap) { - wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode"); -#ifdef CONFIG_AP - if (wpa_s->ap_iface->scan_cb) - wpa_s->ap_iface->scan_cb(wpa_s->ap_iface); -#endif /* CONFIG_AP */ - goto scan_work_done; - } - wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)", wpa_s->own_scan_running, data ? data->scan_info.external_scan : 0); @@ -2049,6 +2040,15 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpas_notify_scan_done(wpa_s, 1); + if (ap) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode"); +#ifdef CONFIG_AP + if (wpa_s->ap_iface->scan_cb) + wpa_s->ap_iface->scan_cb(wpa_s->ap_iface); +#endif /* CONFIG_AP */ + goto scan_work_done; + } + if (data && data->scan_info.external_scan) { wpa_dbg(wpa_s, MSG_DEBUG, "Do not use results from externally requested scan operation for network selection"); wpa_scan_results_free(scan_res); From 9e30180a30bb388cda65d8deec9dbbb990072447 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 21:21:35 +0200 Subject: [PATCH 0207/1105] nl80211: Allow scanning in wpa_supplicant AP mode If the driver supports this, request cfg80211 to allow the explicitly requested scan to go through in AP mode. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211_scan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index 413d6f757..04f6bb879 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -236,6 +236,11 @@ nl80211_scan_common(struct i802_bss *bss, u8 cmd, params->filter_ssids = NULL; drv->num_filter_ssids = params->num_filter_ssids; + if (!drv->hostapd && is_ap_interface(drv->nlmode)) { + wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_AP"); + scan_flags |= NL80211_SCAN_FLAG_AP; + } + if (params->only_new_results) { wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH"); scan_flags |= NL80211_SCAN_FLAG_FLUSH; From e9d2cd71af9fac5dc97d42eba27acfa682a505b5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 21:22:18 +0200 Subject: [PATCH 0208/1105] tests: Scanning in AP mode Signed-off-by: Jouni Malinen --- tests/hwsim/test_dbus.py | 61 +++++++++++++++++++++++++++++++++++++ tests/hwsim/test_wpas_ap.py | 34 +++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py index 41661b8fb..64bf34b54 100644 --- a/tests/hwsim/test_dbus.py +++ b/tests/hwsim/test_dbus.py @@ -5490,6 +5490,67 @@ def test_dbus_ap(dev, apdev): if not t.success(): raise Exception("Expected signals not seen") +def test_dbus_ap_scan(dev, apdev): + """D-Bus AddNetwork for AP mode and scan""" + (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) + iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) + + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + + hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) + bssid = hapd.own_addr() + + class TestDbusConnect(TestDbus): + def __init__(self, bus): + TestDbus.__init__(self, bus) + self.started = False + self.scan_completed = False + + def __enter__(self): + gobject.timeout_add(1, self.run_connect) + gobject.timeout_add(15000, self.timeout) + self.add_signal(self.propertiesChanged, WPAS_DBUS_IFACE, + "PropertiesChanged") + self.add_signal(self.scanDone, WPAS_DBUS_IFACE, "ScanDone") + self.loop.run() + return self + + def propertiesChanged(self, properties): + logger.debug("propertiesChanged: %s" % str(properties)) + if 'State' in properties and properties['State'] == "completed": + self.started = True + logger.info("Try to scan in AP mode") + iface.Scan({'Type': 'active', + 'Channels': [(dbus.UInt32(2412), dbus.UInt32(20))]}) + logger.info("Scan() returned") + + def scanDone(self, success): + logger.debug("scanDone: success=%s" % success) + if self.started: + self.scan_completed = True + self.loop.quit() + + def run_connect(self, *args): + logger.debug("run_connect") + args = dbus.Dictionary({'ssid': ssid, + 'key_mgmt': 'WPA-PSK', + 'psk': passphrase, + 'mode': 2, + 'frequency': 2412, + 'scan_freq': 2412}, + signature='sv') + self.netw = iface.AddNetwork(args) + iface.SelectNetwork(self.netw) + return False + + def success(self): + return self.started and self.scan_completed + + with TestDbusConnect(bus) as t: + if not t.success(): + raise Exception("Expected signals not seen") + def test_dbus_connect_wpa_eap(dev, apdev): """D-Bus AddNetwork and connection with WPA+WPA2-Enterprise AP""" (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) diff --git a/tests/hwsim/test_wpas_ap.py b/tests/hwsim/test_wpas_ap.py index 29005f48e..8af7d31dc 100644 --- a/tests/hwsim/test_wpas_ap.py +++ b/tests/hwsim/test_wpas_ap.py @@ -4,6 +4,7 @@ # This software may be distributed under the terms of the BSD license. # See README for more details. +import hostapd from remotehost import remote_compatible import time import logging @@ -815,3 +816,36 @@ def run_wpas_ap_sae(dev, sae_password, sae_password_id=False): dev[1].request("SET sae_groups ") dev[1].connect("wpas-ap-sae", key_mgmt="SAE", sae_password="12345678", sae_password_id=pw_id, scan_freq="2412") + +def test_wpas_ap_scan(dev, apdev): + """wpa_supplicant AP mode and scanning""" + dev[0].flush_scan_cache() + + hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) + bssid = hapd.own_addr() + + id = dev[0].add_network() + dev[0].set_network(id, "mode", "2") + dev[0].set_network_quoted(id, "ssid", "wpas-ap-open") + dev[0].set_network(id, "key_mgmt", "NONE") + dev[0].set_network(id, "frequency", "2412") + dev[0].set_network(id, "scan_freq", "2412") + dev[0].select_network(id) + wait_ap_ready(dev[0]) + dev[0].dump_monitor() + + if "OK" not in dev[0].request("SCAN freq=2412"): + raise Exception("SCAN command not accepted") + ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS", + "CTRL-EVENT-SCAN-FAILED"], 15) + if ev is None: + raise Exception("Scan result timed out") + if "CTRL-EVENT-SCAN-FAILED ret=-95" in ev: + # Scanning in AP mode not supported + return + if "CTRL-EVENT-SCAN-FAILED" in ev: + raise Exception("Unexpected scan failure reason: " + ev) + if "CTRL-EVENT-SCAN-RESULTS" in ev: + bss = dev[0].get_bss(bssid) + if not bss: + raise Exception("AP not found in scan") From f5c0104f3bc5ebfa00f2de956f2ecbdf3367756a Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sun, 15 Mar 2020 20:04:19 +0100 Subject: [PATCH 0209/1105] Add KEY_FLAG_MODIFY for Extended Key ID support KEY_FLAG_MODIFY was initial added for the planned Extended Key ID support with commit a919a260352a ("Introduce and add key_flag") and then removed with commit 82eaa3e6882f ("Remove the not yet needed KEY_FLAG_MODIFY") to simplify commit e9e69221c1d1 ("Validity checking function for key_flag API"). Add it again and update check_key_flag() accordingly. Signed-off-by: Alexander Wetzel --- src/common/defs.h | 7 +++++-- src/drivers/driver.h | 7 +++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/common/defs.h b/src/common/defs.h index 077d6399a..f62c3ceee 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -430,6 +430,7 @@ enum chan_width { }; enum key_flag { + KEY_FLAG_MODIFY = BIT(0), KEY_FLAG_DEFAULT = BIT(1), KEY_FLAG_RX = BIT(2), KEY_FLAG_TX = BIT(3), @@ -446,8 +447,10 @@ enum key_flag { KEY_FLAG_DEFAULT, KEY_FLAG_PAIRWISE_RX_TX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX_TX, KEY_FLAG_PAIRWISE_RX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX, + KEY_FLAG_PAIRWISE_RX_TX_MODIFY = KEY_FLAG_PAIRWISE_RX_TX | + KEY_FLAG_MODIFY, /* Max allowed flags for each key type */ - KEY_FLAG_PAIRWISE_MASK = KEY_FLAG_PAIRWISE_RX_TX, + KEY_FLAG_PAIRWISE_MASK = KEY_FLAG_PAIRWISE_RX_TX_MODIFY, KEY_FLAG_GROUP_MASK = KEY_FLAG_GROUP_RX_TX_DEFAULT, KEY_FLAG_PMK_MASK = KEY_FLAG_PMK, }; @@ -455,7 +458,7 @@ enum key_flag { static inline int check_key_flag(enum key_flag key_flag) { return !!(!key_flag || - ((key_flag & KEY_FLAG_PAIRWISE) && + ((key_flag & (KEY_FLAG_PAIRWISE | KEY_FLAG_MODIFY)) && (key_flag & ~KEY_FLAG_PAIRWISE_MASK)) || ((key_flag & KEY_FLAG_GROUP) && (key_flag & ~KEY_FLAG_GROUP_MASK)) || diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 642230ec3..b0373954a 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1608,6 +1608,10 @@ struct wpa_driver_set_key_params { /** * key_flag - Additional key flags * + * %KEY_FLAG_MODIFY + * Set when an already installed key must be updated. + * So far the only use-case is changing RX/TX status for + * pairwise keys. Must not be set when deleting a key. * %KEY_FLAG_DEFAULT * Set when the key is also a default key. Must not be set when * deleting a key. @@ -1636,6 +1640,9 @@ struct wpa_driver_set_key_params { * %KEY_FLAG_PAIRWISE_RX * Pairwise key not yet valid for TX. (Only usable when Extended * Key ID is supported by the driver.) + * %KEY_FLAG_PAIRWISE_RX_TX_MODIFY + * Enable TX for a pairwise key installed with + * KEY_FLAG_PAIRWISE_RX. * * Not a valid standalone key type but pre-defined to be combined * with other key_flags: From 094c9cdc7e17666532ec248998d2bf46b09c5f24 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sun, 15 Mar 2020 20:04:20 +0100 Subject: [PATCH 0210/1105] Add parsing of Key ID KDE for Extended Key ID wpa_parse_generic() can now recognize the Key ID KDE that will be needed to deliver the Key ID of the pairwise key when Extended Key ID is used. Signed-off-by: Alexander Wetzel --- src/common/wpa_common.c | 8 ++++++++ src/common/wpa_common.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index c63d7bce1..e8a4a2beb 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2717,6 +2717,14 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } + if (pos[1] >= RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_KEYID) { + ie->key_id = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: KeyID in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { ie->gtk = pos + 2 + RSN_SELECTOR_LEN; diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 7850c878e..1a9a4105f 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -494,6 +494,7 @@ struct wpa_eapol_ie_parse { const u8 *rsn_ie; size_t rsn_ie_len; const u8 *pmkid; + const u8 *key_id; const u8 *gtk; size_t gtk_len; const u8 *mac_addr; From a1afa2df8a521bce88f1e0b13dc6650be0e69494 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 23:24:18 +0200 Subject: [PATCH 0211/1105] Remove unnecessary and confusing length check from the PMKID KDE case wpa_parse_kde_ies(), i.e., the only caller to wpa_parse_generic(), verifies that there is room for KDE Length field and pos[1] (that length) octets of payload in the Key Data buffer. The PMKID KDE case within wpa_parse_generic() was doing an unnecessary separate check for there being room for the Length, OUI, and Data Type fields. This is covered by the check in the calling function with the combination of verifying that pos[1] is large enough to contain RSN_SELECTOR_LEN + PMKID_LEN octets of payload. This is confusing since no other KDE case was checking remaining full buffer room within wpa_parse_generic(). Clean this up by removing the unnecessary check from the PMKID KDE case so that all KDEs are handled consistently. Signed-off-by: Jouni Malinen --- src/common/wpa_common.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index e8a4a2beb..aaeb13023 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2681,12 +2681,10 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, /** * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header - * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data * Returns: 0 on success, 1 if end mark is found, -1 on failure */ -static int wpa_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) +static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie) { if (pos[1] == 0) return 1; @@ -2708,8 +2706,7 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } - if (1 + RSN_SELECTOR_LEN < end - pos && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && + if (pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", @@ -2895,7 +2892,7 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) ie->supp_oper_classes_len = pos[1]; } } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); + ret = wpa_parse_generic(pos, ie); if (ret < 0) break; if (ret > 0) { From ac222415326a4c749e6ea51aaed974489cf874a6 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sun, 15 Mar 2020 20:04:24 +0100 Subject: [PATCH 0212/1105] nl80211: Extended Key ID support Add key configuration parameters needed to support Extended Key ID with pairwise keys. Add a driver capability flag to indicate support forusing this. Signed-off-by: Alexander Wetzel --- src/drivers/driver.h | 2 ++ src/drivers/driver_common.c | 1 + src/drivers/driver_nl80211.c | 18 ++++++++++++++++-- src/drivers/driver_nl80211_capa.c | 4 ++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index b0373954a..78a3387da 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1841,6 +1841,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS 0x2000000000000000ULL /** Driver supports Beacon protection */ #define WPA_DRIVER_FLAGS_BEACON_PROTECTION 0x4000000000000000ULL +/** Driver supports Extended Key ID */ +#define WPA_DRIVER_FLAGS_EXTENDED_KEY_ID 0x8000000000000000ULL u64 flags; #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index f4d06e438..2e03b6676 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -315,6 +315,7 @@ const char * driver_flag_to_string(u64 flag) DF2S(UPDATE_FT_IES); DF2S(SAFE_PTK0_REKEYS); DF2S(BEACON_PROTECTION); + DF2S(EXTENDED_KEY_ID); } return "UNKNOWN"; #undef DF2S diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 4c686d076..ba8d079b2 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3105,7 +3105,12 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, if (!key_msg) return ret; - if (alg == WPA_ALG_NONE && (key_flag & KEY_FLAG_RX_TX)) { + if ((key_flag & KEY_FLAG_PAIRWISE_MASK) == + KEY_FLAG_PAIRWISE_RX_TX_MODIFY) { + msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY); + if (!msg) + goto fail2; + } else if (alg == WPA_ALG_NONE && (key_flag & KEY_FLAG_RX_TX)) { wpa_printf(MSG_DEBUG, "%s: invalid key_flag to delete key", __func__); ret = -EINVAL; @@ -3143,7 +3148,16 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) goto fail; - if ((key_flag & KEY_FLAG_GROUP_MASK) == KEY_FLAG_GROUP_RX) { + if ((key_flag & KEY_FLAG_PAIRWISE_MASK) == + KEY_FLAG_PAIRWISE_RX || + (key_flag & KEY_FLAG_PAIRWISE_MASK) == + KEY_FLAG_PAIRWISE_RX_TX_MODIFY) { + if (nla_put_u8(key_msg, NL80211_KEY_MODE, + key_flag == KEY_FLAG_PAIRWISE_RX ? + NL80211_KEY_NO_TX : NL80211_KEY_SET_TX)) + goto fail; + } else if ((key_flag & KEY_FLAG_GROUP_MASK) == + KEY_FLAG_GROUP_RX) { wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK"); if (nla_put_u32(key_msg, NL80211_KEY_TYPE, NL80211_KEYTYPE_GROUP)) diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 5a51b429d..b4fed9ea8 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -453,6 +453,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_BEACON_PROTECTION)) capa->flags |= WPA_DRIVER_FLAGS_BEACON_PROTECTION; + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_EXT_KEY_ID)) + capa->flags |= WPA_DRIVER_FLAGS_EXTENDED_KEY_ID; } From 796253a65f5875bb60d4f3a51dc938a193a3c36f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 15 Mar 2020 23:42:21 +0200 Subject: [PATCH 0213/1105] nl80211: Debug print set_key() command names This makes it easier to understand the debug log for various set_key() operations. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index ba8d079b2..efcd69ad2 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3107,6 +3107,8 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, if ((key_flag & KEY_FLAG_PAIRWISE_MASK) == KEY_FLAG_PAIRWISE_RX_TX_MODIFY) { + wpa_printf(MSG_DEBUG, + "nl80211: SET_KEY (pairwise RX/TX modify)"); msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY); if (!msg) goto fail2; @@ -3116,6 +3118,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, ret = -EINVAL; goto fail2; } else if (alg == WPA_ALG_NONE) { + wpa_printf(MSG_DEBUG, "nl80211: DEL_KEY"); msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY); if (!msg) goto fail2; @@ -3127,6 +3130,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, ret = -EINVAL; goto fail2; } + wpa_printf(MSG_DEBUG, "nl80211: NEW_KEY"); msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY); if (!msg) goto fail2; From 6ea7a152c6de012c517eb6e1b0e197f33bac7722 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Sun, 15 Mar 2020 20:04:25 +0100 Subject: [PATCH 0214/1105] wlantest: Basic Extended Key ID support Signed-off-by: Alexander Wetzel --- wlantest/bss.c | 6 ++++-- wlantest/rx_data.c | 10 +++++++--- wlantest/rx_eapol.c | 3 +++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/wlantest/bss.c b/wlantest/bss.c index 0556c72e2..3208e65e4 100644 --- a/wlantest/bss.c +++ b/wlantest/bss.c @@ -290,7 +290,7 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, "group=%s%s%s%s%s%s%s%s%s" "mgmt_group_cipher=%s%s%s%s%s" "key_mgmt=%s%s%s%s%s%s%s%s%s" - "rsn_capab=%s%s%s%s%s%s", + "rsn_capab=%s%s%s%s%s%s%s", MAC2STR(bss->bssid), bss->proto == 0 ? "OPEN " : "", bss->proto & WPA_PROTO_WPA ? "WPA " : "", @@ -341,7 +341,9 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, bss->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "", bss->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ? "PEERKEY " : "", - bss->rsn_capab & WPA_CAPABILITY_OCVC ? "OCVC " : ""); + bss->rsn_capab & WPA_CAPABILITY_OCVC ? "OCVC " : "", + bss->rsn_capab & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST ? + "ExtKeyID " : ""); } diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index d86a5886c..1ee25a645 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -466,9 +466,13 @@ static void rx_data_bss_prot(struct wlantest *wt, } keyid = data[3] >> 6; - if (keyid != 0) { - add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in " - "individually addressed Data frame from " MACSTR, + if (keyid != 0 && + (!(sta->rsn_capab & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST) || + !(bss->rsn_capab & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST) || + keyid != 1)) { + add_note(wt, MSG_INFO, + "Unexpected KeyID %d in individually addressed Data frame from " + MACSTR, keyid, MAC2STR(hdr->addr2)); } diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 2e49929c1..1cfdf8e9e 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -464,6 +464,9 @@ static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss, ie.rsn_ie, ie.rsn_ie_len); } + if (ie.key_id) + add_note(wt, MSG_DEBUG, "KeyID %u", ie.key_id[0]); + if (ie.gtk) { wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - GTK KDE", ie.gtk, ie.gtk_len); From 5732e57423a52e76c73372dd5c7c95dc7f625419 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Mar 2020 15:38:27 +0200 Subject: [PATCH 0215/1105] tests: Use hostapd_logdir in sigma_dut_ap_psk_sha256 logdir was prepared for this test case, but it was not actually used. Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 3edcf2159..0fe8b4a48 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -644,7 +644,7 @@ def test_sigma_dut_ap_psk_sha256(dev, apdev, params): logdir = os.path.join(params['logdir'], "sigma_dut_ap_psk_sha256.sigma-hostapd") with HWSimRadio() as (radio, iface): - sigma = start_sigma_dut(iface) + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) try: sigma_dut_cmd_check("ap_reset_default") sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-psk,MODE,11ng") From c557720ef01e2ffc6328898252cd02d819aaf66a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Mar 2020 16:22:32 +0200 Subject: [PATCH 0216/1105] tests: sigma_dut AP configuration for different channels Signed-off-by: Jouni Malinen --- tests/hwsim/run-tests.py | 2 ++ tests/hwsim/test_sigma_dut.py | 64 +++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/tests/hwsim/run-tests.py b/tests/hwsim/run-tests.py index b201cd78d..a0bcdf31d 100755 --- a/tests/hwsim/run-tests.py +++ b/tests/hwsim/run-tests.py @@ -516,6 +516,8 @@ def main(): params = {} params['logdir'] = args.logdir params['long'] = args.long + params['name'] = name + params['prefix'] = os.path.join(args.logdir, name) t(dev, apdev, params) elif t.__code__.co_argcount > 1: t(dev, apdev) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 0fe8b4a48..98679373b 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3956,3 +3956,67 @@ def test_sigma_dut_ap_sae_h2e_anti_clogging(dev, apdev, params): finally: stop_sigma_dut(sigma) dev[0].set("sae_pwe", "0") + +def test_sigma_dut_ap_5ghz(dev, apdev, params): + """sigma_dut controlled AP on 5 GHz""" + run_sigma_dut_ap_channel(dev, apdev, params, 36, '11na', 5180, + check_signal="WIDTH=20 MHz") + +def test_sigma_dut_ap_ht40plus(dev, apdev, params): + """sigma_dut controlled AP and HT40+""" + run_sigma_dut_ap_channel(dev, apdev, params, 36, '11na', 5180, + extra="width,40", check_signal="WIDTH=40 MHz") + +def test_sigma_dut_ap_ht40minus(dev, apdev, params): + """sigma_dut controlled AP and HT40-""" + run_sigma_dut_ap_channel(dev, apdev, params, 40, '11na', 5200, + extra="width,40", check_signal="WIDTH=40 MHz") + +def test_sigma_dut_ap_vht40(dev, apdev, params): + """sigma_dut controlled AP and VHT40""" + run_sigma_dut_ap_channel(dev, apdev, params, 36, '11ac', 5180, + extra="width,40", check_signal="WIDTH=40 MHz", + program="VHT") + +def test_sigma_dut_ap_vht80(dev, apdev, params): + """sigma_dut controlled AP and VHT80""" + run_sigma_dut_ap_channel(dev, apdev, params, 36, '11ac', 5180, + extra="width,80", check_signal="WIDTH=80 MHz", + program="VHT") + +def run_sigma_dut_ap_channel(dev, apdev, params, channel, mode, scan_freq, + extra=None, check_signal=None, program=None): + logdir = params['prefix'] + ".sigma-hostapd" + with HWSimRadio() as (radio, iface): + subprocess.call(['iw', 'reg', 'set', 'US']) + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + cmd = "ap_reset_default" + if program: + cmd += ",program," + program + sigma_dut_cmd_check(cmd) + cmd = "ap_set_wireless,NAME,AP,CHANNEL,%d,SSID,test-psk,MODE,%s" % (channel, mode) + if extra: + cmd += "," + extra + sigma_dut_cmd_check(cmd) + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-PSK,PSK,12345678") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(params['prefix'] + ".sigma-conf", "wb") as f2: + f2.write(f.read()) + + dev[0].connect("test-psk", psk="12345678", scan_freq=str(scan_freq)) + sig = dev[0].request("SIGNAL_POLL") + logger.info("SIGNAL_POLL:\n" + sig.strip()) + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + + sigma_dut_cmd_check("ap_reset_default") + + if check_signal and check_signal not in sig: + raise Exception("Unexpected SIGNAL_POLL data") + finally: + stop_sigma_dut(sigma) + subprocess.call(['iw', 'reg', 'set', '00']) + dev[0].flush_scan_cache() From 51d1924bd8cfa3e58cc7c6e3ba6088949987ce8b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2020 21:23:48 +0200 Subject: [PATCH 0217/1105] FT: Set the new RSNXE Used subfield in FT reassociation This is a workaround needed to keep FT protocol backwards compatible for the cases where either the AP or the STA uses RSNXE, but the other one does not. This commit adds setting of the new field to 1 in Reassociation Request/Response frame during FT protocol when the STA/AP uses RSNXE in other frames. This mechanism is described in 20/332r3. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 6 +++--- src/ap/wpa_auth_ft.c | 14 +++++++++----- src/ap/wpa_auth_i.h | 2 +- src/rsn_supp/wpa_ft.c | 5 +++++ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index ab20705f0..64fc09ca6 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3422,7 +3422,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) conf->r0_key_holder_len, NULL, NULL, pos, kde + kde_len - pos, - NULL, 0); + NULL, 0, 0); } if (res < 0) { wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " @@ -5087,7 +5087,7 @@ int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder, conf->r0_key_holder_len, - NULL, NULL, buf, len, NULL, 0); + NULL, NULL, buf, len, NULL, 0, 0); } #endif /* CONFIG_IEEE80211R_AP */ @@ -5289,7 +5289,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, conf->r0_key_holder_len, NULL, NULL, pos, kde + kde_len - pos, - NULL, 0); + NULL, 0, 0); } if (res < 0) { wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 1795848e1..c8751fddb 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -808,7 +808,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *anonce, const u8 *snonce, u8 *buf, size_t len, const u8 *subelem, - size_t subelem_len) + size_t subelem_len, int rsnxe_used) { u8 *pos = buf, *ielen; size_t hdrlen = use_sha384 ? sizeof(struct rsn_ftie_sha384) : @@ -826,7 +826,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, os_memset(hdr, 0, sizeof(*hdr)); pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, 0); + WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used); if (anonce) os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); if (snonce) @@ -836,7 +836,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, os_memset(hdr, 0, sizeof(*hdr)); pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, 0); + WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used); if (anonce) os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); if (snonce) @@ -2470,6 +2470,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0; u8 rsnxe_buf[10], *rsnxe = rsnxe_buf; size_t rsnxe_len; + int rsnxe_used; int res; struct wpa_auth_config *conf; struct wpa_ft_ies parse; @@ -2643,9 +2644,11 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, anonce = NULL; snonce = NULL; } + rsnxe_used = (auth_alg == WLAN_AUTH_FT) && + (conf->sae_pwe == 1 || conf->sae_pwe == 2); res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len, anonce, snonce, pos, end - pos, - subelem, subelem_len); + subelem, subelem_len, rsnxe_used); os_free(subelem); if (res < 0) return NULL; @@ -3166,7 +3169,8 @@ pmk_r1_derived: pos += ret; ret = wpa_write_ftie(conf, use_sha384, parse.r0kh_id, parse.r0kh_id_len, - sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0); + sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0, + 0); if (ret < 0) goto fail; pos += ret; diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index c2b22eba1..5d7b96c6f 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -294,7 +294,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *anonce, const u8 *snonce, u8 *buf, size_t len, const u8 *subelem, - size_t subelem_len); + size_t subelem_len, int rsnxe_used); int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index baa185ffe..bb3a8b5bb 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -181,6 +181,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, int mdie_len; u8 rsnxe[10]; size_t rsnxe_len; + int rsnxe_used; int res; sm->ft_completed = 0; @@ -309,10 +310,13 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, ftie_pos = pos; *pos++ = WLAN_EID_FAST_BSS_TRANSITION; ftie_len = pos++; + rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && anonce && + (sm->sae_pwe == 1 || sm->sae_pwe == 2); if (wpa_key_mgmt_sha384(sm->key_mgmt)) { struct rsn_ftie_sha384 *ftie; ftie = (struct rsn_ftie_sha384 *) pos; + ftie->mic_control[0] = !!rsnxe_used; fte_mic = ftie->mic; elem_count = &ftie->mic_control[1]; pos += sizeof(*ftie); @@ -323,6 +327,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, struct rsn_ftie *ftie; ftie = (struct rsn_ftie *) pos; + ftie->mic_control[0] = !!rsnxe_used; fte_mic = ftie->mic; elem_count = &ftie->mic_control[1]; pos += sizeof(*ftie); From 497ae9f004278e235d07cff205affce4dd67daf1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2020 21:33:02 +0200 Subject: [PATCH 0218/1105] FT: Verify that RSNXE is used consistently in Reassociation Request Verify that the STA includes RSNXE if it indicated in FTE that RSNXE is used and the AP is also using RSNXE. This is needed to protect against downgrade attacks based on the design proposed in 20/332r3. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth_ft.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index c8751fddb..7ac109e70 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -3242,10 +3242,13 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, int use_sha384; const u8 *anonce, *snonce, *fte_mic; u8 fte_elem_count; + int rsnxe_used; + struct wpa_auth_config *conf; if (sm == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; + conf = &sm->wpa_auth->conf; use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); @@ -3274,8 +3277,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, mdie = (struct rsn_mdie *) parse.mdie; if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, - sm->wpa_auth->conf.mobility_domain, + os_memcmp(mdie->mobility_domain, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); return WLAN_STATUS_INVALID_MDIE; @@ -3292,6 +3294,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, anonce = ftie->anonce; snonce = ftie->snonce; + rsnxe_used = ftie->mic_control[0] & 0x01; fte_elem_count = ftie->mic_control[1]; fte_mic = ftie->mic; } else { @@ -3305,6 +3308,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, anonce = ftie->anonce; snonce = ftie->snonce; + rsnxe_used = ftie->mic_control[0] & 0x01; fte_elem_count = ftie->mic_control[1]; fte_mic = ftie->mic; } @@ -3350,14 +3354,14 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_INVALID_FTIE; } - if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder, + if (os_memcmp_const(parse.r1kh_id, conf->r1_key_holder, FT_R1KH_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " "ReassocReq"); wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE", parse.r1kh_id, FT_R1KH_ID_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID", - sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); + conf->r1_key_holder, FT_R1KH_ID_LEN); return WLAN_STATUS_INVALID_FTIE; } @@ -3419,6 +3423,13 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_INVALID_FTIE; } + if (rsnxe_used && (conf->sae_pwe == 1 || conf->sae_pwe == 2) && + !parse.rsnxe) { + wpa_printf(MSG_INFO, + "FT: FTE indicated that STA uses RSNXE, but RSNXE was not included"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + #ifdef CONFIG_OCV if (wpa_auth_uses_ocv(sm)) { struct wpa_channel_info ci; From 35936cd2cf91c35d4886f45ef86eeb058bb025d1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2020 21:38:22 +0200 Subject: [PATCH 0219/1105] FT: Verify that RSNXE is used consistently in Reassociation Response Verify that the AP included RSNXE in Beacon/Probe Response frames if it indicated in FTE that RSNXE is used. This is needed to protect against downgrade attacks based on the design proposed in 20/332r3. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa_ft.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index bb3a8b5bb..ab73e311c 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -947,6 +947,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); const u8 *anonce, *snonce, *fte_mic; u8 fte_elem_count; + int own_rsnxe_used, rsnxe_used; wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); @@ -985,6 +986,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, anonce = ftie->anonce; snonce = ftie->snonce; + rsnxe_used = ftie->mic_control[0] & 0x01; fte_elem_count = ftie->mic_control[1]; fte_mic = ftie->mic; } else { @@ -998,6 +1000,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, anonce = ftie->anonce; snonce = ftie->snonce; + rsnxe_used = ftie->mic_control[0] & 0x01; fte_elem_count = ftie->mic_control[1]; fte_mic = ftie->mic; } @@ -1095,6 +1098,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return -1; } + if (rsnxe_used && !sm->ap_rsnxe) { + wpa_printf(MSG_INFO, + "FT: FTE indicated that AP uses RSNXE, but RSNXE was not included in Beacon/Probe Response frames"); + return -1; + } + if (!sm->ap_rsn_ie) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No RSNE for this AP known - trying to get from scan results"); @@ -1122,7 +1131,9 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return -1; } - if ((sm->ap_rsnxe && !parse.rsnxe) || + own_rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && + (sm->sae_pwe == 1 || sm->sae_pwe == 2); + if ((sm->ap_rsnxe && !parse.rsnxe && own_rsnxe_used) || (!sm->ap_rsnxe && parse.rsnxe) || (sm->ap_rsnxe && parse.rsnxe && (sm->ap_rsnxe_len != 2 + parse.rsnxe_len || From 6140cca8191e401aba18fe6250ecfc32ccca806f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2020 21:45:22 +0200 Subject: [PATCH 0220/1105] FT: Omit RSNXE from FT protocol Reassociation Request when needed The previous design for adding RSNXE into FT was not backwards compatible. Move to a new design based on 20/332r3 to avoid that issue by not include RSNXE in the FT protocol Reassociation Request frame so that an AP not supporting RSNXE can still validate the FTE MIC correctly. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa_ft.c | 24 +++++++++++++++--------- wpa_supplicant/sme.c | 5 ++++- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index ab73e311c..6d92de5a6 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -162,6 +162,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL * @ric_ies_len: Length of ric_ies buffer in octets * @ap_mdie: Mobility Domain IE from the target AP + * @omit_rsnxe: Whether RSNXE is omitted from Reassociation Request frame * Returns: Pointer to buffer with IEs or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(); @@ -171,7 +172,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, const u8 *kck, size_t kck_len, const u8 *target_ap, const u8 *ric_ies, size_t ric_ies_len, - const u8 *ap_mdie) + const u8 *ap_mdie, int omit_rsnxe) { size_t buf_len; u8 *buf, *pos, *ftie_len, *ftie_pos, *fte_mic, *elem_count; @@ -375,12 +376,16 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, pos += ric_ies_len; } - res = wpa_gen_rsnxe(sm, rsnxe, sizeof(rsnxe)); - if (res < 0) { - os_free(buf); - return NULL; + if (omit_rsnxe) { + rsnxe_len = 0; + } else { + res = wpa_gen_rsnxe(sm, rsnxe, sizeof(rsnxe)); + if (res < 0) { + os_free(buf); + return NULL; + } + rsnxe_len = res; } - rsnxe_len = res; if (kck) { /* @@ -463,7 +468,7 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie) } ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, 0, sm->bssid, NULL, 0, mdie); + NULL, 0, sm->bssid, NULL, 0, mdie, 0); if (ft_ies) { wpa_sm_update_ft_ies(sm, sm->mobility_domain, ft_ies, ft_ies_len); @@ -659,7 +664,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, sm->pmk_r1_name, kck, kck_len, bssid, ric_ies, ric_ies_len, - parse.mdie ? parse.mdie - 2 : NULL); + parse.mdie ? parse.mdie - 2 : NULL, + !sm->ap_rsnxe); if (ft_ies) { wpa_sm_update_ft_ies(sm, sm->mobility_domain, ft_ies, ft_ies_len); @@ -1220,7 +1226,7 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, } ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, 0, target_ap, NULL, 0, mdie); + NULL, 0, target_ap, NULL, 0, mdie, 0); if (ft_ies) { sm->over_the_ds_in_progress = 1; os_memcpy(sm->target_ap, target_ap, ETH_ALEN); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index d4c12d1e3..f7792ec96 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -299,6 +299,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #ifdef CONFIG_MBO const u8 *mbo_ie; #endif /* CONFIG_MBO */ + int omit_rsnxe = 0; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " @@ -506,6 +507,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x", md[0], md[1]); + omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX); if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; @@ -614,7 +616,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #endif /* CONFIG_TESTING_OPTIONS */ if (wpa_s->rsnxe_len > 0 && wpa_s->rsnxe_len <= - sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) { + sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len && + !omit_rsnxe) { os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len); wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len; From b7366a942a586c07a6dbf83558eeb0141e599922 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 20 Mar 2020 21:56:44 +0200 Subject: [PATCH 0221/1105] FT: Omit RSNXE from FT protocol Reassociation Response when needed The previous design for adding RSNXE into FT was not backwards compatible. Move to a new design based on 20/332r3 to avoid that issue by not include RSNXE in the FT protocol Reassociation Response frame so that a STA not supporting RSNXE can still validate the FTE MIC correctly. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 3 ++- src/ap/ieee802_11.c | 15 ++++++++++----- src/ap/wpa_auth.h | 3 ++- src/ap/wpa_auth_ft.c | 16 +++++++++++----- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index bde2d9302..2091385cd 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -483,7 +483,8 @@ skip_wpa_check: #ifdef CONFIG_IEEE80211R_AP p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), - sta->auth_alg, req_ies, req_ies_len); + sta->auth_alg, req_ies, req_ies_len, + !elems.rsnxe); if (!p) { wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 46cc7fae7..c0f9290f8 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3661,7 +3661,8 @@ static int add_associated_sta(struct hostapd_data *hapd, static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, const u8 *addr, u16 status_code, int reassoc, - const u8 *ies, size_t ies_len, int rssi) + const u8 *ies, size_t ies_len, int rssi, + int omit_rsnxe) { int send_len; u8 *buf; @@ -3731,7 +3732,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, * Transition Information, RSN, [RIC Response] */ p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, buf + buflen - p, - sta->auth_alg, ies, ies_len); + sta->auth_alg, ies, ies_len, + omit_rsnxe); if (!p) { wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs"); @@ -3822,7 +3824,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, goto rsnxe_done; } #endif /* CONFIG_TESTING_OPTIONS */ - p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p); + if (!omit_rsnxe) + p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p); #ifdef CONFIG_TESTING_OPTIONS rsnxe_done: #endif /* CONFIG_TESTING_OPTIONS */ @@ -4043,7 +4046,7 @@ void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta) reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS, sta->fils_pending_assoc_is_reassoc, sta->fils_pending_assoc_req, - sta->fils_pending_assoc_req_len, 0); + sta->fils_pending_assoc_req_len, 0, 0); os_free(sta->fils_pending_assoc_req); sta->fils_pending_assoc_req = NULL; sta->fils_pending_assoc_req_len = 0; @@ -4091,6 +4094,7 @@ static void handle_assoc(struct hostapd_data *hapd, #ifdef CONFIG_FILS int delay_assoc = 0; #endif /* CONFIG_FILS */ + int omit_rsnxe = 0; if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : sizeof(mgmt->u.assoc_req))) { @@ -4303,6 +4307,7 @@ static void handle_assoc(struct hostapd_data *hapd, resp = check_assoc_ies(hapd, sta, pos, left, reassoc); if (resp != WLAN_STATUS_SUCCESS) goto fail; + omit_rsnxe = !get_ie(pos, left, WLAN_EID_RSNX); if (hostapd_get_aid(hapd, sta) < 0) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, @@ -4456,7 +4461,7 @@ static void handle_assoc(struct hostapd_data *hapd, #endif /* CONFIG_FILS */ reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos, - left, rssi); + left, rssi, omit_rsnxe); os_free(tmp); /* diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 4edeea151..58aa9ff21 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -425,7 +425,8 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_IEEE80211R_AP u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, size_t max_len, int auth_alg, - const u8 *req_ies, size_t req_ies_len); + const u8 *req_ies, size_t req_ies_len, + int omit_rsnxe); void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, u16 auth_transaction, const u8 *ies, size_t ies_len, void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 7ac109e70..5ed78e6a6 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2463,7 +2463,8 @@ static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end, u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, size_t max_len, int auth_alg, - const u8 *req_ies, size_t req_ies_len) + const u8 *req_ies, size_t req_ies_len, + int omit_rsnxe) { u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; u8 *fte_mic, *elem_count; @@ -2684,10 +2685,15 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, if (ric_start == pos) ric_start = NULL; - res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, sizeof(rsnxe_buf)); - if (res < 0) - return NULL; - rsnxe_len = res; + if (omit_rsnxe) { + rsnxe_len = 0; + } else { + res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, + sizeof(rsnxe_buf)); + if (res < 0) + return NULL; + rsnxe_len = res; + } #ifdef CONFIG_TESTING_OPTIONS if (auth_alg == WLAN_AUTH_FT && sm->wpa_auth->conf.rsnxe_override_ft_set) { From a55ecfeabeb89d16dd05e2d74764df1274d45622 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 21 Mar 2020 00:23:01 +0200 Subject: [PATCH 0222/1105] Allow RSNXE to be removed from Beacon frames for testing purposes The new hostapd configuration parameter no_beacon_rsnxe=1 can be used to remove RSNXE from Beacon frames. This can be used to test protection mechanisms for downgrade attacks. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 ++ src/ap/ap_config.h | 1 + src/ap/beacon.c | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 1a5b742b2..3c7bb395f 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4194,6 +4194,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "igtk_rsc_override") == 0) { wpabuf_free(bss->igtk_rsc_override); bss->igtk_rsc_override = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) { + bss->no_beacon_rsnxe = atoi(pos); #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_SAE } else if (os_strcmp(buf, "sae_password") == 0) { diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 0cb10c118..80be7ed39 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -683,6 +683,7 @@ struct hostapd_bss_config { struct wpabuf *rsnxe_override_ft; struct wpabuf *gtk_rsc_override; struct wpabuf *igtk_rsc_override; + int no_beacon_rsnxe; #endif /* CONFIG_TESTING_OPTIONS */ #define MESH_ENABLED BIT(0) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 53e35492d..ff760a0d1 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -323,6 +323,12 @@ static u8 * hostapd_get_rsnxe(struct hostapd_data *hapd, u8 *pos, size_t len) { const u8 *ie; +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->no_beacon_rsnxe) { + wpa_printf(MSG_INFO, "TESTING: Do not add RSNXE into Beacon"); + return pos; + } +#endif /* CONFIG_TESTING_OPTIONS */ ie = hostapd_wpa_ie(hapd, WLAN_EID_RSNX); if (!ie || 2U + ie[1] > len) return pos; From 2af3d99cd30f6415a9fa41872a155c6d9fd7ce10 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 21 Mar 2020 00:06:26 +0200 Subject: [PATCH 0223/1105] tests: Additional FT-SAE with RSNXE testing Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 1dc75a344..624451e90 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -994,7 +994,8 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): os.unlink(filename) def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, - rsne_override=None, rsnxe_override=None): + rsne_override=None, rsnxe_override=None, + no_beacon_rsnxe2=False): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") ssid = "test-ft" @@ -1021,6 +1022,8 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['rsne_override_ft'] = rsne_override if rsnxe_override: params['rsnxe_override_ft'] = rsnxe_override + if no_beacon_rsnxe2: + params['no_beacon_rsnxe'] = "1" hapd1 = hostapd.add_ap(apdev[1], params) key_mgmt = hapd1.get_config()['key_mgmt'] if key_mgmt.split(' ')[0] != "FT-SAE": @@ -1049,6 +1052,32 @@ def test_ap_ft_sae_h2e_and_loop(dev, apdev): hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2") run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) +def test_ap_ft_sae_h2e_and_loop2(dev, apdev): + """WPA2-PSK-FT-SAE AP (AP loop, STA H2E)""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_downgrade_attack(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E downgrade attack)""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + no_beacon_rsnxe2=True) + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + force_initial_conn_to_first_ap=True, + return_after_initial=True) + dev[0].scan_for_bss(hapd1.own_addr(), freq="2412") + dev[0].request("ROAM " + hapd1.own_addr()) + ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10) + if ev is None: + raise Exception("Association not rejected") + finally: + dev[0].set("sae_pwe", "0") + def test_ap_ft_sae_ptk_rekey0(dev, apdev): """WPA2-PSK-FT-SAE AP and PTK rekey triggered by station""" hapd0, hapd1 = start_ft_sae(dev[0], apdev) From cc79eb725f7b564269619ce4a64be2a80927d392 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 21 Mar 2020 12:57:37 +0200 Subject: [PATCH 0224/1105] Check against integer overflow in int_array functions int_array_concat() and int_array_add_unique() could potentially end up overflowing the int type variable used to calculate their length. While this is mostly theoretical for platforms that use 32-bit int, there might be cases where a 16-bit int overflow could be hit. This could result in accessing memory outside buffer bounds and potentially a double free when realloc() ends up freeing the buffer. All current uses of int_array_add_unique() and most uses of int_array_concat() are currently limited by the buffer limits for the local configuration parameter or frame length and as such, cannot hit this overflow cases. The only case where a long enough int_array could be generated is the combination of scan_freq values for a scan. The memory and CPU resource needs for generating an int_array with 2^31 entries would not be realistic to hit in practice, but a device using LP32 data model with 16-bit int could hit this case. It is better to have more robust checks even if this could not be reached in practice, so handle cases where more than INT_MAX entries would be added to an int_array as memory allocation failures instead of allowing the overflow case to proceed. Signed-off-by: Jouni Malinen --- src/utils/common.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/utils/common.c b/src/utils/common.c index 27bf435d9..e5b3dcbd4 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -7,6 +7,7 @@ */ #include "includes.h" +#include #include "common/ieee802_11_defs.h" #include "common.h" @@ -885,18 +886,28 @@ int int_array_len(const int *a) void int_array_concat(int **res, const int *a) { - int reslen, alen, i; + int reslen, alen, i, new_len; int *n; reslen = int_array_len(*res); alen = int_array_len(a); - - n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); - if (n == NULL) { + new_len = reslen + alen + 1; + if (reslen < 0 || alen < 0 || new_len < 0) { + /* This should not really happen, but if it did, something + * overflowed. Do not try to merge the arrays; instead, make + * this behave like memory allocation failure to avoid messing + * up memory. */ os_free(*res); *res = NULL; return; } + n = os_realloc_array(*res, new_len, sizeof(int)); + if (n == NULL) { + if (new_len) + os_free(*res); + *res = NULL; + return; + } for (i = 0; i <= alen; i++) n[reslen + i] = a[i]; *res = n; @@ -952,6 +963,15 @@ void int_array_add_unique(int **res, int a) return; /* already in the list */ } + if (reslen > INT_MAX - 2) { + /* This should not really happen in practice, but if it did, + * something would overflow. Do not try to add the new value; + * instead, make this behave like memory allocation failure to + * avoid messing up memory. */ + os_free(*res); + *res = NULL; + return; + } n = os_realloc_array(*res, reslen + 2, sizeof(int)); if (n == NULL) { os_free(*res); From 5a296129fc1c7bcbb94e962e12c239a8f9180b37 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Sat, 21 Mar 2020 06:09:30 +0530 Subject: [PATCH 0225/1105] Set beacon protection config irrespective of macro CONFIG_FILS This was not supposed to be conditional on CONFIG_FILS. Fixes: ecbf59e6931f ("wpa_supplicant configuration for Beacon protection") Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 5bb47bcbe..ba0e5c343 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3042,8 +3042,8 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) } else { sm->fils_cache_id_set = 0; } - sm->beacon_prot = config->beacon_prot; #endif /* CONFIG_FILS */ + sm->beacon_prot = config->beacon_prot; } else { sm->network_ctx = NULL; sm->allowed_pairwise_cipher = 0; From 51e8f5d63c1eb51d46a466f750daf178b93e55f3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 21 Mar 2020 15:57:37 +0200 Subject: [PATCH 0226/1105] Ignore duplicated SSID element when parsing Some APs have managed to add two SSID elements into Beacon frames and that used to result in picking the last one which had incorrect data in the known examples of this misbehavior. Pick the first one to get the correct SSID. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_common.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 5da92eaef..6aa38cab2 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -365,6 +365,11 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elen); break; } + if (elems->ssid) { + wpa_printf(MSG_MSGDUMP, + "Ignored duplicated SSID element"); + break; + } elems->ssid = pos; elems->ssid_len = elen; break; From 22547c31480fa24f6685b26e43ce73043e7fbaec Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Thu, 19 Mar 2020 19:21:34 +0530 Subject: [PATCH 0227/1105] More details to the vendor specific driver internal failure reporting Add more hang reason codes for the hang reason in the QCA_NL80211_VENDOR_SUBCMD_HANG events. This also introduces the attribute QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA to carry the required data for the respective hang reason. This data is expected to contain the required dump to analyze the reason for the hang. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 8a56ab7bf..f1a065132 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -5723,6 +5723,39 @@ enum qca_wlan_vendor_hang_reason { QCA_WLAN_HANG_DXE_FAILURE = 12, /* WMI pending commands exceed the maximum count */ QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS = 13, + /* Timeout for peer STA connection accept command's response from the + * FW in AP mode. This command is triggered when a STA (peer) connects + * to AP (DUT). + */ + QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT = 14, + /* Timeout for the AP connection accept command's response from the FW + * in STA mode. This command is triggered when the STA (DUT) connects + * to an AP (peer). + */ + QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT = 15, + /* Timeout waiting for the response to the MAC HW mode change command + * sent to FW as a part of MAC mode switch among DBS (Dual Band + * Simultaneous), SCC (Single Channel Concurrency), and MCC (Multi + * Channel Concurrency) mode. + */ + QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT = 16, + /* Timeout waiting for the response from FW to configure the MAC HW's + * mode. This operation is to configure the single/two MACs in either + * SCC/MCC/DBS mode. + */ + QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT = 17, + /* Timeout waiting for response of VDEV start command from the FW */ + QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT = 18, + /* Timeout waiting for response of VDEV restart command from the FW */ + QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT = 19, + /* Timeout waiting for response of VDEV stop command from the FW */ + QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT = 20, + /* Timeout waiting for response of VDEV delete command from the FW */ + QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT = 21, + /* Timeout waiting for response of peer all delete request command to + * the FW on a specific VDEV. + */ + QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT = 22, }; /** @@ -5735,6 +5768,12 @@ enum qca_wlan_vendor_attr_hang { * qca_wlan_vendor_hang_reason. */ QCA_WLAN_VENDOR_ATTR_HANG_REASON = 1, + /* The binary blob data associated with the hang reason specified by + * QCA_WLAN_VENDOR_ATTR_HANG_REASON. This binary data is expected to + * contain the required dump to analyze the reason for the hang. + * NLA_BINARY attribute, the max size is 1024 bytes. + */ + QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA = 2, QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_HANG_MAX = From 7546c489a95a033c78331915fcdfa0e6fd74d563 Mon Sep 17 00:00:00 2001 From: Ouden Date: Wed, 18 Mar 2020 17:58:37 +0800 Subject: [PATCH 0228/1105] nl80211: Fix RTM NEW/DELLINK IFLA_IFNAME copy for maximum ifname length If the kernel rtm_newlink or rtm_dellink send the maximum length of ifname (IFNAMSIZ), the event handlers in wpa_driver_nl80211_event_rtm_addlink() and wpa_driver_nl80211_event_rtm_dellink() did not copy the IFLA_IFNAME value. Because the RTA_PAYLOAD (IFLA_IFNAME) length already includes the NULL termination, that equals the IFNAMSIZ. Fix the condition when IFNAME reach maximum size. Signed-off-by: Ouden --- src/drivers/driver_nl80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index efcd69ad2..c071cc0e0 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -1047,7 +1047,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, while (RTA_OK(attr, attrlen)) { switch (attr->rta_type) { case IFLA_IFNAME: - if (RTA_PAYLOAD(attr) >= IFNAMSIZ) + if (RTA_PAYLOAD(attr) > IFNAMSIZ) break; os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr)); ifname[RTA_PAYLOAD(attr)] = '\0'; @@ -1222,7 +1222,7 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx, while (RTA_OK(attr, attrlen)) { switch (attr->rta_type) { case IFLA_IFNAME: - if (RTA_PAYLOAD(attr) >= IFNAMSIZ) + if (RTA_PAYLOAD(attr) > IFNAMSIZ) break; os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr)); ifname[RTA_PAYLOAD(attr)] = '\0'; From eb26a6997d45787ef979bf0d7a87ef4243698d2b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 21 Mar 2020 18:12:02 +0200 Subject: [PATCH 0229/1105] Allow SA Query to be disabled for testing purposes The new wpa_supplicant control interface SET parameter disable_sa_query can now be used to disable SA Query on receiving unprotected disconnection event. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 3 +++ wpa_supplicant/sme.c | 4 ++++ wpa_supplicant/wpa_supplicant_i.h | 1 + 3 files changed, 8 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 2321fc358..3b4c50020 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -721,6 +721,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, wpa_s->ignore_assoc_disallow = !!atoi(value); wpa_drv_ignore_assoc_disallow(wpa_s, wpa_s->ignore_assoc_disallow); + } else if (os_strcasecmp(cmd, "disable_sa_query") == 0) { + wpa_s->disable_sa_query = !!atoi(value); } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) { wpa_s->ignore_sae_h2e_only = !!atoi(value); } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) { @@ -8170,6 +8172,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->p2p_go_csa_on_inv = 0; wpa_s->ignore_auth_resp = 0; wpa_s->ignore_assoc_disallow = 0; + wpa_s->disable_sa_query = 0; wpa_s->testing_resend_assoc = 0; wpa_s->ignore_sae_h2e_only = 0; wpa_s->reject_btm_req_reason = 0; diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index f7792ec96..71b67e4a7 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -2658,6 +2658,10 @@ void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, return; if (wpa_s->sme.sa_query_count > 0) return; +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->disable_sa_query) + return; +#endif /* CONFIG_TESTING_OPTIONS */ os_get_reltime(&now); if (wpa_s->sme.last_unprot_disconnect.sec && diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 0de0382dc..e77ebb8f9 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1132,6 +1132,7 @@ struct wpa_supplicant { unsigned int p2p_go_csa_on_inv:1; unsigned int ignore_auth_resp:1; unsigned int ignore_assoc_disallow:1; + unsigned int disable_sa_query:1; unsigned int testing_resend_assoc:1; unsigned int ignore_sae_h2e_only:1; struct wpabuf *sae_commit_override; From a60a0a43c73aa42d8988aba1b5c23e1f2663d054 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 21 Mar 2020 18:13:28 +0200 Subject: [PATCH 0230/1105] tests: Fix bgscan_simple_beacon_loss with REPORTS_TX_ACK_STATUS Stopping the AP from beaconing will also stop it from acknowledging frames and that resulted in bgscan_simple_beacon_loss failing when mac80211_hwsim is registering REPORTS_TX_ACK_STATUS. Work around this by moving to using PMF so that the station ignores the unprotected deauthentiation frames from the AP and also disabling SA Query. This allows the AP to be stopped and restarted with large enough Beacon interval to allow the station to detect beacon loss. Signed-off-by: Jouni Malinen --- tests/hwsim/test_bgscan.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_bgscan.py b/tests/hwsim/test_bgscan.py index f418f56da..0387406fe 100644 --- a/tests/hwsim/test_bgscan.py +++ b/tests/hwsim/test_bgscan.py @@ -71,13 +71,21 @@ def test_bgscan_simple(dev, apdev): def test_bgscan_simple_beacon_loss(dev, apdev): """bgscan_simple and beacon loss""" - hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"}) + params = hostapd.wpa2_params(ssid="bgscan", passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412", - bgscan="simple:1:-20:2") + dev[0].set("disable_sa_query", "1") + dev[0].connect("bgscan", ieee80211w="2", key_mgmt="WPA-PSK-SHA256", + psk="12345678", scan_freq="2412", bgscan="simple:1:-20:2") hapd.set("ext_mgmt_frame_handling", "1") if "OK" not in hapd.request("STOP_AP"): raise Exception("Failed to stop AP") + hapd.disable() + hapd.set("ssid", "foo") + hapd.set("beacon_int", "10000") + hapd.enable() ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=10) if ev is None: raise Exception("Beacon loss not reported") From 3a25897ef77aef313160c4c09f00d8198fb85f68 Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Mon, 16 Mar 2020 14:11:05 -0700 Subject: [PATCH 0231/1105] Adjust max bitrate SNR floors These values were defined in commit a1b790eb9d75 ("Select AP based on estimated maximum throughput") with no justification. Other sources [0,1,2] give a different (consistent) set of SNR floors per MCS index. Adjust the values accordingly. [0] http://www.revolutionwifi.net/revolutionwifi/2014/09/wi-fi-snr-to-mcs-data-rate-mapping.html [1] https://higher-frequency.blogspot.com/2016/10/80211n-80211ac-data-rates-and-snr.html [2] https://www.wlanpros.com/resources/mcs-index-802-11ac-vht-chart/ Signed-off-by: Matthew Wang --- wpa_supplicant/scan.c | 78 ++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index db1f6e1fa..98b0408d8 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -2185,67 +2185,77 @@ void scan_snr(struct wpa_scan_res *res) } -static unsigned int max_ht20_rate(int snr) +static unsigned int max_ht20_rate(int snr, int vht) { - if (snr < 6) + if (snr < 2) + return 0; + if (snr < 5) return 6500; /* HT20 MCS0 */ - if (snr < 8) + if (snr < 9) return 13000; /* HT20 MCS1 */ - if (snr < 13) + if (snr < 11) return 19500; /* HT20 MCS2 */ - if (snr < 17) + if (snr < 15) return 26000; /* HT20 MCS3 */ - if (snr < 20) + if (snr < 18) return 39000; /* HT20 MCS4 */ - if (snr < 23) + if (snr < 20) return 52000; /* HT20 MCS5 */ - if (snr < 24) + if (snr < 25) return 58500; /* HT20 MCS6 */ - return 65000; /* HT20 MCS7 */ + if (snr < 29 || !vht) + return 65000; /* HT20 MCS7 */ + return 78000; /* VHT20 MCS8 */ } -static unsigned int max_ht40_rate(int snr) +static unsigned int max_ht40_rate(int snr, int vht) { - if (snr < 3) + if (snr < 5) + return 0; + if (snr < 8) return 13500; /* HT40 MCS0 */ - if (snr < 6) + if (snr < 12) return 27000; /* HT40 MCS1 */ - if (snr < 10) + if (snr < 14) return 40500; /* HT40 MCS2 */ - if (snr < 15) + if (snr < 18) return 54000; /* HT40 MCS3 */ - if (snr < 17) + if (snr < 21) return 81000; /* HT40 MCS4 */ - if (snr < 22) + if (snr < 23) return 108000; /* HT40 MCS5 */ - if (snr < 24) + if (snr < 28) return 121500; /* HT40 MCS6 */ - return 135000; /* HT40 MCS7 */ + if (snr < 32 || !vht) + return 135000; /* HT40 MCS7 */ + if (snr < 34) + return 162000; /* VHT40 MCS8 */ + return 180000; /* VHT40 MCS9 */ } static unsigned int max_vht80_rate(int snr) { - if (snr < 1) + if (snr < 8) return 0; - if (snr < 2) - return 29300; /* VHT80 MCS0 */ - if (snr < 5) - return 58500; /* VHT80 MCS1 */ - if (snr < 9) - return 87800; /* VHT80 MCS2 */ if (snr < 11) - return 117000; /* VHT80 MCS3 */ + return 29300; /* VHT80 MCS0 */ if (snr < 15) + return 58500; /* VHT80 MCS1 */ + if (snr < 17) + return 87800; /* VHT80 MCS2 */ + if (snr < 21) + return 117000; /* VHT80 MCS3 */ + if (snr < 24) return 175500; /* VHT80 MCS4 */ - if (snr < 16) + if (snr < 26) return 234000; /* VHT80 MCS5 */ - if (snr < 18) + if (snr < 31) return 263300; /* VHT80 MCS6 */ - if (snr < 20) + if (snr < 35) return 292500; /* VHT80 MCS7 */ - if (snr < 22) + if (snr < 37) return 351000; /* VHT80 MCS8 */ return 390000; /* VHT80 MCS9 */ } @@ -2285,7 +2295,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) { ie = get_ie(ies, ies_len, WLAN_EID_HT_CAP); if (ie) { - tmp = max_ht20_rate(snr); + tmp = max_ht20_rate(snr, 0); if (tmp > est) est = tmp; } @@ -2295,7 +2305,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION); if (ie && ie[1] >= 2 && (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { - tmp = max_ht40_rate(snr); + tmp = max_ht40_rate(snr, 0); if (tmp > est) est = tmp; } @@ -2305,7 +2315,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, /* Use +1 to assume VHT is always faster than HT */ ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP); if (ie) { - tmp = max_ht20_rate(snr) + 1; + tmp = max_ht20_rate(snr, 1) + 1; if (tmp > est) est = tmp; @@ -2313,7 +2323,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (ie && ie[1] >= 2 && (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { - tmp = max_ht40_rate(snr) + 1; + tmp = max_ht40_rate(snr, 1) + 1; if (tmp > est) est = tmp; } From 22f0318dbdbddca3dd8a82d0065bc8c93deb23d1 Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Mon, 16 Mar 2020 14:11:06 -0700 Subject: [PATCH 0232/1105] Interpolate rate calculation functions Make max_*_rate() functions and rate calculation at the beginning of wpas_get_est_tpt() more continuous. In wpa_supplicant_need_to_roam(), we compare these values to make a roaming decision. However, at certain SNRs, we see unrealistically large jumps in estimated throughput according to these functions, leading us to make incorrect roaming decisions. Perform linear interpolation where applicable to more accurately reflect actual throughput. Example: wlan0: Current BSS: 88:3d:24:b4:95:d2 freq=2412 level=-69 snr=20 est_throughput=54000 wlan0: Selected BSS: 88:3d:24:b4:89:9e freq=2417 level=-67 snr=22 est_throughput=63500 wlan0: Using signal poll values for the current BSS: level=-69 snr=20 est_throughput=54000 wlan0: Allow reassociation - selected BSS has better estimated throughput 2 dB increase in RSSI likely isn't responsible for a 17% increase in throughput. Signed-off-by: Matthew Wang --- wpa_supplicant/scan.c | 128 +++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 58 deletions(-) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 98b0408d8..eef3517dc 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -2185,81 +2185,75 @@ void scan_snr(struct wpa_scan_res *res) } +static unsigned int interpolate_rate(int snr, int snr0, int snr1, + int rate0, int rate1) +{ + return rate0 + (snr - snr0) * (rate1 - rate0) / (snr1 - snr0); +} + + +#define INTERPOLATE_RATE(snr0, snr1, rate0, rate1) \ + if (snr < (snr1)) \ + return interpolate_rate(snr, (snr0), (snr1), (rate0), (rate1)) + static unsigned int max_ht20_rate(int snr, int vht) { - if (snr < 2) + if (snr < 0) return 0; - if (snr < 5) - return 6500; /* HT20 MCS0 */ - if (snr < 9) - return 13000; /* HT20 MCS1 */ - if (snr < 11) - return 19500; /* HT20 MCS2 */ - if (snr < 15) - return 26000; /* HT20 MCS3 */ - if (snr < 18) - return 39000; /* HT20 MCS4 */ - if (snr < 20) - return 52000; /* HT20 MCS5 */ - if (snr < 25) - return 58500; /* HT20 MCS6 */ - if (snr < 29 || !vht) - return 65000; /* HT20 MCS7 */ - return 78000; /* VHT20 MCS8 */ + INTERPOLATE_RATE(0, 2, 0, 6500); /* HT20 MCS0 */ + INTERPOLATE_RATE(2, 5, 6500, 13000); /* HT20 MCS1 */ + INTERPOLATE_RATE(5, 9, 13000, 19500); /* HT20 MCS2 */ + INTERPOLATE_RATE(9, 11, 19500, 26000); /* HT20 MCS3 */ + INTERPOLATE_RATE(11, 15, 26000, 39000); /* HT20 MCS4 */ + INTERPOLATE_RATE(15, 18, 39000, 52000); /* HT20 MCS5 */ + INTERPOLATE_RATE(18, 20, 52000, 58500); /* HT20 MCS6 */ + INTERPOLATE_RATE(20, 25, 58500, 65000); /* HT20 MCS7 */ + if (!vht) + return 65000; + INTERPOLATE_RATE(25, 29, 65000, 78000); /* VHT20 MCS8 */ + return 78000; } static unsigned int max_ht40_rate(int snr, int vht) { - if (snr < 5) + if (snr < 0) return 0; - if (snr < 8) - return 13500; /* HT40 MCS0 */ - if (snr < 12) - return 27000; /* HT40 MCS1 */ - if (snr < 14) - return 40500; /* HT40 MCS2 */ - if (snr < 18) - return 54000; /* HT40 MCS3 */ - if (snr < 21) - return 81000; /* HT40 MCS4 */ - if (snr < 23) - return 108000; /* HT40 MCS5 */ - if (snr < 28) - return 121500; /* HT40 MCS6 */ - if (snr < 32 || !vht) - return 135000; /* HT40 MCS7 */ - if (snr < 34) - return 162000; /* VHT40 MCS8 */ - return 180000; /* VHT40 MCS9 */ + INTERPOLATE_RATE(0, 5, 0, 13500); /* HT40 MCS0 */ + INTERPOLATE_RATE(5, 8, 13500, 27000); /* HT40 MCS1 */ + INTERPOLATE_RATE(8, 12, 27000, 40500); /* HT40 MCS2 */ + INTERPOLATE_RATE(12, 14, 40500, 54000); /* HT40 MCS3 */ + INTERPOLATE_RATE(14, 18, 54000, 81000); /* HT40 MCS4 */ + INTERPOLATE_RATE(18, 21, 81000, 108000); /* HT40 MCS5 */ + INTERPOLATE_RATE(21, 23, 108000, 121500); /* HT40 MCS6 */ + INTERPOLATE_RATE(23, 28, 121500, 135000); /* HT40 MCS7 */ + if (!vht) + return 135000; + INTERPOLATE_RATE(28, 32, 135000, 162000); /* VHT40 MCS8 */ + INTERPOLATE_RATE(32, 34, 162000, 180000); /* VHT40 MCS9 */ + return 180000; } static unsigned int max_vht80_rate(int snr) { - if (snr < 8) + if (snr < 0) return 0; - if (snr < 11) - return 29300; /* VHT80 MCS0 */ - if (snr < 15) - return 58500; /* VHT80 MCS1 */ - if (snr < 17) - return 87800; /* VHT80 MCS2 */ - if (snr < 21) - return 117000; /* VHT80 MCS3 */ - if (snr < 24) - return 175500; /* VHT80 MCS4 */ - if (snr < 26) - return 234000; /* VHT80 MCS5 */ - if (snr < 31) - return 263300; /* VHT80 MCS6 */ - if (snr < 35) - return 292500; /* VHT80 MCS7 */ - if (snr < 37) - return 351000; /* VHT80 MCS8 */ - return 390000; /* VHT80 MCS9 */ + INTERPOLATE_RATE(0, 8, 0, 29300); /* VHT80 MCS0 */ + INTERPOLATE_RATE(8, 11, 29300, 58500); /* VHT80 MCS1 */ + INTERPOLATE_RATE(11, 15, 58500, 87800); /* VHT80 MCS2 */ + INTERPOLATE_RATE(15, 17, 87800, 117000); /* VHT80 MCS3 */ + INTERPOLATE_RATE(17, 21, 117000, 175500); /* VHT80 MCS4 */ + INTERPOLATE_RATE(21, 24, 175500, 234000); /* VHT80 MCS5 */ + INTERPOLATE_RATE(24, 26, 234000, 263300); /* VHT80 MCS6 */ + INTERPOLATE_RATE(26, 31, 263300, 292500); /* VHT80 MCS7 */ + INTERPOLATE_RATE(31, 35, 292500, 351000); /* VHT80 MCS8 */ + INTERPOLATE_RATE(35, 37, 351000, 390000); /* VHT80 MCS9 */ + return 390000; } +#undef INTERPOLATE_RATE + unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, const u8 *ies, size_t ies_len, int rate, @@ -2280,14 +2274,32 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, rate = 9 * 2; else if (rate > 12 * 2 && snr < 7) rate = 12 * 2; + else if (rate > 12 * 2 && snr < 8) + rate = 14 * 2; + else if (rate > 12 * 2 && snr < 9) + rate = 16 * 2; else if (rate > 18 * 2 && snr < 10) rate = 18 * 2; else if (rate > 24 * 2 && snr < 11) rate = 24 * 2; + else if (rate > 24 * 2 && snr < 12) + rate = 27 * 2; + else if (rate > 24 * 2 && snr < 13) + rate = 30 * 2; + else if (rate > 24 * 2 && snr < 14) + rate = 33 * 2; else if (rate > 36 * 2 && snr < 15) rate = 36 * 2; + else if (rate > 36 * 2 && snr < 16) + rate = 39 * 2; + else if (rate > 36 * 2 && snr < 17) + rate = 42 * 2; + else if (rate > 36 * 2 && snr < 18) + rate = 45 * 2; else if (rate > 48 * 2 && snr < 19) rate = 48 * 2; + else if (rate > 48 * 2 && snr < 20) + rate = 51 * 2; else if (rate > 54 * 2 && snr < 21) rate = 54 * 2; est = rate * 500; From 275509ee673c96e3546901013f02a7ab0c22691e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 21 Mar 2020 19:33:38 +0200 Subject: [PATCH 0233/1105] tests: Update prefer_vht40 throughput estimation Match the updated max_ht40_rate() estimation with VHT. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_vht.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 76257c79b..523c9c04b 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -1041,7 +1041,7 @@ def test_prefer_vht40(dev, apdev): raise Exception("Unexpected BSS0 est_throughput: " + est) est = dev[0].get_bss(bssid2)['est_throughput'] - if est != "135001": + if est != "180001": raise Exception("Unexpected BSS1 est_throughput: " + est) finally: dev[0].request("DISCONNECT") From 7fb365893a0ee2d7c4ddc9654dc905086fffb698 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 21 Mar 2020 23:56:19 +0200 Subject: [PATCH 0234/1105] tests: Wait longer for connection in radius_macacl_unreachable It looks ike the authentication timeouts may continue a bit longer after some kernel changes and that could result in temporarily disabling the network profile. Give this test case more time to complete the connection to avoid reporting failures unnecessarily. Signed-off-by: Jouni Malinen --- tests/hwsim/test_radius.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_radius.py b/tests/hwsim/test_radius.py index 6729f372d..403fbd739 100644 --- a/tests/hwsim/test_radius.py +++ b/tests/hwsim/test_radius.py @@ -963,7 +963,7 @@ def test_radius_macacl_unreachable(dev, apdev): hapd.set("auth_server_port", "1812") hapd.disable() hapd.enable() - dev[0].wait_connected() + dev[0].wait_connected(timeout=20) dev[0].request("DISCONNECT") dev[0].wait_disconnected() From 4391ddd6395f63226ec3b14bcf325356653a614f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 17:30:23 +0200 Subject: [PATCH 0235/1105] Use size_t instead of unsigned_int for last_scan_res This avoids a theoretical unsigned integer overflow case with 32-bit integers, but something that could potentially be hit with 16-bit int (though, even that part looks pretty theoretical in this particular case of number of BSSs in scan results). Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 2 +- wpa_supplicant/wpa_supplicant_i.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 943a34081..127f43e5e 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -906,7 +906,7 @@ void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info, } } - wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u", + wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%zu/%zu", wpa_s->last_scan_res_used, wpa_s->last_scan_res_size); } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index e77ebb8f9..775bce89e 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -607,8 +607,8 @@ struct wpa_supplicant { * results. */ struct wpa_bss **last_scan_res; - unsigned int last_scan_res_used; - unsigned int last_scan_res_size; + size_t last_scan_res_used; + size_t last_scan_res_size; struct os_reltime last_scan; const struct wpa_driver_ops *driver; From d2d16e3100ed15fffa3c475568689b3f1449e976 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 17:46:45 +0200 Subject: [PATCH 0236/1105] Use size_t instead of int or unsigned int for configuration items While int and unsigned int are not going overflow in practice as 32-bit values, these could at least in theory hit an integer overflow with 16-bit int. Use size_t to avoid such potential issue cases. Signed-off-by: Jouni Malinen --- wpa_supplicant/config.c | 6 +++--- wpa_supplicant/config.h | 4 ++-- wpa_supplicant/events.c | 4 ++-- wpa_supplicant/scan.c | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 2b9c3f53e..4f359ede0 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2612,7 +2612,7 @@ static const struct parse_data ssid_fields[] = { int wpa_config_add_prio_network(struct wpa_config *config, struct wpa_ssid *ssid) { - int prio; + size_t prio; struct wpa_ssid *prev, **nlist; /* @@ -4318,7 +4318,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, */ void wpa_config_debug_dump_networks(struct wpa_config *config) { - int prio; + size_t prio; struct wpa_ssid *ssid; for (prio = 0; prio < config->num_prio; prio++) { @@ -4649,7 +4649,7 @@ static int wpa_config_process_p2p_pref_chan( struct wpa_config *config, int line, const char *pos) { struct p2p_channel *pref = NULL, *n; - unsigned int num = 0; + size_t num = 0; const char *pos2; u8 op_class, chan; diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index b3c779233..486432e43 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -332,7 +332,7 @@ struct wpa_cred { */ unsigned int max_bss_load; - unsigned int num_req_conn_capab; + size_t num_req_conn_capab; u8 *req_conn_capab_proto; int **req_conn_capab_port; @@ -403,7 +403,7 @@ struct wpa_config { * This indicates how many per-priority network lists are included in * pssid. */ - int num_prio; + size_t num_prio; /** * cred - Head of the credential list diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 2fc49932b..3758373d4 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1536,7 +1536,7 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, struct wpa_ssid **selected_ssid) { struct wpa_bss *selected = NULL; - int prio; + size_t prio; struct wpa_ssid *next_ssid = NULL; struct wpa_ssid *ssid; @@ -1691,7 +1691,7 @@ int wpa_supplicant_connect(struct wpa_supplicant *wpa_s, static struct wpa_ssid * wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s) { - int prio; + size_t prio; struct wpa_ssid *ssid; for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index eef3517dc..ad9d77af8 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -2628,8 +2628,8 @@ void wpa_scan_free_params(struct wpa_driver_scan_params *params) int wpas_start_pno(struct wpa_supplicant *wpa_s) { - int ret, prio; - size_t i, num_ssid, num_match_ssid; + int ret; + size_t prio, i, num_ssid, num_match_ssid; struct wpa_ssid *ssid; struct wpa_driver_scan_params params; struct sched_scan_plan scan_plan; From a2c23195ade1fd6fad66b0fbad433133c492a2c9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 17:24:21 +0200 Subject: [PATCH 0237/1105] D-Bus: Use size_t for values theoretically larger than 16-bit int These are theoretical cases with 32-bit integers, but cases that could potentially hit an integer overflow with 16-bit int. Signed-off-by: Jouni Malinen --- wpa_supplicant/dbus/dbus_new_handlers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index c842c50e9..01fc67b6f 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1146,7 +1146,7 @@ static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var, DBusMessage **reply) { u8 *ies = NULL, *nies; - int ies_len = 0; + size_t ies_len = 0; DBusMessageIter array_iter, sub_array_iter; char *val; int len; @@ -1177,7 +1177,7 @@ static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var, dbus_message_iter_recurse(&array_iter, &sub_array_iter); dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len); - if (len == 0) { + if (len <= 0) { dbus_message_iter_next(&array_iter); continue; } @@ -1208,7 +1208,7 @@ static int wpas_dbus_get_scan_channels(DBusMessage *message, { DBusMessageIter array_iter, sub_array_iter; int *freqs = NULL, *nfreqs; - int freqs_num = 0; + size_t freqs_num = 0; if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) { wpa_printf(MSG_DEBUG, From 02b43c557c6638327b257c16f3b01aab468e5472 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:00:28 +0200 Subject: [PATCH 0238/1105] RADIUS: Use size_t instead of int for message attributes While RADIUS messages are limited to 4 kB, use size_t to avoid even a theoretical overflow issue with 16-bit int. Signed-off-by: Jouni Malinen --- src/radius/radius.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/radius/radius.c b/src/radius/radius.c index 07240ea22..be16e27b9 100644 --- a/src/radius/radius.c +++ b/src/radius/radius.c @@ -609,7 +609,7 @@ static int radius_msg_add_attr_to_array(struct radius_msg *msg, { if (msg->attr_used >= msg->attr_size) { size_t *nattr_pos; - int nlen = msg->attr_size * 2; + size_t nlen = msg->attr_size * 2; nattr_pos = os_realloc_array(msg->attr_pos, nlen, sizeof(*msg->attr_pos)); From ae7193611f69042436a9f4aaec56c0ff8f7a827a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:07:06 +0200 Subject: [PATCH 0239/1105] Limit maximum number of pending SA Queries There is no point in starting a huge number of pending SA Queries, so limit the number of pending queries to 1000 to have an explicit limit for how large sa_query_count can grow. Signed-off-by: Jouni Malinen --- src/ap/sta_info.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 26885ea49..d3aa15da3 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -1140,6 +1140,8 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) if (sta->sa_query_count > 0 && ap_check_sa_query_timeout(hapd, sta)) return; + if (sta->sa_query_count >= 1000) + return; nbuf = os_realloc_array(sta->sa_query_trans_id, sta->sa_query_count + 1, From 913220cbb881ea405b158ae2116fd769bc4f8f3e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:15:43 +0200 Subject: [PATCH 0240/1105] eloop: Use size_t for signal_count This is more consistent with the other eloop registrations and avoids a theoretical integer overflow with 16-bit int (not that there would ever be more that 32767 signal handlers getting registered). Signed-off-by: Jouni Malinen --- src/utils/eloop.c | 6 +++--- src/utils/eloop_win.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/utils/eloop.c b/src/utils/eloop.c index bb375be10..bcffeeb11 100644 --- a/src/utils/eloop.c +++ b/src/utils/eloop.c @@ -104,7 +104,7 @@ struct eloop_data { struct dl_list timeout; - int signal_count; + size_t signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; @@ -968,7 +968,7 @@ static void eloop_handle_alarm(int sig) static void eloop_handle_signal(int sig) { - int i; + size_t i; #ifndef CONFIG_NATIVE_WINDOWS if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { @@ -992,7 +992,7 @@ static void eloop_handle_signal(int sig) static void eloop_process_pending_signals(void) { - int i; + size_t i; if (eloop.signaled == 0) return; diff --git a/src/utils/eloop_win.c b/src/utils/eloop_win.c index 9c8b12be8..74eaa33ec 100644 --- a/src/utils/eloop_win.c +++ b/src/utils/eloop_win.c @@ -54,7 +54,7 @@ struct eloop_data { struct dl_list timeout; - int signal_count; + size_t signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; @@ -422,7 +422,7 @@ int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, #if 0 static void eloop_handle_signal(int sig) { - int i; + size_t i; eloop.signaled++; for (i = 0; i < eloop.signal_count; i++) { @@ -437,7 +437,7 @@ static void eloop_handle_signal(int sig) static void eloop_process_pending_signals(void) { - int i; + size_t i; if (eloop.signaled == 0) return; @@ -517,7 +517,7 @@ int eloop_register_signal_terminate(eloop_signal_handler handler, eloop.term_signal.handler = handler; eloop.term_signal.user_data = user_data; - + return 0; } From 3f45b8daeb4fbf97eed1ab56f452df7b7d113742 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:22:27 +0200 Subject: [PATCH 0241/1105] hs20-osu-client: Use size_t for certificate components This avoids a theoretical integer overflow with 16-bit unsigned int should a certificate be encoded with more that 65535 friendly names or icons. Signed-off-by: Jouni Malinen --- hs20/client/osu_client.c | 10 +++++----- src/utils/http-utils.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c index 1bf1a0e1a..11bf0db35 100644 --- a/hs20/client/osu_client.c +++ b/hs20/client/osu_client.c @@ -2907,7 +2907,7 @@ static char * get_hostname(const char *url) static int osu_cert_cb(void *_ctx, struct http_cert *cert) { struct hs20_osu_client *ctx = _ctx; - unsigned int i, j; + size_t i, j; int found; char *host = NULL; @@ -3002,7 +3002,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert) size_t name_len = os_strlen(name); wpa_printf(MSG_INFO, - "[%i] Looking for icon file name '%s' match", + "[%zu] Looking for icon file name '%s' match", j, name); for (i = 0; i < cert->num_logo; i++) { struct http_logo *logo = &cert->logo[i]; @@ -3010,7 +3010,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert) char *pos; wpa_printf(MSG_INFO, - "[%i] Comparing to '%s' uri_len=%d name_len=%d", + "[%zu] Comparing to '%s' uri_len=%d name_len=%d", i, logo->uri, (int) uri_len, (int) name_len); if (uri_len < 1 + name_len) { wpa_printf(MSG_INFO, "URI Length is too short"); @@ -3044,7 +3044,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert) if (logo->hash_len != 32) { wpa_printf(MSG_INFO, - "[%i][%i] Icon hash length invalid (should be 32): %d", + "[%zu][%zu] Icon hash length invalid (should be 32): %d", j, i, (int) logo->hash_len); continue; } @@ -3054,7 +3054,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert) } wpa_printf(MSG_DEBUG, - "[%u][%u] Icon hash did not match", j, i); + "[%zu][%zu] Icon hash did not match", j, i); wpa_hexdump_ascii(MSG_DEBUG, "logo->hash", logo->hash, 32); wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]", diff --git a/src/utils/http-utils.h b/src/utils/http-utils.h index 8d4399a37..d9fc925a2 100644 --- a/src/utils/http-utils.h +++ b/src/utils/http-utils.h @@ -28,11 +28,11 @@ struct http_logo { struct http_cert { char **dnsname; - unsigned int num_dnsname; + size_t num_dnsname; struct http_othername *othername; - unsigned int num_othername; + size_t num_othername; struct http_logo *logo; - unsigned int num_logo; + size_t num_logo; }; int soap_init_client(struct http_ctx *ctx, const char *address, From 7858f493f3d0844c2f6bce733ce7e47ccdb535cb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:26:10 +0200 Subject: [PATCH 0242/1105] eloop: Use size_t for socket table->count This is more consistent with the other eloop registrations and avoids a theoretical integer overflow with 16-bit int should more than 32767 sockets be registered (which is not really going to happen in practice). Signed-off-by: Jouni Malinen --- src/utils/eloop.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/utils/eloop.c b/src/utils/eloop.c index bcffeeb11..b4e7f9e71 100644 --- a/src/utils/eloop.c +++ b/src/utils/eloop.c @@ -68,7 +68,7 @@ struct eloop_signal { }; struct eloop_sock_table { - int count; + size_t count; struct eloop_sock *table; eloop_event_type type; int changed; @@ -125,7 +125,8 @@ static void eloop_sigsegv_handler(int sig) static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) { - int i; + size_t i; + if (table == NULL || table->table == NULL) return; for (i = 0; i < table->count; i++) { @@ -139,7 +140,8 @@ static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table) { - int i; + size_t i; + if (table == NULL || table->table == NULL) return; for (i = 0; i < table->count; i++) { @@ -385,7 +387,7 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, #ifdef CONFIG_ELOOP_KQUEUE struct kevent ke; #endif /* CONFIG_ELOOP_KQUEUE */ - int i; + size_t i; if (table == NULL || table->table == NULL || table->count == 0) return; @@ -444,7 +446,7 @@ static int eloop_sock_table_set_fds(struct eloop_sock_table *readers, struct pollfd **pollfds_map, int max_pollfd_map) { - int i; + size_t i; int nxt = 0; int fd; struct pollfd *pfd; @@ -519,7 +521,7 @@ static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table, int max_pollfd_map, short int revents) { - int i; + size_t i; struct pollfd *pfd; if (!table || !table->table) @@ -572,7 +574,7 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *readers, static void eloop_sock_table_set_fds(struct eloop_sock_table *table, fd_set *fds) { - int i; + size_t i; FD_ZERO(fds); @@ -589,7 +591,7 @@ static void eloop_sock_table_set_fds(struct eloop_sock_table *table, static void eloop_sock_table_dispatch(struct eloop_sock_table *table, fd_set *fds) { - int i; + size_t i; if (table == NULL || table->table == NULL) return; @@ -653,7 +655,8 @@ static void eloop_sock_table_dispatch(struct kevent *events, int nfds) static int eloop_sock_table_requeue(struct eloop_sock_table *table) { - int i, r; + size_t i; + int r; r = 0; for (i = 0; i < table->count && table->table; i++) { @@ -694,7 +697,8 @@ int eloop_sock_requeue(void) static void eloop_sock_table_destroy(struct eloop_sock_table *table) { if (table) { - int i; + size_t i; + for (i = 0; i < table->count && table->table; i++) { wpa_printf(MSG_INFO, "ELOOP: remaining socket: " "sock=%d eloop_data=%p user_data=%p " From 2f06008564976bc79772d8ef0d93a16cd6929d38 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:35:45 +0200 Subject: [PATCH 0243/1105] loop: Use size_t for eloop.count This is more consistent with the other eloop registrations and avoids a theoretical integer overflow with 16-bit int should more than 32767 sockets/signals/events be registered. Signed-off-by: Jouni Malinen --- src/utils/eloop.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/utils/eloop.c b/src/utils/eloop.c index b4e7f9e71..b353ab0e4 100644 --- a/src/utils/eloop.c +++ b/src/utils/eloop.c @@ -77,10 +77,10 @@ struct eloop_sock_table { struct eloop_data { int max_sock; - int count; /* sum of all table counts */ + size_t count; /* sum of all table counts */ #ifdef CONFIG_ELOOP_POLL - int max_pollfd_map; /* number of pollfds_map currently allocated */ - int max_poll_fds; /* number of pollfds currently allocated */ + size_t max_pollfd_map; /* number of pollfds_map currently allocated */ + size_t max_poll_fds; /* number of pollfds currently allocated */ struct pollfd *pollfds; struct pollfd **pollfds_map; #endif /* CONFIG_ELOOP_POLL */ @@ -90,12 +90,12 @@ struct eloop_data { #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ #ifdef CONFIG_ELOOP_EPOLL int epollfd; - int epoll_max_event_num; + size_t epoll_max_event_num; struct epoll_event *epoll_events; #endif /* CONFIG_ELOOP_EPOLL */ #ifdef CONFIG_ELOOP_KQUEUE int kqueuefd; - int kqueue_nevents; + size_t kqueue_nevents; struct kevent *kqueue_events; #endif /* CONFIG_ELOOP_KQUEUE */ struct eloop_sock_table readers; @@ -268,7 +268,7 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, #endif /* CONFIG_ELOOP_EPOLL */ #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) struct eloop_sock *temp_table; - int next; + size_t next; #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ struct eloop_sock *tmp; int new_max_sock; @@ -282,7 +282,7 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, return -1; #ifdef CONFIG_ELOOP_POLL - if (new_max_sock >= eloop.max_pollfd_map) { + if ((size_t) new_max_sock >= eloop.max_pollfd_map) { struct pollfd **nmap; nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50, sizeof(struct pollfd *)); @@ -295,7 +295,8 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, if (eloop.count + 1 > eloop.max_poll_fds) { struct pollfd *n; - int nmax = eloop.count + 1 + 50; + size_t nmax = eloop.count + 1 + 50; + n = os_realloc_array(eloop.pollfds, nmax, sizeof(struct pollfd)); if (n == NULL) From 749add5c647e1e4e20114c4c74caa0578cf0e531 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:37:40 +0200 Subject: [PATCH 0244/1105] Limit freq_range_list_parse() result to UINT_MAX entries This addresses a theoretical integer overflow with configuration parameters with 16-bit int. Signed-off-by: Jouni Malinen --- src/utils/common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/common.c b/src/utils/common.c index e5b3dcbd4..16aa7b6ee 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -791,6 +791,10 @@ int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) */ pos = value; while (pos && pos[0]) { + if (count == UINT_MAX) { + os_free(freq); + return -1; + } n = os_realloc_array(freq, count + 1, sizeof(struct wpa_freq_range)); if (n == NULL) { From 9f9a148af609d9dd2928287e6fa18b06a96ec7ee Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:49:04 +0200 Subject: [PATCH 0245/1105] Convert int_array to use size_t instead of int as the length This extends this to allow longer lists with LP32 data model to avoid limit of 16-bit int. Signed-off-by: Jouni Malinen --- src/utils/common.c | 26 +++++++++++++------------- src/utils/common.h | 2 +- src/utils/utils_module_tests.c | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/utils/common.c b/src/utils/common.c index 16aa7b6ee..2c1275193 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -879,9 +879,10 @@ char * freq_range_list_str(const struct wpa_freq_range_list *list) } -int int_array_len(const int *a) +size_t int_array_len(const int *a) { - int i; + size_t i; + for (i = 0; a && a[i]; i++) ; return i; @@ -890,25 +891,24 @@ int int_array_len(const int *a) void int_array_concat(int **res, const int *a) { - int reslen, alen, i, new_len; + size_t reslen, alen, i, max_size; int *n; reslen = int_array_len(*res); alen = int_array_len(a); - new_len = reslen + alen + 1; - if (reslen < 0 || alen < 0 || new_len < 0) { + max_size = (size_t) -1; + if (alen >= max_size - reslen) { /* This should not really happen, but if it did, something - * overflowed. Do not try to merge the arrays; instead, make + * would overflow. Do not try to merge the arrays; instead, make * this behave like memory allocation failure to avoid messing * up memory. */ os_free(*res); *res = NULL; return; } - n = os_realloc_array(*res, new_len, sizeof(int)); + n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); if (n == NULL) { - if (new_len) - os_free(*res); + os_free(*res); *res = NULL; return; } @@ -933,8 +933,7 @@ static int freq_cmp(const void *a, const void *b) void int_array_sort_unique(int *a) { - int alen; - int i, j; + size_t alen, i, j; if (a == NULL) return; @@ -959,7 +958,7 @@ void int_array_sort_unique(int *a) void int_array_add_unique(int **res, int a) { - int reslen; + size_t reslen, max_size; int *n; for (reslen = 0; *res && (*res)[reslen]; reslen++) { @@ -967,7 +966,8 @@ void int_array_add_unique(int **res, int a) return; /* already in the list */ } - if (reslen > INT_MAX - 2) { + max_size = (size_t) -1; + if (reslen > max_size - 2) { /* This should not really happen in practice, but if it did, * something would overflow. Do not try to add the new value; * instead, make this behave like memory allocation failure to diff --git a/src/utils/common.h b/src/utils/common.h index 833469a52..8e5cfe16a 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -547,7 +547,7 @@ int freq_range_list_includes(const struct wpa_freq_range_list *list, unsigned int freq); char * freq_range_list_str(const struct wpa_freq_range_list *list); -int int_array_len(const int *a); +size_t int_array_len(const int *a); void int_array_concat(int **res, const int *a); void int_array_sort_unique(int *a); void int_array_add_unique(int **res, int a); diff --git a/src/utils/utils_module_tests.c b/src/utils/utils_module_tests.c index f75d4065d..365f21fb1 100644 --- a/src/utils/utils_module_tests.c +++ b/src/utils/utils_module_tests.c @@ -226,7 +226,7 @@ static int int_array_tests(void) int test3[] = { 1, 1, 1, -1, 2, 3, 4, 1, 2, 0 }; int test3_res[] = { -1, 1, 2, 3, 4, 0 }; int errors = 0; - int len; + size_t len; wpa_printf(MSG_INFO, "int_array tests"); From b967b5e859149d53cb32bc0b37a6ef60a8b1f554 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 18:51:41 +0200 Subject: [PATCH 0246/1105] Limit scan frequency list to 100 entries There is no real use case for the scan to be requested on more than 100 channels individually. To avoid excessively long lists with invalid configuration, use 100 entry limit for the list before dropping to the fallback scan-all-channels option. Signed-off-by: Jouni Malinen --- wpa_supplicant/scan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index ad9d77af8..b47573094 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1109,7 +1109,9 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) tssid = tssid->next) { if (wpas_network_disabled(wpa_s, tssid)) continue; - if ((params.freqs || !freqs_set) && tssid->scan_freq) { + if (((params.freqs || !freqs_set) && + tssid->scan_freq) && + int_array_len(params.freqs) < 100) { int_array_concat(¶ms.freqs, tssid->scan_freq); } else { From 9efac010204a2de2d0174369e005b25706f03fa9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 22 Mar 2020 19:52:38 +0200 Subject: [PATCH 0247/1105] tests: Fix bgscan_learn_beacon_loss with REPORTS_TX_ACK_STATUS Stopping the AP from beaconing will also stop it from acknowledging frames and that resulted in bgscan_learn_beacon_loss failing when mac80211_hwsim is registering REPORTS_TX_ACK_STATUS. Work around this by moving to using PMF so that the station ignores the unprotected deauthentiation frames from the AP and also disabling SA Query. This allows the AP to be stopped and restarted with large enough Beacon interval to allow the station to detect beacon loss. This is identical to the earlier design change for bgscan_simple_beacon_loss (somehow this bgscan_learn_beacon_loss test case managed to pass at that time). Signed-off-by: Jouni Malinen --- tests/hwsim/test_bgscan.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_bgscan.py b/tests/hwsim/test_bgscan.py index 0387406fe..fdbc03fe6 100644 --- a/tests/hwsim/test_bgscan.py +++ b/tests/hwsim/test_bgscan.py @@ -246,13 +246,21 @@ def test_bgscan_learn(dev, apdev): def test_bgscan_learn_beacon_loss(dev, apdev): """bgscan_simple and beacon loss""" - hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"}) + params = hostapd.wpa2_params(ssid="bgscan", passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412", - bgscan="learn:1:-20:2") + dev[0].set("disable_sa_query", "1") + dev[0].connect("bgscan", ieee80211w="2", key_mgmt="WPA-PSK-SHA256", + psk="12345678", scan_freq="2412", bgscan="learn:1:-20:2") hapd.set("ext_mgmt_frame_handling", "1") if "OK" not in hapd.request("STOP_AP"): raise Exception("Failed to stop AP") + hapd.disable() + hapd.set("ssid", "foo") + hapd.set("beacon_int", "10000") + hapd.enable() ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=10) if ev is None: raise Exception("Beacon loss not reported") From 862aac1fcd20b1136f926c16afb21cfa1defb157 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Fri, 20 Mar 2020 20:04:31 +0100 Subject: [PATCH 0248/1105] AP: Support Extended Key ID Support Extended Key ID in hostapd according to IEEE Std 802.11-2016. Extended Key ID allows to rekey pairwise keys without the otherwise unavoidable MPDU losses on a busy link. The standard is fully backward compatible, allowing an AP to serve STAs with and without Extended Key ID support in the same BSS. Signed-off-by: Alexander Wetzel --- hostapd/config_file.c | 10 ++++++ hostapd/ctrl_iface.c | 8 +++++ hostapd/hostapd.conf | 11 +++++++ src/ap/ap_config.h | 1 + src/ap/wpa_auth.c | 74 ++++++++++++++++++++++++++++++++++++------ src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_ft.c | 2 +- src/ap/wpa_auth_glue.c | 13 +++++++- src/ap/wpa_auth_i.h | 2 ++ src/ap/wpa_auth_ie.c | 20 ++++++++++++ 10 files changed, 130 insertions(+), 12 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 3c7bb395f..2bc0679b5 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2869,6 +2869,16 @@ static int hostapd_config_fill(struct hostapd_config *conf, } } else if (os_strcmp(buf, "wpa") == 0) { bss->wpa = atoi(pos); + } else if (os_strcmp(buf, "extended_key_id") == 0) { + int val = atoi(pos); + + if (bss->extended_key_id < 0 || bss->extended_key_id > 2) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid extended_key_id=%d; allowed range 0..2", + line, bss->extended_key_id); + return 1; + } + bss->extended_key_id = val; } else if (os_strcmp(buf, "wpa_group_rekey") == 0) { bss->wpa_group_rekey = atoi(pos); bss->wpa_group_rekey_set = 1; diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 6d2ecbc9c..1a369ed2a 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1295,6 +1295,14 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, pos += ret; } + if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->extended_key_id) { + ret = os_snprintf(pos, end - pos, "extended_key_id=%d\n", + hapd->conf->extended_key_id); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + return pos - buf; } diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index bc5d1a7f6..b09f6ed0a 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1510,6 +1510,17 @@ own_ip_addr=127.0.0.1 # wpa_key_mgmt=SAE for WPA3-Personal instead of wpa_key_mgmt=WPA-PSK). #wpa=2 +# Extended Key ID support for Individually Addressed frames +# +# Extended Key ID allows to rekey PTK keys without the impacts the "normal" +# PTK rekeying with only a single Key ID 0 has. It can only be used when the +# driver supports it and RSN/WPA2 is used with a CCMP/GCMP pairwise cipher. +# +# 0 = force off, i.e., use only Key ID 0 (default) +# 1 = enable and use Extended Key ID support when possible +# 2 = identical to 1 but start with Key ID 1 when possible +#extended_key_id=0 + # WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit # secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase # (8..63 characters) that will be converted to PSK. This conversion uses SSID diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 80be7ed39..5f4665c07 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -354,6 +354,7 @@ struct hostapd_bss_config { * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */ int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ + int extended_key_id; int wpa_key_mgmt; enum mfp_options ieee80211w; int group_mgmt_cipher; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 64fc09ca6..6512c0194 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -781,7 +781,7 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm) if (sm == NULL) return; - if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { + if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { wpa_printf(MSG_INFO, "WPA: PTK0 rekey not allowed, disconnect " MACSTR, MAC2STR(sm->addr)); @@ -790,6 +790,8 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm) sm->disconnect_reason = WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; } else { + if (sm->use_ext_key_id) + sm->keyidx_active ^= 1; /* flip Key ID */ sm->PTKRequest = TRUE; sm->PTK_valid = 0; } @@ -1754,6 +1756,11 @@ void wpa_remove_ptk(struct wpa_state_machine *sm) 0, KEY_FLAG_PAIRWISE)) wpa_printf(MSG_DEBUG, "RSN: PTK removal from the driver failed"); + if (sm->wpa_auth->conf.extended_key_id && sm->use_ext_key_id && + wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL, + 0, KEY_FLAG_PAIRWISE)) + wpa_printf(MSG_DEBUG, + "RSN: PTK Key ID 1 removal from the driver failed"); sm->pairwise_set = FALSE; eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); } @@ -1812,16 +1819,23 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) sm->Init = FALSE; sm->AuthenticationRequest = TRUE; break; - } else if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { + } + + if (!sm->use_ext_key_id && + sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { wpa_printf(MSG_INFO, "WPA: PTK0 rekey not allowed, disconnect " MACSTR, MAC2STR(sm->addr)); sm->Disconnect = TRUE; - /* Try to encourage the STA reconnect */ + /* Try to encourage the STA to reconnect */ sm->disconnect_reason = WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; break; } + + if (sm->use_ext_key_id) + sm->keyidx_active ^= 1; /* flip Key ID */ + if (sm->GUpdateStationKeys) { /* * Reauthentication cancels the pending group key @@ -3261,6 +3275,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) u8 *wpa_ie; int secure, gtkidx, encr = 0; u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL; + u8 hdr[2]; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; @@ -3317,6 +3332,18 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "sending 3/4 msg of 4-Way Handshake"); if (sm->wpa == WPA_VERSION_WPA2) { + if (sm->use_ext_key_id && sm->TimeoutCtr == 1 && + wpa_auth_set_key(sm->wpa_auth, 0, + wpa_cipher_to_alg(sm->pairwise), + sm->addr, + sm->keyidx_active, sm->PTK.tk, + wpa_cipher_key_len(sm->pairwise), + KEY_FLAG_PAIRWISE_RX)) { + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + /* WPA2 send GTK in the 4-way handshake */ secure = 1; gtk = gsm->GTK[gsm->GN - 1]; @@ -3357,6 +3384,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); + + if (sm->use_ext_key_id) + kde_len += 2 + RSN_SELECTOR_LEN + 2; + if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; #ifdef CONFIG_IEEE80211R_AP @@ -3392,10 +3423,15 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) pos += elen; } #endif /* CONFIG_IEEE80211R_AP */ + hdr[1] = 0; + + if (sm->use_ext_key_id) { + hdr[0] = sm->keyidx_active & 0x01; + pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0); + } + if (gtk) { - u8 hdr[2]; hdr[0] = gtkidx & 0x03; - hdr[1] = 0; pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gtk_len); } @@ -3478,9 +3514,17 @@ SM_STATE(WPA_PTK, PTKINITDONE) if (sm->Pair) { enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); int klen = wpa_cipher_key_len(sm->pairwise); - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk, klen, - KEY_FLAG_PAIRWISE_RX_TX)) { + int res; + + if (sm->use_ext_key_id) + res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr, + sm->keyidx_active, NULL, 0, + KEY_FLAG_PAIRWISE_RX_TX_MODIFY); + else + res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, + 0, sm->PTK.tk, klen, + KEY_FLAG_PAIRWISE_RX_TX); + if (res) { wpa_sta_disconnect(sm->wpa_auth, sm->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); return; @@ -5167,6 +5211,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, struct wpa_group *gsm = sm->group; u8 *wpa_ie; int wpa_ie_len, secure, gtkidx, encr = 0; + u8 hdr[2]; /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2]) @@ -5219,6 +5264,10 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, } kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); + + if (sm->use_ext_key_id) + kde_len += 2 + RSN_SELECTOR_LEN + 2; + if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; #ifdef CONFIG_IEEE80211R_AP @@ -5251,10 +5300,15 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, pos += elen; } #endif /* CONFIG_IEEE80211R_AP */ + hdr[1] = 0; + + if (sm->use_ext_key_id) { + hdr[0] = sm->keyidx_active & 0x01; + pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0); + } + if (gtk) { - u8 hdr[2]; hdr[0] = gtkidx & 0x03; - hdr[1] = 0; pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gtk_len); } diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 58aa9ff21..528516195 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -169,6 +169,7 @@ struct ft_remote_r1kh { struct wpa_auth_config { int wpa; + int extended_key_id; int wpa_key_mgmt; int wpa_pairwise; int wpa_group; diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 5ed78e6a6..476a2be69 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2775,7 +2775,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) * again after association to get the PTK configured, but that could be * optimized by adding the STA entry earlier. */ - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, + if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, sm->keyidx_active, sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) return; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 926ff455f..70d32818a 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -41,6 +41,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, os_memset(wconf, 0, sizeof(*wconf)); wconf->wpa = conf->wpa; + wconf->extended_key_id = conf->extended_key_id; wconf->wpa_key_mgmt = conf->wpa_key_mgmt; wconf->wpa_pairwise = conf->wpa_pairwise; wconf->wpa_group = conf->wpa_group; @@ -433,7 +434,11 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, } #ifdef CONFIG_TESTING_OPTIONS - if (addr && !is_broadcast_ether_addr(addr)) { + if (key_flag & KEY_FLAG_MODIFY) { + /* We are updating an already installed key. Don't overwrite + * the already stored key information with zeros. + */ + } else if (addr && !is_broadcast_ether_addr(addr)) { struct sta_info *sta; sta = ap_get_sta(hapd, addr); @@ -1419,6 +1424,12 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) _conf.wpa_deny_ptk0_rekey = 1; } + if (_conf.extended_key_id && + (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Extended Key ID supported"); + else + _conf.extended_key_id = 0; + hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd); if (hapd->wpa_auth == NULL) { wpa_printf(MSG_ERROR, "WPA initialization failed."); diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 5d7b96c6f..bc59d6a4c 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -61,6 +61,8 @@ struct wpa_state_machine { unsigned int pmk_len; u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */ struct wpa_ptk PTK; + u8 keyidx_active; + Boolean use_ext_key_id; Boolean PTK_valid; Boolean pairwise_set; Boolean tk_already_set; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 2e6d05910..11153e0b8 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -297,6 +297,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, if (rsn_testing) capab |= BIT(8) | BIT(15); #endif /* CONFIG_RSN_TESTING */ + if (conf->extended_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; WPA_PUT_LE16(pos, capab); pos += 2; @@ -553,6 +555,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, const u8 *mdie, size_t mdie_len, const u8 *owe_dh, size_t owe_dh_len) { + struct wpa_auth_config *conf = &wpa_auth->conf; struct wpa_ie_data data; int ciphers, key_mgmt, res, version; u32 selector; @@ -944,6 +947,23 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } #endif /* CONFIG_DPP */ + if (conf->extended_key_id && sm->wpa == WPA_VERSION_WPA2 && + sm->pairwise != WPA_CIPHER_TKIP && + (data.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) { + sm->use_ext_key_id = TRUE; + if (conf->extended_key_id == 2 && + !wpa_key_mgmt_ft(sm->wpa_key_mgmt) && + !wpa_key_mgmt_fils(sm->wpa_key_mgmt)) + sm->keyidx_active = 1; + else + sm->keyidx_active = 0; + wpa_printf(MSG_DEBUG, + "RSN: Extended Key ID supported (start with %d)", + sm->keyidx_active); + } else { + sm->use_ext_key_id = FALSE; + } + if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { os_free(sm->wpa_ie); sm->wpa_ie = os_malloc(wpa_ie_len); From b17b7a8e53f28aed746518321ecd302d0c260971 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Fri, 20 Mar 2020 20:04:32 +0100 Subject: [PATCH 0249/1105] STA: Support Extended Key ID Support Extended Key ID in wpa_supplicant according to IEEE Std 802.11-2016 for infrastructure (AP) associations. Extended Key ID allows to rekey pairwise keys without the otherwise unavoidable MPDU losses on a busy link. The standard is fully backward compatible, allowing STAs to also connect to APs not supporting it. Signed-off-by: Alexander Wetzel --- src/rsn_supp/wpa.c | 117 ++++++++++++++++++++++-- src/rsn_supp/wpa.h | 14 +++ src/rsn_supp/wpa_ft.c | 2 + src/rsn_supp/wpa_i.h | 4 + src/rsn_supp/wpa_ie.c | 2 + wpa_supplicant/ap.c | 1 + wpa_supplicant/config.c | 2 + wpa_supplicant/config.h | 12 +++ wpa_supplicant/config_file.c | 3 + wpa_supplicant/config_winreg.c | 9 ++ wpa_supplicant/ctrl_iface.c | 3 + wpa_supplicant/dbus/dbus_new_handlers.c | 13 ++- wpa_supplicant/driver_i.h | 9 +- wpa_supplicant/wpa_cli.c | 3 +- wpa_supplicant/wpa_supplicant.c | 35 ++++++- wpa_supplicant/wpa_supplicant.conf | 5 + wpa_supplicant/wpas_glue.c | 6 +- 17 files changed, 222 insertions(+), 18 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index ba0e5c343..14fe0846d 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -183,7 +183,7 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) int key_info, ver; u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic; - if (pairwise && sm->wpa_deny_ptk0_rekey && + if (pairwise && sm->wpa_deny_ptk0_rekey && !sm->use_ext_key_id && wpa_sm_get_state(sm) == WPA_COMPLETED) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: PTK0 rekey not allowed, reconnecting"); @@ -608,6 +608,51 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, } +static int wpa_handle_ext_key_id(struct wpa_sm *sm, + struct wpa_eapol_ie_parse *kde) +{ + if (sm->ext_key_id) { + u16 key_id; + + if (!kde->key_id) { + wpa_msg(sm->ctx->msg_ctx, + sm->use_ext_key_id ? MSG_INFO : MSG_DEBUG, + "RSN: No Key ID in Extended Key ID handshake"); + sm->keyidx_active = 0; + return sm->use_ext_key_id ? -1 : 0; + } + + key_id = kde->key_id[0] & 0x03; + if (key_id > 1) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Invalid Extended Key ID: %d", key_id); + return -1; + } + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Using Extended Key ID %d", key_id); + sm->keyidx_active = key_id; + sm->use_ext_key_id = 1; + } else { + if (kde->key_id && (kde->key_id[0] & 0x03)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Non-zero Extended Key ID Key ID in PTK0 handshake"); + return -1; + } + + if (kde->key_id) { + /* This is not supposed to be included here, but ignore + * the case of matching Key ID 0 just in case. */ + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Extended Key ID Key ID 0 in PTK0 handshake"); + } + sm->keyidx_active = 0; + sm->use_ext_key_id = 0; + } + + return 0; +} + + static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, @@ -626,7 +671,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, return; } - if (sm->wpa_deny_ptk0_rekey && wpa_sm_get_state(sm) == WPA_COMPLETED) { + if (sm->wpa_deny_ptk0_rekey && !sm->use_ext_key_id && + wpa_sm_get_state(sm) == WPA_COMPLETED) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: PTK0 rekey not allowed, reconnecting"); wpa_sm_reconnect(sm); @@ -859,13 +905,14 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); } - if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, - sm->ptk.tk, keylen, + if (wpa_sm_set_key(sm, alg, sm->bssid, sm->keyidx_active, 1, key_rsc, + rsclen, sm->ptk.tk, keylen, KEY_FLAG_PAIRWISE | key_flag) < 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to set PTK to the " - "driver (alg=%d keylen=%d bssid=" MACSTR ")", - alg, keylen, MAC2STR(sm->bssid)); + "WPA: Failed to set PTK to the driver (alg=%d keylen=%d bssid=" + MACSTR " idx=%d key_flag=0x%x)", + alg, keylen, MAC2STR(sm->bssid), + sm->keyidx_active, key_flag); return -1; } @@ -879,7 +926,23 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, sm, NULL); } + return 0; +} + +static int wpa_supplicant_activate_ptk(struct wpa_sm *sm) +{ + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Activate PTK (idx=%d bssid=" MACSTR ")", + sm->keyidx_active, MAC2STR(sm->bssid)); + + if (wpa_sm_set_key(sm, 0, sm->bssid, sm->keyidx_active, 0, NULL, 0, + NULL, 0, KEY_FLAG_PAIRWISE_RX_TX_MODIFY) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to activate PTK for TX (idx=%d bssid=" + MACSTR ")", sm->keyidx_active, MAC2STR(sm->bssid)); + return -1; + } return 0; } @@ -1582,6 +1645,9 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) goto failed; + if (wpa_handle_ext_key_id(sm, &ie)) + goto failed; + if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: ANonce from message 1 of 4-Way Handshake " @@ -1627,6 +1693,10 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, } #endif /* CONFIG_OCV */ + if (sm->use_ext_key_id && + wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX)) + goto failed; + if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, &sm->ptk) < 0) { goto failed; @@ -1638,7 +1708,14 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, sm->renew_snonce = 1; if (key_info & WPA_KEY_INFO_INSTALL) { - if (wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX_TX)) + int res; + + if (sm->use_ext_key_id) + res = wpa_supplicant_activate_ptk(sm); + else + res = wpa_supplicant_install_ptk(sm, key, + KEY_FLAG_RX_TX); + if (res) goto failed; } @@ -2880,6 +2957,8 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) #ifdef CONFIG_P2P os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr)); #endif /* CONFIG_P2P */ + + sm->keyidx_active = 0; } @@ -2911,6 +2990,7 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) /* Keys are not needed in the WPA state machine anymore */ wpa_sm_drop_sa(sm); + sm->keyidx_active = 0; sm->msg_3_of_4_ok = 0; os_memset(sm->bssid, 0, ETH_ALEN); @@ -3164,6 +3244,12 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_DENY_PTK0_REKEY: sm->wpa_deny_ptk0_rekey = value; break; + case WPA_PARAM_EXT_KEY_ID: + sm->ext_key_id = value; + break; + case WPA_PARAM_USE_EXT_KEY_ID: + sm->use_ext_key_id = value; + break; default: break; } @@ -3238,6 +3324,18 @@ int wpa_sm_pmf_enabled(struct wpa_sm *sm) } +int wpa_sm_ext_key_id(struct wpa_sm *sm) +{ + return sm ? sm->ext_key_id : 0; +} + + +int wpa_sm_ext_key_id_active(struct wpa_sm *sm) +{ + return sm ? sm->use_ext_key_id : 0; +} + + int wpa_sm_ocv_enabled(struct wpa_sm *sm) { struct wpa_ie_data rsn; @@ -4253,6 +4351,8 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) capab |= WPA_CAPABILITY_MFPR; if (sm->ocv) capab |= WPA_CAPABILITY_OCVC; + if (sm->ext_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; wpabuf_put_le16(buf, capab); /* PMKID Count */ @@ -4680,6 +4780,7 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) keylen, (long unsigned int) sm->ptk.tk_len); goto fail; } + rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); wpa_hexdump_key(MSG_DEBUG, "FILS: Set TK to driver", sm->ptk.tk, keylen); diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 0bd14495a..02b5df883 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -102,6 +102,8 @@ enum wpa_sm_conf_params { WPA_PARAM_OCV, WPA_PARAM_SAE_PWE, WPA_PARAM_DENY_PTK0_REKEY, + WPA_PARAM_EXT_KEY_ID, + WPA_PARAM_USE_EXT_KEY_ID, }; struct rsn_supp_config { @@ -154,6 +156,8 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, int verbose); int wpa_sm_pmf_enabled(struct wpa_sm *sm); +int wpa_sm_ext_key_id(struct wpa_sm *sm); +int wpa_sm_ext_key_id_active(struct wpa_sm *sm); int wpa_sm_ocv_enabled(struct wpa_sm *sm); void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise); @@ -300,6 +304,16 @@ static inline int wpa_sm_pmf_enabled(struct wpa_sm *sm) return 0; } +static inline int wpa_sm_ext_key_id(struct wpa_sm *sm) +{ + return 0; +} + +static inline int wpa_sm_ext_key_id_active(struct wpa_sm *sm) +{ + return 0; +} + static inline int wpa_sm_ocv_enabled(struct wpa_sm *sm) { return 0; diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 6d92de5a6..bec5eb0b2 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -265,6 +265,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, capab |= WPA_CAPABILITY_MFPR; if (sm->ocv) capab |= WPA_CAPABILITY_OCVC; + if (sm->ext_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; WPA_PUT_LE16(pos, capab); pos += 2; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 7af678dcd..5fd70a498 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -68,6 +68,10 @@ struct wpa_sm { int wpa_rsc_relaxation; int owe_ptk_workaround; int beacon_prot; + int ext_key_id; /* whether Extended Key ID is enabled */ + int use_ext_key_id; /* whether Extended Key ID has been detected + * to be used */ + int keyidx_active; /* Key ID for the active TK */ u8 own_addr[ETH_ALEN]; const char *ifname; diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 03c0d7e85..e8a040a2b 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -221,6 +221,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, capab |= WPA_CAPABILITY_MFPR; if (sm->ocv) capab |= WPA_CAPABILITY_OCVC; + if (sm->ext_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; WPA_PUT_LE16(pos, capab); pos += 2; diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 87573ef10..ee7c755b5 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -344,6 +344,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IEEE80211AX */ bss->isolate = !wpa_s->conf->p2p_intra_bss; + bss->extended_key_id = wpa_s->conf->extended_key_id; bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; bss->wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey; diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 4f359ede0..30801abd9 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4293,6 +4293,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD; config->cert_in_cb = DEFAULT_CERT_IN_CB; config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION; + config->extended_key_id = DEFAULT_EXTENDED_KEY_ID; #ifdef CONFIG_MBO config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA; @@ -5057,6 +5058,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(coloc_intf_reporting, 0, 1), 0 }, #ifdef CONFIG_WNM { INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM }, + { INT_RANGE(extended_key_id, 0, 1), 0 }, #endif /* CONFIG_WNM */ }; diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 486432e43..2d4cb1b8f 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -44,6 +44,7 @@ #define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED #define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75 #define DEFAULT_OCE_SUPPORT OCE_STA +#define DEFAULT_EXTENDED_KEY_ID 0 #include "config_ssid.h" #include "wps/wps.h" @@ -1570,6 +1571,17 @@ struct wpa_config { * By default BSS transition management is enabled */ int disable_btm; + + /** + * extended_key_id - Extended Key ID support + * + * IEEE Std 802.11-2016 optionally allows to use Key ID 0 and 1 for PTK + * keys with Extended Key ID. + * + * 0 = don't use Extended Key ID + * 1 = use Extended Key ID when possible + */ + int extended_key_id; }; diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index b8e56f5b2..e77cbca4f 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1596,6 +1596,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) config->p2p_interface_random_mac_addr); if (config->disable_btm) fprintf(f, "disable_btm=1\n"); + if (config->extended_key_id != DEFAULT_EXTENDED_KEY_ID) + fprintf(f, "extended_key_id=%d\n", + config->extended_key_id); } #endif /* CONFIG_NO_CONFIG_WRITE */ diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index 598bc7790..1b7f96ed2 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -277,6 +277,15 @@ static int wpa_config_read_global(struct wpa_config *config, HKEY hk) wpa_config_read_reg_dword(hk, TEXT("okc"), &config->okc); wpa_config_read_reg_dword(hk, TEXT("pmf"), &val); config->pmf = val; + if (wpa_config_read_reg_dword(hk, TEXT("extended_key_id"), + &val) == 0) { + if (val < 0 || val > 1) { + wpa_printf(MSG_ERROR, + "Invalid Extended Key ID setting (%d)", val); + errors++; + } + config->extended_key_id = val; + } return errors ? -1 : 0; } diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 3b4c50020..0c79d5257 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5374,6 +5374,9 @@ static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE); + if (wpa_sm_ext_key_id(wpa_s->wpa)) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 1, 0, + NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE); /* MLME-SETPROTECTION.request(None) */ wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, MLME_SETPROTECTION_PROTECT_TYPE_NONE, diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 01fc67b6f..4e17e31a7 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -991,20 +991,25 @@ dbus_bool_t wpas_dbus_getter_global_capabilities( const struct wpa_dbus_property_desc *property_desc, DBusMessageIter *iter, DBusError *error, void *user_data) { - const char *capabilities[11]; + const char *capabilities[12]; size_t num_items = 0; -#ifdef CONFIG_FILS struct wpa_global *global = user_data; struct wpa_supplicant *wpa_s; +#ifdef CONFIG_FILS int fils_supported = 0, fils_sk_pfs_supported = 0; +#endif /* CONFIG_FILS */ + int ext_key_id_supported = 0; for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { +#ifdef CONFIG_FILS if (wpa_is_fils_supported(wpa_s)) fils_supported = 1; if (wpa_is_fils_sk_pfs_supported(wpa_s)) fils_sk_pfs_supported = 1; - } #endif /* CONFIG_FILS */ + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID) + ext_key_id_supported = 1; + } #ifdef CONFIG_AP capabilities[num_items++] = "ap"; @@ -1037,6 +1042,8 @@ dbus_bool_t wpas_dbus_getter_global_capabilities( #ifdef CONFIG_OWE capabilities[num_items++] = "owe"; #endif /* CONFIG_OWE */ + if (ext_key_id_supported) + capabilities[num_items++] = "extended_key_id"; return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_STRING, diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index d3fb58707..6a03d8e91 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -165,7 +165,14 @@ static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, params.key_flag = key_flag; if (alg != WPA_ALG_NONE) { - if (key_idx >= 0 && key_idx <= 6) + /* keyidx = 1 can be either a broadcast or--with + * Extended Key ID--a unicast key. Use bit 15 for + * the pairwise keyidx 1 which is hopefully high enough + * to not clash with future extensions. + */ + if (key_idx == 1 && (key_flag & KEY_FLAG_PAIRWISE)) + wpa_s->keys_cleared &= ~BIT(15); + else if (key_idx >= 0 && key_idx <= 5) wpa_s->keys_cleared &= ~BIT(key_idx); else wpa_s->keys_cleared = 0; diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 22885e646..730d749fe 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -502,6 +502,7 @@ static char ** wpa_cli_complete_set(const char *str, int pos) "ignore_auth_resp", #endif /* CONFIG_TESTING_OPTIONS */ "relative_rssi", "relative_band_adjust", + "extended_key_id", }; int i, num_fields = ARRAY_SIZE(fields); @@ -593,7 +594,7 @@ static char ** wpa_cli_complete_get(const char *str, int pos) "tdls_external_control", "osu_dir", "wowlan_triggers", "p2p_search_delay", "mac_addr", "rand_addr_lifetime", "preassoc_mac_addr", "key_mgmt_offload", "passive_scan", - "reassoc_same_bss_optim" + "reassoc_same_bss_optim", "extended_key_id" }; int i, num_fields = ARRAY_SIZE(fields); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index c638fe535..f11bac017 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -748,10 +748,15 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr) wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0, NULL, 0, KEY_FLAG_GROUP); } - if (!(wpa_s->keys_cleared & BIT(0)) && addr && + /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */ + if (!(wpa_s->keys_cleared & (BIT(0) | BIT(15))) && addr && !is_zero_ether_addr(addr)) { - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, - 0, KEY_FLAG_PAIRWISE); + if (!(wpa_s->keys_cleared & BIT(0))) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, + 0, NULL, 0, KEY_FLAG_PAIRWISE); + if (!(wpa_s->keys_cleared & BIT(15))) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL, + 0, NULL, 0, KEY_FLAG_PAIRWISE); /* MLME-SETPROTECTION.request(None) */ wpa_drv_mlme_setprotection( wpa_s, addr, @@ -1635,6 +1640,30 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, sae_pwe = 1; wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe); + /* Extended Key ID is only supported in infrastructure BSS so far */ + if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id && + (ssid->proto & WPA_PROTO_RSN) && + ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 | + WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) { + int use_ext_key_id = 0; + + wpa_msg(wpa_s, MSG_DEBUG, + "WPA: Enable Extended Key ID support"); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, + wpa_s->conf->extended_key_id); + if (bss_rsn && + wpa_s->conf->extended_key_id && + wpa_s->pairwise_cipher != WPA_CIPHER_TKIP && + (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) + use_ext_key_id = 1; + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, + use_ext_key_id); + } else { + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0); + } + if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE"); return -1; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index f3a750e3c..591e1343f 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -802,6 +802,11 @@ fast_reauth=1 # Set BIT(1) to Enable OCE in STA-CFON mode #oce=1 +# Extended Key ID support for Individually Addressed frames +# 0 = force off: Do not use Extended Key ID (default) +# 1 = auto: Activate Extended Key ID support if the driver supports it +#extended_key_id=0 + # network block # # Each network (usually AP's sharing the same SSID) is configured as a separate diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 39b05b2b9..a3049daf5 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -533,7 +533,8 @@ static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, } #endif /* CONFIG_TESTING_GET_GTK */ #ifdef CONFIG_TESTING_OPTIONS - if (addr && !is_broadcast_ether_addr(addr)) { + if (addr && !is_broadcast_ether_addr(addr) && + !(key_flag & KEY_FLAG_MODIFY)) { wpa_s->last_tk_alg = alg; os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN); wpa_s->last_tk_key_idx = key_idx; @@ -1077,7 +1078,8 @@ static int wpa_supplicant_eap_auth_start_cb(void *ctx) { struct wpa_supplicant *wpa_s = ctx; - if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey) { + if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey && + !wpa_sm_ext_key_id_active(wpa_s->wpa)) { wpa_msg(wpa_s, MSG_INFO, "WPA: PTK0 rekey not allowed, reconnecting"); wpa_supplicant_reconnect(wpa_s); From 8b63a581663927bc95587d0065214b153e101f72 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 23 Mar 2020 00:08:38 +0200 Subject: [PATCH 0250/1105] Use a shared helper function for RSN supplicant capabilities Avoid practically copy-pasted code for determining local RSN capabilities. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa_ft.c | 12 +----------- src/rsn_supp/wpa_ie.c | 29 ++++++++++++++++++----------- src/rsn_supp/wpa_ie.h | 1 + 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index bec5eb0b2..203a61c78 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -178,7 +178,6 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, u8 *buf, *pos, *ftie_len, *ftie_pos, *fte_mic, *elem_count; struct rsn_mdie *mdie; struct rsn_ie_hdr *rsnie; - u16 capab; int mdie_len; u8 rsnxe[10]; size_t rsnxe_len; @@ -258,16 +257,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, pos += RSN_SELECTOR_LEN; /* RSN Capabilities */ - capab = 0; - if (sm->mfp) - capab |= WPA_CAPABILITY_MFPC; - if (sm->mfp == 2) - capab |= WPA_CAPABILITY_MFPR; - if (sm->ocv) - capab |= WPA_CAPABILITY_OCVC; - if (sm->ext_key_id) - capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; - WPA_PUT_LE16(pos, capab); + WPA_PUT_LE16(pos, rsn_supp_capab(sm)); pos += 2; /* PMKID Count */ diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index e8a040a2b..9068781b1 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -105,6 +105,23 @@ static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, } +u16 rsn_supp_capab(struct wpa_sm *sm) +{ + u16 capab = 0; + + if (sm->mfp) + capab |= WPA_CAPABILITY_MFPC; + if (sm->mfp == 2) + capab |= WPA_CAPABILITY_MFPR; + if (sm->ocv) + capab |= WPA_CAPABILITY_OCVC; + if (sm->ext_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; + + return capab; +} + + static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, int pairwise_cipher, int group_cipher, int key_mgmt, int mgmt_group_cipher, @@ -112,7 +129,6 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, { u8 *pos; struct rsn_ie_hdr *hdr; - u16 capab; u32 suite; if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN + @@ -214,16 +230,7 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, pos += RSN_SELECTOR_LEN; /* RSN Capabilities */ - capab = 0; - if (sm->mfp) - capab |= WPA_CAPABILITY_MFPC; - if (sm->mfp == 2) - capab |= WPA_CAPABILITY_MFPR; - if (sm->ocv) - capab |= WPA_CAPABILITY_OCVC; - if (sm->ext_key_id) - capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; - WPA_PUT_LE16(pos, capab); + WPA_PUT_LE16(pos, rsn_supp_capab(sm)); pos += 2; if (sm->cur_pmksa) { diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h index 6dc6cf560..83a6727fe 100644 --- a/src/rsn_supp/wpa_ie.h +++ b/src/rsn_supp/wpa_ie.h @@ -13,5 +13,6 @@ struct wpa_sm; int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len); int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len); +u16 rsn_supp_capab(struct wpa_sm *sm); #endif /* WPA_IE_H */ From 41c3f0cd5beeff69cff27fa055f6a5b9b3107cba Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 23 Mar 2020 11:22:26 +0200 Subject: [PATCH 0251/1105] Allow last configured Key ID for TK to be fetched from wpa_supplicant "GET last_tk_key_idx" can now be used in testing build to determine which was the last configured Key ID for the pairwise key. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 0c79d5257..e140a3e38 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -919,6 +919,8 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, return wpa_snprintf_hex(buf, buflen, wpa_sm_get_anonce(wpa_s->wpa), WPA_NONCE_LEN); + } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) { + res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx); #endif /* CONFIG_TESTING_OPTIONS */ } else { res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen); From 681e8495b4bd1c9df432b5f2cfa1062291ec510e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 23 Mar 2020 00:32:15 +0200 Subject: [PATCH 0252/1105] tests: Extended Key ID Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 26 ++++++++++- tests/hwsim/test_ap_psk.py | 90 +++++++++++++++++++++++++++++++++++++- tests/hwsim/test_fils.py | 32 +++++++++++++- tests/hwsim/utils.py | 5 +++ 4 files changed, 148 insertions(+), 5 deletions(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 624451e90..b8fecda80 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -18,7 +18,7 @@ import hwsim_utils from hwsim import HWSimRadio import hostapd from tshark import run_tshark -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger, skip_with_fips, parse_ie +from utils import * from wlantest import Wlantest from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations from test_rrm import check_beacon_req @@ -995,7 +995,7 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, rsne_override=None, rsnxe_override=None, - no_beacon_rsnxe2=False): + no_beacon_rsnxe2=False, ext_key_id=False): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") ssid = "test-ft" @@ -1011,6 +1011,8 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['rsne_override_ft'] = rsne_override if rsnxe_override: params['rsnxe_override_ft'] = rsnxe_override + if ext_key_id: + params['extended_key_id'] = '1' hapd0 = hostapd.add_ap(apdev[0], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['wpa_key_mgmt'] = "FT-SAE" @@ -1024,6 +1026,8 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['rsnxe_override_ft'] = rsnxe_override if no_beacon_rsnxe2: params['no_beacon_rsnxe'] = "1" + if ext_key_id: + params['extended_key_id'] = '1' hapd1 = hostapd.add_ap(apdev[1], params) key_mgmt = hapd1.get_config()['key_mgmt'] if key_mgmt.split(' ')[0] != "FT-SAE": @@ -1099,6 +1103,24 @@ def test_ap_ft_sae_ptk_rekey_ap(dev, apdev): only_one_way=True) check_ptk_rekey(dev[0], hapd0, hapd1) +def test_ap_ft_sae_ptk_rekey_ap_ext_key_id(dev, apdev): + """WPA2-PSK-FT-SAE AP and PTK rekey triggered by AP (Ext Key ID)""" + check_ext_key_id_capa(dev[0]) + try: + dev[0].set("extended_key_id", "1") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2, + ext_key_id=True) + check_ext_key_id_capa(hapd0) + check_ext_key_id_capa(hapd1) + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + only_one_way=True) + check_ptk_rekey(dev[0], hapd0, hapd1) + idx = int(dev[0].request("GET last_tk_key_idx")) + if idx != 1: + raise Exception("Unexpected Key ID after TK rekey: %d" % idx) + finally: + dev[0].set("extended_key_id", "0") + def test_ap_ft_sae_over_ds(dev, apdev): """WPA2-PSK-FT-SAE AP over DS""" hapd0, hapd1 = start_ft_sae(dev[0], apdev) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index febbc07fe..b9abf5d82 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -19,7 +19,7 @@ import subprocess import time import hostapd -from utils import HwsimSkip, fail_test, skip_with_fips, start_monitor, stop_monitor, radiotap_build +from utils import * import hwsim_utils from wpasupplicant import WpaSupplicant from tshark import run_tshark @@ -3404,3 +3404,91 @@ def test_ap_wpa2_psk_rsnxe_mismatch_ap(dev, apdev): raise Exception("Unexpected connection") if "reason=17 locally_generated=1" not in ev: raise Exception("Unexpected disconnection reason: " + ev) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_ap0(dev, apdev): + """WPA2-PSK AP and PTK rekey by AP (disabled on STA)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_ap(dev, apdev, 1, 0) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_ap1(dev, apdev): + """WPA2-PSK AP and PTK rekey by AP (start with Key ID 0)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_ap(dev, apdev, 1, 1) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_ap2(dev, apdev): + """WPA2-PSK AP and PTK rekey by AP (start with Key ID 1)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_ap(dev, apdev, 2, 1) + +def run_ap_wpa2_psk_ext_key_id_ptk_rekey_ap(dev, apdev, ap_ext_key_id, + sta_ext_key_id): + check_ext_key_id_capa(dev[0]) + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params['wpa_ptk_rekey'] = '2' + params['extended_key_id'] = str(ap_ext_key_id) + hapd = hostapd.add_ap(apdev[0], params) + check_ext_key_id_capa(hapd) + try: + dev[0].set("extended_key_id", str(sta_ext_key_id)) + dev[0].connect(ssid, psk=passphrase, scan_freq="2412") + idx = int(dev[0].request("GET last_tk_key_idx")) + expect_idx = 1 if ap_ext_key_id == 2 and sta_ext_key_id else 0 + if idx != expect_idx: + raise Exception("Unexpected Key ID for the first TK: %d (expected %d)" % (idx, expect_idx)) + ev = dev[0].wait_event(["WPA: Key negotiation completed"]) + if ev is None: + raise Exception("PTK rekey timed out") + idx = int(dev[0].request("GET last_tk_key_idx")) + expect_idx = 1 if ap_ext_key_id == 1 and sta_ext_key_id else 0 + if idx != expect_idx: + raise Exception("Unexpected Key ID for the second TK: %d (expected %d)" % (idx, expect_idx)) + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + dev[0].set("extended_key_id", "0") + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_sta0(dev, apdev): + """Extended Key ID and PTK rekey by station (Ext Key ID disabled on AP)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_sta(dev, apdev, 0) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_sta1(dev, apdev): + """Extended Key ID and PTK rekey by station (start with Key ID 0)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_sta(dev, apdev, 1) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_sta2(dev, apdev): + """Extended Key ID and PTK rekey by station (start with Key ID 1)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_sta(dev, apdev, 2) + +def run_ap_wpa2_psk_ext_key_id_ptk_rekey_sta(dev, apdev, ext_key_id): + check_ext_key_id_capa(dev[0]) + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params['extended_key_id'] = str(ext_key_id) + hapd = hostapd.add_ap(apdev[0], params) + check_ext_key_id_capa(hapd) + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase(passphrase) + + try: + dev[0].set("extended_key_id", "1") + dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", + scan_freq="2412") + idx = int(dev[0].request("GET last_tk_key_idx")) + expect_idx = 1 if ext_key_id == 2 else 0 + if idx != expect_idx: + raise Exception("Unexpected Key ID for the first TK: %d (expected %d)" % (idx, expect_idx)) + ev = dev[0].wait_event(["WPA: Key negotiation completed", + "CTRL-EVENT-DISCONNECTED"]) + if ev is None: + raise Exception("PTK rekey timed out") + if "CTRL-EVENT-DISCONNECTED" in ev: + raise Exception("Disconnect instead of rekey") + idx = int(dev[0].request("GET last_tk_key_idx")) + expect_idx = 1 if ext_key_id == 1 else 0 + if idx != expect_idx: + raise Exception("Unexpected Key ID for the second TK: %d (expected %d)" % (idx, expect_idx)) + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + dev[0].set("extended_key_id", "0") diff --git a/tests/hwsim/test_fils.py b/tests/hwsim/test_fils.py index 16fc03852..8e4df655e 100644 --- a/tests/hwsim/test_fils.py +++ b/tests/hwsim/test_fils.py @@ -17,7 +17,7 @@ import hostapd from tshark import run_tshark from wpasupplicant import WpaSupplicant import hwsim_utils -from utils import HwsimSkip, alloc_fail +from utils import * from test_erp import check_erp_capa, start_erp_as from test_ap_hs20 import ip_checksum @@ -1655,7 +1655,7 @@ def test_fils_sk_auth_mismatch(dev, apdev, params): hwsim_utils.test_connectivity(dev[0], hapd) def setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=0, wpa_group_rekey=0, - pmksa_caching=True): + pmksa_caching=True, ext_key_id=False): check_fils_capa(dev[0]) check_erp_capa(dev[0]) @@ -1673,6 +1673,8 @@ def setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=0, wpa_group_rekey=0, params['wpa_group_rekey'] = str(wpa_group_rekey) if not pmksa_caching: params['disable_pmksa_caching'] = '1' + if ext_key_id: + params['extended_key_id'] = '1' hapd = hostapd.add_ap(apdev[0]['ifname'], params) dev[0].scan_for_bss(bssid, freq=2412) @@ -2302,3 +2304,29 @@ def test_fils_sk_erp_roam_diff_akm(dev, apdev, params): raise Exception("Failed to connect to the second AP") hwsim_utils.test_connectivity(dev[0], hapd2) + +def test_fils_auth_ptk_rekey_ap_ext_key_id(dev, apdev, params): + """PTK rekeying after FILS authentication triggered by AP (Ext Key ID)""" + check_ext_key_id_capa(dev[0]) + try: + dev[0].set("extended_key_id", "1") + hapd = setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=2, + ext_key_id=True) + check_ext_key_id_capa(hapd) + idx = int(dev[0].request("GET last_tk_key_idx")) + if idx != 0: + raise Exception("Unexpected Key ID before TK rekey: %d" % idx) + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=3) + if ev is None: + raise Exception("PTK rekey timed out") + idx = int(dev[0].request("GET last_tk_key_idx")) + if idx != 1: + raise Exception("Unexpected Key ID after TK rekey: %d" % idx) + hwsim_utils.test_connectivity(dev[0], hapd) + + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1) + if ev is not None: + raise Exception("Rekeying failed - disconnected") + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + dev[0].set("extended_key_id", "0") diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index fdd95eebf..1e7e56c3a 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -89,6 +89,11 @@ def skip_with_fips(dev, reason="Not supported in FIPS mode"): if res and 'FIPS' in res: raise HwsimSkip(reason) +def check_ext_key_id_capa(dev): + res = dev.get_driver_status_field('capa.flags') + if (int(res, 0) & 0x8000000000000000) == 0: + raise HwsimSkip("Extended Key ID not supported") + def get_phy(ap, ifname=None): phy = "phy3" try: From 30ac8ddaf6a535e3a05b86a0bab9f4bc4cb34f1a Mon Sep 17 00:00:00 2001 From: Noam Shaked Date: Sun, 22 Mar 2020 15:44:05 -0700 Subject: [PATCH 0253/1105] Add QCA vendor attributes for ACS over EDMG (IEEE 802.11ay) QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED, conduct ACS for EDMG. QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL, return the EDMG channel. Signed-off-by: Noam Shaked --- src/common/qca-vendor.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index f1a065132..5d24d279d 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -1279,6 +1279,15 @@ enum qca_wlan_vendor_attr_p2p_listen_offload { * Note: If the driver supports the 6 GHz band, the event sent from the driver * includes this attribute along with * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED: Flag attribute. + * Used with command to notify the driver of EDMG request for ACS + * operation. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL: Optional (u8). + * Used with event to notify the EDMG channel number selected in ACS + * operation. + * EDMG primary channel is indicated by QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL */ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, @@ -1297,6 +1306,8 @@ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY = 13, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY = 14, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15, + QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16, + QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17, /* keep last */ QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST, From bb08be757ff12bc8068816a63c1dd84ebe8c9e40 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Sun, 28 Aug 2016 10:56:33 +0800 Subject: [PATCH 0254/1105] Extend vendor attributes to support enhanced CFR capture Enhanced channel frequency response supports capturing of channel status information based on RX. Define previous CFR as version 1 and enhanced CFR as version 2. If target supports both versions, two versions can't be enabled at same time. Extend attributes for enhanced CFR capture in enum qca_wlan_vendor_peer_cfr_capture_attr. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 223 ++++++++++++++++++++++++++++++++++------ 1 file changed, 193 insertions(+), 30 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 5d24d279d..edc8a9144 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7422,10 +7422,40 @@ enum qca_wlan_vendor_attr_roam_scan { * enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG. + * @QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL: CFR method using QoS Null frame + * @QCA_WLAN_VENDOR_CFR_QOS_NULL_WITH_PHASE: CFR method using QoS Null frame + * with phase + * @QCA_WLAN_VENDOR_CFR_PROBE_RESPONSE: CFR method using Probe Response frame */ enum qca_wlan_vendor_cfr_method { - /* CFR method using QOS Null frame */ QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL = 0, + QCA_WLAN_VENDOR_CFR_QOS_NULL_WITH_PHASE = 1, + QCA_WLAN_VENDOR_CFR_PROBE_RESPONSE = 2, +}; + +/** + * enum qca_wlan_vendor_cfr_capture_type - QCA vendor CFR capture type used by + * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE. + * @QCA_WLAN_VENDOR_CFR_DIRECT_FTM: Filter directed FTM ACK frames. + * @QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK: Filter all FTM ACK frames. + * @QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP: Filter NDPA NDP directed frames. + * @QCA_WLAN_VENDOR_CFR_TA_RA: Filter frames based on TA/RA/Subtype which + * is provided by one or more of below attributes: + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER + * @QCA_WLAN_CFR_ALL_PACKET: Filter all packets. + */ +enum qca_wlan_vendor_cfr_capture_type { + QCA_WLAN_VENDOR_CFR_DIRECT_FTM = 0, + QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK = 1, + QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP = 2, + QCA_WLAN_VENDOR_CFR_TA_RA = 3, + QCA_WLAN_VENDOR_CFR_ALL_PACKET = 4, }; /** @@ -7433,44 +7463,177 @@ enum qca_wlan_vendor_cfr_method { * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG to configure peer * Channel Frequency Response capture parameters and enable periodic CFR * capture. + * + * @QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR: Required (6-byte MAC address) + * MAC address of peer. This is for CFR version 1 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE: Required (flag) + * Enable peer CFR capture. This attribute is mandatory to enable peer CFR + * capture. If this attribute is not present, peer CFR capture is disabled. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH: Required (u8) + * BW of measurement, attribute uses the values in enum nl80211_chan_width + * Supported values: 20, 40, 80, 80+80, 160. + * Note that all targets may not support all bandwidths. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY: Required (u32) + * Periodicity of CFR measurement in milliseconds. + * Periodicity should be a multiple of Base timer. + * Current Base timer value supported is 10 milliseconds (default). + * 0 for one shot capture. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD: Required (u8) + * Method used to capture Channel Frequency Response. + * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE: Required (flag) + * Enable periodic CFR capture. + * This attribute is mandatory for version 1 to enable Periodic CFR capture. + * If this attribute is not present, periodic CFR capture is disabled. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION: Required (u8) + * Value is 1 or 2 since there are two versions of CFR capture. Two versions + * can't be enabled at same time. This attribute is mandatory if target + * support both versions and use one of them. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP: Required (u32) + * This attribute is mandatory for version 2 if + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY is used. + * Bits 15:0 bitfield indicates which group is to be enabled. + * Bits 31:16 Reserved for future use. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION: Optional (u32) + * CFR capture duration in microsecond. This attribute is mandatory for + * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL: Optional (u32) + * CFR capture interval in microsecond. This attribute is mandatory for + * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE: Required (u32) + * CFR capture type is defined in enum qca_wlan_vendor_cfr_capture_type. + * This attribute is mandatory for version 2. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK: Optional (u64) + * Bitfield indicating which user in the current UL MU transmissions are + * enabled for CFR capture. Bits 36 to 0 indicate user indexes for 37 users in + * a UL MU transmission. If bit 0 is set, the CFR capture will happen for user + * index 0 in the current UL MU transmission. If bits 0 and 2 are set, CFR + * capture for UL MU TX corresponds to user indices 0 and 2. Bits 63:37 are + * reserved for future use. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT: Optional (u32) + * Indicates the number of consecutive RX frames to be skipped before CFR + * capture is enabled again. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE: Nested attribute containing + * one or more %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY attributes. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY: Nested attribute containing + * the following group attributes: + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER: Required (u32) + * Target supports multiple groups for some configurations. The group number + * can be any value between 0 and 15. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA: Optional (6-byte MAC address) + * Transmitter address which is used to filter frames. This MAC address takes + * effect with QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK. This is for CFR + * version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA: Optional (6-byte MAC address) + * Receiver address which is used to filter frames. This MAC address takes + * effect with QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK. This is for CFR + * version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK: Optional (6-byte MAC address) + * Mask of transmitter address which is used to filter frames. This is for CFR + * version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK: Optional (6-byte MAC address) + * Mask of receiver address which is used to filter frames. This is for CFR + * version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS: Optional (u32) + * Indicates frames with a specific NSS will be filtered for CFR capture. + * This is for CFR version 2 only. This is a bitmask. Bits 7:0 request CFR + * capture to be done for frames matching the NSS specified within this bitmask. + * Bits 31:8 are reserved for future use. Bits 7:0 map to NSS: + * bit 0 : NSS 1 + * bit 1 : NSS 2 + * ... + * bit 7 : NSS 8 + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW: Optional (u32) + * Indicates frames with a specific bandwidth will be filtered for CFR capture. + * This is for CFR version 2 only. This is a bitmask. Bits 4:0 request CFR + * capture to be done for frames matching the bandwidths specified within this + * bitmask. Bits 31:5 are reserved for future use. Bits 4:0 map to bandwidth + * numerated in enum nl80211_band (although not all bands may be supported + * by a given device). + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER: Optional (u32) + * Management frames matching the subtype filter categories will be filtered in + * by MAC for CFR capture. This is a bitmask in which each bit represents the + * corresponding Management frame subtype value per IEEE Std 802.11-2016, + * 9.2.4.1.3 Type and Subtype subfields. For example, Beacon frame control type + * is 8 and its value is 1 << 8 = 0x100. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER: Optional (u32) + * Control frames matching the subtype filter categories will be filtered in by + * MAC for CFR capture. This is a bitmask in which each bit represents the + * corresponding Control frame subtype value per IEEE Std 802.11-2016, + * 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER: Optional (u32) + * Data frames matching the subtype filter categories will be filtered in by + * MAC for CFR capture. This is a bitmask in which each bit represents the + * corresponding Data frame subtype value per IEEE Std 802.11-2016, + * 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only. */ enum qca_wlan_vendor_peer_cfr_capture_attr { QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0, - /* 6-byte MAC address of the peer. - * This attribute is mandatory. - */ QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR = 1, - /* Enable peer CFR Capture, flag attribute. - * This attribute is mandatory to enable peer CFR capture. - * If this attribute is not present, peer CFR capture is disabled. - */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE = 2, - /* BW of measurement, attribute uses the values in enum nl80211_chan_width - * Supported values: 20, 40, 80, 80+80, 160. - * Note that all targets may not support all bandwidths. - * u8 attribute. This attribute is mandatory if attribute - * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. - */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH = 3, - /* Periodicity of CFR measurement in msec. - * Periodicity should be a multiple of Base timer. - * Current Base timer value supported is 10 msecs (default). - * 0 for one shot capture. u32 attribute. - * This attribute is mandatory if attribute - * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. - */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY = 4, - /* Method used to capture Channel Frequency Response. - * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method. - * u8 attribute. This attribute is mandatory if attribute - * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. - */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD = 5, - /* Enable periodic CFR capture, flag attribute. - * This attribute is mandatory to enable Periodic CFR capture. - * If this attribute is not present, periodic CFR capture is disabled. - */ QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE = 6, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION = 7, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP = 8, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION = 9, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL = 10, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE = 11, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK = 12, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT = 13, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE = 14, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY = 15, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER = 16, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA = 17, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA = 18, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK = 19, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK = 20, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS = 21, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW = 22, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25, /* Keep last */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST, From 8e467e3cf4214d88655b2aa92f27ba5361186d7a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 23 Mar 2020 17:58:43 +0200 Subject: [PATCH 0255/1105] wlantest: Check for zero TK even when the real PTK is not known This makes it easier to analyze certain encryption issues. Also print out an error at the default INFO debug verbosity with the frame number. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index 1ee25a645..91c0144f8 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -339,10 +339,10 @@ static void rx_data_bss_prot(struct wlantest *wt, struct wlantest_sta *sta, *sta2; int keyid; u16 fc = le_to_host16(hdr->frame_control); - u8 *decrypted; + u8 *decrypted = NULL; size_t dlen; int tid; - u8 pn[6], *rsc; + u8 pn[6], *rsc = NULL; struct wlantest_tdls *tdls = NULL, *found; const u8 *tk = NULL; int ptk_iter_done = 0; @@ -424,8 +424,14 @@ static void rx_data_bss_prot(struct wlantest *wt, (!sta->ptk_set && sta->pairwise_cipher != WPA_CIPHER_WEP40)) && tk == NULL) { add_note(wt, MSG_MSGDUMP, "No PTK known to decrypt the frame"); - if (dl_list_empty(&wt->ptk)) + if (dl_list_empty(&wt->ptk)) { + if (len >= 4 && sta) { + keyid = data[3] >> 6; + goto check_zero_tk; + } return; + } + try_ptk_iter = 1; } @@ -578,16 +584,25 @@ skip_replay_det: add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs"); } } +check_zero_tk: if (!decrypted) { struct wpa_ptk zero_ptk; + int old_debug_level = wpa_debug_level; os_memset(&zero_ptk, 0, sizeof(zero_ptk)); zero_ptk.tk_len = wpa_cipher_key_len(sta->pairwise_cipher); + wpa_debug_level = MSG_ERROR; decrypted = try_ptk(sta->pairwise_cipher, &zero_ptk, hdr, data, len, &dlen); + wpa_debug_level = old_debug_level; if (decrypted) { add_note(wt, MSG_DEBUG, "Frame was encrypted with zero TK"); + wpa_printf(MSG_INFO, "Zero TK used in frame #%u: A2=" + MACSTR " seq=%u", + wt->frame_num, MAC2STR(hdr->addr2), + WLAN_GET_SEQ_SEQ( + le_to_host16(hdr->seq_ctrl))); write_decrypted_note(wt, decrypted, zero_ptk.tk, zero_ptk.tk_len, keyid); } @@ -597,7 +612,7 @@ skip_replay_det: const u8 *peer_addr = NULL; if (!(fc & (WLAN_FC_FROMDS | WLAN_FC_TODS))) peer_addr = hdr->addr1; - if (!replay) + if (!replay && rsc) os_memcpy(rsc, pn, 6); rx_data_process(wt, bss->bssid, sta->addr, dst, src, decrypted, dlen, 1, peer_addr); From 1e8ea0833dcb0dec7e02a407fb15abd5bcd08c5a Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 23 Mar 2020 14:13:15 +0100 Subject: [PATCH 0256/1105] HE: Add HE support to hostapd_set_freq_params() The parameters that need to be applied are symmetric to those of VHT, however the validation code needs to be tweaked to check the HE capabilities. Signed-off-by: Shashidhar Lakkavalli Signed-off-by: John Crispin --- src/common/hw_features_common.c | 73 +++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 12 deletions(-) diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c index 4f1c4935a..f6c67a375 100644 --- a/src/common/hw_features_common.c +++ b/src/common/hw_features_common.c @@ -475,7 +475,67 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, return 0; } - if (data->vht_enabled) switch (oper_chwidth) { + if (data->he_enabled) switch (oper_chwidth) { + case CHANWIDTH_USE_HT: + if (mode == HOSTAPD_MODE_IEEE80211G && sec_channel_offset) { + if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) { + wpa_printf(MSG_ERROR, + "40 MHz channel width is not supported in 2.4 GHz"); + return -1; + } + break; + } + /* fall through */ + case CHANWIDTH_80MHZ: + if (mode == HOSTAPD_MODE_IEEE80211A) { + if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) { + wpa_printf(MSG_ERROR, + "40/80 MHz channel width is not supported in 5/6 GHz"); + return -1; + } + } + break; + case CHANWIDTH_80P80MHZ: + if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) { + wpa_printf(MSG_ERROR, + "80+80 MHz channel width is not supported in 5/6 GHz"); + return -1; + } + break; + case CHANWIDTH_160MHZ: + if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)) { + wpa_printf(MSG_ERROR, + "160 MHz channel width is not supported in 5 / 6GHz"); + return -1; + } + break; + } else if (data->vht_enabled) switch (oper_chwidth) { + case CHANWIDTH_USE_HT: + break; + case CHANWIDTH_80P80MHZ: + if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) { + wpa_printf(MSG_ERROR, + "80+80 channel width is not supported!"); + return -1; + } + /* fall through */ + case CHANWIDTH_80MHZ: + break; + case CHANWIDTH_160MHZ: + if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | + VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) { + wpa_printf(MSG_ERROR, + "160 MHz channel width is not supported!"); + return -1; + } + break; + } + + if (data->he_enabled || data->vht_enabled) switch (oper_chwidth) { case CHANWIDTH_USE_HT: if (center_segment1 || (center_segment0 != 0 && @@ -484,11 +544,6 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, return -1; break; case CHANWIDTH_80P80MHZ: - if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) { - wpa_printf(MSG_ERROR, - "80+80 channel width is not supported!"); - return -1; - } if (center_segment1 == center_segment0 + 4 || center_segment1 == center_segment0 - 4) return -1; @@ -533,12 +588,6 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, break; case CHANWIDTH_160MHZ: data->bandwidth = 160; - if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | - VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) { - wpa_printf(MSG_ERROR, - "160MHZ channel width is not supported!"); - return -1; - } if (center_segment1) return -1; if (!sec_channel_offset) From 00f6a27628ac571519bf83f44987816510532dd7 Mon Sep 17 00:00:00 2001 From: Noam Shaked Date: Mon, 9 Mar 2020 18:16:02 -0700 Subject: [PATCH 0257/1105] nl80211: Fix offloaded ACS regression for the 60 GHz band Addition of chan_2ghz_or_5ghz_to_freq() broke 60 GHz ACS, because it assumes reported ACS channel is on either 2.4 or 5 GHz band. Fix this by converting chan_2ghz_or_5ghz_to_freq() to a more generic chan_to_freq(). The new function uses hw_mode to support 60 GHz. Fixes: 41cac481a889 ("ACS: Use frequency params in ACS (offload) completed event interface") Signed-off-by: Noam Shaked --- src/drivers/driver_nl80211_event.c | 93 +++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 28 deletions(-) diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index b634a2d12..49d81d785 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1753,8 +1753,41 @@ static enum hostapd_hw_mode get_qca_hw_mode(u8 hw_mode) } -static unsigned int chan_2ghz_or_5ghz_to_freq(u8 chan) +static unsigned int chan_to_freq(struct wpa_driver_nl80211_data *drv, + u8 chan, enum hostapd_hw_mode hw_mode) { + if (hw_mode == NUM_HOSTAPD_MODES) { + /* For drivers that do not report ACS_HW_MODE */ + u16 num_modes, flags; + struct hostapd_hw_modes *modes; + u8 dfs_domain; + int i; + + modes = nl80211_get_hw_feature_data(drv->first_bss, &num_modes, + &flags, &dfs_domain); + if (!modes) { + wpa_printf(MSG_DEBUG, + "nl80211: Fetching hardware mode failed"); + goto try_2_4_or_5; + } + if (num_modes == 1) + hw_mode = modes[0].mode; + + for (i = 0; i < num_modes; i++) { + os_free(modes[i].channels); + os_free(modes[i].rates); + } + + os_free(modes); + } + + if (hw_mode == HOSTAPD_MODE_IEEE80211AD) { + if (chan >= 1 && chan <= 6) + return 56160 + (2160 * chan); + return 0; + } + +try_2_4_or_5: if (chan >= 1 && chan <= 13) return 2407 + 5 * chan; if (chan == 14) @@ -1785,34 +1818,8 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv, return; os_memset(&event, 0, sizeof(event)); - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]) { - event.acs_selected_channels.pri_freq = nla_get_u32( - tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]); - } else { - chan = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]); - event.acs_selected_channels.pri_freq = - chan_2ghz_or_5ghz_to_freq(chan); - } + event.acs_selected_channels.hw_mode = NUM_HOSTAPD_MODES; - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]) { - event.acs_selected_channels.sec_freq = nla_get_u32( - tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]); - } else { - chan = nla_get_u8( - tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]); - event.acs_selected_channels.sec_freq = - chan_2ghz_or_5ghz_to_freq(chan); - } - - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]) - event.acs_selected_channels.vht_seg0_center_ch = - nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]); - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]) - event.acs_selected_channels.vht_seg1_center_ch = - nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]); - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) - event.acs_selected_channels.ch_width = - nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]); if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) { u8 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]); @@ -1827,6 +1834,36 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv, } } + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]) { + event.acs_selected_channels.pri_freq = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]); + } else { + chan = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]); + event.acs_selected_channels.pri_freq = + chan_to_freq(drv, chan, + event.acs_selected_channels.hw_mode); + } + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]) { + event.acs_selected_channels.sec_freq = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]); + } else { + chan = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]); + event.acs_selected_channels.sec_freq = + chan_to_freq(drv, chan, + event.acs_selected_channels.hw_mode); + } + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]) + event.acs_selected_channels.vht_seg0_center_ch = + nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]); + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]) + event.acs_selected_channels.vht_seg1_center_ch = + nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]); + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) + event.acs_selected_channels.ch_width = + nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]); wpa_printf(MSG_INFO, "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d", event.acs_selected_channels.pri_freq, From 634bc4e6df555a1c128b055d6b05ee20b90456e5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 24 Mar 2020 12:33:31 +0200 Subject: [PATCH 0258/1105] tests: sigma_dut sta_scan ShortSSID Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 98679373b..eb3bf0821 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3005,6 +3005,34 @@ def test_sigma_dut_sta_scan_ssid_bssid(dev, apdev): finally: stop_sigma_dut(sigma) +def test_sigma_dut_sta_scan_short_ssid(dev, apdev): + """sigma_dut sta_scan ShortSSID""" + dev[0].flush_scan_cache() + ssid = "test-short-ssid-list" + hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, + "ignore_broadcast_ssid": "1"}) + bssid = apdev[0]['bssid'] + payload = struct.pack('>L', binascii.crc32(ssid.encode())) + val = binascii.hexlify(payload).decode() + sigma = start_sigma_dut(dev[0].ifname) + found = False + try: + cmd = "sta_scan,Interface,%s,ChnlFreq,2412,ShortSSID,%s" % (dev[0].ifname, val) + for i in range(10): + sigma_dut_cmd_check(cmd, timeout=5) + ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"]) + if ev is None: + raise Exception("Scan did not complete") + if bssid in dev[0].request("SCAN_RESULTS"): + found = True + break + finally: + stop_sigma_dut(sigma) + dev[0].request("VENDOR_ELEM_REMOVE 14 *") + + if not found: + raise Exception("AP not found in scan results") + def test_sigma_dut_ap_osen(dev, apdev, params): """sigma_dut controlled AP with OSEN""" logdir = os.path.join(params['logdir'], From e520de8dbed589840edacc52276c1a07db64cffc Mon Sep 17 00:00:00 2001 From: Noam Shaked Date: Mon, 23 Mar 2020 17:19:36 -0700 Subject: [PATCH 0259/1105] Add ACS support for 60 GHz channel bonding hostapd will trigger EDMG auto channel selection by setting QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED. The 60 GHz driver will be called to start an auto channel selection and will return the primary channel and the EDMG channel. Signed-off-by: Noam Shaked --- src/ap/ap_drv_ops.c | 1 + src/ap/drv_callbacks.c | 2 ++ src/drivers/driver.h | 5 +++++ src/drivers/driver_nl80211.c | 8 +++++--- src/drivers/driver_nl80211_event.c | 8 ++++++-- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 0f5e829ff..1aa2ab038 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -938,6 +938,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd) } params.freq_list = freq_list; + params.edmg_enabled = hapd->iface->conf->enable_edmg; params.ht_enabled = !!(hapd->iface->conf->ieee80211n); params.ht40_enabled = !!(hapd->iface->conf->ht_capab & diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 2091385cd..98729f423 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1008,6 +1008,8 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, goto out; } + hapd->iconf->edmg_channel = acs_res->edmg_channel; + if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) { /* set defaults for backwards compatibility */ hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0); diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 78a3387da..39c7f9cb9 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2329,6 +2329,9 @@ struct drv_acs_params { /* ACS frequency list info */ const int *freq_list; + + /* Indicates whether EDMG is enabled */ + int edmg_enabled; }; struct wpa_bss_trans_info { @@ -5724,6 +5727,7 @@ union wpa_event_data { * struct acs_selected_channels - Data for EVENT_ACS_CHANNEL_SELECTED * @pri_freq: Selected primary frequency * @sec_freq: Selected secondary frequency + * @edmg_channel: Selected EDMG channel * @vht_seg0_center_ch: VHT mode Segment0 center channel * The value is the index of the channel center frequency for * 20 MHz, 40 MHz, and 80 MHz channels. The value is the center @@ -5742,6 +5746,7 @@ union wpa_event_data { struct acs_selected_channels { unsigned int pri_freq; unsigned int sec_freq; + u8 edmg_channel; u8 vht_seg0_center_ch; u8 vht_seg1_center_ch; u16 ch_width; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index c071cc0e0..5f2b5651c 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -10436,16 +10436,18 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params) nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH, params->ch_width) || add_acs_ch_list(msg, params->freq_list) || - add_acs_freq_list(msg, params->freq_list)) { + add_acs_freq_list(msg, params->freq_list) || + (params->edmg_enabled && + nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED))) { nlmsg_free(msg); return -ENOBUFS; } nla_nest_end(msg, data); wpa_printf(MSG_DEBUG, - "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d", + "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d EDMG: %d", params->hw_mode, params->ht_enabled, params->ht40_enabled, - params->vht_enabled, params->ch_width); + params->vht_enabled, params->ch_width, params->edmg_enabled); ret = send_and_recv_msgs(drv, msg, NULL, NULL); if (ret) { diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 49d81d785..d4ca2eb29 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1855,6 +1855,9 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv, event.acs_selected_channels.hw_mode); } + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL]) + event.acs_selected_channels.edmg_channel = + nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL]); if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]) event.acs_selected_channels.vht_seg0_center_ch = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]); @@ -1865,13 +1868,14 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv, event.acs_selected_channels.ch_width = nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]); wpa_printf(MSG_INFO, - "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d", + "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d EDMGCH: %d", event.acs_selected_channels.pri_freq, event.acs_selected_channels.sec_freq, event.acs_selected_channels.ch_width, event.acs_selected_channels.vht_seg0_center_ch, event.acs_selected_channels.vht_seg1_center_ch, - event.acs_selected_channels.hw_mode); + event.acs_selected_channels.hw_mode, + event.acs_selected_channels.edmg_channel); /* Ignore ACS channel list check for backwards compatibility */ From a163bfe2bc1afae06ccc2a86e679750fddcdfdd2 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Mon, 23 Mar 2020 21:13:13 +0800 Subject: [PATCH 0260/1105] Change CFR attributes from required to optional Some CFR attributes are used frequently with conditions, so change them from required to optional. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index edc8a9144..6b5d7bff6 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7464,21 +7464,21 @@ enum qca_wlan_vendor_cfr_capture_type { * Channel Frequency Response capture parameters and enable periodic CFR * capture. * - * @QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR: Required (6-byte MAC address) + * @QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR: Optional (6-byte MAC address) * MAC address of peer. This is for CFR version 1 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE: Required (flag) * Enable peer CFR capture. This attribute is mandatory to enable peer CFR * capture. If this attribute is not present, peer CFR capture is disabled. * - * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH: Required (u8) + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH: Optional (u8) * BW of measurement, attribute uses the values in enum nl80211_chan_width * Supported values: 20, 40, 80, 80+80, 160. * Note that all targets may not support all bandwidths. * This attribute is mandatory for version 1 if attribute * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. * - * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY: Required (u32) + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY: Optional (u32) * Periodicity of CFR measurement in milliseconds. * Periodicity should be a multiple of Base timer. * Current Base timer value supported is 10 milliseconds (default). @@ -7486,23 +7486,23 @@ enum qca_wlan_vendor_cfr_capture_type { * This attribute is mandatory for version 1 if attribute * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. * - * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD: Required (u8) + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD: Optional (u8) * Method used to capture Channel Frequency Response. * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method. * This attribute is mandatory for version 1 if attribute * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. * - * @QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE: Required (flag) + * @QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE: Optional (flag) * Enable periodic CFR capture. * This attribute is mandatory for version 1 to enable Periodic CFR capture. * If this attribute is not present, periodic CFR capture is disabled. * - * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION: Required (u8) + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION: Optional (u8) * Value is 1 or 2 since there are two versions of CFR capture. Two versions * can't be enabled at same time. This attribute is mandatory if target * support both versions and use one of them. * - * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP: Required (u32) + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP: Optional (u32) * This attribute is mandatory for version 2 if * QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY is used. * Bits 15:0 bitfield indicates which group is to be enabled. @@ -7516,7 +7516,7 @@ enum qca_wlan_vendor_cfr_capture_type { * CFR capture interval in microsecond. This attribute is mandatory for * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION is used. * - * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE: Required (u32) + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE: Optional (u32) * CFR capture type is defined in enum qca_wlan_vendor_cfr_capture_type. * This attribute is mandatory for version 2. * @@ -7548,7 +7548,7 @@ enum qca_wlan_vendor_cfr_capture_type { * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER * - * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER: Required (u32) + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER: Optional (u32) * Target supports multiple groups for some configurations. The group number * can be any value between 0 and 15. This is for CFR version 2 only. * From a72ec4c221fa8285ce597c45d028c1e35ecd8493 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Tue, 24 Mar 2020 23:46:43 +0800 Subject: [PATCH 0261/1105] Add addition CFR capture type to filter all NDPA NDP frames Add QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL in enum qca_wlan_vendor_cfr_capture_type. This capture type requests all NDPA NDP frames to be filtered. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 6b5d7bff6..02aa9fbcc 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7449,6 +7449,7 @@ enum qca_wlan_vendor_cfr_method { * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER * @QCA_WLAN_CFR_ALL_PACKET: Filter all packets. + * @QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL: Filter all NDPA NDP frames. */ enum qca_wlan_vendor_cfr_capture_type { QCA_WLAN_VENDOR_CFR_DIRECT_FTM = 0, @@ -7456,6 +7457,7 @@ enum qca_wlan_vendor_cfr_capture_type { QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP = 2, QCA_WLAN_VENDOR_CFR_TA_RA = 3, QCA_WLAN_VENDOR_CFR_ALL_PACKET = 4, + QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL = 5, }; /** From 3eb9ddc65847e102cbe8c418232ef9c8cda204b4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 00:06:50 +0200 Subject: [PATCH 0262/1105] Transition Disable KDE definitions Define the OUI Type and bitmap values for Transition Disable KDE. These will be shared by both the AP and STA implementations. Signed-off-by: Jouni Malinen --- src/common/wpa_common.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 1a9a4105f..bcdf160b6 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -113,6 +113,7 @@ WPA_CIPHER_BIP_CMAC_256) #define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4) #define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5) +#define WFA_KEY_DATA_TRANSITION_DISABLE RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x20) #define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) @@ -344,6 +345,12 @@ struct rsn_rdie { le16 status_code; } STRUCT_PACKED; +/* WFA Transition Disable KDE (using OUI_WFA) */ +/* Transition Disable Bitmap bits */ +#define TRANSITION_DISABLE_WPA3_PERSONAL BIT(0) +#define TRANSITION_DISABLE_SAE_PK BIT(1) +#define TRANSITION_DISABLE_WPA3_ENTERPRISE BIT(2) +#define TRANSITION_DISABLE_ENHANCED_OPEN BIT(3) #ifdef _MSC_VER #pragma pack(pop) From 82cc0b0cc2dce13064e9095cf32f454208477a87 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 00:08:26 +0200 Subject: [PATCH 0263/1105] Allow hostapd AP to advertise Transition Disable KDE The new hostapd configuration parameter transition_disable can now be used to configure the AP to advertise that use of a transition mode is disabled. This allows stations to automatically disable transition mode by disabling less secure network profile parameters. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 ++ hostapd/hostapd.conf | 17 +++++++++++++++++ src/ap/ap_config.h | 2 ++ src/ap/wpa_auth.c | 25 ++++++++++++++++++++++--- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 1 + 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 2bc0679b5..d53436751 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4462,6 +4462,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->rssi_reject_assoc_timeout = atoi(pos); } else if (os_strcmp(buf, "pbss") == 0) { bss->pbss = atoi(pos); + } else if (os_strcmp(buf, "transition_disable") == 0) { + bss->transition_disable = strtol(pos, NULL, 16); #ifdef CONFIG_AIRTIME_POLICY } else if (os_strcmp(buf, "airtime_mode") == 0) { int val = atoi(pos); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index b09f6ed0a..6a8c2c5cf 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1905,6 +1905,23 @@ own_ip_addr=127.0.0.1 # default: 30 TUs (= 30.72 milliseconds) #fils_hlp_wait_time=30 +# Transition Disable indication +# The AP can notify authenticated stations to disable transition mode in their +# network profiles when the network has completed transition steps, i.e., once +# sufficiently large number of APs in the ESS have been updated to support the +# more secure alternative. When this indication is used, the stations are +# expected to automatically disable transition mode and less secure security +# options. This includes use of WEP, TKIP (including use of TKIP as the group +# cipher), and connections without PMF. +# Bitmap bits: +# bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK and only +# allow SAE to be used) +# bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK) +# bit 2 (0x04): WPA3-Enterprise (move to requiring PMF) +# bit 3 (0x08): Enhanced Open (disable use of open network; require OWE) +# (default: 0 = do not include Transition Disable KDE) +#transition_disable=0x01 + ##### IEEE 802.11r configuration ############################################## # Mobility Domain identifier (dot11FTMobilityDomainID, MDID) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 5f4665c07..f24257091 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -756,6 +756,8 @@ struct hostapd_bss_config { u8 send_probe_response; + u8 transition_disable; + #define BACKHAUL_BSS 1 #define FRONTHAUL_BSS 2 int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 6512c0194..1e3afd6f2 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2712,8 +2712,13 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, u8 *gtk, dummy_gtk[32]; size_t gtk_len; struct wpa_group *gsm; + size_t plain_len; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; - plain = wpabuf_alloc(1000 + ieee80211w_kde_len(sm)); + plain_len = 1000 + ieee80211w_kde_len(sm); + if (conf->transition_disable) + plain_len += 2 + RSN_SELECTOR_LEN + 1; + plain = wpabuf_alloc(plain_len); if (!plain) return NULL; @@ -2766,6 +2771,13 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, tmp2 = ieee80211w_kde_add(sm, tmp); wpabuf_put(plain, tmp2 - tmp); + if (conf->transition_disable) { + tmp = wpabuf_put(plain, 0); + tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE, + &conf->transition_disable, 1, NULL, 0); + wpabuf_put(plain, tmp2 - tmp); + } + *len = (u8 *) wpabuf_put(plain, 0) - len - 1; #ifdef CONFIG_OCV @@ -3276,6 +3288,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) int secure, gtkidx, encr = 0; u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL; u8 hdr[2]; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; @@ -3400,6 +3413,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (WPA_GET_BE32(sm->ip_addr) > 0) kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; #endif /* CONFIG_P2P */ + + if (conf->transition_disable) + kde_len += 2 + RSN_SELECTOR_LEN + 1; + kde = os_malloc(kde_len); if (kde == NULL) goto done; @@ -3442,9 +3459,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { int res; - struct wpa_auth_config *conf; - conf = &sm->wpa_auth->conf; if (sm->assoc_resp_ftie && kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { os_memcpy(pos, sm->assoc_resp_ftie, @@ -3493,6 +3508,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } #endif /* CONFIG_P2P */ + if (conf->transition_disable) + pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE, + &conf->transition_disable, 1, NULL, 0); + wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 528516195..955445209 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -251,6 +251,7 @@ struct wpa_auth_config { #endif /* CONFIG_FILS */ int sae_pwe; int owe_ptk_workaround; + u8 transition_disable; }; typedef enum { diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 70d32818a..41df213b9 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -195,6 +195,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, #ifdef CONFIG_OWE wconf->owe_ptk_workaround = conf->owe_ptk_workaround; #endif /* CONFIG_OWE */ + wconf->transition_disable = conf->transition_disable; } From 9d1857cf35c8b52c21df672bd277058af542edce Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 00:10:16 +0200 Subject: [PATCH 0264/1105] Process Transition Disable KDE in station mode Check whether the Transition Disable KDE is received from an authenticated AP and if so, whether it contains valid indication for disabling a transition mode. If that is the case, update the local network profile by removing the less secure options. Signed-off-by: Jouni Malinen --- src/common/wpa_common.c | 10 ++++++ src/common/wpa_common.h | 2 ++ src/common/wpa_ctrl.h | 3 ++ src/rsn_supp/wpa.c | 5 +++ src/rsn_supp/wpa.h | 1 + src/rsn_supp/wpa_i.h | 6 ++++ wpa_supplicant/wpas_glue.c | 68 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 95 insertions(+) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index aaeb13023..128474302 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2784,6 +2784,16 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie) return 0; } + if (pos[1] >= RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_TRANSITION_DISABLE) { + ie->transition_disable = pos + 2 + RSN_SELECTOR_LEN; + ie->transition_disable_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, + "WPA: Transition Disable KDE in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + return 0; } diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index bcdf160b6..da58159e4 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -516,6 +516,8 @@ struct wpa_eapol_ie_parse { size_t ftie_len; const u8 *ip_addr_req; const u8 *ip_addr_alloc; + const u8 *transition_disable; + size_t transition_disable_len; const u8 *oci; size_t oci_len; const u8 *osen; diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 12906708a..7471f0d15 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -380,6 +380,9 @@ extern "C" { #define WDS_STA_INTERFACE_ADDED "WDS-STA-INTERFACE-ADDED " #define WDS_STA_INTERFACE_REMOVED "WDS-STA-INTERFACE-REMOVED " +/* Transition mode disabled indication - followed by bitmap */ +#define TRANSITION_DISABLE "TRANSITION-DISABLE " + #ifndef BIT #define BIT(x) (1U << (x)) #endif diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 14fe0846d..1c8966422 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1771,6 +1771,8 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, sm->cur_pmksa = sa; } + if (ie.transition_disable) + wpa_sm_transition_disable(sm, ie.transition_disable[0]); sm->msg_3_of_4_ok = 1; return; @@ -4809,6 +4811,9 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) sm->fils_completed = 1; forced_memzero(&gd, sizeof(gd)); + if (kde.transition_disable) + wpa_sm_transition_disable(sm, kde.transition_disable[0]); + return 0; fail: forced_memzero(&gd, sizeof(gd)); diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 02b5df883..1f22f2f26 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -85,6 +85,7 @@ struct wpa_sm_ctx { void (*fils_hlp_rx)(void *ctx, const u8 *dst, const u8 *src, const u8 *pkt, size_t pkt_len); int (*channel_info)(void *ctx, struct wpa_channel_info *ci); + void (*transition_disable)(void *ctx, u8 bitmap); }; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 5fd70a498..5178c28cb 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -426,6 +426,12 @@ static inline int wpa_sm_channel_info(struct wpa_sm *sm, return sm->ctx->channel_info(sm->ctx->ctx, ci); } +static inline void wpa_sm_transition_disable(struct wpa_sm *sm, u8 bitmap) +{ + if (sm->ctx->transition_disable) + sm->ctx->transition_disable(sm->ctx->ctx, bitmap); +} + int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk, int ver, const u8 *dest, u16 proto, diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index a3049daf5..200a439cb 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1238,6 +1238,73 @@ static int wpa_supplicant_channel_info(void *_wpa_s, return wpa_drv_channel_info(wpa_s, ci); } + +static void disable_wpa_wpa2(struct wpa_ssid *ssid) +{ + ssid->proto &= ~WPA_PROTO_WPA; + ssid->proto |= WPA_PROTO_RSN; + ssid->key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256); + ssid->group_cipher &= ~WPA_CIPHER_TKIP; + if (!(ssid->group_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | + WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256))) + ssid->group_cipher |= WPA_CIPHER_CCMP; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; +} + + +static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap) +{ + struct wpa_supplicant *wpa_s = _wpa_s; + struct wpa_ssid *ssid; + int changed = 0; + + wpa_msg(wpa_s, MSG_INFO, TRANSITION_DISABLE "%02x", bitmap); + + ssid = wpa_s->current_ssid; + if (!ssid) + return; + + if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) && + wpa_key_mgmt_sae(wpa_s->key_mgmt) && + (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && + (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + wpa_printf(MSG_DEBUG, + "WPA3-Personal transition mode disabled based on AP notification"); + disable_wpa_wpa2(ssid); + changed = 1; + } + + if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) && + wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && + (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_IEEE8021X_SHA256)) && + (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + disable_wpa_wpa2(ssid); + changed = 1; + } + + if ((bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) && + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && + (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + !ssid->owe_only) { + ssid->owe_only = 1; + changed = 1; + } + + if (!changed) + return; + +#ifndef CONFIG_NO_CONFIG_WRITE + if (wpa_s->conf->update_config && + wpa_config_write(wpa_s->confname, wpa_s->conf)) + wpa_printf(MSG_DEBUG, "Failed to update configuration"); +#endif /* CONFIG_NO_CONFIG_WRITE */ +} + #endif /* CONFIG_NO_WPA */ @@ -1290,6 +1357,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk; ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx; ctx->channel_info = wpa_supplicant_channel_info; + ctx->transition_disable = wpa_supplicant_transition_disable; wpa_s->wpa = wpa_sm_init(ctx); if (wpa_s->wpa == NULL) { From 96686e637cf093d50b4fa5a8cdb6b75663eacb24 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 00:18:06 +0200 Subject: [PATCH 0265/1105] wpa_supplicant AP mode configuration for Transition Disable KDE Allow AP mode network profile in wpa_supplicant to be configured to advertise Transition Disable DKE. Signed-off-by: Jouni Malinen --- wpa_supplicant/ap.c | 2 ++ wpa_supplicant/config.c | 1 + wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 20 ++++++++++++++++++++ 4 files changed, 24 insertions(+) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index ee7c755b5..624168205 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -607,6 +607,8 @@ no_wps: bss->ftm_responder = wpa_s->conf->ftm_responder; bss->ftm_initiator = wpa_s->conf->ftm_initiator; + bss->transition_disable = ssid->transition_disable; + return 0; } diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 30801abd9..e86fd7f81 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2577,6 +2577,7 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(multi_ap_backhaul_sta, 0, 1) }, { INT_RANGE(ft_eap_pmksa_caching, 0, 1) }, { INT_RANGE(beacon_prot, 0, 1) }, + { INT_RANGE(transition_disable, 0, 255) }, }; #undef OFFSET diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index e77cbca4f..74068d66c 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -935,6 +935,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(multi_ap_backhaul_sta); INT(ft_eap_pmksa_caching); INT(beacon_prot); + INT(transition_disable); #ifdef CONFIG_HT_OVERRIDES INT_DEF(disable_ht, DEFAULT_DISABLE_HT); INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 24c7a3d9b..618145e8b 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -1070,6 +1070,26 @@ struct wpa_ssid { * enabled. */ int beacon_prot; + + /** + * transition_disable - Transition Disable indication + * The AP can notify authenticated stations to disable transition mode + * in their network profiles when the network has completed transition + * steps, i.e., once sufficiently large number of APs in the ESS have + * been updated to support the more secure alternative. When this + * indication is used, the stations are expected to automatically + * disable transition mode and less secure security options. This + * includes use of WEP, TKIP (including use of TKIP as the group + * cipher), and connections without PMF. + * Bitmap bits: + * bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK + * and only allow SAE to be used) + * bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK) + * bit 2 (0x04): WPA3-Enterprise (move to requiring PMF) + * bit 3 (0x08): Enhanced Open (disable use of open network; require + * OWE) + */ + u8 transition_disable; }; #endif /* CONFIG_SSID_H */ From 5cf5680e5c13a80df554c034e54cd1bad72c2c6c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 00:11:35 +0200 Subject: [PATCH 0266/1105] tests: Transition disable Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_eap.py | 30 ++++++++++++++++++++ tests/hwsim/test_owe.py | 44 +++++++++++++++++++++++++++++ tests/hwsim/test_sae.py | 36 ++++++++++++++++++++++++ tests/hwsim/test_wpas_ap.py | 55 +++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+) diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index bdfe96111..14bc27024 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -7314,3 +7314,33 @@ def test_ap_wpa2_eap_sake_no_control_port(dev, apdev): eap_connect(wpas, hapd, "SAKE", "sake user", password_hex="ff23456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", expect_failure=True) + +def test_ap_wpa3_eap_transition_disable(dev, apdev): + """WPA3-Enterprise transition disable indication""" + params = hostapd.wpa2_eap_params(ssid="test-wpa3-eap") + params["ieee80211w"] = "1" + params['transition_disable'] = '0x04' + hapd = hostapd.add_ap(apdev[0], params) + id = dev[0].connect("test-wpa3-eap", key_mgmt="WPA-EAP", ieee80211w="1", + proto="WPA WPA2", pairwise="CCMP", group="TKIP CCMP", + eap="GPSK", identity="gpsk user", + password="abcdefghijklmnop0123456789abcdef", + scan_freq="2412") + + val = dev[0].get_network(id, "ieee80211w") + if val != "2": + raise Exception("Unexpected ieee80211w value: " + val) + val = dev[0].get_network(id, "key_mgmt") + if val != "WPA-EAP": + raise Exception("Unexpected key_mgmt value: " + val) + val = dev[0].get_network(id, "group") + if val != "CCMP": + raise Exception("Unexpected group value: " + val) + val = dev[0].get_network(id, "proto") + if val != "RSN": + raise Exception("Unexpected proto value: " + val) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].request("RECONNECT") + dev[0].wait_connected() diff --git a/tests/hwsim/test_owe.py b/tests/hwsim/test_owe.py index 7750173c8..51cd7bf74 100644 --- a/tests/hwsim/test_owe.py +++ b/tests/hwsim/test_owe.py @@ -761,3 +761,47 @@ def test_owe_ptk_hash(dev, apdev): if ev is None: raise Exception("No PMKSA cache removal event seen") dev[0].dump_monitor() + +def test_owe_transition_mode_disable(dev, apdev): + """Opportunistic Wireless Encryption transition mode disable""" + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + dev[0].flush_scan_cache() + params = {"ssid": "owe-random", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "rsn_pairwise": "CCMP", + "ieee80211w": "2", + "transition_disable": '0x08', + "owe_transition_bssid": apdev[1]['bssid'], + "owe_transition_ssid": '"owe-test"', + "ignore_broadcast_ssid": "1"} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + params = {"ssid": "owe-test", + "owe_transition_bssid": apdev[0]['bssid'], + "owe_transition_ssid": '"owe-random"'} + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid, freq="2412") + dev[0].scan_for_bss(bssid2, freq="2412") + + id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2", + scan_freq="2412") + + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "08": + raise Exception("Unexpected transition disable bitmap: " + ev) + + val = dev[0].get_network(id, "owe_only") + if val != "1": + raise Exception("Unexpected owe_only value: " + val) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].request("RECONNECT") + dev[0].wait_connected() diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index 255d42c48..c845096fc 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -363,6 +363,42 @@ def test_sae_mixed_mfp(dev, apdev): dev[2].connect("test-sae", psk="12345678", ieee80211w="0", scan_freq="2412") dev[2].dump_monitor() +def test_sae_and_psk_transition_disable(dev, apdev): + """SAE and PSK transition disable indication""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") + params["ieee80211w"] = "1" + params['wpa_key_mgmt'] = 'SAE WPA-PSK' + params['transition_disable'] = '0x01' + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].request("SET sae_groups ") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK", + ieee80211w="1", scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "01": + raise Exception("Unexpected transition disable bitmap: " + ev) + + val = dev[0].get_network(id, "ieee80211w") + if val != "2": + raise Exception("Unexpected ieee80211w value: " + val) + val = dev[0].get_network(id, "key_mgmt") + if val != "SAE": + raise Exception("Unexpected key_mgmt value: " + val) + val = dev[0].get_network(id, "group") + if val != "CCMP": + raise Exception("Unexpected group value: " + val) + val = dev[0].get_network(id, "proto") + if val != "RSN": + raise Exception("Unexpected proto value: " + val) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].request("RECONNECT") + dev[0].wait_connected() + def test_sae_mfp(dev, apdev): """SAE and MFP enabled without sae_require_mfp""" check_sae_capab(dev[0]) diff --git a/tests/hwsim/test_wpas_ap.py b/tests/hwsim/test_wpas_ap.py index 8af7d31dc..8211b6b8d 100644 --- a/tests/hwsim/test_wpas_ap.py +++ b/tests/hwsim/test_wpas_ap.py @@ -849,3 +849,58 @@ def test_wpas_ap_scan(dev, apdev): bss = dev[0].get_bss(bssid) if not bss: raise Exception("AP not found in scan") + +def test_wpas_ap_sae(dev): + """wpa_supplicant AP mode - SAE using psk""" + run_wpas_ap_sae(dev, False) + +def test_wpas_ap_sae_and_psk_transition_disable(dev): + """wpa_supplicant AP mode - SAE+PSK transition disable indication""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + if "SAE" not in dev[1].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + dev[0].set("sae_groups", "") + id = dev[0].add_network() + dev[0].set_network(id, "mode", "2") + dev[0].set_network_quoted(id, "ssid", "wpas-ap-sae") + dev[0].set_network(id, "proto", "WPA2") + dev[0].set_network(id, "key_mgmt", "SAE") + dev[0].set_network(id, "transition_disable", "1") + dev[0].set_network(id, "ieee80211w", "1") + dev[0].set_network(id, "pairwise", "CCMP") + dev[0].set_network(id, "group", "CCMP") + dev[0].set_network_quoted(id, "psk", "12345678") + dev[0].set_network(id, "frequency", "2412") + dev[0].set_network(id, "scan_freq", "2412") + dev[0].set_network(id, "wps_disabled", "1") + dev[0].select_network(id) + wait_ap_ready(dev[0]) + + dev[1].set("sae_groups", "") + dev[1].connect("wpas-ap-sae", key_mgmt="SAE WPA-PSK", + psk="12345678", ieee80211w="1", + scan_freq="2412") + ev = dev[1].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "01": + raise Exception("Unexpected transition disable bitmap: " + ev) + + val = dev[1].get_network(id, "ieee80211w") + if val != "2": + raise Exception("Unexpected ieee80211w value: " + val) + val = dev[1].get_network(id, "key_mgmt") + if val != "SAE": + raise Exception("Unexpected key_mgmt value: " + val) + val = dev[1].get_network(id, "group") + if val != "CCMP": + raise Exception("Unexpected group value: " + val) + val = dev[1].get_network(id, "proto") + if val != "RSN": + raise Exception("Unexpected proto value: " + val) + + dev[1].request("DISCONNECT") + dev[1].wait_disconnected() + dev[1].request("RECONNECT") + dev[1].wait_connected() From ff543409055888403f79c8098bba57053d1baf97 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Mon, 23 Mar 2020 19:42:26 +0100 Subject: [PATCH 0267/1105] AP: Fix Extended Key ID parameter check Check the new variable to be set instead the current setting. Signed-off-by: Alexander Wetzel --- hostapd/config_file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index d53436751..bdae3be79 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2872,10 +2872,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "extended_key_id") == 0) { int val = atoi(pos); - if (bss->extended_key_id < 0 || bss->extended_key_id > 2) { + if (val < 0 || val > 2) { wpa_printf(MSG_ERROR, "Line %d: Invalid extended_key_id=%d; allowed range 0..2", - line, bss->extended_key_id); + line, val); return 1; } bss->extended_key_id = val; From 8ca6f924d6665427f50a1c81c7cc7835af2e1684 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Mon, 23 Mar 2020 19:42:28 +0100 Subject: [PATCH 0268/1105] STA: Fix wpa_clear_keys() PTK key deletion logic We have to delete PTK keys when either BIT(0) or BIT(15) are zero and not only when both are zero. Signed-off-by: Alexander Wetzel --- wpa_supplicant/wpa_supplicant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index f11bac017..a01a3e748 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -749,7 +749,7 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr) NULL, 0, KEY_FLAG_GROUP); } /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */ - if (!(wpa_s->keys_cleared & (BIT(0) | BIT(15))) && addr && + if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr && !is_zero_ether_addr(addr)) { if (!(wpa_s->keys_cleared & BIT(0))) wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, From 431e5d58194622d9774cd1a6e2a2a505b6ca4cf4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 00:57:40 +0200 Subject: [PATCH 0269/1105] tests: Add forgotten step to ap_wpa3_eap_transition_disable This was supposed to be included, but was forgotten in an editor window with pending changes.. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_eap.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 14bc27024..026b995cf 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -7326,6 +7326,11 @@ def test_ap_wpa3_eap_transition_disable(dev, apdev): eap="GPSK", identity="gpsk user", password="abcdefghijklmnop0123456789abcdef", scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "04": + raise Exception("Unexpected transition disable bitmap: " + ev) val = dev[0].get_network(id, "ieee80211w") if val != "2": From 14ee49c24b35756458c29715f792250ff9fe6347 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 11:52:47 +0200 Subject: [PATCH 0270/1105] tests: sigma_dut controlled STA and beacon protection Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_pmf.py | 100 +++++++++++++++++----------------- tests/hwsim/test_sigma_dut.py | 34 ++++++++++++ 2 files changed, 85 insertions(+), 49 deletions(-) diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index 3913c5ce7..7feb173b6 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -927,58 +927,11 @@ def mac80211_read_key(keydir): pass return vals -def test_ap_pmf_beacon_protection_bip(dev, apdev): - """WPA2-PSK Beacon protection (BIP)""" - """WPA2-PSK AP with PMF required and Beacon protection enabled (BIP)""" - run_ap_pmf_beacon_protection(dev, apdev, "AES-128-CMAC") - -def test_ap_pmf_beacon_protection_bip_cmac_256(dev, apdev): - """WPA2-PSK Beacon protection (BIP-CMAC-256)""" - run_ap_pmf_beacon_protection(dev, apdev, "BIP-CMAC-256") - -def test_ap_pmf_beacon_protection_bip_gmac_128(dev, apdev): - """WPA2-PSK Beacon protection (BIP-GMAC-128)""" - run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-128") - -def test_ap_pmf_beacon_protection_bip_gmac_256(dev, apdev): - """WPA2-PSK Beacon protection (BIP-GMAC-256)""" - run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-256") - -def run_ap_pmf_beacon_protection(dev, apdev, cipher): - ssid = "test-beacon-prot" - params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") - params["wpa_key_mgmt"] = "WPA-PSK-SHA256" - params["ieee80211w"] = "2" - params["beacon_prot"] = "1" - params["group_mgmt_cipher"] = cipher - try: - hapd = hostapd.add_ap(apdev[0], params) - except Exception as e: - if "Failed to enable hostapd interface" in str(e): - raise HwsimSkip("Beacon protection not supported") - raise - - bssid = hapd.own_addr() - - Wlantest.setup(hapd) - wt = Wlantest() - wt.flush() - wt.add_passphrase("12345678") - - # STA with Beacon protection enabled - dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1", - key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") - - # STA with Beacon protection disabled - dev[1].connect(ssid, psk="12345678", ieee80211w="2", - key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") - - time.sleep(1) - +def check_mac80211_bigtk(dev, hapd): sta_key = None ap_key = None - phy = dev[0].get_driver_status_field("phyname") + phy = dev.get_driver_status_field("phyname") keys = "/sys/kernel/debug/ieee80211/%s/keys" % phy try: for key in os.listdir(keys): @@ -1034,6 +987,55 @@ def run_ap_pmf_beacon_protection(dev, apdev, cipher): if tx_spec < 3: raise Exception("AP did not update BIGTK BIPN sufficiently") +def test_ap_pmf_beacon_protection_bip(dev, apdev): + """WPA2-PSK Beacon protection (BIP)""" + """WPA2-PSK AP with PMF required and Beacon protection enabled (BIP)""" + run_ap_pmf_beacon_protection(dev, apdev, "AES-128-CMAC") + +def test_ap_pmf_beacon_protection_bip_cmac_256(dev, apdev): + """WPA2-PSK Beacon protection (BIP-CMAC-256)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-CMAC-256") + +def test_ap_pmf_beacon_protection_bip_gmac_128(dev, apdev): + """WPA2-PSK Beacon protection (BIP-GMAC-128)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-128") + +def test_ap_pmf_beacon_protection_bip_gmac_256(dev, apdev): + """WPA2-PSK Beacon protection (BIP-GMAC-256)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-256") + +def run_ap_pmf_beacon_protection(dev, apdev, cipher): + ssid = "test-beacon-prot" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["beacon_prot"] = "1" + params["group_mgmt_cipher"] = cipher + try: + hapd = hostapd.add_ap(apdev[0], params) + except Exception as e: + if "Failed to enable hostapd interface" in str(e): + raise HwsimSkip("Beacon protection not supported") + raise + + bssid = hapd.own_addr() + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + # STA with Beacon protection enabled + dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1", + key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") + + # STA with Beacon protection disabled + dev[1].connect(ssid, psk="12345678", ieee80211w="2", + key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") + + time.sleep(1) + check_mac80211_bigtk(dev[0], hapd) + valid_bip = wt.get_bss_counter('valid_bip_mmie', bssid) invalid_bip = wt.get_bss_counter('invalid_bip_mmie', bssid) missing_bip = wt.get_bss_counter('missing_bip_mmie', bssid) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index eb3bf0821..69e48aed6 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -26,6 +26,7 @@ from test_dpp import check_dpp_capab, update_hapd_config, wait_auth_success from test_suite_b import check_suite_b_192_capa, suite_b_as_params, suite_b_192_rsa_ap_params from test_ap_eap import check_eap_capa, int_eap_server_params, check_domain_match, check_domain_suffix_match from test_ap_hs20 import hs20_ap_params +from test_ap_pmf import check_mac80211_bigtk def check_sigma_dut(): if not os.path.exists("./sigma_dut"): @@ -4048,3 +4049,36 @@ def run_sigma_dut_ap_channel(dev, apdev, params, channel, mode, scan_freq, stop_sigma_dut(sigma) subprocess.call(['iw', 'reg', 'set', '00']) dev[0].flush_scan_cache() + +def test_sigma_dut_beacon_prot(dev, apdev): + """sigma_dut controlled STA and beacon protection""" + ssid = "test-pmf-required" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["beacon_prot"] = "1" + try: + hapd = hostapd.add_ap(apdev[0], params) + except Exception as e: + if "Failed to enable hostapd interface" in str(e): + raise HwsimSkip("Beacon protection not supported") + raise + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,PMF" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,type,PSK,passphrase,%s,encpType,aes-ccmp,keymgmttype,wpa2,PMF,Required,BeaconProtection,1" % (ifname, "test-pmf-required", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-pmf-required"), + timeout=10) + sigma_dut_wait_connected(ifname) + + time.sleep(1) + check_mac80211_bigtk(dev[0], hapd) + + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + dev[0].set("ignore_old_scan_res", "0") From f3de8f35bcfe83d5cf64e6c9eacd5880e8071e56 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 12:50:00 +0200 Subject: [PATCH 0271/1105] tests: sigma_dut controlled AP and beacon protection Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 35 +++++++++++++++++++++++++++++++++++ tests/hwsim/wlantest.py | 3 ++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 69e48aed6..dd9e80c31 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -22,6 +22,7 @@ import hostapd from utils import HwsimSkip from hwsim import HWSimRadio import hwsim_utils +from wlantest import Wlantest from test_dpp import check_dpp_capab, update_hapd_config, wait_auth_success from test_suite_b import check_suite_b_192_capa, suite_b_as_params, suite_b_192_rsa_ap_params from test_ap_eap import check_eap_capa, int_eap_server_params, check_domain_match, check_domain_suffix_match @@ -4082,3 +4083,37 @@ def test_sigma_dut_beacon_prot(dev, apdev): finally: stop_sigma_dut(sigma) dev[0].set("ignore_old_scan_res", "0") + +def test_sigma_dut_ap_beacon_prot(dev, apdev, params): + """sigma_dut controlled AP and beacon protection""" + logdir = params['prefix'] + ".sigma-hostapd" + + Wlantest.setup(None) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-psk,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-PSK,PSK,12345678,PMF,Required,BeaconProtection,1") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + + dev[0].connect("test-psk", key_mgmt="WPA-PSK-SHA256", + psk="12345678", scan_freq="2412", + ieee80211w="2", beacon_prot="1") + time.sleep(1) + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + + valid_bip = wt.get_bss_counter('valid_bip_mmie', bssid) + invalid_bip = wt.get_bss_counter('invalid_bip_mmie', bssid) + missing_bip = wt.get_bss_counter('missing_bip_mmie', bssid) + logger.info("wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) + if valid_bip < 0 or invalid_bip > 0 or missing_bip > 0: + raise Exception("Unexpected wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) diff --git a/tests/hwsim/wlantest.py b/tests/hwsim/wlantest.py index b0e817913..6d4343b63 100644 --- a/tests/hwsim/wlantest.py +++ b/tests/hwsim/wlantest.py @@ -91,7 +91,8 @@ class Wlantest: @classmethod def setup(cls, wpa, is_p2p=False): - cls.chan_from_wpa(wpa, is_p2p) + if wpa: + cls.chan_from_wpa(wpa, is_p2p) cls.start_remote_wlantest() cls.setup_done = True From 19e8536d47879b4626515e64a09b9d723da1295f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 13:01:19 +0200 Subject: [PATCH 0272/1105] tests: sigma_dut controlled AP and transition disabled indication Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index dd9e80c31..2e9f26429 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4117,3 +4117,29 @@ def test_sigma_dut_ap_beacon_prot(dev, apdev, params): logger.info("wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) if valid_bip < 0 or invalid_bip > 0 or missing_bip > 0: raise Exception("Unexpected wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) + +def test_sigma_dut_ap_transition_disable(dev, apdev, params): + """sigma_dut controlled AP and transition disabled indication""" + logdir = params['prefix'] + ".sigma-hostapd" + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678,PMF,Required,Transition_Disable,1,Transition_Disable_Index,0") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "01": + raise Exception("Unexpected transition disable bitmap: " + ev) + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) From b766ac488fd443871e36e9f8dd4bef8943875f14 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 18 Mar 2020 23:15:18 +0200 Subject: [PATCH 0273/1105] tests: Use frame injection in monitor_iface_unknown_sta The previously used normal data TX depends on undefined driver behavior after all keys have been removed. That may not be available, so do this more properly with frame injection through a monitor interface. Signed-off-by: Jouni Malinen --- tests/hwsim/test_monitor_interface.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_monitor_interface.py b/tests/hwsim/test_monitor_interface.py index 62ce7383e..e1a48aeb0 100644 --- a/tests/hwsim/test_monitor_interface.py +++ b/tests/hwsim/test_monitor_interface.py @@ -4,6 +4,7 @@ # This software may be distributed under the terms of the BSD license. # See README for more details. +import binascii from remotehost import remote_compatible import logging logger = logging.getLogger() @@ -12,6 +13,7 @@ import time import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant +from utils import radiotap_build, start_monitor, stop_monitor def test_monitor_iface_open(dev, apdev): """Open connection using cfg80211 monitor interface on AP""" @@ -72,9 +74,20 @@ def test_monitor_iface_unknown_sta(dev, apdev): hapd.request("DEAUTHENTICATE " + addr) # But the unprotected Deauth from TX frame-from-unassoc-STA will now be # processed - dev[0].request("DATA_TEST_CONFIG 1") - dev[0].request("DATA_TEST_TX " + bssid + " " + addr + " 0") - dev[0].request("DATA_TEST_CONFIG 0") + try: + sock = start_monitor(apdev[1]["ifname"]) + radiotap = radiotap_build() + + bssid = hapd.own_addr().replace(':', '') + addr = dev[0].own_addr().replace(':', '') + + # Inject Data frame from STA to AP since we not have SA in place + # anymore for normal data TX + frame = binascii.unhexlify("48010000" + bssid + addr + bssid + "0000") + sock.send(radiotap + frame) + finally: + stop_monitor(apdev[1]["ifname"]) + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5) if ev is None: raise Exception("No disconnection") From b7275a8142202e730f70c2812a3e37ce763ad25c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 18 Mar 2020 12:41:46 +0200 Subject: [PATCH 0274/1105] Update STA flags to the driver immediately on disconnection hostapd (and wpa_supplicant in AP mode) was internally updating the STA flags on disconnection cases to remove authorization and association. However, some cases did not result in immediate update of the driver STA entry. Update all such cases to send out the update to the driver as well to reduce risk of race conditions where new frames might be accepted for TX or RX after the port authorization or association has been lost and configured keys are removed. Signed-off-by: Jouni Malinen --- src/ap/ap_drv_ops.c | 2 +- src/ap/drv_callbacks.c | 1 + src/ap/ieee802_11.c | 2 ++ src/ap/sta_info.c | 7 ++++++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 1aa2ab038..1f284f0f3 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -588,7 +588,7 @@ int hostapd_set_frag(struct hostapd_data *hapd, int frag) int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, int total_flags, int flags_or, int flags_and) { - if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) + if (!hapd->driver || !hapd->drv_priv || !hapd->driver->sta_set_flags) return 0; return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, flags_or, flags_and); diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 98729f423..baf3f7c3f 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -712,6 +712,7 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) ap_sta_set_authorized(hapd, sta, 0); sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + hostapd_set_sta_flags(hapd, sta); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index c0f9290f8..1f58ec87c 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4502,6 +4502,7 @@ static void handle_disassoc(struct hostapd_data *hapd, ap_sta_set_authorized(hapd, sta, 0); sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + hostapd_set_sta_flags(hapd, sta); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); @@ -4568,6 +4569,7 @@ static void handle_deauth(struct hostapd_data *hapd, sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + hostapd_set_sta_flags(hapd, sta); wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "deauthenticated"); diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index d3aa15da3..903be28d4 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -164,6 +164,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) /* just in case */ ap_sta_set_authorized(hapd, sta, 0); + hostapd_set_sta_flags(hapd, sta); if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); @@ -544,6 +545,7 @@ skip_poll: case STA_DISASSOC_FROM_CLI: ap_sta_set_authorized(hapd, sta, 0); sta->flags &= ~WLAN_STA_ASSOC; + hostapd_set_sta_flags(hapd, sta); ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = @@ -812,6 +814,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, sta->timeout_next = STA_DEAUTH; } ap_sta_set_authorized(hapd, sta, 0); + hostapd_set_sta_flags(hapd, sta); wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " "for " MACSTR " (%d seconds - " "AP_MAX_INACTIVITY_AFTER_DISASSOC)", @@ -862,6 +865,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); ap_sta_set_authorized(hapd, sta, 0); + hostapd_set_sta_flags(hapd, sta); sta->timeout_next = STA_REMOVE; wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " "for " MACSTR " (%d seconds - " @@ -1329,9 +1333,10 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, if (sta == NULL) return; ap_sta_set_authorized(hapd, sta, 0); + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + hostapd_set_sta_flags(hapd, sta); wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout " "for " MACSTR " (%d seconds - " "AP_MAX_INACTIVITY_AFTER_DEAUTH)", From bc95d58330c7332ed54d54d06f22e211a1e54d66 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 00:07:33 +0200 Subject: [PATCH 0275/1105] Fix a typo in function documentation Signed-off-by: Jouni Malinen --- wpa_supplicant/offchannel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/offchannel.c b/wpa_supplicant/offchannel.c index 77c425fac..e40cf5bbe 100644 --- a/wpa_supplicant/offchannel.c +++ b/wpa_supplicant/offchannel.c @@ -246,7 +246,7 @@ void offchannel_send_action_tx_status( * @buf: Frame to transmit starting from the Category field * @len: Length of @buf in bytes * @wait_time: Wait time for response in milliseconds - * @tx_cb: Callback function for indicating TX status or %NULL for now callback + * @tx_cb: Callback function for indicating TX status or %NULL for no callback * @no_cck: Whether CCK rates are to be disallowed for TX rate selection * Returns: 0 on success or -1 on failure * From 514cc49ba588be6913fb68ae057477dc8fd929aa Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 17:08:38 +0200 Subject: [PATCH 0276/1105] DPP: Store global pointers in struct dpp_authentication Set the global pointer and msg_ctx when allocating struct dpp_authentication instead of needing to pass these to dpp_set_configurator(). Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 17 ++++++++--------- src/common/dpp.c | 28 ++++++++++++++-------------- src/common/dpp.h | 13 +++++++------ wpa_supplicant/dpp_supplicant.c | 15 ++++++++------- 4 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 8e22c8ba6..d2d081f1b 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -543,15 +543,15 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) dpp_auth_deinit(hapd->dpp_auth); } - hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi, + hapd->dpp_auth = dpp_auth_init(hapd->iface->interfaces->dpp, + hapd->msg_ctx, peer_bi, own_bi, allowed_roles, neg_freq, hapd->iface->hw_features, hapd->iface->num_hw_features); if (!hapd->dpp_auth) goto fail; hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); - if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, - hapd->dpp_auth, cmd) < 0) { + if (dpp_set_configurator(hapd->dpp_auth, cmd) < 0) { dpp_auth_deinit(hapd->dpp_auth); hapd->dpp_auth = NULL; goto fail; @@ -663,7 +663,8 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, } hapd->dpp_auth_ok_on_ack = 0; - hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles, + hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp, + hapd->msg_ctx, hapd->dpp_allowed_roles, hapd->dpp_qr_mutual, peer_bi, own_bi, freq, hdr, buf, len); if (!hapd->dpp_auth) { @@ -671,8 +672,7 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, return; } hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); - if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, - hapd->dpp_auth, + if (dpp_set_configurator(hapd->dpp_auth, hapd->dpp_configurator_params) < 0) { dpp_auth_deinit(hapd->dpp_auth); hapd->dpp_auth = NULL; @@ -1675,14 +1675,13 @@ int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd) int ret = -1; char *curve = NULL; - auth = os_zalloc(sizeof(*auth)); + auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx); if (!auth) return -1; curve = get_param(cmd, " curve="); hostapd_dpp_set_testing_options(hapd, auth); - if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, - auth, cmd) == 0 && + if (dpp_set_configurator(auth, cmd) == 0 && dpp_configurator_own_config(auth, curve, 1) == 0) { hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]); ret = 0; diff --git a/src/common/dpp.c b/src/common/dpp.c index 012956b3e..57afbd578 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -2335,20 +2335,22 @@ fail: } -static struct dpp_authentication * dpp_alloc_auth(void *msg_ctx) +struct dpp_authentication * +dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx) { struct dpp_authentication *auth; auth = os_zalloc(sizeof(*auth)); if (!auth) return NULL; + auth->global = dpp; auth->msg_ctx = msg_ctx; auth->conf_resp_status = 255; return auth; } -struct dpp_authentication * dpp_auth_init(void *msg_ctx, +struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, u8 dpp_allowed_roles, @@ -2365,7 +2367,7 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, u8 test_hash[SHA256_MAC_LEN]; #endif /* CONFIG_TESTING_OPTIONS */ - auth = dpp_alloc_auth(msg_ctx); + auth = dpp_alloc_auth(dpp, msg_ctx); if (!auth) return NULL; auth->initiator = 1; @@ -3259,8 +3261,8 @@ static int dpp_auth_build_resp_status(struct dpp_authentication *auth, struct dpp_authentication * -dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, - struct dpp_bootstrap_info *peer_bi, +dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles, + int qr_mutual, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, unsigned int freq, const u8 *hdr, const u8 *attr_start, size_t attr_len) @@ -3301,7 +3303,7 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, wrapped_data, wrapped_data_len); attr_len = wrapped_data - 4 - attr_start; - auth = dpp_alloc_auth(msg_ctx); + auth = dpp_alloc_auth(dpp, msg_ctx); if (!auth) goto fail; auth->peer_bi = peer_bi; @@ -4675,9 +4677,7 @@ dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id) } -int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, - struct dpp_authentication *auth, - const char *cmd) +int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd) { const char *pos; char *tmp = NULL; @@ -4702,7 +4702,7 @@ int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, pos = os_strstr(cmd, " configurator="); if (pos) { pos += 14; - auth->conf = dpp_configurator_get_id(dpp, atoi(pos)); + auth->conf = dpp_configurator_get_id(auth->global, atoi(pos)); if (!auth->conf) { wpa_printf(MSG_INFO, "DPP: Could not find the specified configurator"); @@ -4723,7 +4723,7 @@ int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, } if (dpp_configuration_parse(auth, cmd) < 0) { - wpa_msg(msg_ctx, MSG_INFO, + wpa_msg(auth->msg_ctx, MSG_INFO, "DPP: Failed to set configurator parameters"); goto fail; } @@ -11401,7 +11401,8 @@ static int dpp_controller_rx_auth_req(struct dpp_connection *conn, return 0; } - conn->auth = dpp_auth_req_rx(conn->ctrl->global->msg_ctx, + conn->auth = dpp_auth_req_rx(conn->ctrl->global, + conn->ctrl->global->msg_ctx, conn->ctrl->allowed_roles, conn->ctrl->qr_mutual, peer_bi, own_bi, -1, hdr, buf, len); @@ -11410,8 +11411,7 @@ static int dpp_controller_rx_auth_req(struct dpp_connection *conn, return -1; } - if (dpp_set_configurator(conn->ctrl->global, conn->ctrl->global->msg_ctx, - conn->auth, + if (dpp_set_configurator(conn->auth, conn->ctrl->configurator_params) < 0) { dpp_connection_remove(conn); return -1; diff --git a/src/common/dpp.h b/src/common/dpp.h index ad1bcb0fa..d6da0460b 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -199,6 +199,7 @@ struct dpp_asymmetric_key { #define DPP_MAX_CONF_OBJ 10 struct dpp_authentication { + struct dpp_global *global; void *msg_ctx; u8 peer_version; const struct dpp_curve_params *curve; @@ -429,8 +430,10 @@ int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac); int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info); int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi, struct dpp_bootstrap_info *peer_bi); +struct dpp_authentication * +dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx); struct hostapd_hw_modes; -struct dpp_authentication * dpp_auth_init(void *msg_ctx, +struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, u8 dpp_allowed_roles, @@ -438,8 +441,8 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, struct hostapd_hw_modes *own_modes, u16 num_modes); struct dpp_authentication * -dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, - struct dpp_bootstrap_info *peer_bi, +dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles, + int qr_mutual, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, unsigned int freq, const u8 *hdr, const u8 *attr_start, size_t attr_len); @@ -464,9 +467,7 @@ int dpp_akm_dpp(enum dpp_akm akm); int dpp_akm_ver2(enum dpp_akm akm); int dpp_configuration_valid(const struct dpp_configuration *conf); void dpp_configuration_free(struct dpp_configuration *conf); -int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, - struct dpp_authentication *auth, - const char *cmd); +int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd); void dpp_auth_deinit(struct dpp_authentication *auth); struct wpabuf * dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 6d9427bb3..89d86ca02 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -769,12 +769,12 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) wpa_s->dpp_auth = NULL; } - auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles, neg_freq, - wpa_s->hw.modes, wpa_s->hw.num_modes); + auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles, + neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes); if (!auth) goto fail; wpas_dpp_set_testing_options(wpa_s, auth); - if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) < 0) { + if (dpp_set_configurator(auth, cmd) < 0) { dpp_auth_deinit(auth); goto fail; } @@ -1013,7 +1013,8 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, wpa_s->dpp_gas_client = 0; wpa_s->dpp_auth_ok_on_ack = 0; - wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles, + wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s, + wpa_s->dpp_allowed_roles, wpa_s->dpp_qr_mutual, peer_bi, own_bi, freq, hdr, buf, len); if (!wpa_s->dpp_auth) { @@ -1021,7 +1022,7 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, return; } wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth); - if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth, + if (dpp_set_configurator(wpa_s->dpp_auth, wpa_s->dpp_configurator_params) < 0) { dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; @@ -2340,13 +2341,13 @@ int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd) int ret = -1; char *curve = NULL; - auth = os_zalloc(sizeof(*auth)); + auth = dpp_alloc_auth(wpa_s->dpp, wpa_s); if (!auth) return -1; curve = get_param(cmd, " curve="); wpas_dpp_set_testing_options(wpa_s, auth); - if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 && + if (dpp_set_configurator(auth, cmd) == 0 && dpp_configurator_own_config(auth, curve, 0) == 0) ret = wpas_dpp_handle_config_obj(wpa_s, auth, &auth->conf_obj[0]); From 804fc268af6513706a210edc1eeeb8238bcedb00 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 17:14:06 +0200 Subject: [PATCH 0277/1105] DPP: Allow per-peer configurator parameters to be set This is a more convenient way of addressing cases where a Configurator/Controller may store a large number of peer bootstrapping information instances and may need to manage different configuration parameters for each peer while operating as the Responder. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 11 ++++++++++- src/common/dpp.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 57afbd578..7f0f0b6ea 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -894,6 +894,7 @@ void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info) os_free(info->chan); os_free(info->pk); EVP_PKEY_free(info->pubkey); + str_clear_free(info->configurator_params); os_free(info); } @@ -2370,6 +2371,9 @@ struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, auth = dpp_alloc_auth(dpp, msg_ctx); if (!auth) return NULL; + if (peer_bi->configurator_params && + dpp_set_configurator(auth, peer_bi->configurator_params) < 0) + goto fail; auth->initiator = 1; auth->waiting_auth_resp = 1; auth->allowed_roles = dpp_allowed_roles; @@ -3306,6 +3310,9 @@ dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles, auth = dpp_alloc_auth(dpp, msg_ctx); if (!auth) goto fail; + if (peer_bi && peer_bi->configurator_params && + dpp_set_configurator(auth, peer_bi->configurator_params) < 0) + goto fail; auth->peer_bi = peer_bi; auth->own_bi = own_bi; auth->curve = own_bi->curve; @@ -4683,8 +4690,10 @@ int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd) char *tmp = NULL; int ret = -1; - if (!cmd) + if (!cmd || auth->configurator_set) return 0; + auth->configurator_set = 1; + if (cmd[0] != ' ') { size_t len; diff --git a/src/common/dpp.h b/src/common/dpp.h index d6da0460b..0ec0024cd 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -126,6 +126,7 @@ struct dpp_bootstrap_info { const struct dpp_curve_params *curve; unsigned int pkex_t; /* number of failures before dpp_pkex * instantiation */ + char *configurator_params; }; #define PKEX_COUNTER_T_LIMIT 5 @@ -275,6 +276,7 @@ struct dpp_authentication { int send_conn_status; int conn_status_requested; int akm_use_selector; + int configurator_set; #ifdef CONFIG_TESTING_OPTIONS char *config_obj_override; char *discovery_override; From 547dc7eaa30d5232933d78618a690714f7c59705 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 17:28:59 +0200 Subject: [PATCH 0278/1105] DPP: Add DPP_BOOTSTRAP_SET command "DPP_BOOTSTRAP_SET " can now be used to set peer specific configurator parameters which will override any global parameters from dpp_configurator_params. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 5 +++++ src/common/dpp.c | 20 ++++++++++++++++++++ src/common/dpp.h | 1 + wpa_supplicant/ctrl_iface.c | 4 ++++ 4 files changed, 30 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 1a369ed2a..aaf00c2db 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -3463,6 +3463,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp, atoi(buf + 19), reply, reply_size); + } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) { + if (dpp_bootstrap_set(hapd->iface->interfaces->dpp, + atoi(buf + 18), + os_strchr(buf + 18, ' ')) < 0) + reply_len = -1; } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { if (hostapd_dpp_auth_init(hapd, buf + 13) < 0) reply_len = -1; diff --git a/src/common/dpp.c b/src/common/dpp.c index 7f0f0b6ea..6bb131183 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -10532,6 +10532,26 @@ int dpp_bootstrap_info(struct dpp_global *dpp, int id, } +int dpp_bootstrap_set(struct dpp_global *dpp, int id, const char *params) +{ + struct dpp_bootstrap_info *bi; + + bi = dpp_bootstrap_get_id(dpp, id); + if (!bi) + return -1; + + str_clear_free(bi->configurator_params); + + if (params) { + bi->configurator_params = os_strdup(params); + return bi->configurator_params ? 0 : -1; + } + + bi->configurator_params = NULL; + return 0; +} + + void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, const u8 *r_bootstrap, struct dpp_bootstrap_info **own_bi, diff --git a/src/common/dpp.h b/src/common/dpp.h index 0ec0024cd..bab83a8a4 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -562,6 +562,7 @@ dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer, const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id); int dpp_bootstrap_info(struct dpp_global *dpp, int id, char *reply, int reply_size); +int dpp_bootstrap_set(struct dpp_global *dpp, int id, const char *params); void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, const u8 *r_bootstrap, struct dpp_bootstrap_info **own_bi, diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index e140a3e38..ebcb60e5a 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -10890,6 +10890,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19), reply, reply_size); + } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) { + if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18), + os_strchr(buf + 18, ' ')) < 0) + reply_len = -1; } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0) reply_len = -1; From 7cba35b0edb556f4840caf00d9c90bb84078afd9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 23:24:35 +0200 Subject: [PATCH 0279/1105] DPP2: New identifier definitions Add new identifier definitions for presence announcement, reconfiguration, and certificate enrollment. Signed-off-by: Jouni Malinen --- src/common/dpp.h | 11 +++++++++++ src/common/ieee802_11_common.c | 3 +++ src/common/ieee802_11_defs.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/src/common/dpp.h b/src/common/dpp.h index bab83a8a4..9f3e04820 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -36,6 +36,11 @@ enum dpp_public_action_frame_type { DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10, DPP_PA_CONFIGURATION_RESULT = 11, DPP_PA_CONNECTION_STATUS_RESULT = 12, + DPP_PA_PRESENCE_ANNOUNCEMENT = 13, + DPP_PA_RECONFIG_ANNOUNCEMENT = 14, + DPP_PA_RECONFIG_AUTH_REQ = 15, + DPP_PA_RECONFIG_AUTH_RESP = 16, + DPP_PA_RECONFIG_AUTH_CONF = 17, }; enum dpp_attribute_id { @@ -67,6 +72,9 @@ enum dpp_attribute_id { DPP_ATTR_ENVELOPED_DATA = 0x101A, DPP_ATTR_SEND_CONN_STATUS = 0x101B, DPP_ATTR_CONN_STATUS = 0x101C, + DPP_ATTR_RECONFIG_FLAGS = 0x101D, + DPP_ATTR_C_SIGN_KEY_HASH = 0x101E, + DPP_ATTR_CSR_ATTR_REQ = 0x101F, }; enum dpp_status_error { @@ -81,6 +89,9 @@ enum dpp_status_error { DPP_STATUS_NO_MATCH = 8, DPP_STATUS_CONFIG_REJECTED = 9, DPP_STATUS_NO_AP = 10, + DPP_STATUS_CONFIGURE_PENDING = 11, + DPP_STATUS_CSR_NEEDED = 12, + DPP_STATUS_CSR_BAD = 13, }; #define DPP_CAPAB_ENROLLEE BIT(0) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 6aa38cab2..e7ee24e2a 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -133,6 +133,9 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, case OWE_OUI_TYPE: /* OWE Transition Mode element */ break; + case DPP_CC_OUI_TYPE: + /* DPP Configurator Connectivity element */ + break; default: wpa_printf(MSG_MSGDUMP, "Unknown WFA " "information element ignored " diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 7c51574b5..6c88dda46 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1316,6 +1316,8 @@ struct ieee80211_ampe_ie { #define OWE_IE_VENDOR_TYPE 0x506f9a1c #define OWE_OUI_TYPE 28 #define MULTI_AP_OUI_TYPE 0x1B +#define DPP_CC_IE_VENDOR_TYPE 0x506f9a1e +#define DPP_CC_OUI_TYPE 0x1e #define MULTI_AP_SUB_ELEM_TYPE 0x06 #define MULTI_AP_TEAR_DOWN BIT(4) From 1f0226770c8458b32fa4da8aecf961f180956b4d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 26 Mar 2020 23:41:27 +0200 Subject: [PATCH 0280/1105] DPP2: Add a helper function for building Presence Announcement frame Signed-off-by: Jouni Malinen --- src/common/dpp.c | 70 +++++++++++++++++++++++++++++++++--------------- src/common/dpp.h | 3 ++- 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 6bb131183..ea5d6df57 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1056,6 +1056,32 @@ static const struct dpp_curve_params * dpp_get_curve_nid(int nid) } +static int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len) +{ + const u8 *addr[2]; + size_t len[2]; + + addr[0] = data; + len[0] = data_len; + if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", + bi->pubkey_hash, SHA256_MAC_LEN); + + addr[0] = (const u8 *) "chirp"; + len[0] = 5; + addr[1] = data; + len[1] = data_len; + if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)", + bi->pubkey_hash_chirp, SHA256_MAC_LEN); + + return 0; +} + + static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) { const char *end; @@ -1094,14 +1120,11 @@ static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key", data, data_len); - if (sha256_vector(1, (const u8 **) &data, &data_len, - bi->pubkey_hash) < 0) { + if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); os_free(data); return -1; } - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", - bi->pubkey_hash, SHA256_MAC_LEN); /* DER encoded ASN.1 SubjectPublicKeyInfo * @@ -1519,27 +1542,19 @@ fail: } -int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) +static int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) { struct wpabuf *der; int res; - const u8 *addr[1]; - size_t len[1]; der = dpp_bootstrap_key_der(bi->pubkey); if (!der) return -1; wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", der); - - addr[0] = wpabuf_head(der); - len[0] = wpabuf_len(der); - res = sha256_vector(1, addr, len, bi->pubkey_hash); + res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)); if (res < 0) wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - else - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, - SHA256_MAC_LEN); wpabuf_free(der); return res; } @@ -1552,8 +1567,6 @@ static int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, char *pos, *end; size_t len; struct wpabuf *der = NULL; - const u8 *addr[1]; - int res; if (!curve) { bi->curve = &dpp_curves[0]; @@ -1579,15 +1592,10 @@ static int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", der); - addr[0] = wpabuf_head(der); - len = wpabuf_len(der); - res = sha256_vector(1, addr, &len, bi->pubkey_hash); - if (res < 0) { + if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); goto fail; } - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, - SHA256_MAC_LEN); base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); wpabuf_free(der); @@ -12211,4 +12219,22 @@ void dpp_controller_stop(struct dpp_global *dpp) } } + +struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi) +{ + struct wpabuf *msg; + + wpa_printf(MSG_DEBUG, "DPP: Build Presence Announcement frame"); + + msg = dpp_alloc_msg(DPP_PA_PRESENCE_ANNOUNCEMENT, 4 + SHA256_MAC_LEN); + if (!msg) + return NULL; + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, bi->pubkey_hash_chirp); + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Presence Announcement frame attributes", msg); + return msg; +} + #endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp.h b/src/common/dpp.h index 9f3e04820..d544fba66 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -134,6 +134,7 @@ struct dpp_bootstrap_info { int own; EVP_PKEY *pubkey; u8 pubkey_hash[SHA256_MAC_LEN]; + u8 pubkey_hash_chirp[SHA256_MAC_LEN]; const struct dpp_curve_params *curve; unsigned int pkex_t; /* number of failures before dpp_pkex * instantiation */ @@ -436,7 +437,6 @@ extern size_t dpp_nonce_override_len; void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info); const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type); -int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi, const char *chan_list); int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac); @@ -596,6 +596,7 @@ int dpp_controller_start(struct dpp_global *dpp, void dpp_controller_stop(struct dpp_global *dpp); int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port); +struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); struct dpp_global_config { void *msg_ctx; From 562f77144cd2f4f44969c844b3bf035530351d16 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 12:42:00 +0200 Subject: [PATCH 0281/1105] DPP2: Chirping in wpa_supplicant Enrollee Add a new wpa_supplicant control interface command "DPP_CHIRP own= iter=" to request chirping, i.e., sending of Presence Announcement frames, to be started. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 6 + src/common/dpp.h | 1 + src/common/wpa_ctrl.h | 1 + wpa_supplicant/ctrl_iface.c | 8 + wpa_supplicant/dpp_supplicant.c | 281 ++++++++++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.h | 2 + wpa_supplicant/wpa_supplicant_i.h | 8 + 7 files changed, 307 insertions(+) diff --git a/src/common/dpp.c b/src/common/dpp.c index ea5d6df57..56abe507f 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -131,6 +131,7 @@ struct dpp_global { struct dl_list tcp_init; /* struct dpp_connection */ void *cb_ctx; int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); #endif /* CONFIG_DPP2 */ }; @@ -10333,6 +10334,10 @@ static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id) if (id && bi->id != id) continue; found = 1; +#ifdef CONFIG_DPP2 + if (dpp->remove_bi) + dpp->remove_bi(dpp->cb_ctx, bi); +#endif /* CONFIG_DPP2 */ dl_list_del(&bi->list); dpp_bootstrap_info_free(bi); } @@ -10903,6 +10908,7 @@ struct dpp_global * dpp_global_init(struct dpp_global_config *config) #ifdef CONFIG_DPP2 dpp->cb_ctx = config->cb_ctx; dpp->process_conf_obj = config->process_conf_obj; + dpp->remove_bi = config->remove_bi; #endif /* CONFIG_DPP2 */ dl_list_init(&dpp->bootstrap); diff --git a/src/common/dpp.h b/src/common/dpp.h index d544fba66..513918bb5 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -602,6 +602,7 @@ struct dpp_global_config { void *msg_ctx; void *cb_ctx; int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); }; struct dpp_global * dpp_global_init(struct dpp_global_config *config); diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 7471f0d15..0b0413068 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -187,6 +187,7 @@ extern "C" { #define DPP_EVENT_PKEX_T_LIMIT "DPP-PKEX-T-LIMIT " #define DPP_EVENT_INTRO "DPP-INTRO " #define DPP_EVENT_CONF_REQ_RX "DPP-CONF-REQ-RX " +#define DPP_EVENT_CHIRP_STOPPED "DPP-CHIRP-STOPPED " /* MESH events */ #define MESH_GROUP_STARTED "MESH-GROUP-STARTED " diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index ebcb60e5a..a2b4ee765 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8104,6 +8104,9 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->dpp_resp_wait_time = 0; wpa_s->dpp_resp_max_tries = 0; wpa_s->dpp_resp_retry_time = 0; +#ifdef CONFIG_DPP2 + wpas_dpp_chirp_stop(wpa_s); +#endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN); os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN); @@ -10947,6 +10950,11 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) { dpp_controller_stop(wpa_s->dpp); + } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) { + if (wpas_dpp_chirp(wpa_s, buf + 9) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { + wpas_dpp_chirp_stop(wpa_s); #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ } else { diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 89d86ca02..c6d555662 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -975,6 +975,10 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR, MAC2STR(src)); +#ifdef CONFIG_DPP2 + wpas_dpp_chirp_stop(wpa_s); +#endif /* CONFIG_DPP2 */ + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, &r_bootstrap_len); if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { @@ -1681,6 +1685,15 @@ static int wpas_dpp_process_conf_obj(void *ctx, return res; } + +static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi) +{ + struct wpa_supplicant *wpa_s = ctx; + + if (bi == wpa_s->dpp_chirp_bi) + wpas_dpp_chirp_stop(wpa_s); +} + #endif /* CONFIG_DPP2 */ @@ -2651,6 +2664,7 @@ int wpas_dpp_init(struct wpa_supplicant *wpa_s) config.cb_ctx = wpa_s; #ifdef CONFIG_DPP2 config.process_conf_obj = wpas_dpp_process_conf_obj; + config.remove_bi = wpas_dpp_remove_bi; #endif /* CONFIG_DPP2 */ wpa_s->dpp = dpp_global_init(&config); return wpa_s->dpp ? 0 : -1; @@ -2682,6 +2696,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL); dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = NULL; + wpas_dpp_chirp_stop(wpa_s); #endif /* CONFIG_DPP2 */ offchannel_send_action_done(wpa_s); wpas_dpp_listen_stop(wpa_s); @@ -2694,6 +2709,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) #ifdef CONFIG_DPP2 + int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) { struct dpp_controller_config config; @@ -2710,4 +2726,269 @@ int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) config.configurator_params = wpa_s->dpp_configurator_params; return dpp_controller_start(wpa_s->dpp, &config); } + + +static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx); + +static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + wpa_printf(MSG_DEBUG, "DPP: No chirp response received"); + offchannel_send_action_done(wpa_s); + wpas_dpp_chirp_next(wpa_s, NULL); +} + + +static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s, + unsigned int freq, const u8 *dst, + const u8 *src, const u8 *bssid, + const u8 *data, size_t data_len, + enum offchannel_send_action_result result) +{ + if (result == OFFCHANNEL_SEND_ACTION_FAILED) { + wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz", + wpa_s->dpp_chirp_freq); + if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next, + wpa_s, NULL) < 0) + wpas_dpp_chirp_stop(wpa_s); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response"); + if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout, + wpa_s, NULL) < 0) + wpas_dpp_chirp_stop(wpa_s); +} + + +static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s) +{ + wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(broadcast), wpa_s->dpp_chirp_freq, + DPP_PA_PRESENCE_ANNOUNCEMENT); + if (offchannel_send_action( + wpa_s, wpa_s->dpp_chirp_freq, broadcast, + wpa_s->own_addr, broadcast, + wpabuf_head(wpa_s->dpp_presence_announcement), + wpabuf_len(wpa_s->dpp_presence_announcement), + 2000, wpas_dpp_chirp_tx_status, 0) < 0) + wpas_dpp_chirp_stop(wpa_s); +} + + +static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ + struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi; + unsigned int i; + struct hostapd_hw_modes *mode; + int c; + struct wpa_bss *bss; + + if (!bi) + return; + + wpa_s->dpp_chirp_scan_done = 1; + + os_free(wpa_s->dpp_chirp_freqs); + wpa_s->dpp_chirp_freqs = NULL; + + /* Channels from own bootstrapping info */ + for (i = 0; i < bi->num_freq; i++) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, bi->freq[i]); + + /* Preferred chirping channels */ + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437); + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, + HOSTAPD_MODE_IEEE80211A, 0); + if (mode) { + int chan44 = 0, chan149 = 0; + + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if (chan->flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) + continue; + if (chan->freq == 5220) + chan44 = 1; + if (chan->freq == 5745) + chan149 = 1; + } + if (chan149) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745); + else if (chan44) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220); + } + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, + HOSTAPD_MODE_IEEE80211AD, 0); + if (mode) { + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if ((chan->flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) || + chan->freq != 60480) + continue; + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480); + break; + } + } + + /* Add channels from scan results for APs that advertise Configurator + * Connectivity element */ + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE)) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, + bss->freq); + } + + if (!wpa_s->dpp_chirp_freqs || + eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0) + wpas_dpp_chirp_stop(wpa_s); +} + + +static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + int i; + + if (wpa_s->dpp_chirp_listen) + wpas_dpp_listen_stop(wpa_s); + + if (wpa_s->dpp_chirp_freq == 0) { + if (wpa_s->dpp_chirp_round % 4 == 0 && + !wpa_s->dpp_chirp_scan_done) { + wpa_printf(MSG_DEBUG, + "DPP: Update channel list for chirping"); + wpa_s->scan_req = MANUAL_SCAN_REQ; + wpa_s->scan_res_handler = + wpas_dpp_chirp_scan_res_handler; + wpa_supplicant_req_scan(wpa_s, 0, 0); + return; + } + wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0]; + wpa_s->dpp_chirp_round++; + wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d", + wpa_s->dpp_chirp_round); + } else { + for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++) + if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq) + break; + if (!wpa_s->dpp_chirp_freqs[i]) { + wpa_printf(MSG_DEBUG, + "DPP: Previous chirp freq %d not found", + wpa_s->dpp_chirp_freq); + return; + } + i++; + if (wpa_s->dpp_chirp_freqs[i]) { + wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i]; + } else { + wpa_s->dpp_chirp_iter--; + if (wpa_s->dpp_chirp_iter <= 0) { + wpa_printf(MSG_DEBUG, + "DPP: Chirping iterations completed"); + wpas_dpp_chirp_stop(wpa_s); + return; + } + wpa_s->dpp_chirp_freq = 0; + wpa_s->dpp_chirp_scan_done = 0; + if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next, + wpa_s, NULL) < 0) { + wpas_dpp_chirp_stop(wpa_s); + return; + } + if (wpa_s->dpp_chirp_listen) { + wpa_printf(MSG_DEBUG, + "DPP: Listen on %d MHz during chirp 30 second wait", + wpa_s->dpp_chirp_listen); + wpas_dpp_listen_start(wpa_s, + wpa_s->dpp_chirp_listen); + } else { + wpa_printf(MSG_DEBUG, + "DPP: Wait 30 seconds before starting the next chirping round"); + } + return; + } + } + + wpas_dpp_chirp_start(wpa_s); +} + + +int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd) +{ + const char *pos; + int iter = 1, listen_freq = 0; + struct dpp_bootstrap_info *bi; + + pos = os_strstr(cmd, " own="); + if (!pos) + return -1; + pos += 5; + bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); + if (!bi) { + wpa_printf(MSG_DEBUG, + "DPP: Identified bootstrap info not found"); + return -1; + } + + pos = os_strstr(cmd, " iter="); + if (pos) { + iter = atoi(pos + 6); + if (iter <= 0) + return -1; + } + + pos = os_strstr(cmd, " listen="); + if (pos) { + listen_freq = atoi(pos + 8); + if (iter <= 0) + return -1; + } + + wpas_dpp_chirp_stop(wpa_s); + wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; + wpa_s->dpp_chirp_bi = bi; + wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi); + if (!wpa_s->dpp_presence_announcement) + return -1; + wpa_s->dpp_chirp_iter = iter; + wpa_s->dpp_chirp_round = 0; + wpa_s->dpp_chirp_scan_done = 0; + wpa_s->dpp_chirp_listen = listen_freq; + + return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL); +} + + +void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->dpp_presence_announcement) { + offchannel_send_action_done(wpa_s); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED); + } + wpa_s->dpp_chirp_bi = NULL; + wpabuf_free(wpa_s->dpp_presence_announcement); + wpa_s->dpp_presence_announcement = NULL; + if (wpa_s->dpp_chirp_listen) + wpas_dpp_listen_stop(wpa_s); + wpa_s->dpp_chirp_listen = 0; + wpa_s->dpp_chirp_freq = 0; + os_free(wpa_s->dpp_chirp_freqs); + wpa_s->dpp_chirp_freqs = NULL; + eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL); + if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) { + wpas_abort_ongoing_scan(wpa_s); + wpa_s->scan_res_handler = NULL; + } +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h index 5c3397a24..2ce378dc1 100644 --- a/wpa_supplicant/dpp_supplicant.h +++ b/wpa_supplicant/dpp_supplicant.h @@ -35,5 +35,7 @@ int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd); void wpas_dpp_connected(struct wpa_supplicant *wpa_s); void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s, enum dpp_status_error result); +int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd); +void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s); #endif /* DPP_SUPPLICANT_H */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 775bce89e..b71e33583 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1273,6 +1273,14 @@ struct wpa_supplicant { size_t dpp_last_ssid_len; #ifdef CONFIG_DPP2 struct dpp_pfs *dpp_pfs; + struct wpabuf *dpp_presence_announcement; + struct dpp_bootstrap_info *dpp_chirp_bi; + int dpp_chirp_freq; + int *dpp_chirp_freqs; + int dpp_chirp_iter; + int dpp_chirp_round; + int dpp_chirp_scan_done; + int dpp_chirp_listen; #endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS char *dpp_config_obj_override; From 6f5bc15bec4cdd504c553c930afab61807922652 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 14:03:04 +0200 Subject: [PATCH 0282/1105] DPP2: Configurator Connectivity indication Add a new hostapd configuration parameter dpp_configurator_connectivity=1 to request Configurator connectivity to be advertised for chirping Enrollees. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 ++ hostapd/hostapd.conf | 5 +++++ src/ap/ap_config.h | 1 + src/ap/beacon.c | 4 ++++ src/ap/ieee802_11.h | 3 +++ src/ap/ieee802_11_shared.c | 30 ++++++++++++++++++++++++++++++ 6 files changed, 45 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index bdae3be79..1e640c790 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4408,6 +4408,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "dpp_controller") == 0) { if (hostapd_dpp_controller_parse(bss, pos)) return 1; + } else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) { + bss->dpp_configurator_connectivity = atoi(pos); #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #ifdef CONFIG_OWE diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 6a8c2c5cf..bcddc6b30 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -2304,6 +2304,11 @@ own_ip_addr=127.0.0.1 #dpp_csign #dpp_controller +# Configurator Connectivity indication +# 0: no Configurator is currently connected (default) +# 1: advertise that a Configurator is available +#dpp_configurator_connectivity=0 + #### TDLS (IEEE 802.11z-2010) ################################################# # Prohibit use of TDLS in this BSS diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index f24257091..e0f645f7b 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -740,6 +740,7 @@ struct hostapd_bss_config { struct wpabuf *dpp_csign; #ifdef CONFIG_DPP2 struct dpp_controller_conf *dpp_controller; + int dpp_configurator_connectivity; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ diff --git a/src/ap/beacon.c b/src/ap/beacon.c index ff760a0d1..47ced9a16 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -468,6 +468,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, buflen += hostapd_mbo_ie_len(hapd); buflen += hostapd_eid_owe_trans_len(hapd); + buflen += hostapd_eid_dpp_cc_len(hapd); resp = os_zalloc(buflen); if (resp == NULL) @@ -612,6 +613,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos); pos = hostapd_eid_owe_trans(hapd, pos, (u8 *) resp + buflen - pos); + pos = hostapd_eid_dpp_cc(hapd, pos, (u8 *) resp + buflen - pos); if (hapd->conf->vendor_elements) { os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements), @@ -1164,6 +1166,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tail_len += hostapd_mbo_ie_len(hapd); tail_len += hostapd_eid_owe_trans_len(hapd); + tail_len += hostapd_eid_dpp_cc_len(hapd); tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { @@ -1328,6 +1331,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos); tailpos = hostapd_eid_owe_trans(hapd, tailpos, tail + tail_len - tailpos); + tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos); if (hapd->conf->vendor_elements) { os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 181cfaf0a..c7bdb4b2b 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -183,6 +183,9 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd); u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len); +size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd); +u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len); + int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, int ap_seg1_idx, int *bandwidth, int *seg1_idx); diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index a225639a9..113b4ef04 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -874,6 +874,36 @@ u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, } +size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd) +{ +#ifdef CONFIG_DPP2 + if (hapd->conf->dpp_configurator_connectivity) + return 6; +#endif /* CONFIG_DPP2 */ + return 0; +} + + +u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len) +{ +#ifdef CONFIG_DPP2 + u8 *pos = eid; + + if (!hapd->conf->dpp_configurator_connectivity || len < 6) + return pos; + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = DPP_CC_OUI_TYPE; + + return pos; +#endif /* CONFIG_DPP2 */ + return eid; +} + + void ap_copy_sta_supp_op_classes(struct sta_info *sta, const u8 *supp_op_classes, size_t supp_op_classes_len) From 06dd32903d95339c93b4eea5db2e12d2281da255 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 15:34:09 +0200 Subject: [PATCH 0283/1105] DPP2: Presence Announcement processing at Configurator Process received Presence Announcement frames and initiate Authentication exchange if matching information is available on the Configurator. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 34 ++++++++++++++++- src/common/dpp.h | 2 + wpa_supplicant/dpp_supplicant.c | 65 +++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 56abe507f..c71a6424f 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -2246,6 +2246,7 @@ static int dpp_channel_local_list(struct dpp_authentication *auth, static int dpp_prepare_channel_list(struct dpp_authentication *auth, + unsigned int neg_freq, struct hostapd_hw_modes *own_modes, u16 num_modes) { @@ -2253,6 +2254,14 @@ static int dpp_prepare_channel_list(struct dpp_authentication *auth, char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end; unsigned int i; + if (!own_modes) { + if (!neg_freq) + return -1; + auth->num_freq = 1; + auth->freq[0] = neg_freq; + return 0; + } + if (auth->peer_bi->num_freq > 0) res = dpp_channel_intersect(auth, own_modes, num_modes); else @@ -2392,7 +2401,7 @@ struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, auth->curve = peer_bi->curve; if (dpp_autogen_bootstrap_key(auth) < 0 || - dpp_prepare_channel_list(auth, own_modes, num_modes) < 0) + dpp_prepare_channel_list(auth, neg_freq, own_modes, num_modes) < 0) goto fail; #ifdef CONFIG_TESTING_OPTIONS @@ -2488,6 +2497,8 @@ struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, } #endif /* CONFIG_TESTING_OPTIONS */ + if (neg_freq && auth->num_freq == 1 && auth->freq[0] == neg_freq) + neg_freq = 0; auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash, i_pubkey_hash, neg_freq); if (!auth->req_msg) @@ -10597,10 +10608,29 @@ void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, if (*own_bi && *peer_bi) break; } - } +#ifdef CONFIG_DPP2 +struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp, + const u8 *hash) +{ + struct dpp_bootstrap_info *bi; + + if (!dpp) + return NULL; + + dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) { + if (!bi->own && os_memcmp(bi->pubkey_hash_chirp, hash, + SHA256_MAC_LEN) == 0) + return bi; + } + + return NULL; +} +#endif /* CONFIG_DPP2 */ + + static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi, struct dpp_bootstrap_info *peer_bi) { diff --git a/src/common/dpp.h b/src/common/dpp.h index 513918bb5..61be2184b 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -578,6 +578,8 @@ void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, const u8 *r_bootstrap, struct dpp_bootstrap_info **own_bi, struct dpp_bootstrap_info **peer_bi); +struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp, + const u8 *hash); int dpp_configurator_add(struct dpp_global *dpp, const char *cmd); int dpp_configurator_remove(struct dpp_global *dpp, const char *id); int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id, diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index c6d555662..45fd3a744 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1694,6 +1694,67 @@ static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi) wpas_dpp_chirp_stop(wpa_s); } + +static void +wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *r_bootstrap; + u16 r_bootstrap_len; + struct dpp_bootstrap_info *peer_bi; + struct dpp_authentication *auth; + + if (!wpa_s->dpp) + return; + + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Presence Announcement during ongoing Authentication"); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR, + MAC2STR(src)); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap); + if (!peer_bi) { + wpa_printf(MSG_DEBUG, + "DPP: No matching bootstrapping information found"); + return; + } + + auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL, + DPP_CAPAB_CONFIGURATOR, freq, NULL, 0); + if (!auth) + return; + wpas_dpp_set_testing_options(wpa_s, auth); + if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + auth->neg_freq = freq; + + if (!is_zero_ether_addr(peer_bi->mac_addr)) + os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN); + + wpa_s->dpp_auth = auth; + if (wpas_dpp_auth_init_next(wpa_s) < 0) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + } +} + #endif /* CONFIG_DPP2 */ @@ -2239,6 +2300,10 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, case DPP_PA_CONNECTION_STATUS_RESULT: wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len); break; + case DPP_PA_PRESENCE_ANNOUNCEMENT: + wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len, + freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, From db1ef82538f1d00a2e4a35b50ea508cf22a18aa9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 19:16:42 +0200 Subject: [PATCH 0284/1105] DPP2: Presence Announcement processing in AP/Relay Process the received Presence Announcement frames in AP/Relay. If a matching bootstrapping entry for the peer is found in a local Configurator, that Configurator is used. Otherwise, the frame is relayed to the first configured Controller (if available). Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ src/common/dpp.c | 12 ++++++-- 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index d2d081f1b..7b3690844 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1132,6 +1132,70 @@ static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd, } +static void +hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *r_bootstrap; + u16 r_bootstrap_len; + struct dpp_bootstrap_info *peer_bi; + struct dpp_authentication *auth; + + wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR, + MAC2STR(src)); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp, + r_bootstrap); + if (!peer_bi) { + if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, + src, hdr, buf, len, freq, NULL, + r_bootstrap) == 0) + return; + wpa_printf(MSG_DEBUG, + "DPP: No matching bootstrapping information found"); + return; + } + + if (hapd->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Presence Announcement during ongoing Authentication"); + return; + } + + auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, + peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL, + 0); + if (!auth) + return; + hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); + if (dpp_set_configurator(hapd->dpp_auth, + hapd->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + auth->neg_freq = freq; + + if (!is_zero_ether_addr(peer_bi->mac_addr)) + os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN); + + hapd->dpp_auth = auth; + if (hostapd_dpp_auth_init_next(hapd) < 0) { + dpp_auth_deinit(hapd->dpp_auth); + hapd->dpp_auth = NULL; + } +} + #endif /* CONFIG_DPP2 */ @@ -1581,6 +1645,10 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, case DPP_PA_CONNECTION_STATUS_RESULT: hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len); break; + case DPP_PA_PRESENCE_ANNOUNCEMENT: + hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len, + freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, diff --git a/src/common/dpp.c b/src/common/dpp.c index c71a6424f..7b4825ed2 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -11327,7 +11327,8 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, * continue that session (send this over TCP) and return 0. */ if (type != DPP_PA_PEER_DISCOVERY_REQ && - type != DPP_PA_PEER_DISCOVERY_RESP) { + type != DPP_PA_PEER_DISCOVERY_RESP && + type != DPP_PA_PRESENCE_ANNOUNCEMENT) { dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller, list) { dl_list_for_each(conn, &ctrl->conn, @@ -11342,7 +11343,14 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, if (!r_bootstrap) return -1; - ctrl = dpp_relay_controller_get(dpp, r_bootstrap); + if (type == DPP_PA_PRESENCE_ANNOUNCEMENT) { + /* TODO: Could send this to all configured Controllers. For now, + * only the first Controller is supported. */ + ctrl = dl_list_first(&dpp->controllers, + struct dpp_relay_controller, list); + } else { + ctrl = dpp_relay_controller_get(dpp, r_bootstrap); + } if (!ctrl) return -1; From fa5143feb3cbdb28ba548231db2d97404a1dfd37 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 19:29:44 +0200 Subject: [PATCH 0285/1105] DPP2: Presence Announcement processing in Controller Process the received Presence Announcement frames in Controller. If a matching bootstrapping entry for the peer is found, initiate DPP authentication to complete provisioning of the Enrollee. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/common/dpp.c b/src/common/dpp.c index 7b4825ed2..09f518429 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -11684,6 +11684,76 @@ static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn, } +static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + const u8 *r_bootstrap; + u16 r_bootstrap_len; + struct dpp_bootstrap_info *peer_bi; + struct dpp_authentication *auth; + struct dpp_global *dpp = conn->ctrl->global; + + if (conn->auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Presence Announcement during ongoing Authentication"); + return -1; + } + + wpa_printf(MSG_DEBUG, "DPP: Presence Announcement"); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + peer_bi = dpp_bootstrap_find_chirp(dpp, r_bootstrap); + if (!peer_bi) { + wpa_printf(MSG_DEBUG, + "DPP: No matching bootstrapping information found"); + return -1; + } + + auth = dpp_auth_init(dpp, dpp->msg_ctx, peer_bi, NULL, + DPP_CAPAB_CONFIGURATOR, -1, NULL, 0); + if (!auth) + return -1; + if (dpp_set_configurator(conn->auth, + conn->ctrl->configurator_params) < 0) { + dpp_auth_deinit(auth); + dpp_connection_remove(conn); + return -1; + } + + conn->auth = auth; + + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = wpabuf_alloc(4 + wpabuf_len(conn->auth->req_msg) - 1); + if (!conn->msg_out) + return -1; + wpabuf_put_be32(conn->msg_out, wpabuf_len(conn->auth->req_msg) - 1); + wpabuf_put_data(conn->msg_out, wpabuf_head_u8(conn->auth->req_msg) + 1, + wpabuf_len(conn->auth->req_msg) - 1); + + if (dpp_tcp_send(conn) == 1) { + if (!conn->write_eloop) { + if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, + conn, NULL) < 0) + return -1; + conn->write_eloop = 1; + } + } + + return 0; +} + + static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, size_t len) { @@ -11734,6 +11804,9 @@ static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, case DPP_PA_CONNECTION_STATUS_RESULT: return dpp_controller_rx_conn_status_result(conn, msg, pos, end - pos); + case DPP_PA_PRESENCE_ANNOUNCEMENT: + return dpp_controller_rx_presence_announcement(conn, msg, pos, + end - pos); default: /* TODO: missing messages types */ wpa_printf(MSG_DEBUG, From f1732b4d1a648f58abbd437036d05bb1390fa842 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 12:41:47 +0200 Subject: [PATCH 0286/1105] tests: DPP chirping Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 151 +++++++++++++++++++++++++++++++++-- tests/hwsim/wpasupplicant.py | 11 +++ 2 files changed, 156 insertions(+), 6 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 46d29d4bd..80133225e 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -4571,18 +4571,29 @@ def test_dpp_controller_relay(dev, apdev, params): dev[0].set("dpp_config_processing", "0", allow_fail=True) dev[1].request("DPP_CONTROLLER_STOP") -def run_dpp_controller_relay(dev, apdev, params): +def test_dpp_controller_relay_chirp(dev, apdev, params): + """DPP Controller/Relay with chirping""" + try: + run_dpp_controller_relay(dev, apdev, params, chirp=True) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + dev[1].request("DPP_CONTROLLER_STOP") + +def run_dpp_controller_relay(dev, apdev, params, chirp=False): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) prefix = "dpp_controller_relay" + if chirp: + prefix += "_chirp" cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap") wt = WlantestCapture('lo', cap_lo) # Controller conf_id = dev[1].dpp_configurator_add() - dev[1].set("dpp_configurator_params", - " conf=sta-dpp configurator=%d" % conf_id) + if not chirp: + dev[1].set("dpp_configurator_params", + " conf=sta-dpp configurator=%d" % conf_id) id_c = dev[1].dpp_bootstrap_gen() uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) res = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_c) @@ -4601,20 +4612,40 @@ def run_dpp_controller_relay(dev, apdev, params): params = {"ssid": "unconfigured", "channel": "6", "dpp_controller": "ipaddr=127.0.0.1 pkhash=" + pkhash} + if chirp: + params["channel"] = "11" + params["dpp_configurator_connectivity"] = "1" relay = hostapd.add_ap(apdev[1], params) check_dpp_capab(relay) # Enroll Relay to the network # TODO: Do this over TCP once direct Enrollee-over-TCP case is supported - id_h = relay.dpp_bootstrap_gen(chan="81/6", mac=True) + if chirp: + id_h = relay.dpp_bootstrap_gen(chan="81/11", mac=True) + else: + id_h = relay.dpp_bootstrap_gen(chan="81/6", mac=True) uri_r = relay.request("DPP_BOOTSTRAP_GET_URI %d" % id_h) dev[1].dpp_auth_init(uri=uri_r, conf="ap-dpp", configurator=conf_id) wait_auth_success(relay, dev[1], configurator=dev[1], enrollee=relay) update_hapd_config(relay) - # Initiate from Enrollee with broadcast DPP Authentication Request + # Initiate from Enrollee with broadcast DPP Authentication Request or + # using chirping dev[0].set("dpp_config_processing", "2") - dev[0].dpp_auth_init(uri=uri_c, role="enrollee") + if chirp: + id1 = dev[0].dpp_bootstrap_gen() + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + idc = dev[1].dpp_qr_code(uri) + dev[1].dpp_bootstrap_set(idc, conf="sta-dpp", configurator=conf_id) + if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=5" % id1): + raise Exception("DPP_CHIRP failed") + ev = relay.wait_event(["DPP-RX"], timeout=10) + if ev is None: + raise Exception("Presence Announcement not seen") + if "type=13" not in ev: + raise Exception("Unexpected DPP frame received: " + ev) + else: + dev[0].dpp_auth_init(uri=uri_c, role="enrollee") wait_auth_success(dev[1], dev[0], configurator=dev[1], enrollee=dev[0], allow_enrollee_failure=True, allow_configurator_failure=True) @@ -5039,3 +5070,111 @@ def test_dpp_with_p2p_device(dev, apdev): dev[0].dpp_auth_init(uri=uri1) wait_auth_success(wpas, dev[0], configurator=dev[0], enrollee=wpas, allow_enrollee_failure=True) + +def test_dpp_chirp(dev, apdev, params): + """DPP chirp [long]""" + if not params['long']: + raise HwsimSkip("Skip test case with long duration due to --long not specified") + check_dpp_capab(dev[0]) + dev[0].flush_scan_cache() + + params = {"ssid": "dpp", + "channel": "11"} + hapd = hostapd.add_ap(apdev[0], params) + check_dpp_capab(hapd) + dpp_cc = False + + id1 = dev[0].dpp_bootstrap_gen(chan="81/1") + if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=5" % id1): + raise Exception("DPP_CHIRP failed") + chan1 = 0 + chan6 = 0 + chan11 = 0 + for i in range(30): + ev = dev[0].wait_event(["DPP-CHIRP-STOPPED", + "DPP-TX "], timeout=60) + if ev is None: + raise Exception("DPP chirp stop not reported") + if "DPP-CHIRP-STOPPED" in ev: + break + if "type=13" not in ev: + continue + freq = int(ev.split(' ')[2].split('=')[1]) + if freq == 2412: + chan1 += 1 + elif freq == 2437: + chan6 += 1 + elif freq == 2462: + chan11 += 1 + if not dpp_cc: + hapd.set("dpp_configurator_connectivity", "1") + if "OK" not in hapd.request("UPDATE_BEACON"): + raise Exception("UPDATE_BEACON failed") + dpp_cc = True + if chan1 != 5 or chan6 != 5 or chan11 != 1: + raise Exception("Unexpected number of presence announcements sent: %d %d %d" % (chan1, chan6, chan11)) + +def test_dpp_chirp_listen(dev, apdev, params): + """DPP chirp with listen [long]""" + if not params['long']: + raise HwsimSkip("Skip test case with long duration due to --long not specified") + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + id1 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + + if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=2 listen=2412" % id1): + raise Exception("DPP_CHIRP failed") + for i in range(30): + ev = dev[0].wait_event(["DPP-CHIRP-STOPPED", + "DPP-TX "], timeout=60) + if ev is None: + raise Exception("DPP chirp stop not reported") + if "DPP-CHIRP-STOPPED" in ev: + break + +def test_dpp_chirp_configurator(dev, apdev): + """DPP chirp with a standalone Configurator""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + id1 = dev[0].dpp_bootstrap_gen(chan="81/1") + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + + conf_id = dev[1].dpp_configurator_add() + idc = dev[1].dpp_qr_code(uri) + dev[1].dpp_bootstrap_set(idc, conf="sta-dpp", configurator=conf_id) + dev[1].dpp_listen(2437) + + if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=2" % id1): + raise Exception("DPP_CHIRP failed") + + ev = dev[1].wait_event(["DPP-RX"], timeout=10) + if ev is None: + raise Exception("Presence Announcement not seen") + if "type=13" not in ev: + raise Exception("Unexpected DPP frame received: " + ev) + + wait_auth_success(dev[0], dev[1], dev[1], dev[0]) + +def test_dpp_chirp_configurator_inits(dev, apdev): + """DPP chirp with a standalone Configurator initiating""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + id1 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + + conf_id = dev[1].dpp_configurator_add() + idc = dev[1].dpp_qr_code(uri) + + if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=2 listen=2412" % id1): + raise Exception("DPP_CHIRP failed") + for i in range(2): + ev = dev[0].wait_event(["DPP-TX "], timeout=10) + if ev is None or "type=13" not in ev: + raise Exception("Presence Announcement not sent") + + dev[1].dpp_auth_init(uri=uri, conf="sta-dpp", configurator=conf_id) + wait_auth_success(dev[0], dev[1], dev[1], dev[0]) diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index d99e6889d..00fcc68d1 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1490,6 +1490,17 @@ class WpaSupplicant: raise Exception("Failed to generate bootstrapping info") return int(res) + def dpp_bootstrap_set(self, id, conf=None, configurator=None, extra=None): + cmd = "DPP_BOOTSTRAP_SET %d" % id + if extra: + cmd += " " + extra + if conf: + cmd += " conf=" + conf + if configurator is not None: + cmd += " configurator=%d" % configurator + if "OK" not in self.request(cmd): + raise Exception("Failed to set bootstrapping parameters") + def dpp_listen(self, freq, netrole=None, qr=None, role=None): cmd = "DPP_LISTEN " + str(freq) if netrole: From 80d0e50dc54f337afa6c88be4f1c44ff28f7abb7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 19:44:11 +0200 Subject: [PATCH 0287/1105] DPP2: Use a helper function for encapsulating TCP message This functionality was repeated for multiple different frames. Use a shared helper function to avoid such duplication. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 141 +++++++++++++---------------------------------- 1 file changed, 37 insertions(+), 104 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 09f518429..f0636b4ac 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -11095,6 +11095,32 @@ static int dpp_tcp_send(struct dpp_connection *conn) } +static int dpp_tcp_send_msg(struct dpp_connection *conn, + const struct wpabuf *msg) +{ + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1); + if (!conn->msg_out) + return -1; + wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1); + wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1, + wpabuf_len(msg) - 1); + + if (dpp_tcp_send(conn) == 1) { + if (!conn->write_eloop) { + if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, + conn, NULL) < 0) + return -1; + conn->write_eloop = 1; + } + } + + return 0; +} + + static void dpp_controller_start_gas_client(struct dpp_connection *conn) { struct dpp_authentication *auth = conn->auth; @@ -11108,27 +11134,8 @@ static void dpp_controller_start_gas_client(struct dpp_connection *conn) return; } - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = wpabuf_alloc(4 + wpabuf_len(buf) - 1); - if (!conn->msg_out) { - wpabuf_free(buf); - return; - } - wpabuf_put_be32(conn->msg_out, wpabuf_len(buf) - 1); - wpabuf_put_data(conn->msg_out, wpabuf_head_u8(buf) + 1, - wpabuf_len(buf) - 1); + dpp_tcp_send_msg(conn, buf); wpabuf_free(buf); - - if (dpp_tcp_send(conn) == 1) { - if (!conn->write_eloop) { - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, - conn, NULL) < 0) - return; - conn->write_eloop = 1; - } - } } @@ -11498,26 +11505,7 @@ static int dpp_controller_rx_auth_req(struct dpp_connection *conn, return -1; } - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = wpabuf_alloc(4 + wpabuf_len(conn->auth->resp_msg) - 1); - if (!conn->msg_out) - return -1; - wpabuf_put_be32(conn->msg_out, wpabuf_len(conn->auth->resp_msg) - 1); - wpabuf_put_data(conn->msg_out, wpabuf_head_u8(conn->auth->resp_msg) + 1, - wpabuf_len(conn->auth->resp_msg) - 1); - - if (dpp_tcp_send(conn) == 1) { - if (!conn->write_eloop) { - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, - conn, NULL) < 0) - return -1; - conn->write_eloop = 1; - } - } - - return 0; + return dpp_tcp_send_msg(conn, conn->auth->resp_msg); } @@ -11526,6 +11514,7 @@ static int dpp_controller_rx_auth_resp(struct dpp_connection *conn, { struct dpp_authentication *auth = conn->auth; struct wpabuf *msg; + int res; if (!auth) return -1; @@ -11544,30 +11533,10 @@ static int dpp_controller_rx_auth_resp(struct dpp_connection *conn, return -1; } - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1); - if (!conn->msg_out) { - wpabuf_free(msg); - return -1; - } - wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1); - wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1, - wpabuf_len(msg) - 1); - wpabuf_free(msg); - conn->on_tcp_tx_complete_auth_ok = 1; - if (dpp_tcp_send(conn) == 1) { - if (!conn->write_eloop) { - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, - conn, NULL) < 0) - return -1; - conn->write_eloop = 1; - } - } - - return 0; + res = dpp_tcp_send_msg(conn, msg); + wpabuf_free(msg); + return res; } @@ -11730,27 +11699,7 @@ static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, } conn->auth = auth; - - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = wpabuf_alloc(4 + wpabuf_len(conn->auth->req_msg) - 1); - if (!conn->msg_out) - return -1; - wpabuf_put_be32(conn->msg_out, wpabuf_len(conn->auth->req_msg) - 1); - wpabuf_put_data(conn->msg_out, wpabuf_head_u8(conn->auth->req_msg) + 1, - wpabuf_len(conn->auth->req_msg) - 1); - - if (dpp_tcp_send(conn) == 1) { - if (!conn->write_eloop) { - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, - conn, NULL) < 0) - return -1; - conn->write_eloop = 1; - } - } - - return 0; + return dpp_tcp_send_msg(conn, conn->auth->req_msg); } @@ -11901,7 +11850,7 @@ static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) { struct dpp_authentication *auth = conn->auth; int res; - struct wpabuf *msg, *encaps; + struct wpabuf *msg; enum dpp_status_error status; wpa_printf(MSG_DEBUG, @@ -11923,35 +11872,19 @@ static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK) return -1; -#ifdef CONFIG_DPP2 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result"); status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK; msg = dpp_build_conf_result(auth, status); if (!msg) return -1; - encaps = wpabuf_alloc(4 + wpabuf_len(msg) - 1); - if (!encaps) { - wpabuf_free(msg); - return -1; - } - wpabuf_put_be32(encaps, wpabuf_len(msg) - 1); - wpabuf_put_data(encaps, wpabuf_head_u8(msg) + 1, wpabuf_len(msg) - 1); - wpabuf_free(msg); - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", encaps); - - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = encaps; conn->on_tcp_tx_complete_remove = 1; - dpp_tcp_send(conn); + res = dpp_tcp_send_msg(conn, msg); + wpabuf_free(msg); /* This exchange will be terminated in the TX status handler */ - return 0; -#else /* CONFIG_DPP2 */ - return -1; -#endif /* CONFIG_DPP2 */ + return res; } From ef46f143bca2be900aa0d6d1b3bcec7e880889f2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 20:00:42 +0200 Subject: [PATCH 0288/1105] tests: dpp_controller_rx_failure to match implementation changes Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 80133225e..2365b5a36 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -4763,7 +4763,7 @@ def run_dpp_controller_rx_failure(dev, apdev): "eloop_sock_table_add_sock;?eloop_register_sock;dpp_controller_tcp_cb", "dpp_controller_rx", "dpp_controller_rx_auth_req", - "wpabuf_alloc;=dpp_controller_rx_auth_req"] + "wpabuf_alloc;=dpp_tcp_send_msg;dpp_controller_rx_auth_req"] cmd = "DPP_AUTH_INIT peer=%d tcp_addr=127.0.0.1" % peer for func in tests: with alloc_fail(dev[0], 1, func): From a3eda98c229bd22d4a93bf05263c8169e7e50d43 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 27 Mar 2020 21:05:44 +0200 Subject: [PATCH 0289/1105] tests: Skip background scans in beacon loss tests bgscan_learn_beacon_loss was failing quite frequently and it looks like the background scans were related to those failures. Since those scans are not really relevant to testing beacon loss, get rid of them in these test cases to avoid incorrect failures. Signed-off-by: Jouni Malinen --- tests/hwsim/test_bgscan.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_bgscan.py b/tests/hwsim/test_bgscan.py index fdbc03fe6..5951f82e0 100644 --- a/tests/hwsim/test_bgscan.py +++ b/tests/hwsim/test_bgscan.py @@ -78,7 +78,8 @@ def test_bgscan_simple_beacon_loss(dev, apdev): dev[0].set("disable_sa_query", "1") dev[0].connect("bgscan", ieee80211w="2", key_mgmt="WPA-PSK-SHA256", - psk="12345678", scan_freq="2412", bgscan="simple:1:-20:2") + psk="12345678", scan_freq="2412", + bgscan="simple:100:-20:200") hapd.set("ext_mgmt_frame_handling", "1") if "OK" not in hapd.request("STOP_AP"): raise Exception("Failed to stop AP") @@ -253,7 +254,7 @@ def test_bgscan_learn_beacon_loss(dev, apdev): dev[0].set("disable_sa_query", "1") dev[0].connect("bgscan", ieee80211w="2", key_mgmt="WPA-PSK-SHA256", - psk="12345678", scan_freq="2412", bgscan="learn:1:-20:2") + psk="12345678", scan_freq="2412", bgscan="learn:100:-20:200") hapd.set("ext_mgmt_frame_handling", "1") if "OK" not in hapd.request("STOP_AP"): raise Exception("Failed to stop AP") From 2b4f9ce2870aae14dee85e58e769014490e4edab Mon Sep 17 00:00:00 2001 From: Sathishkumar Muruganandam Date: Tue, 24 Mar 2020 16:34:42 +0530 Subject: [PATCH 0290/1105] hostapd: Add HE bit in BSSID Information field of own Neighbor Report Add definition for HE bit in neighbor report BSSID Information field from IEEE P802.11ax/D6.0, 9.4.2.36 Neighbor Report element. Signed-off-by: Sathishkumar Muruganandam --- src/ap/neighbor_db.c | 2 ++ src/common/ieee802_11_defs.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c index 4012ae4c3..01bf88623 100644 --- a/src/ap/neighbor_db.c +++ b/src/ap/neighbor_db.c @@ -256,6 +256,8 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd) /* VHT bit added in IEEE P802.11-REVmc/D4.3 */ if (vht) bssid_info |= NEI_REP_BSSID_INFO_VHT; + if (he) + bssid_info |= NEI_REP_BSSID_INFO_HE; } /* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */ diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 6c88dda46..8dc469881 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2094,7 +2094,7 @@ enum phy_type { PHY_TYPE_VHT = 9, }; -/* IEEE P802.11-REVmc/D5.0, 9.4.2.37 - Neighbor Report element */ +/* IEEE P802.11-REVmd/D3.0, 9.4.2.36 - Neighbor Report element */ /* BSSID Information Field */ #define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0) #define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1) @@ -2111,6 +2111,7 @@ enum phy_type { #define NEI_REP_BSSID_INFO_HT BIT(11) #define NEI_REP_BSSID_INFO_VHT BIT(12) #define NEI_REP_BSSID_INFO_FTM BIT(13) +#define NEI_REP_BSSID_INFO_HE BIT(14) /* * IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information From ca57d5f55322b48c5e6e2c882c95ce648dfc9096 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 12:22:28 +0200 Subject: [PATCH 0291/1105] Return an enum from wpa_validate_wpa_ie() This is more specific then returning a generic int and also allows the compiler to do more checks. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 79 +++++++++++++++++++++++++++++------------- src/ap/ieee802_11.c | 53 ++++++++++++++++------------ src/ap/wpa_auth.h | 15 ++++---- src/ap/wpa_auth_ie.c | 13 +++---- 4 files changed, 101 insertions(+), 59 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index baf3f7c3f..f80a3857b 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -109,7 +109,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, const u8 *req_ies, size_t req_ies_len, int reassoc) { struct sta_info *sta; - int new_assoc, res; + int new_assoc; + enum wpa_validate_result res; struct ieee802_11_elems elems; const u8 *ie; size_t ielen; @@ -323,33 +324,63 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, elems.rsnxe ? elems.rsnxe_len + 2 : 0, elems.mdie, elems.mdie_len, elems.owe_dh, elems.owe_dh_len); - if (res != WPA_IE_OK) { + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + switch (res) { + case WPA_IE_OK: + reason = WLAN_REASON_UNSPECIFIED; + status = WLAN_STATUS_SUCCESS; + break; + case WPA_INVALID_IE: + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + break; + case WPA_INVALID_GROUP: + reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; + status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + break; + case WPA_INVALID_PAIRWISE: + reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; + status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + break; + case WPA_INVALID_AKMP: + reason = WLAN_REASON_AKMP_NOT_VALID; + status = WLAN_STATUS_AKMP_NOT_VALID; + break; + case WPA_NOT_ENABLED: + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + break; + case WPA_ALLOC_FAIL: + reason = WLAN_REASON_UNSPECIFIED; + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + break; + case WPA_MGMT_FRAME_PROTECTION_VIOLATION: + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + break; + case WPA_INVALID_MGMT_GROUP_CIPHER: + reason = WLAN_REASON_CIPHER_SUITE_REJECTED; + status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + break; + case WPA_INVALID_MDIE: + reason = WLAN_REASON_INVALID_MDE; + status = WLAN_STATUS_INVALID_MDIE; + break; + case WPA_INVALID_PROTO: + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + break; + case WPA_INVALID_PMKID: + reason = WLAN_REASON_INVALID_PMKID; + status = WLAN_STATUS_INVALID_PMKID; + break; + } + if (status != WLAN_STATUS_SUCCESS) { wpa_printf(MSG_DEBUG, "WPA/RSN information element rejected? (res %u)", res); wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); - if (res == WPA_INVALID_GROUP) { - reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; - status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - } else if (res == WPA_INVALID_PAIRWISE) { - reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; - status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - } else if (res == WPA_INVALID_AKMP) { - reason = WLAN_REASON_AKMP_NOT_VALID; - status = WLAN_STATUS_AKMP_NOT_VALID; - } else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) { - reason = WLAN_REASON_INVALID_IE; - status = WLAN_STATUS_INVALID_IE; - } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) { - reason = WLAN_REASON_CIPHER_SUITE_REJECTED; - status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; - } else if (res == WPA_INVALID_PMKID) { - reason = WLAN_REASON_INVALID_PMKID; - status = WLAN_STATUS_INVALID_PMKID; - } else { - reason = WLAN_REASON_INVALID_IE; - status = WLAN_STATUS_INVALID_IE; - } goto fail; } diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 1f58ec87c..50120c448 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1611,27 +1611,35 @@ static int auth_sae_queued_addr(struct hostapd_data *hapd, const u8 *addr) #endif /* CONFIG_SAE */ -static u16 wpa_res_to_status_code(int res) +static u16 wpa_res_to_status_code(enum wpa_validate_result res) { - if (res == WPA_INVALID_GROUP) - return WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - if (res == WPA_INVALID_PAIRWISE) - return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - if (res == WPA_INVALID_AKMP) - return WLAN_STATUS_AKMP_NOT_VALID; - if (res == WPA_ALLOC_FAIL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) - return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; - if (res == WPA_INVALID_MGMT_GROUP_CIPHER) - return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; - if (res == WPA_INVALID_MDIE) - return WLAN_STATUS_INVALID_MDIE; - if (res == WPA_INVALID_PMKID) - return WLAN_STATUS_INVALID_PMKID; - if (res != WPA_IE_OK) + switch (res) { + case WPA_IE_OK: + return WLAN_STATUS_SUCCESS; + case WPA_INVALID_IE: return WLAN_STATUS_INVALID_IE; - return WLAN_STATUS_SUCCESS; + case WPA_INVALID_GROUP: + return WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + case WPA_INVALID_PAIRWISE: + return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + case WPA_INVALID_AKMP: + return WLAN_STATUS_AKMP_NOT_VALID; + case WPA_NOT_ENABLED: + return WLAN_STATUS_INVALID_IE; + case WPA_ALLOC_FAIL: + return WLAN_STATUS_UNSPECIFIED_FAILURE; + case WPA_MGMT_FRAME_PROTECTION_VIOLATION: + return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + case WPA_INVALID_MGMT_GROUP_CIPHER: + return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + case WPA_INVALID_MDIE: + return WLAN_STATUS_INVALID_MDIE; + case WPA_INVALID_PROTO: + return WLAN_STATUS_INVALID_IE; + case WPA_INVALID_PMKID: + return WLAN_STATUS_INVALID_PMKID; + } + return WLAN_STATUS_INVALID_IE; } @@ -1651,7 +1659,7 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, u16 resp = WLAN_STATUS_SUCCESS; const u8 *end; struct ieee802_11_elems elems; - int res; + enum wpa_validate_result res; struct wpa_ie_data rsn; struct rsn_pmksa_cache_entry *pmksa = NULL; @@ -3044,7 +3052,7 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd, u16 status; u8 *owe_buf, ie[256 * 2]; size_t ie_len = 0; - int res; + enum wpa_validate_result res; if (!rsn_ie || rsn_ie_len < 2) { wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq"); @@ -3255,7 +3263,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, } if (hapd->conf->wpa && wpa_ie) { - int res; + enum wpa_validate_result res; + wpa_ie -= 2; wpa_ie_len += 2; if (sta->wpa_sm == NULL) diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 955445209..85fb3d6f6 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -331,19 +331,20 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth); int wpa_reconfig(struct wpa_authenticator *wpa_auth, struct wpa_auth_config *conf); -enum { +enum wpa_validate_result { WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE, WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL, WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER, WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID }; -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int freq, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *rsnxe, size_t rsnxe_len, - const u8 *mdie, size_t mdie_len, - const u8 *owe_dh, size_t owe_dh_len); +enum wpa_validate_result +wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int freq, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *rsnxe, size_t rsnxe_len, + const u8 *mdie, size_t mdie_len, + const u8 *owe_dh, size_t owe_dh_len); int wpa_validate_osen(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, const u8 *osen_ie, size_t osen_ie_len); diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 11153e0b8..496e8e946 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -548,12 +548,13 @@ static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) } -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int freq, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *rsnxe, size_t rsnxe_len, - const u8 *mdie, size_t mdie_len, - const u8 *owe_dh, size_t owe_dh_len) +enum wpa_validate_result +wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int freq, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *rsnxe, size_t rsnxe_len, + const u8 *mdie, size_t mdie_len, + const u8 *owe_dh, size_t owe_dh_len) { struct wpa_auth_config *conf = &wpa_auth->conf; struct wpa_ie_data data; From 7c021dec3a95803fc129d8533adcaeea82910c9c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 12:33:48 +0200 Subject: [PATCH 0292/1105] DPP2: Allow AP to require or reject PFS The new hostapd configuration parameter dpp_pfs can be used to specify how PFS is applied to associations. The default behavior (dpp_pfs=0) remains same as it was previously, i.e., allow the station to decide whether to use PFS. PFS use can now be required (dpp_pfs=1) or rejected (dpp_pfs=2). Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 10 ++++++++++ hostapd/hostapd.conf | 6 ++++++ src/ap/ap_config.h | 1 + src/ap/drv_callbacks.c | 4 ++++ src/ap/ieee802_11.c | 2 ++ src/ap/wpa_auth.h | 6 +++++- src/ap/wpa_auth_glue.c | 3 +++ src/ap/wpa_auth_ie.c | 10 ++++++++++ 8 files changed, 41 insertions(+), 1 deletion(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 1e640c790..7a184c440 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4410,6 +4410,16 @@ static int hostapd_config_fill(struct hostapd_config *conf, return 1; } else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) { bss->dpp_configurator_connectivity = atoi(pos); + } else if (os_strcmp(buf, "dpp_pfs") == 0) { + int val = atoi(pos); + + if (val < 0 || val > 2) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid dpp_pfs value '%s'", + line, pos); + return -1; + } + bss->dpp_pfs = val; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #ifdef CONFIG_OWE diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index bcddc6b30..812c09a9f 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -2309,6 +2309,12 @@ own_ip_addr=127.0.0.1 # 1: advertise that a Configurator is available #dpp_configurator_connectivity=0 +# DPP PFS +# 0: allow PFS to be used or not used (default) +# 1: require PFS to be used (note: not compatible with DPP R1) +# 2: do not allow PFS to be used +#dpp_pfs=0 + #### TDLS (IEEE 802.11z-2010) ################################################# # Prohibit use of TDLS in this BSS diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index e0f645f7b..7930fc374 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -741,6 +741,7 @@ struct hostapd_bss_config { #ifdef CONFIG_DPP2 struct dpp_controller_conf *dpp_controller; int dpp_configurator_connectivity; + int dpp_pfs; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index f80a3857b..64cbd84d8 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -375,6 +375,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, reason = WLAN_REASON_INVALID_PMKID; status = WLAN_STATUS_INVALID_PMKID; break; + case WPA_DENIED_OTHER_REASON: + reason = WLAN_REASON_UNSPECIFIED; + status = WLAN_STATUS_ASSOC_DENIED_UNSPEC; + break; } if (status != WLAN_STATUS_SUCCESS) { wpa_printf(MSG_DEBUG, diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 50120c448..045a6cbcd 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1638,6 +1638,8 @@ static u16 wpa_res_to_status_code(enum wpa_validate_result res) return WLAN_STATUS_INVALID_IE; case WPA_INVALID_PMKID: return WLAN_STATUS_INVALID_PMKID; + case WPA_DENIED_OTHER_REASON: + return WLAN_STATUS_ASSOC_DENIED_UNSPEC; } return WLAN_STATUS_INVALID_IE; } diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 85fb3d6f6..868aaa1fa 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -252,6 +252,9 @@ struct wpa_auth_config { int sae_pwe; int owe_ptk_workaround; u8 transition_disable; +#ifdef CONFIG_DPP2 + int dpp_pfs; +#endif /* CONFIG_DPP2 */ }; typedef enum { @@ -335,7 +338,8 @@ enum wpa_validate_result { WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE, WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL, WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER, - WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID + WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID, + WPA_DENIED_OTHER_REASON }; enum wpa_validate_result diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 41df213b9..7a1ed24e8 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -196,6 +196,9 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wconf->owe_ptk_workaround = conf->owe_ptk_workaround; #endif /* CONFIG_OWE */ wconf->transition_disable = conf->transition_disable; +#ifdef CONFIG_DPP2 + wconf->dpp_pfs = conf->dpp_pfs; +#endif /* CONFIG_DPP2 */ } diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 496e8e946..2ac1df47e 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -864,6 +864,16 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP2 + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && + ((conf->dpp_pfs == 1 && !owe_dh) || + (conf->dpp_pfs == 2 && owe_dh))) { + wpa_printf(MSG_DEBUG, "DPP: PFS %s", + conf->dpp_pfs == 1 ? "required" : "not allowed"); + return WPA_DENIED_OTHER_REASON; + } +#endif /* CONFIG_DPP2 */ + sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0); if (sm->pairwise < 0) return WPA_INVALID_PAIRWISE; From 5058f771d917a5683b0c9a6eca3ddc4519ff901f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 15:06:15 +0200 Subject: [PATCH 0293/1105] DPP2: Allow station to require or not allow PFS The new wpa_supplicant network profile parameter dpp_pfs can be used to specify how PFS is applied to associations. The default behavior (dpp_pfs=0) remains same as it was previously, i.e., try to use PFS if the AP supports it. PFS use can now be required (dpp_pfs=1) or disabled (dpp_pfs=2). This is also working around an interoperability issue of DPP R2 STA with certain hostapd builds that included both OWE and DPP functionality. That issue was introduced by commit 09368515d130 ("OWE: Process Diffie-Hellman Parameter element in AP mode") and removed by commit 16a4e931f03e ("OWE: Allow Diffie-Hellman Parameter element to be included with DPP"). hostapd builds between those two commits would reject DPP association attempt with PFS. The new wpa_supplicant default (dpp_pfs=0) behavior is to automatically try to connect again with PFS disabled if that happens. Signed-off-by: Jouni Malinen --- wpa_supplicant/config.c | 1 + wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 16 +++++++++++++ wpa_supplicant/ctrl_iface.c | 1 + wpa_supplicant/events.c | 37 ++++++++++++++++++++++++++++++ wpa_supplicant/sme.c | 4 +++- wpa_supplicant/wpa_supplicant.c | 3 ++- wpa_supplicant/wpa_supplicant.conf | 6 +++++ wpa_supplicant/wpa_supplicant_i.h | 1 + 9 files changed, 68 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index e86fd7f81..563d18fb8 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2570,6 +2570,7 @@ static const struct parse_data ssid_fields[] = { { STR_LEN(dpp_netaccesskey) }, { INT(dpp_netaccesskey_expiry) }, { STR_LEN(dpp_csign) }, + { INT_RANGE(dpp_pfs, 0, 2) }, #endif /* CONFIG_DPP */ { INT_RANGE(owe_group, 0, 65535) }, { INT_RANGE(owe_only, 0, 1) }, diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 74068d66c..074b3b31a 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -928,6 +928,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(dpp_netaccesskey); INT(dpp_netaccesskey_expiry); STR(dpp_csign); + INT(dpp_pfs); #endif /* CONFIG_DPP */ INT(owe_group); INT(owe_only); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 618145e8b..c214b6c3f 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -1002,6 +1002,22 @@ struct wpa_ssid { */ size_t dpp_csign_len; + /** + * dpp_pfs - DPP PFS + * 0: allow PFS to be used or not used + * 1: require PFS to be used (note: not compatible with DPP R1) + * 2: do not allow PFS to be used + */ + int dpp_pfs; + + /** + * dpp_pfs_fallback - DPP PFS fallback selection + * + * This is an internally used variable (i.e., not used in external + * configuration) to track state of the DPP PFS fallback mechanism. + */ + int dpp_pfs_fallback; + /** * owe_group - OWE DH Group * diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index a2b4ee765..7301d50fc 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8106,6 +8106,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->dpp_resp_retry_time = 0; #ifdef CONFIG_DPP2 wpas_dpp_chirp_stop(wpa_s); + wpa_s->dpp_pfs_fallback = 0; #endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 3758373d4..e8b8a9c98 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3196,6 +3196,10 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, #ifdef CONFIG_MBO wpas_mbo_check_pmf(wpa_s, bss, wpa_s->current_ssid); #endif /* CONFIG_MBO */ + +#ifdef CONFIG_DPP2 + wpa_s->dpp_pfs_fallback = 0; +#endif /* CONFIG_DPP2 */ } @@ -4364,6 +4368,39 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP2 + /* Try to follow AP's PFS policy. WLAN_STATUS_ASSOC_DENIED_UNSPEC is + * the status code defined in the DPP R2 tech spec. + * WLAN_STATUS_AKMP_NOT_VALID is addressed in the same manner as an + * interoperability workaround with older hostapd implementation. */ + if (wpa_s->current_ssid && + wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP && + wpa_s->current_ssid->dpp_pfs == 0 && + (data->assoc_reject.status_code == + WLAN_STATUS_ASSOC_DENIED_UNSPEC || + data->assoc_reject.status_code == WLAN_STATUS_AKMP_NOT_VALID)) { + struct wpa_ssid *ssid = wpa_s->current_ssid; + struct wpa_bss *bss = wpa_s->current_bss; + + wpa_s->current_ssid->dpp_pfs_fallback ^= 1; + if (!bss) + bss = wpa_supplicant_get_new_bss(wpa_s, bssid); + if (!bss || wpa_s->dpp_pfs_fallback) { + wpa_printf(MSG_DEBUG, + "DPP: Updated PFS policy for next try"); + wpas_connection_failed(wpa_s, bssid); + wpa_supplicant_mark_disassoc(wpa_s); + return; + } + wpa_printf(MSG_DEBUG, "DPP: Try again with updated PFS policy"); + wpa_s->dpp_pfs_fallback = 1; + wpas_connect_work_done(wpa_s); + wpa_supplicant_mark_disassoc(wpa_s); + wpa_supplicant_connect(wpa_s, bss, ssid); + return; + } +#endif /* CONFIG_DPP2 */ + #ifdef CONFIG_MBO if (data->assoc_reject.status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS && diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 71b67e4a7..a35310157 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1793,7 +1793,9 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, #ifdef CONFIG_DPP2 if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid && - wpa_s->current_ssid->dpp_netaccesskey) { + wpa_s->current_ssid->dpp_netaccesskey && + wpa_s->current_ssid->dpp_pfs != 2 && + !wpa_s->current_ssid->dpp_pfs_fallback) { struct wpa_ssid *ssid = wpa_s->current_ssid; dpp_pfs_free(wpa_s->dpp_pfs); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index a01a3e748..8016fd3ac 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3071,7 +3071,8 @@ static u8 * wpas_populate_assoc_ies( #ifdef CONFIG_DPP2 if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP && - ssid->dpp_netaccesskey) { + ssid->dpp_netaccesskey && + ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) { dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 591e1343f..f242c3a9e 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1461,6 +1461,12 @@ fast_reauth=1 # 1-65535 = DH Group to use for FILS PFS #fils_dh_group=0 +# DPP PFS +# 0: allow PFS to be used or not used (default) +# 1: require PFS to be used (note: not compatible with DPP R1) +# 2: do not allow PFS to be used +#dpp_pfs=0 + # MAC address policy # 0 = use permanent MAC address # 1 = use random MAC address for each ESS connection diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index b71e33583..b7cf7f4df 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1273,6 +1273,7 @@ struct wpa_supplicant { size_t dpp_last_ssid_len; #ifdef CONFIG_DPP2 struct dpp_pfs *dpp_pfs; + int dpp_pfs_fallback; struct wpabuf *dpp_presence_announcement; struct dpp_bootstrap_info *dpp_chirp_bi; int dpp_chirp_freq; From e96d319140f741207fea26d000b9fc8b76b8084b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 15:05:57 +0200 Subject: [PATCH 0294/1105] tests: DPP PFS Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 61 ++++++++++++++++++++++++++++++++++++ tests/hwsim/wpasupplicant.py | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 2365b5a36..2b99bcf85 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5178,3 +5178,64 @@ def test_dpp_chirp_configurator_inits(dev, apdev): dev[1].dpp_auth_init(uri=uri, conf="sta-dpp", configurator=conf_id) wait_auth_success(dev[0], dev[1], dev[1], dev[0]) + +def start_dpp_pfs_ap(apdev, pfs): + params = {"ssid": "dpp", + "wpa": "2", + "wpa_key_mgmt": "DPP", + "dpp_pfs": str(pfs), + "ieee80211w": "2", + "rsn_pairwise": "CCMP", + "dpp_connector": params1_ap_connector, + "dpp_csign": params1_csign, + "dpp_netaccesskey": params1_ap_netaccesskey} + try: + hapd = hostapd.add_ap(apdev, params) + except: + raise HwsimSkip("DPP not supported") + return hapd + +def run_dpp_pfs_sta(dev, pfs, fail=False): + dev.connect("dpp", key_mgmt="DPP", scan_freq="2412", + ieee80211w="2", dpp_pfs=str(pfs), + dpp_csign=params1_csign, + dpp_connector=params1_sta_connector, + dpp_netaccesskey=params1_sta_netaccesskey, + wait_connect=not fail) + if fail: + for i in range(2): + ev = dev.wait_event(["CTRL-EVENT-ASSOC-REJECT", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev is None: + raise Exception("Connection result not reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + dev.request("REMOVE_NETWORK all") + else: + dev.request("REMOVE_NETWORK all") + dev.wait_disconnected() + dev.dump_monitor() + +def test_dpp_pfs_ap_0(dev, apdev): + """DPP PFS AP default""" + check_dpp_capab(dev[0]) + hapd = start_dpp_pfs_ap(apdev[0], 0) + run_dpp_pfs_sta(dev[0], 0) + run_dpp_pfs_sta(dev[0], 1) + run_dpp_pfs_sta(dev[0], 2) + +def test_dpp_pfs_ap_1(dev, apdev): + """DPP PFS AP required""" + check_dpp_capab(dev[0]) + hapd = start_dpp_pfs_ap(apdev[0], 1) + run_dpp_pfs_sta(dev[0], 0) + run_dpp_pfs_sta(dev[0], 1) + run_dpp_pfs_sta(dev[0], 2, fail=True) + +def test_dpp_pfs_ap_2(dev, apdev): + """DPP PFS AP not allowed""" + check_dpp_capab(dev[0]) + hapd = start_dpp_pfs_ap(apdev[0], 2) + run_dpp_pfs_sta(dev[0], 0) + run_dpp_pfs_sta(dev[0], 1, fail=True) + run_dpp_pfs_sta(dev[0], 2) diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 00fcc68d1..e273084ac 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1099,7 +1099,7 @@ class WpaSupplicant: "bssid_whitelist", "mem_only_psk", "eap_workaround", "engine", "fils_dh_group", "bssid_hint", "dpp_csign", "dpp_csign_expiry", - "dpp_netaccesskey", "dpp_netaccesskey_expiry", + "dpp_netaccesskey", "dpp_netaccesskey_expiry", "dpp_pfs", "group_mgmt", "owe_group", "owe_only", "owe_ptk_workaround", "roaming_consortium_selection", "ocv", From 1f4e9946bcbb571c17e19bd124adbc8bab3f5270 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 16:31:14 +0200 Subject: [PATCH 0295/1105] Sync with mac80211-next.git include/uapi/linux/nl80211.h This brings in nl80211 definitions as of 2020-02-20. Signed-off-by: Jouni Malinen --- src/drivers/nl80211_copy.h | 171 ++++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 2 deletions(-) diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index 934e62fe8..2b6911618 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -11,7 +11,7 @@ * Copyright 2008 Jouni Malinen * Copyright 2008 Colin McCabe * Copyright 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -264,6 +264,29 @@ * %NL80211_ATTR_VLAN_ID. */ +/** + * DOC: TID configuration + * + * TID config support can be checked in the %NL80211_ATTR_TID_CONFIG + * attribute given in wiphy capabilities. + * + * The necessary configuration parameters are mentioned in + * &enum nl80211_tid_config_attr and it will be passed to the + * %NL80211_CMD_SET_TID_CONFIG command in %NL80211_ATTR_TID_CONFIG. + * + * If the configuration needs to be applied for specific peer then the MAC + * address of the peer needs to be passed in %NL80211_ATTR_MAC, otherwise the + * configuration will be applied for all the connected peers in the vif except + * any peers that have peer specific configuration for the TID by default; if + * the %NL80211_TID_CONFIG_ATTR_OVERRIDE flag is set, peer specific values + * will be overwritten. + * + * All this configuration is valid only for STA's current connection + * i.e. the configuration will be reset to default when the STA connects back + * after disconnection/roaming, and this configuration will be cleared when + * the interface goes down. + */ + /** * enum nl80211_commands - supported nl80211 commands * @@ -1125,6 +1148,9 @@ * peer MAC address and %NL80211_ATTR_FRAME is used to specify the frame * content. The frame is ethernet data. * + * @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration + * is passed using %NL80211_ATTR_TID_CONFIG attribute. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1349,6 +1375,8 @@ enum nl80211_commands { NL80211_CMD_PROBE_MESH_LINK, + NL80211_CMD_SET_TID_CONFIG, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1604,7 +1632,8 @@ enum nl80211_commands { * flag is included, then control port frames are sent over NL80211 instead * using %CMD_CONTROL_PORT_FRAME. If control port routing over NL80211 is * to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER - * flag. + * flag. When used with %NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, pre-auth + * frames are not forwared over the control port. * * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. * We recommend using nested, driver-specific attributes within this. @@ -2409,6 +2438,38 @@ enum nl80211_commands { * %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not * advertised for a specific interface type. * + * @NL80211_ATTR_TID_CONFIG: TID specific configuration in a + * nested attribute with &enum nl80211_tid_config_attr sub-attributes; + * on output (in wiphy attributes) it contains only the feature sub- + * attributes. + * + * @NL80211_ATTR_CONTROL_PORT_NO_PREAUTH: disable preauth frame rx on control + * port in order to forward/receive them as ordinary data frames. + * + * @NL80211_ATTR_PMK_LIFETIME: Maximum lifetime for PMKSA in seconds (u32, + * dot11RSNAConfigPMKReauthThreshold; 0 is not a valid value). + * An optional parameter configured through %NL80211_CMD_SET_PMKSA. + * Drivers that trigger roaming need to know the lifetime of the + * configured PMKSA for triggering the full vs. PMKSA caching based + * authentication. This timeout helps authentication methods like SAE, + * where PMK gets updated only by going through a full (new SAE) + * authentication instead of getting updated during an association for EAP + * authentication. No new full authentication within the PMK expiry shall + * result in a disassociation at the end of the lifetime. + * + * @NL80211_ATTR_PMK_REAUTH_THRESHOLD: Reauthentication threshold time, in + * terms of percentage of %NL80211_ATTR_PMK_LIFETIME + * (u8, dot11RSNAConfigPMKReauthThreshold, 1..100). This is an optional + * parameter configured through %NL80211_CMD_SET_PMKSA. Requests the + * driver to trigger a full authentication roam (without PMKSA caching) + * after the reauthentication threshold time, but before the PMK lifetime + * has expired. + * + * Authentication methods like SAE need to be able to generate a new PMKSA + * entry without having to force a disconnection after the PMK timeout. If + * no roaming occurs between the reauth threshold and PMK expiration, + * disassociation is still forced. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2877,6 +2938,13 @@ enum nl80211_attrs { NL80211_ATTR_IFTYPE_AKM_SUITES, + NL80211_ATTR_TID_CONFIG, + + NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, + + NL80211_ATTR_PMK_LIFETIME, + NL80211_ATTR_PMK_REAUTH_THRESHOLD, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -4722,6 +4790,69 @@ enum nl80211_tx_power_setting { NL80211_TX_POWER_FIXED, }; +/** + * enum nl80211_tid_config - TID config state + * @NL80211_TID_CONFIG_ENABLE: Enable config for the TID + * @NL80211_TID_CONFIG_DISABLE: Disable config for the TID + */ +enum nl80211_tid_config { + NL80211_TID_CONFIG_ENABLE, + NL80211_TID_CONFIG_DISABLE, +}; + +/* enum nl80211_tid_config_attr - TID specific configuration. + * @NL80211_TID_CONFIG_ATTR_PAD: pad attribute for 64-bit values + * @NL80211_TID_CONFIG_ATTR_VIF_SUPP: a bitmap (u64) of attributes supported + * for per-vif configuration; doesn't list the ones that are generic + * (%NL80211_TID_CONFIG_ATTR_TIDS, %NL80211_TID_CONFIG_ATTR_OVERRIDE). + * @NL80211_TID_CONFIG_ATTR_PEER_SUPP: same as the previous per-vif one, but + * per peer instead. + * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribue, if no peer + * is selected, if set indicates that the new configuration overrides + * all previous peer configurations, otherwise previous peer specific + * configurations should be left untouched. If peer is selected then + * it will reset particular TID configuration of that peer and it will + * not accept other TID config attributes along with peer. + * @NL80211_TID_CONFIG_ATTR_TIDS: a bitmask value of TIDs (bit 0 to 7) + * Its type is u16. + * @NL80211_TID_CONFIG_ATTR_NOACK: Configure ack policy for the TID. + * specified in %NL80211_TID_CONFIG_ATTR_TID. see %enum nl80211_tid_config. + * Its type is u8. + * @NL80211_TID_CONFIG_ATTR_RETRY_SHORT: Number of retries used with data frame + * transmission, user-space sets this configuration in + * &NL80211_CMD_SET_TID_CONFIG. It is u8 type, min value is 1 and + * the max value is advertised by the driver in this attribute on + * output in wiphy capabilities. + * @NL80211_TID_CONFIG_ATTR_RETRY_LONG: Number of retries used with data frame + * transmission, user-space sets this configuration in + * &NL80211_CMD_SET_TID_CONFIG. Its type is u8, min value is 1 and + * the max value is advertised by the driver in this attribute on + * output in wiphy capabilities. + * @NL80211_TID_CONFIG_ATTR_AMPDU_CTRL: Enable/Disable aggregation for the TIDs + * specified in %NL80211_TID_CONFIG_ATTR_TIDS. Its type is u8, using + * the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL: Enable/Disable RTS_CTS for the TIDs + * specified in %NL80211_TID_CONFIG_ATTR_TIDS. It is u8 type, using + * the values from &nl80211_tid_config. + */ +enum nl80211_tid_config_attr { + __NL80211_TID_CONFIG_ATTR_INVALID, + NL80211_TID_CONFIG_ATTR_PAD, + NL80211_TID_CONFIG_ATTR_VIF_SUPP, + NL80211_TID_CONFIG_ATTR_PEER_SUPP, + NL80211_TID_CONFIG_ATTR_OVERRIDE, + NL80211_TID_CONFIG_ATTR_TIDS, + NL80211_TID_CONFIG_ATTR_NOACK, + NL80211_TID_CONFIG_ATTR_RETRY_SHORT, + NL80211_TID_CONFIG_ATTR_RETRY_LONG, + NL80211_TID_CONFIG_ATTR_AMPDU_CTRL, + NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL, + + /* keep last */ + __NL80211_TID_CONFIG_ATTR_AFTER_LAST, + NL80211_TID_CONFIG_ATTR_MAX = __NL80211_TID_CONFIG_ATTR_AFTER_LAST - 1 +}; + /** * enum nl80211_packet_pattern_attr - packet pattern attribute * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute @@ -5544,6 +5675,15 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection * and can receive key configuration for BIGTK using key indexes 6 and 7. * + * @NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH: The driver can disable the + * forwarding of preauth frames over the control port. They are then + * handled as ordinary data frames. + * + * @NL80211_EXT_FEATURE_PROTECTED_TWT: Driver supports protected TWT frames + * + * @NL80211_EXT_FEATURE_DEL_IBSS_STA: The driver supports removing stations + * in IBSS mode, essentially by dropping their state. + * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ @@ -5592,6 +5732,9 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_VLAN_OFFLOAD, NL80211_EXT_FEATURE_AQL, NL80211_EXT_FEATURE_BEACON_PROTECTION, + NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH, + NL80211_EXT_FEATURE_PROTECTED_TWT, + NL80211_EXT_FEATURE_DEL_IBSS_STA, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, @@ -6214,12 +6357,14 @@ enum nl80211_ftm_responder_stats { * @NL80211_PREAMBLE_HT: HT preamble * @NL80211_PREAMBLE_VHT: VHT preamble * @NL80211_PREAMBLE_DMG: DMG preamble + * @NL80211_PREAMBLE_HE: HE preamble */ enum nl80211_preamble { NL80211_PREAMBLE_LEGACY, NL80211_PREAMBLE_HT, NL80211_PREAMBLE_VHT, NL80211_PREAMBLE_DMG, + NL80211_PREAMBLE_HE, }; /** @@ -6412,6 +6557,10 @@ enum nl80211_peer_measurement_attrs { * is valid) * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST: u32 attribute indicating * the maximum FTMs per burst (if not present anything is valid) + * @NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED: flag attribute indicating if + * trigger based ranging measurement is supported + * @NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED: flag attribute indicating + * if non trigger based ranging measurement is supported * * @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal * @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number @@ -6427,6 +6576,8 @@ enum nl80211_peer_measurement_ftm_capa { NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST, + NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED, + NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED, /* keep last */ NUM_NL80211_PMSR_FTM_CAPA_ATTR, @@ -6456,6 +6607,20 @@ enum nl80211_peer_measurement_ftm_capa { * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag) * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC: request civic location data * (flag) + * @NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED: request trigger based ranging + * measurement (flag). + * This attribute and %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED are + * mutually exclusive. + * if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based + * ranging will be used. + * @NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED: request non trigger based + * ranging measurement (flag) + * This attribute and %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED are + * mutually exclusive. + * if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based + * ranging will be used. * * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number @@ -6472,6 +6637,8 @@ enum nl80211_peer_measurement_ftm_req { NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES, NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI, NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC, + NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED, + NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED, /* keep last */ NUM_NL80211_PMSR_FTM_REQ_ATTR, From bbf94a0958aa23fcd360d15035b222eb3f6662ad Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Mon, 23 Mar 2020 19:11:24 +0530 Subject: [PATCH 0296/1105] nl80211: Configure PMKSA lifetime and reauth threshold timer to driver Drivers that trigger roaming need to know the lifetime and reauth threshold time of configured PMKSA so that they can trigger full authentication to avoid unnecessary disconnection. To support this, send dot11RSNAConfigPMKLifetime and dot11RSNAConfigPMKReauthThreshold values configured in wpa_supplicant to the driver while configuring a PMKSA. Signed-off-by: Veerendranath Jakkam --- src/drivers/driver.h | 2 ++ src/drivers/driver_nl80211.c | 6 ++++++ src/rsn_supp/pmksa_cache.c | 4 +++- src/rsn_supp/preauth.c | 2 +- src/rsn_supp/wpa.h | 3 ++- src/rsn_supp/wpa_i.h | 6 ++++-- wpa_supplicant/preauth_test.c | 3 ++- wpa_supplicant/wpas_glue.c | 5 ++++- 8 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 39c7f9cb9..bc4f0ef95 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2357,6 +2357,8 @@ struct wpa_pmkid_params { const u8 *pmkid; const u8 *pmk; size_t pmk_len; + u32 pmk_lifetime; + u8 pmk_reauth_threshold; }; /* Mask used to specify which connection parameters have to be updated */ diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 5f2b5651c..4790770bf 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8228,6 +8228,12 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd, (params->fils_cache_id && nla_put(msg, NL80211_ATTR_FILS_CACHE_ID, 2, params->fils_cache_id)) || + (params->pmk_lifetime && + nla_put_u32(msg, NL80211_ATTR_PMK_LIFETIME, + params->pmk_lifetime)) || + (params->pmk_reauth_threshold && + nla_put_u8(msg, NL80211_ATTR_PMK_REAUTH_THRESHOLD, + params->pmk_reauth_threshold)) || (cmd != NL80211_CMD_DEL_PMKSA && params->pmk_len && params->pmk_len <= PMK_MAX_LEN && nla_put(msg, NL80211_ATTR_PMK, params->pmk_len, params->pmk))) { diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index 9c970f811..bd32cef08 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -267,7 +267,9 @@ pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, entry->network_ctx, entry->akmp); wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa, entry->pmkid, entry->fils_cache_id_set ? entry->fils_cache_id : NULL, - entry->pmk, entry->pmk_len); + entry->pmk, entry->pmk_len, + pmksa->sm->dot11RSNAConfigPMKLifetime, + pmksa->sm->dot11RSNAConfigPMKReauthThreshold); return entry; } diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index a7ca2ed8b..a10192172 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -349,7 +349,7 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) * PMKIDs again, so report the existing data now. */ if (p) { wpa_sm_add_pmkid(sm, NULL, candidate->bssid, p->pmkid, - NULL, p->pmk, p->pmk_len); + NULL, p->pmk, p->pmk_len, 0, 0); } dl_list_del(&candidate->list); diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 1f22f2f26..796f39203 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -42,7 +42,8 @@ struct wpa_sm_ctx { size_t *msg_len, void **data_pos); int (*add_pmkid)(void *ctx, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, - const u8 *pmk, size_t pmk_len); + const u8 *pmk, size_t pmk_len, u32 pmk_lifetime, + u8 pmk_reauth_threshold); int (*remove_pmkid)(void *ctx, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id); void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 5178c28cb..1ad75dcfa 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -264,11 +264,13 @@ static inline u8 * wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *cache_id, const u8 *pmk, - size_t pmk_len) + size_t pmk_len, u32 pmk_lifetime, + u8 pmk_reauth_threshold) { WPA_ASSERT(sm->ctx->add_pmkid); return sm->ctx->add_pmkid(sm->ctx->ctx, network_ctx, bssid, pmkid, - cache_id, pmk, pmk_len); + cache_id, pmk, pmk_len, pmk_lifetime, + pmk_reauth_threshold); } static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, void *network_ctx, diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c index 7ed5860f0..4a8f4ff8f 100644 --- a/wpa_supplicant/preauth_test.c +++ b/wpa_supplicant/preauth_test.c @@ -153,7 +153,8 @@ static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, static int wpa_supplicant_add_pmkid(void *wpa_s, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, - const u8 *pmk, size_t pmk_len) + const u8 *pmk, size_t pmk_len, + u32 pmk_lifetime, u8 pmk_reauth_threshold) { printf("%s - not implemented\n", __func__); return -1; diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 200a439cb..6bd271e12 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -574,7 +574,8 @@ static struct wpa_ssid * wpas_get_network_ctx(struct wpa_supplicant *wpa_s, static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, - const u8 *pmk, size_t pmk_len) + const u8 *pmk, size_t pmk_len, + u32 pmk_lifetime, u8 pmk_reauth_threshold) { struct wpa_supplicant *wpa_s = _wpa_s; struct wpa_ssid *ssid; @@ -596,6 +597,8 @@ static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, params.pmkid = pmkid; params.pmk = pmk; params.pmk_len = pmk_len; + params.pmk_lifetime = pmk_lifetime; + params.pmk_reauth_threshold = pmk_reauth_threshold; return wpa_drv_add_pmkid(wpa_s, ¶ms); } From 62e12afcf1ee50dd492ee8b13c8dd7cc5a33f2f4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 19:29:12 +0200 Subject: [PATCH 0297/1105] wpa_auth: Clean up pointer dereferences Use local variables to avoid sm->wpa_auth->conf type of dereferences where multiple instances within a function can be cleaned up. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 148 +++++++++++++++++++++++----------------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 1e3afd6f2..fd20c5606 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -745,23 +745,26 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) void wpa_auth_sta_deinit(struct wpa_state_machine *sm) { + struct wpa_authenticator *wpa_auth; + if (sm == NULL) return; - if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + wpa_auth = sm->wpa_auth; + if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "strict rekeying - force GTK rekey since STA " "is leaving"); if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk, - sm->wpa_auth, NULL) == -1) - eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, - NULL); + wpa_auth, NULL) == -1) + eloop_register_timeout(0, 500000, wpa_rekey_gtk, + wpa_auth, NULL); } - eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); + eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); sm->pending_1_of_4_timeout = 0; eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); - eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); + eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm); #ifdef CONFIG_IEEE80211R_AP wpa_ft_sta_deinit(sm); #endif /* CONFIG_IEEE80211R_AP */ @@ -1472,6 +1475,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *kde, size_t kde_len, int keyidx, int encr, int force_version) { + struct wpa_auth_config *conf = &wpa_auth->conf; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; size_t len, mic_len, keyhdrlen; @@ -1528,7 +1532,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, hdr = os_zalloc(len); if (hdr == NULL) return; - hdr->version = wpa_auth->conf.eapol_version; + hdr->version = conf->eapol_version; hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; hdr->length = host_to_be16(len - sizeof(*hdr)); key = (struct wpa_eapol_key *) (hdr + 1); @@ -1544,7 +1548,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; WPA_PUT_BE16(key->key_info, key_info); - alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; + alg = pairwise ? sm->pairwise : conf->wpa_group; if (sm->wpa == WPA_VERSION_WPA2 && !pairwise) WPA_PUT_BE16(key->key_length, 0); else @@ -1664,9 +1668,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, } #ifdef CONFIG_TESTING_OPTIONS if (!pairwise && - wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 && - drand48() < - wpa_auth->conf.corrupt_gtk_rekey_mic_probability) { + conf->corrupt_gtk_rekey_mic_probability > 0.0 && + drand48() < conf->corrupt_gtk_rekey_mic_probability) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "Corrupting group EAPOL-Key Key MIC"); key_mic[0]++; @@ -1674,8 +1677,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_TESTING_OPTIONS */ } - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, - 1); + wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1); wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, sm->pairwise_set); os_free(hdr); @@ -2747,8 +2749,7 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, /* GTK KDE */ gtk = gsm->GTK[gsm->GN - 1]; gtk_len = gsm->GTK_len; - if (sm->wpa_auth->conf.disable_gtk || - sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random GTK to each STA to prevent use * of GTK in the BSS. @@ -3172,7 +3173,8 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) struct wpa_bigtk_kde bigtk; struct wpa_group *gsm = sm->group; u8 rsc[WPA_KEY_RSC_LEN]; - size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + struct wpa_auth_config *conf = &sm->wpa_auth->conf; + size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher); if (!sm->mgmt_frame_prot) return pos; @@ -3185,8 +3187,7 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) else os_memcpy(igtk.pn, rsc, sizeof(igtk.pn)); os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len); - if (sm->wpa_auth->conf.disable_gtk || - sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random IGTK to each STA to prevent use of * IGTK in the BSS. @@ -3198,7 +3199,7 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, NULL, 0); - if (!sm->wpa_auth->conf.beacon_prot) + if (!conf->beacon_prot) return pos; bigtk.keyid[0] = gsm->GN_bigtk; @@ -3294,12 +3295,11 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) sm->TimeoutEvt = FALSE; sm->TimeoutCtr++; - if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && - sm->TimeoutCtr > 1) { + if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) { /* Do not allow retransmission of EAPOL-Key msg 3/4 */ return; } - if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { + if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; @@ -3313,8 +3313,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ wpa_ie = sm->wpa_auth->wpa_ie; wpa_ie_len = sm->wpa_auth->wpa_ie_len; - if (sm->wpa == WPA_VERSION_WPA && - (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && + if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) && wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) { /* WPA-only STA, remove RSN IE and possible MDIE */ wpa_ie = wpa_ie + wpa_ie[1] + 2; @@ -3323,20 +3322,20 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie_len = wpa_ie[1] + 2; } #ifdef CONFIG_TESTING_OPTIONS - if (sm->wpa_auth->conf.rsne_override_eapol_set) { + if (conf->rsne_override_eapol_set) { wpa_ie_buf2 = replace_ie( "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN, - sm->wpa_auth->conf.rsne_override_eapol, - sm->wpa_auth->conf.rsne_override_eapol_len); + conf->rsne_override_eapol, + conf->rsne_override_eapol_len); if (!wpa_ie_buf2) goto done; wpa_ie = wpa_ie_buf2; } - if (sm->wpa_auth->conf.rsnxe_override_eapol_set) { + if (conf->rsnxe_override_eapol_set) { wpa_ie_buf = replace_ie( "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX, - sm->wpa_auth->conf.rsnxe_override_eapol, - sm->wpa_auth->conf.rsnxe_override_eapol_len); + conf->rsnxe_override_eapol, + conf->rsnxe_override_eapol_len); if (!wpa_ie_buf) goto done; wpa_ie = wpa_ie_buf; @@ -3361,7 +3360,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) secure = 1; gtk = gsm->GTK[gsm->GN - 1]; gtk_len = gsm->GTK_len; - if (sm->wpa_auth->conf.disable_gtk || + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random GTK to each STA to prevent use @@ -3501,8 +3500,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (WPA_GET_BE32(sm->ip_addr) > 0) { u8 addr[3 * 4]; os_memcpy(addr, sm->ip_addr, 4); - os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4); - os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4); + os_memcpy(addr + 4, conf->ip_addr_mask, 4); + os_memcpy(addr + 8, conf->ip_addr_go, 4); pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC, addr, sizeof(addr), NULL, 0); } @@ -3590,6 +3589,7 @@ SM_STATE(WPA_PTK, PTKINITDONE) SM_STEP(WPA_PTK) { struct wpa_authenticator *wpa_auth = sm->wpa_auth; + struct wpa_auth_config *conf = &wpa_auth->conf; if (sm->Init) SM_ENTER(WPA_PTK, INITIALIZE); @@ -3624,7 +3624,7 @@ SM_STEP(WPA_PTK) break; case WPA_PTK_AUTHENTICATION2: if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && - wpa_auth_get_eapol(sm->wpa_auth, sm->addr, + wpa_auth_get_eapol(wpa_auth, sm->addr, WPA_EAPOL_keyRun) > 0) SM_ENTER(WPA_PTK, INITPMK); else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || @@ -3635,7 +3635,7 @@ SM_STEP(WPA_PTK) SM_ENTER(WPA_PTK, INITPMK); break; case WPA_PTK_INITPMK: - if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, + if (wpa_auth_get_eapol(wpa_auth, sm->addr, WPA_EAPOL_keyAvailable) > 0) { SM_ENTER(WPA_PTK, PTKSTART); #ifdef CONFIG_DPP @@ -3644,13 +3644,13 @@ SM_STEP(WPA_PTK) #endif /* CONFIG_DPP */ } else { wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "INITPMK - keyAvailable = false"); SM_ENTER(WPA_PTK, DISCONNECT); } break; case WPA_PTK_INITPSK: - if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, + if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr, NULL, NULL, NULL)) { SM_ENTER(WPA_PTK, PTKSTART); #ifdef CONFIG_SAE @@ -3658,7 +3658,7 @@ SM_STEP(WPA_PTK) SM_ENTER(WPA_PTK, PTKSTART); #endif /* CONFIG_SAE */ } else { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "no PSK configured for the STA"); wpa_auth->dot11RSNA4WayHandshakeFailures++; SM_ENTER(WPA_PTK, DISCONNECT); @@ -3668,13 +3668,11 @@ SM_STEP(WPA_PTK) if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && sm->EAPOLKeyPairwise) SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); - else if (sm->TimeoutCtr > - sm->wpa_auth->conf.wpa_pairwise_update_count) { + else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) { wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_vlogger( - sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PTKSTART: Retry limit %u reached", - sm->wpa_auth->conf.wpa_pairwise_update_count); + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKSTART: Retry limit %u reached", + conf->wpa_pairwise_update_count); SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKSTART); @@ -3698,14 +3696,13 @@ SM_STEP(WPA_PTK) sm->EAPOLKeyPairwise && sm->MICVerified) SM_ENTER(WPA_PTK, PTKINITDONE); else if (sm->TimeoutCtr > - sm->wpa_auth->conf.wpa_pairwise_update_count || - (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + conf->wpa_pairwise_update_count || + (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1)) { wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_vlogger( - sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PTKINITNEGOTIATING: Retry limit %u reached", - sm->wpa_auth->conf.wpa_pairwise_update_count); + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKINITNEGOTIATING: Retry limit %u reached", + conf->wpa_pairwise_update_count); SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); @@ -3736,16 +3733,16 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) u8 *kde_buf = NULL, *pos, hdr[2]; size_t kde_len; u8 *gtk, dummy_gtk[32]; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); sm->GTimeoutCtr++; - if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && - sm->GTimeoutCtr > 1) { + if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) { /* Do not allow retransmission of EAPOL-Key group msg 1/2 */ return; } - if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) { + if (sm->GTimeoutCtr > conf->wpa_group_update_count) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; @@ -3762,8 +3759,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) "sending 1/2 msg of Group Key Handshake"); gtk = gsm->GTK[gsm->GN - 1]; - if (sm->wpa_auth->conf.disable_gtk || - sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random GTK to each STA to prevent use * of GTK in the BSS. @@ -3809,8 +3805,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) { -#ifdef CONFIG_OCV struct wpa_authenticator *wpa_auth = sm->wpa_auth; +#ifdef CONFIG_OCV const u8 *key_data, *mic; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; @@ -3875,7 +3871,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) sm->GUpdateStationKeys = FALSE; sm->GTimeoutCtr = 0; /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, "group key handshake completed (%s)", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); sm->has_GTK = TRUE; @@ -3932,6 +3928,7 @@ SM_STEP(WPA_PTK_GROUP) static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { + struct wpa_auth_config *conf = &wpa_auth->conf; int ret = 0; size_t len; @@ -3944,8 +3941,8 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, wpa_hexdump_key(MSG_DEBUG, "GTK", group->GTK[group->GN - 1], group->GTK_len); - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { - len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + len = wpa_cipher_key_len(conf->group_mgmt_cipher); os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", @@ -3956,9 +3953,9 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, group->IGTK[group->GN_igtk - 4], len); } - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION && - wpa_auth->conf.beacon_prot) { - len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION && + conf->beacon_prot) { + len = wpa_cipher_key_len(conf->group_mgmt_cipher); os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion", @@ -4178,21 +4175,22 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { + struct wpa_auth_config *conf = &wpa_auth->conf; int ret = 0; if (wpa_auth_set_key(wpa_auth, group->vlan_id, - wpa_cipher_to_alg(wpa_auth->conf.wpa_group), + wpa_cipher_to_alg(conf->wpa_group), broadcast_ether_addr, group->GN, group->GTK[group->GN - 1], group->GTK_len, KEY_FLAG_GROUP_TX_DEFAULT) < 0) ret = -1; - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { enum wpa_alg alg; size_t len; - alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher); - len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + alg = wpa_cipher_to_alg(conf->group_mgmt_cipher); + len = wpa_cipher_key_len(conf->group_mgmt_cipher); if (ret == 0 && wpa_auth_set_key(wpa_auth, group->vlan_id, alg, @@ -4201,7 +4199,7 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, KEY_FLAG_GROUP_TX_DEFAULT) < 0) ret = -1; - if (ret == 0 && wpa_auth->conf.beacon_prot && + if (ret == 0 && conf->beacon_prot && wpa_auth_set_key(wpa_auth, group->vlan_id, alg, broadcast_ether_addr, group->GN_bigtk, group->BIGTK[group->GN_bigtk - 6], len, @@ -4369,6 +4367,7 @@ static const char * wpa_bool_txt(int val) int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) { + struct wpa_auth_config *conf; int len = 0, ret; char pmkid_txt[PMKID_LEN * 2 + 1]; #ifdef CONFIG_RSN_PREAUTH @@ -4379,6 +4378,7 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) if (wpa_auth == NULL) return len; + conf = &wpa_auth->conf; ret = os_snprintf(buf + len, buflen - len, "dot11RSNAOptionImplemented=TRUE\n" @@ -4386,8 +4386,8 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) "dot11RSNAEnabled=%s\n" "dot11RSNAPreauthenticationEnabled=%s\n", wpa_bool_txt(preauth), - wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), - wpa_bool_txt(wpa_auth->conf.rsn_preauth)); + wpa_bool_txt(conf->wpa & WPA_PROTO_RSN), + wpa_bool_txt(conf->rsn_preauth)); if (os_snprintf_error(buflen - len, ret)) return len; len += ret; @@ -4422,10 +4422,10 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) "dot11RSNA4WayHandshakeFailures=%u\n" "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", RSN_VERSION, - !!wpa_auth->conf.wpa_strict_rekey, - wpa_auth->conf.wpa_group_update_count, - wpa_auth->conf.wpa_pairwise_update_count, - wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8, + !!conf->wpa_strict_rekey, + conf->wpa_group_update_count, + conf->wpa_pairwise_update_count, + wpa_cipher_key_len(conf->wpa_group) * 8, dot11RSNAConfigPMKLifetime, dot11RSNAConfigPMKReauthThreshold, dot11RSNAConfigSATimeout, From 9385f03febf5471ec830fe55b6bab312fc403930 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 19:36:00 +0200 Subject: [PATCH 0298/1105] wpa_auth: Coding style cleanup for pointer is NULL comparisons Use !ptr instead of ptr == NULL. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 131 +++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index fd20c5606..2b11aa189 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -106,7 +106,7 @@ static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, wpa_eapol_variable var) { - if (wpa_auth->cb->get_eapol == NULL) + if (!wpa_auth->cb->get_eapol) return -1; return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var); } @@ -118,7 +118,7 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, const u8 *prev_psk, size_t *psk_len, int *vlan_id) { - if (wpa_auth->cb->get_psk == NULL) + if (!wpa_auth->cb->get_psk) return NULL; return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr, prev_psk, psk_len, vlan_id); @@ -128,7 +128,7 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, const u8 *addr, u8 *msk, size_t *len) { - if (wpa_auth->cb->get_msk == NULL) + if (!wpa_auth->cb->get_msk) return -1; return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len); } @@ -140,7 +140,7 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, u8 *key, size_t key_len, enum key_flag key_flag) { - if (wpa_auth->cb->set_key == NULL) + if (!wpa_auth->cb->set_key) return -1; return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx, key, key_len, key_flag); @@ -152,7 +152,7 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, { int res; - if (wpa_auth->cb->get_seqnum == NULL) + if (!wpa_auth->cb->get_seqnum) return -1; res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq); #ifdef CONFIG_TESTING_OPTIONS @@ -184,7 +184,7 @@ static inline int wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *data, size_t data_len, int encrypt) { - if (wpa_auth->cb->send_eapol == NULL) + if (!wpa_auth->cb->send_eapol) return -1; return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len, encrypt); @@ -195,7 +195,7 @@ wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth, const u8 *addr) { - if (wpa_auth->cb->start_ampe == NULL) + if (!wpa_auth->cb->start_ampe) return -1; return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr); } @@ -206,7 +206,7 @@ int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, int (*cb)(struct wpa_state_machine *sm, void *ctx), void *cb_ctx) { - if (wpa_auth->cb->for_each_sta == NULL) + if (!wpa_auth->cb->for_each_sta) return 0; return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx); } @@ -216,7 +216,7 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, int (*cb)(struct wpa_authenticator *a, void *ctx), void *cb_ctx) { - if (wpa_auth->cb->for_each_auth == NULL) + if (!wpa_auth->cb->for_each_auth) return 0; return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx); } @@ -225,7 +225,7 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, logger_level level, const char *txt) { - if (wpa_auth->cb->logger == NULL) + if (!wpa_auth->cb->logger) return; wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt); } @@ -238,7 +238,7 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, int maxlen; va_list ap; - if (wpa_auth->cb->logger == NULL) + if (!wpa_auth->cb->logger) return; maxlen = os_strlen(fmt) + 100; @@ -259,7 +259,7 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, const u8 *addr, u16 reason) { - if (wpa_auth->cb->disconnect == NULL) + if (!wpa_auth->cb->disconnect) return; wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)", MAC2STR(addr), reason); @@ -417,7 +417,7 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, struct wpa_group *group; group = os_zalloc(sizeof(struct wpa_group)); - if (group == NULL) + if (!group) return NULL; group->GTKAuthenticator = TRUE; @@ -473,7 +473,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, struct wpa_authenticator *wpa_auth; wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); - if (wpa_auth == NULL) + if (!wpa_auth) return NULL; os_memcpy(wpa_auth->addr, addr, ETH_ALEN); os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); @@ -487,7 +487,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, } wpa_auth->group = wpa_group_init(wpa_auth, 0, 1); - if (wpa_auth->group == NULL) { + if (!wpa_auth->group) { os_free(wpa_auth->wpa_ie); os_free(wpa_auth); return NULL; @@ -495,7 +495,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, wpa_auth); - if (wpa_auth->pmksa == NULL) { + if (!wpa_auth->pmksa) { wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); os_free(wpa_auth->group); os_free(wpa_auth->wpa_ie); @@ -505,7 +505,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, #ifdef CONFIG_IEEE80211R_AP wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); - if (wpa_auth->ft_pmk_cache == NULL) { + if (!wpa_auth->ft_pmk_cache) { wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); os_free(wpa_auth->group); os_free(wpa_auth->wpa_ie); @@ -601,7 +601,8 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth, struct wpa_auth_config *conf) { struct wpa_group *group; - if (wpa_auth == NULL) + + if (!wpa_auth) return 0; os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); @@ -635,7 +636,7 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, return NULL; sm = os_zalloc(sizeof(struct wpa_state_machine)); - if (sm == NULL) + if (!sm) return NULL; os_memcpy(sm->addr, addr, ETH_ALEN); if (p2p_dev_addr) @@ -652,7 +653,7 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm) { - if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) + if (!wpa_auth || !wpa_auth->conf.wpa || !sm) return -1; #ifdef CONFIG_IEEE80211R_AP @@ -702,7 +703,7 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) /* WPA/RSN was not used - clear WPA state. This is needed if the STA * reassociates back to the same AP while the previous entry for the * STA has not yet been removed. */ - if (sm == NULL) + if (!sm) return; sm->wpa_key_mgmt = 0; @@ -747,7 +748,7 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm) { struct wpa_authenticator *wpa_auth; - if (sm == NULL) + if (!sm) return; wpa_auth = sm->wpa_auth; @@ -781,7 +782,7 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm) static void wpa_request_new_ptk(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return; if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { @@ -822,7 +823,7 @@ static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, int i; for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { if (ctr[i].valid && - (replay_counter == NULL || + (!replay_counter || os_memcmp(replay_counter, ctr[i].counter, WPA_REPLAY_COUNTER_LEN) == 0)) ctr[i].valid = FALSE; @@ -839,7 +840,7 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, struct rsn_mdie *mdie; if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || - ie.num_pmkid != 1 || ie.pmkid == NULL) { + ie.num_pmkid != 1 || !ie.pmkid) { wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " "FT 4-way handshake message 2/4"); return -1; @@ -929,7 +930,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, pmk, &pmk_len, &vlan_id); - if (pmk == NULL) + if (!pmk) break; #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { @@ -998,7 +999,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, size_t keyhdrlen, mic_len; u8 *mic; - if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) + if (!wpa_auth || !wpa_auth->conf.wpa || !sm) return; wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len); @@ -1396,7 +1397,7 @@ continue_processing: os_free(sm->last_rx_eapol_key); sm->last_rx_eapol_key = os_memdup(data, data_len); - if (sm->last_rx_eapol_key == NULL) + if (!sm->last_rx_eapol_key) return; sm->last_rx_eapol_key_len = data_len; @@ -1530,7 +1531,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, len += AES_BLOCK_SIZE; hdr = os_zalloc(len); - if (hdr == NULL) + if (!hdr) return; hdr->version = conf->eapol_version; hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; @@ -1602,7 +1603,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_FILS */ } else if (encr && kde) { buf = os_zalloc(key_data_len); - if (buf == NULL) { + if (!buf) { os_free(hdr); return; } @@ -1694,7 +1695,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; u32 ctr; - if (sm == NULL) + if (!sm) return; __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, @@ -1772,7 +1773,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) { int remove_ptk = 1; - if (sm == NULL) + if (!sm) return -1; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, @@ -2914,7 +2915,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, pmk, &pmk_len, &vlan_id); - if (pmk == NULL) + if (!pmk) break; psk_found = 1; #ifdef CONFIG_IEEE80211R_AP @@ -3011,7 +3012,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) eapol_key_ie_len = kde.wpa_ie_len; } ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt); - if (sm->wpa_ie == NULL || + if (!sm->wpa_ie || wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len, eapol_key_ie, eapol_key_ie_len)) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, @@ -3417,7 +3418,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) kde_len += 2 + RSN_SELECTOR_LEN + 1; kde = os_malloc(kde_len); - if (kde == NULL) + if (!kde) goto done; pos = kde; @@ -3772,7 +3773,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); kde_buf = os_malloc(kde_len); - if (kde_buf == NULL) + if (!kde_buf) return; kde = pos = kde_buf; @@ -4029,7 +4030,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) /* update GTK when exiting WNM-Sleep Mode */ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) { - if (sm == NULL || sm->is_wnmsleep) + if (!sm || sm->is_wnmsleep) return; wpa_group_update_sta(sm, NULL); @@ -4275,7 +4276,7 @@ static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, static int wpa_sm_step(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return 0; if (sm->in_step_loop) { @@ -4323,7 +4324,7 @@ static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) void wpa_auth_sm_notify(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return; eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); } @@ -4334,7 +4335,7 @@ void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) int tmp, i; struct wpa_group *group; - if (wpa_auth == NULL) + if (!wpa_auth) return; group = wpa_auth->group; @@ -4376,7 +4377,7 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) const int preauth = 0; #endif /* CONFIG_RSN_PREAUTH */ - if (wpa_auth == NULL) + if (!wpa_auth) return len; conf = &wpa_auth->conf; @@ -4461,7 +4462,7 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) int len = 0, ret; u32 pairwise = 0; - if (sm == NULL) + if (!sm) return 0; /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ @@ -4542,7 +4543,7 @@ const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len) int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return -1; return sm->wpa_key_mgmt; } @@ -4550,7 +4551,7 @@ int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return 0; return sm->wpa; } @@ -4575,7 +4576,7 @@ int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm) int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, struct rsn_pmksa_cache_entry *entry) { - if (sm == NULL || sm->pmksa != entry) + if (!sm || sm->pmksa != entry) return -1; sm->pmksa = NULL; return 0; @@ -4598,7 +4599,7 @@ void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) { - if (wpa_auth == NULL) + if (!wpa_auth) return NULL; *len = wpa_auth->wpa_ie_len; return wpa_auth->wpa_ie; @@ -4609,7 +4610,7 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, unsigned int pmk_len, int session_timeout, struct eapol_state_machine *eapol) { - if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 || + if (!sm || sm->wpa != WPA_VERSION_WPA2 || sm->wpa_auth->conf.disable_pmksa_caching) return -1; @@ -4645,7 +4646,7 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, int session_timeout, struct eapol_state_machine *eapol) { - if (wpa_auth == NULL) + if (!wpa_auth) return -1; wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len); @@ -4706,7 +4707,7 @@ void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, { struct rsn_pmksa_cache_entry *pmksa; - if (wpa_auth == NULL || wpa_auth->pmksa == NULL) + if (!wpa_auth || !wpa_auth->pmksa) return; pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); if (pmksa) { @@ -4872,13 +4873,13 @@ wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) { struct wpa_group *group; - if (wpa_auth == NULL || wpa_auth->group == NULL) + if (!wpa_auth || !wpa_auth->group) return NULL; wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", vlan_id); group = wpa_group_init(wpa_auth, vlan_id, 0); - if (group == NULL) + if (!group) return NULL; group->next = wpa_auth->group->next; @@ -4898,7 +4899,7 @@ int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id) { struct wpa_group *group; - if (wpa_auth == NULL) + if (!wpa_auth) return 0; group = wpa_auth->group; @@ -4908,9 +4909,9 @@ int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id) group = group->next; } - if (group == NULL) { + if (!group) { group = wpa_auth_add_group(wpa_auth, vlan_id); - if (group == NULL) + if (!group) return -1; } @@ -4939,7 +4940,7 @@ int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id) struct wpa_group *group; int ret = 0; - if (wpa_auth == NULL) + if (!wpa_auth) return 0; group = wpa_auth->group; @@ -4949,7 +4950,7 @@ int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id) group = group->next; } - if (group == NULL) + if (!group) return -1; wpa_printf(MSG_DEBUG, @@ -4984,7 +4985,7 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) { struct wpa_group *group; - if (sm == NULL || sm->wpa_auth == NULL) + if (!sm || !sm->wpa_auth) return 0; group = sm->wpa_auth->group; @@ -4994,9 +4995,9 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) group = group->next; } - if (group == NULL) { + if (!group) { group = wpa_auth_add_group(sm->wpa_auth, vlan_id); - if (group == NULL) + if (!group) return -1; } @@ -5020,7 +5021,7 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int ack) { - if (wpa_auth == NULL || sm == NULL) + if (!wpa_auth || !sm) return; wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR " ack=%d", MAC2STR(sm->addr), ack); @@ -5057,7 +5058,7 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, int wpa_auth_uses_sae(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return 0; return wpa_key_mgmt_sae(sm->wpa_key_mgmt); } @@ -5065,7 +5066,7 @@ int wpa_auth_uses_sae(struct wpa_state_machine *sm) int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return 0; return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE; } @@ -5074,7 +5075,7 @@ int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) #ifdef CONFIG_P2P int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) { - if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0) + if (!sm || WPA_GET_BE32(sm->ip_addr) == 0) return -1; os_memcpy(addr, sm->ip_addr, 4); return 0; @@ -5296,7 +5297,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, } #endif /* CONFIG_IEEE80211R_AP */ kde = os_malloc(kde_len); - if (kde == NULL) + if (!kde) return -1; pos = kde; @@ -5423,7 +5424,7 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); kde_buf = os_malloc(kde_len); - if (kde_buf == NULL) + if (!kde_buf) return -1; kde = pos = kde_buf; From f83d3491b98e02e81579c1feb1268209a50611c7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 19:48:32 +0200 Subject: [PATCH 0299/1105] wpa_auth: Do not split strings into multiple lines Avoid unnecessary splitting of long string constants into multiple lines. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 224 ++++++++++++++++++++++------------------------ 1 file changed, 105 insertions(+), 119 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 2b11aa189..583ff793f 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -292,8 +292,8 @@ static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) struct wpa_authenticator *wpa_auth = eloop_ctx; if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); + wpa_printf(MSG_ERROR, + "Failed to get random data for WPA initialization."); } else { wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); wpa_hexdump_key(MSG_DEBUG, "GMK", @@ -425,9 +425,8 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); if (random_pool_ready() != 1) { - wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " - "for secure operations - update keys later when " - "the first station connects"); + wpa_printf(MSG_INFO, + "WPA: Not enough entropy in random pool for secure operations - update keys later when the first station connects"); } /* @@ -437,16 +436,16 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, * on embedded devices. */ if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); + wpa_printf(MSG_ERROR, + "Failed to get random data for WPA initialization."); os_free(group); return NULL; } group->GInit = TRUE; if (delay_init) { - wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start " - "until Beacon frames have been configured"); + wpa_printf(MSG_DEBUG, + "WPA: Delay group state machine start until Beacon frames have been configured"); /* Initialization is completed in wpa_init_keys(). */ } else { wpa_group_sm_step(wpa_auth, group); @@ -544,8 +543,8 @@ int wpa_init_keys(struct wpa_authenticator *wpa_auth) { struct wpa_group *group = wpa_auth->group; - wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial " - "keys"); + wpa_printf(MSG_DEBUG, + "WPA: Start group state machine to set initial keys"); wpa_group_sm_step(wpa_auth, group); group->GInit = FALSE; wpa_group_sm_step(wpa_auth, group); @@ -659,8 +658,7 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_IEEE80211R_AP if (sm->ft_completed) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "FT authentication already completed - do not " - "start 4-way handshake"); + "FT authentication already completed - do not start 4-way handshake"); /* Go to PTKINITDONE state to allow GTK rekeying */ sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; sm->Pair = TRUE; @@ -715,8 +713,9 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) #ifdef CONFIG_P2P if (WPA_GET_BE32(sm->ip_addr)) { u32 start; - wpa_printf(MSG_DEBUG, "P2P: Free assigned IP " - "address %u.%u.%u.%u from " MACSTR, + wpa_printf(MSG_DEBUG, + "P2P: Free assigned IP address %u.%u.%u.%u from " + MACSTR, sm->ip_addr[0], sm->ip_addr[1], sm->ip_addr[2], sm->ip_addr[3], MAC2STR(sm->addr)); @@ -754,8 +753,7 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm) wpa_auth = sm->wpa_auth; if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "strict rekeying - force GTK rekey since STA " - "is leaving"); + "strict rekeying - force GTK rekey since STA is leaving"); if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk, wpa_auth, NULL) == -1) eloop_register_timeout(0, 500000, wpa_rekey_gtk, @@ -772,8 +770,9 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm) if (sm->in_step_loop) { /* Must not free state machine while wpa_sm_step() is running. * Freeing will be completed in the end of wpa_sm_step(). */ - wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " - "machine deinit for " MACSTR, MAC2STR(sm->addr)); + wpa_printf(MSG_DEBUG, + "WPA: Registering pending STA state machine deinit for " + MACSTR, MAC2STR(sm->addr)); sm->pending_deinit = 1; } else wpa_free_sta_sm(sm); @@ -841,8 +840,8 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || ie.num_pmkid != 1 || !ie.pmkid) { - wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " - "FT 4-way handshake message 2/4"); + wpa_printf(MSG_DEBUG, + "FT: No PMKR1Name in FT 4-way handshake message 2/4"); return -1; } @@ -851,8 +850,9 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, sm->sup_pmk_r1_name, PMKID_LEN); if (!kde->mdie || !kde->ftie) { - wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " - "message 2/4", kde->mdie ? "FTIE" : "MDIE"); + wpa_printf(MSG_DEBUG, + "FT: No %s in FT 4-way handshake message 2/4", + kde->mdie ? "FTIE" : "MDIE"); return -1; } @@ -886,18 +886,15 @@ static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth, { /* Supplicant reported a Michael MIC error */ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Error Request " - "(STA detected Michael MIC failure (group=%d))", + "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))", group); if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "ignore Michael MIC failure report since " - "group cipher is not TKIP"); + "ignore Michael MIC failure report since group cipher is not TKIP"); } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "ignore Michael MIC failure report since " - "pairwise cipher is not TKIP"); + "ignore Michael MIC failure report since pairwise cipher is not TKIP"); } else { if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0) return 1; /* STA entry was removed */ @@ -1027,8 +1024,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC", mic, mic_len); if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { - wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " - "key_data overflow (%d > %lu)", + wpa_printf(MSG_INFO, + "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %lu)", key_data_length, (unsigned long) (data_len - sizeof(*hdr) - keyhdrlen)); @@ -1041,18 +1038,18 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, * Some deployed station implementations seem to send * msg 4/4 with incorrect type value in WPA2 mode. */ - wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " - "with unexpected WPA type in RSN mode"); + wpa_printf(MSG_DEBUG, + "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode"); } else if (key->type != EAPOL_KEY_TYPE_RSN) { - wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " - "unexpected type %d in RSN mode", + wpa_printf(MSG_DEBUG, + "Ignore EAPOL-Key with unexpected type %d in RSN mode", key->type); return; } } else { if (key->type != EAPOL_KEY_TYPE_WPA) { - wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " - "unexpected type %d in WPA mode", + wpa_printf(MSG_DEBUG, + "Ignore EAPOL-Key with unexpected type %d in WPA mode", key->type); return; } @@ -1097,9 +1094,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, - "advertised support for " - "AES-128-CMAC, but did not " - "use it"); + "advertised support for AES-128-CMAC, but did not use it"); return; } @@ -1108,8 +1103,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, - "did not use HMAC-SHA1-AES " - "with CCMP/GCMP"); + "did not use HMAC-SHA1-AES with CCMP/GCMP"); return; } } @@ -1127,8 +1121,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, os_memcmp(key->replay_counter, sm->req_replay_counter, WPA_REPLAY_COUNTER_LEN) <= 0) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, - "received EAPOL-Key request with " - "replayed counter"); + "received EAPOL-Key request with replayed counter"); return; } } @@ -1151,9 +1144,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, * even if we have already sent out EAPOL-Key 3/4. */ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "Process SNonce update from STA " - "based on retransmitted EAPOL-Key " - "1/4"); + "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4"); sm->update_snonce = 1; os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN); sm->alt_snonce_valid = TRUE; @@ -1182,12 +1173,12 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, key->replay_counter) && sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "ignore retransmitted EAPOL-Key %s - " - "SNonce did not change", msgtxt); + "ignore retransmitted EAPOL-Key %s - SNonce did not change", + msgtxt); } else { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "received EAPOL-Key %s with " - "unexpected replay counter", msgtxt); + "received EAPOL-Key %s with unexpected replay counter", + msgtxt); } for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { if (!sm->key_replay[i].valid) @@ -1218,8 +1209,7 @@ continue_processing: (!sm->update_snonce || sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/4 in " - "invalid state (%d) - dropped", + "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped", sm->wpa_ptk_state); return; } @@ -1234,9 +1224,8 @@ continue_processing: * Counter update and the station will be allowed to * continue. */ - wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " - "collect more entropy for random number " - "generation"); + wpa_printf(MSG_DEBUG, + "WPA: Reject 4-way handshake to collect more entropy for random number generation"); random_mark_pool_ready(); wpa_sta_disconnect(wpa_auth, sm->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); @@ -1247,8 +1236,7 @@ continue_processing: if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || !sm->PTK_valid) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 4/4 in " - "invalid state (%d) - dropped", + "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped", sm->wpa_ptk_state); return; } @@ -1257,8 +1245,7 @@ continue_processing: if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING || !sm->PTK_valid) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/2 in " - "invalid state (%d) - dropped", + "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped", sm->wpa_ptk_group_state); return; } @@ -1337,8 +1324,7 @@ continue_processing: WPA_REPLAY_COUNTER_LEN); } else { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key request with " - "invalid MIC"); + "received EAPOL-Key request with invalid MIC"); return; } @@ -1354,8 +1340,7 @@ continue_processing: return; /* STA entry was removed */ } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Request for new " - "4-Way Handshake"); + "received EAPOL-Key Request for new 4-Way Handshake"); wpa_request_new_ptk(sm); } else if (key_data_length > 0 && wpa_parse_kde_ies(key_data, key_data_length, @@ -1363,8 +1348,7 @@ continue_processing: kde.mac_addr) { } else { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Request for GTK " - "rekeying"); + "received EAPOL-Key Request for GTK rekeying"); eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); wpa_rekey_gtk(wpa_auth, NULL); } @@ -1505,9 +1489,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); - wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " - "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " - "encr=%d)", + wpa_printf(MSG_DEBUG, + "WPA: Send EAPOL(version=%d secure=%d mic=%d ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d encr=%d)", version, (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, @@ -1655,8 +1638,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, if (key_info & WPA_KEY_INFO_MIC) { if (!sm->PTK_valid || !mic_len) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "PTK not valid when sending EAPOL-Key " - "frame"); + "PTK not valid when sending EAPOL-Key frame"); os_free(hdr); return; } @@ -1715,8 +1697,9 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, #ifdef TEST_FUZZ timeout_ms = 1; #endif /* TEST_FUZZ */ - wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " - "counter %u)", timeout_ms, ctr); + wpa_printf(MSG_DEBUG, + "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)", + timeout_ms, ctr); eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, wpa_send_eapol_timeout, wpa_auth, sm); } @@ -1813,8 +1796,8 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) * sure that the WPA state machines gets initialized * properly at this point. */ - wpa_printf(MSG_DEBUG, "WPA state machine had not been " - "started - initialize now"); + wpa_printf(MSG_DEBUG, + "WPA state machine had not been started - initialize now"); sm->started = 1; sm->Init = TRUE; if (wpa_sm_step(sm) == 1) @@ -1852,8 +1835,8 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) break; case WPA_ASSOC_FT: #ifdef CONFIG_IEEE80211R_AP - wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " - "after association"); + wpa_printf(MSG_DEBUG, + "FT: Retry PTK configuration after association"); wpa_ft_install_ptk(sm); /* Using FT protocol, not WPA auth state machine */ @@ -1986,11 +1969,11 @@ static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, * GMK and Counter here to improve their strength if there was not * enough entropy available immediately after system startup. */ - wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " - "station"); + wpa_printf(MSG_DEBUG, + "WPA: Re-initialize GMK/Counter on first station"); if (random_pool_ready() != 1) { - wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " - "to proceed - reject first 4-way handshake"); + wpa_printf(MSG_INFO, + "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake"); group->reject_4way_hs_for_entropy = TRUE; } else { group->first_sta_seen = TRUE; @@ -2024,8 +2007,8 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) * stronger protection against potential precomputation attacks. */ if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " - "ANonce."); + wpa_printf(MSG_ERROR, + "WPA: Failed to get random data for ANonce."); sm->Disconnect = TRUE; return; } @@ -2082,8 +2065,9 @@ SM_STATE(WPA_PTK, INITPMK) pmk_len = PMK_LEN_SUITE_B_192; else pmk_len = PMK_LEN; - wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " - "(MSK len=%lu PMK len=%u)", (unsigned long) len, + wpa_printf(MSG_DEBUG, + "WPA: PMK from EAPOL state machine (MSK len=%lu PMK len=%u)", + (unsigned long) len, pmk_len); if (len < pmk_len) { wpa_printf(MSG_DEBUG, @@ -3106,10 +3090,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PMKR1Name mismatch in FT 4-way " - "handshake"); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " - "Supplicant", + "PMKR1Name mismatch in FT 4-way handshake"); + wpa_hexdump(MSG_DEBUG, + "FT: PMKR1Name from Supplicant", sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", sm->pmk_r1_name, WPA_PMK_NAME_LEN); @@ -3390,8 +3373,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) * WPA if the supplicant used it first. */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "STA used Secure bit in WPA msg 2/4 - " - "set Secure for 3/4 as workaround"); + "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround"); secure = 1; } } @@ -3432,8 +3414,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) elen = pos - kde; res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert " - "PMKR1Name into RSN IE in EAPOL-Key data"); + wpa_printf(MSG_ERROR, + "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data"); goto done; } pos -= wpa_ie_len; @@ -3476,8 +3458,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) NULL, 0, 0); } if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " - "into EAPOL-Key Key Data"); + wpa_printf(MSG_ERROR, + "FT: Failed to insert FTIE into EAPOL-Key Key Data"); goto done; } pos += res; @@ -3974,8 +3956,9 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "GTK_INIT (VLAN-ID %d)", group->vlan_id); + wpa_printf(MSG_DEBUG, + "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)", + group->vlan_id); group->changed = FALSE; /* GInit is not cleared here; avoid loop */ group->wpa_group_state = WPA_GROUP_GTK_INIT; @@ -4010,8 +3993,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) * station needs to be counted here anyway. */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "GUpdateStationKeys was already set when " - "marking station for GTK rekeying"); + "GUpdateStationKeys was already set when marking station for GTK rekeying"); } /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */ @@ -4142,8 +4124,9 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, { int tmp; - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "SETKEYS (VLAN-ID %d)", group->vlan_id); + wpa_printf(MSG_DEBUG, + "WPA: group state machine entering state SETKEYS (VLAN-ID %d)", + group->vlan_id); group->changed = TRUE; group->wpa_group_state = WPA_GROUP_SETKEYS; group->GTKReKey = FALSE; @@ -4162,8 +4145,8 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, wpa_gtk_update(wpa_auth, group); if (group->GKeyDoneStations) { - wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " - "GKeyDoneStations=%d when starting new GTK rekey", + wpa_printf(MSG_DEBUG, + "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey", group->GKeyDoneStations); group->GKeyDoneStations = 0; } @@ -4216,7 +4199,7 @@ static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) { if (sm->group == ctx) { wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR - " for discconnection due to fatal failure", + " for disconnection due to fatal failure", MAC2STR(sm->addr)); sm->Disconnect = TRUE; } @@ -4228,7 +4211,8 @@ static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE"); + wpa_printf(MSG_DEBUG, + "WPA: group state machine entering state FATAL_FAILURE"); group->changed = TRUE; group->wpa_group_state = WPA_GROUP_FATAL_FAILURE; wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group); @@ -4238,8 +4222,9 @@ static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); + wpa_printf(MSG_DEBUG, + "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)", + group->vlan_id); group->changed = TRUE; group->wpa_group_state = WPA_GROUP_SETKEYSDONE; @@ -4306,8 +4291,9 @@ static int wpa_sm_step(struct wpa_state_machine *sm) sm->in_step_loop = 0; if (sm->pending_deinit) { - wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " - "machine deinit for " MACSTR, MAC2STR(sm->addr)); + wpa_printf(MSG_DEBUG, + "WPA: Completing pending STA state machine deinit for " + MACSTR, MAC2STR(sm->addr)); wpa_free_sta_sm(sm); return 1; } @@ -5007,8 +4993,9 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) return -1; - wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " - "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); + wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR + " to use group state machine for VLAN ID %d", + MAC2STR(sm->addr), vlan_id); wpa_group_get(sm->wpa_auth, group); wpa_group_put(sm->wpa_auth, sm->group); @@ -5037,8 +5024,8 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, * the station has received the frame. */ int timeout_ms = eapol_key_timeout_subseq; - wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " - "timeout by %u ms because of acknowledged frame", + wpa_printf(MSG_DEBUG, + "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame", timeout_ms); eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); eloop_register_timeout(timeout_ms / 1000, @@ -5277,8 +5264,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, * WPA if the supplicant used it first. */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "STA used Secure bit in WPA msg 2/4 - " - "set Secure for 3/4 as workaround"); + "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround"); secure = 1; } } @@ -5311,8 +5297,8 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, elen = pos - kde; res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert " - "PMKR1Name into RSN IE in EAPOL-Key data"); + wpa_printf(MSG_ERROR, + "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data"); os_free(kde); return -1; } @@ -5366,8 +5352,8 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, NULL, 0, 0); } if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " - "into EAPOL-Key Key Data"); + wpa_printf(MSG_ERROR, + "FT: Failed to insert FTIE into EAPOL-Key Key Data"); os_free(kde); return -1; } From 7b156a3c5acdb95916b41482f6e73899876da27b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 19:54:10 +0200 Subject: [PATCH 0300/1105] wpa_auth: Use printf format %zu instead of type casts Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 583ff793f..d04b5e765 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1015,9 +1015,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, key_data = mic + mic_len + 2; key_data_length = WPA_GET_BE16(mic + mic_len); wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR - " key_info=0x%x type=%u mic_len=%u key_data_length=%u", + " key_info=0x%x type=%u mic_len=%zu key_data_length=%u", MAC2STR(sm->addr), key_info, key->type, - (unsigned int) mic_len, key_data_length); + mic_len, key_data_length); wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key header (ending before Key MIC)", key, sizeof(*key)); @@ -1025,10 +1025,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, mic, mic_len); if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { wpa_printf(MSG_INFO, - "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %lu)", + "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)", key_data_length, - (unsigned long) (data_len - sizeof(*hdr) - - keyhdrlen)); + data_len - sizeof(*hdr) - keyhdrlen); return; } @@ -1490,13 +1489,13 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); wpa_printf(MSG_DEBUG, - "WPA: Send EAPOL(version=%d secure=%d mic=%d ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d encr=%d)", + "WPA: Send EAPOL(version=%d secure=%d mic=%d ack=%d install=%d pairwise=%d kde_len=%zu keyidx=%d encr=%d)", version, (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, - pairwise, (unsigned long) kde_len, keyidx, encr); + pairwise, kde_len, keyidx, encr); key_data_len = kde_len; @@ -1603,8 +1602,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, wpa_use_aes_key_wrap(sm->wpa_key_mgmt) || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { wpa_printf(MSG_DEBUG, - "WPA: Encrypt Key Data using AES-WRAP (KEK length %u)", - (unsigned int) sm->PTK.kek_len); + "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)", + sm->PTK.kek_len); if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, (key_data_len - 8) / 8, buf, key_data)) { os_free(hdr); @@ -2066,13 +2065,12 @@ SM_STATE(WPA_PTK, INITPMK) else pmk_len = PMK_LEN; wpa_printf(MSG_DEBUG, - "WPA: PMK from EAPOL state machine (MSK len=%lu PMK len=%u)", - (unsigned long) len, - pmk_len); + "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)", + len, pmk_len); if (len < pmk_len) { wpa_printf(MSG_DEBUG, - "WPA: MSK not long enough (%u) to create PMK (%u)", - (unsigned int) len, (unsigned int) pmk_len); + "WPA: MSK not long enough (%zu) to create PMK (%u)", + len, pmk_len); sm->Disconnect = TRUE; return; } @@ -2504,9 +2502,9 @@ int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies, if (elems.fils_key_confirm_len != sm->fils_key_auth_len) { wpa_printf(MSG_DEBUG, - "FILS: Unexpected Key-Auth length %d (expected %d)", + "FILS: Unexpected Key-Auth length %d (expected %zu)", elems.fils_key_confirm_len, - (int) sm->fils_key_auth_len); + sm->fils_key_auth_len); return -1; } @@ -2841,8 +2839,8 @@ u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf, os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain)); pos += wpabuf_len(plain); - wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__, - (unsigned int) wpabuf_len(plain)); + wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__, + wpabuf_len(plain)); wpabuf_clear_free(plain); sm->fils_completed = 1; return pos; From 1a18f8df6370ae05c5d7f49f40adc43e02387f40 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 20:38:11 +0200 Subject: [PATCH 0301/1105] nl80211: Allow full AP client state capability to be disabled The new driver param full_ap_client_state=0 can be used to test functionality with the driver capability for full AP client state being forced to be disabled. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 4790770bf..3b7c31c89 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8128,6 +8128,9 @@ static int nl80211_set_param(void *priv, const char *param) if (os_strstr(param, "control_port=0")) drv->capa.flags &= ~WPA_DRIVER_FLAGS_CONTROL_PORT; + if (os_strstr(param, "full_ap_client_state=0")) + drv->capa.flags &= ~WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE; + return 0; } From 54e2961f80e283c7fc43b5f667ea6c948f334f0b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 20:39:19 +0200 Subject: [PATCH 0302/1105] Add a hostapd testing option for skipping association pruning The new skip_prune_assoc=1 parameter can be used to configure hostapd not to prune associations from other BSSs operated by the same process when a station associates with another BSS. This can be helpful in testing roaming cases where association and authorization state is maintained in an AP when the stations returns. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 ++ src/ap/ap_config.h | 1 + src/ap/utils.c | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 7a184c440..425446c24 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4206,6 +4206,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->igtk_rsc_override = wpabuf_parse_bin(pos); } else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) { bss->no_beacon_rsnxe = atoi(pos); + } else if (os_strcmp(buf, "skip_prune_assoc") == 0) { + bss->skip_prune_assoc = atoi(pos); #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_SAE } else if (os_strcmp(buf, "sae_password") == 0) { diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 7930fc374..2a0bf0763 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -685,6 +685,7 @@ struct hostapd_bss_config { struct wpabuf *gtk_rsc_override; struct wpabuf *igtk_rsc_override; int no_beacon_rsnxe; + int skip_prune_assoc; #endif /* CONFIG_TESTING_OPTIONS */ #define MESH_ENABLED BIT(0) diff --git a/src/ap/utils.c b/src/ap/utils.c index fcb371bec..bedad6eb0 100644 --- a/src/ap/utils.c +++ b/src/ap/utils.c @@ -56,6 +56,10 @@ static int prune_associations(struct hostapd_iface *iface, void *ctx) ohapd = iface->bss[j]; if (ohapd == data->hapd) continue; +#ifdef CONFIG_TESTING_OPTIONS + if (ohapd->conf->skip_prune_assoc) + continue; +#endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_FST /* Don't prune STAs belong to same FST */ if (ohapd->iface->fst && From 6f291896b923e4a3f9337c7fc6d444bb00f9572e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Mar 2020 20:40:47 +0200 Subject: [PATCH 0303/1105] tests: FT roaming cases with authorized STA entry remaining Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 47 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index b8fecda80..770b26131 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -675,7 +675,7 @@ def run_ap_ft_separate_hostapd(dev, apdev, params, over_ds): hapd1 = hostapd.add_ap(apdev2[1], params) run_roams(dev[0], apdev2, hapd0, hapd1, ssid, passphrase, - over_ds=over_ds, test_connectivity=False) + over_ds=over_ds, test_connectivity=False, roams=2) hglobal.terminate() @@ -995,7 +995,8 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, rsne_override=None, rsnxe_override=None, - no_beacon_rsnxe2=False, ext_key_id=False): + no_beacon_rsnxe2=False, ext_key_id=False, + skip_prune_assoc=False): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") ssid = "test-ft" @@ -1013,6 +1014,8 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['rsnxe_override_ft'] = rsnxe_override if ext_key_id: params['extended_key_id'] = '1' + if skip_prune_assoc: + params['skip_prune_assoc'] = '1' hapd0 = hostapd.add_ap(apdev[0], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['wpa_key_mgmt'] = "FT-SAE" @@ -1028,6 +1031,8 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['no_beacon_rsnxe'] = "1" if ext_key_id: params['extended_key_id'] = '1' + if skip_prune_assoc: + params['skip_prune_assoc'] = '1' hapd1 = hostapd.add_ap(apdev[1], params) key_mgmt = hapd1.get_config()['key_mgmt'] if key_mgmt.split(' ')[0] != "FT-SAE": @@ -3294,3 +3299,41 @@ def test_ap_ft_r0_key_expiration(dev, apdev): dev[0].dump_monitor() dev[0].request("RECONNECT") dev[0].wait_connected() + +def test_ap_ft_no_full_ap_client_state(dev, apdev): + """WPA2-PSK-FT AP with full_ap_client_state=0""" + run_ap_ft_skip_prune_assoc(dev, apdev, False, False) + +def test_ap_ft_skip_prune_assoc(dev, apdev): + """WPA2-PSK-FT AP with skip_prune_assoc""" + run_ap_ft_skip_prune_assoc(dev, apdev, True, True) + +def test_ap_ft_skip_prune_assoc2(dev, apdev): + """WPA2-PSK-FT AP with skip_prune_assoc (disable full_ap_client_state)""" + run_ap_ft_skip_prune_assoc(dev, apdev, True, False, test_connectivity=False) + +def run_ap_ft_skip_prune_assoc(dev, apdev, skip_prune_assoc, + full_ap_client_state, test_connectivity=True): + ssid = "test-ft" + passphrase = "12345678" + + params = ft_params1(ssid=ssid, passphrase=passphrase) + if skip_prune_assoc: + params['skip_prune_assoc'] = '1' + if not full_ap_client_state: + params['driver_params'] = "full_ap_client_state=0" + hapd0 = hostapd.add_ap(apdev[0], params) + params = ft_params2(ssid=ssid, passphrase=passphrase) + if skip_prune_assoc: + params['skip_prune_assoc'] = '1' + if not full_ap_client_state: + params['driver_params'] = "full_ap_client_state=0" + hapd1 = hostapd.add_ap(apdev[1], params) + + run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, + test_connectivity=test_connectivity) + +def test_ap_ft_sae_skip_prune_assoc(dev, apdev): + """WPA2-PSK-FT-SAE AP with skip_prune_assoc""" + hapd0, hapd1 = start_ft_sae(dev[0], apdev, skip_prune_assoc=True) + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) From 478bc00b5f7ae0b90eb070fe865f1e59c4faf360 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 29 Mar 2020 13:46:44 +0200 Subject: [PATCH 0304/1105] tests: Assume --long for UML If we use user-mode-linux, we have time-travel, and then the --long argument doesn't really make a difference, so just assume that's the case. Signed-off-by: Johannes Berg --- tests/hwsim/vm/vm-run.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/hwsim/vm/vm-run.sh b/tests/hwsim/vm/vm-run.sh index b31beb139..06dee0689 100755 --- a/tests/hwsim/vm/vm-run.sh +++ b/tests/hwsim/vm/vm-run.sh @@ -136,6 +136,9 @@ function finish { } trap finish EXIT +if [ -z $KVM ]; then + RUN_TEST_ARGS="--long $RUN_TEST_ARGS" +fi echo "$RUN_TEST_ARGS" > $argsfile A="mac80211_hwsim.support_p2p_device=0 " From 80914e9eb2e451d5b75f786e934b4c078944b5a2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Mar 2020 18:56:48 +0300 Subject: [PATCH 0305/1105] DPP2: Fix build with OpenSSL 1.0.2 (EVP_PKEY_get0_EC_KEY() wrapper) EVP_PKEY_get0_EC_KEY() was added in OpenSSL 1.1.0, so add a compatibility wrapper for it when building with OpenSSL 1.0.2. Fixes: c025c2eb5911 ("DPP: DPPEnvelopedData generation for Configurator backup") Fixes: 7d9e3200544c ("DPP: Received Configurator backup processing") Signed-off-by: Jouni Malinen --- src/common/dpp.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/common/dpp.c b/src/common/dpp.c index f0636b4ac..784961ddd 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -73,6 +73,14 @@ static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, *ps = sig->s; } + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + #endif From eedf08f7a9504ad6743121162e5be009c7eeb519 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 27 Mar 2020 15:51:44 -0700 Subject: [PATCH 0306/1105] tests: Convert kernel-config to defconfig Make the included kernel-config a little more minimal by checking in the defconfig instead. Generate the defconfig by checking out a linux at tag wt-2020-03-17, copy kernel-config to .config, run 'yes "" | make oldconfig && make savedefconfig', and copy resulting defconfig to kernel-config. Signed-off-by: Thomas Pedersen --- tests/hwsim/vm/kernel-config | 2177 +--------------------------------- 1 file changed, 18 insertions(+), 2159 deletions(-) diff --git a/tests/hwsim/vm/kernel-config b/tests/hwsim/vm/kernel-config index e41d69823..503815917 100644 --- a/tests/hwsim/vm/kernel-config +++ b/tests/hwsim/vm/kernel-config @@ -1,905 +1,81 @@ -# -# Automatically generated file; DO NOT EDIT. -# Linux/x86 4.10.0-rc5 Kernel Configuration -# -CONFIG_64BIT=y -CONFIG_X86_64=y -CONFIG_X86=y -CONFIG_INSTRUCTION_DECODER=y -CONFIG_OUTPUT_FORMAT="elf64-x86-64" -CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_MMU=y -CONFIG_ARCH_MMAP_RND_BITS_MIN=28 -CONFIG_ARCH_MMAP_RND_BITS_MAX=32 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y -CONFIG_HAVE_SETUP_PER_CPU_AREA=y -CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y -CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y -CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -CONFIG_ZONE_DMA32=y -CONFIG_AUDIT_ARCH=y -CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y -CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y -CONFIG_X86_64_SMP=y -CONFIG_ARCH_SUPPORTS_UPROBES=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_DEBUG_RODATA=y -CONFIG_PGTABLE_LEVELS=4 -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_IRQ_WORK=y -CONFIG_BUILDTIME_EXTABLE_SORT=y -CONFIG_THREAD_INFO_IN_TASK=y - -# -# General setup -# -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -# CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_BZIP2=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_XZ=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_HAVE_KERNEL_LZ4=y -# CONFIG_KERNEL_GZIP is not set CONFIG_KERNEL_BZIP2=y -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_XZ is not set -# CONFIG_KERNEL_LZO is not set -# CONFIG_KERNEL_LZ4 is not set -CONFIG_DEFAULT_HOSTNAME="(none)" # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -# CONFIG_POSIX_MQUEUE is not set # CONFIG_CROSS_MEMORY_ATTACH is not set -# CONFIG_FHANDLE is not set -# CONFIG_USELIB is not set -# CONFIG_AUDIT is not set -CONFIG_HAVE_ARCH_AUDITSYSCALL=y - -# -# IRQ subsystem -# -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_PENDING_IRQ=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -# CONFIG_IRQ_DOMAIN_DEBUG is not set -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_SPARSE_IRQ=y -CONFIG_CLOCKSOURCE_WATCHDOG=y -CONFIG_ARCH_CLOCKSOURCE_DATA=y -CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y -CONFIG_GENERIC_CMOS_UPDATE=y - -# -# Timers subsystem -# -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ_COMMON=y -# CONFIG_HZ_PERIODIC is not set -CONFIG_NO_HZ_IDLE=y -# CONFIG_NO_HZ_FULL is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y - -# -# CPU/Task time and stats accounting -# -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set -# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_PREEMPT=y CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y - -# -# RCU Subsystem -# -CONFIG_PREEMPT_RCU=y -# CONFIG_RCU_EXPERT is not set -CONFIG_SRCU=y -# CONFIG_TASKS_RCU is not set -CONFIG_RCU_STALL_COMMON=y -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_EXPEDITE_BOOT is not set -# CONFIG_BUILD_BIN2C is not set -# CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=21 -CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -CONFIG_NMI_LOG_BUF_SHIFT=13 -CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y -CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y -CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y -CONFIG_ARCH_SUPPORTS_INT128=y -# CONFIG_CGROUPS is not set -# CONFIG_CHECKPOINT_RESTORE is not set -# CONFIG_NAMESPACES is not set -# CONFIG_SCHED_AUTOGROUP is not set -# CONFIG_SYSFS_DEPRECATED is not set -# CONFIG_RELAY is not set -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_HAVE_PCSPKR_PLATFORM=y -CONFIG_BPF=y -CONFIG_EXPERT=y -CONFIG_MULTIUSER=y -CONFIG_SGETMASK_SYSCALL=y -CONFIG_SYSFS_SYSCALL=y -# CONFIG_SYSCTL_SYSCALL is not set -CONFIG_POSIX_TIMERS=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y -CONFIG_KALLSYMS_BASE_RELATIVE=y -CONFIG_PRINTK=y -CONFIG_PRINTK_NMI=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_PCSPKR_PLATFORM=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -# CONFIG_BPF_SYSCALL is not set -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_ADVISE_SYSCALLS=y -# CONFIG_USERFAULTFD is not set -CONFIG_PCI_QUIRKS=y -CONFIG_MEMBARRIER=y +# CONFIG_FHANDLE is not set CONFIG_EMBEDDED=y -CONFIG_HAVE_PERF_EVENTS=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y # CONFIG_COMPAT_BRK is not set -# CONFIG_SLAB is not set -CONFIG_SLUB=y -# CONFIG_SLOB is not set -# CONFIG_SLAB_FREELIST_RANDOM is not set -CONFIG_SLUB_CPU_PARTIAL=y -# CONFIG_SYSTEM_DATA_VERIFICATION is not set -# CONFIG_PROFILING is not set -CONFIG_TRACEPOINTS=y -CONFIG_HAVE_OPROFILE=y -CONFIG_OPROFILE_NMI_TIMER=y -CONFIG_JUMP_LABEL=y -# CONFIG_STATIC_KEYS_SELFTEST is not set -# CONFIG_UPROBES is not set -# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -CONFIG_ARCH_USE_BUILTIN_BSWAP=y -CONFIG_HAVE_IOREMAP_PROT=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_OPTPROBES=y -CONFIG_HAVE_KPROBES_ON_FTRACE=y -CONFIG_HAVE_NMI=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_CONTIGUOUS=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BREAKPOINT=y -CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y -CONFIG_HAVE_USER_RETURN_NOTIFIER=y -CONFIG_HAVE_PERF_EVENTS_NMI=y -CONFIG_HAVE_PERF_REGS=y -CONFIG_HAVE_PERF_USER_STACK_DUMP=y -CONFIG_HAVE_ARCH_JUMP_LABEL=y -CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y -CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y -CONFIG_HAVE_CMPXCHG_LOCAL=y -CONFIG_HAVE_CMPXCHG_DOUBLE=y -CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -CONFIG_HAVE_GCC_PLUGINS=y -# CONFIG_GCC_PLUGINS is not set -CONFIG_HAVE_CC_STACKPROTECTOR=y -# CONFIG_CC_STACKPROTECTOR is not set -CONFIG_CC_STACKPROTECTOR_NONE=y -# CONFIG_CC_STACKPROTECTOR_REGULAR is not set -# CONFIG_CC_STACKPROTECTOR_STRONG is not set -CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y -CONFIG_HAVE_CONTEXT_TRACKING=y -CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y -CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y -CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y -CONFIG_HAVE_ARCH_HUGE_VMAP=y -CONFIG_HAVE_ARCH_SOFT_DIRTY=y -CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y -CONFIG_ARCH_HAS_ELF_RANDOMIZE=y -CONFIG_HAVE_ARCH_MMAP_RND_BITS=y -CONFIG_HAVE_EXIT_THREAD=y -CONFIG_ARCH_MMAP_RND_BITS=28 -CONFIG_HAVE_COPY_THREAD_TLS=y -CONFIG_HAVE_STACK_VALIDATION=y -# CONFIG_HAVE_ARCH_HASH is not set -# CONFIG_ISA_BUS_API is not set -# CONFIG_CPU_NO_EFFICIENT_FFS is not set -CONFIG_HAVE_ARCH_VMAP_STACK=y -CONFIG_VMAP_STACK=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y -# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -# CONFIG_MODULES is not set -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_BLOCK=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_BSGLIB is not set -# CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_DEV_ZONED is not set -# CONFIG_BLK_CMDLINE_PARSER is not set -# CONFIG_BLK_WBT is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_AIX_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -CONFIG_EFI_PARTITION=y -# CONFIG_SYSV68_PARTITION is not set -# CONFIG_CMDLINE_PARTITION is not set -CONFIG_BLK_MQ_PCI=y - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_DEFAULT_NOOP=y -CONFIG_DEFAULT_IOSCHED="noop" -CONFIG_UNINLINE_SPIN_UNLOCK=y -CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_ARCH_USE_QUEUED_RWLOCKS=y -CONFIG_QUEUED_RWLOCKS=y -# CONFIG_FREEZER is not set - -# -# Processor type and features -# -CONFIG_ZONE_DMA=y CONFIG_SMP=y -CONFIG_X86_FEATURE_NAMES=y -CONFIG_X86_FAST_FEATURE_TESTS=y -# CONFIG_X86_X2APIC is not set -CONFIG_X86_MPPARSE=y -# CONFIG_GOLDFISH is not set -# CONFIG_INTEL_RDT_A is not set # CONFIG_X86_EXTENDED_PLATFORM is not set -# CONFIG_X86_INTEL_LPSS is not set -# CONFIG_X86_AMD_PLATFORM_DEVICE is not set -# CONFIG_IOSF_MBI is not set -CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_HYPERVISOR_GUEST=y CONFIG_PARAVIRT=y -# CONFIG_PARAVIRT_DEBUG is not set CONFIG_PARAVIRT_SPINLOCKS=y -# CONFIG_QUEUED_LOCK_STAT is not set -# CONFIG_XEN is not set -CONFIG_KVM_GUEST=y -# CONFIG_KVM_DEBUG_FS is not set -# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set -CONFIG_PARAVIRT_CLOCK=y -CONFIG_NO_BOOTMEM=y -# CONFIG_MK8 is not set -# CONFIG_MPSC is not set CONFIG_MCORE2=y -# CONFIG_MATOM is not set -# CONFIG_GENERIC_CPU is not set -CONFIG_X86_INTERNODE_CACHE_SHIFT=6 -CONFIG_X86_L1_CACHE_SHIFT=6 -CONFIG_X86_INTEL_USERCOPY=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_P6_NOP=y -CONFIG_X86_TSC=y -CONFIG_X86_CMPXCHG64=y -CONFIG_X86_CMOV=y -CONFIG_X86_MINIMUM_CPU_FAMILY=64 -CONFIG_X86_DEBUGCTLMSR=y -# CONFIG_PROCESSOR_SELECT is not set -CONFIG_CPU_SUP_INTEL=y -CONFIG_CPU_SUP_AMD=y -CONFIG_CPU_SUP_CENTAUR=y -CONFIG_HPET_TIMER=y -CONFIG_DMI=y CONFIG_GART_IOMMU=y -# CONFIG_CALGARY_IOMMU is not set -CONFIG_SWIOTLB=y -CONFIG_IOMMU_HELPER=y -# CONFIG_MAXSMP is not set CONFIG_NR_CPUS=4 -# CONFIG_SCHED_SMT is not set -CONFIG_SCHED_MC=y -CONFIG_SCHED_MC_PRIO=y -# CONFIG_PREEMPT_NONE is not set -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_PREEMPT_COUNT=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_X86_IO_APIC=y -# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set # CONFIG_X86_MCE is not set - -# -# Performance monitoring -# -CONFIG_PERF_EVENTS_INTEL_UNCORE=y -CONFIG_PERF_EVENTS_INTEL_RAPL=y -CONFIG_PERF_EVENTS_INTEL_CSTATE=y -# CONFIG_PERF_EVENTS_AMD_POWER is not set -# CONFIG_VM86 is not set -CONFIG_X86_16BIT=y -CONFIG_X86_ESPFIX64=y -CONFIG_X86_VSYSCALL_EMULATION=y -# CONFIG_I8K is not set -CONFIG_MICROCODE=y -CONFIG_MICROCODE_INTEL=y -# CONFIG_MICROCODE_AMD is not set CONFIG_MICROCODE_OLD_INTERFACE=y -# CONFIG_X86_MSR is not set -# CONFIG_X86_CPUID is not set -CONFIG_ARCH_PHYS_ADDR_T_64BIT=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -# CONFIG_NUMA is not set -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_SPARSEMEM_MANUAL=y -CONFIG_SPARSEMEM=y -CONFIG_HAVE_MEMORY_PRESENT=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_HAVE_MEMBLOCK_NODE_MAP=y -CONFIG_ARCH_DISCARD_MEMBLOCK=y -# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set -# CONFIG_MEMORY_HOTPLUG is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y -# CONFIG_COMPACTION is not set -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_BOUNCE is not set -CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 -# CONFIG_TRANSPARENT_HUGEPAGE is not set -# CONFIG_CLEANCACHE is not set -# CONFIG_CMA is not set -# CONFIG_ZPOOL is not set -# CONFIG_ZBUD is not set -# CONFIG_ZSMALLOC is not set -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT=y -# CONFIG_IDLE_PAGE_TRACKING is not set -CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y -CONFIG_ARCH_HAS_PKEYS=y -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_RESERVE_LOW=64 -CONFIG_MTRR=y # CONFIG_MTRR_SANITIZER is not set -CONFIG_X86_PAT=y -CONFIG_ARCH_USES_PG_UNCACHED=y -CONFIG_ARCH_RANDOM=y -CONFIG_X86_SMAP=y -# CONFIG_X86_INTEL_MPX is not set -CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y -# CONFIG_EFI is not set # CONFIG_SECCOMP is not set CONFIG_HZ_100=y -# CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=100 -CONFIG_SCHED_HRTICK=y -# CONFIG_KEXEC is not set -# CONFIG_KEXEC_FILE is not set -# CONFIG_CRASH_DUMP is not set -CONFIG_PHYSICAL_START=0x1000000 # CONFIG_RELOCATABLE is not set CONFIG_PHYSICAL_ALIGN=0x1000000 -# CONFIG_HOTPLUG_CPU is not set -# CONFIG_LEGACY_VSYSCALL_NATIVE is not set CONFIG_LEGACY_VSYSCALL_EMULATE=y -# CONFIG_LEGACY_VSYSCALL_NONE is not set -# CONFIG_CMDLINE_BOOL is not set -CONFIG_MODIFY_LDT_SYSCALL=y -CONFIG_HAVE_LIVEPATCH=y -CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y - -# -# Power management and ACPI options -# # CONFIG_SUSPEND is not set -# CONFIG_PM is not set -CONFIG_ACPI=y -CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y -CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y -CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y -# CONFIG_ACPI_DEBUGGER is not set -# CONFIG_ACPI_PROCFS_POWER is not set -CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y -# CONFIG_ACPI_EC_DEBUGFS is not set # CONFIG_ACPI_AC is not set # CONFIG_ACPI_BATTERY is not set # CONFIG_ACPI_BUTTON is not set # CONFIG_ACPI_FAN is not set -# CONFIG_ACPI_DOCK is not set -CONFIG_ACPI_CPU_FREQ_PSS=y -CONFIG_ACPI_PROCESSOR_CSTATE=y -CONFIG_ACPI_PROCESSOR_IDLE=y -CONFIG_ACPI_CPPC_LIB=y -CONFIG_ACPI_PROCESSOR=y -# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_CUSTOM_DSDT is not set -CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y -# CONFIG_ACPI_DEBUG is not set -# CONFIG_ACPI_PCI_SLOT is not set -CONFIG_X86_PM_TIMER=y -# CONFIG_ACPI_CONTAINER is not set -CONFIG_ACPI_HOTPLUG_IOAPIC=y -# CONFIG_ACPI_SBS is not set -# CONFIG_ACPI_HED is not set -# CONFIG_ACPI_CUSTOM_METHOD is not set -# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set -CONFIG_HAVE_ACPI_APEI=y -CONFIG_HAVE_ACPI_APEI_NMI=y -# CONFIG_ACPI_APEI is not set -# CONFIG_DPTF_POWER is not set -# CONFIG_PMIC_OPREGION is not set -# CONFIG_ACPI_CONFIGFS is not set -# CONFIG_SFI is not set - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set - -# -# CPU frequency scaling drivers -# -CONFIG_X86_INTEL_PSTATE=y -# CONFIG_X86_PCC_CPUFREQ is not set -# CONFIG_X86_ACPI_CPUFREQ is not set -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -# CONFIG_X86_P4_CLOCKMOD is not set - -# -# shared options -# -# CONFIG_X86_SPEEDSTEP_LIB is not set - -# -# CPU Idle -# -CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y -# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set -# CONFIG_INTEL_IDLE is not set - -# -# Bus options (PCI etc.) -# -CONFIG_PCI=y -CONFIG_PCI_DIRECT=y # CONFIG_PCI_MMCONFIG is not set -CONFIG_PCI_DOMAINS=y -# CONFIG_PCI_CNB20LE_QUIRK is not set -# CONFIG_PCIEPORTBUS is not set -CONFIG_PCI_BUS_ADDR_T_64BIT=y -# CONFIG_PCI_MSI is not set -# CONFIG_PCI_DEBUG is not set -# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set -# CONFIG_PCI_STUB is not set -# CONFIG_HT_IRQ is not set -# CONFIG_PCI_IOV is not set -# CONFIG_PCI_PRI is not set -# CONFIG_PCI_PASID is not set -CONFIG_PCI_LABEL=y -# CONFIG_HOTPLUG_PCI is not set - -# -# PCI host controller drivers -# -# CONFIG_ISA_BUS is not set # CONFIG_ISA_DMA_API is not set -CONFIG_AMD_NB=y -# CONFIG_PCCARD is not set -# CONFIG_RAPIDIO is not set -# CONFIG_X86_SYSFB is not set - -# -# Executable file formats / Emulations -# -CONFIG_BINFMT_ELF=y -CONFIG_ELFCORE=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_BINFMT_SCRIPT=y -# CONFIG_HAVE_AOUT is not set -# CONFIG_BINFMT_MISC is not set -CONFIG_COREDUMP=y -# CONFIG_IA32_EMULATION is not set -# CONFIG_X86_X32 is not set -CONFIG_X86_DEV_DMA_OPS=y -CONFIG_PMC_ATOM=y +# CONFIG_DMIID is not set +# CONFIG_VIRTUALIZATION is not set +CONFIG_JUMP_LABEL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +# CONFIG_COMPACTION is not set +# CONFIG_BOUNCE is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 CONFIG_NET=y -CONFIG_NET_INGRESS=y - -# -# Networking options -# CONFIG_PACKET=y -# CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y -# CONFIG_UNIX_DIAG is not set -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y -# CONFIG_IP_FIB_TRIE_STATS is not set CONFIG_IP_MULTIPLE_TABLES=y -# CONFIG_IP_ROUTE_MULTIPATH is not set -# CONFIG_IP_ROUTE_VERBOSE is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE_DEMUX is not set -CONFIG_NET_IP_TUNNEL=y -# CONFIG_IP_MROUTE is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_NET_UDP_TUNNEL is not set -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_DIAG is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=y -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_IPV6_ILA is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=y -CONFIG_INET6_XFRM_MODE_TUNNEL=y -CONFIG_INET6_XFRM_MODE_BEET=y -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -# CONFIG_IPV6_VTI is not set -CONFIG_IPV6_SIT=y -# CONFIG_IPV6_SIT_6RD is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_FOU is not set -# CONFIG_IPV6_FOU_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_IPV6_SEG6_LWTUNNEL is not set -# CONFIG_IPV6_SEG6_HMAC is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NET_PTP_CLASSIFY is not set -# CONFIG_NETWORK_PHY_TIMESTAMPING is not set CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_NETFILTER_ADVANCED=y CONFIG_BRIDGE_NETFILTER=y - -# -# Core Netfilter Configuration -# -CONFIG_NETFILTER_INGRESS=y -CONFIG_NETFILTER_NETLINK=y -# CONFIG_NETFILTER_NETLINK_ACCT is not set -# CONFIG_NETFILTER_NETLINK_QUEUE is not set -# CONFIG_NETFILTER_NETLINK_LOG is not set -# CONFIG_NF_CONNTRACK is not set -# CONFIG_NF_LOG_NETDEV is not set CONFIG_NF_TABLES=y -# CONFIG_NF_TABLES_INET is not set -# CONFIG_NF_TABLES_NETDEV is not set -# CONFIG_NFT_EXTHDR is not set -# CONFIG_NFT_META is not set -# CONFIG_NFT_RT is not set -# CONFIG_NFT_NUMGEN is not set -# CONFIG_NFT_SET_RBTREE is not set -# CONFIG_NFT_SET_HASH is not set -# CONFIG_NFT_COUNTER is not set -# CONFIG_NFT_LOG is not set -# CONFIG_NFT_LIMIT is not set -# CONFIG_NFT_OBJREF is not set -# CONFIG_NFT_QUOTA is not set -# CONFIG_NFT_REJECT is not set -# CONFIG_NFT_COMPAT is not set -# CONFIG_NFT_HASH is not set CONFIG_NETFILTER_XTABLES=y - -# -# Xtables combined modules -# -# CONFIG_NETFILTER_XT_MARK is not set - -# -# Xtables targets -# -# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set -# CONFIG_NETFILTER_XT_TARGET_HMARK is not set -# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set -# CONFIG_NETFILTER_XT_TARGET_LOG is not set -# CONFIG_NETFILTER_XT_TARGET_MARK is not set -# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set -# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set -# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set -# CONFIG_NETFILTER_XT_TARGET_TEE is not set -# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set - -# -# Xtables matches -# -# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set -# CONFIG_NETFILTER_XT_MATCH_BPF is not set -# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set -# CONFIG_NETFILTER_XT_MATCH_CPU is not set -# CONFIG_NETFILTER_XT_MATCH_DCCP is not set -# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set -# CONFIG_NETFILTER_XT_MATCH_DSCP is not set -# CONFIG_NETFILTER_XT_MATCH_ECN is not set -# CONFIG_NETFILTER_XT_MATCH_ESP is not set -# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set -# CONFIG_NETFILTER_XT_MATCH_HL is not set -# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set -# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set -# CONFIG_NETFILTER_XT_MATCH_L2TP is not set -# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set -# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set -# CONFIG_NETFILTER_XT_MATCH_MAC is not set -# CONFIG_NETFILTER_XT_MATCH_MARK is not set -# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set -# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set -# CONFIG_NETFILTER_XT_MATCH_OSF is not set -# CONFIG_NETFILTER_XT_MATCH_OWNER is not set -# CONFIG_NETFILTER_XT_MATCH_POLICY is not set -# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y -# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set -# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set -# CONFIG_NETFILTER_XT_MATCH_REALM is not set -# CONFIG_NETFILTER_XT_MATCH_RECENT is not set -# CONFIG_NETFILTER_XT_MATCH_SCTP is not set -# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set -# CONFIG_NETFILTER_XT_MATCH_STRING is not set -# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set -# CONFIG_NETFILTER_XT_MATCH_TIME is not set -# CONFIG_NETFILTER_XT_MATCH_U32 is not set -# CONFIG_IP_SET is not set -# CONFIG_IP_VS is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_NF_DEFRAG_IPV4 is not set -# CONFIG_NF_SOCKET_IPV4 is not set -# CONFIG_NF_TABLES_IPV4 is not set -# CONFIG_NF_TABLES_ARP is not set -# CONFIG_NF_DUP_IPV4 is not set -# CONFIG_NF_LOG_ARP is not set -# CONFIG_NF_LOG_IPV4 is not set -# CONFIG_NF_REJECT_IPV4 is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set - -# -# IPv6: Netfilter Configuration -# -# CONFIG_NF_DEFRAG_IPV6 is not set -# CONFIG_NF_SOCKET_IPV6 is not set -# CONFIG_NF_TABLES_IPV6 is not set -# CONFIG_NF_DUP_IPV6 is not set -# CONFIG_NF_REJECT_IPV6 is not set -# CONFIG_NF_LOG_IPV6 is not set -# CONFIG_IP6_NF_IPTABLES is not set CONFIG_NF_TABLES_BRIDGE=y -# CONFIG_NF_LOG_BRIDGE is not set CONFIG_BRIDGE_NF_EBTABLES=y -# CONFIG_BRIDGE_EBT_BROUTE is not set CONFIG_BRIDGE_EBT_T_FILTER=y -# CONFIG_BRIDGE_EBT_T_NAT is not set -# CONFIG_BRIDGE_EBT_802_3 is not set -# CONFIG_BRIDGE_EBT_AMONG is not set CONFIG_BRIDGE_EBT_ARP=y CONFIG_BRIDGE_EBT_IP=y CONFIG_BRIDGE_EBT_IP6=y -# CONFIG_BRIDGE_EBT_LIMIT is not set -# CONFIG_BRIDGE_EBT_MARK is not set CONFIG_BRIDGE_EBT_PKTTYPE=y -# CONFIG_BRIDGE_EBT_STP is not set -# CONFIG_BRIDGE_EBT_VLAN is not set CONFIG_BRIDGE_EBT_ARPREPLY=y -# CONFIG_BRIDGE_EBT_DNAT is not set -# CONFIG_BRIDGE_EBT_MARK_T is not set -# CONFIG_BRIDGE_EBT_REDIRECT is not set -# CONFIG_BRIDGE_EBT_SNAT is not set -# CONFIG_BRIDGE_EBT_LOG is not set -# CONFIG_BRIDGE_EBT_NFLOG is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_L2TP is not set -CONFIG_STP=y CONFIG_BRIDGE=y -CONFIG_BRIDGE_IGMP_SNOOPING=y -# CONFIG_BRIDGE_VLAN_FILTERING is not set -CONFIG_HAVE_NET_DSA=y -# CONFIG_NET_DSA is not set CONFIG_VLAN_8021Q=y -# CONFIG_VLAN_8021Q_GVRP is not set -# CONFIG_VLAN_8021Q_MVRP is not set -# CONFIG_DECNET is not set -CONFIG_LLC=y -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_PHONET is not set -# CONFIG_6LOWPAN is not set -# CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set -# CONFIG_BATMAN_ADV is not set -# CONFIG_OPENVSWITCH is not set -# CONFIG_VSOCKETS is not set -# CONFIG_NETLINK_DIAG is not set -# CONFIG_MPLS is not set -# CONFIG_HSR is not set -# CONFIG_NET_SWITCHDEV is not set -# CONFIG_NET_L3_MASTER_DEV is not set -# CONFIG_NET_NCSI is not set -CONFIG_RPS=y -CONFIG_RFS_ACCEL=y -CONFIG_XPS=y -CONFIG_NET_RX_BUSY_POLL=y -CONFIG_BQL=y -CONFIG_NET_FLOW_LIMIT=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set -# CONFIG_AF_KCM is not set -# CONFIG_STREAM_PARSER is not set -CONFIG_FIB_RULES=y -CONFIG_WIRELESS=y -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PROC=y CONFIG_CFG80211=y -# CONFIG_NL80211_TESTMODE is not set CONFIG_CFG80211_DEVELOPER_WARNINGS=y -# CONFIG_CFG80211_CERTIFICATION_ONUS is not set -CONFIG_CFG80211_DEFAULT_PS=y CONFIG_CFG80211_DEBUGFS=y -# CONFIG_CFG80211_INTERNAL_REGDB is not set -CONFIG_CFG80211_CRDA_SUPPORT=y CONFIG_CFG80211_WEXT=y -# CONFIG_LIB80211 is not set CONFIG_MAC80211=y -CONFIG_MAC80211_HAS_RC=y -CONFIG_MAC80211_RC_MINSTREL=y -CONFIG_MAC80211_RC_MINSTREL_HT=y -# CONFIG_MAC80211_RC_MINSTREL_VHT is not set -CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y -CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" CONFIG_MAC80211_MESH=y CONFIG_MAC80211_DEBUGFS=y CONFIG_MAC80211_MESSAGE_TRACING=y @@ -909,978 +85,66 @@ CONFIG_MAC80211_VERBOSE_DEBUG=y CONFIG_MAC80211_MLME_DEBUG=y CONFIG_MAC80211_STA_DEBUG=y CONFIG_MAC80211_HT_DEBUG=y -# CONFIG_MAC80211_OCB_DEBUG is not set CONFIG_MAC80211_IBSS_DEBUG=y CONFIG_MAC80211_PS_DEBUG=y -# CONFIG_MAC80211_MPL_DEBUG is not set -# CONFIG_MAC80211_MPATH_DEBUG is not set -# CONFIG_MAC80211_MHWMP_DEBUG is not set -# CONFIG_MAC80211_MESH_SYNC_DEBUG is not set -# CONFIG_MAC80211_MESH_CSA_DEBUG is not set -# CONFIG_MAC80211_MESH_PS_DEBUG is not set CONFIG_MAC80211_TDLS_DEBUG=y -# CONFIG_MAC80211_DEBUG_COUNTERS is not set -CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 -# CONFIG_WIMAX is not set CONFIG_RFKILL=y -# CONFIG_RFKILL_INPUT is not set CONFIG_NET_9P=y CONFIG_NET_9P_VIRTIO=y -# CONFIG_NET_9P_DEBUG is not set -# CONFIG_CAIF is not set -# CONFIG_CEPH_LIB is not set -# CONFIG_NFC is not set -# CONFIG_LWTUNNEL is not set -CONFIG_DST_CACHE=y -# CONFIG_NET_DEVLINK is not set -CONFIG_MAY_USE_DEVLINK=y -CONFIG_HAVE_EBPF_JIT=y - -# -# Device Drivers -# - -# -# Generic Driver Options -# +CONFIG_PCI=y CONFIG_UEVENT_HELPER=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_DEVTMPFS is not set -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set -CONFIG_ALLOW_DEV_COREDUMP=y -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_GENERIC_CPU_DEVICES is not set -CONFIG_GENERIC_CPU_AUTOPROBE=y -# CONFIG_DMA_SHARED_BUFFER is not set - -# -# Bus devices -# -# CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -# CONFIG_OF is not set -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -# CONFIG_PARPORT is not set -CONFIG_PNP=y # CONFIG_PNP_DEBUG_MESSAGES is not set - -# -# Protocols -# -CONFIG_PNPACPI=y # CONFIG_BLK_DEV is not set -# CONFIG_BLK_DEV_NVME is not set -# CONFIG_NVME_FC is not set -# CONFIG_NVME_TARGET is not set - -# -# Misc devices -# -# CONFIG_SENSORS_LIS3LV02D is not set -# CONFIG_DUMMY_IRQ is not set -# CONFIG_IBM_ASM is not set -# CONFIG_PHANTOM is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set -# CONFIG_ENCLOSURE_SERVICES is not set -# CONFIG_HP_ILO is not set -# CONFIG_SRAM is not set -# CONFIG_C2PORT is not set - -# -# EEPROM support -# -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_CB710_CORE is not set - -# -# Texas Instruments shared transport line discipline -# - -# -# Altera FPGA firmware download module -# -# CONFIG_INTEL_MEI is not set -# CONFIG_INTEL_MEI_ME is not set -# CONFIG_INTEL_MEI_TXE is not set -# CONFIG_VMWARE_VMCI is not set - -# -# Intel MIC Bus Driver -# -# CONFIG_INTEL_MIC_BUS is not set - -# -# SCIF Bus Driver -# -# CONFIG_SCIF_BUS is not set - -# -# VOP Bus Driver -# -# CONFIG_VOP_BUS is not set - -# -# Intel MIC Host Driver -# - -# -# Intel MIC Card Driver -# - -# -# SCIF Driver -# - -# -# Intel MIC Coprocessor State Management (COSM) Drivers -# - -# -# VOP Driver -# -# CONFIG_GENWQE is not set -# CONFIG_ECHO is not set -# CONFIG_CXL_BASE is not set -# CONFIG_CXL_AFU_DRIVER_OPS is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_DMA is not set -# CONFIG_SCSI_NETLINK is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_FIREWIRE is not set -# CONFIG_FIREWIRE_NOSY is not set -# CONFIG_MACINTOSH_DRIVERS is not set CONFIG_NETDEVICES=y -CONFIG_NET_CORE=y -# CONFIG_BONDING is not set CONFIG_DUMMY=y -# CONFIG_EQUALIZER is not set -# CONFIG_NET_TEAM is not set -# CONFIG_MACVLAN is not set -# CONFIG_VXLAN is not set -# CONFIG_MACSEC is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_TUN is not set -# CONFIG_TUN_VNET_CROSS_LE is not set -# CONFIG_VETH is not set -# CONFIG_VIRTIO_NET is not set -# CONFIG_NLMON is not set -# CONFIG_ARCNET is not set - -# -# CAIF transport drivers -# - -# -# Distributed Switch Architecture drivers -# # CONFIG_ETHERNET is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_NET_SB1000 is not set -# CONFIG_PHYLIB is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Host-side USB support is needed for USB Network Adapter support -# -CONFIG_WLAN=y -# CONFIG_WIRELESS_WDS is not set -CONFIG_WLAN_VENDOR_ADMTEK=y -# CONFIG_ADM8211 is not set -CONFIG_WLAN_VENDOR_ATH=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_ATH5K is not set -# CONFIG_ATH5K_PCI is not set -# CONFIG_ATH9K is not set -# CONFIG_ATH6KL is not set -# CONFIG_WIL6210 is not set -# CONFIG_ATH10K is not set -# CONFIG_WCN36XX is not set -CONFIG_WLAN_VENDOR_ATMEL=y -# CONFIG_ATMEL is not set -CONFIG_WLAN_VENDOR_BROADCOM=y -# CONFIG_B43 is not set -# CONFIG_B43LEGACY is not set -# CONFIG_BRCMSMAC is not set -# CONFIG_BRCMFMAC is not set -CONFIG_WLAN_VENDOR_CISCO=y -CONFIG_WLAN_VENDOR_INTEL=y -# CONFIG_IPW2100 is not set -# CONFIG_IPW2200 is not set -# CONFIG_IWL4965 is not set -# CONFIG_IWL3945 is not set -# CONFIG_IWLWIFI is not set -CONFIG_WLAN_VENDOR_INTERSIL=y -# CONFIG_HOSTAP is not set -# CONFIG_HERMES is not set -# CONFIG_P54_COMMON is not set -# CONFIG_PRISM54 is not set -CONFIG_WLAN_VENDOR_MARVELL=y -# CONFIG_LIBERTAS is not set -# CONFIG_LIBERTAS_THINFIRM is not set -# CONFIG_MWIFIEX is not set -# CONFIG_MWL8K is not set -CONFIG_WLAN_VENDOR_MEDIATEK=y -CONFIG_WLAN_VENDOR_RALINK=y -# CONFIG_RT2X00 is not set -CONFIG_WLAN_VENDOR_REALTEK=y -# CONFIG_RTL8180 is not set -CONFIG_RTL_CARDS=y -# CONFIG_RTL8192CE is not set -# CONFIG_RTL8192SE is not set -# CONFIG_RTL8192DE is not set -# CONFIG_RTL8723AE is not set -# CONFIG_RTL8723BE is not set -# CONFIG_RTL8188EE is not set -# CONFIG_RTL8192EE is not set -# CONFIG_RTL8821AE is not set -CONFIG_WLAN_VENDOR_RSI=y -# CONFIG_RSI_91X is not set -CONFIG_WLAN_VENDOR_ST=y -# CONFIG_CW1200 is not set -CONFIG_WLAN_VENDOR_TI=y -# CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set -# CONFIG_WL18XX is not set -# CONFIG_WLCORE is not set -CONFIG_WLAN_VENDOR_ZYDAS=y CONFIG_MAC80211_HWSIM=y - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# -# CONFIG_WAN is not set -# CONFIG_VMXNET3 is not set -# CONFIG_FUJITSU_ES is not set -# CONFIG_ISDN is not set -# CONFIG_NVM is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set -# CONFIG_INPUT_SPARSEKMAP is not set -# CONFIG_INPUT_MATRIXKMAP is not set - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set -# CONFIG_RMI4_CORE is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set -# CONFIG_SERIO_LIBPS2 is not set -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_ALTERA_PS2 is not set -# CONFIG_SERIO_PS2MULT is not set -# CONFIG_SERIO_ARC_PS2 is not set -# CONFIG_USERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_TTY=y -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_NOZOMI is not set -# CONFIG_N_GSM is not set -# CONFIG_TRACE_SINK is not set -CONFIG_DEVMEM=y -# CONFIG_DEVKMEM is not set - -# -# Serial drivers -# -CONFIG_SERIAL_EARLYCON=y CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y # CONFIG_SERIAL_8250_PNP is not set -# CONFIG_SERIAL_8250_FINTEK is not set CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_FSL is not set -# CONFIG_SERIAL_8250_DW is not set -# CONFIG_SERIAL_8250_RT288X is not set -CONFIG_SERIAL_8250_LPSS=y # CONFIG_SERIAL_8250_MID is not set -# CONFIG_SERIAL_8250_MOXA is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_UARTLITE is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -# CONFIG_SERIAL_SCCNXP is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -# CONFIG_SERIAL_ARC is not set -# CONFIG_SERIAL_RP2 is not set -# CONFIG_SERIAL_FSL_LPUART is not set -# CONFIG_TTY_PRINTK is not set -# CONFIG_VIRTIO_CONSOLE is not set -# CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_MWAVE is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HPET is not set -# CONFIG_HANGCHECK_TIMER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set -CONFIG_DEVPORT=y -# CONFIG_XILLYBUS is not set - -# -# I2C support -# -# CONFIG_I2C is not set -# CONFIG_SPI is not set -# CONFIG_SPMI is not set -# CONFIG_HSI is not set - -# -# PPS support -# -# CONFIG_PPS is not set - -# -# PPS generators support -# - -# -# PTP clock support -# -# CONFIG_PTP_1588_CLOCK is not set - -# -# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. -# -# CONFIG_GPIOLIB is not set -# CONFIG_W1 is not set -# CONFIG_POWER_AVS is not set -# CONFIG_POWER_RESET is not set CONFIG_POWER_SUPPLY=y -# CONFIG_POWER_SUPPLY_DEBUG is not set -# CONFIG_PDA_POWER is not set -# CONFIG_TEST_POWER is not set -# CONFIG_BATTERY_DS2780 is not set -# CONFIG_BATTERY_DS2781 is not set -# CONFIG_BATTERY_BQ27XXX is not set -# CONFIG_CHARGER_MAX8903 is not set # CONFIG_HWMON is not set -CONFIG_THERMAL=y -# CONFIG_THERMAL_WRITABLE_TRIPS is not set -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set -# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set -# CONFIG_THERMAL_GOV_FAIR_SHARE is not set -CONFIG_THERMAL_GOV_STEP_WISE=y -# CONFIG_THERMAL_GOV_BANG_BANG is not set -# CONFIG_THERMAL_GOV_USER_SPACE is not set -# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set -# CONFIG_THERMAL_EMULATION is not set -# CONFIG_INTEL_POWERCLAMP is not set -# CONFIG_INTEL_SOC_DTS_THERMAL is not set - -# -# ACPI INT340X thermal drivers -# -# CONFIG_INT340X_THERMAL is not set -# CONFIG_INTEL_PCH_THERMAL is not set -# CONFIG_WATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -# CONFIG_SSB is not set -CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# -# CONFIG_BCMA is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_CROS_EC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_LPC_ICH is not set -# CONFIG_LPC_SCH is not set -# CONFIG_MFD_INTEL_LPSS_ACPI is not set -# CONFIG_MFD_INTEL_LPSS_PCI is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_KEMPLD is not set -# CONFIG_MFD_MT6397 is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_RTSX_PCI is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_SYSCON is not set -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_REGULATOR is not set -# CONFIG_MEDIA_SUPPORT is not set - -# -# Graphics support -# -# CONFIG_AGP is not set -CONFIG_VGA_ARB=y -CONFIG_VGA_ARB_MAX_GPUS=16 -# CONFIG_VGA_SWITCHEROO is not set -# CONFIG_DRM is not set - -# -# ACP (Audio CoProcessor) Configuration -# - -# -# Frame buffer Devices -# CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FB_CMDLINE=y -CONFIG_FB_NOTIFY=y -# CONFIG_FB_DDC is not set -CONFIG_FB_BOOT_VESA_SUPPORT=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ARC is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_VGA16 is not set CONFIG_FB_VESA=y -# CONFIG_FB_N411 is not set -# CONFIG_FB_HGA is not set -# CONFIG_FB_OPENCORES is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_I740 is not set -# CONFIG_FB_LE80578 is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_S3 is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_VT8623 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_ARK is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_CARMINE is not set -# CONFIG_FB_IBM_GXT4500 is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_MB862XX is not set -# CONFIG_FB_BROADSHEET is not set -# CONFIG_FB_AUO_K190X is not set -# CONFIG_FB_SIMPLE is not set -# CONFIG_FB_SM712 is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -# CONFIG_VGASTATE is not set - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y CONFIG_VGACON_SOFT_SCROLLBACK=y -CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 -CONFIG_DUMMY_CONSOLE=y -CONFIG_DUMMY_CONSOLE_COLUMNS=80 -CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -# CONFIG_LOGO is not set -# CONFIG_SOUND is not set - -# -# HID support -# -CONFIG_HID=y -# CONFIG_HID_BATTERY_STRENGTH is not set CONFIG_HIDRAW=y -# CONFIG_UHID is not set -CONFIG_HID_GENERIC=y - -# -# Special HID drivers -# -# CONFIG_HID_A4TECH is not set -# CONFIG_HID_ACRUX is not set -# CONFIG_HID_APPLE is not set -# CONFIG_HID_AUREAL is not set -# CONFIG_HID_BELKIN is not set -# CONFIG_HID_CHERRY is not set -# CONFIG_HID_CHICONY is not set -# CONFIG_HID_CMEDIA is not set -# CONFIG_HID_CYPRESS is not set -# CONFIG_HID_DRAGONRISE is not set -# CONFIG_HID_EMS_FF is not set -# CONFIG_HID_ELECOM is not set -# CONFIG_HID_EZKEY is not set -# CONFIG_HID_GEMBIRD is not set -# CONFIG_HID_GFRM is not set -# CONFIG_HID_KEYTOUCH is not set -# CONFIG_HID_KYE is not set -# CONFIG_HID_WALTOP is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID_ICADE is not set -# CONFIG_HID_TWINHAN is not set -# CONFIG_HID_KENSINGTON is not set -# CONFIG_HID_LCPOWER is not set -# CONFIG_HID_LENOVO is not set -# CONFIG_HID_LOGITECH is not set -# CONFIG_HID_MAGICMOUSE is not set -# CONFIG_HID_MAYFLASH is not set -# CONFIG_HID_MICROSOFT is not set -# CONFIG_HID_MONTEREY is not set -# CONFIG_HID_MULTITOUCH is not set -# CONFIG_HID_ORTEK is not set -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PETALYNX is not set -# CONFIG_HID_PICOLCD is not set -# CONFIG_HID_PLANTRONICS is not set -# CONFIG_HID_PRIMAX is not set -# CONFIG_HID_SAITEK is not set -# CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SPEEDLINK is not set -# CONFIG_HID_STEELSERIES is not set -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_RMI is not set -# CONFIG_HID_GREENASIA is not set -# CONFIG_HID_SMARTJOYPLUS is not set -# CONFIG_HID_TIVO is not set -# CONFIG_HID_TOPSEED is not set -# CONFIG_HID_THRUSTMASTER is not set -# CONFIG_HID_UDRAW_PS3 is not set -# CONFIG_HID_WACOM is not set -# CONFIG_HID_XINMO is not set -# CONFIG_HID_ZEROPLUS is not set -# CONFIG_HID_ZYDACRON is not set -# CONFIG_HID_SENSOR_HUB is not set -# CONFIG_HID_ALPS is not set - -# -# Intel ISH HID support -# -# CONFIG_INTEL_ISH_HID is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SUPPORT is not set -# CONFIG_UWB is not set -# CONFIG_MMC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_ACCESSIBILITY is not set -# CONFIG_INFINIBAND is not set -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -# CONFIG_EDAC is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_MC146818_LIB=y -# CONFIG_RTC_CLASS is not set -# CONFIG_DMADEVICES is not set - -# -# DMABUF options -# -# CONFIG_SYNC_FILE is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set CONFIG_VIRT_DRIVERS=y -CONFIG_VIRTIO=y - -# -# Virtio drivers -# CONFIG_VIRTIO_PCI=y -CONFIG_VIRTIO_PCI_LEGACY=y -# CONFIG_VIRTIO_BALLOON is not set -# CONFIG_VIRTIO_INPUT is not set -# CONFIG_VIRTIO_MMIO is not set - -# -# Microsoft Hyper-V guest support -# -# CONFIG_HYPERV is not set -# CONFIG_STAGING is not set # CONFIG_X86_PLATFORM_DEVICES is not set -# CONFIG_CHROME_PLATFORMS is not set - -# -# Hardware Spinlock drivers -# - -# -# Clock Source drivers -# -CONFIG_CLKEVT_I8253=y -CONFIG_I8253_LOCK=y -CONFIG_CLKBLD_I8253=y -# CONFIG_ATMEL_PIT is not set -# CONFIG_SH_TIMER_CMT is not set -# CONFIG_SH_TIMER_MTU2 is not set -# CONFIG_SH_TIMER_TMU is not set -# CONFIG_EM_TIMER_STI is not set -CONFIG_MAILBOX=y -CONFIG_PCC=y -# CONFIG_ALTERA_MBOX is not set # CONFIG_IOMMU_SUPPORT is not set - -# -# Remoteproc drivers -# -# CONFIG_REMOTEPROC is not set - -# -# Rpmsg drivers -# - -# -# SOC (System On Chip) specific Drivers -# - -# -# Broadcom SoC drivers -# -# CONFIG_SUNXI_SRAM is not set -# CONFIG_SOC_TI is not set -# CONFIG_PM_DEVFREQ is not set -# CONFIG_EXTCON is not set -# CONFIG_MEMORY is not set -# CONFIG_IIO is not set -# CONFIG_NTB is not set -# CONFIG_VME_BUS is not set -# CONFIG_PWM is not set -CONFIG_ARM_GIC_MAX_NR=1 -# CONFIG_IPACK_BUS is not set -# CONFIG_RESET_CONTROLLER is not set -# CONFIG_FMC is not set - -# -# PHY Subsystem -# -# CONFIG_GENERIC_PHY is not set -# CONFIG_PHY_PXA_28NM_HSIC is not set -# CONFIG_PHY_PXA_28NM_USB2 is not set -# CONFIG_BCM_KONA_USB2_PHY is not set -# CONFIG_POWERCAP is not set -# CONFIG_MCB is not set - -# -# Performance monitor support -# -# CONFIG_RAS is not set -# CONFIG_THUNDERBOLT is not set - -# -# Android -# -# CONFIG_ANDROID is not set -# CONFIG_NVMEM is not set -# CONFIG_STM is not set -# CONFIG_INTEL_TH is not set - -# -# FPGA Configuration Support -# -# CONFIG_FPGA is not set - -# -# Firmware Drivers -# -# CONFIG_ARM_SCPI_PROTOCOL is not set -# CONFIG_EDD is not set -CONFIG_FIRMWARE_MEMMAP=y -# CONFIG_DELL_RBU is not set -# CONFIG_DCDBAS is not set -# CONFIG_DMIID is not set -# CONFIG_DMI_SYSFS is not set -CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y -# CONFIG_ISCSI_IBFT_FIND is not set -# CONFIG_FW_CFG_SYSFS is not set -# CONFIG_GOOGLE_FIRMWARE is not set -# CONFIG_EFI_DEV_PATH_PARSER is not set - -# -# Tegra firmware driver -# - -# -# File systems -# -CONFIG_DCACHE_WORD_ACCESS=y -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_EXT4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set -# CONFIG_F2FS_FS is not set -# CONFIG_FS_DAX is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_EXPORTFS_BLOCK_OPS is not set -CONFIG_FILE_LOCKING=y -CONFIG_MANDATORY_FILE_LOCKING=y -# CONFIG_FS_ENCRYPTION is not set -# CONFIG_FSNOTIFY is not set # CONFIG_DNOTIFY is not set # CONFIG_INOTIFY_USER is not set -# CONFIG_FANOTIFY is not set -# CONFIG_QUOTA is not set -# CONFIG_QUOTACTL is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set -# CONFIG_OVERLAY_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -# CONFIG_PROC_CHILDREN is not set -CONFIG_KERNFS=y -CONFIG_SYSFS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y -CONFIG_TMPFS_XATTR=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_ARCH_HAS_GIGANTIC_PAGE=y CONFIG_CONFIGFS_FS=y # CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NETWORK_FILESYSTEMS=y -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_CEPH_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set CONFIG_9P_FS=y CONFIG_9P_FS_POSIX_ACL=y -# CONFIG_9P_FS_SECURITY is not set -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_MAC_ROMAN is not set -# CONFIG_NLS_MAC_CELTIC is not set -# CONFIG_NLS_MAC_CENTEURO is not set -# CONFIG_NLS_MAC_CROATIAN is not set -# CONFIG_NLS_MAC_CYRILLIC is not set -# CONFIG_NLS_MAC_GAELIC is not set -# CONFIG_NLS_MAC_GREEK is not set -# CONFIG_NLS_MAC_ICELAND is not set -# CONFIG_NLS_MAC_INUIT is not set -# CONFIG_NLS_MAC_ROMANIAN is not set -# CONFIG_NLS_MAC_TURKISH is not set -# CONFIG_NLS_UTF8 is not set -# CONFIG_DLM is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y - -# -# printk and dmesg options -# +CONFIG_CRYPTO_ECHAINIV=y +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_HW is not set CONFIG_PRINTK_TIME=y -CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 -# CONFIG_BOOT_PRINTK_DELAY is not set CONFIG_DYNAMIC_DEBUG=y - -# -# Compile-time checks and compiler options -# CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_REDUCED=y -# CONFIG_DEBUG_INFO_SPLIT is not set -# CONFIG_DEBUG_INFO_DWARF4 is not set -# CONFIG_GDB_SCRIPTS is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_READABLE_ASM is not set -# CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_PAGE_OWNER is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_SECTION_MISMATCH=y -CONFIG_SECTION_MISMATCH_WARN_ONLY=y -CONFIG_ARCH_WANT_FRAME_POINTERS=y -CONFIG_FRAME_POINTER=y -# CONFIG_STACK_VALIDATION is not set -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set CONFIG_MAGIC_SYSRQ=y -CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 -CONFIG_DEBUG_KERNEL=y - -# -# Memory Debugging -# CONFIG_PAGE_EXTENSION=y CONFIG_DEBUG_PAGEALLOC=y -# CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT is not set -# CONFIG_PAGE_POISONING is not set -# CONFIG_DEBUG_PAGE_REF is not set +CONFIG_DEBUG_RODATA_TEST=y CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_SELFTEST=y CONFIG_DEBUG_OBJECTS_FREE=y @@ -1888,426 +152,21 @@ CONFIG_DEBUG_OBJECTS_TIMERS=y CONFIG_DEBUG_OBJECTS_WORK=y CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 CONFIG_SLUB_DEBUG_ON=y -# CONFIG_SLUB_STATS is not set -CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=400 -# CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF is not set CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_VIRTUAL is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set -CONFIG_HAVE_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_STACKOVERFLOW is not set -CONFIG_HAVE_ARCH_KMEMCHECK=y -CONFIG_HAVE_ARCH_KASAN=y -# CONFIG_KASAN is not set -CONFIG_ARCH_HAS_KCOV=y -# CONFIG_KCOV is not set -# CONFIG_DEBUG_SHIRQ is not set - -# -# Debug Lockups and Hangs -# -CONFIG_LOCKUP_DETECTOR=y -CONFIG_HARDLOCKUP_DETECTOR=y -# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -# CONFIG_WQ_WATCHDOG is not set CONFIG_PANIC_ON_OOPS=y -CONFIG_PANIC_ON_OOPS_VALUE=1 -CONFIG_PANIC_TIMEOUT=0 -CONFIG_SCHED_DEBUG=y -CONFIG_SCHED_INFO=y -CONFIG_SCHEDSTATS=y -# CONFIG_SCHED_STACK_END_CHECK is not set -# CONFIG_DEBUG_TIMEKEEPING is not set -CONFIG_TIMER_STATS=y -CONFIG_DEBUG_PREEMPT=y - -# -# Lock Debugging (spinlocks, mutexes, etc...) -# -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set -CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_HARDLOCKUP_DETECTOR=y CONFIG_PROVE_LOCKING=y -CONFIG_LOCKDEP=y CONFIG_LOCK_STAT=y CONFIG_DEBUG_LOCKDEP=y CONFIG_DEBUG_ATOMIC_SLEEP=y -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_LOCK_TORTURE_TEST is not set -CONFIG_TRACE_IRQFLAGS=y -CONFIG_STACKTRACE=y CONFIG_DEBUG_KOBJECT=y -# CONFIG_DEBUG_KOBJECT_RELEASE is not set -CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_LIST=y -CONFIG_DEBUG_PI_LIST=y -# CONFIG_DEBUG_SG is not set CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_DEBUG_CREDENTIALS is not set - -# -# RCU Debugging -# -CONFIG_PROVE_RCU=y -CONFIG_PROVE_RCU_REPEATEDLY=y -CONFIG_SPARSE_RCU_POINTER=y -# CONFIG_TORTURE_TEST is not set -# CONFIG_RCU_PERF_TEST is not set -# CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_TRACE is not set -# CONFIG_RCU_EQS_DEBUG is not set -# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_NOTIFIER_ERROR_INJECTION is not set -# CONFIG_FAULT_INJECTION is not set CONFIG_LATENCYTOP=y -CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_NOP_TRACER=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_HAVE_FENTRY=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACE_CLOCK=y -CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y -CONFIG_TRACING=y -CONFIG_GENERIC_TRACER=y -CONFIG_TRACING_SUPPORT=y -CONFIG_FTRACE=y CONFIG_FUNCTION_TRACER=y -CONFIG_FUNCTION_GRAPH_TRACER=y -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_PREEMPT_TRACER is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_HWLAT_TRACER is not set -# CONFIG_FTRACE_SYSCALLS is not set -# CONFIG_TRACER_SNAPSHOT is not set -CONFIG_BRANCH_PROFILE_NONE=y -# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set -# CONFIG_PROFILE_ALL_BRANCHES is not set -# CONFIG_STACK_TRACER is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_UPROBE_EVENT is not set -# CONFIG_PROBE_EVENTS is not set -CONFIG_DYNAMIC_FTRACE=y -CONFIG_DYNAMIC_FTRACE_WITH_REGS=y -# CONFIG_FUNCTION_PROFILER is not set -CONFIG_FTRACE_MCOUNT_RECORD=y -# CONFIG_FTRACE_STARTUP_TEST is not set -# CONFIG_MMIOTRACE is not set -# CONFIG_HIST_TRIGGERS is not set -# CONFIG_TRACEPOINT_BENCHMARK is not set -# CONFIG_RING_BUFFER_BENCHMARK is not set -# CONFIG_RING_BUFFER_STARTUP_TEST is not set -# CONFIG_TRACE_ENUM_MAP_FILE is not set - -# -# Runtime Testing -# -# CONFIG_LKDTM is not set -# CONFIG_TEST_LIST_SORT is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_RBTREE_TEST is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_TEST_HEXDUMP is not set -# CONFIG_TEST_STRING_HELPERS is not set -# CONFIG_TEST_KSTRTOX is not set -# CONFIG_TEST_PRINTF is not set -# CONFIG_TEST_BITMAP is not set -# CONFIG_TEST_UUID is not set -# CONFIG_TEST_RHASHTABLE is not set -# CONFIG_TEST_HASH is not set -# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_TEST_FIRMWARE is not set -# CONFIG_TEST_UDELAY is not set -# CONFIG_MEMTEST is not set -# CONFIG_BUG_ON_DATA_CORRUPTION is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y -# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set -# CONFIG_UBSAN is not set -CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y # CONFIG_STRICT_DEVMEM is not set # CONFIG_X86_VERBOSE_BOOTUP is not set -CONFIG_EARLY_PRINTK=y -# CONFIG_EARLY_PRINTK_DBGP is not set -# CONFIG_X86_PTDUMP_CORE is not set -# CONFIG_X86_PTDUMP is not set -CONFIG_DEBUG_RODATA_TEST=y -# CONFIG_DEBUG_WX is not set -CONFIG_DOUBLEFAULT=y -# CONFIG_DEBUG_TLBFLUSH is not set -# CONFIG_IOMMU_DEBUG is not set -# CONFIG_IOMMU_STRESS is not set -CONFIG_HAVE_MMIOTRACE_SUPPORT=y -CONFIG_IO_DELAY_TYPE_0X80=0 -CONFIG_IO_DELAY_TYPE_0XED=1 -CONFIG_IO_DELAY_TYPE_UDELAY=2 -CONFIG_IO_DELAY_TYPE_NONE=3 -CONFIG_IO_DELAY_0X80=y -# CONFIG_IO_DELAY_0XED is not set -# CONFIG_IO_DELAY_UDELAY is not set -# CONFIG_IO_DELAY_NONE is not set -CONFIG_DEFAULT_IO_DELAY_TYPE=0 -# CONFIG_DEBUG_BOOT_PARAMS is not set -# CONFIG_CPA_DEBUG is not set -# CONFIG_OPTIMIZE_INLINING is not set -# CONFIG_DEBUG_ENTRY is not set -# CONFIG_DEBUG_NMI_SELFTEST is not set -CONFIG_X86_DEBUG_FPU=y -# CONFIG_PUNIT_ATOM_DEBUG is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY_DMESG_RESTRICT is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITYFS is not set -CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y -CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y -# CONFIG_HARDENED_USERCOPY is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ALGAPI2=y -CONFIG_CRYPTO_AEAD=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_AKCIPHER2=y -CONFIG_CRYPTO_KPP2=y -CONFIG_CRYPTO_ACOMP2=y -# CONFIG_CRYPTO_RSA is not set -# CONFIG_CRYPTO_DH is not set -# CONFIG_CRYPTO_ECDH is not set -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -# CONFIG_CRYPTO_USER is not set -CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y -CONFIG_CRYPTO_GF128MUL=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_NULL2=y -# CONFIG_CRYPTO_PCRYPT is not set -CONFIG_CRYPTO_WORKQUEUE=y -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_MCRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set - -# -# Authenticated Encryption with Associated Data -# -CONFIG_CRYPTO_CCM=y -CONFIG_CRYPTO_GCM=y -# CONFIG_CRYPTO_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_SEQIV=y -CONFIG_CRYPTO_ECHAINIV=y - -# -# Block modes -# -# CONFIG_CRYPTO_CBC is not set -CONFIG_CRYPTO_CTR=y -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_KEYWRAP is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_CMAC is not set -CONFIG_CRYPTO_HMAC=y -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_VMAC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_CRC32C_INTEL is not set -# CONFIG_CRYPTO_CRC32 is not set -# CONFIG_CRYPTO_CRC32_PCLMUL is not set -CONFIG_CRYPTO_CRCT10DIF=y -CONFIG_CRYPTO_GHASH=y -# CONFIG_CRYPTO_POLY1305 is not set -# CONFIG_CRYPTO_POLY1305_X86_64 is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA1_SSSE3 is not set -# CONFIG_CRYPTO_SHA256_SSSE3 is not set -# CONFIG_CRYPTO_SHA512_SSSE3 is not set -# CONFIG_CRYPTO_SHA1_MB is not set -# CONFIG_CRYPTO_SHA256_MB is not set -# CONFIG_CRYPTO_SHA512_MB is not set -CONFIG_CRYPTO_SHA256=y -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_SHA3 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set - -# -# Ciphers -# -CONFIG_CRYPTO_AES=y -# CONFIG_CRYPTO_AES_X86_64 is not set -# CONFIG_CRYPTO_AES_NI_INTEL is not set -# CONFIG_CRYPTO_ANUBIS is not set -CONFIG_CRYPTO_ARC4=y -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_BLOWFISH_X86_64 is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAMELLIA_X86_64 is not set -# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set -# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_CAST6_AVX_X86_64 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_DES3_EDE_X86_64 is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SALSA20_X86_64 is not set -# CONFIG_CRYPTO_CHACHA20 is not set -# CONFIG_CRYPTO_CHACHA20_X86_64 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set -# CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set -# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_TWOFISH_X86_64 is not set -# CONFIG_CRYPTO_TWOFISH_X86_64_3WAY is not set -# CONFIG_CRYPTO_TWOFISH_AVX_X86_64 is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_LZO is not set -# CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set -# CONFIG_CRYPTO_LZ4HC is not set - -# -# Random Number Generation -# -# CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_DRBG_HMAC=y -# CONFIG_CRYPTO_DRBG_HASH is not set -# CONFIG_CRYPTO_DRBG_CTR is not set -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_JITTERENTROPY=y -# CONFIG_CRYPTO_USER_API_HASH is not set -# CONFIG_CRYPTO_USER_API_SKCIPHER is not set -# CONFIG_CRYPTO_USER_API_RNG is not set -# CONFIG_CRYPTO_USER_API_AEAD is not set -# CONFIG_CRYPTO_HW is not set - -# -# Certificates for signature checking -# -CONFIG_HAVE_KVM=y -# CONFIG_VIRTUALIZATION is not set -CONFIG_BINARY_PRINTF=y - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_HAVE_ARCH_BITREVERSE is not set -CONFIG_RATIONAL=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_NET_UTILS=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IO=y -CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_ARCH_HAS_FAST_MULTIPLIER=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC32_SELFTEST is not set -CONFIG_CRC32_SLICEBY8=y -# CONFIG_CRC32_SLICEBY4 is not set -# CONFIG_CRC32_SARWATE is not set -# CONFIG_CRC32_BIT is not set -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -# CONFIG_CRC8 is not set -# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set -# CONFIG_RANDOM32_SELFTEST is not set -# CONFIG_XZ_DEC is not set -# CONFIG_XZ_DEC_BCJ is not set -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAS_DMA=y -CONFIG_CPU_RMAP=y -CONFIG_DQL=y -CONFIG_GLOB=y -# CONFIG_GLOB_SELFTEST is not set -CONFIG_NLATTR=y -# CONFIG_CORDIC is not set -# CONFIG_DDR is not set -# CONFIG_IRQ_POLL is not set -CONFIG_FONT_SUPPORT=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_SG_SPLIT is not set -# CONFIG_SG_POOL is not set -CONFIG_ARCH_HAS_SG_CHAIN=y -CONFIG_ARCH_HAS_PMEM_API=y -CONFIG_ARCH_HAS_MMIO_FLUSH=y -CONFIG_SBITMAP=y From 34708b4893e409cb1559679c2a99e25d1bc41982 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 27 Mar 2020 15:51:45 -0700 Subject: [PATCH 0307/1105] tests: Include UML defconfig Include a defconfig for building kernel as UML. Also update the README with a few notes related to UML. Signed-off-by: Thomas Pedersen --- tests/hwsim/vm/README | 24 ++++-- tests/hwsim/vm/kernel-config.uml | 131 +++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 tests/hwsim/vm/kernel-config.uml diff --git a/tests/hwsim/vm/README b/tests/hwsim/vm/README index 4cea85b98..224d65a26 100644 --- a/tests/hwsim/vm/README +++ b/tests/hwsim/vm/README @@ -1,9 +1,23 @@ -These scripts allow you to run the hwsim tests inside a KVM virtual machine. +These scripts allow you to run the hwsim tests inside a KVM virtual machine or +as a UML (User Mode Linux) program. -To set it up, first compile a kernel with the kernel-config file as the -.config. You can adjust it as needed, the configuration is for a 64-bit -x86 system and should be close to minimal. The architecture must be the -same as your host since the host's filesystem is used. +To set it up, first compile a kernel with the kernel-config[.uml] file as the +.config. You can adjust it as needed, the configuration is for a 64-bit x86 +system and should be close to minimal. The architecture must be the same as +your host since the host's filesystem is used. + +To build the regular x86_64 kernel, simply issue + +yes "" | make -j + +or to build UML: + +yes "" | ARCH=um make -j + +Running a UML kernel is recommended as it can optimize out any sleep()s or +kernel timers by taking advantage of UML time travel mode, greatly increasing +test efficiency (~3200 tests can be run in under 5 minutes using parallel-vm.py +on a 24 core CPU). Install the required tools: at least 'kvm', if you want tracing trace-cmd, valgrind if you want, etc. diff --git a/tests/hwsim/vm/kernel-config.uml b/tests/hwsim/vm/kernel-config.uml new file mode 100644 index 000000000..b0f2f65ac --- /dev/null +++ b/tests/hwsim/vm/kernel-config.uml @@ -0,0 +1,131 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_PID_NS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SLAB=y +CONFIG_HOSTFS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MMAPPER=y +# CONFIG_SECCOMP is not set +CONFIG_UML_TIME_TRAVEL_SUPPORT=y +CONFIG_SSL=y +CONFIG_NULL_CHAN=y +CONFIG_PORT_CHAN=y +CONFIG_PTY_CHAN=y +CONFIG_TTY_CHAN=y +CONFIG_XTERM_CHAN=y +CONFIG_CON_CHAN="pts" +CONFIG_SSL_CHAN="pts" +CONFIG_UML_NET=y +CONFIG_UML_NET_TUNTAP=y +CONFIG_UML_NET_VECTOR=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_BINFMT_MISC=y +# CONFIG_COMPACTION is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=y +CONFIG_NF_TABLES=y +CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NF_TABLES_BRIDGE=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_T_FILTER=y +CONFIG_BRIDGE_EBT_ARP=y +CONFIG_BRIDGE_EBT_IP=y +CONFIG_BRIDGE_EBT_IP6=y +CONFIG_BRIDGE_EBT_PKTTYPE=y +CONFIG_BRIDGE_EBT_ARPREPLY=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_VLAN_8021Q=y +CONFIG_CFG80211=y +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=y +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_DEBUGFS=y +CONFIG_MAC80211_MESSAGE_TRACING=y +CONFIG_MAC80211_DEBUG_MENU=y +CONFIG_MAC80211_VERBOSE_DEBUG=y +CONFIG_MAC80211_MLME_DEBUG=y +CONFIG_MAC80211_STA_DEBUG=y +CONFIG_MAC80211_HT_DEBUG=y +CONFIG_MAC80211_OCB_DEBUG=y +CONFIG_MAC80211_IBSS_DEBUG=y +CONFIG_MAC80211_PS_DEBUG=y +CONFIG_MAC80211_TDLS_DEBUG=y +CONFIG_MAC80211_DEBUG_COUNTERS=y +CONFIG_RFKILL=y +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_BLK_DEV_UBD=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_DUMMY=y +CONFIG_MACSEC=y +CONFIG_VETH=y +# CONFIG_ETHERNET is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +CONFIG_MAC80211_HWSIM=y +CONFIG_LEGACY_PTY_COUNT=32 +# CONFIG_HW_RANDOM is not set +CONFIG_UML_RANDOM=y +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY_USER is not set +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y +CONFIG_LSM="yama,loadpin,safesetid,integrity" +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRC16=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1024 +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y +CONFIG_PREEMPTIRQ_EVENTS=y +# CONFIG_RUNTIME_TESTING_MENU is not set From 3f88d2ba0d30fa59e92b8a809db5e737dc01cebd Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Mon, 23 Mar 2020 19:42:27 +0100 Subject: [PATCH 0308/1105] AP: Drop not needed condition to delete PTK ID 1 Signed-off-by: Alexander Wetzel --- src/ap/wpa_auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index d04b5e765..e0ffb2718 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1741,7 +1741,7 @@ void wpa_remove_ptk(struct wpa_state_machine *sm) 0, KEY_FLAG_PAIRWISE)) wpa_printf(MSG_DEBUG, "RSN: PTK removal from the driver failed"); - if (sm->wpa_auth->conf.extended_key_id && sm->use_ext_key_id && + if (sm->use_ext_key_id && wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL, 0, KEY_FLAG_PAIRWISE)) wpa_printf(MSG_DEBUG, From af6a2b727c645bdbc5faf4c9c8f52ccc134fa38c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Mar 2020 21:09:56 +0300 Subject: [PATCH 0309/1105] tests: Use complete CHAN_SWITCH parameters in ap_vht_csa_vht40_disable Specify the secondary channel offset and correct center_freq1 value to make the parameters complete for a 40 MHz channel. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_vht.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 523c9c04b..4e8540cf0 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -892,7 +892,7 @@ def test_ap_vht_csa_vht40_disable(dev, apdev): dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745") hwsim_utils.test_connectivity(dev[0], hapd) - hapd.request("CHAN_SWITCH 5 5200 center_freq1=5200 bandwidth=40 ht") + hapd.request("CHAN_SWITCH 5 5200 center_freq1=5210 sec_channel_offset=1 bandwidth=40 ht") ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) if ev is None: raise Exception("CSA finished event timed out") From 30b6d4bb7d0f89e80de38d3cc1827a638f3ee358 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 28 Jan 2020 15:09:49 +0000 Subject: [PATCH 0310/1105] hostapd: Basic channel check for CHAN_SWITCH parameters Implement channel sanity check for the CHAN_SWITCH command. Verify provided values for bandwidth, frequencies, and secondary channel offset. Reject requested channel switch operation if basic constraints on frequencies and bandwidth are not fulfilled. Signed-off-by: Sergey Matyukevich --- hostapd/ctrl_iface.c | 97 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index aaf00c2db..f35f87edc 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2432,6 +2432,96 @@ static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd, #endif /* CONFIG_TESTING_OPTIONS */ +static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) +{ + switch (params->bandwidth) { + case 0: + /* bandwidth not specified: use 20 MHz by default */ + /* fall-through */ + case 20: + if (params->center_freq1 && + params->center_freq1 != params->freq) + return -1; + + if (params->center_freq2 || params->sec_channel_offset) + return -1; + break; + case 40: + if (params->center_freq2 || !params->sec_channel_offset) + return -1; + + if (!params->center_freq1) + break; + switch (params->sec_channel_offset) { + case 1: + if (params->freq + 10 != params->center_freq1) + return -1; + break; + case -1: + if (params->freq - 10 != params->center_freq1) + return -1; + break; + default: + return -1; + } + break; + case 80: + if (!params->center_freq1 || !params->sec_channel_offset) + return 1; + + switch (params->sec_channel_offset) { + case 1: + if (params->freq - 10 != params->center_freq1 && + params->freq + 30 != params->center_freq1) + return 1; + break; + case -1: + if (params->freq + 10 != params->center_freq1 && + params->freq - 30 != params->center_freq1) + return -1; + break; + default: + return -1; + } + + /* Adjacent and overlapped are not allowed for 80+80 */ + if (params->center_freq2 && + params->center_freq1 - params->center_freq2 <= 80 && + params->center_freq2 - params->center_freq1 <= 80) + return 1; + break; + case 160: + if (!params->center_freq1 || params->center_freq2 || + !params->sec_channel_offset) + return -1; + + switch (params->sec_channel_offset) { + case 1: + if (params->freq + 70 != params->center_freq1 && + params->freq + 30 != params->center_freq1 && + params->freq - 10 != params->center_freq1 && + params->freq - 50 != params->center_freq1) + return -1; + break; + case -1: + if (params->freq + 50 != params->center_freq1 && + params->freq + 10 != params->center_freq1 && + params->freq - 30 != params->center_freq1 && + params->freq - 70 != params->center_freq1) + return -1; + break; + default: + return -1; + } + break; + default: + return -1; + } + + return 0; +} + + static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, char *pos) { @@ -2444,6 +2534,13 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, if (ret) return ret; + ret = hostapd_ctrl_check_freq_params(&settings.freq_params); + if (ret) { + wpa_printf(MSG_INFO, + "chanswitch: invalid frequency settings provided"); + return ret; + } + for (i = 0; i < iface->num_bss; i++) { /* Save CHAN_SWITCH VHT config */ From 7988767393337befb39eeedcff1f327e3b219c19 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 28 Jan 2020 15:09:51 +0000 Subject: [PATCH 0311/1105] DFS: Rename and export hostapd_config_dfs_chan_available helper Rename DFS helper hostapd_config_dfs_chan_available() to hostapd_is_dfs_chan_available(). Enable access to this helper function from other hostapd components. Signed-off-by: Sergey Matyukevich --- src/ap/dfs.c | 4 ++-- src/ap/dfs.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 6fc806d7b..2e350ff08 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -856,7 +856,7 @@ int hostapd_handle_dfs(struct hostapd_iface *iface) } -static int hostapd_config_dfs_chan_available(struct hostapd_iface *iface) +int hostapd_is_dfs_chan_available(struct hostapd_iface *iface) { int n_chans, n_chans1, start_chan_idx, start_chan_idx1; @@ -904,7 +904,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, * another radio. */ if (iface->state != HAPD_IFACE_ENABLED && - hostapd_config_dfs_chan_available(iface)) { + hostapd_is_dfs_chan_available(iface)) { hostapd_setup_interface_complete(iface, 0); iface->cac_started = 0; } diff --git a/src/ap/dfs.h b/src/ap/dfs.h index f0fa6f688..b73c4ece1 100644 --- a/src/ap/dfs.h +++ b/src/ap/dfs.h @@ -25,6 +25,7 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, int cf1, int cf2); int hostapd_is_dfs_required(struct hostapd_iface *iface); +int hostapd_is_dfs_chan_available(struct hostapd_iface *iface); int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, int cf1, int cf2); From 683e7c75594d716e53ff40e265419fddea5d319e Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 28 Jan 2020 15:09:52 +0000 Subject: [PATCH 0312/1105] DFS: Add new hostapd_is_dfs_overlap() helper Add a new hostapd_is_dfs_overlap() helper function to DFS module. This function tells whether the selected frequency range overlaps with DFS channels in the current hostapd configuration. Selected frequency reange is specified by its center frequency and bandwidth. Signed-off-by: Sergey Matyukevich --- src/ap/dfs.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ap/dfs.h | 2 ++ 2 files changed, 55 insertions(+) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 2e350ff08..3c078b9cb 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -1290,3 +1290,56 @@ int hostapd_handle_dfs_offload(struct hostapd_iface *iface) __func__, iface->freq); return 2; } + + +int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, + int center_freq) +{ + struct hostapd_channel_data *chan; + struct hostapd_hw_modes *mode = iface->current_mode; + int half_width; + int res = 0; + int i; + + if (!iface->conf->ieee80211h || !mode || + mode->mode != HOSTAPD_MODE_IEEE80211A) + return 0; + + switch (width) { + case CHAN_WIDTH_20_NOHT: + case CHAN_WIDTH_20: + half_width = 10; + break; + case CHAN_WIDTH_40: + half_width = 20; + break; + case CHAN_WIDTH_80: + case CHAN_WIDTH_80P80: + half_width = 40; + break; + case CHAN_WIDTH_160: + half_width = 80; + break; + default: + wpa_printf(MSG_WARNING, "DFS chanwidth %d not supported", + width); + return 0; + } + + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; + + if (!(chan->flag & HOSTAPD_CHAN_RADAR)) + continue; + + if (center_freq - chan->freq < half_width && + chan->freq - center_freq < half_width) + res++; + } + + wpa_printf(MSG_DEBUG, "DFS: (%d, %d): in range: %s", + center_freq - half_width, center_freq + half_width, + res ? "yes" : "no"); + + return res; +} diff --git a/src/ap/dfs.h b/src/ap/dfs.h index b73c4ece1..606c1b393 100644 --- a/src/ap/dfs.h +++ b/src/ap/dfs.h @@ -30,5 +30,7 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, int cf1, int cf2); int hostapd_handle_dfs_offload(struct hostapd_iface *iface); +int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, + int center_freq); #endif /* DFS_H */ From c60717f839649c522757e01541f3d4b749658299 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 28 Jan 2020 15:09:53 +0000 Subject: [PATCH 0313/1105] hostapd: Add support for DFS channels in CHAN_SWITCH Enable support for DFS channels in the CHAN_SWITCH command. Perform CAC instead of CSA if DFS channel is selected. Then restart normal AP operations. Note that the current implementation provides a simplified approach. It does not check if the selected DFS channel block is already in the HOSTAPD_CHAN_DFS_AVAILABLE state. CAC procedure is restarted anyway. Signed-off-by: Sergey Matyukevich --- hostapd/ctrl_iface.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index f35f87edc..d90b5dc8f 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -59,6 +59,7 @@ #include "ap/neighbor_db.h" #include "ap/rrm.h" #include "ap/dpp_hostapd.h" +#include "ap/dfs.h" #include "wps/wps_defs.h" #include "wps/wps.h" #include "fst/fst_ctrl_iface.h" @@ -2528,7 +2529,10 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, #ifdef NEED_AP_MLME struct csa_settings settings; int ret; + int dfs_range = 0; unsigned int i; + int bandwidth; + u8 chan; ret = hostapd_parse_csa_settings(pos, &settings); if (ret) @@ -2541,6 +2545,61 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, return ret; } + switch (settings.freq_params.bandwidth) { + case 40: + bandwidth = CHAN_WIDTH_40; + break; + case 80: + if (settings.freq_params.center_freq2) + bandwidth = CHAN_WIDTH_80P80; + else + bandwidth = CHAN_WIDTH_80; + break; + case 160: + bandwidth = CHAN_WIDTH_160; + break; + default: + bandwidth = CHAN_WIDTH_20; + break; + } + + if (settings.freq_params.center_freq1) + dfs_range += hostapd_is_dfs_overlap( + iface, bandwidth, settings.freq_params.center_freq1); + else + dfs_range += hostapd_is_dfs_overlap( + iface, bandwidth, settings.freq_params.freq); + + if (settings.freq_params.center_freq2) + dfs_range += hostapd_is_dfs_overlap( + iface, bandwidth, settings.freq_params.center_freq2); + + if (dfs_range) { + ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan); + if (ret == NUM_HOSTAPD_MODES) { + wpa_printf(MSG_ERROR, + "Failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)", + settings.freq_params.freq, + settings.freq_params.sec_channel_offset, + settings.freq_params.bandwidth); + return -1; + } + + settings.freq_params.channel = chan; + + wpa_printf(MSG_DEBUG, + "DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)", + settings.freq_params.channel, + settings.freq_params.freq, + settings.freq_params.sec_channel_offset, + settings.freq_params.bandwidth, + settings.freq_params.center_freq1); + + /* Perform CAC and switch channel */ + hostapd_switch_channel_fallback(iface, &settings.freq_params); + return 0; + } + for (i = 0; i < iface->num_bss; i++) { /* Save CHAN_SWITCH VHT config */ From 91498a12253bc1fc17ee5af544882106ccfa1759 Mon Sep 17 00:00:00 2001 From: Sergey Matyukevich Date: Tue, 28 Jan 2020 15:09:54 +0000 Subject: [PATCH 0314/1105] hostapd: DFS for channel switch in repeater mode In repeater mode remote AP may request channel switch to a new channel. Check if DFS is required for the new channel before proceeding with normal AP operations. Start CAC procedure if radar detection is required and channel is not yet marked as available. Signed-off-by: Sergey Matyukevich --- src/ap/drv_callbacks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 64cbd84d8..559bb87c2 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -945,6 +945,12 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d dfs=%d", freq, is_dfs); + } else if (is_dfs && + hostapd_is_dfs_required(hapd->iface) && + !hostapd_is_dfs_chan_available(hapd->iface) && + !hapd->iface->cac_started) { + hostapd_disable_iface(hapd->iface); + hostapd_enable_iface(hapd->iface); } for (i = 0; i < hapd->iface->num_bss; i++) From 4e9cfc3eb80291a1eecd9a659979882a9f293f72 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Mar 2020 20:49:27 +0300 Subject: [PATCH 0315/1105] tests: DFS channel switch Signed-off-by: Jouni Malinen --- tests/hwsim/test_dfs.py | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/hwsim/test_dfs.py b/tests/hwsim/test_dfs.py index 2b7fc4a85..8851de9d9 100644 --- a/tests/hwsim/test_dfs.py +++ b/tests/hwsim/test_dfs.py @@ -608,3 +608,52 @@ def test_dfs_radar_vht80_downgrade(dev, apdev, params): raise Exception("Unexpected SIGNAL_POLL value: " + str(sig)) finally: clear_regdom(hapd, dev) + +def test_dfs_chan_switch(dev, apdev, params): + """DFS channel switch [long]""" + if not params['long']: + raise HwsimSkip("Skip test case with long duration due to --long not specified") + try: + hapd = None + hapd = start_dfs_ap(apdev[0], country="US") + + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5260" not in ev: + raise Exception("Unexpected DFS freq result") + ev = hapd.wait_event(["AP-ENABLED"], timeout=5) + if not ev: + raise Exception("AP setup timed out") + freq = hapd.get_status_field("freq") + if freq != "5260": + raise Exception("Unexpected frequency") + + dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5260 5280") + dev[0].wait_regdom(country_ie=True) + hwsim_utils.test_connectivity(dev[0], hapd) + + if "OK" not in hapd.request("CHAN_SWITCH 5 5280 ht"): + raise Exception("CHAN_SWITCH failed") + # This results in BSS going down before restart, so the STA is expected + # to report disconnection. + dev[0].wait_disconnected() + ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) + if "freq=5280" not in ev: + raise Exception("Unexpected channel: " + ev) + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5280" not in ev: + raise Exception("Unexpected DFS freq result") + ev = hapd.wait_event(["AP-ENABLED"], timeout=5) + if not ev: + raise Exception("AP setup timed out") + freq = hapd.get_status_field("freq") + if freq != "5280": + raise Exception("Unexpected frequency") + + dev[0].wait_connected(timeout=30) + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + clear_regdom(hapd, dev) From 66e20bb1a70577ae5918060affa358afacb39a23 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Mar 2020 23:07:42 +0300 Subject: [PATCH 0316/1105] Fix the dpp_configurator_sign example command The mandatory ssid parameter was forgotten from this command when it was added to the dpp_auth_init examples. Signed-off-by: Jouni Malinen --- wpa_supplicant/README-DPP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/README-DPP b/wpa_supplicant/README-DPP index 457e32eef..b59d8bf49 100644 --- a/wpa_supplicant/README-DPP +++ b/wpa_supplicant/README-DPP @@ -156,7 +156,7 @@ command to get DPP credentials. > dpp_configurator_add (returns configurator id) -> dpp_configurator_sign conf= configurator= +> dpp_configurator_sign conf= configurator= ssid= Sample AP configuration files after provisioning From d4f5d1f0c748130ee095621aa5e53d317a2377e7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 29 Mar 2020 23:24:45 +0300 Subject: [PATCH 0317/1105] DPP: Add some more details on how to use DPP Signed-off-by: Jouni Malinen --- wpa_supplicant/README-DPP | 63 ++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/wpa_supplicant/README-DPP b/wpa_supplicant/README-DPP index b59d8bf49..d378245cd 100644 --- a/wpa_supplicant/README-DPP +++ b/wpa_supplicant/README-DPP @@ -9,40 +9,44 @@ Connector mechanism. Introduction to DPP ------------------- -Device provisioning Protocol allows enrolling of interface-less devices -in a secure Wi-Fi network using many methods like QR code based -authentication( detailed below ), PKEX based authentication etc. In DPP -a Configurator is used to provide network credentials to the devices. -The three phases of DPP connection are authentication, configuration and +Device Provisioning Protocol (also known as Wi-Fi Easy Connect) allows +enrolling of interface-less devices in a secure Wi-Fi network using many +methods like QR code based authentication (detailed below), PKEX based +authentication (password with in-band provisioning), etc. In DPP a +Configurator is used to provide network credentials to the devices. The +three phases of DPP connection are authentication, configuration and network introduction. +More information about Wi-Fi Easy Connect is available from this Wi-Fi +Alliance web page: +https://www.wi-fi.org/discover-wi-fi/wi-fi-easy-connect + Build config setup ------------------ -The following changes must go in the config file used to compile hostapd -and wpa_supplicant. +The following parameters must be included in the config file used to +compile hostapd and wpa_supplicant. wpa_supplicant build config --------------------------- -Enable DPP and protected management frame in wpa_supplicant build config -file +Enable DPP in wpa_supplicant build config file CONFIG_DPP=y hostapd build config -------------------- -Enable DPP and protected management frame in hostapd build config file +Enable DPP in hostapd build config file CONFIG_DPP=y Configurator build config ------------------------- -Any STA or AP device can act as a Configurator. Enable DPP and protected -managment frames in build config. For an AP to act as Configurator, -Interworking needs to be enabled. For wpa_supplicant it is not required. +Any STA or AP device can act as a Configurator. Enable DPP in build +config. For an AP to act as a Configurator, Interworking needs to be +enabled for GAS. For wpa_supplicant it is not required. CONFIG_INTERWORKING=y @@ -90,41 +94,46 @@ To get key of Configurator > dpp_configurator_get_key -How to configure an enrollee using Configurator +How to configure an Enrollee using Configurator ----------------------------------------------- -On enrollee side: +On Enrollee side: -Generate QR code for the device. Store the qr code id returned by the +Generate QR code for the device. Store the QR code id returned by the command. -> dpp_bootstrap_gen type=qrcode mac= chan= key= -(returns bootstrapping info id) +> dpp_bootstrap_gen type=qrcode mac= chan= key= +(Returns bootstrapping info id. If the key parameter is not included, a new key +is generated automatically. The MAC address is specified without octet +separating colons. The channel list includes the possible channels on which the +device is waiting. This uses global operating classes; e.g., 81/1 is the 2.4 +GHz channel 1 on 2412 MHz.) -Get QR Code of device using the bootstrap info id. +Get URI for the QR Code of device using the bootstrap info id. > dpp_bootstrap_get_uri -Make device listen to DPP request (The central frequency of channel 1 is -2412) in case if enrollee is a client device. +Make device listen to DPP request. The central frequency of the 2.4 GHz +band channel 1 is 2412 MHz) in case the Enrollee is a client device. An +AP as an Enrollee is listening on its operating channel. > dpp_listen On Configurator side: Enter the QR Code in the Configurator. -> dpp_qr_code "" +> dpp_qr_code "" On successfully adding QR Code, a bootstrapping info id is returned. -Send provisioning request to enrollee. (conf is ap-dpp if enrollee is an -AP. conf is sta-dpp if enrollee is a client) +Send provisioning request to Enrollee. (conf is ap-dpp if Enrollee is an +AP. conf is sta-dpp if Enrollee is a client) > dpp_auth_init peer= conf= ssid= configurator= or for legacy (PSK/SAE) provisioning for a station Enrollee: > dpp_auth_init peer= conf=sta-psk ssid= pass= -The DPP values will be printed in the console. Save this values into the -config file. If the enrollee is an AP, we need to manually write these -values to the hostapd config file. If the enrollee is a client device, +The DPP values will be printed in the console. Save these values into the +config file. If the Enrollee is an AP, we need to manually write these +values to the hostapd config file. If the Enrollee is a client device, these details can be automatically saved to config file using the following command. From e149051ced781ef7b29ae47e98c6d06e4e666f68 Mon Sep 17 00:00:00 2001 From: Sriram R Date: Thu, 26 Mar 2020 08:42:19 +0530 Subject: [PATCH 0318/1105] hostapd: Validate the country_code parameter value cfg80211/regulatory supports only ISO 3166-1 alpha2 country code and that's what this parameter is supposed to use, so validate the country code input before accepting the value. Only characters A..Z are accepted. Signed-off-by: Sriram R --- hostapd/config_file.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 425446c24..1d8c03973 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2463,6 +2463,13 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) { bss->skip_inactivity_poll = atoi(pos); } else if (os_strcmp(buf, "country_code") == 0) { + if (pos[0] < 'A' || pos[0] > 'Z' || + pos[1] < 'A' || pos[1] > 'Z') { + wpa_printf(MSG_ERROR, + "Line %d: Invalid country_code '%s'", + line, pos); + return 1; + } os_memcpy(conf->country, pos, 2); } else if (os_strcmp(buf, "country3") == 0) { conf->country[2] = strtol(pos, NULL, 16); From 7c8f540ee0a8b95026bf2683ca9a3f44d39d0c40 Mon Sep 17 00:00:00 2001 From: P Praneesh Date: Mon, 9 Mar 2020 16:23:50 +0530 Subject: [PATCH 0319/1105] wpa_supplicant: Add HE override support Add HE override support under the build parameter CONFIG_HE_OVERRIDES=y. The disable_he=1 network profile parameter can be used to disable HE. This requires a fallback to VHT on the 5 GHz band and to HT on the 2.4 GHz band. There is no nl80211 support for configuring the driver to disable HE, so for now, this applies only to IBSS and mesh cases. Signed-off-by: P Praneesh --- src/drivers/driver.h | 7 +++++++ wpa_supplicant/Android.mk | 4 ++++ wpa_supplicant/Makefile | 4 ++++ wpa_supplicant/config.c | 3 +++ wpa_supplicant/config_file.c | 3 +++ wpa_supplicant/config_ssid.h | 10 ++++++++++ wpa_supplicant/sme.c | 3 +++ wpa_supplicant/wpa_cli.c | 3 +++ wpa_supplicant/wpa_supplicant.c | 26 ++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ 10 files changed, 66 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index bc4f0ef95..6ffa7fece 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1096,6 +1096,13 @@ struct wpa_driver_associate_params { const struct ieee80211_vht_capabilities *vhtcaps_mask; #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + /** + * disable_he - Disable HE for this connection + */ + int disable_he; +#endif /* CONFIG_HE_OVERRIDES */ + /** * req_key_mgmt_offload - Request key management offload for connection * diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index c348766ca..fbbb06191 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -166,6 +166,10 @@ ifdef CONFIG_VHT_OVERRIDES L_CFLAGS += -DCONFIG_VHT_OVERRIDES endif +ifdef CONFIG_HE_OVERRIDES +L_CFLAGS += -DCONFIG_HE_OVERRIDES +endif + ifndef CONFIG_BACKEND CONFIG_BACKEND=file endif diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 88f688b62..0d9950d78 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -198,6 +198,10 @@ ifdef CONFIG_VHT_OVERRIDES CFLAGS += -DCONFIG_VHT_OVERRIDES endif +ifdef CONFIG_HE_OVERRIDES +CFLAGS += -DCONFIG_HE_OVERRIDES +endif + ifndef CONFIG_BACKEND CONFIG_BACKEND=file endif diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 563d18fb8..49b25f124 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2544,6 +2544,9 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(vht_tx_mcs_nss_7, -1, 3) }, { INT_RANGE(vht_tx_mcs_nss_8, -1, 3) }, #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + { INT_RANGE(disable_he, 0, 1)}, +#endif /* CONFIG_HE_OVERRIDES */ { INT(ap_max_inactivity) }, { INT(dtim_period) }, { INT(beacon_int) }, diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 074b3b31a..a69c4cc6d 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -971,6 +971,9 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT_DEF(vht_tx_mcs_nss_7, -1); INT_DEF(vht_tx_mcs_nss_8, -1); #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + INT(disable_he); +#endif /* CONFIG_HE_OVERRIDES */ #undef STR #undef INT diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index c214b6c3f..979f868e3 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -779,6 +779,16 @@ struct wpa_ssid { vht_tx_mcs_nss_7, vht_tx_mcs_nss_8; #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + /** + * disable_he - Disable HE (IEEE 802.11ax) for this network + * + * By default, use it if it is available, but this can be configured + * to 1 to have it disabled. + */ + int disable_he; +#endif /* CONFIG_HE_OVERRIDES */ + /** * ap_max_inactivity - Timeout in seconds to detect STA's inactivity * diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index a35310157..0cc81bf0c 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1869,6 +1869,9 @@ pfs_fail: params.vhtcaps_mask = &vhtcaps_mask; wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + wpa_supplicant_apply_he_overrides(wpa_s, wpa_s->current_ssid, ¶ms); +#endif /* CONFIG_HE_OVERRIDES */ #ifdef CONFIG_IEEE80211R if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies && get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 730d749fe..07d5f315c 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1460,6 +1460,9 @@ static const char *network_fields[] = { "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5", "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8", #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + "disable_he", +#endif /* CONFIG_HE_OVERRIDES */ "ap_max_inactivity", "dtim_period", "beacon_int", #ifdef CONFIG_MACSEC "macsec_policy", diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 8016fd3ac..2cacb202d 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2406,6 +2406,10 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */ if (is_24ghz) freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; +#ifdef CONFIG_HE_OVERRIDES + if (is_24ghz && ssid->disable_he) + freq->he_enabled = 0; +#endif /* CONFIG_HE_OVERRIDES */ /* Setup higher BW only for 5 GHz */ if (mode->mode != HOSTAPD_MODE_IEEE80211A) @@ -2604,6 +2608,12 @@ skip_ht40: #endif /* CONFIG_HT_OVERRIDES */ } +#ifdef CONFIG_HE_OVERRIDES + if (ssid->disable_he) { + vht_freq.he_enabled = 0; + freq->he_enabled = 0; + } +#endif /* CONFIG_HE_OVERRIDES */ if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, freq->channel, ssid->enable_edmg, ssid->edmg_channel, freq->ht_enabled, @@ -3710,6 +3720,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.vhtcaps_mask = &vhtcaps_mask; wpa_supplicant_apply_vht_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + wpa_supplicant_apply_he_overrides(wpa_s, ssid, ¶ms); +#endif /* CONFIG_HE_OVERRIDES */ #ifdef CONFIG_P2P /* @@ -5272,6 +5285,19 @@ void wpa_supplicant_apply_vht_overrides( #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES +void wpa_supplicant_apply_he_overrides( + struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params) +{ + if (!ssid) + return; + + params->disable_he = ssid->disable_he; +} +#endif /* CONFIG_HE_OVERRIDES */ + + static int pcsc_reader_init(struct wpa_supplicant *wpa_s) { #ifdef PCSC_FUNCS diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index b7cf7f4df..e0de59fa2 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1311,6 +1311,9 @@ void wpa_supplicant_apply_ht_overrides( void wpa_supplicant_apply_vht_overrides( struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_driver_associate_params *params); +void wpa_supplicant_apply_he_overrides( + struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params); int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, From 0e794989e56959e37039cedb23b1e100fe2bca1f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2020 16:07:25 +0300 Subject: [PATCH 0320/1105] Beacon frame protection event for incorrect protection Define a driver interface event for Beacon frame protection failures. Report such events over the control interface and send a WNM-Notification Request frame to the AP as well. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_defs.h | 7 +++++++ src/common/wpa_ctrl.h | 2 ++ src/drivers/driver.h | 16 ++++++++++++++++ src/drivers/driver_common.c | 1 + wpa_supplicant/events.c | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 8dc469881..7f31e09a1 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1881,6 +1881,13 @@ enum wnm_sleep_mode_subelement_id { WNM_SLEEP_SUBELEM_BIGTK = 2, }; +/* WNM notification type (IEEE P802.11-REVmd/D3.0, Table 9-430) */ +enum wnm_notification_Type { + WNM_NOTIF_TYPE_FIRMWARE_UPDATE = 0, + WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE = 2, + WNM_NOTIF_TYPE_VENDOR_SPECIFIC = 221, +}; + /* Channel Switch modes (802.11h) */ #define CHAN_SWITCH_MODE_ALLOW_TX 0 #define CHAN_SWITCH_MODE_BLOCK_TX 1 diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 0b0413068..ca1c35f85 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -95,6 +95,8 @@ extern "C" { /** SAE authentication failed due to unknown password identifier */ #define WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER \ "CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER " +/** Unprotected Beacon frame dropped */ +#define WPA_EVENT_UNPROT_BEACON "CTRL-EVENT-UNPROT-BEACON " /** IP subnet status change notification * diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 6ffa7fece..032bbd892 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4970,6 +4970,15 @@ enum wpa_event_type { * EVENT_UPDATE_DH - Notification of updated DH information */ EVENT_UPDATE_DH, + + /** + * EVENT_UNPROT_BEACON - Unprotected Beacon frame received + * + * This event should be called when a Beacon frame is dropped due to it + * not being protected correctly. union wpa_event_data::unprot_beacon + * is required to provide more details of the frame. + */ + EVENT_UNPROT_BEACON, }; @@ -5822,6 +5831,13 @@ union wpa_event_data { const u8 *ie; size_t ie_len; } update_dh; + + /** + * struct unprot_beacon - Data for EVENT_UNPROT_BEACON + */ + struct unprot_beacon { + const u8 *sa; + } unprot_beacon; }; /** diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 2e03b6676..63846db2e 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -89,6 +89,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(INTERFACE_MAC_CHANGED); E2S(WDS_STA_INTERFACE_STATUS); E2S(UPDATE_DH); + E2S(UNPROT_BEACON); } return "UNKNOWN"; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e8b8a9c98..19a883bee 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4467,6 +4467,38 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, } +static void wpas_event_unprot_beacon(struct wpa_supplicant *wpa_s, + struct unprot_beacon *data) +{ + struct wpabuf *buf; + int res; + + if (!data || wpa_s->wpa_state != WPA_COMPLETED || + os_memcmp(data->sa, wpa_s->bssid, ETH_ALEN) != 0) + return; + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_UNPROT_BEACON MACSTR, + MAC2STR(data->sa)); + + buf = wpabuf_alloc(4); + if (!buf) + return; + + wpabuf_put_u8(buf, WLAN_ACTION_WNM); + wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); + wpabuf_put_u8(buf, 1); /* Dialog Token */ + wpabuf_put_u8(buf, WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE); + + res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0); + if (res < 0) + wpa_printf(MSG_DEBUG, + "Failed to send WNM-Notification Request frame"); + + wpabuf_free(buf); +} + + void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { @@ -5271,6 +5303,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->sta_opmode.rx_nss); #endif /* CONFIG_AP */ break; + case EVENT_UNPROT_BEACON: + wpas_event_unprot_beacon(wpa_s, &data->unprot_beacon); + break; default: wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event); break; From a371164f888a63d8dbce3fab5f78c381fd7d179c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2020 16:29:24 +0300 Subject: [PATCH 0321/1105] Process received WNM Notification Request for beacon protection failures Report received notifications for beacon protection failures in syslog and control interface. Signed-off-by: Jouni Malinen --- src/ap/wnm_ap.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 891f90f29..67281b38d 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -522,6 +522,30 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, } +static void wnm_beacon_protection_failure(struct hostapd_data *hapd, + const u8 *addr) +{ + struct sta_info *sta; + + if (!hapd->conf->beacon_prot) + return; + + sta = ap_get_sta(hapd, addr); + if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) { + wpa_printf(MSG_DEBUG, "Station " MACSTR + " not found for received WNM-Notification Request", + MAC2STR(addr)); + return; + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Beacon protection failure reported"); + wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_UNPROT_BEACON "reporter=" + MACSTR, MAC2STR(addr)); +} + + static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd, const u8 *addr, const u8 *buf, size_t len) @@ -540,8 +564,14 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd, MAC2STR(addr), dialog_token, type); wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements", buf, len); - if (type == WLAN_EID_VENDOR_SPECIFIC) + switch (type) { + case WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE: + wnm_beacon_protection_failure(hapd, addr); + break; + case WNM_NOTIF_TYPE_VENDOR_SPECIFIC: mbo_ap_wnm_notification_req(hapd, addr, buf, len); + break; + } } From 1dcfbab254a4f165de98223e7a0aff5b04ecbd7e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2020 17:16:55 +0300 Subject: [PATCH 0322/1105] DPP2: Clear requirement for QR Code mutual authentication for chirping The chirping cases are not really targeting interactive operations, so clear the requirement for mutual authentication when DPP_CHIRP command is used. This avoids testing isues where an earlier DPP_LISTEN command has used qr=mutual parameter and that seting not getting cleared before the next DPP_CHIRP command is used. This fixes a test case failure in the following test sequence: dpp_auth_resp_status_failure dpp_controller_relay_chirp Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 45fd3a744..e578e0aef 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3020,6 +3020,7 @@ int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd) wpas_dpp_chirp_stop(wpa_s); wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; + wpa_s->dpp_qr_mutual = 0; wpa_s->dpp_chirp_bi = bi; wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi); if (!wpa_s->dpp_presence_announcement) From 0dc58cfa956c0bcfd16021d3ad5144c6b6c29aaa Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2020 18:30:33 +0300 Subject: [PATCH 0323/1105] wlantest: Do not report decryption keys when checking only zero TK All the "Failed to decrypt frame" debug prints were confusing since those were not supposed to be shown unless there were one or more real TKs available. The recently added check for zero TK added these notes for that case which is not really correct, so get rid of them. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index 91c0144f8..58c986d83 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -325,7 +325,7 @@ skip_replay_det: write_pcap_decrypted(wt, (const u8 *) hdr, hdrlen, decrypted, dlen); } else - add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); + add_note(wt, MSG_DEBUG, "Failed to decrypt frame (group)"); os_free(decrypted); } @@ -348,6 +348,7 @@ static void rx_data_bss_prot(struct wlantest *wt, int ptk_iter_done = 0; int try_ptk_iter = 0; int replay = 0; + int only_zero_tk = 0; if (hdr->addr1[0] & 0x01) { rx_data_bss_prot_group(wt, hdr, hdrlen, qos, dst, src, @@ -427,6 +428,7 @@ static void rx_data_bss_prot(struct wlantest *wt, if (dl_list_empty(&wt->ptk)) { if (len >= 4 && sta) { keyid = data[3] >> 6; + only_zero_tk = 1; goto check_zero_tk; } return; @@ -619,7 +621,7 @@ check_zero_tk: write_pcap_decrypted(wt, (const u8 *) hdr, hdrlen, decrypted, dlen); } else { - if (!try_ptk_iter) + if (!try_ptk_iter && !only_zero_tk) add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); /* Assume the frame was corrupted and there was no FCS to check. From 08ac6f807d09faa965d6f5fdaab783197ac3e85d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2020 18:46:14 +0300 Subject: [PATCH 0324/1105] wlantest: Update PTK after rekeying even if EAPOL-Key msg 4/4 is missing Update TPTK to PTK if a valid EAPOL-Key msg 2/4 and 3/4 are available, but 4/4 is missing. This avoids certain cases where the new TK could be derived, but it was not being used to try to decrypt following encrypted frames. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 51 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index 58c986d83..fa8df77be 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -330,6 +330,26 @@ skip_replay_det: } +static u8 * try_ptk_decrypt(struct wlantest *wt, struct wlantest_sta *sta, + const struct ieee80211_hdr *hdr, int keyid, + const u8 *data, size_t len, + const u8 *tk, size_t tk_len, size_t *dlen) +{ + u8 *decrypted = NULL; + + if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) + decrypted = ccmp_256_decrypt(tk, hdr, data, len, dlen); + else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || + sta->pairwise_cipher == WPA_CIPHER_GCMP_256) + decrypted = gcmp_decrypt(tk, tk_len, hdr, data, len, dlen); + else + decrypted = ccmp_decrypt(tk, hdr, data, len, dlen); + write_decrypted_note(wt, decrypted, tk, tk_len, keyid); + + return decrypted; +} + + static void rx_data_bss_prot(struct wlantest *wt, const struct ieee80211_hdr *hdr, size_t hdrlen, const u8 *qos, const u8 *dst, const u8 *src, @@ -562,18 +582,9 @@ skip_replay_det: } else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) { decrypted = wep_decrypt(wt, hdr, data, len, &dlen); } else if (sta->ptk_set) { - if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) - decrypted = ccmp_256_decrypt(sta->ptk.tk, hdr, data, - len, &dlen); - else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || - sta->pairwise_cipher == WPA_CIPHER_GCMP_256) - decrypted = gcmp_decrypt(sta->ptk.tk, sta->ptk.tk_len, - hdr, data, len, &dlen); - else - decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data, len, - &dlen); - write_decrypted_note(wt, decrypted, sta->ptk.tk, - sta->ptk.tk_len, keyid); + decrypted = try_ptk_decrypt(wt, sta, hdr, keyid, data, len, + sta->ptk.tk, sta->ptk.tk_len, + &dlen); } else { decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, keyid, data, len, &dlen); @@ -620,6 +631,22 @@ check_zero_tk: dlen, 1, peer_addr); write_pcap_decrypted(wt, (const u8 *) hdr, hdrlen, decrypted, dlen); + } else if (sta->tptk_set) { + /* Check whether TPTK has a matching TK that could be used to + * decrypt the frame. That could happen if EAPOL-Key msg 4/4 + * was missing in the capture and this was PTK rekeying. */ + decrypted = try_ptk_decrypt(wt, sta, hdr, keyid, data, len, + sta->tptk.tk, sta->tptk.tk_len, + &dlen); + if (decrypted) { + add_note(wt, MSG_DEBUG, + "Update PTK (rekeying; no valid EAPOL-Key msg 4/4 seen)"); + os_memcpy(&sta->ptk, &sta->tptk, sizeof(sta->ptk)); + sta->ptk_set = 1; + sta->tptk_set = 0; + os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods)); + os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); + } } else { if (!try_ptk_iter && !only_zero_tk) add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); From e4eb009d9863c6d7216121573cd34271b5d26666 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 2 Apr 2020 15:35:56 +0300 Subject: [PATCH 0325/1105] DPP2: Add Connector and C-sign-key in psk/sae credentials for reconfig If the Enrollee indicates support for DPP R2 or newer, add Connector and C-sign-key in psk/sae credentials (i.e., cases where DPP AKM is not enabled) for reconfiguration. Extend processing of such credentials in wpa_supplicant network profile addition to handle this new case correctly by not setting key_mgmt=DPP based on Connector being present, but by looking at the actual akm value in the config object. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 3 ++- src/common/dpp.c | 21 +++++++++++++++++---- wpa_supplicant/dpp_supplicant.c | 8 +++++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 7b3690844..c86f01ba7 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -708,7 +708,8 @@ static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd, * message. */ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s", conf->connector); - } else if (conf->passphrase[0]) { + } + if (conf->passphrase[0]) { char hex[64 * 2 + 1]; wpa_snprintf_hex(hex, sizeof(hex), diff --git a/src/common/dpp.c b/src/common/dpp.c index 784961ddd..572800e4d 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -5236,7 +5236,7 @@ dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, return NULL; } - if (dpp_akm_dpp(conf->akm)) + if (dpp_akm_dpp(conf->akm) || (auth->peer_version >= 2 && auth->conf)) return dpp_build_conf_obj_dpp(auth, conf); return dpp_build_conf_obj_legacy(auth, conf); } @@ -6724,7 +6724,8 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, conf->connector = os_strdup(signed_connector); dpp_copy_csign(conf, csign_pub); - dpp_copy_netaccesskey(auth, conf); + if (dpp_akm_dpp(conf->akm)) + dpp_copy_netaccesskey(auth, conf); ret = 0; fail: @@ -6836,6 +6837,7 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth, struct json_token *root, *token, *discovery, *cred; struct dpp_config_obj *conf; struct wpabuf *ssid64 = NULL; + int legacy; root = json_parse((const char *) conf_obj, conf_obj_len); if (!root) @@ -6923,10 +6925,21 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth, } conf->akm = dpp_akm_from_str(token->string); - if (dpp_akm_legacy(conf->akm)) { + legacy = dpp_akm_legacy(conf->akm); + if (legacy && auth->peer_version >= 2) { + struct json_token *csign, *s_conn; + + csign = json_get_member(cred, "csign"); + s_conn = json_get_member(cred, "signedConnector"); + if (csign && csign->type == JSON_OBJECT && + s_conn && s_conn->type == JSON_STRING) + legacy = 0; + } + if (legacy) { if (dpp_parse_cred_legacy(conf, cred) < 0) goto fail; - } else if (dpp_akm_dpp(conf->akm)) { + } else if (dpp_akm_dpp(conf->akm) || + (auth->peer_version >= 2 && dpp_akm_legacy(conf->akm))) { if (dpp_parse_cred_dpp(auth, conf, cred) < 0) goto fail; } else { diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index e578e0aef..c1ebf10d3 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1100,8 +1100,10 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, ssid->ssid_len = conf->ssid_len; if (conf->connector) { - ssid->key_mgmt = WPA_KEY_MGMT_DPP; - ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; + if (dpp_akm_dpp(conf->akm)) { + ssid->key_mgmt = WPA_KEY_MGMT_DPP; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; + } ssid->dpp_connector = os_strdup(conf->connector); if (!ssid->dpp_connector) goto fail; @@ -1130,7 +1132,7 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, if (!conf->connector || dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) { - if (!conf->connector) + if (!conf->connector || !dpp_akm_dpp(conf->akm)) ssid->key_mgmt = 0; if (dpp_akm_psk(conf->akm)) ssid->key_mgmt |= WPA_KEY_MGMT_PSK | From a34fb797884685123d747a22cbb52cd4eeb70157 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 2 Apr 2020 15:38:20 +0300 Subject: [PATCH 0326/1105] tests: DPP reconfiguration connector Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 2b99bcf85..ff1ed6b79 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5239,3 +5239,65 @@ def test_dpp_pfs_ap_2(dev, apdev): run_dpp_pfs_sta(dev[0], 0) run_dpp_pfs_sta(dev[0], 1, fail=True) run_dpp_pfs_sta(dev[0], 2) + +def test_dpp_reconfig_connector(dev, apdev): + """DPP reconfiguration connector""" + try: + run_dpp_reconfig_connector(dev, apdev) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_reconfig_connector(dev, apdev): + check_dpp_capab(dev[0], min_ver=2) + check_dpp_capab(dev[1], min_ver=2) + + ssid = "reconfig" + passphrase = "secret passphrase" + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].set("dpp_config_processing", "2") + id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) + uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + dev[0].dpp_listen(2412) + configurator = dev[1].dpp_configurator_add() + conf = 'sta-psk' + dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid=ssid, + passphrase=passphrase, configurator=configurator) + res = wait_auth_success(dev[0], dev[1], configurator=dev[1], + enrollee=dev[0]) + + ev = dev[0].wait_event(["DPP-CONFOBJ-SSID"], timeout=1) + if ev is None: + raise Exception("SSID not reported") + res_ssid = ev.split(' ')[1] + if res_ssid != ssid: + raise Exception("Unexpected SSID value") + + ev = dev[0].wait_event(["DPP-CONNECTOR"], timeout=1) + if ev is None: + raise Exception("Connector not reported") + connector = ev.split(' ')[1] + + ev = dev[0].wait_event(["DPP-C-SIGN-KEY"], timeout=1) + if ev is None: + raise Exception("C-sign-key not reported") + p = ev.split(' ') + csign = p[1] + + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1) + if ev is None: + raise Exception("DPP network profile not generated") + id = ev.split(' ')[1] + + dev[0].wait_connected() + + n_key_mgmt = dev[0].get_network(id, "key_mgmt") + if n_key_mgmt != "WPA-PSK FT-PSK WPA-PSK-SHA256": + raise Exception("Unexpected key_mgmt: " + n_key_mgmt) + n_connector = dev[0].get_network(id, "dpp_connector") + if n_connector.strip('"') != connector: + raise Exception("Connector mismatch: %s %s" % (n_connector, connector)) + n_csign = dev[0].get_network(id, "dpp_csign") + if n_csign.strip('"') != csign: + raise Exception("csign mismatch: %s %s" % (n_csign, csign)) From bf9f49396b49424357e02ead25b6fc9e81852085 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 12:18:11 +0300 Subject: [PATCH 0327/1105] OWE: Remove check for unexpected DH Parameter IE use with other AKMs While the Diffie-Hellman Parameter element is defined in RFC 8110 explicitly for use witht he OWE AKM, it has now been proposed to be used with another AKM (DPP). Should any other AKM be extended in similar manner in the future, the check against unexpected use could result in additional interoperability issues. Remove that and instead, ignore the unexpected Diffie-Hellman Parameter element if it is included in (Re)Association Request frame when any other AKM is negotiated. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth_ie.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 2ac1df47e..9bcb997a1 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -851,17 +851,6 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, "OWE: No Diffie-Hellman Parameter element"); return WPA_INVALID_AKMP; } -#ifdef CONFIG_DPP - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && owe_dh) { - /* Diffie-Hellman Parameter element can be used with DPP as - * well, so allow this to proceed. */ - } else -#endif /* CONFIG_DPP */ - if (sm->wpa_key_mgmt != WPA_KEY_MGMT_OWE && owe_dh) { - wpa_printf(MSG_DEBUG, - "OWE: Unexpected Diffie-Hellman Parameter element with non-OWE AKM"); - return WPA_INVALID_AKMP; - } #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP2 From 872299f4b3167cd2a91829eb06f48f56418fc3d8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 12:43:48 +0300 Subject: [PATCH 0328/1105] DPP2: Store netAccessKey in psk/sae credentials for reconfig Connector alone is not sufficient for authentication during reconfiguration, so store the netAccessKey as well. Fixes: e4eb009d9863 ("DPP2: Add Connector and C-sign-key in psk/sae credentials for reconfig") Signed-off-by: Jouni Malinen --- src/common/dpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 572800e4d..ae4ed3fd0 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -6724,7 +6724,7 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, conf->connector = os_strdup(signed_connector); dpp_copy_csign(conf, csign_pub); - if (dpp_akm_dpp(conf->akm)) + if (dpp_akm_dpp(conf->akm) || auth->peer_version >= 2) dpp_copy_netaccesskey(auth, conf); ret = 0; From 62d561615599538faa30f0006f83b80f237c13ef Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 12:45:03 +0300 Subject: [PATCH 0329/1105] tests: DPP netAccessKey for reconfig Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index ff1ed6b79..7c5536515 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5285,6 +5285,13 @@ def run_dpp_reconfig_connector(dev, apdev): p = ev.split(' ') csign = p[1] + ev = dev[0].wait_event(["DPP-NET-ACCESS-KEY"], timeout=1) + if ev is None: + raise Exception("netAccessKey not reported") + p = ev.split(' ') + net_access_key = p[1] + net_access_key_expiry = p[2] if len(p) > 2 else None + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1) if ev is None: raise Exception("DPP network profile not generated") @@ -5301,3 +5308,7 @@ def run_dpp_reconfig_connector(dev, apdev): n_csign = dev[0].get_network(id, "dpp_csign") if n_csign.strip('"') != csign: raise Exception("csign mismatch: %s %s" % (n_csign, csign)) + n_net_access_key = dev[0].get_network(id, "dpp_netaccesskey") + if n_net_access_key.strip('"') != net_access_key: + raise Exception("net_access_key mismatch: %s %s" % (n_net_access_key, + net_access_key)) From f964a54ec2b74ec5c589b181079ce2fa8e8ee303 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 12:54:44 +0300 Subject: [PATCH 0330/1105] tests: Remove duplicate definitions of csign/connector in sigma_dut There is no need to duplicate the definitions of the exact same values within each test function. Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 2e9f26429..b75112d8e 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -1619,16 +1619,16 @@ def run_sigma_dut_dpp_qr_resp(dev, apdev, conf_idx, chan_list=None, finally: stop_sigma_dut(sigma) +csign = "30770201010420768240a3fc89d6662d9782f120527fe7fb9edc6366ab0b9c7dde96125cfd250fa00a06082a8648ce3d030107a144034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" +csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" +ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg" +ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b" + def test_sigma_dut_dpp_qr_init_enrollee(dev, apdev): """sigma_dut DPP/QR initiator as Enrollee""" check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - csign = "30770201010420768240a3fc89d6662d9782f120527fe7fb9edc6366ab0b9c7dde96125cfd250fa00a06082a8648ce3d030107a144034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg" - ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b" - params = {"ssid": "DPPNET01", "wpa": "2", "ieee80211w": "2", @@ -1718,11 +1718,6 @@ def run_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev, extra=''): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - csign = "30770201010420768240a3fc89d6662d9782f120527fe7fb9edc6366ab0b9c7dde96125cfd250fa00a06082a8648ce3d030107a144034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg" - ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b" - params = {"ssid": "DPPNET01", "wpa": "2", "ieee80211w": "2", @@ -1800,11 +1795,6 @@ def run_sigma_dut_dpp_qr_mutual_resp_enrollee(dev, apdev, extra=None): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - csign = "30770201010420768240a3fc89d6662d9782f120527fe7fb9edc6366ab0b9c7dde96125cfd250fa00a06082a8648ce3d030107a144034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg" - ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b" - params = {"ssid": "DPPNET01", "wpa": "2", "ieee80211w": "2", @@ -1889,11 +1879,6 @@ def run_sigma_dut_dpp_qr_mutual_init_enrollee(dev, apdev, resp_pending): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - csign = "30770201010420768240a3fc89d6662d9782f120527fe7fb9edc6366ab0b9c7dde96125cfd250fa00a06082a8648ce3d030107a144034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg" - ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b" - params = {"ssid": "DPPNET01", "wpa": "2", "ieee80211w": "2", @@ -2684,11 +2669,6 @@ def init_sigma_dut_dpp_proto_peer_disc_req(dev, apdev): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - csign = "30770201010420768240a3fc89d6662d9782f120527fe7fb9edc6366ab0b9c7dde96125cfd250fa00a06082a8648ce3d030107a144034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708" - ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg" - ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b" - params = {"ssid": "DPPNET01", "wpa": "2", "ieee80211w": "2", From 4b9a1ba0ad52d2723e55da10c92984fb1e4eaf79 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 12:59:47 +0300 Subject: [PATCH 0331/1105] tests: Use a helper function for starting DPP AP in sigma_dut tests Remove unnecessary code duplication. Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 74 ++++++----------------------------- 1 file changed, 12 insertions(+), 62 deletions(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index b75112d8e..5465c13df 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -1624,11 +1624,7 @@ csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf4 ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg" ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b" -def test_sigma_dut_dpp_qr_init_enrollee(dev, apdev): - """sigma_dut DPP/QR initiator as Enrollee""" - check_dpp_capab(dev[0]) - check_dpp_capab(dev[1]) - +def start_dpp_ap(apdev): params = {"ssid": "DPPNET01", "wpa": "2", "ieee80211w": "2", @@ -1638,10 +1634,16 @@ def test_sigma_dut_dpp_qr_init_enrollee(dev, apdev): "dpp_csign": csign_pub, "dpp_netaccesskey": ap_netaccesskey} try: - hapd = hostapd.add_ap(apdev[0], params) + hapd = hostapd.add_ap(apdev, params) except: raise HwsimSkip("DPP not supported") + return hapd +def test_sigma_dut_dpp_qr_init_enrollee(dev, apdev): + """sigma_dut DPP/QR initiator as Enrollee""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + hapd = start_dpp_ap(apdev[0]) sigma = start_sigma_dut(dev[0].ifname) try: dev[0].set("dpp_config_processing", "2") @@ -1717,20 +1719,7 @@ def test_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev): def run_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev, extra=''): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - - params = {"ssid": "DPPNET01", - "wpa": "2", - "ieee80211w": "2", - "wpa_key_mgmt": "DPP", - "rsn_pairwise": "CCMP", - "dpp_connector": ap_connector, - "dpp_csign": csign_pub, - "dpp_netaccesskey": ap_netaccesskey} - try: - hapd = hostapd.add_ap(apdev[0], params) - except: - raise HwsimSkip("DPP not supported") - + hapd = start_dpp_ap(apdev[0]) sigma = start_sigma_dut(dev[0].ifname) try: dev[0].set("dpp_config_processing", "2") @@ -1794,20 +1783,7 @@ def test_sigma_dut_dpp_qr_mutual_resp_enrollee_pending(dev, apdev): def run_sigma_dut_dpp_qr_mutual_resp_enrollee(dev, apdev, extra=None): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - - params = {"ssid": "DPPNET01", - "wpa": "2", - "ieee80211w": "2", - "wpa_key_mgmt": "DPP", - "rsn_pairwise": "CCMP", - "dpp_connector": ap_connector, - "dpp_csign": csign_pub, - "dpp_netaccesskey": ap_netaccesskey} - try: - hapd = hostapd.add_ap(apdev[0], params) - except: - raise HwsimSkip("DPP not supported") - + hapd = start_dpp_ap(apdev[0]) sigma = start_sigma_dut(dev[0].ifname) try: dev[0].set("dpp_config_processing", "2") @@ -1878,20 +1854,7 @@ def test_sigma_dut_dpp_qr_mutual_init_enrollee_pending(dev, apdev): def run_sigma_dut_dpp_qr_mutual_init_enrollee(dev, apdev, resp_pending): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - - params = {"ssid": "DPPNET01", - "wpa": "2", - "ieee80211w": "2", - "wpa_key_mgmt": "DPP", - "rsn_pairwise": "CCMP", - "dpp_connector": ap_connector, - "dpp_csign": csign_pub, - "dpp_netaccesskey": ap_netaccesskey} - try: - hapd = hostapd.add_ap(apdev[0], params) - except: - raise HwsimSkip("DPP not supported") - + hapd = start_dpp_ap(apdev[0]) sigma = start_sigma_dut(dev[0].ifname) try: dev[0].set("dpp_config_processing", "2") @@ -2668,20 +2631,7 @@ def run_sigma_dut_dpp_proto_responder_pkex(dev, step, frame, attr, result, fail) def init_sigma_dut_dpp_proto_peer_disc_req(dev, apdev): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - - params = {"ssid": "DPPNET01", - "wpa": "2", - "ieee80211w": "2", - "wpa_key_mgmt": "DPP", - "rsn_pairwise": "CCMP", - "dpp_connector": ap_connector, - "dpp_csign": csign_pub, - "dpp_netaccesskey": ap_netaccesskey} - try: - hapd = hostapd.add_ap(apdev[0], params) - except: - raise HwsimSkip("DPP not supported") - + hapd = start_dpp_ap(apdev[0]) dev[0].set("dpp_config_processing", "2") cmd = "DPP_CONFIGURATOR_ADD key=" + csign From 512b6c02e0f347b30666d5d747da9f9129b1a5b9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 15:47:18 +0300 Subject: [PATCH 0332/1105] DPP: Mandate mutual auth with NFC negotiated connection handover Mark own bootstrap information as having been used in NFC negotiated connection handover and do not accept non-mutual authentication when processing Authentication Response from the peer when such bootstrapping information is used. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 8 ++++++++ src/common/dpp.h | 2 ++ wpa_supplicant/dpp_supplicant.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/src/common/dpp.c b/src/common/dpp.c index ae4ed3fd0..c4ee9b8ab 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -3952,6 +3952,14 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, dpp_auth_fail(auth, "Missing Initiator Bootstrapping Key Hash attribute"); return NULL; + } else if (auth->own_bi && + auth->own_bi->type == DPP_BOOTSTRAP_NFC_URI && + auth->own_bi->nfc_negotiated) { + /* NFC negotiated connection handover bootstrapping mandates + * use of mutual authentication */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return NULL; } auth->peer_version = 1; /* default to the first version */ diff --git a/src/common/dpp.h b/src/common/dpp.h index 61be2184b..afbedc554 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -138,6 +138,8 @@ struct dpp_bootstrap_info { const struct dpp_curve_params *curve; unsigned int pkex_t; /* number of failures before dpp_pkex * instantiation */ + int nfc_negotiated; /* whether this has been used in NFC negotiated + * connection handover */ char *configurator_params; }; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index c1ebf10d3..f90463ff6 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -118,6 +118,7 @@ int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd) own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); if (!own_bi) return -1; + own_bi->nfc_negotiated = 1; pos = os_strstr(cmd, " uri="); if (!pos) @@ -149,6 +150,7 @@ int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd) own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); if (!own_bi) return -1; + own_bi->nfc_negotiated = 1; pos = os_strstr(cmd, " uri="); if (!pos) From 169cf4653480729cd55734a3d82aa5e61883efc8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 16:21:30 +0300 Subject: [PATCH 0333/1105] tests: sigma_dut and DPP with NFC Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 156 ++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 5465c13df..32b0bf433 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -2853,6 +2853,162 @@ def test_sigma_dut_dpp_tcp_enrollee_init(dev, apdev): stop_sigma_dut(sigma) dev[1].request("DPP_CONTROLLER_STOP") +def test_sigma_dut_dpp_nfc_handover_requestor_enrollee(dev, apdev): + """sigma_dut DPP/NFC handover requestor as Enrollee""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + hapd = start_dpp_ap(apdev[0]) + sigma = start_sigma_dut(dev[0].ifname) + try: + dev[0].set("dpp_config_processing", "2") + + cmd = "DPP_CONFIGURATOR_ADD key=" + csign + res = dev[1].request(cmd) + if "FAIL" in res: + raise Exception("Failed to add configurator") + conf_id = int(res) + dev[1].set("dpp_configurator_params", + " conf=sta-dpp ssid=%s configurator=%d" % (to_hex("DPPNET01"), conf_id)) + + id_own = dev[1].dpp_bootstrap_gen(type="nfc-uri", chan="81/1,6,11", + mac=True) + uri_own = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_own) + + res = sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPBS,NFC") + hex = res.split(',')[3] + uri_peer = from_hex(hex) + logger.info("URI from sigma_dut: " + uri_peer) + + sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,NFC" % to_hex(uri_own)) + + res = dev[1].request("DPP_NFC_HANDOVER_REQ own=%d uri=%s" % (id_own, + uri_peer)) + if "FAIL" in res: + raise Exception("Failed to process NFC Handover Request") + info = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_own) + logger.info("Updated local bootstrapping info:\n" + info) + freq = None + for line in info.splitlines(): + if line.startswith("use_freq="): + freq = int(line.split('=')[1]) + if freq is None: + raise Exception("Selected channel not indicated") + uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_own) + logger.info("Updated URI[1]: " + uri1) + dev[1].dpp_listen(freq, role="configurator") + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPProvisioningRole,Enrollee,DPPBS,NFC,DPPNFCHandover,Negotiated_Requestor,DPPTimeout,6,DPPWaitForConnect,Yes", timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK" not in res: + raise Exception("Unexpected result: " + res) + finally: + dev[0].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + +def test_sigma_dut_dpp_nfc_handover_selector_enrollee(dev, apdev): + """sigma_dut DPP/NFC handover selector as Enrollee""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + hapd = start_dpp_ap(apdev[0]) + sigma = start_sigma_dut(dev[0].ifname) + try: + dev[0].set("dpp_config_processing", "2") + + cmd = "DPP_CONFIGURATOR_ADD key=" + csign + res = dev[1].request(cmd) + if "FAIL" in res: + raise Exception("Failed to add configurator") + conf_id = int(res) + dev[1].set("dpp_configurator_params", + " conf=sta-dpp ssid=%s configurator=%d" % (to_hex("DPPNET01"), conf_id)) + + id_own = dev[1].dpp_bootstrap_gen(type="nfc-uri", chan="81/1,6,11", + mac=True) + uri_own = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_own) + + res = sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPBS,NFC") + hex = res.split(',')[3] + uri_peer = from_hex(hex) + logger.info("URI from sigma_dut: " + uri_peer) + + sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,NFC" % to_hex(uri_own)) + + res = dev[1].request("DPP_NFC_HANDOVER_SEL own=%d uri=%s" % (id_own, + uri_peer)) + if "FAIL" in res: + raise Exception("Failed to process NFC Handover Select") + peer = int(res) + dev[1].dpp_auth_init(peer=peer, own=id_own, configurator=conf_id, + conf="sta-dpp", ssid="DPPNET01") + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPProvisioningRole,Enrollee,DPPBS,NFC,DPPNFCHandover,Negotiated_Selector,DPPTimeout,6,DPPWaitForConnect,Yes", timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK" not in res: + raise Exception("Unexpected result: " + res) + finally: + dev[0].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + +def test_sigma_dut_dpp_nfc_static_read_enrollee(dev, apdev): + """sigma_dut DPP/NFC read tag as Enrollee""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + hapd = start_dpp_ap(apdev[0]) + sigma = start_sigma_dut(dev[0].ifname) + try: + dev[0].set("dpp_config_processing", "2") + + cmd = "DPP_CONFIGURATOR_ADD key=" + csign + res = dev[1].request(cmd) + if "FAIL" in res: + raise Exception("Failed to add configurator") + conf_id = int(res) + dev[1].set("dpp_configurator_params", + " conf=sta-dpp ssid=%s configurator=%d" % (to_hex("DPPNET01"), conf_id)) + + id_own = dev[1].dpp_bootstrap_gen(type="nfc-uri", chan="81/6", mac=True) + uri_own = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_own) + + sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,NFC" % to_hex(uri_own)) + dev[1].dpp_listen(2437, role="configurator") + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPProvisioningRole,Enrollee,DPPBS,NFC,DPPNFCHandover,Static,DPPTimeout,6,DPPWaitForConnect,Yes", timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK" not in res: + raise Exception("Unexpected result: " + res) + finally: + dev[0].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + +def test_sigma_dut_dpp_nfc_static_write_enrollee(dev, apdev): + """sigma_dut DPP/NFC write tag as Enrollee""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + hapd = start_dpp_ap(apdev[0]) + sigma = start_sigma_dut(dev[0].ifname) + try: + dev[0].set("dpp_config_processing", "2") + + cmd = "DPP_CONFIGURATOR_ADD key=" + csign + res = dev[1].request(cmd) + if "FAIL" in res: + raise Exception("Failed to add configurator") + conf_id = int(res) + dev[1].set("dpp_configurator_params", + " conf=sta-dpp ssid=%s configurator=%d" % (to_hex("DPPNET01"), conf_id)) + + res = sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPBS,NFC") + hex = res.split(',')[3] + uri_peer = from_hex(hex) + logger.info("URI from sigma_dut: " + uri_peer) + + dev[1].dpp_auth_init(nfc_uri=uri_peer, configurator=conf_id, + conf="sta-dpp", ssid="DPPNET01") + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Responder,DPPProvisioningRole,Enrollee,DPPBS,NFC,DPPNFCHandover,Static,DPPTimeout,6,DPPWaitForConnect,Yes", timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK" not in res: + raise Exception("Unexpected result: " + res) + finally: + dev[0].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + def test_sigma_dut_preconfigured_profile(dev, apdev): """sigma_dut controlled connection using preconfigured profile""" try: From c7a9a5745bccdb0cb987a09cbeee502dab660456 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Fri, 3 Apr 2020 17:22:03 +0530 Subject: [PATCH 0334/1105] P2P: Start group with user configured params after accepting invitation Use global configuration parameters while invoking a persistent P2P group after accepting P2P Invitation Request from a peer. Signed-off-by: Jouni Malinen --- wpa_supplicant/p2p_supplicant.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index e86c082b3..e94bffe52 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3182,8 +3182,12 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid, MAC2STR(sa), s->id); } wpas_p2p_group_add_persistent( - wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0, - 0, NULL, + wpa_s, s, go, 0, op_freq, 0, + wpa_s->conf->p2p_go_ht40, + wpa_s->conf->p2p_go_vht, + 0, + wpa_s->conf->p2p_go_he, + wpa_s->conf->p2p_go_edmg, NULL, go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 1); } else if (bssid) { From ca70f36c20db0776a9776ad99517f459fd3532f8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 21:16:06 +0300 Subject: [PATCH 0335/1105] tests: Make ap_vht_csa_vht40_disable more robust Wait for disconnection and reconnection after CSA since mac80211 does not support clean CSA to disable VHT. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_vht.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 4e8540cf0..24658d1f9 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -889,7 +889,7 @@ def test_ap_vht_csa_vht40_disable(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) bssid = hapd.own_addr() - dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745") + dev[0].connect("vht", key_mgmt="NONE", scan_freq="5200 5745") hwsim_utils.test_connectivity(dev[0], hapd) hapd.request("CHAN_SWITCH 5 5200 center_freq1=5210 sec_channel_offset=1 bandwidth=40 ht") @@ -903,7 +903,14 @@ def test_ap_vht_csa_vht40_disable(dev, apdev): raise Exception("Channel switch event not seen") if "freq=5200" not in ev: raise Exception("Channel mismatch: " + ev) - time.sleep(0.5) + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5) + if ev: + # mac80211 does not support CSA to disable VHT, so the channel + # switch will be followed by disconnection and attempt to reconnect. + # Wait for that here to avoid failing the test case based on how + # example the connectivity test would get timed compared to getting + # disconnected or reconnected. + dev[0].wait_connected() hwsim_utils.test_connectivity(dev[0], hapd) dev[1].connect("vht", key_mgmt="NONE", scan_freq="5200") From 866c3acb8cce8806d0b40393a407347e1b9add32 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2020 23:56:10 +0300 Subject: [PATCH 0336/1105] wlantest: Do not report decryption failures for WEP keys if no keys If no WEP keys are available, there is not going to be an attempt to decrypt the frame, so don't claim decryption failed. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index fa8df77be..e8160c3f6 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -260,8 +260,9 @@ static void rx_data_bss_prot_group(struct wlantest *wt, check_plaintext_prot(wt, hdr, data, len); keyid = data[3] >> 6; - if (bss->gtk_len[keyid] == 0 && bss->group_cipher != WPA_CIPHER_WEP40) - { + if (bss->gtk_len[keyid] == 0 && + (bss->group_cipher != WPA_CIPHER_WEP40 || + dl_list_empty(&wt->wep))) { add_note(wt, MSG_MSGDUMP, "No GTK known to decrypt the frame " "(A2=" MACSTR " KeyID=%d)", MAC2STR(hdr->addr2), keyid); From 3e537313e85f8a3af93b8e3a60c96ebebb9ccdc5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 00:00:17 +0300 Subject: [PATCH 0337/1105] wlantest: Add debug print with frame number for decryption failures This makes it more convenient to find the frames that could not be decrypted. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index e8160c3f6..df78953f2 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -325,8 +325,13 @@ skip_replay_det: os_memcpy(bss->rsc[keyid], pn, 6); write_pcap_decrypted(wt, (const u8 *) hdr, hdrlen, decrypted, dlen); - } else + } else { + wpa_printf(MSG_DEBUG, "Failed to decrypt frame (group) #%u A2=" + MACSTR " seq=%u", + wt->frame_num, MAC2STR(hdr->addr2), + WLAN_GET_SEQ_SEQ(le_to_host16(hdr->seq_ctrl))); add_note(wt, MSG_DEBUG, "Failed to decrypt frame (group)"); + } os_free(decrypted); } @@ -370,6 +375,7 @@ static void rx_data_bss_prot(struct wlantest *wt, int try_ptk_iter = 0; int replay = 0; int only_zero_tk = 0; + u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); if (hdr->addr1[0] & 0x01) { rx_data_bss_prot_group(wt, hdr, hdrlen, qos, dst, src, @@ -542,7 +548,6 @@ static void rx_data_bss_prot(struct wlantest *wt, else ccmp_get_pn(pn, data); if (os_memcmp(pn, rsc, 6) <= 0) { - u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); char pn_hex[6 * 2 + 1], rsc_hex[6 * 2 + 1]; wpa_snprintf_hex(pn_hex, sizeof(pn_hex), pn, 6); @@ -649,8 +654,14 @@ check_zero_tk: os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); } } else { - if (!try_ptk_iter && !only_zero_tk) + if (!try_ptk_iter && !only_zero_tk) { + wpa_printf(MSG_DEBUG, + "Failed to decrypt frame #%u A2=" MACSTR + " seq=%u", + wt->frame_num, MAC2STR(hdr->addr2), + WLAN_GET_SEQ_SEQ(seq_ctrl)); add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); + } /* Assume the frame was corrupted and there was no FCS to check. * Allow retry of this particular frame to be processed so that From c8a3565947ba4dd2ff48e0e54fedd235b2fe015d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 00:04:32 +0300 Subject: [PATCH 0338/1105] wlantest: Remove duplicate PN/RSC prints from replay cases The PN and RSC are already printed in the "replay detected" debug message so there is no point in having separate hexdumps of the same values immediately after that. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index df78953f2..ef85e46e3 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -291,8 +291,6 @@ static void rx_data_bss_prot_group(struct wlantest *wt, (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ? " Retry" : "", keyid, pn_hex, rsc_hex); - wpa_hexdump(MSG_INFO, "RX PN", pn, 6); - wpa_hexdump(MSG_INFO, "RSC", bss->rsc[keyid], 6); replay = 1; } @@ -562,8 +560,6 @@ static void rx_data_bss_prot(struct wlantest *wt, (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ? " Retry" : "", keyid, tid, pn_hex, rsc_hex); - wpa_hexdump(MSG_INFO, "RX PN", pn, 6); - wpa_hexdump(MSG_INFO, "RSC", rsc, 6); replay = 1; } From 116bbf7953d8a5643c82e30f97f822e067c3df09 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 00:06:59 +0300 Subject: [PATCH 0339/1105] wlantest: Add frame number fo replay detected messages This makes it easier to find the relevant frames. Signed-off-by: Jouni Malinen --- wlantest/rx_data.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index ef85e46e3..b632013a8 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -283,14 +283,14 @@ static void rx_data_bss_prot_group(struct wlantest *wt, wpa_snprintf_hex(rsc_hex, sizeof(rsc_hex), bss->rsc[keyid], 6); add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR " A2=" MACSTR " A3=" MACSTR - " seq=%u frag=%u%s keyid=%d %s<=%s", + " seq=%u frag=%u%s keyid=%d #%u %s<=%s", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl), (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ? " Retry" : "", - keyid, pn_hex, rsc_hex); + keyid, wt->frame_num, pn_hex, rsc_hex); replay = 1; } @@ -552,14 +552,14 @@ static void rx_data_bss_prot(struct wlantest *wt, wpa_snprintf_hex(rsc_hex, sizeof(rsc_hex), rsc, 6); add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR " A2=" MACSTR " A3=" MACSTR - " seq=%u frag=%u%s keyid=%d tid=%d %s<=%s", + " seq=%u frag=%u%s keyid=%d tid=%d #%u %s<=%s", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl), (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ? " Retry" : "", - keyid, tid, pn_hex, rsc_hex); + keyid, tid, wt->frame_num, pn_hex, rsc_hex); replay = 1; } From fe4c0ea723258687cc094b2000656ce26408be6c Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Tue, 31 Mar 2020 11:09:00 -0700 Subject: [PATCH 0340/1105] tests: Enable MACsec testing by default in the VM kernel Include support for MACsec testing in the (vm) kernel by default. Don't include support in the example hostapd or wpa_supplicant configs yet since that would potentially break the build on older distributions like Ubuntu 16.04, which is supported until April 2021. Signed-off-by: Thomas Pedersen --- tests/hwsim/vm/kernel-config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/hwsim/vm/kernel-config b/tests/hwsim/vm/kernel-config index 503815917..2aff20af4 100644 --- a/tests/hwsim/vm/kernel-config +++ b/tests/hwsim/vm/kernel-config @@ -12,6 +12,7 @@ CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y CONFIG_LOG_BUF_SHIFT=21 +CONFIG_NAMESPACES=y # CONFIG_FHANDLE is not set CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set @@ -98,6 +99,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_BLK_DEV is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y +CONFIG_MACSEC=y +CONFIG_VETH=y # CONFIG_ETHERNET is not set CONFIG_MAC80211_HWSIM=y # CONFIG_INPUT_KEYBOARD is not set From 97beccc8380f347ce4aa8066341ee9d6aeb03554 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 18:08:14 +0300 Subject: [PATCH 0341/1105] SAE: Fix build without DPP/OWE/ERP SAE needs sha256-kdf.c to be included in the build. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 1 + hostapd/Makefile | 1 + wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + 4 files changed, 4 insertions(+) diff --git a/hostapd/Android.mk b/hostapd/Android.mk index fce40620f..0f0556501 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -252,6 +252,7 @@ L_CFLAGS += -DCONFIG_SAE OBJS += src/common/sae.c NEED_ECC=y NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y NEED_DRAGONFLY=y endif diff --git a/hostapd/Makefile b/hostapd/Makefile index 0a3b8dde7..326e91b8c 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -296,6 +296,7 @@ CFLAGS += -DCONFIG_SAE OBJS += ../src/common/sae.o NEED_ECC=y NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y NEED_AP_MLME=y NEED_DRAGONFLY=y endif diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index fbbb06191..e44b366b5 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -237,6 +237,7 @@ L_CFLAGS += -DCONFIG_SAE OBJS += src/common/sae.c NEED_ECC=y NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y NEED_DRAGONFLY=y ifdef CONFIG_TESTING_OPTIONS NEED_DH_GROUPS_ALL=y diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 0d9950d78..6138a3120 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -269,6 +269,7 @@ CFLAGS += -DCONFIG_SAE OBJS += ../src/common/sae.o NEED_ECC=y NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y NEED_DRAGONFLY=y ifdef CONFIG_TESTING_OPTIONS NEED_DH_GROUPS_ALL=y From 41a10324492e09183d6758bd310a32ec66702b50 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 18:28:06 +0300 Subject: [PATCH 0342/1105] tests: New style fuzzing tool for SAE commit parsing Signed-off-by: Jouni Malinen --- tests/fuzzing/sae/Makefile | 24 +++++++++++ .../corpus/sae-commit-h2e-rejected-groups.dat | Bin 0 -> 102 bytes .../sae/corpus/sae-commit-h2e-token.dat | Bin 0 -> 101 bytes tests/fuzzing/sae/corpus/sae-commit-pw-id.dat | Bin 0 -> 101 bytes tests/fuzzing/sae/corpus/sae-commit-token.dat | Bin 0 -> 130 bytes tests/fuzzing/sae/corpus/sae-commit-valid.dat | Bin 0 -> 98 bytes tests/fuzzing/sae/sae.c | 39 ++++++++++++++++++ 7 files changed, 63 insertions(+) create mode 100644 tests/fuzzing/sae/Makefile create mode 100644 tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat create mode 100644 tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat create mode 100644 tests/fuzzing/sae/corpus/sae-commit-pw-id.dat create mode 100644 tests/fuzzing/sae/corpus/sae-commit-token.dat create mode 100644 tests/fuzzing/sae/corpus/sae-commit-valid.dat create mode 100644 tests/fuzzing/sae/sae.c diff --git a/tests/fuzzing/sae/Makefile b/tests/fuzzing/sae/Makefile new file mode 100644 index 000000000..0a56e0628 --- /dev/null +++ b/tests/fuzzing/sae/Makefile @@ -0,0 +1,24 @@ +all: sae +include ../rules.include + +CFLAGS += -DCONFIG_SHA256 +CFLAGS += -DCONFIG_ECC + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += $(SRC)/crypto/crypto_openssl.o +LIBS += -lcrypto +OBJS += $(SRC)/crypto/dh_groups.o +OBJS += $(SRC)/crypto/sha256-prf.o +OBJS += $(SRC)/crypto/sha256-kdf.o +OBJS += $(SRC)/common/dragonfly.o + +sae: sae.o $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: + $(MAKE) -C $(SRC) clean + rm -f sae *~ *.o *.d ../*~ ../*.o ../*.d + +-include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat b/tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat new file mode 100644 index 0000000000000000000000000000000000000000..cd129a474a726d28b51b2280127d1d650eb04cda GIT binary patch literal 102 zcmV-s0Ga<208|=nJjbH(_K3tR3*!ii@RWbONRp*d1ON1&E-_G}%;8~xd<7qxPmG)o zv8AFTOtIEWsptP(>a*mwgSoYf78o<))4MF>>^d|^j!KwdSE!+=hWTauMQcasx=vVV IrT+q409Fh%GXMYp literal 0 HcmV?d00001 diff --git a/tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat b/tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat new file mode 100644 index 0000000000000000000000000000000000000000..b2886c70d20902b56d93407b8ab2c2c1016ee221 GIT binary patch literal 101 zcmV-r0Gj_308|=nJjbH(_K3tR3*!ii@RWbONRp*d1ON1&E-_G}%;8~xd<7qxPmG)o zv8AFTOtIEWsptP(>a*mwgSoYf78o<))4MF>>^d|^j!KwdSE!+=hWTauMQcasx=vVV HrT+n4A=orC literal 0 HcmV?d00001 diff --git a/tests/fuzzing/sae/corpus/sae-commit-pw-id.dat b/tests/fuzzing/sae/corpus/sae-commit-pw-id.dat new file mode 100644 index 0000000000000000000000000000000000000000..5ca903ed20160871f74acbec6f5677b8a0da26d7 GIT binary patch literal 101 zcmV-r0Gj_308|=nJjbH(_K3tR3*!ii@RWbONRp*d1ON1&E-_G}%;8~xd<7qxPmG)o zv8AFTOtIEWsptP(>a*mwgSoYf78o<))4MF>>^d|^j!KwdSE!+=hWTauMQcasx=vVV HrT+mTA)GV! literal 0 HcmV?d00001 diff --git a/tests/fuzzing/sae/corpus/sae-commit-token.dat b/tests/fuzzing/sae/corpus/sae-commit-token.dat new file mode 100644 index 0000000000000000000000000000000000000000..b25cc49f8e106b67bf25f144507a9d8d72b0c705 GIT binary patch literal 130 zcmWe;AOu3Ba&3+;`uMHmhz|E-j;;?=>i2p~S{lgw|I2(m!+^zS9ws)_u*%Q!@0r8D zap@vupN-eNS3dtA^J?>xZOuEkc8f_EKf1hI=gAu@6OTTx842Ml7OrUfnfk{y+x^8Z Izle;b0ElZc)&Kwi literal 0 HcmV?d00001 diff --git a/tests/fuzzing/sae/corpus/sae-commit-valid.dat b/tests/fuzzing/sae/corpus/sae-commit-valid.dat new file mode 100644 index 0000000000000000000000000000000000000000..eadfa4993b89ad45438a77849cecd14f420cf7ba GIT binary patch literal 98 zcmV-o0Ga*mwgSoYf78o<))4MF>>^d|^j!KwdSE!+=hWTauMQcasx=vVV ErG@J<)&Kwi literal 0 HcmV?d00001 diff --git a/tests/fuzzing/sae/sae.c b/tests/fuzzing/sae/sae.c new file mode 100644 index 000000000..8819a4abb --- /dev/null +++ b/tests/fuzzing/sae/sae.c @@ -0,0 +1,39 @@ +/* + * SAE fuzzer + * Copyright (c) 2020, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/sae.h" +#include "../fuzzer-common.h" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct sae_data sae; + u16 res; + const u8 *token = NULL; + size_t token_len = 0; + int groups[] = { 19, 0 }; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + os_memset(&sae, 0, sizeof(sae)); + res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 0); + wpa_printf(MSG_DEBUG, "sae_parse_commit(0): %u", res); + sae_clear_data(&sae); + res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 1); + wpa_printf(MSG_DEBUG, "sae_parse_commit(1): %u", res); + sae_clear_data(&sae); + os_program_deinit(); + + return 0; +} From af23f3a84954d066b6c2c521c5ba1c5e7e7efcf2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 20:07:38 +0300 Subject: [PATCH 0343/1105] tests: New style fuzzing tool for DPP URI parsing Signed-off-by: Jouni Malinen --- tests/fuzzing/dpp-uri/Makefile | 33 +++++++++++++++++++ tests/fuzzing/dpp-uri/corpus/1.dat | 1 + tests/fuzzing/dpp-uri/corpus/2.dat | 1 + tests/fuzzing/dpp-uri/corpus/3.dat | 1 + tests/fuzzing/dpp-uri/dpp-uri.c | 51 ++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+) create mode 100644 tests/fuzzing/dpp-uri/Makefile create mode 100644 tests/fuzzing/dpp-uri/corpus/1.dat create mode 100644 tests/fuzzing/dpp-uri/corpus/2.dat create mode 100644 tests/fuzzing/dpp-uri/corpus/3.dat create mode 100644 tests/fuzzing/dpp-uri/dpp-uri.c diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile new file mode 100644 index 000000000..27b2fddb3 --- /dev/null +++ b/tests/fuzzing/dpp-uri/Makefile @@ -0,0 +1,33 @@ +all: dpp-uri +include ../rules.include + +CFLAGS += -DCONFIG_DPP +CFLAGS += -DCONFIG_DPP2 +CFLAGS += -DCONFIG_SHA256 +CFLAGS += -DCONFIG_SHA384 +CFLAGS += -DCONFIG_SHA512 +CFLAGS += -DCONFIG_ECC +CFLAGS += -DCONFIG_OPENSSL_CMAC + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += $(SRC)/crypto/crypto_openssl.o +LIBS += -lcrypto + +OBJS += $(SRC)/crypto/aes-ctr.o +OBJS += $(SRC)/crypto/aes-siv.o +OBJS += $(SRC)/crypto/sha256-kdf.o +OBJS += $(SRC)/crypto/sha384-kdf.o +OBJS += $(SRC)/crypto/sha512-kdf.o +OBJS += $(SRC)/tls/asn1.o +OBJS += $(SRC)/common/dpp.o + +dpp-uri: dpp-uri.o $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: + $(MAKE) -C $(SRC) clean + rm -f dpp-uri *~ *.o *.d ../*~ ../*.o ../*.d + +-include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/dpp-uri/corpus/1.dat b/tests/fuzzing/dpp-uri/corpus/1.dat new file mode 100644 index 000000000..b2387e09a --- /dev/null +++ b/tests/fuzzing/dpp-uri/corpus/1.dat @@ -0,0 +1 @@ +DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;; \ No newline at end of file diff --git a/tests/fuzzing/dpp-uri/corpus/2.dat b/tests/fuzzing/dpp-uri/corpus/2.dat new file mode 100644 index 000000000..ee2ff90dd --- /dev/null +++ b/tests/fuzzing/dpp-uri/corpus/2.dat @@ -0,0 +1 @@ +DPP:C:81/1,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;; \ No newline at end of file diff --git a/tests/fuzzing/dpp-uri/corpus/3.dat b/tests/fuzzing/dpp-uri/corpus/3.dat new file mode 100644 index 000000000..ce7ad16f3 --- /dev/null +++ b/tests/fuzzing/dpp-uri/corpus/3.dat @@ -0,0 +1 @@ +DPP:I:SN=4774LH2b4044;M:010203040506;C:81/1,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;; \ No newline at end of file diff --git a/tests/fuzzing/dpp-uri/dpp-uri.c b/tests/fuzzing/dpp-uri/dpp-uri.c new file mode 100644 index 000000000..77db5b8bb --- /dev/null +++ b/tests/fuzzing/dpp-uri/dpp-uri.c @@ -0,0 +1,51 @@ +/* + * DPP URI fuzzer + * Copyright (c) 2020, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/dpp.h" +#include "../fuzzer-common.h" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct dpp_global *dpp; + struct dpp_global_config config; + struct dpp_bootstrap_info *bi; + char *uri; + char buf[1000]; + int ret = -1; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + uri = os_malloc(size + 1); + if (!uri) + goto out; + os_memcpy(uri, data, size); + uri[size] = '\0'; + os_memset(&config, 0, sizeof(config)); + dpp = dpp_global_init(&config); + if (!dpp) + goto out; + + bi = dpp_add_qr_code(dpp, uri); + if (bi && dpp_bootstrap_info(dpp, bi->id, buf, sizeof(buf)) > 0) + wpa_printf(MSG_DEBUG, "DPP: %s", buf); + dpp_global_deinit(dpp); + + ret = 0; +out: + os_free(uri); + os_program_deinit(); + + return ret; +} From d867e11811eb0e264bb5e62f8904ecddf7027ba9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 21:50:37 +0300 Subject: [PATCH 0344/1105] FT: Remove and re-add STA entry after FT protocol success with PMF Allow STA entry to be removed and re-added to the driver with PMF is used with FT. Previously, this case resulted in cfg80211 rejecting STA entry update after successful FT protocol use if the association had not been dropped and it could not be dropped for the PMF case in handle_auth(). Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 24 +----------------------- src/ap/sta_info.c | 30 ++++++++++++++++++++++++++++++ src/ap/sta_info.h | 1 + src/ap/wpa_auth.c | 2 +- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_ft.c | 16 ++++++++++++++-- src/ap/wpa_auth_glue.c | 29 +++++++++++++++++++++++++++++ src/ap/wpa_auth_i.h | 2 +- 8 files changed, 78 insertions(+), 27 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 045a6cbcd..2a5f6e5ec 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -2526,32 +2526,10 @@ static void handle_auth(struct hostapd_data *hapd, (!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) && !(hapd->conf->mesh & MESH_ENABLED) && !(sta->added_unassoc)) { - /* - * If a station that is already associated to the AP, is trying - * to authenticate again, remove the STA entry, in order to make - * sure the STA PS state gets cleared and configuration gets - * updated. To handle this, station's added_unassoc flag is - * cleared once the station has completed association. - */ - ap_sta_set_authorized(hapd, sta, 0); - hostapd_drv_sta_remove(hapd, sta->addr); - sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH | - WLAN_STA_AUTHORIZED); - - if (hostapd_sta_add(hapd, sta->addr, 0, 0, - sta->supported_rates, - sta->supported_rates_len, - 0, NULL, NULL, NULL, 0, - sta->flags, 0, 0, 0, 0)) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_NOTICE, - "Could not add STA to kernel driver"); + if (ap_sta_re_add(hapd, sta) < 0) { resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto fail; } - - sta->added_unassoc = 1; } switch (auth_alg) { diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 903be28d4..93f1f0c20 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -1497,3 +1497,33 @@ int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, return eloop_is_timeout_registered(ap_sta_delayed_1x_auth_fail_cb, hapd, sta); } + + +int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta) +{ + /* + * If a station that is already associated to the AP, is trying to + * authenticate again, remove the STA entry, in order to make sure the + * STA PS state gets cleared and configuration gets updated. To handle + * this, station's added_unassoc flag is cleared once the station has + * completed association. + */ + ap_sta_set_authorized(hapd, sta, 0); + hostapd_drv_sta_remove(hapd, sta->addr); + sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH | WLAN_STA_AUTHORIZED); + + if (hostapd_sta_add(hapd, sta->addr, 0, 0, + sta->supported_rates, + sta->supported_rates_len, + 0, NULL, NULL, NULL, 0, + sta->flags, 0, 0, 0, 0)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_NOTICE, + "Could not add STA to kernel driver"); + return -1; + } + + sta->added_unassoc = 1; + return 0; +} diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 8ff6ac62f..308aa29d9 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -358,5 +358,6 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, struct sta_info *sta); int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, struct sta_info *sta); +int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta); #endif /* STA_INFO_H */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index e0ffb2718..070236a89 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1836,7 +1836,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) #ifdef CONFIG_IEEE80211R_AP wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration after association"); - wpa_ft_install_ptk(sm); + wpa_ft_install_ptk(sm, 1); /* Using FT protocol, not WPA auth state machine */ sm->ft_completed = 1; diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 868aaa1fa..fafabe9c5 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -301,6 +301,7 @@ struct wpa_auth_callbacks { int *bandwidth, int *seg1_idx); #ifdef CONFIG_IEEE80211R_AP struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr); + int (*add_sta_ft)(void *ctx, const u8 *sta_addr); int (*set_vlan)(void *ctx, const u8 *sta_addr, struct vlan_description *vlan); int (*get_vlan)(void *ctx, const u8 *sta_addr, diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 476a2be69..6f6c18eec 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2747,7 +2747,16 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, } -void wpa_ft_install_ptk(struct wpa_state_machine *sm) +static inline int wpa_auth_add_sta_ft(struct wpa_authenticator *wpa_auth, + const u8 *addr) +{ + if (!wpa_auth->cb->add_sta_ft) + return -1; + return wpa_auth->cb->add_sta_ft(wpa_auth->cb_ctx, addr); +} + + +void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry) { enum wpa_alg alg; int klen; @@ -2769,6 +2778,9 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) return; } + if (!retry) + wpa_auth_add_sta_ft(sm->wpa_auth, sm->addr); + /* FIX: add STA entry to kernel/driver here? The set_key will fail * most likely without this.. At the moment, STA entry is added only * after association has been completed. This function will be called @@ -3140,7 +3152,7 @@ pmk_r1_derived: sm->pairwise = pairwise; sm->PTK_valid = TRUE; sm->tk_already_set = FALSE; - wpa_ft_install_ptk(sm); + wpa_ft_install_ptk(sm, 0); if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN"); diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 7a1ed24e8..79880e478 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1038,6 +1038,34 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) } +static int hostapd_wpa_auth_add_sta_ft(void *ctx, const u8 *sta_addr) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + sta = ap_get_sta(hapd, sta_addr); + if (!sta) + return -1; + + if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) && + (sta->flags & WLAN_STA_MFP) && ap_sta_is_authorized(sta) && + !(hapd->conf->mesh & MESH_ENABLED) && !(sta->added_unassoc)) { + /* We could not do this in handle_auth() since there was a + * PMF-enabled association for the STA and the new + * authentication attempt was not yet fully processed. Now that + * we are ready to configure the TK to the driver, + * authentication has succeeded and we can clean up the driver + * STA entry to avoid issues with any maintained state from the + * previous association. */ + wpa_printf(MSG_DEBUG, + "FT: Remove and re-add driver STA entry after successful FT authentication"); + return ap_sta_re_add(hapd, sta); + } + + return 0; +} + + static int hostapd_wpa_auth_set_vlan(void *ctx, const u8 *sta_addr, struct vlan_description *vlan) { @@ -1399,6 +1427,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) #ifdef CONFIG_IEEE80211R_AP .send_ft_action = hostapd_wpa_auth_send_ft_action, .add_sta = hostapd_wpa_auth_add_sta, + .add_sta_ft = hostapd_wpa_auth_add_sta_ft, .add_tspec = hostapd_wpa_auth_add_tspec, .set_vlan = hostapd_wpa_auth_set_vlan, .get_vlan = hostapd_wpa_auth_get_vlan, diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index bc59d6a4c..813612e74 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -300,7 +300,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); -void wpa_ft_install_ptk(struct wpa_state_machine *sm); +void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry); int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, const u8 *pmk_r0, const u8 *pmk_r0_name); #endif /* CONFIG_IEEE80211R_AP */ From 9dd5373122e3330f81f62b6a7b6967e2f6104bf6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 21:49:31 +0300 Subject: [PATCH 0345/1105] tests: FT+PMF roaming with skip_prune Verify hostapd behavior during FT protocol processing when a STA entry is still present in the AP and that association has PMF negotiated. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 770b26131..a7a71711a 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -3312,8 +3312,17 @@ def test_ap_ft_skip_prune_assoc2(dev, apdev): """WPA2-PSK-FT AP with skip_prune_assoc (disable full_ap_client_state)""" run_ap_ft_skip_prune_assoc(dev, apdev, True, False, test_connectivity=False) +def test_ap_ft_skip_prune_assoc_pmf(dev, apdev): + """WPA2-PSK-FT/PMF AP with skip_prune_assoc""" + run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True) + +def test_ap_ft_skip_prune_assoc_pmf_over_ds(dev, apdev): + """WPA2-PSK-FT/PMF AP with skip_prune_assoc (over DS)""" + run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True, over_ds=True) + def run_ap_ft_skip_prune_assoc(dev, apdev, skip_prune_assoc, - full_ap_client_state, test_connectivity=True): + full_ap_client_state, test_connectivity=True, + pmf=False, over_ds=False): ssid = "test-ft" passphrase = "12345678" @@ -3322,16 +3331,21 @@ def run_ap_ft_skip_prune_assoc(dev, apdev, skip_prune_assoc, params['skip_prune_assoc'] = '1' if not full_ap_client_state: params['driver_params'] = "full_ap_client_state=0" + if pmf: + params["ieee80211w"] = "2" hapd0 = hostapd.add_ap(apdev[0], params) params = ft_params2(ssid=ssid, passphrase=passphrase) if skip_prune_assoc: params['skip_prune_assoc'] = '1' if not full_ap_client_state: params['driver_params'] = "full_ap_client_state=0" + if pmf: + params["ieee80211w"] = "2" hapd1 = hostapd.add_ap(apdev[1], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, - test_connectivity=test_connectivity) + ieee80211w="2" if pmf else "0", + over_ds=over_ds, test_connectivity=test_connectivity) def test_ap_ft_sae_skip_prune_assoc(dev, apdev): """WPA2-PSK-FT-SAE AP with skip_prune_assoc""" From 153333ef6b67a30fb1581df26815713acdd0e698 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 23:42:05 +0300 Subject: [PATCH 0346/1105] FT RRB: Remove confusing debug print about extra data The "FT: Ignore extra data in end" hexdump is quite confusing since it shows all the IEs that were actually either processed or forwarded. There is no code path that could reach this debug print with actual real extra data. Remove it and the dead increment of pos to avoid warnings from static analyzers. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth_ft.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 6f6c18eec..4ca18ab6b 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -4572,7 +4572,6 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, return -1; } status_code = WPA_GET_LE16(pos); - pos += 2; wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Response " "(status_code=%d)", status_code); @@ -4585,11 +4584,6 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, return -1; } - if (end > pos) { - wpa_hexdump(MSG_DEBUG, "FT: Ignore extra data in end", - pos, end - pos); - } - return 0; } From ec182d5e939c03b2688e7fd8618e8f34af021b04 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 4 Apr 2020 23:57:18 +0300 Subject: [PATCH 0347/1105] tests: SAE/PMF roam Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index c845096fc..63a61b8f0 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -2580,3 +2580,30 @@ def test_sae_and_psk_multiple_passwords(dev, apdev, params): dev[1].connect("test-sae", psk="passphrase1", scan_freq="2412") dev[1].request("REMOVE_NETWORK all") dev[1].wait_disconnected() + +def test_sae_pmf_roam(dev, apdev): + """SAE/PMF roam""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params['ieee80211w'] = '2' + params['skip_prune_assoc'] = '1' + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + dev[0].set("sae_groups", "") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", + ieee80211w="2", scan_freq="2412") + dev[0].dump_monitor() + hapd.wait_sta() + + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid2, freq=2412) + dev[0].roam(bssid2) + dev[0].dump_monitor() + hapd2.wait_sta() + + dev[0].roam(bssid) + dev[0].dump_monitor() From e9db8b59c98f289f9ac10201771d51063af64424 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 17:56:20 +0300 Subject: [PATCH 0348/1105] wlantest: Use BSD compatible UDP header struct Signed-off-by: Jouni Malinen --- wlantest/wired.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wlantest/wired.c b/wlantest/wired.c index 653be337a..67ae8a9af 100644 --- a/wlantest/wired.c +++ b/wlantest/wired.c @@ -212,9 +212,9 @@ static void process_udp(struct wlantest *wt, u32 dst, u32 src, return; udp = (const struct udphdr *) data; /* TODO: check UDP checksum */ - sport = be_to_host16(udp->source); - dport = be_to_host16(udp->dest); - ulen = be_to_host16(udp->len); + sport = be_to_host16(udp->uh_sport); + dport = be_to_host16(udp->uh_dport); + ulen = be_to_host16(udp->uh_ulen); if (ulen > len) return; From e13f836dde5f0dea64d36b7caafbd5de0a581c3f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 17:56:59 +0300 Subject: [PATCH 0349/1105] wlantest: Comment out ICMP processing from OS X builds For now, allow this to be compiled without ICMP support. Signed-off-by: Jouni Malinen --- wlantest/rx_ip.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wlantest/rx_ip.c b/wlantest/rx_ip.c index 0e833ec6c..fdf80b7d7 100644 --- a/wlantest/rx_ip.c +++ b/wlantest/rx_ip.c @@ -14,6 +14,8 @@ #include "wlantest.h" +#ifndef __APPLE__ + static void ping_update(struct wlantest *wt, struct wlantest_sta *sta, int req, u32 src, u32 dst, u16 id, u16 seq) { @@ -95,6 +97,8 @@ static void rx_data_icmp(struct wlantest *wt, const u8 *bssid, ping_update(wt, sta, hdr->type == ICMP_ECHO, src, dst, id, seq); } +#endif /* __APPLE__ */ + static int hwsim_test_packet(const u8 *data, size_t len) { @@ -169,9 +173,11 @@ void rx_data_ip(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr, plen = len - 4 * ip->ip_hl; switch (ip->ip_p) { +#ifndef __APPLE__ case IPPROTO_ICMP: rx_data_icmp(wt, bssid, sta_addr, ip->ip_dst.s_addr, ip->ip_src.s_addr, payload, plen, peer_addr); break; +#endif /* __APPLE__ */ } } From c25dc978a6dbb0eb7ce2923d4912205701a44d87 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 17:57:32 +0300 Subject: [PATCH 0350/1105] wlantest: Comment out Linux packet socket from OS X build For now, allow wlantest to be built on OS X without support for live sniffer capturing. Signed-off-by: Jouni Malinen --- wlantest/monitor.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/wlantest/monitor.c b/wlantest/monitor.c index afcc3806f..f28708689 100644 --- a/wlantest/monitor.c +++ b/wlantest/monitor.c @@ -7,14 +7,36 @@ */ #include "utils/includes.h" +#ifndef __APPLE__ #include #include +#endif /* __APPLE__ */ #include "utils/common.h" #include "utils/eloop.h" #include "wlantest.h" +#ifdef __APPLE__ + +int monitor_init(struct wlantest *wt, const char *ifname) +{ + return -1; +} + + +int monitor_init_wired(struct wlantest *wt, const char *ifname) +{ + return -1; +} + + +void monitor_deinit(struct wlantest *wt) +{ +} + +#else /* __APPLE__ */ + static void monitor_read(int sock, void *eloop_ctx, void *sock_ctx) { struct wlantest *wt = eloop_ctx; @@ -146,3 +168,5 @@ void monitor_deinit(struct wlantest *wt) wt->monitor_wired = -1; } } + +#endif /* __APPLE__ */ From d4c3964117d5fe3a8c2b2f44c80ea807a3057ec3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 17:58:46 +0300 Subject: [PATCH 0351/1105] wlantest: Link without libwlantest The ar operations with embedded libraries were not exactly portable or strictly speaking necessary. Drop that library completely to make this more portable. Signed-off-by: Jouni Malinen --- wlantest/Makefile | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/wlantest/Makefile b/wlantest/Makefile index 0fdf3ff91..708d4525d 100644 --- a/wlantest/Makefile +++ b/wlantest/Makefile @@ -42,8 +42,8 @@ endif @$(E) " CC " $< -OBJS_lib += ../src/utils/libutils.a -OBJS_lib += ../src/crypto/libcrypto.a +OWN_LIBS += ../src/utils/libutils.a +OWN_LIBS += ../src/crypto/libcrypto.a CFLAGS += -DCONFIG_OCV CFLAGS += -DCONFIG_IEEE80211R @@ -98,37 +98,20 @@ TOBJS += gcmp.o $(MAKE) -C ../src/crypto -ifneq ($(CONFIG_SOLIB), yes) -LIBWLANTEST = libwlantest.a -libwlantest.a: $(OBJS_lib) - $(AR) crT libwlantest.a $(OBJS_lib) - $(RANLIB) libwlantest.a - -else -CFLAGS += -fPIC -DPIC -LDFLAGS += -shared - -LIBWLANTEST = libwlantest.so -libwlantest.so: $(OBJS_lib) - $(LDO) $(LDFLAGS) $(OBJS_lib) -o $(LIBWLANTEST) - -endif - - OBJS_cli = wlantest_cli.o -wlantest: $(OBJS) $(LIBWLANTEST) - $(LDO) $(LDFLAGS) -o wlantest $(OBJS) -L. -lwlantest $(LIBS) +wlantest: $(OBJS) $(OWN_LIBS) + $(LDO) $(LDFLAGS) -o wlantest $(OBJS) $(OWN_LIBS) $(LIBS) -wlantest_cli: $(OBJS_cli) $(LIBWLANTEST) - $(LDO) $(LDFLAGS) -o wlantest_cli $(OBJS_cli) -L. -lwlantest $(LIBS) +wlantest_cli: $(OBJS_cli) $(OWN_LIBS) + $(LDO) $(LDFLAGS) -o wlantest_cli $(OBJS_cli) $(OWN_LIBS) $(LIBS) -test_vectors: $(TOBJS) $(LIBWLANTEST) - $(LDO) $(LDFLAGS) -o test_vectors $(TOBJS) -L. -lwlantest $(LIBS) +test_vectors: $(TOBJS) $(OWN_LIBS) + $(LDO) $(LDFLAGS) -o test_vectors $(TOBJS) $(OWN_LIBS) $(LIBS) clean: $(MAKE) -C ../src clean - rm -f core *~ *.o *.d libwlantest.a libwlantest.so $(ALL) + rm -f core *~ *.o *.d $(ALL) -include $(OBJS:%.o=%.d) From d73bbae492a96c3a27ab7364b467e2ca18ae5573 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 17:59:57 +0300 Subject: [PATCH 0352/1105] wlantest: Do not include rt library for OS X builds That is not needed or available by default, so simply drop it from the build. Signed-off-by: Jouni Malinen --- wlantest/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wlantest/Makefile b/wlantest/Makefile index 708d4525d..22ea646c0 100644 --- a/wlantest/Makefile +++ b/wlantest/Makefile @@ -2,6 +2,8 @@ ALL=wlantest wlantest_cli test_vectors all: $(ALL) +UNAME := $(shell uname -s) + ifndef CC CC=gcc endif @@ -19,8 +21,10 @@ CFLAGS += -I. CFLAGS += -I../src CFLAGS += -I../src/utils +ifneq ($(UNAME),Darwin) # glibc < 2.17 needs -lrt for clock_gettime() LIBS += -lrt +endif ifndef LDO LDO=$(CC) From 63ccec5433c6eb4ece5e2733dfbd6e4b6e3802fe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 19:38:41 +0300 Subject: [PATCH 0353/1105] tests: Remove test-x509 This has been obsoleted by tests/fuzzing/x509. Signed-off-by: Jouni Malinen --- tests/Makefile | 5 +---- tests/test-x509.c | 47 ----------------------------------------------- 2 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 tests/test-x509.c diff --git a/tests/Makefile b/tests/Makefile index ee07921a4..0817c9a27 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,7 +1,7 @@ TESTS=test-base64 test-md4 test-milenage \ test-rsa-sig-ver \ test-sha1 \ - test-sha256 test-aes test-asn1 test-x509 test-x509v3 test-list test-rc4 + test-sha256 test-aes test-asn1 test-x509v3 test-list test-rc4 all: $(TESTS) @@ -148,9 +148,6 @@ test-sha256: test-sha256.o $(LIBS) test-tls: test-tls.o $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-x509: test-x509.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) - test-x509v3: test-x509v3.o $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) diff --git a/tests/test-x509.c b/tests/test-x509.c deleted file mode 100644 index 055446ecc..000000000 --- a/tests/test-x509.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Testing tool for X.509v3 routines - * Copyright (c) 2006-2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "tls/x509v3.h" - - -#ifdef TEST_LIBFUZZER -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - struct x509_certificate *cert; - - cert = x509_certificate_parse(data, size); - x509_certificate_free(cert); - return 0; -} -#else /* TEST_LIBFUZZER */ -int main(int argc, char *argv[]) -{ - FILE *f; - u8 buf[3000]; - size_t len; - struct x509_certificate *cert; - - wpa_debug_level = 0; - - f = fopen(argv[1], "rb"); - if (f == NULL) - return -1; - len = fread(buf, 1, sizeof(buf), f); - fclose(f); - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) - printf("Failed to parse X.509 certificate\n"); - x509_certificate_free(cert); - - return 0; -} -#endif /* TEST_LIBFUZZER */ From eac6eb70248be41671fcb1700df14fa148e8d221 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 19:59:47 +0300 Subject: [PATCH 0354/1105] X509: Use unique debug prints for unused bits entries This makes it easier to understand which X.509 BIT STRING value has the unused bits. Signed-off-by: Jouni Malinen --- src/tls/x509v3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tls/x509v3.c b/src/tls/x509v3.c index 5c8ac5676..d2e685cb3 100644 --- a/src/tls/x509v3.c +++ b/src/tls/x509v3.c @@ -264,7 +264,8 @@ static int x509_parse_public_key(const u8 *buf, size_t len, return -1; pos = hdr.payload; if (*pos) { - wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", + wpa_printf(MSG_DEBUG, + "X509: BITSTRING (subjectPublicKey) - %d unused bits", *pos); /* * TODO: should this be rejected? X.509 certificates are @@ -1851,7 +1852,8 @@ struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) } pos = hdr.payload; if (*pos) { - wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", + wpa_printf(MSG_DEBUG, + "X509: BITSTRING (signatureValue) - %d unused bits", *pos); /* PKCS #1 v1.5 10.2.1: * It is an error if the length in bits of the signature S is From f8d8b7d92d654cc0899d885b1065e1d3c6fd4fc0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 20:12:59 +0300 Subject: [PATCH 0355/1105] tests: Enable dumping of key information in test-x509v3 Signed-off-by: Jouni Malinen --- tests/test-x509v3.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test-x509v3.c b/tests/test-x509v3.c index bfb069871..06cd6eaab 100644 --- a/tests/test-x509v3.c +++ b/tests/test-x509v3.c @@ -21,6 +21,7 @@ int main(int argc, char *argv[]) int i, reason; wpa_debug_level = 0; + wpa_debug_show_keys = 1; if (argc < 3 || strcmp(argv[1], "-v") != 0) { printf("usage: test_x509v3 -v ..\n"); From 24a6bca7046c0fdf6fd7d2f20ff3207642622c95 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 5 Apr 2020 20:13:26 +0300 Subject: [PATCH 0356/1105] PKCS#1: Debug dump invalid Signature EB Signed-off-by: Jouni Malinen --- src/tls/pkcs1.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tls/pkcs1.c b/src/tls/pkcs1.c index 141ac50df..654c01b76 100644 --- a/src/tls/pkcs1.c +++ b/src/tls/pkcs1.c @@ -157,6 +157,7 @@ int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, plain[0] != 0x00 || plain[1] != 0x01) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure"); + wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len); return -1; } @@ -165,6 +166,7 @@ int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, if (plain[2] != 0xff) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " "PS (BT=01)"); + wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len); return -1; } while (pos < plain + len && *pos == 0xff) @@ -174,12 +176,14 @@ int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " "padding"); + wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len); return -1; } if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure (2)"); + wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len); return -1; } pos++; From 7a510a97ba497c29d2382cc8310c4f69bded3972 Mon Sep 17 00:00:00 2001 From: Edayilliam Jayadev Date: Fri, 27 Mar 2020 13:50:01 +0530 Subject: [PATCH 0357/1105] Add an attribute for secondary 80 MHz span of agile spectral scan Add an attribute QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 for describing the secondary 80 MHz span of agile spectral scan. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 02aa9fbcc..bcb693946 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -5467,8 +5467,12 @@ enum qca_wlan_vendor_attr_spectral_scan { * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE * Center frequency (in MHz) of the span of interest or * for convenience, center frequency (in MHz) of any channel - * in the span of interest. If agile spectral scan is initiated - * without setting a valid frequency it returns the error code + * in the span of interest. For 80+80 MHz agile spectral scan + * request it represents center frequency (in MHz) of the primary + * 80 MHz span or for convenience, center frequency (in MHz) of any + * channel in the primary 80 MHz span. If agile spectral scan is + * initiated without setting a valid frequency it returns the + * error code * (QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED). * u32 attribute. */ @@ -5495,6 +5499,20 @@ enum qca_wlan_vendor_attr_spectral_scan { * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG = 28, + /* This specifies the frequency span over which spectral scan would be + * carried out. Its value depends on the value of + * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE and the relation is as + * follows. + * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL + * Not applicable. Spectral scan would happen in the operating span. + * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE + * This attribute is applicable only for agile spectral scan + * requests in 80+80 MHz mode. It represents center frequency (in + * MHz) of the secondary 80 MHz span or for convenience, center + * frequency (in MHz) of any channel in the secondary 80 MHz span. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 = 29, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX = From af0178c75b05640b8e14cbba5168f565013fcabf Mon Sep 17 00:00:00 2001 From: Edayilliam Jayadev Date: Fri, 27 Mar 2020 11:43:43 +0530 Subject: [PATCH 0358/1105] Add vendor attributes indicating number of spectral detectors Add per bandwidth capability attributes which indicate the number of spectral detectors used. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index bcb693946..e599b8d7e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -5603,6 +5603,26 @@ enum qca_wlan_vendor_attr_spectral_cap { * for 80+80 MHz mode. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_80_80 = 13, + /* Number of spectral detectors used for scan in 20 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_20_MHZ = 14, + /* Number of spectral detectors used for scan in 40 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_40_MHZ = 15, + /* Number of spectral detectors used for scan in 80 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80_MHZ = 16, + /* Number of spectral detectors used for scan in 160 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_160_MHZ = 17, + /* Number of spectral detectors used for scan in 80+80 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ = 18, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX = From 2012a26d0f7d1089b17f958bf3dec4cebf014a03 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 14 Apr 2020 16:36:07 +0300 Subject: [PATCH 0359/1105] tests: AP may discard FT ReassocReq in ap_ft_sae_h2e_downgrade_attack This is in preparation for a hostapd implementation change on how to address the unexpected RSNXE Used field value in FTE during FT reassociation. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index a7a71711a..abc9431e8 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -1080,10 +1080,17 @@ def test_ap_ft_sae_h2e_downgrade_attack(dev, apdev): force_initial_conn_to_first_ap=True, return_after_initial=True) dev[0].scan_for_bss(hapd1.own_addr(), freq="2412") - dev[0].request("ROAM " + hapd1.own_addr()) - ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10) - if ev is None: - raise Exception("Association not rejected") + if "OK" not in dev[0].request("ROAM " + hapd1.own_addr()): + raise Exception("ROAM command failed") + # The target AP is expected to discard Reassociation Response frame due + # to RSNXE Used mismatch. This will result in roaming timeout and + # returning back to the old AP. + ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev and "CTRL-EVENT-ASSOC-REJECT" in ev: + pass + elif ev and hapd1.own_addr() in ev: + raise Exception("Roaming succeeded unexpectedly") finally: dev[0].set("sae_pwe", "0") From 5344af7d22ac8c3171592b6afd6a5aaa8f023cb1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 14 Apr 2020 13:46:00 +0300 Subject: [PATCH 0360/1105] FT: Discard ReassocReq with mismatching RSNXE Used value Discard the FT Reassociation Request frame instead of rejecting it (i.e., do not send Reassociation Response frame) if RSNXE Used is indicated in FTE, but no RSNXE is included even though the AP is advertising RSNXE. While there is not really much of a difference between discarding and rejecting the frame, this discarding behavior is what the standard says for this type of an error case. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 11 +++++++---- src/ap/ieee802_11.c | 12 +++++++----- src/ap/wpa_auth.h | 2 +- src/ap/wpa_auth_ft.c | 4 ++-- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 559bb87c2..524a15132 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -117,7 +117,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; u8 *p = buf; u16 reason = WLAN_REASON_UNSPECIFIED; - u16 status = WLAN_STATUS_SUCCESS; + int status = WLAN_STATUS_SUCCESS; const u8 *p2p_dev_addr = NULL; if (addr == NULL) { @@ -606,17 +606,19 @@ skip_wpa_check: wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE && elems.owe_dh) { u8 *npos; + u16 ret_status; npos = owe_assoc_req_process(hapd, sta, elems.owe_dh, elems.owe_dh_len, p, sizeof(buf) - (p - buf), - &status); + &ret_status); + status = ret_status; if (npos) p = npos; if (!npos && status == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { - hostapd_sta_assoc(hapd, addr, reassoc, status, buf, + hostapd_sta_assoc(hapd, addr, reassoc, ret_status, buf, p - buf); return 0; } @@ -709,7 +711,8 @@ skip_wpa_check: fail: #ifdef CONFIG_IEEE80211R_AP - hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); + if (status >= 0) + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); #endif /* CONFIG_IEEE80211R_AP */ hostapd_drv_sta_disassoc(hapd, sta->addr, reason); ap_free_sta(hapd, sta); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 2a5f6e5ec..28ac7aa4b 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3104,11 +3104,11 @@ end: #endif /* CONFIG_OWE */ -static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, +static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, const u8 *ies, size_t ies_len, int reassoc) { struct ieee802_11_elems elems; - u16 resp; + int resp; const u8 *wpa_ie; size_t wpa_ie_len; const u8 *p2p_dev_addr = NULL; @@ -4075,7 +4075,8 @@ static void handle_assoc(struct hostapd_data *hapd, int reassoc, int rssi) { u16 capab_info, listen_interval, seq_ctrl, fc; - u16 resp = WLAN_STATUS_SUCCESS, reply_res; + int resp = WLAN_STATUS_SUCCESS; + u16 reply_res; const u8 *pos; int left, i; struct sta_info *sta; @@ -4449,8 +4450,9 @@ static void handle_assoc(struct hostapd_data *hapd, } #endif /* CONFIG_FILS */ - reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos, - left, rssi, omit_rsnxe); + if (resp >= 0) + reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, + pos, left, rssi, omit_rsnxe); os_free(tmp); /* diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index fafabe9c5..c12221194 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -441,7 +441,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, u16 auth_transaction, u16 resp, const u8 *ies, size_t ies_len), void *ctx); -u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, +int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len); int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len); int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 4ca18ab6b..30e801a3a 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -3247,7 +3247,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, } -u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, +int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len) { struct wpa_ft_ies parse; @@ -3445,7 +3445,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, !parse.rsnxe) { wpa_printf(MSG_INFO, "FT: FTE indicated that STA uses RSNXE, but RSNXE was not included"); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + return -1; /* discard request */ } #ifdef CONFIG_OCV From b2d8dc59f4cba73544e17dfc1ff2f0c0ef73b206 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 14 Apr 2020 13:48:43 +0300 Subject: [PATCH 0361/1105] FT: Testing override for RSNXE Used subfield in FTE Allow wpa_supplicant to be requested to override the RSNXE Used subfield in FT reassociation case for testing purposes with "SET ft_rsnxe_used <0/1/2>" where 0 = no override, 1 = override to 1, and 2 = override to 0. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 5 +++++ src/rsn_supp/wpa.h | 1 + src/rsn_supp/wpa_ft.c | 7 +++++++ src/rsn_supp/wpa_i.h | 1 + wpa_supplicant/ctrl_iface.c | 3 +++ wpa_supplicant/wpa_supplicant.c | 4 ++++ wpa_supplicant/wpa_supplicant_i.h | 1 + 7 files changed, 22 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 1c8966422..60084c6ab 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3252,6 +3252,11 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_USE_EXT_KEY_ID: sm->use_ext_key_id = value; break; +#ifdef CONFIG_TESTING_OPTIONS + case WPA_PARAM_FT_RSNXE_USED: + sm->ft_rsnxe_used = value; + break; +#endif /* CONFIG_TESTING_OPTIONS */ default: break; } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 796f39203..0986c6c61 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -106,6 +106,7 @@ enum wpa_sm_conf_params { WPA_PARAM_DENY_PTK0_REKEY, WPA_PARAM_EXT_KEY_ID, WPA_PARAM_USE_EXT_KEY_ID, + WPA_PARAM_FT_RSNXE_USED, }; struct rsn_supp_config { diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 203a61c78..3e51cf2a1 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -305,6 +305,13 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, ftie_len = pos++; rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && anonce && (sm->sae_pwe == 1 || sm->sae_pwe == 2); +#ifdef CONFIG_TESTING_OPTIONS + if (anonce && sm->ft_rsnxe_used) { + rsnxe_used = sm->ft_rsnxe_used == 1; + wpa_printf(MSG_DEBUG, "TESTING: FT: Force RSNXE Used %d", + rsnxe_used); + } +#endif /* CONFIG_TESTING_OPTIONS */ if (wpa_key_mgmt_sha384(sm->key_mgmt)) { struct rsn_ftie_sha384 *ftie; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 1ad75dcfa..497d12885 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -153,6 +153,7 @@ struct wpa_sm { #ifdef CONFIG_TESTING_OPTIONS struct wpabuf *test_assoc_ie; + int ft_rsnxe_used; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_FILS diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 7301d50fc..ae7cc8f6a 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -747,6 +747,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, break; pos++; } + } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) { + wpa_s->ft_rsnxe_used = atoi(value); } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) { wpabuf_free(wpa_s->rsne_override_eapol); if (os_strcmp(value, "NULL") == 0) @@ -8184,6 +8186,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->disable_sa_query = 0; wpa_s->testing_resend_assoc = 0; wpa_s->ignore_sae_h2e_only = 0; + wpa_s->ft_rsnxe_used = 0; wpa_s->reject_btm_req_reason = 0; wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL); os_free(wpa_s->get_pref_freq_list_override); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 2cacb202d..e29ed83e1 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1639,6 +1639,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, if (ssid->sae_password_id && sae_pwe != 3) sae_pwe = 1; wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe); +#ifdef CONFIG_TESTING_OPTIONS + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED, + wpa_s->ft_rsnxe_used); +#endif /* CONFIG_TESTING_OPTIONS */ /* Extended Key ID is only supported in infrastructure BSS so far */ if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id && diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index e0de59fa2..997e5f642 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1135,6 +1135,7 @@ struct wpa_supplicant { unsigned int disable_sa_query:1; unsigned int testing_resend_assoc:1; unsigned int ignore_sae_h2e_only:1; + int ft_rsnxe_used; struct wpabuf *sae_commit_override; enum wpa_alg last_tk_alg; u8 last_tk_addr[ETH_ALEN]; From 6ac48fd9e8aa9feea3d6a8b7918e133030f17b9b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 14 Apr 2020 13:50:53 +0300 Subject: [PATCH 0362/1105] tests: FT-SAE AP and unexpected RSNXE Used in ReassocReq Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index abc9431e8..2b1d925e3 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -1213,6 +1213,25 @@ def test_ap_ft_sae_h2e_rsnxe_mismatch(dev, apdev): finally: dev[0].set("sae_pwe", "0") +def test_ap_ft_sae_rsnxe_used_mismatch(dev, apdev): + """FT-SAE AP and unexpected RSNXE Used in ReassocReq""" + try: + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2") + dev[0].set("sae_pwe", "0") + dev[0].set("ft_rsnxe_used", "1") + next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", + sae=True, return_after_initial=True) + if "OK" not in dev[0].request("ROAM " + next): + raise Exception("ROAM command failed") + # The target AP is expected to discard Reassociation Response frame due + # to RSNXE Used mismatch. This will result in roaming timeout and + # returning back to the old AP. + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5) + if ev and next in ev: + raise Exception("Roaming succeeded unexpectedly") + finally: + dev[0].set("sae_pwe", "0") + def test_ap_ft_sae_pw_id(dev, apdev): """FT-SAE with Password Identifier""" if "SAE" not in dev[0].get_capability("auth_alg"): From 9b222b6130affccd3b88cc1673a17f05d02d59bc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 14 Apr 2020 19:23:09 +0300 Subject: [PATCH 0363/1105] nl80211: Remove unnecessary inclusion of l2_packet.h The only l2_packet use within this file was removed by commit d12dab4c6f9e ("nl80211: Use non-receiving socket for EAPOL TX"). Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 3b7c31c89..21f5000b0 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -30,7 +30,6 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/wpa_common.h" -#include "l2_packet/l2_packet.h" #include "netlink.h" #include "linux_defines.h" #include "linux_ioctl.h" From 7ad6016e191db9417ff57eae498f2ec7df70c739 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 15 Apr 2020 13:55:28 +0300 Subject: [PATCH 0364/1105] tests: sigma_dut controlled FT protocol with RSNXE Used mismatch Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 32b0bf433..e934bc958 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4229,3 +4229,76 @@ def test_sigma_dut_ap_transition_disable(dev, apdev, params): sigma_dut_cmd_check("ap_reset_default") finally: stop_sigma_dut(sigma) + +def test_sigma_dut_ft_rsnxe_used_mismatch(dev, apdev): + """sigma_dut controlled FT protocol with RSNXE Used mismatch""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE FT-SAE' + params["ieee80211w"] = "2" + params['sae_password'] = "hello" + params['sae_pwe'] = "2" + params['mobility_domain'] = 'aabb' + bssid = apdev[0]['bssid'].replace(':', '') + params['nas_identifier'] = bssid + '.nas.example.com' + params['r1_key_holder'] = bssid + params['pmk_r1_push'] = '0' + params['r0kh'] = 'ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff' + params['r1kh'] = '00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff' + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + sigma_dut_cmd_check("sta_reset_default,interface,%s" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,AKMSuiteType,8;9" % (ifname, "test-sae", "hello")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + sigma_dut_wait_connected(ifname) + dev[0].dump_monitor() + + bssid2 = apdev[1]['bssid'].replace(':', '') + params['nas_identifier'] = bssid2 + '.nas.example.com' + params['r1_key_holder'] = bssid2 + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + sigma_dut_cmd_check("sta_reassoc,interface,%s,Channel,1,bssid,%s" % (ifname, bssid2)) + count = 0 + for i in range(5): + ev = dev[0].wait_event(["Trying to associate", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev is None: + raise Exception("Connection timed out") + if "CTRL-EVENT-CONNECTED" in ev: + break + count += 1 + dev[0].dump_monitor() + if count != 1: + raise Exception("Unexpected number of association attempts for the first FT protocol exchange (expecting success)") + + sigma_dut_cmd_check("sta_set_rfeature,interface,%s,prog,WPA3,ReassocReq_RSNXE_Used,1" % ifname) + sigma_dut_cmd_check("sta_reassoc,interface,%s,Channel,1,bssid,%s" % (ifname, bssid)) + count = 0 + for i in range(5): + ev = dev[0].wait_event(["Trying to associate", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev is None: + raise Exception("Connection timed out") + if "CTRL-EVENT-CONNECTED" in ev: + break + count += 1 + dev[0].dump_monitor() + if count != 2: + raise Exception("Unexpected number of association attempts for the second FT protocol exchange (expecting failure)") + + sigma_dut_cmd_check("sta_disconnect,interface," + ifname) + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) From a6c689d35482cd15bf14458326903145fa0c4315 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 16 Apr 2020 23:22:57 +0300 Subject: [PATCH 0365/1105] FT: Testing override for RSNXE Used subfield in FTE (AP) Allow hostapd to be requested to override the RSNXE Used subfield in FT reassociation case for testing purposes with "ft_rsnxe_used=<0/1/2>" where 0 = no override, 1 = override to 1, and 2 = override to 0. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 ++ hostapd/ctrl_iface.c | 6 ++++++ src/ap/ap_config.h | 1 + src/ap/wpa_auth.c | 7 +++++++ src/ap/wpa_auth.h | 2 ++ src/ap/wpa_auth_ft.c | 7 +++++++ src/ap/wpa_auth_glue.c | 1 + 7 files changed, 26 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 1d8c03973..cc1855dcd 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4215,6 +4215,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->no_beacon_rsnxe = atoi(pos); } else if (os_strcmp(buf, "skip_prune_assoc") == 0) { bss->skip_prune_assoc = atoi(pos); + } else if (os_strcmp(buf, "ft_rsnxe_used") == 0) { + bss->ft_rsnxe_used = atoi(pos); #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_SAE } else if (os_strcmp(buf, "sae_password") == 0) { diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index d90b5dc8f..c5b258bf1 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1477,6 +1477,12 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) if (hapd->started) hostapd_setup_sae_pt(hapd->conf); } + +#ifdef CONFIG_TESTING_OPTIONS + if (os_strcmp(cmd, "ft_rsnxe_used") == 0) + wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth, + hapd->conf->ft_rsnxe_used); +#endif /* CONFIG_TESTING_OPTIONS */ } return ret; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 2a0bf0763..0503400b5 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -686,6 +686,7 @@ struct hostapd_bss_config { struct wpabuf *igtk_rsc_override; int no_beacon_rsnxe; int skip_prune_assoc; + int ft_rsnxe_used; #endif /* CONFIG_TESTING_OPTIONS */ #define MESH_ENABLED BIT(0) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 070236a89..8ecb17318 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -5459,4 +5459,11 @@ int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth) return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL); } + +void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val) +{ + if (wpa_auth) + wpa_auth->conf.ft_rsnxe_used = val; +} + #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index c12221194..1ea067bcf 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -238,6 +238,7 @@ struct wpa_auth_config { unsigned int rsnxe_override_ft_set:1; unsigned int gtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1; + int ft_rsnxe_used; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_P2P u8 ip_addr_go[4]; @@ -522,5 +523,6 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, void *ctx1, void *ctx2); int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth); void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm); +void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val); #endif /* WPA_AUTH_H */ diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 30e801a3a..4b17da7a4 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2647,6 +2647,13 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, } rsnxe_used = (auth_alg == WLAN_AUTH_FT) && (conf->sae_pwe == 1 || conf->sae_pwe == 2); +#ifdef CONFIG_TESTING_OPTIONS + if (sm->wpa_auth->conf.ft_rsnxe_used) { + rsnxe_used = sm->wpa_auth->conf.ft_rsnxe_used == 1; + wpa_printf(MSG_DEBUG, "TESTING: FT: Force RSNXE Used %d", + rsnxe_used); + } +#endif /* CONFIG_TESTING_OPTIONS */ res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len, anonce, snonce, pos, end - pos, subelem, subelem_len, rsnxe_used); diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 79880e478..058b34ca3 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -174,6 +174,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wpabuf_len(conf->igtk_rsc_override)); wconf->igtk_rsc_override_set = 1; } + wconf->ft_rsnxe_used = conf->ft_rsnxe_used; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_P2P os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); From b6545522472012b4630a73448867bfd853f885fb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 16 Apr 2020 23:24:06 +0300 Subject: [PATCH 0366/1105] tests: FT-SAE AP and unexpected RSNXE Used in ReassocResp Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 2b1d925e3..dbc02d026 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -996,7 +996,7 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, rsne_override=None, rsnxe_override=None, no_beacon_rsnxe2=False, ext_key_id=False, - skip_prune_assoc=False): + skip_prune_assoc=False, ft_rsnxe_used=False): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") ssid = "test-ft" @@ -1016,6 +1016,8 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['extended_key_id'] = '1' if skip_prune_assoc: params['skip_prune_assoc'] = '1' + if ft_rsnxe_used: + params['ft_rsnxe_used'] = '1' hapd0 = hostapd.add_ap(apdev[0], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['wpa_key_mgmt'] = "FT-SAE" @@ -1033,6 +1035,8 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, params['extended_key_id'] = '1' if skip_prune_assoc: params['skip_prune_assoc'] = '1' + if ft_rsnxe_used: + params['ft_rsnxe_used'] = '1' hapd1 = hostapd.add_ap(apdev[1], params) key_mgmt = hapd1.get_config()['key_mgmt'] if key_mgmt.split(' ')[0] != "FT-SAE": @@ -1223,7 +1227,7 @@ def test_ap_ft_sae_rsnxe_used_mismatch(dev, apdev): sae=True, return_after_initial=True) if "OK" not in dev[0].request("ROAM " + next): raise Exception("ROAM command failed") - # The target AP is expected to discard Reassociation Response frame due + # The target AP is expected to discard Reassociation Request frame due # to RSNXE Used mismatch. This will result in roaming timeout and # returning back to the old AP. ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5) @@ -1232,6 +1236,33 @@ def test_ap_ft_sae_rsnxe_used_mismatch(dev, apdev): finally: dev[0].set("sae_pwe", "0") +def test_ap_ft_sae_rsnxe_used_mismatch2(dev, apdev): + """FT-SAE AP and unexpected RSNXE Used in ReassocResp""" + try: + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0", + ft_rsnxe_used=True) + dev[0].set("sae_pwe", "2") + next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", + sae=True, return_after_initial=True) + if "OK" not in dev[0].request("ROAM " + next): + raise Exception("ROAM command failed") + # The STA is expected to discard Reassociation Response frame due to + # RSNXE Used mismatch. This will result in returning back to the old AP. + ev = dev[0].wait_disconnected() + if next not in ev: + raise Exception("Unexpected disconnection BSSID: " + ev) + if "reason=13 locally_generated=1" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + ev = dev[0].wait_connected() + if next in ev: + raise Exception("Roaming succeeded unexpectedly") + + hapd0.set("ft_rsnxe_used", "0") + hapd1.set("ft_rsnxe_used", "0") + dev[0].roam(next); + finally: + dev[0].set("sae_pwe", "0") + def test_ap_ft_sae_pw_id(dev, apdev): """FT-SAE with Password Identifier""" if "SAE" not in dev[0].get_capability("auth_alg"): From 11bd6ea60e729741a23d9ecd475d630c4303854a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 16 Apr 2020 23:58:36 +0300 Subject: [PATCH 0367/1105] tests: sigma_dut controlled AP with FT and RSNXE Used mismatch Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index e934bc958..a115da12a 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4302,3 +4302,37 @@ def test_sigma_dut_ft_rsnxe_used_mismatch(dev, apdev): sigma_dut_cmd_check("sta_reset_default,interface," + ifname) finally: stop_sigma_dut(sigma) + +def test_sigma_dut_ap_ft_rsnxe_used_mismatch(dev, apdev, params): + """sigma_dut controlled AP with FT and RSNXE Used mismatch""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng,DOMAIN,aabb") + sigma_dut_cmd_check("ap_set_security,NAME,AP,AKMSuiteType,8;9,SAEPasswords,hello,PMF,Required") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "wb") as f2: + f2.write(f.read()) + + dev[0].connect("test-sae", key_mgmt="FT-SAE", sae_password="hello", + ieee80211w="2", scan_freq="2412") + + sigma_dut_cmd_check("ap_set_rfeature,NAME,AP,type,WPA3,ReassocResp_RSNXE_Used,1") + # This would need to be followed by FT protocol roaming test, but + # that is not currently convenient to implement, so for now, this + # test is based on manual inspection of hostapd getting configured + # properly. + + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) From 6b1c590ebb87bd4ddd2930feb621f463197d1125 Mon Sep 17 00:00:00 2001 From: Disha Das Date: Thu, 9 Apr 2020 09:42:21 +0530 Subject: [PATCH 0368/1105] Allow TKIP support to be removed from build Add a build flag CONFIG_NO_TKIP=y to remove all TKIP functionality from hostapd and wpa_supplicant builds. This disables use of TKIP as both the pairwise and group cipher. The end result does not interoperate with a WPA(v1)-only device or WPA+WPA2 mixed modes. Signed-off-by: Disha Das --- hostapd/Android.mk | 4 +++ hostapd/Makefile | 4 +++ hostapd/defconfig | 7 ++++ src/ap/ap_config.c | 5 +++ src/ap/wps_hostapd.c | 44 +++++++++++++++++++++++++ src/common/wpa_common.c | 9 +++++ src/common/wpa_common.h | 10 ++++++ src/wps/wps_attr_build.c | 6 ++++ src/wps/wps_enrollee.c | 11 +++++++ src/wps/wps_registrar.c | 4 +++ wpa_supplicant/Android.mk | 4 +++ wpa_supplicant/Makefile | 4 +++ wpa_supplicant/config_ssid.h | 5 +++ wpa_supplicant/ctrl_iface.c | 14 ++++++++ wpa_supplicant/dbus/dbus_new.c | 4 +++ wpa_supplicant/dbus/dbus_new_handlers.c | 17 +++++++++- wpa_supplicant/defconfig | 9 +++++ wpa_supplicant/wps_supplicant.c | 5 +++ 18 files changed, 165 insertions(+), 1 deletion(-) diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 0f0556501..d47b64f4e 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -314,6 +314,10 @@ ifdef CONFIG_WEP L_CFLAGS += -DCONFIG_WEP endif +ifdef CONFIG_NO_TKIP +L_CFLAGS += -DCONFIG_NO_TKIP +endif + include $(LOCAL_PATH)/src/drivers/drivers.mk diff --git a/hostapd/Makefile b/hostapd/Makefile index 326e91b8c..9475f2e84 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -1243,6 +1243,10 @@ ifdef CONFIG_WEP CFLAGS += -DCONFIG_WEP endif +ifdef CONFIG_NO_TKIP +CFLAGS += -DCONFIG_NO_TKIP +endif + ALL=hostapd hostapd_cli all: verify_config $(ALL) diff --git a/hostapd/defconfig b/hostapd/defconfig index 5133db26b..64f03bd84 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -388,3 +388,10 @@ CONFIG_IPV6=y # release under this optional build parameter. This functionality is subject to # be completely removed in a future release. #CONFIG_WEP=y + +# Remove all TKIP functionality +# TKIP is an old cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used anymore. For now, the default hostapd +# build includes this to allow mixed mode WPA+WPA2 networks to be enabled, but +# that functionality is subject to be removed in the future. +#CONFIG_NO_TKIP=y diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 5bf4502b0..35a32a130 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -74,8 +74,13 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) bss->wpa_disable_eapol_key_retries = DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES; bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; +#ifdef CONFIG_NO_TKIP + bss->wpa_pairwise = WPA_CIPHER_CCMP; + bss->wpa_group = WPA_CIPHER_CCMP; +#else /* CONFIG_NO_TKIP */ bss->wpa_pairwise = WPA_CIPHER_TKIP; bss->wpa_group = WPA_CIPHER_TKIP; +#endif /* CONFIG_NO_TKIP */ bss->rsn_pairwise = 0; bss->max_num_sta = MAX_STA_COUNT; diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 1d77b946e..dc8aa8f65 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -364,6 +364,13 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, bss->ssid.ssid_set = 1; } +#ifdef CONFIG_NO_TKIP + if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | + WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) + bss->wpa = 2; + else + bss->wpa = 0; +#else /* CONFIG_NO_TKIP */ if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) bss->wpa = 3; @@ -373,6 +380,7 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, bss->wpa = 1; else bss->wpa = 0; +#endif /* CONFIG_NO_TKIP */ if (bss->wpa) { if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) @@ -387,8 +395,10 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, else bss->wpa_pairwise |= WPA_CIPHER_CCMP; } +#ifndef CONFIG_NO_TKIP if (cred->encr_type & WPS_ENCR_TKIP) bss->wpa_pairwise |= WPA_CIPHER_TKIP; +#endif /* CONFIG_NO_TKIP */ bss->rsn_pairwise = bss->wpa_pairwise; bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, @@ -559,6 +569,13 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) fprintf(nconf, "\n"); } +#ifdef CONFIG_NO_TKIP + if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | + WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) + wpa = 2; + else + wpa = 0; +#else /* CONFIG_NO_TKIP */ if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) wpa = 3; @@ -568,6 +585,7 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) wpa = 1; else wpa = 0; +#endif /* CONFIG_NO_TKIP */ if (wpa) { char *prefix; @@ -611,9 +629,11 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) prefix = " "; } +#ifndef CONFIG_NO_TKIP if (cred->encr_type & WPS_ENCR_TKIP) { fprintf(nconf, "%sTKIP", prefix); } +#endif /* CONFIG_NO_TKIP */ fprintf(nconf, "\n"); if (cred->key_len >= 8 && cred->key_len < 64) { @@ -1160,12 +1180,24 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->encr_types_rsn |= WPS_ENCR_AES; } if (conf->rsn_pairwise & WPA_CIPHER_TKIP) { +#ifdef CONFIG_NO_TKIP + wpa_printf(MSG_INFO, "WPS: TKIP not supported"); + goto fail; +#else /* CONFIG_NO_TKIP */ wps->encr_types |= WPS_ENCR_TKIP; wps->encr_types_rsn |= WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ } } if (conf->wpa & WPA_PROTO_WPA) { +#ifdef CONFIG_NO_TKIP + if (!(conf->wpa & WPA_PROTO_RSN)) { + wpa_printf(MSG_INFO, "WPS: WPA(v1) not supported"); + goto fail; + } + conf->wpa &= ~WPA_PROTO_WPA; +#else /* CONFIG_NO_TKIP */ if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) wps->auth_types |= WPS_AUTH_WPAPSK; if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) @@ -1179,6 +1211,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->encr_types |= WPS_ENCR_TKIP; wps->encr_types_wpa |= WPS_ENCR_TKIP; } +#endif /* CONFIG_NO_TKIP */ } if (conf->ssid.security_policy == SECURITY_PLAINTEXT) { @@ -1218,10 +1251,17 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->ap_encr_type = wps->encr_types; if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) { /* Override parameters to enable security by default */ +#ifdef CONFIG_NO_TKIP + wps->auth_types = WPS_AUTH_WPA2PSK; + wps->encr_types = WPS_ENCR_AES; + wps->encr_types_rsn = WPS_ENCR_AES; + wps->encr_types_wpa = WPS_ENCR_AES; +#else /* CONFIG_NO_TKIP */ wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; wps->encr_types_rsn = WPS_ENCR_AES | WPS_ENCR_TKIP; wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ } if ((hapd->conf->multi_ap & FRONTHAUL_BSS) && @@ -1801,8 +1841,10 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid, if (os_strncmp(auth, "OPEN", 4) == 0) cred.auth_type = WPS_AUTH_OPEN; +#ifndef CONFIG_NO_TKIP else if (os_strncmp(auth, "WPAPSK", 6) == 0) cred.auth_type = WPS_AUTH_WPAPSK; +#endif /* CONFIG_NO_TKIP */ else if (os_strncmp(auth, "WPA2PSK", 7) == 0) cred.auth_type = WPS_AUTH_WPA2PSK; else @@ -1811,8 +1853,10 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid, if (encr) { if (os_strncmp(encr, "NONE", 4) == 0) cred.encr_type = WPS_ENCR_NONE; +#ifndef CONFIG_NO_TKIP else if (os_strncmp(encr, "TKIP", 4) == 0) cred.encr_type = WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ else if (os_strncmp(encr, "CCMP", 4) == 0) cred.encr_type = WPS_ENCR_AES; else diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 128474302..46b647bcd 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2319,11 +2319,18 @@ enum wpa_alg wpa_cipher_to_alg(int cipher) int wpa_cipher_valid_pairwise(int cipher) { +#ifdef CONFIG_NO_TKIP + return cipher == WPA_CIPHER_CCMP_256 || + cipher == WPA_CIPHER_GCMP_256 || + cipher == WPA_CIPHER_CCMP || + cipher == WPA_CIPHER_GCMP; +#else /* CONFIG_NO_TKIP */ return cipher == WPA_CIPHER_CCMP_256 || cipher == WPA_CIPHER_GCMP_256 || cipher == WPA_CIPHER_CCMP || cipher == WPA_CIPHER_GCMP || cipher == WPA_CIPHER_TKIP; +#endif /* CONFIG_NO_TKIP */ } @@ -2476,8 +2483,10 @@ int wpa_parse_cipher(const char *value) val |= WPA_CIPHER_CCMP; else if (os_strcmp(start, "GCMP") == 0) val |= WPA_CIPHER_GCMP; +#ifndef CONFIG_NO_TKIP else if (os_strcmp(start, "TKIP") == 0) val |= WPA_CIPHER_TKIP; +#endif /* CONFIG_NO_TKIP */ #ifdef CONFIG_WEP else if (os_strcmp(start, "WEP104") == 0) val |= WPA_CIPHER_WEP104; diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index da58159e4..c0ef689c6 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -22,6 +22,15 @@ #define OWE_DH_GROUP 19 +#ifdef CONFIG_NO_TKIP +#define WPA_ALLOWED_PAIRWISE_CIPHERS \ +(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_NONE | \ +WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) +#define WPA_ALLOWED_GROUP_CIPHERS \ +(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | \ +WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \ +WPA_CIPHER_GTK_NOT_USED) +#else /* CONFIG_NO_TKIP */ #define WPA_ALLOWED_PAIRWISE_CIPHERS \ (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE | \ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) @@ -29,6 +38,7 @@ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | \ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \ WPA_CIPHER_GTK_NOT_USED) +#endif /* CONFIG_NO_TKIP */ #define WPA_ALLOWED_GROUP_MGMT_CIPHERS \ (WPA_CIPHER_AES_128_CMAC | WPA_CIPHER_BIP_GMAC_128 | WPA_CIPHER_BIP_GMAC_256 | \ WPA_CIPHER_BIP_CMAC_256) diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c index 5ec7133af..f37225676 100644 --- a/src/wps/wps_attr_build.c +++ b/src/wps/wps_attr_build.c @@ -310,6 +310,9 @@ int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) auth_types &= ~WPS_AUTH_WPA; auth_types &= ~WPS_AUTH_WPA2; auth_types &= ~WPS_AUTH_SHARED; +#ifdef CONFIG_NO_TKIP + auth_types &= ~WPS_AUTH_WPAPSK; +#endif /* CONFIG_NO_TKIP */ #ifdef CONFIG_WPS_TESTING if (wps_force_auth_types_in_use) { wpa_printf(MSG_DEBUG, @@ -331,6 +334,9 @@ int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) { u16 encr_types = WPS_ENCR_TYPES; encr_types &= ~WPS_ENCR_WEP; +#ifdef CONFIG_NO_TKIP + encr_types &= ~WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ #ifdef CONFIG_WPS_TESTING if (wps_force_encr_types_in_use) { wpa_printf(MSG_DEBUG, diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 80ed603fc..819cd43f6 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -880,6 +880,17 @@ static int wps_process_ap_settings_e(struct wps_data *wps, cred.auth_type |= WPS_AUTH_WPA2PSK; } +#ifdef CONFIG_NO_TKIP + if (cred.encr_type & WPS_ENCR_TKIP) { + wpa_printf(MSG_DEBUG, "WPS: Disable encr_type TKIP"); + cred.encr_type &= ~WPS_ENCR_TKIP; + } + if (cred.auth_type & WPS_AUTH_WPAPSK) { + wpa_printf(MSG_DEBUG, "WPS: Disable auth_type WPAPSK"); + cred.auth_type &= ~WPS_AUTH_WPAPSK; + } +#endif /* CONFIG_NO_TKIP */ + if (wps->wps->cred_cb) { cred.cred_attr = wpabuf_head(attrs); cred.cred_attr_len = wpabuf_len(attrs); diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 9ee89ae34..9e1ee36da 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1677,8 +1677,10 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) wps->wps->auth_types, wps->auth_type); if (wps->auth_type & WPS_AUTH_WPA2PSK) wps->auth_type = WPS_AUTH_WPA2PSK; +#ifndef CONFIG_NO_TKIP else if (wps->auth_type & WPS_AUTH_WPAPSK) wps->auth_type = WPS_AUTH_WPAPSK; +#endif /* CONFIG_NO_TKIP */ else if (wps->auth_type & WPS_AUTH_OPEN) wps->auth_type = WPS_AUTH_OPEN; else { @@ -1700,8 +1702,10 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) wps->auth_type == WPS_AUTH_WPAPSK) { if (wps->encr_type & WPS_ENCR_AES) wps->encr_type = WPS_ENCR_AES; +#ifndef CONFIG_NO_TKIP else if (wps->encr_type & WPS_ENCR_TKIP) wps->encr_type = WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ else { wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " "type for WPA/WPA2"); diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index e44b366b5..a08da4d64 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -387,6 +387,10 @@ ifdef CONFIG_WEP L_CFLAGS += -DCONFIG_WEP endif +ifdef CONFIG_NO_TKIP +L_CFLAGS += -DCONFIG_NO_TKIP +endif + include $(LOCAL_PATH)/src/drivers/drivers.mk diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 6138a3120..7a02027e2 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1852,6 +1852,10 @@ ifdef CONFIG_WEP CFLAGS += -DCONFIG_WEP endif +ifdef CONFIG_NO_TKIP +CFLAGS += -DCONFIG_NO_TKIP +endif + ifndef LDO LDO=$(CC) endif diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 979f868e3..1e2c32268 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -19,8 +19,13 @@ EAPOL_FLAG_REQUIRE_KEY_BROADCAST) #define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN) #define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X) +#ifdef CONFIG_NO_TKIP +#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP) +#define DEFAULT_GROUP (WPA_CIPHER_CCMP) +#else /* CONFIG_NO_TKIP */ #define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) #define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) +#endif /* CONFIG_NO_TKIP */ #define DEFAULT_FRAGMENT_SIZE 1398 #define DEFAULT_BG_SCAN_PERIOD -1 diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index ae7cc8f6a..13e2f41a9 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -3959,7 +3959,9 @@ static const struct cipher_info ciphers[] = { { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 }, { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 }, { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 }, +#ifndef CONFIG_NO_TKIP { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 }, +#endif /* CONFIG_NO_TKIP */ { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 }, #ifdef CONFIG_WEP { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 }, @@ -3990,7 +3992,11 @@ static int ctrl_iface_get_capability_pairwise(int res, char *strict, if (res < 0) { if (strict) return 0; +#ifdef CONFIG_NO_TKIP + len = os_strlcpy(buf, "CCMP NONE", buflen); +#else /* CONFIG_NO_TKIP */ len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); +#endif /* CONFIG_NO_TKIP */ if (len >= buflen) return -1; return len; @@ -4027,9 +4033,17 @@ static int ctrl_iface_get_capability_group(int res, char *strict, if (strict) return 0; #ifdef CONFIG_WEP +#ifdef CONFIG_NO_TKIP + len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen); +#else /* CONFIG_NO_TKIP */ len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); +#endif /* CONFIG_NO_TKIP */ #else /* CONFIG_WEP */ +#ifdef CONFIG_NO_TKIP + len = os_strlcpy(buf, "CCMP", buflen); +#else /* CONFIG_NO_TKIP */ len = os_strlcpy(buf, "CCMP TKIP", buflen); +#endif /* CONFIG_NO_TKIP */ #endif /* CONFIG_WEP */ if (len >= buflen) return -1; diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index e9e77bd18..793a881ef 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -750,10 +750,12 @@ void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s, if (cred->auth_type & WPS_AUTH_OPEN) auth_type[at_num++] = "open"; +#ifndef CONFIG_NO_TKIP if (cred->auth_type & WPS_AUTH_WPAPSK) auth_type[at_num++] = "wpa-psk"; if (cred->auth_type & WPS_AUTH_WPA) auth_type[at_num++] = "wpa-eap"; +#endif /* CONFIG_NO_TKIP */ if (cred->auth_type & WPS_AUTH_WPA2) auth_type[at_num++] = "wpa2-eap"; if (cred->auth_type & WPS_AUTH_WPA2PSK) @@ -761,8 +763,10 @@ void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s, if (cred->encr_type & WPS_ENCR_NONE) encr_type[et_num++] = "none"; +#ifndef CONFIG_NO_TKIP if (cred->encr_type & WPS_ENCR_TKIP) encr_type[et_num++] = "tkip"; +#endif /* CONFIG_NO_TKIP */ if (cred->encr_type & WPS_ENCR_AES) encr_type[et_num++] = "aes"; diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 4e17e31a7..d1f9607c6 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -2632,7 +2632,11 @@ dbus_bool_t wpas_dbus_getter_capabilities( /***** pairwise cipher */ if (res < 0) { +#ifdef CONFIG_NO_TKIP + const char *args[] = {"ccmp", "none"}; +#else /* CONFIG_NO_TKIP */ const char *args[] = {"ccmp", "tkip", "none"}; +#endif /* CONFIG_NO_TKIP */ if (!wpa_dbus_dict_append_string_array( &iter_dict, "Pairwise", args, @@ -2655,9 +2659,11 @@ dbus_bool_t wpas_dbus_getter_capabilities( ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "gcmp")) || +#ifndef CONFIG_NO_TKIP ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "tkip")) || +#endif /* CONFIG_NO_TKIP */ ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) && !wpa_dbus_dict_string_array_add_element( &iter_array, "none")) || @@ -2671,7 +2677,10 @@ dbus_bool_t wpas_dbus_getter_capabilities( /***** group cipher */ if (res < 0) { const char *args[] = { - "ccmp", "tkip", + "ccmp", +#ifndef CONFIG_NO_TKIP + "tkip", +#endif /* CONFIG_NO_TKIP */ #ifdef CONFIG_WEP "wep104", "wep40" #endif /* CONFIG_WEP */ @@ -2698,9 +2707,11 @@ dbus_bool_t wpas_dbus_getter_capabilities( ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "gcmp")) || +#ifndef CONFIG_NO_TKIP ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "tkip")) || +#endif /* CONFIG_NO_TKIP */ #ifdef CONFIG_WEP ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) && !wpa_dbus_dict_string_array_add_element( @@ -4759,9 +4770,11 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop( group = "wep104"; break; #endif /* CONFIG_WEP */ +#ifndef CONFIG_NO_TKIP case WPA_CIPHER_TKIP: group = "tkip"; break; +#endif /* CONFIG_NO_TKIP */ case WPA_CIPHER_CCMP: group = "ccmp"; break; @@ -4784,8 +4797,10 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop( /* Pairwise */ n = 0; +#ifndef CONFIG_NO_TKIP if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP) pairwise[n++] = "tkip"; +#endif /* CONFIG_NO_TKIP */ if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP) pairwise[n++] = "ccmp"; if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP) diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index a87b58620..cbe49c8ec 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -611,3 +611,12 @@ CONFIG_DPP=y # release under this optional build parameter. This functionality is subject to # be completely removed in a future release. #CONFIG_WEP=y + +# Remove all TKIP functionality +# TKIP is an old cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used anymore for anything else than a +# backwards compatibility option as a group cipher when connecting to APs that +# use WPA+WPA2 mixed mode. For now, the default wpa_supplicant build includes +# support for this by default, but that functionality is subject to be removed +# in the future. +#CONFIG_NO_TKIP=y diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index a10c34cf0..d34e059a8 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -1618,8 +1618,13 @@ int wpas_wps_init(struct wpa_supplicant *wpa_s) os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN); wpas_wps_set_uuid(wpa_s, wps); +#ifdef CONFIG_NO_TKIP + wps->auth_types = WPS_AUTH_WPA2PSK; + wps->encr_types = WPS_ENCR_AES; +#else /* CONFIG_NO_TKIP */ wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ os_memset(&rcfg, 0, sizeof(rcfg)); rcfg.new_psk_cb = wpas_wps_new_psk_cb; From de5bf2d1994c53ba1b25ad10f77e17bd209c93ec Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 17 Apr 2020 16:06:25 +0300 Subject: [PATCH 0369/1105] tests: Do not enable TKIP group cipher for FT tests without need Change run_roams() default to CCMP-only and enable TKIP only in the test case that needs this. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index dbc02d026..adefab9f9 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -130,7 +130,7 @@ def ft_params2_r0kh_mismatch(rsn=True, ssid=None, passphrase=None): def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, sae=False, eap=False, fail_test=False, roams=1, - pairwise_cipher="CCMP", group_cipher="TKIP CCMP", ptk_rekey="0", + pairwise_cipher="CCMP", group_cipher="CCMP", ptk_rekey="0", test_connectivity=True, eap_identity="gpsk user", conndev=False, force_initial_conn_to_first_ap=False, sha384=False, group_mgmt=None, ocv=None, sae_password=None, @@ -454,7 +454,8 @@ def test_ap_ft_mixed(dev, apdev): params = ft_params2(rsn=False, ssid=ssid, passphrase=passphrase) hapd1 = hostapd.add_ap(apdev[1], params) - run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase) + run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, + group_cipher="TKIP CCMP") def test_ap_ft_pmf(dev, apdev): """WPA2-PSK-FT AP with PMF""" From 21cf2c5baf9fd455f198c62b1ca427284e1611ac Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 17 Apr 2020 16:07:24 +0300 Subject: [PATCH 0370/1105] tests: Skip more tests based on missing TKIP support This makes it more convenient to run tests with builds that disable TKIP/WPA(v1) support completely. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ciphers.py | 12 +++++++++++- tests/hwsim/test_ap_eap.py | 4 +++- tests/hwsim/test_ap_ft.py | 1 + tests/hwsim/test_ap_hs20.py | 5 ++++- tests/hwsim/test_ap_mixed.py | 3 ++- tests/hwsim/test_ap_pmf.py | 4 ++-- tests/hwsim/test_ap_psk.py | 7 +++++++ tests/hwsim/test_ap_tdls.py | 5 ++++- tests/hwsim/test_ap_vht.py | 1 + tests/hwsim/test_ap_wps.py | 15 +++++++++++++-- tests/hwsim/test_dbus.py | 3 ++- tests/hwsim/test_hapd_ctrl.py | 3 ++- tests/hwsim/test_he.py | 1 + tests/hwsim/test_ibss.py | 9 ++++++++- tests/hwsim/test_multi_ap.py | 2 ++ tests/hwsim/test_nfc_wps.py | 5 ++++- tests/hwsim/test_wext.py | 3 ++- tests/hwsim/test_wpas_ctrl.py | 3 ++- tests/hwsim/test_wpas_mesh.py | 5 +++-- tests/hwsim/utils.py | 6 ++++++ 20 files changed, 80 insertions(+), 17 deletions(-) diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index ae78e0ccc..ba54102d4 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -13,7 +13,7 @@ import subprocess import hwsim_utils import hostapd -from utils import HwsimSkip, skip_with_fips, require_under_vm +from utils import * from wlantest import Wlantest from wpasupplicant import WpaSupplicant @@ -78,12 +78,14 @@ def check_group_mgmt_cipher(dev, ap, cipher, sta_req_cipher=None): def test_ap_cipher_tkip(dev, apdev): """WPA2-PSK/TKIP connection""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) check_cipher(dev[0], apdev[0], "TKIP") @remote_compatible def test_ap_cipher_tkip_countermeasures_ap(dev, apdev): """WPA-PSK/TKIP countermeasures (detected by AP)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) testfile = "/sys/kernel/debug/ieee80211/%s/netdev:%s/tkip_mic_test" % (dev[0].get_driver_status_field("phyname"), dev[0].ifname) if dev[0].cmd_execute(["ls", testfile])[0] != 0: raise HwsimSkip("tkip_mic_test not supported in mac80211") @@ -118,6 +120,7 @@ def test_ap_cipher_tkip_countermeasures_ap(dev, apdev): def test_ap_cipher_tkip_countermeasures_ap_mixed_mode(dev, apdev): """WPA+WPA2-PSK/TKIP countermeasures (detected by mixed mode AP)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) testfile = "/sys/kernel/debug/ieee80211/%s/netdev:%s/tkip_mic_test" % (dev[0].get_driver_status_field("phyname"), dev[0].ifname) if dev[0].cmd_execute(["ls", testfile])[0] != 0: raise HwsimSkip("tkip_mic_test not supported in mac80211") @@ -166,6 +169,7 @@ def test_ap_cipher_tkip_countermeasures_ap_mixed_mode(dev, apdev): def test_ap_cipher_tkip_countermeasures_sta(dev, apdev): """WPA-PSK/TKIP countermeasures (detected by STA)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) params = {"ssid": "tkip-countermeasures", "wpa_passphrase": "12345678", "wpa": "1", @@ -202,6 +206,7 @@ def test_ap_cipher_tkip_countermeasures_sta2(dev, apdev, params): if not params['long']: raise HwsimSkip("Skip test case with long duration due to --long not specified") skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) params = {"ssid": "tkip-countermeasures", "wpa_passphrase": "12345678", "wpa": "1", @@ -365,6 +370,7 @@ def test_ap_cipher_gcmp_ccmp(dev, apdev, params): def test_ap_cipher_mixed_wpa_wpa2(dev, apdev): """WPA2-PSK/CCMP/ and WPA-PSK/TKIP mixed configuration""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-wpa2-psk" passphrase = "12345678" params = {"ssid": ssid, @@ -516,6 +522,7 @@ def test_ap_cipher_replay_protection_ap_ccmp(dev, apdev): def test_ap_cipher_replay_protection_ap_tkip(dev, apdev): """TKIP replay protection on AP""" + skip_without_tkip(dev[0]) run_ap_cipher_replay_protection_ap(dev, apdev, "TKIP") def test_ap_cipher_replay_protection_ap_gcmp(dev, apdev): @@ -572,6 +579,7 @@ def test_ap_cipher_replay_protection_sta_ccmp(dev, apdev): def test_ap_cipher_replay_protection_sta_tkip(dev, apdev): """TKIP replay protection on STA (TK)""" + skip_without_tkip(dev[0]) run_ap_cipher_replay_protection_sta(dev, apdev, "TKIP") def test_ap_cipher_replay_protection_sta_gcmp(dev, apdev): @@ -586,6 +594,7 @@ def test_ap_cipher_replay_protection_sta_gtk_ccmp(dev, apdev): def test_ap_cipher_replay_protection_sta_gtk_tkip(dev, apdev): """TKIP replay protection on STA (GTK)""" + skip_without_tkip(dev[0]) run_ap_cipher_replay_protection_sta(dev, apdev, "TKIP", gtk=True) def test_ap_cipher_replay_protection_sta_gtk_gcmp(dev, apdev): @@ -987,6 +996,7 @@ def test_ap_wpa2_plaintext_group_m1_pmf(dev, apdev): def test_ap_wpa2_gtk_initial_rsc_tkip(dev, apdev): """Initial group cipher RSC (TKIP)""" + skip_without_tkip(dev[0]) run_ap_wpa2_gtk_initial_rsc(dev, apdev, "TKIP") def test_ap_wpa2_gtk_initial_rsc_ccmp(dev, apdev): diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 026b995cf..7e39aace7 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -24,7 +24,7 @@ import tempfile import hwsim_utils from hwsim import HWSimRadio import hostapd -from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips, wait_fail_trigger, require_under_vm +from utils import * from wpasupplicant import WpaSupplicant from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations, set_test_assoc_ie @@ -3304,6 +3304,7 @@ def test_ap_wpa2_eap_psk_oom(dev, apdev): def test_ap_wpa_eap_peap_eap_mschapv2(dev, apdev): """WPA-Enterprise connection using EAP-PEAP/EAP-MSCHAPv2""" + skip_without_tkip(dev[0]) check_eap_capa(dev[0], "MSCHAPV2") params = hostapd.wpa_eap_params(ssid="test-wpa-eap") hapd = hostapd.add_ap(apdev[0], params) @@ -7317,6 +7318,7 @@ def test_ap_wpa2_eap_sake_no_control_port(dev, apdev): def test_ap_wpa3_eap_transition_disable(dev, apdev): """WPA3-Enterprise transition disable indication""" + skip_without_tkip(dev[0]) params = hostapd.wpa2_eap_params(ssid="test-wpa3-eap") params["ieee80211w"] = "1" params['transition_disable'] = '0x04' diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index adefab9f9..1162f98af 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -442,6 +442,7 @@ def test_ap_ft_many_vlan(dev, apdev): def test_ap_ft_mixed(dev, apdev): """WPA2-PSK-FT mixed-mode AP""" + skip_without_tkip(dev[0]) ssid = "test-ft-mixed" passphrase = "12345678" diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index a8dac6b70..c484b5003 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -17,7 +17,7 @@ import socket import subprocess import hostapd -from utils import HwsimSkip, skip_with_fips, alloc_fail, fail_test, wait_fail_trigger +from utils import * import hwsim_utils from tshark import run_tshark from wlantest import Wlantest @@ -5989,6 +5989,9 @@ def test_ap_hs20_set_profile_failures(dev, apdev): def test_ap_hs20_unexpected(dev, apdev): """Unexpected Hotspot 2.0 AP configuration""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) + skip_without_tkip(dev[2]) check_eap_capa(dev[0], "MSCHAPV2") bssid = apdev[0]['bssid'] params = hostapd.wpa_eap_params(ssid="test-hs20-fake") diff --git a/tests/hwsim/test_ap_mixed.py b/tests/hwsim/test_ap_mixed.py index 81b85e6aa..e758ae923 100644 --- a/tests/hwsim/test_ap_mixed.py +++ b/tests/hwsim/test_ap_mixed.py @@ -9,11 +9,12 @@ logger = logging.getLogger() import hostapd import hwsim_utils -from utils import skip_with_fips +from utils import * def test_ap_mixed_security(dev, apdev): """WPA/WPA2 with PSK, EAP, SAE, FT in a single BSS""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) dev[0].flush_scan_cache() sae = "SAE" in dev[2].get_capability("auth_alg") ssid = "test-mixed" diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index 7feb173b6..fc1529b9e 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -13,8 +13,7 @@ logger = logging.getLogger() import hwsim_utils import hostapd -from utils import alloc_fail, fail_test, wait_fail_trigger, HwsimSkip, \ - radiotap_build, start_monitor, stop_monitor +from utils import * from wlantest import Wlantest from wpasupplicant import WpaSupplicant @@ -854,6 +853,7 @@ def run_ap_pmf_inject_data(dev, apdev): def test_ap_pmf_tkip_reject(dev, apdev): """Mixed mode BSS and MFP-enabled AP rejecting TKIP""" + skip_without_tkip(dev[0]) params = hostapd.wpa2_params(ssid="test-pmf", passphrase="12345678") params['wpa'] = '3' params["ieee80211w"] = "1" diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index b9abf5d82..b741cca71 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -333,6 +333,7 @@ def test_ap_wpa2_sha256_ptk_rekey_ap(dev, apdev): def test_ap_wpa_ptk_rekey(dev, apdev): """WPA-PSK/TKIP AP and PTK rekey enforced by station""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-psk" passphrase = 'qwertyuiop' params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase) @@ -349,6 +350,7 @@ def test_ap_wpa_ptk_rekey(dev, apdev): def test_ap_wpa_ptk_rekey_ap(dev, apdev): """WPA-PSK/TKIP AP and PTK rekey enforced by AP""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-psk" passphrase = 'qwertyuiop' params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase) @@ -494,6 +496,7 @@ def test_ap_wpa2_gtk_rekey_request(dev, apdev): def test_ap_wpa_gtk_rekey(dev, apdev): """WPA-PSK/TKIP AP and GTK rekey enforced by AP""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-psk" passphrase = 'qwertyuiop' params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase) @@ -1565,6 +1568,7 @@ def test_ap_wpa2_psk_ext_eapol_type_diff(dev, apdev): @remote_compatible def test_ap_wpa_psk_ext_eapol(dev, apdev): """WPA2-PSK AP using external EAPOL supplicant""" + skip_without_tkip(dev[0]) (bssid, ssid, hapd, snonce, pmk, addr, wpae) = eapol_test(apdev[0], dev[0], wpa2=False) @@ -2803,6 +2807,7 @@ def test_ap_wpa2_psk_incorrect_passphrase(dev, apdev): def test_ap_wpa_ie_parsing(dev, apdev): """WPA IE parsing""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-psk" passphrase = 'qwertyuiop' params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase) @@ -3034,6 +3039,7 @@ def test_ap_wpa2_psk_assoc_rsn_pmkid(dev, apdev): def test_ap_wpa_psk_rsn_pairwise(dev, apdev): """WPA-PSK AP and only rsn_pairwise set""" + skip_without_tkip(dev[0]) params = {"ssid": "wpapsk", "wpa": "1", "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "TKIP", "wpa_passphrase": "1234567890"} hapd = hostapd.add_ap(apdev[0], params) @@ -3154,6 +3160,7 @@ def test_ap_wpa2_disable_eapol_retry_group(dev, apdev): def test_ap_wpa2_psk_mic_0(dev, apdev): """WPA2-PSK/TKIP and MIC=0 in EAPOL-Key msg 3/4""" + skip_without_tkip(dev[0]) bssid = apdev[0]['bssid'] ssid = "test-wpa2-psk" passphrase = 'qwertyuiop' diff --git a/tests/hwsim/test_ap_tdls.py b/tests/hwsim/test_ap_tdls.py index 31d581516..1af072263 100644 --- a/tests/hwsim/test_ap_tdls.py +++ b/tests/hwsim/test_ap_tdls.py @@ -14,7 +14,7 @@ import hwsim_utils from hostapd import HostapdGlobal from hostapd import Hostapd import hostapd -from utils import HwsimSkip, skip_with_fips +from utils import * from wlantest import Wlantest from test_ap_vht import vht_supported from test_wep import check_wep_capa @@ -291,6 +291,8 @@ def test_ap_wpa2_tdls_double_tpk_m2(dev, apdev): def test_ap_wpa_tdls(dev, apdev): """WPA-PSK AP and two stations using TDLS""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) hapd = hostapd.add_ap(apdev[0], hostapd.wpa_params(ssid="test-wpa-psk", passphrase="12345678")) @@ -303,6 +305,7 @@ def test_ap_wpa_tdls(dev, apdev): def test_ap_wpa_mixed_tdls(dev, apdev): """WPA+WPA2-PSK AP and two stations using TDLS""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) hapd = hostapd.add_ap(apdev[0], hostapd.wpa_mixed_params(ssid="test-wpa-mixed-psk", passphrase="12345678")) diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 24658d1f9..c7851d557 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -1117,6 +1117,7 @@ def test_ap_vht_use_sta_nsts(dev, apdev): def test_ap_vht_tkip(dev, apdev): """VHT and TKIP""" + skip_without_tkip(dev[0]) try: hapd = None params = {"ssid": "vht", diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index b1b0331c4..2b07caac3 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -41,8 +41,7 @@ import xml.etree.ElementTree as ET import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips -from utils import wait_fail_trigger, clear_regdom +from utils import * from test_ap_eap import int_eap_server_params from test_sae import check_sae_capab from test_wep import check_wep_capa @@ -56,6 +55,7 @@ def wps_start_ap(apdev, ssid="test-wps-conf"): @remote_compatible def test_ap_wps_init(dev, apdev): """Initial AP configuration with first WPS Enrollee""" + skip_without_tkip(dev[0]) ssid = "test-wps" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1"}) @@ -111,6 +111,7 @@ def test_ap_wps_init(dev, apdev): def test_ap_wps_init_2ap_pbc(dev, apdev): """Initial two-radio AP configuration with first WPS PBC Enrollee""" + skip_without_tkip(dev[0]) ssid = "test-wps" params = {"ssid": ssid, "eap_server": "1", "wps_state": "1"} hapd = hostapd.add_ap(apdev[0], params) @@ -147,6 +148,7 @@ def test_ap_wps_init_2ap_pbc(dev, apdev): def test_ap_wps_init_2ap_pin(dev, apdev): """Initial two-radio AP configuration with first WPS PIN Enrollee""" + skip_without_tkip(dev[0]) ssid = "test-wps" params = {"ssid": ssid, "eap_server": "1", "wps_state": "1"} hapd = hostapd.add_ap(apdev[0], params) @@ -411,6 +413,7 @@ def test_ap_wps_conf_pin(dev, apdev): def test_ap_wps_conf_pin_mixed_mode(dev, apdev): """WPS PIN provisioning with configured AP (WPA+WPA2)""" + skip_without_tkip(dev[0]) ssid = "test-wps-conf-pin-mixed" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "2", @@ -588,6 +591,7 @@ def test_ap_wps_reg_connect_zero_len_ap_pin(dev, apdev): def test_ap_wps_reg_connect_mixed_mode(dev, apdev): """WPS registrar using AP PIN to connect (WPA+WPA2)""" + skip_without_tkip(dev[0]) ssid = "test-wps-reg-ap-pin" appin = "12345670" hostapd.add_ap(apdev[0], @@ -786,6 +790,7 @@ def test_ap_wps_reg_config_ext_processing(dev, apdev): def test_ap_wps_reg_config_tkip(dev, apdev): """WPS registrar configuring AP to use TKIP and AP upgrading to TKIP+CCMP""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wps-init-ap" appin = "12345670" hostapd.add_ap(apdev[0], @@ -1985,6 +1990,7 @@ def _test_ap_wps_er_learn_oom(dev, apdev): def test_ap_wps_fragmentation(dev, apdev): """WPS with fragmentation in EAP-WSC and mixed mode WPA+WPA2""" + skip_without_tkip(dev[0]) ssid = "test-wps-fragmentation" appin = "12345670" hapd = hostapd.add_ap(apdev[0], @@ -2458,6 +2464,7 @@ def test_ap_wps_pin_request_file(dev, apdev): def test_ap_wps_auto_setup_with_config_file(dev, apdev): """WPS auto-setup with configuration file""" + skip_without_tkip(dev[0]) conffile = "/tmp/ap_wps_auto_setup_with_config_file.conf" ifname = apdev[0]['ifname'] try: @@ -3642,6 +3649,7 @@ def test_ap_wps_disabled(dev, apdev): def test_ap_wps_mixed_cred(dev, apdev): """WPS 2.0 STA merging mixed mode WPA/WPA2 credentials""" + skip_without_tkip(dev[0]) ssid = "test-wps-wep" params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", "skip_cred_build": "1", "extra_cred": "wps-mixed-cred"} @@ -10134,6 +10142,7 @@ def test_ap_wps_pbc_in_m1(dev, apdev): def test_ap_wps_pbc_mac_addr_change(dev, apdev, params): """WPS M1 with MAC address change""" + skip_without_tkip(dev[0]) ssid = "test-wps-mac-addr-change" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1"}) @@ -10284,6 +10293,8 @@ def run_ap_wps_conf_pin_cipher(dev, apdev, cipher): def test_ap_wps_and_sae(dev, apdev): """Initial AP configuration with first WPS Enrollee and adding SAE""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) try: run_ap_wps_and_sae(dev, apdev) finally: diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py index 64bf34b54..e9d6b9e39 100644 --- a/tests/hwsim/test_dbus.py +++ b/tests/hwsim/test_dbus.py @@ -24,7 +24,7 @@ except ImportError: import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test +from utils import * from p2p_utils import * from test_ap_tdls import connect_2sta_open from test_ap_eap import check_altsubject_match_support @@ -5553,6 +5553,7 @@ def test_dbus_ap_scan(dev, apdev): def test_dbus_connect_wpa_eap(dev, apdev): """D-Bus AddNetwork and connection with WPA+WPA2-Enterprise AP""" + skip_without_tkip(dev[0]) (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) diff --git a/tests/hwsim/test_hapd_ctrl.py b/tests/hwsim/test_hapd_ctrl.py index a83b570ef..0d8c10a1e 100644 --- a/tests/hwsim/test_hapd_ctrl.py +++ b/tests/hwsim/test_hapd_ctrl.py @@ -10,7 +10,7 @@ import os from remotehost import remote_compatible import hostapd import hwsim_utils -from utils import skip_with_fips, alloc_fail, fail_test, HwsimSkip +from utils import * @remote_compatible def test_hapd_ctrl_status(dev, apdev): @@ -613,6 +613,7 @@ def test_hapd_dup_network_global_wpa2(dev, apdev): def test_hapd_dup_network_global_wpa(dev, apdev): """hostapd and DUP_NETWORK command (WPA)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' src_ssid = "hapd-ctrl-src" dst_ssid = "hapd-ctrl-dst" diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index d86e2423a..41407343a 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -956,6 +956,7 @@ def test_he_use_sta_nsts(dev, apdev): def test_he_tkip(dev, apdev): """HE and TKIP""" + skip_without_tkip(dev[0]) try: hapd = None params = {"ssid": "he", diff --git a/tests/hwsim/test_ibss.py b/tests/hwsim/test_ibss.py index ce7e5eda3..8e688bd73 100644 --- a/tests/hwsim/test_ibss.py +++ b/tests/hwsim/test_ibss.py @@ -12,7 +12,7 @@ import re import subprocess import hwsim_utils -from utils import alloc_fail, wait_fail_trigger +from utils import * from test_wep import check_wep_capa def connect_ibss_cmd(dev, id, freq=2412): @@ -190,6 +190,9 @@ def test_ibss_rsn_group_rekey(dev): def test_ibss_wpa_none(dev): """IBSS WPA-None""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) + skip_without_tkip(dev[2]) ssid = "ibss-wpa-none" logger.info("Start IBSS on the first STA") @@ -258,6 +261,8 @@ def test_ibss_wpa_none(dev): def test_ibss_wpa_none_ccmp(dev): """IBSS WPA-None/CCMP""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) ssid = "ibss-wpa-none" logger.info("Start IBSS on the first STA") @@ -378,6 +383,8 @@ def test_ibss_open_retry(dev): def test_ibss_rsn_tkip(dev): """IBSS RSN with TKIP as the cipher""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) ssid = "ibss-rsn-tkip" id = add_ibss_rsn_tkip(dev[0], ssid) diff --git a/tests/hwsim/test_multi_ap.py b/tests/hwsim/test_multi_ap.py index 5b28cf8da..4070d3ea7 100644 --- a/tests/hwsim/test_multi_ap.py +++ b/tests/hwsim/test_multi_ap.py @@ -5,6 +5,7 @@ # See README for more details. import hostapd +from utils import * def test_multi_ap_association(dev, apdev): """Multi-AP association in backhaul BSS""" @@ -183,6 +184,7 @@ def test_multi_ap_wps_split_psk(dev, apdev): def test_multi_ap_wps_split_mixed(dev, apdev): """WPS on split fronthaul and backhaul AP with mixed-mode fronthaul""" + skip_without_tkip(dev[0]) backhaul_ssid = "multi-ap-backhaul-wps" backhaul_passphrase = "87654321" params = hostapd.wpa_mixed_params(ssid="multi-ap-fronthaul-wps", diff --git a/tests/hwsim/test_nfc_wps.py b/tests/hwsim/test_nfc_wps.py index e98eb4113..a0e2d454f 100644 --- a/tests/hwsim/test_nfc_wps.py +++ b/tests/hwsim/test_nfc_wps.py @@ -13,7 +13,7 @@ logger = logging.getLogger() import hwsim_utils import hostapd -from utils import alloc_fail, fail_test, clear_regdom +from utils import * def check_wpa2_connection(sta, ap, hapd, ssid, mixed=False): status = sta.get_status() @@ -104,6 +104,7 @@ def test_nfc_wps_config_token(dev, apdev): def test_nfc_wps_config_token_init(dev, apdev): """NFC tag with configuration token from AP with auto configuration""" + skip_without_tkip(dev[0]) ssid = "test-wps-nfc-conf-token-init" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1"}) @@ -122,6 +123,7 @@ def test_nfc_wps_config_token_init(dev, apdev): @remote_compatible def test_nfc_wps_password_token_sta_init(dev, apdev): """Initial AP configuration with first WPS NFC Enrollee""" + skip_without_tkip(dev[0]) ssid = "test-wps-nfc-pw-token-init" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1"}) @@ -216,6 +218,7 @@ def test_nfc_wps_password_token_ap_preconf(dev, apdev): def test_nfc_wps_handover_init(dev, apdev): """Connect to WPS AP with NFC connection handover and move to configured state""" + skip_without_tkip(dev[0]) try: _test_nfc_wps_handover_init(dev, apdev) finally: diff --git a/tests/hwsim/test_wext.py b/tests/hwsim/test_wext.py index 8e1ed7159..f50e1d1b7 100644 --- a/tests/hwsim/test_wext.py +++ b/tests/hwsim/test_wext.py @@ -11,7 +11,7 @@ import os import hostapd import hwsim_utils from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, skip_with_fips +from utils import * from test_rfkill import get_rfkill from test_wep import check_wep_capa @@ -56,6 +56,7 @@ def test_wext_wpa2_psk(dev, apdev): def test_wext_wpa_psk(dev, apdev): """WEXT driver interface with WPA-PSK""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) wpas = get_wext_interface() params = hostapd.wpa_params(ssid="wext-wpa-psk", passphrase="12345678") diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py index cd3053460..cc3d5e98b 100644 --- a/tests/hwsim/test_wpas_ctrl.py +++ b/tests/hwsim/test_wpas_ctrl.py @@ -17,12 +17,13 @@ import hostapd import hwsim_utils from hwsim import HWSimRadio from wpasupplicant import WpaSupplicant -from utils import alloc_fail, fail_test +from utils import * from test_wpas_ap import wait_ap_ready @remote_compatible def test_wpas_ctrl_network(dev): """wpa_supplicant ctrl_iface network set/get""" + skip_without_tkip(dev[0]) id = dev[0].add_network() if "FAIL" not in dev[0].request("SET_NETWORK " + str(id)): diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index ed38ac129..5db1d28ce 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -16,8 +16,7 @@ import binascii import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger, \ - radiotap_build, start_monitor, stop_monitor +from utils import * from tshark import run_tshark, run_tshark_json from test_ap_ht import set_world_reg from test_sae import build_sae_commit, sae_rx_commit_token_req @@ -514,6 +513,7 @@ def test_mesh_secure_gcmp_256_gmac_256(dev, apdev): def test_mesh_secure_invalid_pairwise_cipher(dev, apdev): """Secure mesh and invalid group cipher""" check_mesh_support(dev[0], secure=True) + skip_without_tkip(dev[0]) dev[0].request("SET sae_groups ") id = add_mesh_secure_net(dev[0], pairwise="TKIP", group="CCMP") if dev[0].mesh_group_add(id) != None: @@ -524,6 +524,7 @@ def test_mesh_secure_invalid_pairwise_cipher(dev, apdev): def test_mesh_secure_invalid_group_cipher(dev, apdev): """Secure mesh and invalid group cipher""" + skip_without_tkip(dev[0]) check_mesh_support(dev[0], secure=True) dev[0].request("SET sae_groups ") id = add_mesh_secure_net(dev[0], pairwise="CCMP", group="TKIP") diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index 1e7e56c3a..66f5285a5 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -94,6 +94,12 @@ def check_ext_key_id_capa(dev): if (int(res, 0) & 0x8000000000000000) == 0: raise HwsimSkip("Extended Key ID not supported") +def skip_without_tkip(dev): + res = dev.get_capability("fips") + if "TKIP" not in dev.get_capability("pairwise") or \ + "TKIP" not in dev.get_capability("group"): + raise HwsimSkip("Cipher TKIP not supported") + def get_phy(ap, ifname=None): phy = "phy3" try: From 7b82d0bd5877c432dae05126067244b80b82e6fb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 17 Apr 2020 18:16:13 +0300 Subject: [PATCH 0371/1105] tests: Skip test cases where hostapd does not support TKIP Signed-off-by: Jouni Malinen --- tests/hwsim/hostapd.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index 62b3302be..571757506 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -196,6 +196,9 @@ class Hostapd: def set(self, field, value): if "OK" not in self.request("SET " + field + " " + value): + if "TKIP" in value and (field == "wpa_pairwise" or \ + field == "rsn_pairwise"): + raise utils.HwsimSkip("Cipher TKIP not supported") raise Exception("Failed to set hostapd parameter " + field) def set_defaults(self): From d0b382fd11312444cac9bd9efc98c6f745a3d278 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 17 Apr 2020 21:46:12 +0300 Subject: [PATCH 0372/1105] tests: ap_wps_init to allow TKIP-disabled hostapd build Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_wps.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index 2b07caac3..fd778e8d6 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -97,14 +97,20 @@ def test_ap_wps_init(dev, apdev): conf = hapd.request("GET_CONFIG") if "wps_state=configured" not in conf: raise Exception("AP not in WPS configured state") - if "wpa=3" not in conf: - raise Exception("AP not in WPA+WPA2 configuration") - if "rsn_pairwise_cipher=CCMP TKIP" not in conf: - raise Exception("Unexpected rsn_pairwise_cipher") - if "wpa_pairwise_cipher=CCMP TKIP" not in conf: - raise Exception("Unexpected wpa_pairwise_cipher") - if "group_cipher=TKIP" not in conf: - raise Exception("Unexpected group_cipher") + if "wpa=2" in conf: + if "rsn_pairwise_cipher=CCMP" not in conf: + raise Exception("Unexpected rsn_pairwise_cipher") + if "group_cipher=CCMP" not in conf: + raise Exception("Unexpected group_cipher") + else: + if "wpa=3" not in conf: + raise Exception("AP not in WPA+WPA2 configuration") + if "rsn_pairwise_cipher=CCMP TKIP" not in conf: + raise Exception("Unexpected rsn_pairwise_cipher") + if "wpa_pairwise_cipher=CCMP TKIP" not in conf: + raise Exception("Unexpected wpa_pairwise_cipher") + if "group_cipher=TKIP" not in conf: + raise Exception("Unexpected group_cipher") if len(dev[0].list_networks()) != 3: raise Exception("Unexpected number of network blocks") From 48ac76591910d891970202d44dda21b3cbf89555 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 17 Apr 2020 21:51:26 +0300 Subject: [PATCH 0373/1105] tests: ap_wpa2_eap_assoc_rsn to allow TKIP-disabled hostapd build Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_eap.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 7e39aace7..24de73e6c 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -6737,7 +6737,7 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apdev): dev[0].request("REMOVE_NETWORK all") dev[0].wait_disconnected() - tests = [("Invalid group cipher", "30060100000fac02", 41), + tests = [("Invalid group cipher", "30060100000fac02", [40, 41]), ("Invalid pairwise cipher", "300c0100000fac040100000fac02", 42)] for title, ie, status in tests: logger.info(title) @@ -6749,7 +6749,15 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apdev): ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"]) if ev is None: raise Exception("Association rejection not reported") - if "status_code=" + str(status) not in ev: + ok = False + if isinstance(status, list): + for i in status: + ok = "status_code=" + str(i) in ev + if ok: + break + else: + ok = "status_code=" + str(status) in ev + if not ok: raise Exception("Unexpected status code: " + ev) dev[0].request("REMOVE_NETWORK all") dev[0].dump_monitor() From 7162c6ecf5d2ce2bbfd6409d444b63aa392defb4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 17 Apr 2020 21:55:18 +0300 Subject: [PATCH 0374/1105] tests: Use SAE instead of WPA/TKIP in ap_multi_bss_acs This makes the test case work with no-TKIP hostapd builds. Signed-off-by: Jouni Malinen --- tests/hwsim/multi-bss-acs.conf | 8 ++++---- tests/hwsim/test_ap_acs.py | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/hwsim/multi-bss-acs.conf b/tests/hwsim/multi-bss-acs.conf index 4e1db46c0..f5a25e82b 100644 --- a/tests/hwsim/multi-bss-acs.conf +++ b/tests/hwsim/multi-bss-acs.conf @@ -22,7 +22,7 @@ bss=wlan3-3 bssid=02:00:00:00:03:02 ctrl_interface=/var/run/hostapd ssid=bss-3 -wpa=1 -wpa_key_mgmt=WPA-PSK -rsn_pairwise=TKIP -wpa_passphrase=qwertyuiop +wpa=2 +wpa_key_mgmt=SAE +rsn_pairwise=CCMP +sae_password=qwertyuiop diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index ed05c903a..62bf8553a 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -12,6 +12,7 @@ import hostapd from utils import skip_with_fips, alloc_fail, fail_test, HwsimSkip, clear_regdom from test_ap_ht import clear_scan_cache from test_dfs import wait_dfs_event +from test_sae import check_sae_capab def force_prev_ap_on_24g(ap): # For now, make sure the last operating channel was on 2.4 GHz band to get @@ -118,6 +119,7 @@ def test_ap_acs_invalid_chanlist(dev, apdev): def test_ap_multi_bss_acs(dev, apdev): """hostapd start with a multi-BSS configuration file using ACS""" skip_with_fips(dev[0]) + check_sae_capab(dev[2]) force_prev_ap_on_24g(apdev[0]) # start the actual test @@ -131,7 +133,8 @@ def test_ap_multi_bss_acs(dev, apdev): dev[0].connect("bss-1", key_mgmt="NONE", scan_freq=freq) dev[1].connect("bss-2", psk="12345678", scan_freq=freq) - dev[2].connect("bss-3", psk="qwertyuiop", scan_freq=freq) + dev[2].set("sae_groups", "") + dev[2].connect("bss-3", key_mgmt="SAE", psk="qwertyuiop", scan_freq=freq) def test_ap_acs_40mhz(dev, apdev): """Automatic channel selection for 40 MHz channel""" From 6255a8ac1f7016d2b1d089889917a131c0a4ef4d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 17 Apr 2020 22:05:07 +0300 Subject: [PATCH 0375/1105] WPS: Convert WPA/TKIP-only to WPA+WPA2 mixed mode credential This case of accepting WPA/TKIP-only credential based on internal registrar request to configure an AP to use TKIP was still remaining while all the WPS cases were supposed to enable mixed mode automatically. This is bit of a corner case since this is based on explicit local request to configure TKIP, but anyway, convert this one as well to allow WPA2/CCMP to be used. Signed-off-by: Jouni Malinen --- wpa_supplicant/wps_supplicant.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index d34e059a8..b160fd0d4 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -484,7 +484,7 @@ static int wpa_supplicant_wps_cred(void *ctx, case WPS_ENCR_NONE: break; case WPS_ENCR_TKIP: - ssid->pairwise_cipher = WPA_CIPHER_TKIP; + ssid->pairwise_cipher = WPA_CIPHER_TKIP | WPA_CIPHER_CCMP; break; case WPS_ENCR_AES: ssid->pairwise_cipher = WPA_CIPHER_CCMP; @@ -525,7 +525,7 @@ static int wpa_supplicant_wps_cred(void *ctx, case WPS_AUTH_WPAPSK: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_PSK; - ssid->proto = WPA_PROTO_WPA; + ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN; break; case WPS_AUTH_WPA2PSK: ssid->auth_alg = WPA_AUTH_ALG_OPEN; From b5bf18768fae185ad933d8d990a1d1afc3c9cd69 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 17 Apr 2020 22:07:03 +0300 Subject: [PATCH 0376/1105] tests: ap_wps_reg_config_tkip to allow no-TKIP hostapd build Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_wps.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index fd778e8d6..cee66f98f 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -799,9 +799,9 @@ def test_ap_wps_reg_config_tkip(dev, apdev): skip_without_tkip(dev[0]) ssid = "test-wps-init-ap" appin = "12345670" - hostapd.add_ap(apdev[0], - {"ssid": ssid, "eap_server": "1", "wps_state": "1", - "ap_pin": appin}) + hapd = hostapd.add_ap(apdev[0], + {"ssid": ssid, "eap_server": "1", "wps_state": "1", + "ap_pin": appin}) logger.info("WPS configuration step") dev[0].flush_scan_cache() dev[0].request("SET wps_version_number 0x10") @@ -822,8 +822,12 @@ def test_ap_wps_reg_config_tkip(dev, apdev): raise Exception("Not fully connected: wpa_state={} bssid={}".format(status['wpa_state'], status['bssid'])) if status['ssid'] != new_ssid: raise Exception("Unexpected SSID") - if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP': + if status['pairwise_cipher'] != 'CCMP': raise Exception("Unexpected encryption configuration") + if status['group_cipher'] != 'TKIP': + conf = hapd.request("GET_CONFIG") + if "group_cipher=CCMP" not in conf or status['group_cipher'] != 'CCMP': + raise Exception("Unexpected encryption configuration") if status['key_mgmt'] != 'WPA2-PSK': raise Exception("Unexpected key_mgmt") From 7e88ed8e2d2af0438da19f4cf0ae94a6415c3374 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 18 Apr 2020 11:00:49 +0300 Subject: [PATCH 0377/1105] tests: Use function decorator to clean up --long processing Signed-off-by: Jouni Malinen --- tests/hwsim/run-tests.py | 22 +++++++++++++++------ tests/hwsim/test_ap_acs.py | 16 +++++++-------- tests/hwsim/test_ap_ciphers.py | 7 +++---- tests/hwsim/test_ap_dynamic.py | 2 +- tests/hwsim/test_ap_eap.py | 7 +++---- tests/hwsim/test_ap_wps.py | 21 +++++++++----------- tests/hwsim/test_dfs.py | 35 ++++++++++++++------------------- tests/hwsim/test_dpp.py | 16 +++++++-------- tests/hwsim/test_he.py | 14 ++++++------- tests/hwsim/test_hostapd_oom.py | 7 +++---- tests/hwsim/test_p2p_grpform.py | 29 ++++++++++++--------------- tests/hwsim/test_wpas_mesh.py | 7 +++---- tests/hwsim/utils.py | 4 ++++ 13 files changed, 90 insertions(+), 97 deletions(-) diff --git a/tests/hwsim/run-tests.py b/tests/hwsim/run-tests.py index a0bcdf31d..7ed632b66 100755 --- a/tests/hwsim/run-tests.py +++ b/tests/hwsim/run-tests.py @@ -187,6 +187,18 @@ def rename_log(logdir, basename, testname, dev): logger.info("Failed to rename log files") logger.info(e) +def is_long_duration_test(t): + return hasattr(t, "long_duration_test") and t.long_duration_test + +def get_test_description(t): + if t.__doc__ is None: + desc = "MISSING DESCRIPTION" + else: + desc = t.__doc__ + if is_long_duration_test(t): + desc += " [long]" + return desc + def main(): tests = [] test_modules = [] @@ -319,13 +331,10 @@ def main(): if args.update_tests_db: for t in tests_to_run: name = t.__name__.replace('test_', '', 1) - if t.__doc__ is None: - print(name + " - MISSING DESCRIPTION") - else: - print(name + " - " + t.__doc__) + print(name + " - " + get_test_description(t)) if conn: sql = 'INSERT OR REPLACE INTO tests(test,description) VALUES (?, ?)' - params = (name, t.__doc__) + params = (name, get_test_description(t)) try: conn.execute(sql, params) except Exception as e: @@ -512,10 +521,11 @@ def main(): sys.exit(1) skip_reason = None try: + if is_long_duration_test(t) and not args.long: + raise HwsimSkip("Skip test case with long duration due to --long not specified") if t.__code__.co_argcount > 2: params = {} params['logdir'] = args.logdir - params['long'] = args.long params['name'] = name params['prefix'] = os.path.join(args.logdir, name) t(dev, apdev, params) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index 62bf8553a..a5644195d 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -9,7 +9,7 @@ logger = logging.getLogger() import time import hostapd -from utils import skip_with_fips, alloc_fail, fail_test, HwsimSkip, clear_regdom +from utils import * from test_ap_ht import clear_scan_cache from test_dfs import wait_dfs_event from test_sae import check_sae_capab @@ -390,10 +390,9 @@ def test_ap_acs_errors(dev, apdev): if not ev: raise Exception("ACS start timed out") -def test_ap_acs_dfs(dev, apdev, params): - """Automatic channel selection, HT scan, and DFS [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_acs_dfs(dev, apdev): + """Automatic channel selection, HT scan, and DFS""" try: hapd = None force_prev_ap_on_5g(apdev[0]) @@ -472,10 +471,9 @@ def test_ap_acs_exclude_dfs(dev, apdev, params): dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) dev[0].flush_scan_cache() -def test_ap_acs_vht160_dfs(dev, apdev, params): - """Automatic channel selection 160 MHz, HT scan, and DFS [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_acs_vht160_dfs(dev, apdev): + """Automatic channel selection 160 MHz, HT scan, and DFS""" try: hapd = None force_prev_ap_on_5g(apdev[0]) diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index ba54102d4..fb0d9b614 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -201,10 +201,9 @@ def test_ap_cipher_tkip_countermeasures_sta(dev, apdev): if ev is not None: raise Exception("Unexpected connection during TKIP countermeasures") -def test_ap_cipher_tkip_countermeasures_sta2(dev, apdev, params): - """WPA-PSK/TKIP countermeasures (detected by two STAs) [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_cipher_tkip_countermeasures_sta2(dev, apdev): + """WPA-PSK/TKIP countermeasures (detected by two STAs)""" skip_with_fips(dev[0]) skip_without_tkip(dev[0]) params = {"ssid": "tkip-countermeasures", diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index aab59f4ef..07afee313 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -13,7 +13,7 @@ import os import hwsim_utils import hostapd -from utils import alloc_fail, require_under_vm, get_phy +from utils import * from test_ap_acs import force_prev_ap_on_24g @remote_compatible diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 24de73e6c..6e2193076 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -3026,10 +3026,9 @@ def test_ap_wpa2_eap_eke(dev, apdev): eap_connect(dev[0], hapd, "EKE", "eke user", password="hello1", expect_failure=True) -def test_ap_wpa2_eap_eke_many(dev, apdev, params): - """WPA2-Enterprise connection using EAP-EKE (many connections) [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_wpa2_eap_eke_many(dev, apdev): + """WPA2-Enterprise connection using EAP-EKE (many connections)""" params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") hostapd.add_ap(apdev[0], params) success = 0 diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index cee66f98f..54e4eaf6a 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -2513,10 +2513,9 @@ def test_ap_wps_auto_setup_with_config_file(dev, apdev): except: pass -def test_ap_wps_pbc_timeout(dev, apdev, params): - """wpa_supplicant PBC walk time and WPS ER SelReg timeout [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_wps_pbc_timeout(dev, apdev): + """wpa_supplicant PBC walk time and WPS ER SelReg timeout""" ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e" hapd = add_ssdp_ap(apdev[0], ap_uuid) @@ -10422,16 +10421,14 @@ def test_ap_wps_appl_ext(dev, apdev): dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin)) dev[0].wait_connected(timeout=30) -def test_ap_wps_pbc_ap_timeout(dev, apdev, params): - """WPS PBC timeout on AP [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_wps_pbc_ap_timeout(dev, apdev): + """WPS PBC timeout on AP""" run_ap_wps_ap_timeout(dev, apdev, "WPS_PBC") -def test_ap_wps_pin_ap_timeout(dev, apdev, params): - """WPS PIN timeout on AP [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_wps_pin_ap_timeout(dev, apdev): + """WPS PIN timeout on AP""" run_ap_wps_ap_timeout(dev, apdev, "WPS_PIN any 12345670 10") def run_ap_wps_ap_timeout(dev, apdev, cmd): diff --git a/tests/hwsim/test_dfs.py b/tests/hwsim/test_dfs.py index 8851de9d9..3efe6bb2d 100644 --- a/tests/hwsim/test_dfs.py +++ b/tests/hwsim/test_dfs.py @@ -135,10 +135,9 @@ def test_dfs(dev, apdev): finally: clear_regdom(hapd, dev) -def test_dfs_etsi(dev, apdev, params): - """DFS and uniform spreading requirement for ETSI [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dfs_etsi(dev, apdev): + """DFS and uniform spreading requirement for ETSI""" try: hapd = None hapd = start_dfs_ap(apdev[0]) @@ -450,10 +449,9 @@ def test_dfs_radar_ht40minus(dev, apdev): clear_regdom(hapd, dev) dev[0].request("STA_AUTOCONNECT 1") -def test_dfs_ht40_minus(dev, apdev, params): - """DFS CAC functionality on channel 104 HT40- [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dfs_ht40_minus(dev, apdev): + """DFS CAC functionality on channel 104 HT40-""" try: hapd = None hapd = start_dfs_ap(apdev[0], ht40minus=True, channel=104) @@ -505,10 +503,9 @@ def test_dfs_cac_restart_on_enable(dev, apdev): finally: clear_regdom(hapd, dev) -def test_dfs_rrm(dev, apdev, params): - """DFS with RRM [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dfs_rrm(dev, apdev): + """DFS with RRM""" try: hapd = None hapd = start_dfs_ap(apdev[0], country="US", rrm_beacon_report=True) @@ -534,10 +531,9 @@ def test_dfs_rrm(dev, apdev, params): finally: clear_regdom(hapd, dev) -def test_dfs_radar_vht80_downgrade(dev, apdev, params): - """DFS channel bandwidth downgrade from VHT80 to VHT40 [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dfs_radar_vht80_downgrade(dev, apdev): + """DFS channel bandwidth downgrade from VHT80 to VHT40""" try: # Start with 80 MHz channel 100 (5500 MHz) to find a radar hapd = None @@ -609,10 +605,9 @@ def test_dfs_radar_vht80_downgrade(dev, apdev, params): finally: clear_regdom(hapd, dev) -def test_dfs_chan_switch(dev, apdev, params): - """DFS channel switch [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dfs_chan_switch(dev, apdev): + """DFS channel switch""" try: hapd = None hapd = start_dfs_ap(apdev[0], country="US") diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 7c5536515..2cff4c814 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -19,7 +19,7 @@ import time import hostapd import hwsim_utils from hwsim import HWSimRadio -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger +from utils import * from wpasupplicant import WpaSupplicant from wlantest import WlantestCapture @@ -5071,10 +5071,9 @@ def test_dpp_with_p2p_device(dev, apdev): wait_auth_success(wpas, dev[0], configurator=dev[0], enrollee=wpas, allow_enrollee_failure=True) -def test_dpp_chirp(dev, apdev, params): - """DPP chirp [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dpp_chirp(dev, apdev): + """DPP chirp""" check_dpp_capab(dev[0]) dev[0].flush_scan_cache() @@ -5114,10 +5113,9 @@ def test_dpp_chirp(dev, apdev, params): if chan1 != 5 or chan6 != 5 or chan11 != 1: raise Exception("Unexpected number of presence announcements sent: %d %d %d" % (chan1, chan6, chan11)) -def test_dpp_chirp_listen(dev, apdev, params): - """DPP chirp with listen [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dpp_chirp_listen(dev, apdev): + """DPP chirp with listen""" check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index 41407343a..25f53e713 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -420,10 +420,9 @@ def test_he_40(devs, apdevs): dev.request("DISCONNECT") clear_regdom(hapd, devs) -def test_he160(dev, apdev, params): - """HE with 160 MHz channel width (1) [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_he160(dev, apdev): + """HE with 160 MHz channel width (1)""" try: hapd = None params = {"ssid": "he", @@ -492,10 +491,9 @@ def test_he160(dev, apdev, params): dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) dev[0].flush_scan_cache() -def test_he160b(dev, apdev, params): - """HE with 160 MHz channel width (2) [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_he160b(dev, apdev): + """HE with 160 MHz channel width (2)""" try: hapd = None diff --git a/tests/hwsim/test_hostapd_oom.py b/tests/hwsim/test_hostapd_oom.py index a2cc59e2c..169ae015f 100644 --- a/tests/hwsim/test_hostapd_oom.py +++ b/tests/hwsim/test_hostapd_oom.py @@ -10,7 +10,7 @@ logger = logging.getLogger() import time import hostapd -from utils import HwsimSkip +from utils import * def hostapd_oom_loop(apdev, params, start_func="main"): hapd = hostapd.add_ap(apdev[0], {"ssid": "ctrl"}) @@ -125,10 +125,9 @@ def test_hostapd_oom_wpa2_psk_connect(dev, apdev): break dev[0].request("SCAN_INTERVAL 5") -def test_hostapd_oom_wpa2_eap_connect(dev, apdev, params): +@long_duration_test +def test_hostapd_oom_wpa2_eap_connect(dev, apdev): """hostapd failing during WPA2-EAP mode connection due to OOM""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") params['acct_server_addr'] = "127.0.0.1" params['acct_server_port'] = "1813" diff --git a/tests/hwsim/test_p2p_grpform.py b/tests/hwsim/test_p2p_grpform.py index 88c7d7e93..88e253c0b 100644 --- a/tests/hwsim/test_p2p_grpform.py +++ b/tests/hwsim/test_p2p_grpform.py @@ -14,8 +14,7 @@ import os import hostapd import hwsim_utils -import utils -from utils import HwsimSkip +from utils import * from wpasupplicant import WpaSupplicant from p2p_utils import * from test_p2p_messages import parse_p2p_public_action, p2p_hdr, p2p_attr_capability, p2p_attr_go_intent, p2p_attr_config_timeout, p2p_attr_listen_channel, p2p_attr_intended_interface_addr, p2p_attr_channel_list, p2p_attr_device_info, p2p_attr_operating_channel, ie_p2p, ie_wsc, mgmt_tx, P2P_GO_NEG_REQ @@ -46,7 +45,7 @@ def test_grpform_a(dev): raise Exception("Unexpected group interface name") check_grpform_results(i_res, r_res) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") def test_grpform_b(dev): @@ -67,7 +66,7 @@ def test_grpform_b(dev): if "FAIL" not in dev[0].group_request("P2P_GROUP_MEMBER 00:11:22:33:44:55"): raise Exception("P2P_GROUP_MEMBER for non-member accepted") remove_group(dev[0], dev[1]) - if r_res['ifname'] in utils.get_ifnames(): + if r_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") def test_grpform_c(dev): @@ -82,9 +81,9 @@ def test_grpform_c(dev): raise Exception("Unexpected group interface name") check_grpform_results(i_res, r_res) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") - if r_res['ifname'] in utils.get_ifnames(): + if r_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") @remote_compatible @@ -99,9 +98,9 @@ def test_grpform2_c(dev): dev[1].global_request("SET p2p_no_group_iface 0") [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0, r_dev=dev[1], r_intent=15) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") - if r_res['ifname'] in utils.get_ifnames(): + if r_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") @remote_compatible @@ -116,9 +115,9 @@ def test_grpform3_c(dev): dev[1].global_request("SET p2p_no_group_iface 0") [i_res, r_res] = go_neg_pin(i_dev=dev[0], i_intent=15, r_dev=dev[1], r_intent=0) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") - if r_res['ifname'] in utils.get_ifnames(): + if r_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") @remote_compatible @@ -734,11 +733,9 @@ def test_grpform_goneg_fail_with_group_iface(dev): if ev is None: raise Exception("GO Negotiation failure timed out") -def test_grpform_cred_ready_timeout(dev, apdev, params): - """P2P GO Negotiation wait for credentials to become ready [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") - +@long_duration_test +def test_grpform_cred_ready_timeout(dev): + """P2P GO Negotiation wait for credentials to become ready""" dev[1].p2p_listen() addr1 = dev[1].p2p_dev_addr() if not dev[0].discover_peer(addr1): @@ -1181,7 +1178,7 @@ def test_grpform_random_addr(dev): check_grpform_results(i_res, r_res) hwsim_utils.test_connectivity_p2p(dev[0], dev[1]) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") finally: dev[0].global_request("SET p2p_interface_random_mac_addr 0") diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 5db1d28ce..aac49e2d0 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -1294,10 +1294,9 @@ def test_wpas_mesh_password_mismatch(dev, apdev): if count == 0: raise Exception("Neither dev0 nor dev1 reported auth failure") -def test_wpas_mesh_password_mismatch_retry(dev, apdev, params): - """Mesh password mismatch and retry [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_wpas_mesh_password_mismatch_retry(dev, apdev): + """Mesh password mismatch and retry""" check_mesh_support(dev[0], secure=True) dev[0].request("SET sae_groups ") id = add_mesh_secure_net(dev[0]) diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index 66f5285a5..c901dd639 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -30,6 +30,10 @@ class HwsimSkip(Exception): def __str__(self): return self.reason +def long_duration_test(func): + func.long_duration_test = True + return func + class alloc_fail(object): def __init__(self, dev, count, funcs): self._dev = dev From 40341e16a5d0452f5537f7d0aa5e787c01c82345 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 18 Apr 2020 11:05:49 +0300 Subject: [PATCH 0378/1105] tests: Move check_wep_capa() into utils.py Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_params.py | 3 +-- tests/hwsim/test_ap_tdls.py | 1 - tests/hwsim/test_ap_wps.py | 1 - tests/hwsim/test_cfg80211.py | 2 +- tests/hwsim/test_connect_cmd.py | 2 +- tests/hwsim/test_ibss.py | 1 - tests/hwsim/test_ieee8021x.py | 3 +-- tests/hwsim/test_radius.py | 3 +-- tests/hwsim/test_scan.py | 4 +--- tests/hwsim/test_wep.py | 6 +----- tests/hwsim/test_wext.py | 1 - tests/hwsim/test_wpas_ap.py | 3 +-- tests/hwsim/utils.py | 4 ++++ 13 files changed, 12 insertions(+), 22 deletions(-) diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py index 4c5deb8d5..8b5fdea82 100644 --- a/tests/hwsim/test_ap_params.py +++ b/tests/hwsim/test_ap_params.py @@ -15,8 +15,7 @@ import time import hwsim_utils import hostapd from tshark import run_tshark -from utils import alloc_fail, HwsimSkip, parse_ie -from test_wep import check_wep_capa +from utils import * @remote_compatible def test_ap_fragmentation_rts_set_high(dev, apdev): diff --git a/tests/hwsim/test_ap_tdls.py b/tests/hwsim/test_ap_tdls.py index 1af072263..de2f02ac1 100644 --- a/tests/hwsim/test_ap_tdls.py +++ b/tests/hwsim/test_ap_tdls.py @@ -17,7 +17,6 @@ import hostapd from utils import * from wlantest import Wlantest from test_ap_vht import vht_supported -from test_wep import check_wep_capa def start_ap_wpa2_psk(ap): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index 54e4eaf6a..c8514b260 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -44,7 +44,6 @@ from wpasupplicant import WpaSupplicant from utils import * from test_ap_eap import int_eap_server_params from test_sae import check_sae_capab -from test_wep import check_wep_capa def wps_start_ap(apdev, ssid="test-wps-conf"): params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", diff --git a/tests/hwsim/test_cfg80211.py b/tests/hwsim/test_cfg80211.py index 9c7935e70..3ee7a909b 100644 --- a/tests/hwsim/test_cfg80211.py +++ b/tests/hwsim/test_cfg80211.py @@ -16,7 +16,7 @@ import hwsim_utils from tshark import run_tshark from nl80211 import * from wpasupplicant import WpaSupplicant -from test_wep import check_wep_capa +from utils import * def nl80211_command(dev, cmd, attr): res = dev.request("VENDOR ffffffff {} {}".format(nl80211_cmd[cmd], diff --git a/tests/hwsim/test_connect_cmd.py b/tests/hwsim/test_connect_cmd.py index 07a9ab651..3c0985137 100644 --- a/tests/hwsim/test_connect_cmd.py +++ b/tests/hwsim/test_connect_cmd.py @@ -12,7 +12,7 @@ import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant from p2p_utils import * -from test_wep import check_wep_capa +from utils import * def test_connect_cmd_open(dev, apdev): """Open connection using cfg80211 connect command""" diff --git a/tests/hwsim/test_ibss.py b/tests/hwsim/test_ibss.py index 8e688bd73..29ebd8129 100644 --- a/tests/hwsim/test_ibss.py +++ b/tests/hwsim/test_ibss.py @@ -13,7 +13,6 @@ import subprocess import hwsim_utils from utils import * -from test_wep import check_wep_capa def connect_ibss_cmd(dev, id, freq=2412): dev.dump_monitor() diff --git a/tests/hwsim/test_ieee8021x.py b/tests/hwsim/test_ieee8021x.py index 194694819..89c282b39 100644 --- a/tests/hwsim/test_ieee8021x.py +++ b/tests/hwsim/test_ieee8021x.py @@ -13,9 +13,8 @@ import time import hostapd import hwsim_utils -from utils import skip_with_fips +from utils import * from tshark import run_tshark -from test_wep import check_wep_capa logger = logging.getLogger() diff --git a/tests/hwsim/test_radius.py b/tests/hwsim/test_radius.py index 403fbd739..84163f36d 100644 --- a/tests/hwsim/test_radius.py +++ b/tests/hwsim/test_radius.py @@ -18,10 +18,9 @@ import threading import time import hostapd -from utils import HwsimSkip, require_under_vm, skip_with_fips, alloc_fail, fail_test, wait_fail_trigger +from utils import * from test_ap_hs20 import build_dhcp_ack from test_ap_ft import ft_params1 -from test_wep import check_wep_capa def connect(dev, ssid, wait_connect=True): dev.connect(ssid, key_mgmt="WPA-EAP", scan_freq="2412", diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index 56ab9c57d..ef6ebbaf6 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -15,11 +15,9 @@ import subprocess import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, fail_test, alloc_fail, wait_fail_trigger, parse_ie -from utils import clear_regdom_dev +from utils import * from tshark import run_tshark from test_ap_csa import switch_channel, wait_channel_switch, csa_supported -from test_wep import check_wep_capa def check_scan(dev, params, other_started=False, test_busy=False): if not other_started: diff --git a/tests/hwsim/test_wep.py b/tests/hwsim/test_wep.py index 38e34964a..6df9ef899 100644 --- a/tests/hwsim/test_wep.py +++ b/tests/hwsim/test_wep.py @@ -11,11 +11,7 @@ import subprocess from remotehost import remote_compatible import hostapd import hwsim_utils -from utils import clear_regdom, HwsimSkip - -def check_wep_capa(dev): - if "WEP40" not in dev.get_capability("group"): - raise HwsimSkip("WEP not supported") +from utils import * @remote_compatible def test_wep_open_auth(dev, apdev): diff --git a/tests/hwsim/test_wext.py b/tests/hwsim/test_wext.py index f50e1d1b7..e14eecede 100644 --- a/tests/hwsim/test_wext.py +++ b/tests/hwsim/test_wext.py @@ -13,7 +13,6 @@ import hwsim_utils from wpasupplicant import WpaSupplicant from utils import * from test_rfkill import get_rfkill -from test_wep import check_wep_capa def get_wext_interface(): if not os.path.exists("/proc/net/wireless"): diff --git a/tests/hwsim/test_wpas_ap.py b/tests/hwsim/test_wpas_ap.py index 8211b6b8d..b5b43114a 100644 --- a/tests/hwsim/test_wpas_ap.py +++ b/tests/hwsim/test_wpas_ap.py @@ -11,10 +11,9 @@ import logging logger = logging.getLogger() import hwsim_utils -from utils import HwsimSkip, alloc_fail, clear_regdom_dev +from utils import * from wpasupplicant import WpaSupplicant from test_p2p_channel import set_country -from test_wep import check_wep_capa def wait_ap_ready(dev): ev = dev.wait_event(["CTRL-EVENT-CONNECTED"]) diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index c901dd639..ee2f3ee12 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -104,6 +104,10 @@ def skip_without_tkip(dev): "TKIP" not in dev.get_capability("group"): raise HwsimSkip("Cipher TKIP not supported") +def check_wep_capa(dev): + if "WEP40" not in dev.get_capability("group"): + raise HwsimSkip("WEP not supported") + def get_phy(ap, ifname=None): phy = "phy3" try: From 31bdd8b7c70e62e54d80421b8728ced2f7681939 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 18 Apr 2020 11:07:33 +0300 Subject: [PATCH 0379/1105] tests: Move check_sae_capa() into utils.py Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_acs.py | 1 - tests/hwsim/test_ap_wps.py | 1 - tests/hwsim/test_sae.py | 6 +----- tests/hwsim/test_wpas_config.py | 2 +- tests/hwsim/utils.py | 4 ++++ 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index a5644195d..1833c0fd8 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -12,7 +12,6 @@ import hostapd from utils import * from test_ap_ht import clear_scan_cache from test_dfs import wait_dfs_event -from test_sae import check_sae_capab def force_prev_ap_on_24g(ap): # For now, make sure the last operating channel was on 2.4 GHz band to get diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index c8514b260..0ecf2961f 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -43,7 +43,6 @@ import hostapd from wpasupplicant import WpaSupplicant from utils import * from test_ap_eap import int_eap_server_params -from test_sae import check_sae_capab def wps_start_ap(apdev, ssid="test-wps-conf"): params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index 63a61b8f0..ed6ae89dc 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -17,13 +17,9 @@ import subprocess import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger, start_monitor, stop_monitor, radiotap_build +from utils import * from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations -def check_sae_capab(dev): - if "SAE" not in dev.get_capability("auth_alg"): - raise HwsimSkip("SAE not supported") - @remote_compatible def test_sae(dev, apdev): """SAE with default group""" diff --git a/tests/hwsim/test_wpas_config.py b/tests/hwsim/test_wpas_config.py index 14816a0e1..6bf62d0b7 100644 --- a/tests/hwsim/test_wpas_config.py +++ b/tests/hwsim/test_wpas_config.py @@ -10,7 +10,7 @@ import os from wpasupplicant import WpaSupplicant import hostapd -from test_sae import check_sae_capab +from utils import * config_checks = [("ap_scan", "0"), ("update_config", "1"), diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index ee2f3ee12..7f50ab25e 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -108,6 +108,10 @@ def check_wep_capa(dev): if "WEP40" not in dev.get_capability("group"): raise HwsimSkip("WEP not supported") +def check_sae_capab(dev): + if "SAE" not in dev.get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + def get_phy(ap, ifname=None): phy = "phy3" try: From 1bba048d78685373b59f26a276cc3a302ff32e89 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 18 Apr 2020 11:09:36 +0300 Subject: [PATCH 0380/1105] tests: Move vht_supported() into utils.py Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_tdls.py | 1 - tests/hwsim/test_ap_vht.py | 7 ------- tests/hwsim/test_rrm.py | 4 +--- tests/hwsim/utils.py | 7 +++++++ 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/hwsim/test_ap_tdls.py b/tests/hwsim/test_ap_tdls.py index de2f02ac1..05c4ca3e4 100644 --- a/tests/hwsim/test_ap_tdls.py +++ b/tests/hwsim/test_ap_tdls.py @@ -16,7 +16,6 @@ from hostapd import Hostapd import hostapd from utils import * from wlantest import Wlantest -from test_ap_vht import vht_supported def start_ap_wpa2_psk(ap): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index c7851d557..338e8c806 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -18,13 +18,6 @@ from test_dfs import wait_dfs_event from test_ap_csa import csa_supported from test_ap_ht import clear_scan_cache -def vht_supported(): - cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) - reg = cmd.stdout.read() - if "@ 80)" in reg or "@ 160)" in reg: - return True - return False - def test_ap_vht80(dev, apdev): """VHT with 80 MHz channel width""" try: diff --git a/tests/hwsim/test_rrm.py b/tests/hwsim/test_rrm.py index dde98932b..425edb20e 100644 --- a/tests/hwsim/test_rrm.py +++ b/tests/hwsim/test_rrm.py @@ -16,11 +16,9 @@ import time import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger -from utils import disable_hapd, clear_regdom_dev, clear_regdom +from utils import * from test_ap_ht import clear_scan_cache from remotehost import remote_compatible -from test_ap_vht import vht_supported def check_rrm_support(dev): rrm = int(dev.get_driver_status_field("capa.rrm_flags"), 16) diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index 7f50ab25e..57b570c2e 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -112,6 +112,13 @@ def check_sae_capab(dev): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") +def vht_supported(): + cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) + reg = cmd.stdout.read() + if "@ 80)" in reg or "@ 160)" in reg: + return True + return False + def get_phy(ap, ifname=None): phy = "phy3" try: From 0b218771852492ff2417198323577e3a75037a9c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 18 Apr 2020 11:12:54 +0300 Subject: [PATCH 0381/1105] tests: Move clear_scan_cache() and set_world_reg() to utils.py Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_acs.py | 1 - tests/hwsim/test_ap_ht.py | 19 +------------------ tests/hwsim/test_ap_open.py | 1 - tests/hwsim/test_ap_vht.py | 1 - tests/hwsim/test_he.py | 1 - tests/hwsim/test_ocv.py | 3 +-- tests/hwsim/test_p2p_concurrency.py | 3 +-- tests/hwsim/test_rrm.py | 1 - tests/hwsim/test_ssid.py | 8 ++++---- tests/hwsim/test_wpas_mesh.py | 1 - tests/hwsim/utils.py | 18 ++++++++++++++++++ 11 files changed, 25 insertions(+), 32 deletions(-) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index 1833c0fd8..450a38fa1 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -10,7 +10,6 @@ import time import hostapd from utils import * -from test_ap_ht import clear_scan_cache from test_dfs import wait_dfs_event def force_prev_ap_on_24g(ap): diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py index c2b032c11..51187177b 100644 --- a/tests/hwsim/test_ap_ht.py +++ b/tests/hwsim/test_ap_ht.py @@ -12,27 +12,10 @@ import struct import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, parse_ie, clear_regdom +from utils import * import hwsim_utils from test_ap_csa import csa_supported -def clear_scan_cache(apdev): - ifname = apdev['ifname'] - hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'up']) - hostapd.cmd_execute(apdev, ['iw', ifname, 'scan', 'trigger', 'freq', '2412', - 'flush']) - time.sleep(0.1) - hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'down']) - -def set_world_reg(apdev0=None, apdev1=None, dev0=None): - if apdev0: - hostapd.cmd_execute(apdev0, ['iw', 'reg', 'set', '00']) - if apdev1: - hostapd.cmd_execute(apdev1, ['iw', 'reg', 'set', '00']) - if dev0: - dev0.cmd_execute(['iw', 'reg', 'set', '00']) - time.sleep(0.1) - def test_ap_ht40_scan(dev, apdev): """HT40 co-ex scan""" clear_scan_cache(apdev[0]) diff --git a/tests/hwsim/test_ap_open.py b/tests/hwsim/test_ap_open.py index fd9919bb1..62f221542 100644 --- a/tests/hwsim/test_ap_open.py +++ b/tests/hwsim/test_ap_open.py @@ -18,7 +18,6 @@ from tshark import run_tshark from utils import * from wpasupplicant import WpaSupplicant from wlantest import WlantestCapture -from test_ap_ht import set_world_reg @remote_compatible def test_ap_open(dev, apdev): diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 338e8c806..f0e2f3d61 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -16,7 +16,6 @@ from wpasupplicant import WpaSupplicant from utils import * from test_dfs import wait_dfs_event from test_ap_csa import csa_supported -from test_ap_ht import clear_scan_cache def test_ap_vht80(dev, apdev): """VHT with 80 MHz channel width""" diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index 25f53e713..22c9402f7 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -15,7 +15,6 @@ from wpasupplicant import WpaSupplicant from utils import * from test_dfs import wait_dfs_event from test_ap_csa import csa_supported -from test_ap_ht import clear_scan_cache def test_he_open(dev, apdev): """HE AP with open mode configuration""" diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py index df84e7124..5456f3ba0 100644 --- a/tests/hwsim/test_ocv.py +++ b/tests/hwsim/test_ocv.py @@ -12,9 +12,8 @@ logger = logging.getLogger() import hostapd from wpasupplicant import WpaSupplicant import hwsim_utils -from utils import HwsimSkip +from utils import * -from test_ap_ht import set_world_reg from test_ap_psk import parse_eapol, build_eapol, pmk_to_ptk, eapol_key_mic, recv_eapol, send_eapol, reply_eapol, build_eapol_key_3_4, aes_wrap, pad_key_data #TODO: Refuse setting up AP with OCV but without MFP support diff --git a/tests/hwsim/test_p2p_concurrency.py b/tests/hwsim/test_p2p_concurrency.py index 512886ba4..8fb2bb929 100644 --- a/tests/hwsim/test_p2p_concurrency.py +++ b/tests/hwsim/test_p2p_concurrency.py @@ -13,8 +13,7 @@ import time import hwsim_utils import hostapd from p2p_utils import * -from test_ap_ht import clear_scan_cache -from utils import HwsimSkip +from utils import * @remote_compatible def test_concurrent_autogo(dev, apdev): diff --git a/tests/hwsim/test_rrm.py b/tests/hwsim/test_rrm.py index 425edb20e..2b43c4c59 100644 --- a/tests/hwsim/test_rrm.py +++ b/tests/hwsim/test_rrm.py @@ -17,7 +17,6 @@ import time import hostapd from wpasupplicant import WpaSupplicant from utils import * -from test_ap_ht import clear_scan_cache from remotehost import remote_compatible def check_rrm_support(dev): diff --git a/tests/hwsim/test_ssid.py b/tests/hwsim/test_ssid.py index d4ee4e370..faee75d5f 100644 --- a/tests/hwsim/test_ssid.py +++ b/tests/hwsim/test_ssid.py @@ -77,7 +77,7 @@ def test_ssid_utf8(dev, apdev): if "[UTF-8]" not in dev[0].request("SCAN_RESULTS"): raise Exception("[UTF-8] flag not included in SCAN_RESULTS") -def clear_scan_cache(hapd, dev): +def clear_scan_cache2(hapd, dev): # clear BSS table to avoid issues in following test cases dev[0].request("REMOVE_NETWORK all") dev[1].request("REMOVE_NETWORK all") @@ -97,7 +97,7 @@ def test_ssid_hidden(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected connection") - clear_scan_cache(hapd, dev) + clear_scan_cache2(hapd, dev) @remote_compatible def test_ssid_hidden2(dev, apdev): @@ -110,7 +110,7 @@ def test_ssid_hidden2(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected connection") - clear_scan_cache(hapd, dev) + clear_scan_cache2(hapd, dev) @remote_compatible def test_ssid_hidden_wpa2(dev, apdev): @@ -124,4 +124,4 @@ def test_ssid_hidden_wpa2(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected connection") - clear_scan_cache(hapd, dev) + clear_scan_cache2(hapd, dev) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index aac49e2d0..3c918184f 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -18,7 +18,6 @@ import hostapd from wpasupplicant import WpaSupplicant from utils import * from tshark import run_tshark, run_tshark_json -from test_ap_ht import set_world_reg from test_sae import build_sae_commit, sae_rx_commit_token_req from hwsim_utils import set_group_map diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index 57b570c2e..5afa76b24 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -13,6 +13,7 @@ import time import remotehost import logging logger = logging.getLogger() +import hostapd def get_ifnames(): ifnames = [] @@ -224,3 +225,20 @@ def start_monitor(ifname, freq=2412): def stop_monitor(ifname): subprocess.call(["ip", "link", "set", "dev", ifname, "down"]) subprocess.call(["iw", ifname, "set", "type", "managed"]) + +def clear_scan_cache(apdev): + ifname = apdev['ifname'] + hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'up']) + hostapd.cmd_execute(apdev, ['iw', ifname, 'scan', 'trigger', 'freq', '2412', + 'flush']) + time.sleep(0.1) + hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'down']) + +def set_world_reg(apdev0=None, apdev1=None, dev0=None): + if apdev0: + hostapd.cmd_execute(apdev0, ['iw', 'reg', 'set', '00']) + if apdev1: + hostapd.cmd_execute(apdev1, ['iw', 'reg', 'set', '00']) + if dev0: + dev0.cmd_execute(['iw', 'reg', 'set', '00']) + time.sleep(0.1) From 52ed13b78d7606823a2db77e0ecb613348332dbc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 18 Apr 2020 11:31:49 +0300 Subject: [PATCH 0382/1105] tests: Move csa_supported() into utils.py Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_csa.py | 9 +-------- tests/hwsim/test_ap_ht.py | 1 - tests/hwsim/test_ap_vht.py | 1 - tests/hwsim/test_he.py | 1 - tests/hwsim/test_scan.py | 2 +- tests/hwsim/utils.py | 7 +++++++ 6 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tests/hwsim/test_ap_csa.py b/tests/hwsim/test_ap_csa.py index 2bf9c9a8a..744d1e1f2 100644 --- a/tests/hwsim/test_ap_csa.py +++ b/tests/hwsim/test_ap_csa.py @@ -11,7 +11,7 @@ logger = logging.getLogger() import hwsim_utils import hostapd -from utils import HwsimSkip +from utils import * def connect(dev, apdev, scan_freq="2412", **kwargs): params = {"ssid": "ap-csa", @@ -55,13 +55,6 @@ def wait_channel_switch(dev, freq): if "freq=%d" % freq not in ev: raise Exception("Unexpected frequency: " + ev) -# This function checks whether the provided dev, which may be either -# WpaSupplicant or Hostapd supports CSA. -def csa_supported(dev): - res = dev.get_driver_status() - if (int(res['capa.flags'], 0) & 0x80000000) == 0: - raise HwsimSkip("CSA not supported") - @remote_compatible def test_ap_csa_1_switch(dev, apdev): """AP Channel Switch, one switch""" diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py index 51187177b..99adb12a3 100644 --- a/tests/hwsim/test_ap_ht.py +++ b/tests/hwsim/test_ap_ht.py @@ -14,7 +14,6 @@ import hostapd from wpasupplicant import WpaSupplicant from utils import * import hwsim_utils -from test_ap_csa import csa_supported def test_ap_ht40_scan(dev, apdev): """HT40 co-ex scan""" diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index f0e2f3d61..dce0dfff9 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -15,7 +15,6 @@ import hostapd from wpasupplicant import WpaSupplicant from utils import * from test_dfs import wait_dfs_event -from test_ap_csa import csa_supported def test_ap_vht80(dev, apdev): """VHT with 80 MHz channel width""" diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index 22c9402f7..ce3199290 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -14,7 +14,6 @@ import hostapd from wpasupplicant import WpaSupplicant from utils import * from test_dfs import wait_dfs_event -from test_ap_csa import csa_supported def test_he_open(dev, apdev): """HE AP with open mode configuration""" diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index ef6ebbaf6..9bf7a0fd4 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -17,7 +17,7 @@ import hostapd from wpasupplicant import WpaSupplicant from utils import * from tshark import run_tshark -from test_ap_csa import switch_channel, wait_channel_switch, csa_supported +from test_ap_csa import switch_channel, wait_channel_switch def check_scan(dev, params, other_started=False, test_busy=False): if not other_started: diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index 5afa76b24..c259a766c 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -120,6 +120,13 @@ def vht_supported(): return True return False +# This function checks whether the provided dev, which may be either +# WpaSupplicant or Hostapd supports CSA. +def csa_supported(dev): + res = dev.get_driver_status() + if (int(res['capa.flags'], 0) & 0x80000000) == 0: + raise HwsimSkip("CSA not supported") + def get_phy(ap, ifname=None): phy = "phy3" try: From bb9e3935dd1cb0e1d702da51ac9bfa39f7f6dacd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 12:29:00 +0300 Subject: [PATCH 0383/1105] driver: Add second driver capability flags bitmap All 64 bits of the capability flags bitmap are used, so add a new variable to hold future capability bits. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 31 +++++++++++++++++++++++++++++++ hostapd/main.c | 1 + src/ap/hostapd.h | 1 + src/drivers/driver.h | 3 +++ src/drivers/driver_common.c | 10 ++++++++++ wpa_supplicant/ctrl_iface.c | 31 +++++++++++++++++++++++++++++++ wpa_supplicant/mesh.c | 1 + wpa_supplicant/wpa_supplicant.c | 1 + wpa_supplicant/wpa_supplicant_i.h | 1 + 9 files changed, 80 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index c5b258bf1..c6160ded3 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -3105,6 +3105,34 @@ static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf, } +static int hostapd_ctrl_driver_flags2(struct hostapd_iface *iface, char *buf, + size_t buflen) +{ + int ret, i; + char *pos, *end; + + ret = os_snprintf(buf, buflen, "%016llX:\n", + (long long unsigned) iface->drv_flags2); + if (os_snprintf_error(buflen, ret)) + return -1; + + pos = buf + ret; + end = buf + buflen; + + for (i = 0; i < 64; i++) { + if (iface->drv_flags2 & (1LLU << i)) { + ret = os_snprintf(pos, end - pos, "%s\n", + driver_flag2_to_string(1LLU << i)); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } + + return pos - buf; +} + + static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, const char *txtaddr) { @@ -3517,6 +3545,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply, reply_size); + } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { + reply_len = hostapd_ctrl_driver_flags2(hapd->iface, reply, + reply_size); } else if (os_strcmp(buf, "TERMINATE") == 0) { eloop_terminate(); } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { diff --git a/hostapd/main.c b/hostapd/main.c index 4af8e8f9c..6a69412d0 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -218,6 +218,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface) struct wowlan_triggers *triggs; iface->drv_flags = capa.flags; + iface->drv_flags2 = capa.flags2; iface->probe_resp_offloads = capa.probe_resp_offloads; /* * Use default extended capa values from per-radio information diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index ec5b9d57f..fff15f118 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -475,6 +475,7 @@ struct hostapd_iface { struct ap_info *ap_hash[STA_HASH_SIZE]; u64 drv_flags; + u64 drv_flags2; /* * A bitmap of supported protocols for probe response offload. See diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 032bbd892..e01f26c12 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1852,6 +1852,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_EXTENDED_KEY_ID 0x8000000000000000ULL u64 flags; + u64 flags2; + #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ (drv_flags & WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE) @@ -5921,6 +5923,7 @@ wpa_get_wowlan_triggers(const char *wowlan_triggers, const struct wpa_driver_capa *capa); /* Convert driver flag to string */ const char * driver_flag_to_string(u64 flag); +const char * driver_flag2_to_string(u64 flag2); /* NULL terminated array of linked in driver wrappers */ extern const struct wpa_driver_ops *const wpa_drivers[]; diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 63846db2e..c62cf51e3 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -321,3 +321,13 @@ const char * driver_flag_to_string(u64 flag) return "UNKNOWN"; #undef DF2S } + + +const char * driver_flag2_to_string(u64 flag2) +{ +#define DF2S(x) case WPA_DRIVER_FLAGS2_ ## x: return #x + switch (flag2) { + } + return "UNKNOWN"; +#undef DF2S +} diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 13e2f41a9..541de758e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -7960,6 +7960,34 @@ static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s, } +static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s, + char *buf, size_t buflen) +{ + int ret, i; + char *pos, *end; + + ret = os_snprintf(buf, buflen, "%016llX:\n", + (long long unsigned) wpa_s->drv_flags2); + if (os_snprintf_error(buflen, ret)) + return -1; + + pos = buf + ret; + end = buf + buflen; + + for (i = 0; i < 64; i++) { + if (wpa_s->drv_flags2 & (1LLU << i)) { + ret = os_snprintf(pos, end - pos, "%s\n", + driver_flag2_to_string(1LLU << i)); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } + + return pos - buf; +} + + static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) { @@ -10730,6 +10758,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply, reply_size); + } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { + reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply, + reply_size); #ifdef ANDROID } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index b504124fa..c085466b1 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -268,6 +268,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, return -ENOMEM; ifmsh->drv_flags = wpa_s->drv_flags; + ifmsh->drv_flags2 = wpa_s->drv_flags2; ifmsh->num_bss = 1; ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, sizeof(struct hostapd_data *)); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index e29ed83e1..6a69ccebf 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6243,6 +6243,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, if (capa_res == 0) { wpa_s->drv_capa_known = 1; wpa_s->drv_flags = capa.flags; + wpa_s->drv_flags2 = capa.flags2; wpa_s->drv_enc = capa.enc; wpa_s->drv_rrm_flags = capa.rrm_flags; wpa_s->probe_resp_offloads = capa.probe_resp_offloads; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 997e5f642..619ae42b6 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -725,6 +725,7 @@ struct wpa_supplicant { unsigned int no_suitable_network; u64 drv_flags; + u64 drv_flags2; unsigned int drv_enc; unsigned int drv_rrm_flags; From 932546ac285744802f04b10bb091792b3fbf646e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 12:30:55 +0300 Subject: [PATCH 0384/1105] nl80211: Add a separate driver capability for control port RX This is needed since the initial implementation of the control port mechanism in the kernel mixed in RSN pre-authentication ethertype unconditionally (and IMHO, incorrectly) into the control port. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 4 +++- src/drivers/driver_common.c | 1 + src/drivers/driver_nl80211.c | 4 +++- src/drivers/driver_nl80211_capa.c | 3 +++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index e01f26c12..019a1081e 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1838,7 +1838,7 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_FTM_RESPONDER 0x0100000000000000ULL /** Driver support 4-way handshake offload for WPA-Personal */ #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK 0x0200000000000000ULL -/** Driver supports a separate control port for EAPOL frames */ +/** Driver supports a separate control port TX for EAPOL frames */ #define WPA_DRIVER_FLAGS_CONTROL_PORT 0x0400000000000000ULL /** Driver supports VLAN offload */ #define WPA_DRIVER_FLAGS_VLAN_OFFLOAD 0x0800000000000000ULL @@ -1852,6 +1852,8 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_EXTENDED_KEY_ID 0x8000000000000000ULL u64 flags; +/** Driver supports a separate control port RX for EAPOL frames */ +#define WPA_DRIVER_FLAGS2_CONTROL_PORT_RX 0x0000000000000001ULL u64 flags2; #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index c62cf51e3..23a6a4293 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -327,6 +327,7 @@ const char * driver_flag2_to_string(u64 flag2) { #define DF2S(x) case WPA_DRIVER_FLAGS2_ ## x: return #x switch (flag2) { + DF2S(CONTROL_PORT_RX); } return "UNKNOWN"; #undef DF2S diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 21f5000b0..3364054f8 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8124,8 +8124,10 @@ static int nl80211_set_param(void *priv, const char *param) drv->test_use_roc_tx = 1; } - if (os_strstr(param, "control_port=0")) + if (os_strstr(param, "control_port=0")) { drv->capa.flags &= ~WPA_DRIVER_FLAGS_CONTROL_PORT; + drv->capa.flags2 &= ~WPA_DRIVER_FLAGS2_CONTROL_PORT_RX; + } if (os_strstr(param, "full_ap_client_state=0")) drv->capa.flags &= ~WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index b4fed9ea8..f0335912c 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -441,6 +441,9 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211)) capa->flags |= WPA_DRIVER_FLAGS_CONTROL_PORT; + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH)) + capa->flags2 |= WPA_DRIVER_FLAGS2_CONTROL_PORT_RX; if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_VLAN_OFFLOAD)) From 6f70fcd986de35a13808a8f87bc1f7b2ba0765e4 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Sat, 11 Apr 2020 12:25:18 +0200 Subject: [PATCH 0385/1105] nl80211: Check ethertype for control port RX nl80211 control port event handling previously did not differentiate between EAPOL and RSN preauth ethertypes. Add checking of the ethertype and report unexpected frames (only EAPOL frames are supposed to be delivered through this path). Signed-off-by: Markus Theil --- src/drivers/driver_nl80211_event.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index d4ca2eb29..6c4fd68c9 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -2505,12 +2505,34 @@ static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data *drv, static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv, struct nlattr **tb) { - if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_FRAME]) + u8 *src_addr; + u16 ethertype; + + if (!tb[NL80211_ATTR_MAC] || + !tb[NL80211_ATTR_FRAME] || + !tb[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) return; - drv_event_eapol_rx(drv->ctx, nla_data(tb[NL80211_ATTR_MAC]), - nla_data(tb[NL80211_ATTR_FRAME]), - nla_len(tb[NL80211_ATTR_FRAME])); + src_addr = nla_data(tb[NL80211_ATTR_MAC]); + ethertype = nla_get_u16(tb[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]); + + switch (ethertype) { + case ETH_P_RSN_PREAUTH: + wpa_printf(MSG_INFO, "nl80211: Got pre-auth frame from " + MACSTR " over control port unexpectedly", + MAC2STR(src_addr)); + break; + case ETH_P_PAE: + drv_event_eapol_rx(drv->ctx, src_addr, + nla_data(tb[NL80211_ATTR_FRAME]), + nla_len(tb[NL80211_ATTR_FRAME])); + break; + default: + wpa_printf(MSG_INFO, "nl80211: Unxpected ethertype 0x%04x from " + MACSTR " over control port", + ethertype, MAC2STR(src_addr)); + break; + } } From b4a70018ee903b2789dde77ff25ca9929ad5724a Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Sat, 11 Apr 2020 12:25:19 +0200 Subject: [PATCH 0386/1105] nl80211: Handle control port frame in bss events In order to work in AP mode, handle control port frame RX as per bss event. Signed-off-by: Markus Theil --- src/drivers/driver_nl80211_event.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 6c4fd68c9..17a06d8f8 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -2751,9 +2751,6 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, case NL80211_CMD_UPDATE_OWE_INFO: mlme_event_dh_event(drv, bss, tb); break; - case NL80211_CMD_CONTROL_PORT_FRAME: - nl80211_control_port_frame(drv, tb); - break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", cmd); @@ -2843,6 +2840,9 @@ int process_bss_event(struct nl_msg *msg, void *arg) case NL80211_CMD_EXTERNAL_AUTH: nl80211_external_auth(bss->drv, tb); break; + case NL80211_CMD_CONTROL_PORT_FRAME: + nl80211_control_port_frame(bss->drv, tb); + break; default: wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", gnlh->cmd); From 8609aa5ba3d49771f60cbc19a2f18a9ab8fe4085 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Sat, 11 Apr 2020 12:25:21 +0200 Subject: [PATCH 0387/1105] nl80211: Tie connect handle to bss init/destroy This commit creates a connect nl_sock * for every bss unconditionally. It is used in the next commit for nl80211 control port RX. Signed-off-by: Markus Theil --- src/drivers/driver_nl80211.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 3364054f8..228385457 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -158,6 +158,7 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss); static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, struct hostapd_freq_params *freq); +static int nl80211_init_connect_handle(struct i802_bss *bss); static int wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, const u8 *set_addr, int first, @@ -1928,6 +1929,8 @@ static int nl80211_init_bss(struct i802_bss *bss) nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_bss_event, bss); + nl80211_init_connect_handle(bss); + return 0; } @@ -1936,6 +1939,9 @@ static void nl80211_destroy_bss(struct i802_bss *bss) { nl_cb_put(bss->nl_cb); bss->nl_cb = NULL; + + if (bss->nl_connect) + nl80211_destroy_eloop_handle(&bss->nl_connect, 1); } @@ -2715,8 +2721,6 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, if (drv->vendor_cmd_test_avail) qca_vendor_test(drv); - nl80211_init_connect_handle(bss); - return 0; } @@ -2829,9 +2833,6 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) nl80211_del_p2pdev(bss); } - if (bss->nl_connect) - nl80211_destroy_eloop_handle(&bss->nl_connect, 1); - nl80211_destroy_bss(drv->first_bss); os_free(drv->filter_ssids); From 12ea7dee311be52a8f6ae4fb19c356655d71db00 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Sat, 11 Apr 2020 12:25:22 +0200 Subject: [PATCH 0388/1105] nl80211: Use nl80211 control port for receiving EAPOL frames Use and/or set socker owner where necessary to allow EAPOL frames to be received using the nl80211 control port. This is done when the driver indicates support for the control port without previous hardcoded reception of RSN preauth frames. Use methods which set or use the connection owner nl_sock * where necessary. Initial operations need to register with the SOCKET_OWNER attribute set (e.g., connect for STA mode). Final operations need to use the socket which holds the owner attribute (e.g., disconnect for STA mode). Signed-off-by: Markus Theil --- src/drivers/driver_nl80211.c | 100 ++++++++++++++++++++++-------- src/drivers/driver_nl80211.h | 1 + src/drivers/driver_nl80211_scan.c | 2 +- 3 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 228385457..c72dda381 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -438,6 +438,52 @@ int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, } +/* Use this method to mark that it is necessary to own the connection/interface + * for this operation. + * handle may be set to NULL, to get the same behavior as send_and_recv_msgs(). + * set_owner can be used to mark this socket for receiving control port frames. + */ +static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv, + struct nl_msg *msg, + struct nl_sock *handle, int set_owner, + int (*valid_handler)(struct nl_msg *, + void *), + void *valid_data) +{ + /* Control port over nl80211 needs the flags and attributes below. + * + * The Linux kernel has initial checks for them (in nl80211.c) like: + * validate_pae_over_nl80211(...) + * or final checks like: + * dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid + * + * Final operations (e.g., disassociate) don't need to set these + * attributes, but they have to be performed on the socket, which has + * the connection owner property set in the kernel. + */ + if ((drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) && + handle && set_owner && + (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_OVER_NL80211) || + nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER) || + nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) || + nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_PREAUTH))) + return -1; + + return send_and_recv(drv->global, handle ? handle : drv->global->nl, + msg, valid_handler, valid_data); +} + + +struct nl_sock * get_connect_handle(struct i802_bss *bss) +{ + if ((bss->drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) || + bss->use_nl_connect) + return bss->nl_connect; + + return NULL; +} + + struct family_data { const char *group; int id; @@ -3437,18 +3483,14 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss, return nl80211_leave_ibss(drv, 1); } if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { - struct nl_sock *nl_connect = NULL; - - if (bss->use_nl_connect) - nl_connect = bss->nl_connect; return wpa_driver_nl80211_disconnect(drv, reason_code, - nl_connect); + get_connect_handle(bss)); } wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)", __func__, MAC2STR(addr), reason_code); nl80211_mark_disconnected(drv); ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, - reason_code, 0, NULL); + reason_code, 0, get_connect_handle(bss)); /* * For locally generated deauthenticate, supplicant already generates a * DEAUTH event, so ignore the event from NL80211. @@ -4432,7 +4474,8 @@ static int wpa_driver_nl80211_set_ap(void *priv, } #endif /* CONFIG_IEEE80211AX */ - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", ret, strerror(-ret)); @@ -5452,7 +5495,9 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv, int ret; msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, + get_connect_handle(drv->first_bss), 1, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d " "(%s)", ret, strerror(-ret)); @@ -5584,7 +5629,9 @@ retry: if (ret < 0) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, + get_connect_handle(drv->first_bss), 1, + NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)", @@ -5985,12 +6032,8 @@ skip_auth_type: if (ret) goto fail; - if (nl_connect) - ret = send_and_recv(drv->global, nl_connect, msg, - NULL, (void *) -1); - else - ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); - + ret = send_and_recv_msgs_owner(drv, msg, nl_connect, 1, NULL, + (void *) -1); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " @@ -6059,19 +6102,17 @@ static int wpa_driver_nl80211_associate( if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { enum nl80211_iftype nlmode = params->p2p ? NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION; - struct nl_sock *nl_connect = NULL; if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0) return -1; if (params->key_mgmt_suite == WPA_KEY_MGMT_SAE || - params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE) { - nl_connect = bss->nl_connect; + params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE) bss->use_nl_connect = 1; - } else { + else bss->use_nl_connect = 0; - } - return wpa_driver_nl80211_connect(drv, params, nl_connect); + return wpa_driver_nl80211_connect(drv, params, + get_connect_handle(bss)); } nl80211_mark_disconnected(drv); @@ -6106,7 +6147,9 @@ static int wpa_driver_nl80211_associate( goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, + get_connect_handle(drv->first_bss), 1, + NULL, NULL); msg = NULL; if (ret) { wpa_dbg(drv->ctx, MSG_DEBUG, @@ -9502,7 +9545,12 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) < 0) goto fail; - ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf); + /* This test vendor_cmd can be used with nl80211 commands that + * need the connect nl_sock, so use the owner-setting variant + * of send_and_recv_msgs(). */ + ret = send_and_recv_msgs_owner(drv, msg, + get_connect_handle(bss), 0, + cmd_reply_handler, buf); if (ret) wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d", ret); @@ -9957,7 +10005,8 @@ static int nl80211_join_mesh(struct i802_bss *bss, if (nl80211_put_mesh_config(msg, ¶ms->conf) < 0) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1, + NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)", @@ -10014,7 +10063,8 @@ static int wpa_driver_nl80211_leave_mesh(void *priv) wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex); msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 0, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)", ret, strerror(-ret)); diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 6e6c87247..538d40364 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -229,6 +229,7 @@ struct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd); int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), void *valid_data); +struct nl_sock * get_connect_handle(struct i802_bss *bss); int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, const char *ifname, enum nl80211_iftype iftype, const u8 *addr, int wds, diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index 04f6bb879..17e8b2c2e 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -872,7 +872,7 @@ static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv, wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, WLAN_REASON_PREV_AUTH_NOT_VALID, 1, - NULL); + get_connect_handle(drv->first_bss)); } } From c1bc0dd80de855dd766371915bca02ab15af0439 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 15:43:41 +0300 Subject: [PATCH 0389/1105] nl80211: Disable EAPOL TX over control port in AP mode by default Since this nl80211 mechanism for sending EAPOL frames does not currently support TX status notification, disable it by default of AP mode where the Authenticator state machine uses those notifications to optimize retransmission. The control port TX can be enabled for AP mode with driver param control_port_ap=1. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 8 +++++++- src/drivers/driver_nl80211.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index c72dda381..0ffb14dc7 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5328,7 +5328,10 @@ static int wpa_driver_nl80211_hapd_send_eapol( int res; int qos = flags & WPA_STA_WMM; - if (drv->capa.flags & WPA_DRIVER_FLAGS_CONTROL_PORT) + /* For now, disable EAPOL TX over control port in AP mode by default + * since it does not provide TX status notifications. */ + if (drv->control_port_ap && + (drv->capa.flags & WPA_DRIVER_FLAGS_CONTROL_PORT)) return nl80211_tx_control_port(bss, addr, ETH_P_EAPOL, data, data_len, !encrypt); @@ -8173,6 +8176,9 @@ static int nl80211_set_param(void *priv, const char *param) drv->capa.flags2 &= ~WPA_DRIVER_FLAGS2_CONTROL_PORT_RX; } + if (os_strstr(param, "control_port_ap=1")) + drv->control_port_ap = 1; + if (os_strstr(param, "full_ap_client_state=0")) drv->capa.flags &= ~WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE; diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 538d40364..19ac44a42 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -171,6 +171,7 @@ struct wpa_driver_nl80211_data { unsigned int roam_vendor_cmd_avail:1; unsigned int get_supported_akm_suites_avail:1; unsigned int add_sta_node_vendor_cmd_avail:1; + unsigned int control_port_ap:1; u64 vendor_scan_cookie; u64 remain_on_chan_cookie; From 533d06340f86c4205bef92e02d282cf654db9339 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 15:52:42 +0300 Subject: [PATCH 0390/1105] tests: WPA2-PSK AP with nl80211 control port in AP mode Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_psk.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index b741cca71..f52e38843 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -3359,6 +3359,39 @@ def test_ap_wpa2_psk_no_control_port(dev, apdev): wpas.wait_disconnected() wpas.dump_monitor() +def test_ap_wpa2_psk_ap_control_port(dev, apdev): + """WPA2-PSK AP with nl80211 control port in AP mode""" + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params['driver_params'] = "control_port_ap=1" + hapd = hostapd.add_ap(apdev[0], params) + + flags = hapd.request("DRIVER_FLAGS").splitlines()[1:] + flags2 = hapd.request("DRIVER_FLAGS2").splitlines()[1:] + logger.info("AP driver flags: " + str(flags)) + logger.info("AP driver flags2: " + str(flags2)) + if 'CONTROL_PORT' not in flags or 'CONTROL_PORT_RX' not in flags2: + raise HwsimSkip("No AP driver support for CONTROL_PORT") + + flags = dev[0].request("DRIVER_FLAGS").splitlines()[1:] + flags2 = dev[0].request("DRIVER_FLAGS2").splitlines()[1:] + logger.info("STA driver flags: " + str(flags)) + logger.info("STA driver flags2: " + str(flags2)) + if 'CONTROL_PORT' not in flags or 'CONTROL_PORT_RX' not in flags2: + raise HwsimSkip("No STA driver support for CONTROL_PORT") + + dev[0].connect(ssid, psk=passphrase, scan_freq="2412") + hapd.wait_sta() + hwsim_utils.test_connectivity(dev[0], hapd) + if "OK" not in dev[0].request("KEY_REQUEST 0 1"): + raise Exception("KEY_REQUEST failed") + ev = dev[0].wait_event(["WPA: Key negotiation completed"]) + if ev is None: + raise Exception("PTK rekey timed out") + hapd.wait_ptkinitdone(dev[0].own_addr()) + hwsim_utils.test_connectivity(dev[0], hapd) + def test_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev): """RSNE mismatch in EAPOL-Key msg 3/4""" ie = "30140100000fac040100000fac040100000fac020c80" From 9d6334e811f72e4b6a843ba3e9d7e2f7dc807acd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 16:13:26 +0300 Subject: [PATCH 0391/1105] Do not open l2_packet bridge workaround socket if control port is used This allows wpa_supplicant to avoid the packet socket workaround for cases where a bridge interface is used if the driver supports control port for EAPOL frame TX and RX. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 6a69ccebf..1941efa90 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4761,6 +4761,13 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, } +static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s) +{ + return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) || + !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX); +} + + int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) { if ((!wpa_s->p2p_mgmt || @@ -4847,7 +4854,7 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN); wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); - if (wpa_s->bridge_ifname[0]) { + if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) { wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge " "interface '%s'", wpa_s->bridge_ifname); wpa_s->l2_br = l2_packet_init_bridge( From c3bb8865a014c0b26861b5147269beae5331353a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 16:15:18 +0300 Subject: [PATCH 0392/1105] Clean up l2_packet_get_own_addr() call There is no need for this to be outside the if block that is used to check whether l2_packet is used for the interface. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 1941efa90..5703319d2 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4785,17 +4785,18 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) L2_PACKET_FILTER_PKTTYPE)) wpa_dbg(wpa_s, MSG_DEBUG, "Failed to attach pkt_type filter"); + + if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { + wpa_msg(wpa_s, MSG_ERROR, + "Failed to get own L2 address"); + return -1; + } } else { const u8 *addr = wpa_drv_get_mac_addr(wpa_s); if (addr) os_memcpy(wpa_s->own_addr, addr, ETH_ALEN); } - if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { - wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address"); - return -1; - } - wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); wpas_wps_update_mac_addr(wpa_s); From e480ed38ebc4a2db068108a68f79e188139a9c13 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 17:41:38 +0300 Subject: [PATCH 0393/1105] tests: ap_open_out_of_memory to skip i802_init test if needed The eloop_register_read_sock() call in i802_init() will be skipped if the driver supports control port for EAPOL RX, so need to skip this part of the test case conditionally. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_open.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_open.py b/tests/hwsim/test_ap_open.py index 62f221542..2919cda52 100644 --- a/tests/hwsim/test_ap_open.py +++ b/tests/hwsim/test_ap_open.py @@ -277,6 +277,7 @@ def hapd_out_of_mem(hapd, apdev, count, func): def test_ap_open_out_of_memory(dev, apdev): """hostapd failing to setup interface due to allocation failure""" hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) + flags2 = hapd.request("DRIVER_FLAGS2").splitlines()[1:] hapd_out_of_mem(hapd, apdev[1], 1, "hostapd_alloc_bss_data") for i in range(1, 3): @@ -292,8 +293,9 @@ def test_ap_open_out_of_memory(dev, apdev): for i in range(1, 3): hapd_out_of_mem(hapd, apdev[1], i, "=wpa_driver_nl80211_drv_init") - # eloop_register_read_sock() call from i802_init() - hapd_out_of_mem(hapd, apdev[1], 1, "eloop_sock_table_add_sock;?eloop_register_sock;?eloop_register_read_sock;=i802_init") + if 'CONTROL_PORT_RX' not in flags2: + # eloop_register_read_sock() call from i802_init() + hapd_out_of_mem(hapd, apdev[1], 1, "eloop_sock_table_add_sock;?eloop_register_sock;?eloop_register_read_sock;=i802_init") # verify that a new interface can still be added when memory allocation does # not fail From 95cbf450909abd4e45793c479d8e0d00618d3618 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 16:25:27 +0300 Subject: [PATCH 0394/1105] nl80211: Do not open EAPOL RX socket when using control port for RX (AP) drv->eapol_sock is used only for receiving EAPOL frames in AP mode, so it is not needed when using control port for EAPOL frame RX. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 0ffb14dc7..e221e5867 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -7288,6 +7288,12 @@ static void *i802_init(struct hostapd_data *hapd, } #endif /* CONFIG_LIBNL3_ROUTE */ + if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) { + wpa_printf(MSG_DEBUG, + "nl80211: Do not open EAPOL RX socket - using control port for RX"); + goto skip_eapol_sock; + } + drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); if (drv->eapol_sock < 0) { wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s", @@ -7300,6 +7306,7 @@ static void *i802_init(struct hostapd_data *hapd, wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol"); goto failed; } +skip_eapol_sock: if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, params->own_addr)) From 7a880b129de8f439324ab0c04a20417af022a29c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 16:36:47 +0300 Subject: [PATCH 0395/1105] l2_packet: Allow initialization without RX handling This can be used to minimize resource use when receive path is not needed. Signed-off-by: Jouni Malinen --- src/l2_packet/l2_packet.h | 4 ++++ src/l2_packet/l2_packet_freebsd.c | 2 +- src/l2_packet/l2_packet_linux.c | 6 ++++-- src/l2_packet/l2_packet_ndis.c | 3 ++- src/l2_packet/l2_packet_none.c | 4 ++-- src/l2_packet/l2_packet_pcap.c | 4 ++-- src/l2_packet/l2_packet_privsep.c | 3 ++- src/l2_packet/l2_packet_winpcap.c | 3 +++ 8 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/l2_packet/l2_packet.h b/src/l2_packet/l2_packet.h index 53871774b..6a862806f 100644 --- a/src/l2_packet/l2_packet.h +++ b/src/l2_packet/l2_packet.h @@ -61,6 +61,10 @@ enum l2_packet_filter_type { * points to len bytes of the payload after the layer 2 header and similarly, * TX buffers start with payload. This behavior can be changed by setting * l2_hdr=1 to include the layer 2 header in the data buffer. + * + * IF rx_callback is NULL, receive operation is not opened at all, i.e., only + * the TX path and additional helper functions for fetching MAC and IP + * addresses can be used. */ struct l2_packet_data * l2_packet_init( const char *ifname, const u8 *own_addr, unsigned short protocol, diff --git a/src/l2_packet/l2_packet_freebsd.c b/src/l2_packet/l2_packet_freebsd.c index aa8364827..60de9fe6b 100644 --- a/src/l2_packet/l2_packet_freebsd.c +++ b/src/l2_packet/l2_packet_freebsd.c @@ -84,7 +84,7 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) packet = pcap_next(pcap, &hdr); - if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) + if (!l2->rx_callback || !packet || hdr.caplen < sizeof(*ethhdr)) return; ethhdr = (struct l2_ethhdr *) packet; diff --git a/src/l2_packet/l2_packet_linux.c b/src/l2_packet/l2_packet_linux.c index 138dcafcf..7897bc026 100644 --- a/src/l2_packet/l2_packet_linux.c +++ b/src/l2_packet/l2_packet_linux.c @@ -312,7 +312,8 @@ struct l2_packet_data * l2_packet_init( ll.sll_family = PF_PACKET; ll.sll_ifindex = ifr.ifr_ifindex; ll.sll_protocol = htons(protocol); - if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) { + if (rx_callback && + bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) { wpa_printf(MSG_ERROR, "%s: bind[PF_PACKET]: %s", __func__, strerror(errno)); close(l2->fd); @@ -329,7 +330,8 @@ struct l2_packet_data * l2_packet_init( } os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); + if (rx_callback) + eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); return l2; } diff --git a/src/l2_packet/l2_packet_ndis.c b/src/l2_packet/l2_packet_ndis.c index 716778164..4a4b639fd 100644 --- a/src/l2_packet/l2_packet_ndis.c +++ b/src/l2_packet/l2_packet_ndis.c @@ -294,7 +294,8 @@ static void l2_packet_callback(struct l2_packet_data *l2) } rx_src = ethhdr->h_source; - l2->rx_callback(l2->rx_callback_ctx, rx_src, rx_buf, rx_len); + if (l2->rx_callback) + l2->rx_callback(l2->rx_callback_ctx, rx_src, rx_buf, rx_len); #ifndef _WIN32_WCE l2_ndisuio_start_read(l2, 1); #endif /* _WIN32_WCE */ diff --git a/src/l2_packet/l2_packet_none.c b/src/l2_packet/l2_packet_none.c index 307fc6daa..bc7a4e82d 100644 --- a/src/l2_packet/l2_packet_none.c +++ b/src/l2_packet/l2_packet_none.c @@ -84,7 +84,7 @@ struct l2_packet_data * l2_packet_init( * TODO: open connection for receiving frames */ l2->fd = -1; - if (l2->fd >= 0) + if (rx_callback && l2->fd >= 0) eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); return l2; @@ -112,7 +112,7 @@ void l2_packet_deinit(struct l2_packet_data *l2) eloop_unregister_read_sock(l2->fd); /* TODO: close connection */ } - + os_free(l2); } diff --git a/src/l2_packet/l2_packet_pcap.c b/src/l2_packet/l2_packet_pcap.c index 423c099fd..c2b17fcf8 100644 --- a/src/l2_packet/l2_packet_pcap.c +++ b/src/l2_packet/l2_packet_pcap.c @@ -127,7 +127,7 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) packet = pcap_next(pcap, &hdr); - if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) + if (!l2->rx_callback || !packet || hdr.caplen < sizeof(*ethhdr)) return; ethhdr = (struct l2_ethhdr *) packet; @@ -152,7 +152,7 @@ static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr, unsigned char *buf; size_t len; - if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr)) + if (!l2->rx_callback || !pkt_data || hdr->caplen < sizeof(*ethhdr)) return; ethhdr = (struct l2_ethhdr *) pkt_data; diff --git a/src/l2_packet/l2_packet_privsep.c b/src/l2_packet/l2_packet_privsep.c index ce86802c2..014a45f34 100644 --- a/src/l2_packet/l2_packet_privsep.c +++ b/src/l2_packet/l2_packet_privsep.c @@ -216,7 +216,8 @@ struct l2_packet_data * l2_packet_init( } os_memcpy(l2->own_addr, reply, ETH_ALEN); - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); + if (rx_callback) + eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); return l2; diff --git a/src/l2_packet/l2_packet_winpcap.c b/src/l2_packet/l2_packet_winpcap.c index 74085a316..3452051f5 100644 --- a/src/l2_packet/l2_packet_winpcap.c +++ b/src/l2_packet/l2_packet_winpcap.c @@ -224,6 +224,9 @@ struct l2_packet_data * l2_packet_init( return NULL; } + if (!rx_callback) + return l2; + l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); l2->rx_done = CreateEvent(NULL, TRUE, FALSE, NULL); l2->rx_notify = CreateEvent(NULL, TRUE, FALSE, NULL); From 2c70b7d0b4adbcfc8a9e178edea4503b61f23d2c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 16:38:29 +0300 Subject: [PATCH 0396/1105] Do not open l2_packet(EAPOL) for receive unnecessarily If the driver supports control port for EAPOL RX, do not register l2_packet for RX to minimize unnecessary operation load. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 5703319d2..50478c11e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4777,7 +4777,9 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) wpa_s->l2 = l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_EAPOL, - wpa_supplicant_rx_eapol, wpa_s, 0); + wpas_eapol_needs_l2_packet(wpa_s) ? + wpa_supplicant_rx_eapol : NULL, + wpa_s, 0); if (wpa_s->l2 == NULL) return -1; From 01152687432f672000b6b66963dad1134c56cfba Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 16:41:47 +0300 Subject: [PATCH 0397/1105] nl80211: Move nl80211_init_connect_handle() to avoid forward declaration This has no changes to the function itself, i.e., it is just moved to a location that is above the first caller. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 39 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index e221e5867..75792f340 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -158,7 +158,6 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss); static int wpa_driver_nl80211_set_mode_ibss(struct i802_bss *bss, struct hostapd_freq_params *freq); -static int nl80211_init_connect_handle(struct i802_bss *bss); static int wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, const u8 *set_addr, int first, @@ -1964,6 +1963,25 @@ static void wpa_driver_nl80211_handle_eapol_tx_status(int sock, } +static int nl80211_init_connect_handle(struct i802_bss *bss) +{ + if (bss->nl_connect) { + wpa_printf(MSG_DEBUG, + "nl80211: Connect handle already created (nl_connect=%p)", + bss->nl_connect); + return -1; + } + + bss->nl_connect = nl_create_handle(bss->nl_cb, "connect"); + if (!bss->nl_connect) + return -1; + nl80211_register_eloop_read(&bss->nl_connect, + wpa_driver_nl80211_event_receive, + bss->nl_cb, 1); + return 0; +} + + static int nl80211_init_bss(struct i802_bss *bss) { bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); @@ -2211,25 +2229,6 @@ static int nl80211_register_action_frame(struct i802_bss *bss, } -static int nl80211_init_connect_handle(struct i802_bss *bss) -{ - if (bss->nl_connect) { - wpa_printf(MSG_DEBUG, - "nl80211: Connect handle already created (nl_connect=%p)", - bss->nl_connect); - return -1; - } - - bss->nl_connect = nl_create_handle(bss->nl_cb, "connect"); - if (!bss->nl_connect) - return -1; - nl80211_register_eloop_read(&bss->nl_connect, - wpa_driver_nl80211_event_receive, - bss->nl_cb, 1); - return 0; -} - - static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) { struct wpa_driver_nl80211_data *drv = bss->drv; From f23b70f163781ad3c063469741be12c762c2078e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 16:56:35 +0300 Subject: [PATCH 0398/1105] Silence compiler warning in no-NEED_AP_MLME hostapd builds The static function hostapd_ctrl_check_freq_params() was called only within #ifdef NEED_AP_MLME block so the function needs to be defined under matching condition. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index c6160ded3..6e8352f2f 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2439,6 +2439,7 @@ static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd, #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef NEED_AP_MLME static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) { switch (params->bandwidth) { @@ -2527,6 +2528,7 @@ static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) return 0; } +#endif /* NEED_AP_MLME */ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, From 3e6383f31a09c3c3bb9b7b93f6b1d2856d66e487 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 19 Apr 2020 16:58:59 +0300 Subject: [PATCH 0399/1105] DPP2: Silence compiler warning with no-CONFIG_DPP2 and OpenSSL 1.0.2 EVP_PKEY_get0_EC_KEY() compatibility wrapper is used only within CONFIG_DPP2 blocks, so define it with matching condition. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/dpp.c b/src/common/dpp.c index c4ee9b8ab..080c86aab 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -74,12 +74,14 @@ static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, } +#ifdef CONFIG_DPP2 static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { if (pkey->type != EVP_PKEY_EC) return NULL; return pkey->pkey.ec; } +#endif /* CONFIG_DPP2 */ #endif From 99cf89555313056d3a8fa54b21d02dc880b363e1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 20 Apr 2020 20:29:31 +0300 Subject: [PATCH 0400/1105] Include stdbool.h to allow C99 bool to be used We have practically started requiring some C99 features, so might as well finally go ahead and bring in the C99 bool as well. Signed-off-by: Jouni Malinen --- src/utils/includes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/includes.h b/src/utils/includes.h index 75513fc8c..741fc9c14 100644 --- a/src/utils/includes.h +++ b/src/utils/includes.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include From 4d2ec436e3ef249e47de6eac3e8e2d4aee077d68 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 20 Apr 2020 23:52:04 +0300 Subject: [PATCH 0401/1105] DPP: Add driver operation for enabling/disabling listen mode This can be used to configure RX filter to be able to receive broadcast DPP Public Action frames. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 11 +++++++++++ wpa_supplicant/dpp_supplicant.c | 2 ++ wpa_supplicant/driver_i.h | 7 +++++++ 3 files changed, 20 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 019a1081e..c624c29c9 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4424,6 +4424,17 @@ struct wpa_driver_ops { */ int (*update_dh_ie)(void *priv, const u8 *peer_mac, u16 reason_code, const u8 *ie, size_t ie_len); + + /** + * dpp_listen - Notify driver about start/stop of DPP listen + * @priv: Private driver interface data + * @enable: Whether listen state is enabled (or disabled) + * Returns: 0 on success, -1 on failure + * + * This optional callback can be used to update RX frame filtering to + * explicitly allow reception of broadcast Public Action frames. + */ + int (*dpp_listen)(void *priv, bool enable); }; /** diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index f90463ff6..351f8da9d 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -857,6 +857,7 @@ static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit) } wpa_s->off_channel_freq = 0; wpa_s->roc_waiting_drv_freq = lwork->freq; + wpa_drv_dpp_listen(wpa_s, true); } @@ -931,6 +932,7 @@ void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz", wpa_s->dpp_listen_freq); wpa_drv_cancel_remain_on_channel(wpa_s); + wpa_drv_dpp_listen(wpa_s, false); wpa_s->dpp_listen_freq = 0; wpas_dpp_listen_work_done(wpa_s); } diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 6a03d8e91..d0bcc6c00 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -1108,4 +1108,11 @@ static inline int wpa_drv_set_4addr_mode(struct wpa_supplicant *wpa_s, int val) wpa_s->bridge_ifname, val); } +static inline int wpa_drv_dpp_listen(struct wpa_supplicant *wpa_s, bool enable) +{ + if (!wpa_s->driver->dpp_listen) + return 0; + return wpa_s->driver->dpp_listen(wpa_s->drv_priv, enable); +} + #endif /* DRIVER_I_H */ From 60a2de56833c1de4eca57afe646bb23f079dd810 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 21 Apr 2020 00:16:16 +0300 Subject: [PATCH 0402/1105] EAP server: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/eap_server/eap.h | 34 +++---- src/eap_server/eap_i.h | 23 ++--- src/eap_server/eap_server.c | 130 ++++++++++++------------ src/eap_server/eap_server_aka.c | 28 ++--- src/eap_server/eap_server_eke.c | 20 ++-- src/eap_server/eap_server_fast.c | 12 +-- src/eap_server/eap_server_gpsk.c | 16 +-- src/eap_server/eap_server_gtc.c | 12 +-- src/eap_server/eap_server_identity.c | 14 +-- src/eap_server/eap_server_ikev2.c | 12 +-- src/eap_server/eap_server_md5.c | 14 +-- src/eap_server/eap_server_mschapv2.c | 18 ++-- src/eap_server/eap_server_pax.c | 32 +++--- src/eap_server/eap_server_peap.c | 12 +-- src/eap_server/eap_server_psk.c | 18 ++-- src/eap_server/eap_server_pwd.c | 18 ++-- src/eap_server/eap_server_sake.c | 24 ++--- src/eap_server/eap_server_sim.c | 30 +++--- src/eap_server/eap_server_teap.c | 12 +-- src/eap_server/eap_server_tls.c | 12 +-- src/eap_server/eap_server_tnc.c | 20 ++-- src/eap_server/eap_server_ttls.c | 12 +-- src/eap_server/eap_server_vendor_test.c | 12 +-- src/eap_server/eap_server_wsc.c | 14 +-- 24 files changed, 274 insertions(+), 275 deletions(-) diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h index 540b4e70b..61032cc01 100644 --- a/src/eap_server/eap.h +++ b/src/eap_server/eap.h @@ -45,43 +45,43 @@ struct eap_user { struct eap_eapol_interface { /* Lower layer to full authenticator variables */ - Boolean eapResp; /* shared with EAPOL Backend Authentication */ + bool eapResp; /* shared with EAPOL Backend Authentication */ struct wpabuf *eapRespData; - Boolean portEnabled; + bool portEnabled; int retransWhile; - Boolean eapRestart; /* shared with EAPOL Authenticator PAE */ + bool eapRestart; /* shared with EAPOL Authenticator PAE */ int eapSRTT; int eapRTTVAR; /* Full authenticator to lower layer variables */ - Boolean eapReq; /* shared with EAPOL Backend Authentication */ - Boolean eapNoReq; /* shared with EAPOL Backend Authentication */ - Boolean eapSuccess; - Boolean eapFail; - Boolean eapTimeout; + bool eapReq; /* shared with EAPOL Backend Authentication */ + bool eapNoReq; /* shared with EAPOL Backend Authentication */ + bool eapSuccess; + bool eapFail; + bool eapTimeout; struct wpabuf *eapReqData; u8 *eapKeyData; size_t eapKeyDataLen; u8 *eapSessionId; size_t eapSessionIdLen; - Boolean eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */ + bool eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */ /* AAA interface to full authenticator variables */ - Boolean aaaEapReq; - Boolean aaaEapNoReq; - Boolean aaaSuccess; - Boolean aaaFail; + bool aaaEapReq; + bool aaaEapNoReq; + bool aaaSuccess; + bool aaaFail; struct wpabuf *aaaEapReqData; u8 *aaaEapKeyData; size_t aaaEapKeyDataLen; - Boolean aaaEapKeyAvailable; + bool aaaEapKeyAvailable; int aaaMethodTimeout; /* Full authenticator to AAA interface variables */ - Boolean aaaEapResp; + bool aaaEapResp; struct wpabuf *aaaEapRespData; /* aaaIdentity -> eap_get_identity() */ - Boolean aaaTimeout; + bool aaaTimeout; }; struct eap_server_erp_key { @@ -124,7 +124,7 @@ struct eap_config { * callback context. */ void *eap_sim_db_priv; - Boolean backend_auth; + bool backend_auth; int eap_server; /** diff --git a/src/eap_server/eap_i.h b/src/eap_server/eap_i.h index 44896a695..28bb564e9 100644 --- a/src/eap_server/eap_i.h +++ b/src/eap_server/eap_i.h @@ -32,15 +32,14 @@ struct eap_method { struct wpabuf * (*buildReq)(struct eap_sm *sm, void *priv, u8 id); int (*getTimeout)(struct eap_sm *sm, void *priv); - Boolean (*check)(struct eap_sm *sm, void *priv, - struct wpabuf *respData); + bool (*check)(struct eap_sm *sm, void *priv, struct wpabuf *respData); void (*process)(struct eap_sm *sm, void *priv, struct wpabuf *respData); - Boolean (*isDone)(struct eap_sm *sm, void *priv); + bool (*isDone)(struct eap_sm *sm, void *priv); u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); /* isSuccess is not specified in draft-ietf-eap-statemachine-05.txt, * but it is useful in implementing Policy.getDecision() */ - Boolean (*isSuccess)(struct eap_sm *sm, void *priv); + bool (*isSuccess)(struct eap_sm *sm, void *priv); /** * free - Free EAP method data @@ -138,13 +137,13 @@ struct eap_sm { int methodTimeout; /* Short-term (not maintained between packets) */ - Boolean rxResp; - Boolean rxInitiate; + bool rxResp; + bool rxInitiate; int respId; enum eap_type respMethod; int respVendor; u32 respVendorMethod; - Boolean ignore; + bool ignore; enum { DECISION_SUCCESS, DECISION_FAILURE, DECISION_CONTINUE, DECISION_PASSTHROUGH, DECISION_INITIATE_REAUTH_START @@ -153,7 +152,7 @@ struct eap_sm { /* Miscellaneous variables */ const struct eap_method *m; /* selected EAP method */ /* not defined in RFC 4137 */ - Boolean changed; + bool changed; void *eapol_ctx; const struct eapol_callbacks *eapol_cb; void *eap_method_priv; @@ -169,7 +168,7 @@ struct eap_sm { int init_phase2; const struct eap_config *cfg; struct eap_config cfg_buf; - Boolean update_user; + bool update_user; unsigned int num_rounds; unsigned int num_rounds_short; @@ -183,12 +182,12 @@ struct eap_sm { struct wpabuf *assoc_wps_ie; struct wpabuf *assoc_p2p_ie; - Boolean start_reauth; + bool start_reauth; u8 peer_addr[ETH_ALEN]; - Boolean initiate_reauth_start_sent; - Boolean try_initiate_reauth; + bool initiate_reauth_start_sent; + bool try_initiate_reauth; #ifdef CONFIG_TESTING_OPTIONS u32 tls_test_flags; diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c index 34ce23946..0b7a5b98c 100644 --- a/src/eap_server/eap_server.c +++ b/src/eap_server/eap_server.c @@ -9,7 +9,7 @@ * in RFC 4137. However, to support backend authentication in RADIUS * authentication server functionality, parts of backend authenticator (also * from RFC 4137) are mixed in. This functionality is enabled by setting - * backend_auth configuration variable to TRUE. + * backend_auth configuration variable to true. */ #include "includes.h" @@ -38,7 +38,7 @@ static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, static enum eap_type eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor); static int eap_sm_Policy_getDecision(struct eap_sm *sm); -static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method); +static bool eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method); static int eap_get_erp_send_reauth_start(struct eap_sm *sm) @@ -230,19 +230,19 @@ SM_STATE(EAP, INITIALIZE) eap_server_clear_identity(sm); } - sm->try_initiate_reauth = FALSE; + sm->try_initiate_reauth = false; sm->currentId = -1; - sm->eap_if.eapSuccess = FALSE; - sm->eap_if.eapFail = FALSE; - sm->eap_if.eapTimeout = FALSE; + sm->eap_if.eapSuccess = false; + sm->eap_if.eapFail = false; + sm->eap_if.eapTimeout = false; bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); sm->eap_if.eapKeyData = NULL; sm->eap_if.eapKeyDataLen = 0; os_free(sm->eap_if.eapSessionId); sm->eap_if.eapSessionId = NULL; sm->eap_if.eapSessionIdLen = 0; - sm->eap_if.eapKeyAvailable = FALSE; - sm->eap_if.eapRestart = FALSE; + sm->eap_if.eapKeyAvailable = false; + sm->eap_if.eapRestart = false; /* * This is not defined in RFC 4137, but method state needs to be @@ -322,7 +322,7 @@ SM_STATE(EAP, RETRANSMIT) sm->retransCount++; if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) - sm->eap_if.eapReq = TRUE; + sm->eap_if.eapReq = true; } wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_RETRANSMIT MACSTR, @@ -347,8 +347,8 @@ SM_STATE(EAP, RECEIVED) SM_STATE(EAP, DISCARD) { SM_ENTRY(EAP, DISCARD); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapNoReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapNoReq = true; } @@ -362,17 +362,17 @@ SM_STATE(EAP, SEND_REQUEST) sm->num_rounds_short = 0; if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = true; } else { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = false; } } else { wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData"); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - sm->eap_if.eapNoReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = false; + sm->eap_if.eapNoReq = true; } } @@ -382,7 +382,7 @@ SM_STATE(EAP, INTEGRITY_CHECK) SM_ENTRY(EAP, INTEGRITY_CHECK); if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) { - sm->ignore = TRUE; + sm->ignore = true; return; } @@ -552,7 +552,7 @@ SM_STATE(EAP, PROPOSE_METHOD) SM_ENTRY(EAP, PROPOSE_METHOD); - sm->try_initiate_reauth = FALSE; + sm->try_initiate_reauth = false; try_another_method: type = eap_sm_Policy_getNextMethod(sm, &vendor); if (vendor == EAP_VENDOR_IETF) @@ -640,7 +640,7 @@ SM_STATE(EAP, TIMEOUT_FAILURE) { SM_ENTRY(EAP, TIMEOUT_FAILURE); - sm->eap_if.eapTimeout = TRUE; + sm->eap_if.eapTimeout = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TIMEOUT_FAILURE MACSTR, MAC2STR(sm->peer_addr)); @@ -655,7 +655,7 @@ SM_STATE(EAP, FAILURE) sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId); wpabuf_free(sm->lastReqData); sm->lastReqData = NULL; - sm->eap_if.eapFail = TRUE; + sm->eap_if.eapFail = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE MACSTR, MAC2STR(sm->peer_addr)); @@ -671,8 +671,8 @@ SM_STATE(EAP, SUCCESS) wpabuf_free(sm->lastReqData); sm->lastReqData = NULL; if (sm->eap_if.eapKeyData) - sm->eap_if.eapKeyAvailable = TRUE; - sm->eap_if.eapSuccess = TRUE; + sm->eap_if.eapKeyAvailable = true; + sm->eap_if.eapSuccess = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS MACSTR, MAC2STR(sm->peer_addr)); @@ -683,8 +683,8 @@ SM_STATE(EAP, INITIATE_REAUTH_START) { SM_ENTRY(EAP, INITIATE_REAUTH_START); - sm->initiate_reauth_start_sent = TRUE; - sm->try_initiate_reauth = TRUE; + sm->initiate_reauth_start_sent = true; + sm->try_initiate_reauth = true; sm->currentId = eap_sm_nextId(sm, sm->currentId); wpa_printf(MSG_DEBUG, "EAP: building EAP-Initiate-Re-auth-Start: Identifier %d", @@ -760,7 +760,7 @@ static void erp_send_finish_reauth(struct eap_sm *sm, sm->lastReqData = NULL; if ((flags & 0x80) || !erp) { - sm->eap_if.eapFail = TRUE; + sm->eap_if.eapFail = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE MACSTR, MAC2STR(sm->peer_addr)); return; @@ -784,10 +784,10 @@ static void erp_send_finish_reauth(struct eap_sm *sm, return; } sm->eap_if.eapKeyDataLen = erp->rRK_len; - sm->eap_if.eapKeyAvailable = TRUE; + sm->eap_if.eapKeyAvailable = true; wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK", sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); - sm->eap_if.eapSuccess = TRUE; + sm->eap_if.eapSuccess = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS MACSTR, MAC2STR(sm->peer_addr)); @@ -811,7 +811,7 @@ SM_STATE(EAP, INITIATE_RECEIVED) SM_ENTRY(EAP, INITIATE_RECEIVED); - sm->rxInitiate = FALSE; + sm->rxInitiate = false; pos = eap_hdr_validate(EAP_VENDOR_IETF, (enum eap_type) EAP_ERP_TYPE_REAUTH, @@ -988,7 +988,7 @@ report_error: return; fail: - sm->ignore = TRUE; + sm->ignore = true; } #endif /* CONFIG_ERP */ @@ -1000,7 +1000,7 @@ SM_STATE(EAP, INITIALIZE_PASSTHROUGH) wpabuf_free(sm->eap_if.aaaEapRespData); sm->eap_if.aaaEapRespData = NULL; - sm->try_initiate_reauth = FALSE; + sm->try_initiate_reauth = false; } @@ -1021,7 +1021,7 @@ SM_STATE(EAP, RETRANSMIT2) sm->retransCount++; if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) - sm->eap_if.eapReq = TRUE; + sm->eap_if.eapReq = true; } wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_RETRANSMIT2 MACSTR, @@ -1041,8 +1041,8 @@ SM_STATE(EAP, RECEIVED2) SM_STATE(EAP, DISCARD2) { SM_ENTRY(EAP, DISCARD2); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapNoReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapNoReq = true; } @@ -1054,17 +1054,17 @@ SM_STATE(EAP, SEND_REQUEST2) if (sm->eap_if.eapReqData) { if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = true; } else { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = false; } } else { wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData"); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - sm->eap_if.eapNoReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = false; + sm->eap_if.eapNoReq = true; } } @@ -1103,11 +1103,11 @@ SM_STATE(EAP, AAA_IDLE) { SM_ENTRY(EAP, AAA_IDLE); - sm->eap_if.aaaFail = FALSE; - sm->eap_if.aaaSuccess = FALSE; - sm->eap_if.aaaEapReq = FALSE; - sm->eap_if.aaaEapNoReq = FALSE; - sm->eap_if.aaaEapResp = TRUE; + sm->eap_if.aaaFail = false; + sm->eap_if.aaaSuccess = false; + sm->eap_if.aaaEapReq = false; + sm->eap_if.aaaEapNoReq = false; + sm->eap_if.aaaEapResp = true; } @@ -1115,7 +1115,7 @@ SM_STATE(EAP, TIMEOUT_FAILURE2) { SM_ENTRY(EAP, TIMEOUT_FAILURE2); - sm->eap_if.eapTimeout = TRUE; + sm->eap_if.eapTimeout = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TIMEOUT_FAILURE2 MACSTR, MAC2STR(sm->peer_addr)); @@ -1127,7 +1127,7 @@ SM_STATE(EAP, FAILURE2) SM_ENTRY(EAP, FAILURE2); eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); - sm->eap_if.eapFail = TRUE; + sm->eap_if.eapFail = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE2 MACSTR, MAC2STR(sm->peer_addr)); @@ -1149,14 +1149,14 @@ SM_STATE(EAP, SUCCESS2) sm->eap_if.eapKeyDataLen = 0; } - sm->eap_if.eapSuccess = TRUE; + sm->eap_if.eapSuccess = true; /* * Start reauthentication with identity request even though we know the * previously used identity. This is needed to get reauthentication * started properly. */ - sm->start_reauth = TRUE; + sm->start_reauth = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS2 MACSTR, MAC2STR(sm->peer_addr)); @@ -1217,7 +1217,7 @@ SM_STEP(EAP) case EAP_IDLE: if (sm->eap_if.retransWhile == 0) { if (sm->try_initiate_reauth) { - sm->try_initiate_reauth = FALSE; + sm->try_initiate_reauth = false; SM_ENTER(EAP, SELECT_ACTION); } else { SM_ENTER(EAP, RETRANSMIT); @@ -1491,8 +1491,8 @@ static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp) size_t plen; /* parse rxResp, respId, respMethod */ - sm->rxResp = FALSE; - sm->rxInitiate = FALSE; + sm->rxResp = false; + sm->rxInitiate = false; sm->respId = -1; sm->respMethod = EAP_TYPE_NONE; sm->respVendor = EAP_VENDOR_IETF; @@ -1518,9 +1518,9 @@ static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp) sm->respId = hdr->identifier; if (hdr->code == EAP_CODE_RESPONSE) - sm->rxResp = TRUE; + sm->rxResp = true; else if (hdr->code == EAP_CODE_INITIATE) - sm->rxInitiate = TRUE; + sm->rxInitiate = true; if (plen > sizeof(*hdr)) { u8 *pos = (u8 *) (hdr + 1); @@ -1702,7 +1702,7 @@ static enum eap_type eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor) if (sm->identity == NULL || sm->currentId == -1) { *vendor = EAP_VENDOR_IETF; next = EAP_TYPE_IDENTITY; - sm->update_user = TRUE; + sm->update_user = true; } else if (sm->user && idx < EAP_MAX_METHODS && (sm->user->methods[idx].vendor != EAP_VENDOR_IETF || sm->user->methods[idx].method != EAP_TYPE_NONE)) { @@ -1730,7 +1730,7 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) sm->m->isSuccess(sm, sm->eap_method_priv)) { wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> " "SUCCESS"); - sm->update_user = TRUE; + sm->update_user = true; return DECISION_SUCCESS; } @@ -1738,7 +1738,7 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) !sm->m->isSuccess(sm, sm->eap_method_priv)) { wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> " "FAILURE"); - sm->update_user = TRUE; + sm->update_user = true; return DECISION_FAILURE; } @@ -1765,12 +1765,12 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) sm->user->methods[0].method == EAP_TYPE_IDENTITY) { wpa_printf(MSG_DEBUG, "EAP: getDecision: stop " "identity request loop -> FAILURE"); - sm->update_user = TRUE; + sm->update_user = true; return DECISION_FAILURE; } - sm->update_user = FALSE; + sm->update_user = false; } - sm->start_reauth = FALSE; + sm->start_reauth = false; if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && (sm->user->methods[sm->user_eap_method_index].vendor != @@ -1801,9 +1801,9 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) } -static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method) +static bool eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method) { - return method == EAP_TYPE_IDENTITY ? TRUE : FALSE; + return method == EAP_TYPE_IDENTITY; } @@ -1820,7 +1820,7 @@ int eap_server_sm_step(struct eap_sm *sm) { int res = 0; do { - sm->changed = FALSE; + sm->changed = false; SM_STEP_RUN(EAP); if (sm->changed) res = 1; diff --git a/src/eap_server/eap_server_aka.c b/src/eap_server/eap_server_aka.c index 22dd965d6..e9bf0300c 100644 --- a/src/eap_server/eap_server_aka.c +++ b/src/eap_server/eap_server_aka.c @@ -664,8 +664,8 @@ static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_aka_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_aka_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_aka_data *data = priv; const u8 *pos; @@ -675,25 +675,25 @@ static Boolean eap_aka_check(struct eap_sm *sm, void *priv, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } -static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) +static bool eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) { if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR || subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) - return FALSE; + return false; switch (data->state) { case IDENTITY: if (subtype != EAP_AKA_SUBTYPE_IDENTITY) { wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case CHALLENGE: @@ -701,30 +701,30 @@ static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case REAUTH: if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) { wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case NOTIFICATION: if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) { wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; default: wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for " "processing a response", data->state); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1269,7 +1269,7 @@ static void eap_aka_process(struct eap_sm *sm, void *priv, } -static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv) +static bool eap_aka_isDone(struct eap_sm *sm, void *priv) { struct eap_aka_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -1308,7 +1308,7 @@ static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_aka_isSuccess(struct eap_sm *sm, void *priv) { struct eap_aka_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_eke.c b/src/eap_server/eap_server_eke.c index 71fab9624..eac3245cd 100644 --- a/src/eap_server/eap_server_eke.c +++ b/src/eap_server/eap_server_eke.c @@ -380,8 +380,8 @@ static struct wpabuf * eap_eke_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_eke_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_eke_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_eke_data *data = priv; size_t len; @@ -391,28 +391,28 @@ static Boolean eap_eke_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-EKE: Invalid frame"); - return TRUE; + return true; } eke_exch = *pos; wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: EKE-Exch=%d", eke_exch); if (data->state == IDENTITY && eke_exch == EAP_EKE_ID) - return FALSE; + return false; if (data->state == COMMIT && eke_exch == EAP_EKE_COMMIT) - return FALSE; + return false; if (data->state == CONFIRM && eke_exch == EAP_EKE_CONFIRM) - return FALSE; + return false; if (eke_exch == EAP_EKE_FAILURE) - return FALSE; + return false; wpa_printf(MSG_INFO, "EAP-EKE: Unexpected EKE-Exch=%d in state=%d", eke_exch, data->state); - return TRUE; + return true; } @@ -716,7 +716,7 @@ static void eap_eke_process(struct eap_sm *sm, void *priv, } -static Boolean eap_eke_isDone(struct eap_sm *sm, void *priv) +static bool eap_eke_isDone(struct eap_sm *sm, void *priv) { struct eap_eke_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -757,7 +757,7 @@ static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_eke_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_eke_isSuccess(struct eap_sm *sm, void *priv) { struct eap_eke_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_fast.c b/src/eap_server/eap_server_fast.c index 0270821cc..55d48d91f 100644 --- a/src/eap_server/eap_server_fast.c +++ b/src/eap_server/eap_server_fast.c @@ -929,8 +929,8 @@ static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_fast_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_fast_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -938,10 +938,10 @@ static Boolean eap_fast_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_FAST, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-FAST: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1563,7 +1563,7 @@ static void eap_fast_process(struct eap_sm *sm, void *priv, } -static Boolean eap_fast_isDone(struct eap_sm *sm, void *priv) +static bool eap_fast_isDone(struct eap_sm *sm, void *priv) { struct eap_fast_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -1614,7 +1614,7 @@ static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_fast_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_fast_isSuccess(struct eap_sm *sm, void *priv) { struct eap_fast_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_gpsk.c b/src/eap_server/eap_server_gpsk.c index a7742751a..4081b9f99 100644 --- a/src/eap_server/eap_server_gpsk.c +++ b/src/eap_server/eap_server_gpsk.c @@ -208,8 +208,8 @@ static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_gpsk_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_gpsk_data *data = priv; const u8 *pos; @@ -218,21 +218,21 @@ static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame"); - return TRUE; + return true; } wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos); if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2) - return FALSE; + return false; if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4) - return FALSE; + return false; wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d", *pos, data->state); - return TRUE; + return true; } @@ -560,7 +560,7 @@ static void eap_gpsk_process(struct eap_sm *sm, void *priv, } -static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv) +static bool eap_gpsk_isDone(struct eap_sm *sm, void *priv) { struct eap_gpsk_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -601,7 +601,7 @@ static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) { struct eap_gpsk_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_gtc.c b/src/eap_server/eap_server_gtc.c index fcccbcbd5..6310793a7 100644 --- a/src/eap_server/eap_server_gtc.c +++ b/src/eap_server/eap_server_gtc.c @@ -74,8 +74,8 @@ static struct wpabuf * eap_gtc_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_gtc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_gtc_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -83,10 +83,10 @@ static Boolean eap_gtc_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -184,14 +184,14 @@ static void eap_gtc_process(struct eap_sm *sm, void *priv, } -static Boolean eap_gtc_isDone(struct eap_sm *sm, void *priv) +static bool eap_gtc_isDone(struct eap_sm *sm, void *priv) { struct eap_gtc_data *data = priv; return data->state != CONTINUE; } -static Boolean eap_gtc_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_gtc_isSuccess(struct eap_sm *sm, void *priv) { struct eap_gtc_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_identity.c b/src/eap_server/eap_server_identity.c index 1b1db53f2..813e1d6de 100644 --- a/src/eap_server/eap_server_identity.c +++ b/src/eap_server/eap_server_identity.c @@ -79,8 +79,8 @@ static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, } -static Boolean eap_identity_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_identity_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -89,10 +89,10 @@ static Boolean eap_identity_check(struct eap_sm *sm, void *priv, respData, &len); if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -127,7 +127,7 @@ static void eap_identity_process(struct eap_sm *sm, void *priv, os_free(buf); } if (sm->identity) - sm->update_user = TRUE; + sm->update_user = true; os_free(sm->identity); sm->identity = os_malloc(len ? len : 1); if (sm->identity == NULL) { @@ -140,14 +140,14 @@ static void eap_identity_process(struct eap_sm *sm, void *priv, } -static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) +static bool eap_identity_isDone(struct eap_sm *sm, void *priv) { struct eap_identity_data *data = priv; return data->state != CONTINUE; } -static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_identity_isSuccess(struct eap_sm *sm, void *priv) { struct eap_identity_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_ikev2.c b/src/eap_server/eap_server_ikev2.c index 897637e8e..ef3cc8ccc 100644 --- a/src/eap_server/eap_server_ikev2.c +++ b/src/eap_server/eap_server_ikev2.c @@ -236,8 +236,8 @@ static struct wpabuf * eap_ikev2_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_ikev2_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -246,10 +246,10 @@ static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv, &len); if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -465,14 +465,14 @@ static void eap_ikev2_process(struct eap_sm *sm, void *priv, } -static Boolean eap_ikev2_isDone(struct eap_sm *sm, void *priv) +static bool eap_ikev2_isDone(struct eap_sm *sm, void *priv) { struct eap_ikev2_data *data = priv; return data->state == DONE || data->state == FAIL; } -static Boolean eap_ikev2_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_ikev2_isSuccess(struct eap_sm *sm, void *priv) { struct eap_ikev2_data *data = priv; return data->state == DONE && data->ikev2.state == IKEV2_DONE && diff --git a/src/eap_server/eap_server_md5.c b/src/eap_server/eap_server_md5.c index cf5ceb1d1..c9b500cdb 100644 --- a/src/eap_server/eap_server_md5.c +++ b/src/eap_server/eap_server_md5.c @@ -73,8 +73,8 @@ static struct wpabuf * eap_md5_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_md5_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_md5_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -82,16 +82,16 @@ static Boolean eap_md5_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame"); - return TRUE; + return true; } if (*pos != CHAP_MD5_LEN || 1 + CHAP_MD5_LEN > len) { wpa_printf(MSG_INFO, "EAP-MD5: Invalid response " "(response_len=%d payload_len=%lu", *pos, (unsigned long) len); - return TRUE; + return true; } - return FALSE; + return false; } @@ -136,14 +136,14 @@ static void eap_md5_process(struct eap_sm *sm, void *priv, } -static Boolean eap_md5_isDone(struct eap_sm *sm, void *priv) +static bool eap_md5_isDone(struct eap_sm *sm, void *priv) { struct eap_md5_data *data = priv; return data->state != CONTINUE; } -static Boolean eap_md5_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_md5_isSuccess(struct eap_sm *sm, void *priv) { struct eap_md5_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_mschapv2.c b/src/eap_server/eap_server_mschapv2.c index 8a1621aff..9b3eb26ef 100644 --- a/src/eap_server/eap_server_mschapv2.c +++ b/src/eap_server/eap_server_mschapv2.c @@ -235,8 +235,8 @@ static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv, } -static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_mschapv2_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_mschapv2_data *data = priv; struct eap_mschapv2_hdr *resp; @@ -247,7 +247,7 @@ static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame"); - return TRUE; + return true; } resp = (struct eap_mschapv2_hdr *) pos; @@ -255,7 +255,7 @@ static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, resp->op_code != MSCHAPV2_OP_RESPONSE) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Response - " "ignore op %d", resp->op_code); - return TRUE; + return true; } if (data->state == SUCCESS_REQ && @@ -263,17 +263,17 @@ static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, resp->op_code != MSCHAPV2_OP_FAILURE) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Success or " "Failure - ignore op %d", resp->op_code); - return TRUE; + return true; } if (data->state == FAILURE_REQ && resp->op_code != MSCHAPV2_OP_FAILURE) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Failure " "- ignore op %d", resp->op_code); - return TRUE; + return true; } - return FALSE; + return false; } @@ -531,7 +531,7 @@ static void eap_mschapv2_process(struct eap_sm *sm, void *priv, } -static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv) +static bool eap_mschapv2_isDone(struct eap_sm *sm, void *priv) { struct eap_mschapv2_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -564,7 +564,7 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv) { struct eap_mschapv2_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_pax.c b/src/eap_server/eap_server_pax.c index 5ed29efd1..fb089d50a 100644 --- a/src/eap_server/eap_server_pax.c +++ b/src/eap_server/eap_server_pax.c @@ -195,8 +195,8 @@ static struct wpabuf * eap_pax_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_pax_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_pax_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_pax_data *data = priv; struct eap_pax_hdr *resp; @@ -207,7 +207,7 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame"); - return TRUE; + return true; } mlen = sizeof(struct eap_hdr) + 1 + len; @@ -225,14 +225,14 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv, resp->op_code != EAP_PAX_OP_STD_2) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX_STD-2 - " "ignore op %d", resp->op_code); - return TRUE; + return true; } if (data->state == PAX_STD_3 && resp->op_code != EAP_PAX_OP_ACK) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX-ACK - " "ignore op %d", resp->op_code); - return TRUE; + return true; } if (resp->op_code != EAP_PAX_OP_STD_2 && @@ -244,38 +244,38 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv, if (data->mac_id != resp->mac_id) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected MAC ID 0x%x, " "received 0x%x", data->mac_id, resp->mac_id); - return TRUE; + return true; } if (resp->dh_group_id != EAP_PAX_DH_GROUP_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Expected DH Group ID 0x%x, " "received 0x%x", EAP_PAX_DH_GROUP_NONE, resp->dh_group_id); - return TRUE; + return true; } if (resp->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Expected Public Key ID 0x%x, " "received 0x%x", EAP_PAX_PUBLIC_KEY_NONE, resp->public_key_id); - return TRUE; + return true; } if (resp->flags & EAP_PAX_FLAGS_MF) { /* TODO: add support for reassembling fragments */ wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported"); - return TRUE; + return true; } if (resp->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: Unexpected CE flag"); - return TRUE; + return true; } if (data->keys_set) { if (len - sizeof(*resp) < EAP_PAX_ICV_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: No ICV in the packet"); - return TRUE; + return true; } icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN; wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); @@ -285,18 +285,18 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv, NULL, 0, NULL, 0, icvbuf) < 0) { wpa_printf(MSG_INFO, "EAP-PAX: Failed to calculate ICV"); - return TRUE; + return true; } if (os_memcmp_const(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", icvbuf, EAP_PAX_ICV_LEN); - return TRUE; + return true; } } - return FALSE; + return false; } @@ -513,7 +513,7 @@ static void eap_pax_process(struct eap_sm *sm, void *priv, } -static Boolean eap_pax_isDone(struct eap_sm *sm, void *priv) +static bool eap_pax_isDone(struct eap_sm *sm, void *priv) { struct eap_pax_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -563,7 +563,7 @@ static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_pax_isSuccess(struct eap_sm *sm, void *priv) { struct eap_pax_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c index 02d8b8e88..f234f6fa5 100644 --- a/src/eap_server/eap_server_peap.c +++ b/src/eap_server/eap_server_peap.c @@ -569,8 +569,8 @@ static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_peap_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_peap_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -578,10 +578,10 @@ static Boolean eap_peap_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1289,7 +1289,7 @@ static void eap_peap_process(struct eap_sm *sm, void *priv, } -static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) +static bool eap_peap_isDone(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -1383,7 +1383,7 @@ static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_peap_isSuccess(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_psk.c b/src/eap_server/eap_server_psk.c index 511973c94..f55f70dd8 100644 --- a/src/eap_server/eap_server_psk.c +++ b/src/eap_server/eap_server_psk.c @@ -171,8 +171,8 @@ static struct wpabuf * eap_psk_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_psk_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_psk_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_psk_data *data = priv; size_t len; @@ -182,7 +182,7 @@ static Boolean eap_psk_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return TRUE; + return true; } t = EAP_PSK_FLAGS_GET_T(*pos); @@ -191,22 +191,22 @@ static Boolean eap_psk_check(struct eap_sm *sm, void *priv, if (data->state == PSK_1 && t != 1) { wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-2 - " "ignore T=%d", t); - return TRUE; + return true; } if (data->state == PSK_3 && t != 3) { wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - " "ignore T=%d", t); - return TRUE; + return true; } if ((t == 1 && len < sizeof(struct eap_psk_hdr_2)) || (t == 3 && len < sizeof(struct eap_psk_hdr_4))) { wpa_printf(MSG_DEBUG, "EAP-PSK: Too short frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -433,7 +433,7 @@ static void eap_psk_process(struct eap_sm *sm, void *priv, } -static Boolean eap_psk_isDone(struct eap_sm *sm, void *priv) +static bool eap_psk_isDone(struct eap_sm *sm, void *priv) { struct eap_psk_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -474,7 +474,7 @@ static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_psk_isSuccess(struct eap_sm *sm, void *priv) { struct eap_psk_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c index 6bf3a23d0..81cddca60 100644 --- a/src/eap_server/eap_server_pwd.c +++ b/src/eap_server/eap_server_pwd.c @@ -530,8 +530,8 @@ eap_pwd_build_req(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_pwd_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_pwd_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_pwd_data *data = priv; const u8 *pos; @@ -540,7 +540,7 @@ static Boolean eap_pwd_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-pwd: Invalid frame"); - return TRUE; + return true; } wpa_printf(MSG_DEBUG, "EAP-pwd: Received frame: exch = %d, len = %d", @@ -548,20 +548,20 @@ static Boolean eap_pwd_check(struct eap_sm *sm, void *priv, if (data->state == PWD_ID_Req && ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_ID_EXCH)) - return FALSE; + return false; if (data->state == PWD_Commit_Req && ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_COMMIT_EXCH)) - return FALSE; + return false; if (data->state == PWD_Confirm_Req && ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_CONFIRM_EXCH)) - return FALSE; + return false; wpa_printf(MSG_INFO, "EAP-pwd: Unexpected opcode=%d in state=%d", *pos, data->state); - return TRUE; + return true; } @@ -1003,14 +1003,14 @@ static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_pwd_is_success(struct eap_sm *sm, void *priv) +static bool eap_pwd_is_success(struct eap_sm *sm, void *priv) { struct eap_pwd_data *data = priv; return data->state == SUCCESS; } -static Boolean eap_pwd_is_done(struct eap_sm *sm, void *priv) +static bool eap_pwd_is_done(struct eap_sm *sm, void *priv) { struct eap_pwd_data *data = priv; return (data->state == SUCCESS) || (data->state == FAILURE); diff --git a/src/eap_server/eap_server_sake.c b/src/eap_server/eap_server_sake.c index 56cfbfb32..8c39e63b9 100644 --- a/src/eap_server/eap_server_sake.c +++ b/src/eap_server/eap_server_sake.c @@ -232,8 +232,8 @@ static struct wpabuf * eap_sake_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_sake_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_sake_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_sake_data *data = priv; struct eap_sake_hdr *resp; @@ -244,7 +244,7 @@ static Boolean eap_sake_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, respData, &len); if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { wpa_printf(MSG_INFO, "EAP-SAKE: Invalid frame"); - return TRUE; + return true; } resp = (struct eap_sake_hdr *) pos; @@ -254,33 +254,33 @@ static Boolean eap_sake_check(struct eap_sm *sm, void *priv, if (version != EAP_SAKE_VERSION) { wpa_printf(MSG_INFO, "EAP-SAKE: Unknown version %d", version); - return TRUE; + return true; } if (session_id != data->session_id) { wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", session_id, data->session_id); - return TRUE; + return true; } wpa_printf(MSG_DEBUG, "EAP-SAKE: Received frame: subtype=%d", subtype); if (data->state == IDENTITY && subtype == EAP_SAKE_SUBTYPE_IDENTITY) - return FALSE; + return false; if (data->state == CHALLENGE && subtype == EAP_SAKE_SUBTYPE_CHALLENGE) - return FALSE; + return false; if (data->state == CONFIRM && subtype == EAP_SAKE_SUBTYPE_CONFIRM) - return FALSE; + return false; if (subtype == EAP_SAKE_SUBTYPE_AUTH_REJECT) - return FALSE; + return false; wpa_printf(MSG_INFO, "EAP-SAKE: Unexpected subtype=%d in state=%d", subtype, data->state); - return TRUE; + return true; } @@ -456,7 +456,7 @@ static void eap_sake_process(struct eap_sm *sm, void *priv, } -static Boolean eap_sake_isDone(struct eap_sm *sm, void *priv) +static bool eap_sake_isDone(struct eap_sm *sm, void *priv) { struct eap_sake_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -497,7 +497,7 @@ static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_sake_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_sake_isSuccess(struct eap_sm *sm, void *priv) { struct eap_sake_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_sim.c b/src/eap_server/eap_server_sim.c index d7ac87ce5..8a6828962 100644 --- a/src/eap_server/eap_server_sim.c +++ b/src/eap_server/eap_server_sim.c @@ -360,8 +360,8 @@ static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_sim_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_sim_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -369,55 +369,55 @@ static Boolean eap_sim_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } -static Boolean eap_sim_unexpected_subtype(struct eap_sim_data *data, - u8 subtype) +static bool eap_sim_unexpected_subtype(struct eap_sim_data *data, + u8 subtype) { if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) - return FALSE; + return false; switch (data->state) { case START: if (subtype != EAP_SIM_SUBTYPE_START) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case CHALLENGE: if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case REAUTH: if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case NOTIFICATION: if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; default: wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " "processing a response", data->state); - return TRUE; + return true; } - return FALSE; + return false; } @@ -794,7 +794,7 @@ static void eap_sim_process(struct eap_sm *sm, void *priv, } -static Boolean eap_sim_isDone(struct eap_sm *sm, void *priv) +static bool eap_sim_isDone(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -833,7 +833,7 @@ static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_sim_isSuccess(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_teap.c b/src/eap_server/eap_server_teap.c index a2cbf7a7b..d7b1b0995 100644 --- a/src/eap_server/eap_server_teap.c +++ b/src/eap_server/eap_server_teap.c @@ -965,8 +965,8 @@ static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_teap_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_teap_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -974,10 +974,10 @@ static Boolean eap_teap_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TEAP, respData, &len); if (!pos || len < 1) { wpa_printf(MSG_INFO, "EAP-TEAP: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1974,7 +1974,7 @@ static void eap_teap_process(struct eap_sm *sm, void *priv, } -static Boolean eap_teap_isDone(struct eap_sm *sm, void *priv) +static bool eap_teap_isDone(struct eap_sm *sm, void *priv) { struct eap_teap_data *data = priv; @@ -2032,7 +2032,7 @@ static u8 * eap_teap_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_teap_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_teap_isSuccess(struct eap_sm *sm, void *priv) { struct eap_teap_data *data = priv; diff --git a/src/eap_server/eap_server_tls.c b/src/eap_server/eap_server_tls.c index c64cebb40..769fd1fe0 100644 --- a/src/eap_server/eap_server_tls.c +++ b/src/eap_server/eap_server_tls.c @@ -226,8 +226,8 @@ check_established: } -static Boolean eap_tls_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_tls_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_tls_data *data = priv; const u8 *pos; @@ -246,10 +246,10 @@ static Boolean eap_tls_check(struct eap_sm *sm, void *priv, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -346,7 +346,7 @@ static void eap_tls_process(struct eap_sm *sm, void *priv, } -static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv) +static bool eap_tls_isDone(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -431,7 +431,7 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_tls_isSuccess(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_tnc.c b/src/eap_server/eap_server_tnc.c index f6cdcb1ef..36fb5c34d 100644 --- a/src/eap_server/eap_server_tnc.c +++ b/src/eap_server/eap_server_tnc.c @@ -320,8 +320,8 @@ static struct wpabuf * eap_tnc_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_tnc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_tnc_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_tnc_data *data = priv; const u8 *pos; @@ -331,29 +331,29 @@ static Boolean eap_tnc_check(struct eap_sm *sm, void *priv, &len); if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame"); - return TRUE; + return true; } if (len == 0 && data->state != WAIT_FRAG_ACK) { wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (empty)"); - return TRUE; + return true; } if (len == 0) - return FALSE; /* Fragment ACK does not include flags */ + return false; /* Fragment ACK does not include flags */ if ((*pos & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", *pos & EAP_TNC_VERSION_MASK); - return TRUE; + return true; } if (*pos & EAP_TNC_FLAGS_START) { wpa_printf(MSG_DEBUG, "EAP-TNC: Peer used Start flag"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -537,14 +537,14 @@ static void eap_tnc_process(struct eap_sm *sm, void *priv, } -static Boolean eap_tnc_isDone(struct eap_sm *sm, void *priv) +static bool eap_tnc_isDone(struct eap_sm *sm, void *priv) { struct eap_tnc_data *data = priv; return data->state == DONE || data->state == FAIL; } -static Boolean eap_tnc_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_tnc_isSuccess(struct eap_sm *sm, void *priv) { struct eap_tnc_data *data = priv; return data->state == DONE; diff --git a/src/eap_server/eap_server_ttls.c b/src/eap_server/eap_server_ttls.c index 721835dbf..2f0c041d5 100644 --- a/src/eap_server/eap_server_ttls.c +++ b/src/eap_server/eap_server_ttls.c @@ -509,8 +509,8 @@ static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_ttls_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_ttls_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -518,10 +518,10 @@ static Boolean eap_ttls_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1260,7 +1260,7 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv, } -static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv) +static bool eap_ttls_isDone(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -1290,7 +1290,7 @@ static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_ttls_isSuccess(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_vendor_test.c b/src/eap_server/eap_server_vendor_test.c index 963997759..77860411b 100644 --- a/src/eap_server/eap_server_vendor_test.c +++ b/src/eap_server/eap_server_vendor_test.c @@ -88,8 +88,8 @@ static struct wpabuf * eap_vendor_test_buildReq(struct eap_sm *sm, void *priv, } -static Boolean eap_vendor_test_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_vendor_test_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -97,10 +97,10 @@ static Boolean eap_vendor_test_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-VENDOR-TEST: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -130,7 +130,7 @@ static void eap_vendor_test_process(struct eap_sm *sm, void *priv, } -static Boolean eap_vendor_test_isDone(struct eap_sm *sm, void *priv) +static bool eap_vendor_test_isDone(struct eap_sm *sm, void *priv) { struct eap_vendor_test_data *data = priv; return data->state == SUCCESS; @@ -158,7 +158,7 @@ static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_vendor_test_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_vendor_test_isSuccess(struct eap_sm *sm, void *priv) { struct eap_vendor_test_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_wsc.c b/src/eap_server/eap_server_wsc.c index 364c089aa..fc70cf196 100644 --- a/src/eap_server/eap_server_wsc.c +++ b/src/eap_server/eap_server_wsc.c @@ -270,8 +270,8 @@ static struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_wsc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_wsc_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -280,10 +280,10 @@ static Boolean eap_wsc_check(struct eap_sm *sm, void *priv, respData, &len); if (pos == NULL || len < 2) { wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -462,17 +462,17 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv, } -static Boolean eap_wsc_isDone(struct eap_sm *sm, void *priv) +static bool eap_wsc_isDone(struct eap_sm *sm, void *priv) { struct eap_wsc_data *data = priv; return data->state == FAIL; } -static Boolean eap_wsc_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_wsc_isSuccess(struct eap_sm *sm, void *priv) { /* EAP-WSC will always result in EAP-Failure */ - return FALSE; + return false; } From de3f8d9fd1e886a1f7ceec46e7b74a3845cac3c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 22 Apr 2020 00:51:13 +0300 Subject: [PATCH 0403/1105] tests: Fix new fuzzer builds $(LIBS) got included twice into the linker command line from $^ and $(LIBS). The former ended up getting converted based on host CPU rather than target. Fix that by removing duplication and -lcrypto from $(LIBS). Signed-off-by: Jouni Malinen --- tests/fuzzing/dpp-uri/Makefile | 3 +-- tests/fuzzing/sae/Makefile | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index 27b2fddb3..10c4ea2f4 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -13,7 +13,6 @@ LIBS += $(SRC)/common/libcommon.a LIBS += $(SRC)/utils/libutils.a OBJS += $(SRC)/crypto/crypto_openssl.o -LIBS += -lcrypto OBJS += $(SRC)/crypto/aes-ctr.o OBJS += $(SRC)/crypto/aes-siv.o @@ -24,7 +23,7 @@ OBJS += $(SRC)/tls/asn1.o OBJS += $(SRC)/common/dpp.o dpp-uri: dpp-uri.o $(OBJS) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto clean: $(MAKE) -C $(SRC) clean diff --git a/tests/fuzzing/sae/Makefile b/tests/fuzzing/sae/Makefile index 0a56e0628..5b86c2f43 100644 --- a/tests/fuzzing/sae/Makefile +++ b/tests/fuzzing/sae/Makefile @@ -8,14 +8,13 @@ LIBS += $(SRC)/common/libcommon.a LIBS += $(SRC)/utils/libutils.a OBJS += $(SRC)/crypto/crypto_openssl.o -LIBS += -lcrypto OBJS += $(SRC)/crypto/dh_groups.o OBJS += $(SRC)/crypto/sha256-prf.o OBJS += $(SRC)/crypto/sha256-kdf.o OBJS += $(SRC)/common/dragonfly.o sae: sae.o $(OBJS) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto clean: $(MAKE) -C $(SRC) clean From 0c5edededa319e6bba5a555dcee2e08a9de759a0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 22 Apr 2020 17:04:43 +0300 Subject: [PATCH 0404/1105] DPP: Fix config exchange with gas_rand_mac_addr Do not use a random MAC address for the GAS exchange that is used as part of the DPP protocol exchange since that would break DPP. Configurator expects the same MAC address to be used for DPP Authentication exchange and DPP Configuration exchange (GAS). Since the DPP Authentication exchange has already used the MAC address configured on the interface, use of a random address for the GAS exchange would not provide any additional privacy protection. If a random MAC address needs to be used for this type of an exchange, that random address would need to be first configured on the interface before starting DPP exchange. This does not change GAS query behavior for any other use case, i.e., the gas_rand_mac_addr configuration continues to apply to all the Interworking/Hotspot 2.0 uses. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 2 +- wpa_supplicant/gas_query.c | 23 ++++++++++++++++++++--- wpa_supplicant/gas_query.h | 2 +- wpa_supplicant/hs20_supplicant.c | 3 ++- wpa_supplicant/interworking.c | 8 +++++--- wpa_supplicant/wpa_supplicant.conf | 5 +++++ 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 351f8da9d..291b96b75 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1428,7 +1428,7 @@ static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s) MAC2STR(auth->peer_mac_addr), auth->curr_freq); res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq, - 1, buf, wpas_dpp_gas_resp_cb, wpa_s); + 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); wpabuf_free(buf); diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c index 8e977a3ec..759b9b9cd 100644 --- a/wpa_supplicant/gas_query.c +++ b/wpa_supplicant/gas_query.c @@ -43,6 +43,7 @@ struct gas_query_pending { unsigned int offchannel_tx_started:1; unsigned int retry:1; unsigned int wildcard_bssid:1; + unsigned int maintain_addr:1; int freq; u16 status_code; struct wpabuf *req; @@ -693,7 +694,8 @@ static void gas_query_start_cb(struct wpa_radio_work *work, int deinit) return; } - if (wpas_update_random_addr_disassoc(wpa_s) < 0) { + if (!query->maintain_addr && + wpas_update_random_addr_disassoc(wpa_s) < 0) { wpa_msg(wpa_s, MSG_INFO, "Failed to assign random MAC address for GAS"); gas_query_free(query, 1); @@ -749,12 +751,23 @@ static int gas_query_set_sa(struct gas_query *gas, struct wpa_supplicant *wpa_s = gas->wpa_s; struct os_reltime now; - if (!wpa_s->conf->gas_rand_mac_addr || + if (query->maintain_addr || + !wpa_s->conf->gas_rand_mac_addr || !(wpa_s->current_bss ? (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA))) { /* Use own MAC address as the transmitter address */ + wpa_printf(MSG_DEBUG, + "GAS: Use own MAC address as the transmitter address%s%s%s", + query->maintain_addr ? " (maintain_addr)" : "", + !wpa_s->conf->gas_rand_mac_addr ? " (no gas_rand_mac_adr set)" : "", + !(wpa_s->current_bss ? + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) : + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA)) ? + " (no driver rand capa" : ""); os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN); return 0; } @@ -800,6 +813,9 @@ static int gas_query_set_sa(struct gas_query *gas, * @gas: GAS query data from gas_query_init() * @dst: Destination MAC address for the query * @freq: Frequency (in MHz) for the channel on which to send the query + * @wildcard_bssid: Force use of wildcard BSSID value + * @maintain_addr: Maintain own MAC address for exchange (i.e., ignore MAC + * address randomization rules) * @req: GAS query payload (to be freed by gas_query module in case of success * return) * @cb: Callback function for reporting GAS query result and response @@ -807,7 +823,7 @@ static int gas_query_set_sa(struct gas_query *gas, * Returns: dialog token (>= 0) on success or -1 on failure */ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, - int wildcard_bssid, struct wpabuf *req, + int wildcard_bssid, int maintain_addr, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, @@ -829,6 +845,7 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, return -1; query->gas = gas; + query->maintain_addr = !!maintain_addr; if (gas_query_set_sa(gas, query)) { os_free(query); return -1; diff --git a/wpa_supplicant/gas_query.h b/wpa_supplicant/gas_query.h index d2b455442..f9ce7b680 100644 --- a/wpa_supplicant/gas_query.h +++ b/wpa_supplicant/gas_query.h @@ -35,7 +35,7 @@ enum gas_query_result { }; int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, - int wildcard_bssid, struct wpabuf *req, + int wildcard_bssid, int maintain_addr, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index 47a1d0175..3bf777e6a 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -288,7 +288,8 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, anqp_resp_cb, + wpa_s); if (res < 0) { wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 49b9907b0..c48525cec 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -316,7 +316,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, buf, + res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, 0, buf, interworking_anqp_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); @@ -2804,7 +2804,8 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, anqp_resp_cb, + wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); @@ -3243,7 +3244,8 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, } else wpabuf_put_le16(buf, 0); - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, gas_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, gas_resp_cb, + wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); wpabuf_free(buf); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index f242c3a9e..3b9056770 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -481,6 +481,11 @@ fast_reauth=1 # 0 = use permanent MAC address # 1 = use random MAC address # 2 = like 1, but maintain OUI (with local admin bit set) +# Note that this setting is ignored when a specific MAC address is needed for +# a full protocol exchange that includes GAS, e.g., when going through a DPP +# exchange that exposes the configured interface address as part of the DP +# Public Action frame exchanges before using GAS. That same address is then used +# during the GAS exchange as well to avoid breaking the protocol expectations. #gas_rand_mac_addr=0 # Lifetime of GAS random MAC address in seconds (default: 60) From fe319fc7eddae81fca63d241026d707646a18009 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 22 Apr 2020 17:04:08 +0300 Subject: [PATCH 0405/1105] tests: DPP QR Code and authentication exchange (rand_mac_addr=1) Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 2cff4c814..02329e088 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5310,3 +5310,15 @@ def run_dpp_reconfig_connector(dev, apdev): if n_net_access_key.strip('"') != net_access_key: raise Exception("net_access_key mismatch: %s %s" % (n_net_access_key, net_access_key)) + +def test_dpp_qr_code_auth_rand_mac_addr(dev, apdev): + """DPP QR Code and authentication exchange (rand_mac_addr=1)""" + flags = int(dev[0].get_driver_status_field('capa.flags'), 16) + if flags & 0x0000400000000000 == 0: + raise HwsimSkip("Driver does not support random GAS TA") + + try: + dev[0].set("gas_rand_mac_addr", "1") + run_dpp_qr_code_auth_unicast(dev, apdev, None) + finally: + dev[0].set("gas_rand_mac_addr", "0") From 1025a9052c6e3cc066fb01af10833da20783e1d8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 17:06:36 +0300 Subject: [PATCH 0406/1105] Sync with mac80211-next.git include/uapi/linux/nl80211.h This brings in nl80211 definitions as of 2020-02-24. Signed-off-by: Jouni Malinen --- src/drivers/nl80211_copy.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index 2b6911618..9679d561f 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -687,6 +687,10 @@ * four bytes for vendor frames including the OUI. The registration * cannot be dropped, but is removed automatically when the netlink * socket is closed. Multiple registrations can be made. + * The %NL80211_ATTR_RECEIVE_MULTICAST flag attribute can be given if + * %NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS is available, in which + * case the registration can also be modified to include/exclude the + * flag, rather than requiring unregistration to change it. * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for * backward compatibility * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This @@ -1151,6 +1155,11 @@ * @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration * is passed using %NL80211_ATTR_TID_CONFIG attribute. * + * @NL80211_CMD_UNPROT_BEACON: Unprotected or incorrectly protected Beacon + * frame. This event is used to indicate that a received Beacon frame was + * dropped because it did not include a valid MME MIC while beacon + * protection was enabled (BIGTK configured in station mode). + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1377,6 +1386,8 @@ enum nl80211_commands { NL80211_CMD_SET_TID_CONFIG, + NL80211_CMD_UNPROT_BEACON, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -2470,6 +2481,9 @@ enum nl80211_commands { * no roaming occurs between the reauth threshold and PMK expiration, * disassociation is still forced. * + * @NL80211_ATTR_RECEIVE_MULTICAST: multicast flag for the + * %NL80211_CMD_REGISTER_FRAME command, see the description there. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2945,6 +2959,8 @@ enum nl80211_attrs { NL80211_ATTR_PMK_LIFETIME, NL80211_ATTR_PMK_REAUTH_THRESHOLD, + NL80211_ATTR_RECEIVE_MULTICAST, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -5674,6 +5690,8 @@ enum nl80211_feature_flags { * * @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection * and can receive key configuration for BIGTK using key indexes 6 and 7. + * @NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT: The driver supports Beacon + * protection as a client only and cannot transmit protected beacons. * * @NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH: The driver can disable the * forwarding of preauth frames over the control port. They are then @@ -5684,6 +5702,9 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_DEL_IBSS_STA: The driver supports removing stations * in IBSS mode, essentially by dropping their state. * + * @NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS: management frame registrations + * are possible for multicast frames and those will be reported properly. + * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ @@ -5735,6 +5756,8 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH, NL80211_EXT_FEATURE_PROTECTED_TWT, NL80211_EXT_FEATURE_DEL_IBSS_STA, + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS, + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, From 4d9c313f2a6dc092caee55299062de897bddd6ea Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Apr 2020 23:30:23 +0300 Subject: [PATCH 0407/1105] WPA: Fix wpa_parse_kde_ies() handling with vendor specific elements Documentation of the return values for wpa_parse_vendor_specific() and wpa_parse_generic() were not accurate and the parsing results from these were not really handled appropriately. There is no point in calling wpa_parse_vendor_specific() if wpa_parse_generic() recognizes a KDE. Not that this would break anything in practice, but still, it looks confusing. The part about handling wpa_parse_vendor_specific() return value can, at least in theory, break some cases where an unexpectedly short KDE/vendor specific element were present and something would need to be recognized after it. That does not really happen with any standard compliant implementation and this is unlikely to cause any real harm, but it is clearer to handle this more appropriately even for any theoretical case, including misbehavior of a peer device. Instead of stopping parsing on too short vendor specific element, continue parsing the following KDEs/IEs. Skip the wpa_parse_vendor_specific() call when a KDE has been recognized. Also fix the return value documentation for wpa_parse_generic() and remove the useless return value from wpa_parse_vendor_specific(). Signed-off-by: Jouni Malinen --- src/common/wpa_common.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 46b647bcd..eb1861a87 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2655,10 +2655,9 @@ int fils_domain_name_hash(const char *domain, u8 *hash) * @pos: Pointer to the IE header * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure */ -static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) +static void wpa_parse_vendor_specific(const u8 *pos, const u8 *end, + struct wpa_eapol_ie_parse *ie) { unsigned int oui; @@ -2666,7 +2665,7 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, wpa_printf(MSG_MSGDUMP, "Too short vendor specific IE ignored (len=%u)", pos[1]); - return 1; + return; } oui = WPA_GET_BE24(&pos[2]); @@ -2683,7 +2682,6 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, ie->wmm, ie->wmm_len); } } - return 0; } @@ -2691,7 +2689,7 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure + * Returns: 0 on success, 1 if end mark is found, 2 if KDE is not recognized */ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie) { @@ -2803,7 +2801,7 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie) return 0; } - return 0; + return 2; } @@ -2912,20 +2910,18 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) } } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { ret = wpa_parse_generic(pos, ie); - if (ret < 0) - break; - if (ret > 0) { + if (ret == 1) { + /* end mark found */ ret = 0; break; } - ret = wpa_parse_vendor_specific(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; + if (ret == 2) { + /* not a known KDE */ + wpa_parse_vendor_specific(pos, end, ie); } + + ret = 0; } else { wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key Key Data IE", From 56024a233a87e8762394c40237c19b5041b03976 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Apr 2020 23:52:12 +0300 Subject: [PATCH 0408/1105] WPA auth: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/ap/preauth_auth.c | 2 +- src/ap/wpa_auth.c | 197 +++++++++++++++++++++-------------------- src/ap/wpa_auth_ft.c | 8 +- src/ap/wpa_auth_glue.c | 7 +- src/ap/wpa_auth_i.h | 54 +++++------ src/ap/wpa_auth_ie.c | 4 +- 6 files changed, 136 insertions(+), 136 deletions(-) diff --git a/src/ap/preauth_auth.c b/src/ap/preauth_auth.c index 3e0c8000d..2ff186177 100644 --- a/src/ap/preauth_auth.c +++ b/src/ap/preauth_auth.c @@ -82,7 +82,7 @@ static void rsn_preauth_receive(void *ctx, const u8 *src_addr, sta = NULL; } else { sta->eapol_sm->radius_identifier = -1; - sta->eapol_sm->portValid = TRUE; + sta->eapol_sm->portValid = true; sta->eapol_sm->flags |= EAPOL_SM_PREAUTH; } } diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 8ecb17318..4881357f5 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -317,9 +317,9 @@ static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) while (group) { wpa_group_get(wpa_auth, group); - group->GTKReKey = TRUE; + group->GTKReKey = true; do { - group->changed = FALSE; + group->changed = false; wpa_group_sm_step(wpa_auth, group); } while (group->changed); @@ -420,7 +420,7 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, if (!group) return NULL; - group->GTKAuthenticator = TRUE; + group->GTKAuthenticator = true; group->vlan_id = vlan_id; group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); @@ -442,14 +442,14 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, return NULL; } - group->GInit = TRUE; + group->GInit = true; if (delay_init) { wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start until Beacon frames have been configured"); /* Initialization is completed in wpa_init_keys(). */ } else { wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; + group->GInit = false; wpa_group_sm_step(wpa_auth, group); } @@ -546,7 +546,7 @@ int wpa_init_keys(struct wpa_authenticator *wpa_auth) wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial keys"); wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; + group->GInit = false; wpa_group_sm_step(wpa_auth, group); if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) return -1; @@ -616,9 +616,9 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth, */ group = wpa_auth->group; group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); - group->GInit = TRUE; + group->GInit = true; wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; + group->GInit = false; wpa_group_sm_step(wpa_auth, group); return 0; @@ -661,7 +661,7 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, "FT authentication already completed - do not start 4-way handshake"); /* Go to PTKINITDONE state to allow GTK rekeying */ sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; - sm->Pair = TRUE; + sm->Pair = true; return 0; } #endif /* CONFIG_IEEE80211R_AP */ @@ -672,14 +672,14 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, "FILS authentication already completed - do not start 4-way handshake"); /* Go to PTKINITDONE state to allow GTK rekeying */ sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; - sm->Pair = TRUE; + sm->Pair = true; return 0; } #endif /* CONFIG_FILS */ if (sm->started) { os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); - sm->ReAuthenticationRequest = TRUE; + sm->ReAuthenticationRequest = true; return wpa_sm_step(sm); } @@ -687,11 +687,11 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, "start authentication"); sm->started = 1; - sm->Init = TRUE; + sm->Init = true; if (wpa_sm_step(sm) == 1) return 1; /* should not really happen */ - sm->Init = FALSE; - sm->AuthenticationRequest = TRUE; + sm->Init = false; + sm->AuthenticationRequest = true; return wpa_sm_step(sm); } @@ -726,7 +726,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) #endif /* CONFIG_P2P */ if (sm->GUpdateStationKeys) { sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; + sm->GUpdateStationKeys = false; } #ifdef CONFIG_IEEE80211R_AP os_free(sm->assoc_resp_ftie); @@ -788,14 +788,14 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm) wpa_printf(MSG_INFO, "WPA: PTK0 rekey not allowed, disconnect " MACSTR, MAC2STR(sm->addr)); - sm->Disconnect = TRUE; + sm->Disconnect = true; /* Try to encourage the STA to reconnect */ sm->disconnect_reason = WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; } else { if (sm->use_ext_key_id) sm->keyidx_active ^= 1; /* flip Key ID */ - sm->PTKRequest = TRUE; + sm->PTKRequest = true; sm->PTK_valid = 0; } } @@ -825,7 +825,7 @@ static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, (!replay_counter || os_memcmp(replay_counter, ctr[i].counter, WPA_REPLAY_COUNTER_LEN) == 0)) - ctr[i].valid = FALSE; + ctr[i].valid = false; } } @@ -976,7 +976,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); forced_memzero(&PTK, sizeof(PTK)); - sm->PTK_valid = TRUE; + sm->PTK_valid = true; return 0; } @@ -1146,7 +1146,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4"); sm->update_snonce = 1; os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN); - sm->alt_snonce_valid = TRUE; + sm->alt_snonce_valid = true; os_memcpy(sm->alt_replay_counter, sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); @@ -1278,7 +1278,7 @@ continue_processing: } #endif /* CONFIG_FILS */ - sm->MICVerified = FALSE; + sm->MICVerified = false; if (sm->PTK_valid && !sm->update_snonce) { if (mic_len && wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK, @@ -1311,7 +1311,7 @@ continue_processing: #ifdef TEST_FUZZ continue_fuzz: #endif /* TEST_FUZZ */ - sm->MICVerified = TRUE; + sm->MICVerified = true; eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); sm->pending_1_of_4_timeout = 0; } @@ -1385,7 +1385,7 @@ continue_processing: sm->last_rx_eapol_key_len = data_len; sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); - sm->EAPOLKeyReceived = TRUE; + sm->EAPOLKeyReceived = true; sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); @@ -1448,7 +1448,7 @@ static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) sm->pending_1_of_4_timeout = 0; wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); - sm->TimeoutEvt = TRUE; + sm->TimeoutEvt = true; wpa_sm_step(sm); } @@ -1548,7 +1548,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, WPA_REPLAY_COUNTER_LEN); wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", key->replay_counter, WPA_REPLAY_COUNTER_LEN); - sm->key_replay[0].valid = TRUE; + sm->key_replay[0].valid = true; if (nonce) os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); @@ -1735,7 +1735,7 @@ static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, void wpa_remove_ptk(struct wpa_state_machine *sm) { - sm->PTK_valid = FALSE; + sm->PTK_valid = false; os_memset(&sm->PTK, 0, sizeof(sm->PTK)); if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0, KEY_FLAG_PAIRWISE)) @@ -1746,7 +1746,7 @@ void wpa_remove_ptk(struct wpa_state_machine *sm) 0, KEY_FLAG_PAIRWISE)) wpa_printf(MSG_DEBUG, "RSN: PTK Key ID 1 removal from the driver failed"); - sm->pairwise_set = FALSE; + sm->pairwise_set = false; eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); } @@ -1775,7 +1775,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) break; case WPA_DEAUTH: case WPA_DISASSOC: - sm->DeauthenticationRequest = TRUE; + sm->DeauthenticationRequest = true; #ifdef CONFIG_IEEE80211R_AP os_memset(sm->PMK, 0, sizeof(sm->PMK)); sm->pmk_len = 0; @@ -1798,11 +1798,11 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) wpa_printf(MSG_DEBUG, "WPA state machine had not been started - initialize now"); sm->started = 1; - sm->Init = TRUE; + sm->Init = true; if (wpa_sm_step(sm) == 1) return 1; /* should not really happen */ - sm->Init = FALSE; - sm->AuthenticationRequest = TRUE; + sm->Init = false; + sm->AuthenticationRequest = true; break; } @@ -1811,7 +1811,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) wpa_printf(MSG_INFO, "WPA: PTK0 rekey not allowed, disconnect " MACSTR, MAC2STR(sm->addr)); - sm->Disconnect = TRUE; + sm->Disconnect = true; /* Try to encourage the STA to reconnect */ sm->disconnect_reason = WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; @@ -1827,10 +1827,10 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) * update for this STA. */ sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->PtkGroupInit = TRUE; + sm->GUpdateStationKeys = false; + sm->PtkGroupInit = true; } - sm->ReAuthenticationRequest = TRUE; + sm->ReAuthenticationRequest = true; break; case WPA_ASSOC_FT: #ifdef CONFIG_IEEE80211R_AP @@ -1856,7 +1856,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) break; #endif /* CONFIG_FILS */ case WPA_DRV_STA_REMOVED: - sm->tk_already_set = FALSE; + sm->tk_already_set = false; return 0; } @@ -1873,7 +1873,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) #endif /* CONFIG_FILS */ if (remove_ptk) { - sm->PTK_valid = FALSE; + sm->PTK_valid = false; os_memset(&sm->PTK, 0, sizeof(sm->PTK)); if (event != WPA_REAUTH_EAPOL) @@ -1885,7 +1885,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) * wpa_sm_step() is already running - avoid recursive call to * it by making the existing loop process the new update. */ - sm->changed = TRUE; + sm->changed = true; return 0; } return wpa_sm_step(sm); @@ -1898,18 +1898,18 @@ SM_STATE(WPA_PTK, INITIALIZE) if (sm->Init) { /* Init flag is not cleared here, so avoid busy * loop by claiming nothing changed. */ - sm->changed = FALSE; + sm->changed = false; } sm->keycount = 0; if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; + sm->GUpdateStationKeys = false; if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = FALSE; + sm->PInitAKeys = false; if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and * Local AA > Remote AA)) */) { - sm->Pair = TRUE; + sm->Pair = true; } wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); wpa_remove_ptk(sm); @@ -1929,7 +1929,7 @@ SM_STATE(WPA_PTK, DISCONNECT) u16 reason = sm->disconnect_reason; SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); - sm->Disconnect = FALSE; + sm->Disconnect = false; sm->disconnect_reason = 0; if (!reason) reason = WLAN_REASON_PREV_AUTH_NOT_VALID; @@ -1940,7 +1940,7 @@ SM_STATE(WPA_PTK, DISCONNECT) SM_STATE(WPA_PTK, DISCONNECTED) { SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); - sm->DeauthenticationRequest = FALSE; + sm->DeauthenticationRequest = false; } @@ -1948,11 +1948,11 @@ SM_STATE(WPA_PTK, AUTHENTICATION) { SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - sm->PTK_valid = FALSE; + sm->PTK_valid = false; wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, 1); wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); - sm->AuthenticationRequest = FALSE; + sm->AuthenticationRequest = false; } @@ -1973,18 +1973,18 @@ static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, if (random_pool_ready() != 1) { wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake"); - group->reject_4way_hs_for_entropy = TRUE; + group->reject_4way_hs_for_entropy = true; } else { - group->first_sta_seen = TRUE; - group->reject_4way_hs_for_entropy = FALSE; + group->first_sta_seen = true; + group->reject_4way_hs_for_entropy = false; } if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 || wpa_gtk_update(wpa_auth, group) < 0 || wpa_group_config_group_keys(wpa_auth, group) < 0) { wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed"); - group->first_sta_seen = FALSE; - group->reject_4way_hs_for_entropy = TRUE; + group->first_sta_seen = false; + group->reject_4way_hs_for_entropy = true; } } @@ -1994,7 +1994,7 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); wpa_group_ensure_init(sm->wpa_auth, sm->group); - sm->ReAuthenticationRequest = FALSE; + sm->ReAuthenticationRequest = false; /* * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat @@ -2008,7 +2008,7 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { wpa_printf(MSG_ERROR, "WPA: Failed to get random data for ANonce."); - sm->Disconnect = TRUE; + sm->Disconnect = true; return; } wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, @@ -2026,7 +2026,7 @@ static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm) if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { wpa_printf(MSG_ERROR, "WPA: Failed to get random data for ANonce"); - sm->Disconnect = TRUE; + sm->Disconnect = true; return -1; } wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce, @@ -2053,7 +2053,7 @@ SM_STATE(WPA_PTK, INITPMK) } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { wpa_printf(MSG_DEBUG, "DPP: No PMKSA cache entry for STA - reject connection"); - sm->Disconnect = TRUE; + sm->Disconnect = true; sm->disconnect_reason = WLAN_REASON_INVALID_PMKID; return; #endif /* CONFIG_DPP */ @@ -2071,7 +2071,7 @@ SM_STATE(WPA_PTK, INITPMK) wpa_printf(MSG_DEBUG, "WPA: MSK not long enough (%zu) to create PMK (%u)", len, pmk_len); - sm->Disconnect = TRUE; + sm->Disconnect = true; return; } os_memcpy(sm->PMK, msk, pmk_len); @@ -2090,21 +2090,21 @@ SM_STATE(WPA_PTK, INITPMK) } else { wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p", sm->wpa_auth->cb->get_msk); - sm->Disconnect = TRUE; + sm->Disconnect = true; return; } forced_memzero(msk, sizeof(msk)); sm->req_replay_counter_used = 0; - /* IEEE 802.11i does not set keyRun to FALSE, but not doing this + /* IEEE 802.11i does not set keyRun to false, but not doing this * will break reauthentication since EAPOL state machines may not be * get into AUTHENTICATING state that clears keyRun before WPA state * machine enters AUTHENTICATION2 state and goes immediately to INITPMK * state and takes PMK from the previously used AAA Key. This will * eventually fail in 4-Way Handshake because Supplicant uses PMK - * derived from the new AAA Key. Setting keyRun = FALSE here seems to + * derived from the new AAA Key. Setting keyRun = false here seems to * be good workaround for this issue. */ - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false); } @@ -2145,9 +2145,9 @@ SM_STATE(WPA_PTK, PTKSTART) size_t pmkid_len = 0; SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); - sm->PTKRequest = FALSE; - sm->TimeoutEvt = FALSE; - sm->alt_snonce_valid = FALSE; + sm->PTKRequest = false; + sm->TimeoutEvt = false; + sm->alt_snonce_valid = false; sm->TimeoutCtr++; if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { @@ -2312,8 +2312,8 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, fils_ft, &fils_ft_len); if (res < 0) return res; - sm->PTK_valid = TRUE; - sm->tk_already_set = FALSE; + sm->PTK_valid = true; + sm->tk_already_set = false; #ifdef CONFIG_IEEE80211R_AP if (fils_ft_len) { @@ -2811,7 +2811,7 @@ int fils_set_tk(struct wpa_state_machine *sm) wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); return -1; } - sm->tk_already_set = TRUE; + sm->tk_already_set = true; return 0; } @@ -2882,8 +2882,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround; SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; - sm->update_snonce = FALSE; + sm->EAPOLKeyReceived = false; + sm->update_snonce = false; os_memset(&PTK, 0, sizeof(PTK)); mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); @@ -3117,11 +3117,11 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) sm->pmk_len = PMK_LEN; } - sm->MICVerified = TRUE; + sm->MICVerified = true; os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); forced_memzero(&PTK, sizeof(PTK)); - sm->PTK_valid = TRUE; + sm->PTK_valid = true; } @@ -3274,7 +3274,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) struct wpa_auth_config *conf = &sm->wpa_auth->conf; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); - sm->TimeoutEvt = FALSE; + sm->TimeoutEvt = false; sm->TimeoutCtr++; if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) { @@ -3509,7 +3509,7 @@ done: SM_STATE(WPA_PTK, PTKINITDONE) { SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; + sm->EAPOLKeyReceived = false; if (sm->Pair) { enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); int klen = wpa_cipher_key_len(sm->pairwise); @@ -3529,7 +3529,7 @@ SM_STATE(WPA_PTK, PTKINITDONE) return; } /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ - sm->pairwise_set = TRUE; + sm->pairwise_set = true; wpa_auth_set_ptk_rekey_timer(sm); @@ -3551,12 +3551,13 @@ SM_STATE(WPA_PTK, PTKINITDONE) wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 1); } - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, + false); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true); if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = TRUE; + sm->PInitAKeys = true; else - sm->has_GTK = TRUE; + sm->has_GTK = true; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, "pairwise key handshake completed (%s)", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); @@ -3606,7 +3607,7 @@ SM_STEP(WPA_PTK) case WPA_PTK_AUTHENTICATION2: if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && wpa_auth_get_eapol(wpa_auth, sm->addr, - WPA_EAPOL_keyRun) > 0) + WPA_EAPOL_keyRun)) SM_ENTER(WPA_PTK, INITPMK); else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE @@ -3617,7 +3618,7 @@ SM_STEP(WPA_PTK) break; case WPA_PTK_INITPMK: if (wpa_auth_get_eapol(wpa_auth, sm->addr, - WPA_EAPOL_keyAvailable) > 0) { + WPA_EAPOL_keyAvailable)) { SM_ENTER(WPA_PTK, PTKSTART); #ifdef CONFIG_DPP } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) { @@ -3700,7 +3701,7 @@ SM_STATE(WPA_PTK_GROUP, IDLE) if (sm->Init) { /* Init flag is not cleared here, so avoid busy * loop by claiming nothing changed. */ - sm->changed = FALSE; + sm->changed = false; } sm->GTimeoutCtr = 0; } @@ -3730,8 +3731,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) } if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = FALSE; - sm->TimeoutEvt = FALSE; + sm->PInitAKeys = false; + sm->TimeoutEvt = false; /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ os_memset(rsc, 0, WPA_KEY_RSC_LEN); if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) @@ -3797,7 +3798,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) #endif /* CONFIG_OCV */ SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); - sm->EAPOLKeyReceived = FALSE; + sm->EAPOLKeyReceived = false; #ifdef CONFIG_OCV mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); @@ -3849,13 +3850,13 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; + sm->GUpdateStationKeys = false; sm->GTimeoutCtr = 0; /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, "group key handshake completed (%s)", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); - sm->has_GTK = TRUE; + sm->has_GTK = true; } @@ -3864,8 +3865,8 @@ SM_STATE(WPA_PTK_GROUP, KEYERROR) SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->Disconnect = TRUE; + sm->GUpdateStationKeys = false; + sm->Disconnect = true; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, "group key handshake failed (%s) after %u tries", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN", @@ -3877,7 +3878,7 @@ SM_STEP(WPA_PTK_GROUP) { if (sm->Init || sm->PtkGroupInit) { SM_ENTER(WPA_PTK_GROUP, IDLE); - sm->PtkGroupInit = FALSE; + sm->PtkGroupInit = false; } else switch (sm->wpa_ptk_group_state) { case WPA_PTK_GROUP_IDLE: if (sm->GUpdateStationKeys || @@ -3957,7 +3958,7 @@ static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, wpa_printf(MSG_DEBUG, "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)", group->vlan_id); - group->changed = FALSE; /* GInit is not cleared here; avoid loop */ + group->changed = false; /* GInit is not cleared here; avoid loop */ group->wpa_group_state = WPA_GROUP_GTK_INIT; /* GTK[0..N] = 0 */ @@ -3981,7 +3982,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "Not in PTKINITDONE; skip Group Key update"); - sm->GUpdateStationKeys = FALSE; + sm->GUpdateStationKeys = false; return 0; } if (sm->GUpdateStationKeys) { @@ -3999,7 +4000,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) return 0; sm->group->GKeyDoneStations++; - sm->GUpdateStationKeys = TRUE; + sm->GUpdateStationKeys = true; wpa_sm_step(sm); return 0; @@ -4125,9 +4126,9 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, wpa_printf(MSG_DEBUG, "WPA: group state machine entering state SETKEYS (VLAN-ID %d)", group->vlan_id); - group->changed = TRUE; + group->changed = true; group->wpa_group_state = WPA_GROUP_SETKEYS; - group->GTKReKey = FALSE; + group->GTKReKey = false; tmp = group->GM; group->GM = group->GN; group->GN = tmp; @@ -4199,7 +4200,7 @@ static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR " for disconnection due to fatal failure", MAC2STR(sm->addr)); - sm->Disconnect = TRUE; + sm->Disconnect = true; } return 0; @@ -4211,7 +4212,7 @@ static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, { wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE"); - group->changed = TRUE; + group->changed = true; group->wpa_group_state = WPA_GROUP_FATAL_FAILURE; wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group); } @@ -4223,7 +4224,7 @@ static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, wpa_printf(MSG_DEBUG, "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)", group->vlan_id); - group->changed = TRUE; + group->changed = true; group->wpa_group_state = WPA_GROUP_SETKEYSDONE; if (wpa_group_config_group_keys(wpa_auth, group) < 0) { @@ -4275,8 +4276,8 @@ static int wpa_sm_step(struct wpa_state_machine *sm) if (sm->pending_deinit) break; - sm->changed = FALSE; - sm->wpa_auth->group->changed = FALSE; + sm->changed = false; + sm->wpa_auth->group->changed = false; SM_STEP_RUN(WPA_PTK); if (sm->pending_deinit) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 4b17da7a4..5af65aad8 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2799,8 +2799,8 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry) return; /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ - sm->pairwise_set = TRUE; - sm->tk_already_set = TRUE; + sm->pairwise_set = true; + sm->tk_already_set = true; } @@ -3157,8 +3157,8 @@ pmk_r1_derived: return WLAN_STATUS_UNSPECIFIED_FAILURE; sm->pairwise = pairwise; - sm->PTK_valid = TRUE; - sm->tk_already_set = FALSE; + sm->PTK_valid = true; + sm->tk_already_set = false; wpa_ft_install_ptk(sm, 0); if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 058b34ca3..44ab83095 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -277,16 +277,15 @@ static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, break; case WPA_EAPOL_keyRun: if (sta->eapol_sm) - sta->eapol_sm->keyRun = value ? TRUE : FALSE; + sta->eapol_sm->keyRun = value; break; case WPA_EAPOL_keyAvailable: if (sta->eapol_sm) - sta->eapol_sm->eap_if->eapKeyAvailable = - value ? TRUE : FALSE; + sta->eapol_sm->eap_if->eapKeyAvailable = value; break; case WPA_EAPOL_keyDone: if (sta->eapol_sm) - sta->eapol_sm->keyDone = value ? TRUE : FALSE; + sta->eapol_sm->keyDone = value; break; case WPA_EAPOL_inc_EapolFramesTx: if (sta->eapol_sm) diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 813612e74..af0aaca1b 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -39,20 +39,20 @@ struct wpa_state_machine { WPA_PTK_GROUP_KEYERROR } wpa_ptk_group_state; - Boolean Init; - Boolean DeauthenticationRequest; - Boolean AuthenticationRequest; - Boolean ReAuthenticationRequest; - Boolean Disconnect; + bool Init; + bool DeauthenticationRequest; + bool AuthenticationRequest; + bool ReAuthenticationRequest; + bool Disconnect; u16 disconnect_reason; /* specific reason code to use with Disconnect */ u32 TimeoutCtr; u32 GTimeoutCtr; - Boolean TimeoutEvt; - Boolean EAPOLKeyReceived; - Boolean EAPOLKeyPairwise; - Boolean EAPOLKeyRequest; - Boolean MICVerified; - Boolean GUpdateStationKeys; + bool TimeoutEvt; + bool EAPOLKeyReceived; + bool EAPOLKeyPairwise; + bool EAPOLKeyRequest; + bool MICVerified; + bool GUpdateStationKeys; u8 ANonce[WPA_NONCE_LEN]; u8 SNonce[WPA_NONCE_LEN]; u8 alt_SNonce[WPA_NONCE_LEN]; @@ -62,21 +62,21 @@ struct wpa_state_machine { u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */ struct wpa_ptk PTK; u8 keyidx_active; - Boolean use_ext_key_id; - Boolean PTK_valid; - Boolean pairwise_set; - Boolean tk_already_set; + bool use_ext_key_id; + bool PTK_valid; + bool pairwise_set; + bool tk_already_set; int keycount; - Boolean Pair; + bool Pair; struct wpa_key_replay_counter { u8 counter[WPA_REPLAY_COUNTER_LEN]; - Boolean valid; + bool valid; } key_replay[RSNA_MAX_EAPOL_RETRIES], prev_key_replay[RSNA_MAX_EAPOL_RETRIES]; - Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */ - Boolean PTKRequest; /* not in IEEE 802.11i state machine */ - Boolean has_GTK; - Boolean PtkGroupInit; /* init request for PTK Group state machine */ + bool PInitAKeys; /* WPA only, not in IEEE 802.11i */ + bool PTKRequest; /* not in IEEE 802.11i state machine */ + bool has_GTK; + bool PtkGroupInit; /* init request for PTK Group state machine */ u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */ size_t last_rx_eapol_key_len; @@ -174,12 +174,12 @@ struct wpa_group { struct wpa_group *next; int vlan_id; - Boolean GInit; + bool GInit; int GKeyDoneStations; - Boolean GTKReKey; + bool GTKReKey; int GTK_len; int GN, GM; - Boolean GTKAuthenticator; + bool GTKAuthenticator; u8 Counter[WPA_NONCE_LEN]; enum { @@ -191,9 +191,9 @@ struct wpa_group { u8 GMK[WPA_GMK_LEN]; u8 GTK[2][WPA_GTK_MAX_LEN]; u8 GNonce[WPA_NONCE_LEN]; - Boolean changed; - Boolean first_sta_seen; - Boolean reject_4way_hs_for_entropy; + bool changed; + bool first_sta_seen; + bool reject_4way_hs_for_entropy; u8 IGTK[2][WPA_IGTK_MAX_LEN]; u8 BIGTK[2][WPA_IGTK_MAX_LEN]; int GN_igtk, GM_igtk; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 9bcb997a1..8dfd65700 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -950,7 +950,7 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, if (conf->extended_key_id && sm->wpa == WPA_VERSION_WPA2 && sm->pairwise != WPA_CIPHER_TKIP && (data.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) { - sm->use_ext_key_id = TRUE; + sm->use_ext_key_id = true; if (conf->extended_key_id == 2 && !wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !wpa_key_mgmt_fils(sm->wpa_key_mgmt)) @@ -961,7 +961,7 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, "RSN: Extended Key ID supported (start with %d)", sm->keyidx_active); } else { - sm->use_ext_key_id = FALSE; + sm->use_ext_key_id = false; } if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { From 3dc69721e8f206141aff221ab2ea7438a63a116d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 00:29:09 +0300 Subject: [PATCH 0409/1105] EAPOL auth: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/ap/ieee802_1x.c | 81 ++++++++++++------------ src/ap/ieee802_1x.h | 7 +-- src/eapol_auth/eapol_auth_sm.c | 102 +++++++++++++++---------------- src/eapol_auth/eapol_auth_sm_i.h | 40 ++++++------ 4 files changed, 114 insertions(+), 116 deletions(-) diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 6d4d43554..ee095f618 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -878,7 +878,7 @@ static void handle_eap_response(struct hostapd_data *hapd, wpabuf_free(sm->eap_if->eapRespData); sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); - sm->eapolEap = TRUE; + sm->eapolEap = true; } @@ -909,7 +909,7 @@ static void handle_eap_initiate(struct hostapd_data *hapd, wpabuf_free(sm->eap_if->eapRespData); sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); - sm->eapolEap = TRUE; + sm->eapolEap = true; #endif /* CONFIG_ERP */ } @@ -1140,7 +1140,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, } #endif /* CONFIG_WPS */ - sta->eapol_sm->eap_if->portEnabled = TRUE; + sta->eapol_sm->eap_if->portEnabled = true; } /* since we support version 1, we can ignore version field and proceed @@ -1167,7 +1167,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, "cached PMKSA available - ignore it since STA sent EAPOL-Start"); wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa); } - sta->eapol_sm->eapolStart = TRUE; + sta->eapol_sm->eapolStart = true; sta->eapol_sm->dot1xAuthEapolStartFramesRx++; eap_server_clear_identity(sta->eapol_sm->eap); wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); @@ -1180,7 +1180,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; accounting_sta_stop(hapd, sta); - sta->eapol_sm->eapolLogoff = TRUE; + sta->eapol_sm->eapolLogoff = true; sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; eap_server_clear_identity(sta->eapol_sm->eap); break; @@ -1297,7 +1297,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) } #endif /* CONFIG_WPS */ - sta->eapol_sm->eap_if->portEnabled = TRUE; + sta->eapol_sm->eap_if->portEnabled = true; #ifdef CONFIG_IEEE80211R_AP if (sta->auth_alg == WLAN_AUTH_FT) { @@ -1306,13 +1306,13 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) "PMK from FT - skip IEEE 802.1X/EAP"); /* Setup EAPOL state machines to already authenticated state * because of existing FT information from R0KH. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; + sta->eapol_sm->keyRun = true; + sta->eapol_sm->eap_if->eapKeyAvailable = true; sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - sta->eapol_sm->authFail = FALSE; - sta->eapol_sm->portValid = TRUE; + sta->eapol_sm->authSuccess = true; + sta->eapol_sm->authFail = false; + sta->eapol_sm->portValid = true; if (sta->eapol_sm->eap) eap_sm_notify_cached(sta->eapol_sm->eap); ap_sta_bind_vlan(hapd, sta); @@ -1329,13 +1329,13 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) "PMK from FILS - skip IEEE 802.1X/EAP"); /* Setup EAPOL state machines to already authenticated state * because of existing FILS information. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; + sta->eapol_sm->keyRun = true; + sta->eapol_sm->eap_if->eapKeyAvailable = true; sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - sta->eapol_sm->authFail = FALSE; - sta->eapol_sm->portValid = TRUE; + sta->eapol_sm->authSuccess = true; + sta->eapol_sm->authFail = false; + sta->eapol_sm->portValid = true; if (sta->eapol_sm->eap) eap_sm_notify_cached(sta->eapol_sm->eap); wpa_auth_set_ptk_rekey_timer(sta->wpa_sm); @@ -1350,12 +1350,12 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); /* Setup EAPOL state machines to already authenticated state * because of existing PMKSA information in the cache. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; + sta->eapol_sm->keyRun = true; + sta->eapol_sm->eap_if->eapKeyAvailable = true; sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - sta->eapol_sm->authFail = FALSE; + sta->eapol_sm->authSuccess = true; + sta->eapol_sm->authFail = false; if (sta->eapol_sm->eap) eap_sm_notify_cached(sta->eapol_sm->eap); pmksa_cache_to_eapol_data(hapd, pmksa, sta->eapol_sm); @@ -1367,7 +1367,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) * re-authentication without having to wait for the * Supplicant to send EAPOL-Start. */ - sta->eapol_sm->reAuthenticate = TRUE; + sta->eapol_sm->reAuthenticate = true; } eapol_auth_step(sta->eapol_sm); } @@ -1415,7 +1415,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, if (!sm || !sm->last_recv_radius) { if (sm) - sm->eap_if->aaaEapNoReq = TRUE; + sm->eap_if->aaaEapNoReq = true; return; } @@ -1429,7 +1429,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_WARNING, "could not extract EAP-Message from RADIUS message"); - sm->eap_if->aaaEapNoReq = TRUE; + sm->eap_if->aaaEapNoReq = true; return; } @@ -1438,7 +1438,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, HOSTAPD_LEVEL_WARNING, "too short EAP packet received from authentication server"); wpabuf_free(eap); - sm->eap_if->aaaEapNoReq = TRUE; + sm->eap_if->aaaEapNoReq = true; return; } @@ -1473,7 +1473,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, "decapsulated EAP packet (code=%d id=%d len=%d) from RADIUS server: %s", hdr->code, hdr->identifier, be_to_host16(hdr->length), buf); - sm->eap_if->aaaEapReq = TRUE; + sm->eap_if->aaaEapReq = true; wpabuf_free(sm->eap_if->aaaEapReqData); sm->eap_if->aaaEapReqData = eap; @@ -1512,7 +1512,7 @@ static void ieee802_1x_get_keys(struct hostapd_data *hapd, os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len, keys->send, keys->send_len); sm->eap_if->aaaEapKeyDataLen = len; - sm->eap_if->aaaEapKeyAvailable = TRUE; + sm->eap_if->aaaEapKeyAvailable = true; } } else { wpa_printf(MSG_DEBUG, @@ -1880,7 +1880,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg, if (vlan_desc.notempty && !hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) { - sta->eapol_sm->authFail = TRUE; + sta->eapol_sm->authFail = true; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "Invalid VLAN %d%s received from RADIUS server", @@ -1893,7 +1893,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg, if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED && !vlan_desc.notempty) { - sta->eapol_sm->authFail = TRUE; + sta->eapol_sm->authFail = true; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_INFO, "authentication server did not include required VLAN ID in Access-Accept"); @@ -2019,7 +2019,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, else ap_sta_no_session_timeout(hapd, sta); - sm->eap_if->aaaSuccess = TRUE; + sm->eap_if->aaaSuccess = true; override_eapReq = 1; ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret, shared_secret_len); @@ -2031,7 +2031,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, (int) session_timeout : -1); break; case RADIUS_CODE_ACCESS_REJECT: - sm->eap_if->aaaFail = TRUE; + sm->eap_if->aaaFail = true; override_eapReq = 1; if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE, &reason_code) == 0) { @@ -2042,7 +2042,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, } break; case RADIUS_CODE_ACCESS_CHALLENGE: - sm->eap_if->aaaEapReq = TRUE; + sm->eap_if->aaaEapReq = true; if (session_timeout_set) { /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */ sm->eap_if->aaaMethodTimeout = session_timeout; @@ -2063,7 +2063,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, ieee802_1x_decapsulate_radius(hapd, sta); if (override_eapReq) - sm->eap_if->aaaEapReq = FALSE; + sm->eap_if->aaaEapReq = false; #ifdef CONFIG_FILS #ifdef NEED_AP_MLME @@ -2109,7 +2109,7 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR, MAC2STR(sta->addr)); - sm->eap_if->portEnabled = FALSE; + sm->eap_if->portEnabled = false; ap_sta_disconnect(hapd, sta, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); } @@ -2148,7 +2148,7 @@ static int ieee802_1x_sta_key_available(struct hostapd_data *hapd, struct sta_info *sta, void *ctx) { if (sta->eapol_sm) { - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; + sta->eapol_sm->eap_if->eapKeyAvailable = true; eapol_auth_step(sta->eapol_sm); } return 0; @@ -2677,26 +2677,25 @@ const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm, void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled) + bool enabled) { if (!sm) return; - sm->eap_if->portEnabled = enabled ? TRUE : FALSE; + sm->eap_if->portEnabled = enabled; eapol_auth_step(sm); } -void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, - int valid) +void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid) { if (!sm) return; - sm->portValid = valid ? TRUE : FALSE; + sm->portValid = valid; eapol_auth_step(sm); } -void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) +void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth) { if (!sm) return; @@ -2707,7 +2706,7 @@ void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) } -static const char * bool_txt(Boolean val) +static const char * bool_txt(bool val) { return val ? "TRUE" : "FALSE"; } diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h index bb85b93d6..70dc11afe 100644 --- a/src/ap/ieee802_1x.h +++ b/src/ap/ieee802_1x.h @@ -42,10 +42,9 @@ const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len); const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm, size_t *len); void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled); -void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, - int valid); -void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth); + bool enabled); +void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid); +void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth); int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, char *buf, size_t buflen); diff --git a/src/eapol_auth/eapol_auth_sm.c b/src/eapol_auth/eapol_auth_sm.c index 2e79614fd..e3a57e7db 100644 --- a/src/eapol_auth/eapol_auth_sm.c +++ b/src/eapol_auth/eapol_auth_sm.c @@ -206,10 +206,10 @@ SM_STATE(AUTH_PAE, INITIALIZE) * get here on disconnection event without advancing to the * AUTHENTICATING state to clear keyRun before the IEEE 802.11 RSN * authenticator state machine runs and that may advance from - * AUTHENTICATION2 to INITPMK if keyRun = TRUE has been left from the + * AUTHENTICATION2 to INITPMK if keyRun = true has been left from the * last association. This can be avoided by clearing keyRun here. */ - sm->keyRun = FALSE; + sm->keyRun = false; } @@ -229,7 +229,7 @@ SM_STATE(AUTH_PAE, DISCONNECTED) sm->authPortStatus = Unauthorized; setPortUnauthorized(); sm->reAuthCount = 0; - sm->eapolLogoff = FALSE; + sm->eapolLogoff = false; if (!from_initialize) { sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, sm->flags & EAPOL_SM_PREAUTH, @@ -251,7 +251,7 @@ SM_STATE(AUTH_PAE, RESTART) SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae); - sm->eap_if->eapRestart = TRUE; + sm->eap_if->eapRestart = true; } @@ -262,7 +262,7 @@ SM_STATE(AUTH_PAE, CONNECTING) SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae); - sm->reAuthenticate = FALSE; + sm->reAuthenticate = false; sm->reAuthCount++; } @@ -277,7 +277,7 @@ SM_STATE(AUTH_PAE, HELD) sm->authPortStatus = Unauthorized; setPortUnauthorized(); sm->quietWhile = sm->quietPeriod; - sm->eapolLogoff = FALSE; + sm->eapolLogoff = false; eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING, "authentication failed - EAP type: %d (%s)", @@ -324,13 +324,13 @@ SM_STATE(AUTH_PAE, AUTHENTICATING) { SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae); - sm->eapolStart = FALSE; - sm->authSuccess = FALSE; - sm->authFail = FALSE; - sm->authTimeout = FALSE; - sm->authStart = TRUE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; + sm->eapolStart = false; + sm->authSuccess = false; + sm->authFail = false; + sm->authTimeout = false; + sm->authStart = true; + sm->keyRun = false; + sm->keyDone = false; } @@ -347,9 +347,9 @@ SM_STATE(AUTH_PAE, ABORTING) SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae); - sm->authAbort = TRUE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; + sm->authAbort = true; + sm->keyRun = false; + sm->keyDone = false; } @@ -360,7 +360,7 @@ SM_STATE(AUTH_PAE, FORCE_AUTH) sm->authPortStatus = Authorized; setPortAuthorized(); sm->portMode = ForceAuthorized; - sm->eapolStart = FALSE; + sm->eapolStart = false; txCannedSuccess(); } @@ -372,7 +372,7 @@ SM_STATE(AUTH_PAE, FORCE_UNAUTH) sm->authPortStatus = Unauthorized; setPortUnauthorized(); sm->portMode = ForceUnauthorized; - sm->eapolStart = FALSE; + sm->eapolStart = false; txCannedFail(); } @@ -457,8 +457,8 @@ SM_STATE(BE_AUTH, INITIALIZE) SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth); abortAuth(); - sm->eap_if->eapNoReq = FALSE; - sm->authAbort = FALSE; + sm->eap_if->eapNoReq = false; + sm->authAbort = false; } @@ -467,7 +467,7 @@ SM_STATE(BE_AUTH, REQUEST) SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); txReq(); - sm->eap_if->eapReq = FALSE; + sm->eap_if->eapReq = false; sm->backendOtherRequestsToSupplicant++; /* @@ -481,7 +481,7 @@ SM_STATE(BE_AUTH, REQUEST) * EAP-Request from the main EAP method. This can be avoided by * clearing eapolEap here. */ - sm->eapolEap = FALSE; + sm->eapolEap = false; } @@ -489,11 +489,11 @@ SM_STATE(BE_AUTH, RESPONSE) { SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth); - sm->authTimeout = FALSE; - sm->eapolEap = FALSE; - sm->eap_if->eapNoReq = FALSE; + sm->authTimeout = false; + sm->eapolEap = false; + sm->eap_if->eapNoReq = false; sm->aWhile = sm->serverTimeout; - sm->eap_if->eapResp = TRUE; + sm->eap_if->eapResp = true; /* sendRespToServer(); */ sm->backendResponses++; } @@ -504,8 +504,8 @@ SM_STATE(BE_AUTH, SUCCESS) SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth); txReq(); - sm->authSuccess = TRUE; - sm->keyRun = TRUE; + sm->authSuccess = true; + sm->keyRun = true; } @@ -514,7 +514,7 @@ SM_STATE(BE_AUTH, FAIL) SM_ENTRY_MA(BE_AUTH, FAIL, be_auth); txReq(); - sm->authFail = TRUE; + sm->authFail = true; } @@ -522,7 +522,7 @@ SM_STATE(BE_AUTH, TIMEOUT) { SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth); - sm->authTimeout = TRUE; + sm->authTimeout = true; } @@ -530,7 +530,7 @@ SM_STATE(BE_AUTH, IDLE) { SM_ENTRY_MA(BE_AUTH, IDLE, be_auth); - sm->authStart = FALSE; + sm->authStart = false; } @@ -538,7 +538,7 @@ SM_STATE(BE_AUTH, IGNORE) { SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth); - sm->eap_if->eapNoReq = FALSE; + sm->eap_if->eapNoReq = false; } @@ -621,7 +621,7 @@ SM_STATE(REAUTH_TIMER, REAUTHENTICATE) { SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer); - sm->reAuthenticate = TRUE; + sm->reAuthenticate = true; sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, EAPOL_AUTH_REAUTHENTICATE); } @@ -663,8 +663,8 @@ SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT) SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); txKey(); - sm->eap_if->eapKeyAvailable = FALSE; - sm->keyDone = TRUE; + sm->eap_if->eapKeyAvailable = false; + sm->keyDone = true; } @@ -705,7 +705,7 @@ SM_STATE(KEY_RX, KEY_RECEIVE) SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx); processKey(); - sm->rxKey = FALSE; + sm->rxKey = false; } @@ -807,7 +807,7 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE; sm->reAuthPeriod = eapol->conf.eap_reauth_period; - sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE; + sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0; sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT; @@ -820,14 +820,14 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, #ifdef CONFIG_WEP if (!eapol->conf.wpa && (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0)) - sm->keyTxEnabled = TRUE; + sm->keyTxEnabled = true; else #endif /* CONFIG_WEP */ - sm->keyTxEnabled = FALSE; + sm->keyTxEnabled = false; if (eapol->conf.wpa) - sm->portValid = FALSE; + sm->portValid = false; else - sm->portValid = TRUE; + sm->portValid = true; os_memset(&eap_sess, 0, sizeof(eap_sess)); eap_sess.assoc_wps_ie = assoc_wps_ie; @@ -949,7 +949,7 @@ restart: /* TODO: find a better location for this */ if (sm->eap_if->aaaEapResp) { - sm->eap_if->aaaEapResp = FALSE; + sm->eap_if->aaaEapResp = false; if (sm->eap_if->aaaEapRespData == NULL) { wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, " "but no aaaEapRespData available"); @@ -996,14 +996,14 @@ void eapol_auth_step(struct eapol_state_machine *sm) static void eapol_auth_initialize(struct eapol_state_machine *sm) { - sm->initializing = TRUE; + sm->initializing = true; /* Initialize the state machines by asserting initialize and then * deasserting it after one step */ - sm->initialize = TRUE; + sm->initialize = true; eapol_sm_step_run(sm); - sm->initialize = FALSE; + sm->initialize = false; eapol_sm_step_run(sm); - sm->initializing = FALSE; + sm->initializing = false; /* Start one second tick for port timers state machine */ eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); @@ -1091,7 +1091,7 @@ void eapol_auth_reauthenticate(struct eapol_state_machine *sm) { wpa_printf(MSG_DEBUG, "EAPOL: External reauthentication trigger for " MACSTR, MAC2STR(sm->addr)); - sm->reAuthenticate = TRUE; + sm->reAuthenticate = true; eapol_auth_step(sm); } @@ -1144,9 +1144,9 @@ int eapol_auth_set_conf(struct eapol_state_machine *sm, const char *param, if (os_strcasecmp(param, "reAuthEnabled") == 0) { if (os_strcmp(value, "TRUE") == 0) - sm->reAuthEnabled = TRUE; + sm->reAuthEnabled = true; else if (os_strcmp(value, "FALSE") == 0) - sm->reAuthEnabled = FALSE; + sm->reAuthEnabled = false; else return -1; eapol_auth_step(sm); @@ -1155,9 +1155,9 @@ int eapol_auth_set_conf(struct eapol_state_machine *sm, const char *param, if (os_strcasecmp(param, "KeyTransmissionEnabled") == 0) { if (os_strcmp(value, "TRUE") == 0) - sm->keyTxEnabled = TRUE; + sm->keyTxEnabled = true; else if (os_strcmp(value, "FALSE") == 0) - sm->keyTxEnabled = FALSE; + sm->keyTxEnabled = false; else return -1; eapol_auth_step(sm); diff --git a/src/eapol_auth/eapol_auth_sm_i.h b/src/eapol_auth/eapol_auth_sm_i.h index 04386b2ce..3c6898310 100644 --- a/src/eapol_auth/eapol_auth_sm_i.h +++ b/src/eapol_auth/eapol_auth_sm_i.h @@ -43,23 +43,23 @@ struct eapol_state_machine { int reAuthWhen; /* global variables */ - Boolean authAbort; - Boolean authFail; + bool authAbort; + bool authFail; PortState authPortStatus; - Boolean authStart; - Boolean authTimeout; - Boolean authSuccess; - Boolean eapolEap; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; - Boolean keyTxEnabled; + bool authStart; + bool authTimeout; + bool authSuccess; + bool eapolEap; + bool initialize; + bool keyDone; + bool keyRun; + bool keyTxEnabled; PortTypes portControl; - Boolean portValid; - Boolean reAuthenticate; + bool portValid; + bool reAuthenticate; /* Port Timers state machine */ - /* 'Boolean tick' implicitly handled as registered timeout */ + /* 'bool tick' implicitly handled as registered timeout */ /* Authenticator PAE state machine */ enum { AUTH_PAE_INITIALIZE, AUTH_PAE_DISCONNECTED, AUTH_PAE_CONNECTING, @@ -67,8 +67,8 @@ struct eapol_state_machine { AUTH_PAE_ABORTING, AUTH_PAE_HELD, AUTH_PAE_FORCE_AUTH, AUTH_PAE_FORCE_UNAUTH, AUTH_PAE_RESTART } auth_pae_state; /* variables */ - Boolean eapolLogoff; - Boolean eapolStart; + bool eapolLogoff; + bool eapolStart; PortTypes portMode; unsigned int reAuthCount; /* constants */ @@ -109,7 +109,7 @@ struct eapol_state_machine { } reauth_timer_state; /* constants */ unsigned int reAuthPeriod; /* default 3600 s */ - Boolean reAuthEnabled; + bool reAuthEnabled; /* Authenticator Key Transmit state machine */ enum { AUTH_KEY_TX_NO_KEY_TRANSMIT, AUTH_KEY_TX_KEY_TRANSMIT @@ -118,14 +118,14 @@ struct eapol_state_machine { /* Key Receive state machine */ enum { KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE } key_rx_state; /* variables */ - Boolean rxKey; + bool rxKey; /* Controlled Directions state machine */ enum { CTRL_DIR_FORCE_BOTH, CTRL_DIR_IN_OR_BOTH } ctrl_dir_state; /* variables */ ControlledDirection adminControlledDirections; ControlledDirection operControlledDirections; - Boolean operEdge; + bool operEdge; /* Authenticator Statistics Table */ Counter dot1xAuthEapolFramesRx; @@ -161,8 +161,8 @@ struct eapol_state_machine { struct eap_sm *eap; - Boolean initializing; /* in process of initializing state machines */ - Boolean changed; + bool initializing; /* in process of initializing state machines */ + bool changed; struct eapol_authenticator *eapol; From 37e3501bf770cff9cad49e28f774aac96a1d976c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 00:41:16 +0300 Subject: [PATCH 0410/1105] FST: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/ap/hostapd.c | 6 +-- src/fst/fst.c | 16 +++--- src/fst/fst.h | 16 +++--- src/fst/fst_ctrl_aux.h | 4 +- src/fst/fst_ctrl_iface.c | 48 ++++++++--------- src/fst/fst_ctrl_iface.h | 2 +- src/fst/fst_group.c | 10 ++-- src/fst/fst_group.h | 4 +- src/fst/fst_iface.c | 8 +-- src/fst/fst_iface.h | 8 +-- src/fst/fst_session.c | 96 ++++++++++++++++----------------- src/fst/fst_session.h | 12 ++--- wpa_supplicant/wpa_supplicant.c | 4 +- 13 files changed, 117 insertions(+), 117 deletions(-) diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index f2e964ac0..5515ab34d 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1772,7 +1772,7 @@ static void fst_hostapd_update_mb_ie_cb(void *ctx, const u8 *addr, static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { struct sta_info *s = (struct sta_info *) *get_ctx; @@ -1794,7 +1794,7 @@ static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx, static const u8 * fst_hostapd_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { struct hostapd_data *hapd = ctx; @@ -1806,7 +1806,7 @@ static const u8 * fst_hostapd_get_peer_first(void *ctx, static const u8 * fst_hostapd_get_peer_next(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { return fst_hostapd_get_sta(get_ctx, mb_only); } diff --git a/src/fst/fst.c b/src/fst/fst.c index fbe1175ac..21ef3d8b7 100644 --- a/src/fst/fst.c +++ b/src/fst/fst.c @@ -20,7 +20,7 @@ struct dl_list fst_global_ctrls_list; static void fst_ctrl_iface_notify_peer_state_change(struct fst_iface *iface, - Boolean connected, + bool connected, const u8 *peer_addr) { union fst_event_extra extra; @@ -42,7 +42,7 @@ struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr, struct fst_group *g; struct fst_group *group = NULL; struct fst_iface *iface = NULL; - Boolean new_group = FALSE; + bool new_group = false; WPA_ASSERT(ifname != NULL); WPA_ASSERT(iface_obj != NULL); @@ -62,7 +62,7 @@ struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr, cfg->group_id); return NULL; } - new_group = TRUE; + new_group = true; } iface = fst_iface_create(group, ifname, own_addr, iface_obj, cfg); @@ -166,7 +166,7 @@ void fst_global_del_ctrl(struct fst_ctrl_handle *h) void fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt, size_t len) { - if (fst_iface_is_connected(iface, mgmt->sa, FALSE)) + if (fst_iface_is_connected(iface, mgmt->sa, false)) fst_session_on_action_rx(iface, mgmt, len); else wpa_printf(MSG_DEBUG, @@ -187,7 +187,7 @@ void fst_notify_peer_connected(struct fst_iface *iface, const u8 *addr) fst_printf_iface(iface, MSG_DEBUG, MACSTR " became connected", MAC2STR(addr)); - fst_ctrl_iface_notify_peer_state_change(iface, TRUE, addr); + fst_ctrl_iface_notify_peer_state_change(iface, true, addr); } @@ -203,12 +203,12 @@ void fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr) fst_printf_iface(iface, MSG_DEBUG, MACSTR " became disconnected", MAC2STR(addr)); - fst_ctrl_iface_notify_peer_state_change(iface, FALSE, addr); + fst_ctrl_iface_notify_peer_state_change(iface, false, addr); } -Boolean fst_are_ifaces_aggregated(struct fst_iface *iface1, - struct fst_iface *iface2) +bool fst_are_ifaces_aggregated(struct fst_iface *iface1, + struct fst_iface *iface2) { return fst_iface_get_group(iface1) == fst_iface_get_group(iface2); } diff --git a/src/fst/fst.h b/src/fst/fst.h index 7ba60d545..2410a6ef1 100644 --- a/src/fst/fst.h +++ b/src/fst/fst.h @@ -113,24 +113,24 @@ struct fst_wpa_obj { * get_peer_first - Get MAC address of the 1st connected STA * @ctx: User context %ctx * @get_ctx: Context to be used for %get_peer_next call - * @mb_only: %TRUE if only multi-band capable peer should be reported + * @mb_only: %true if only multi-band capable peer should be reported * Returns: Address of the 1st connected STA, %NULL if no STAs connected */ const u8 * (*get_peer_first)(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only); + bool mb_only); /** * get_peer_next - Get MAC address of the next connected STA * @ctx: User context %ctx * @get_ctx: Context received from %get_peer_first or previous * %get_peer_next call - * @mb_only: %TRUE if only multi-band capable peer should be reported + * @mb_only: %true if only multi-band capable peer should be reported * Returns: Address of the next connected STA, %NULL if no more STAs * connected */ const u8 * (*get_peer_next)(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only); + bool mb_only); }; /** @@ -273,11 +273,11 @@ void fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr); * @iface1: 1st FST interface object * @iface1: 2nd FST interface object * - * Returns: %TRUE if the interfaces belong to the same FST group, - * %FALSE otherwise + * Returns: %true if the interfaces belong to the same FST group, + * %false otherwise */ -Boolean fst_are_ifaces_aggregated(struct fst_iface *iface1, - struct fst_iface *iface2); +bool fst_are_ifaces_aggregated(struct fst_iface *iface1, + struct fst_iface *iface2); /** * fst_update_mac_addr - Notify FST about MAC address change diff --git a/src/fst/fst_ctrl_aux.h b/src/fst/fst_ctrl_aux.h index 0aff5d061..ab80b6fc4 100644 --- a/src/fst/fst_ctrl_aux.h +++ b/src/fst/fst_ctrl_aux.h @@ -54,12 +54,12 @@ enum fst_initiator { union fst_event_extra { struct fst_event_extra_iface_state { - Boolean attached; + bool attached; char ifname[FST_MAX_INTERFACE_SIZE]; char group_id[FST_MAX_GROUP_ID_SIZE]; } iface_state; /* for EVENT_FST_IFACE_STATE_CHANGED */ struct fst_event_extra_peer_state { - Boolean connected; + bool connected; char ifname[FST_MAX_INTERFACE_SIZE]; u8 addr[ETH_ALEN]; } peer_state; /* for EVENT_PEER_STATE_CHANGED */ diff --git a/src/fst/fst_ctrl_iface.c b/src/fst/fst_ctrl_iface.c index 7df3362b6..45607b6d9 100644 --- a/src/fst/fst_ctrl_iface.c +++ b/src/fst/fst_ctrl_iface.c @@ -32,8 +32,8 @@ static struct fst_group * get_fst_group_by_id(const char *id) /* notifications */ -static Boolean format_session_state_extra(const union fst_event_extra *extra, - char *buffer, size_t size) +static bool format_session_state_extra(const union fst_event_extra *extra, + char *buffer, size_t size) { int len; char reject_str[32] = FST_CTRL_PVAL_NONE; @@ -42,7 +42,7 @@ static Boolean format_session_state_extra(const union fst_event_extra *extra, ss = &extra->session_state; if (ss->new_state != FST_SESSION_STATE_INITIAL) - return TRUE; + return true; switch (ss->extra.to_initial.reason) { case REASON_REJECT: @@ -183,10 +183,10 @@ static int session_get(const char *session_id, char *buf, size_t buflen) return os_snprintf(buf, buflen, "FAIL\n"); } - old_peer_addr = fst_session_get_peer_addr(s, TRUE); - new_peer_addr = fst_session_get_peer_addr(s, FALSE); - new_iface = fst_session_get_iface(s, FALSE); - old_iface = fst_session_get_iface(s, TRUE); + old_peer_addr = fst_session_get_peer_addr(s, true); + new_peer_addr = fst_session_get_peer_addr(s, false); + new_iface = fst_session_get_iface(s, false); + old_iface = fst_session_get_iface(s, true); return os_snprintf(buf, buflen, FST_CSG_PNAME_OLD_PEER_ADDR "=" MACSTR "\n" @@ -227,13 +227,13 @@ static int session_set(const char *session_id, char *buf, size_t buflen) p++; if (os_strncasecmp(p, FST_CSS_PNAME_OLD_IFNAME, q - p) == 0) { - ret = fst_session_set_str_ifname(s, q + 1, TRUE); + ret = fst_session_set_str_ifname(s, q + 1, true); } else if (os_strncasecmp(p, FST_CSS_PNAME_NEW_IFNAME, q - p) == 0) { - ret = fst_session_set_str_ifname(s, q + 1, FALSE); + ret = fst_session_set_str_ifname(s, q + 1, false); } else if (os_strncasecmp(p, FST_CSS_PNAME_OLD_PEER_ADDR, q - p) == 0) { - ret = fst_session_set_str_peer_addr(s, q + 1, TRUE); + ret = fst_session_set_str_peer_addr(s, q + 1, true); } else if (os_strncasecmp(p, FST_CSS_PNAME_NEW_PEER_ADDR, q - p) == 0) { - ret = fst_session_set_str_peer_addr(s, q + 1, FALSE); + ret = fst_session_set_str_peer_addr(s, q + 1, false); } else if (os_strncasecmp(p, FST_CSS_PNAME_LLT, q - p) == 0) { ret = fst_session_set_str_llt(s, q + 1); } else { @@ -539,8 +539,8 @@ static int iface_peers(const char *group_id, char *buf, size_t buflen) if (!found) return os_snprintf(buf, buflen, "FAIL\n"); - addr = fst_iface_get_peer_first(f, &ctx, FALSE); - for (; addr != NULL; addr = fst_iface_get_peer_next(f, &ctx, FALSE)) { + addr = fst_iface_get_peer_first(f, &ctx, false); + for (; addr != NULL; addr = fst_iface_get_peer_next(f, &ctx, false)) { int res; res = os_snprintf(buf + ret, buflen - ret, MACSTR "\n", @@ -692,7 +692,7 @@ static int print_band(unsigned num, struct fst_iface *iface, const u8 *addr, static void fst_ctrl_iface_on_iface_state_changed(struct fst_iface *i, - Boolean attached) + bool attached) { union fst_event_extra extra; @@ -710,14 +710,14 @@ static void fst_ctrl_iface_on_iface_state_changed(struct fst_iface *i, static int fst_ctrl_iface_on_iface_added(struct fst_iface *i) { - fst_ctrl_iface_on_iface_state_changed(i, TRUE); + fst_ctrl_iface_on_iface_state_changed(i, true); return 0; } static void fst_ctrl_iface_on_iface_removed(struct fst_iface *i) { - fst_ctrl_iface_on_iface_state_changed(i, FALSE); + fst_ctrl_iface_on_iface_state_changed(i, false); } @@ -749,7 +749,7 @@ int fst_ctrl_iface_mb_info(const u8 *addr, char *buf, size_t buflen) foreach_fst_group(g) { foreach_fst_group_iface(g, f) { - if (fst_iface_is_connected(f, addr, TRUE)) { + if (fst_iface_is_connected(f, addr, true)) { ret += print_band(num++, f, addr, buf + ret, buflen - ret); } @@ -789,7 +789,7 @@ int fst_ctrl_iface_receive(const char *cmd, char *reply, size_t reply_size) const struct fst_command *c; const char *p; const char *temp; - Boolean non_spaces_found; + bool non_spaces_found; for (c = commands; c->name; c++) { if (os_strncasecmp(cmd, c->name, os_strlen(c->name)) != 0) @@ -800,10 +800,10 @@ int fst_ctrl_iface_receive(const char *cmd, char *reply, size_t reply_size) return os_snprintf(reply, reply_size, "FAIL\n"); p++; temp = p; - non_spaces_found = FALSE; + non_spaces_found = false; while (*temp) { if (!isspace(*temp)) { - non_spaces_found = TRUE; + non_spaces_found = true; break; } temp++; @@ -818,18 +818,18 @@ int fst_ctrl_iface_receive(const char *cmd, char *reply, size_t reply_size) } -int fst_read_next_int_param(const char *params, Boolean *valid, char **endp) +int fst_read_next_int_param(const char *params, bool *valid, char **endp) { int ret = -1; const char *curp; - *valid = FALSE; + *valid = false; *endp = (char *) params; curp = params; if (*curp) { ret = (int) strtol(curp, endp, 0); if (!**endp || isspace(**endp)) - *valid = TRUE; + *valid = true; } return ret; @@ -887,7 +887,7 @@ int fst_parse_attach_command(const char *cmd, char *ifname, size_t ifname_size, { char *pos; char *endp; - Boolean is_valid; + bool is_valid; int val; if (fst_read_next_text_param(cmd, ifname, ifname_size, &endp) || diff --git a/src/fst/fst_ctrl_iface.h b/src/fst/fst_ctrl_iface.h index 4d0cd9fce..354b81fc7 100644 --- a/src/fst/fst_ctrl_iface.h +++ b/src/fst/fst_ctrl_iface.h @@ -30,7 +30,7 @@ fst_ctrl_iface_mb_info(const u8 *addr, char *buf, size_t buflen) #endif /* CONFIG_FST */ -int fst_read_next_int_param(const char *params, Boolean *valid, char **endp); +int fst_read_next_int_param(const char *params, bool *valid, char **endp); int fst_read_next_text_param(const char *params, char *buf, size_t buflen, char **endp); int fst_read_peer_addr(const char *mac, u8 *peer_addr); diff --git a/src/fst/fst_group.c b/src/fst/fst_group.c index a4ae016d9..d1c401497 100644 --- a/src/fst/fst_group.c +++ b/src/fst/fst_group.c @@ -305,7 +305,7 @@ fst_group_get_peer_other_connection_1(struct fst_iface *iface, if (other_iface == iface || band_id != fst_iface_get_band_id(other_iface)) continue; - if (fst_iface_is_connected(other_iface, tmp_peer_addr, FALSE)) { + if (fst_iface_is_connected(other_iface, tmp_peer_addr, false)) { os_memcpy(other_peer_addr, tmp_peer_addr, ETH_ALEN); return other_iface; } @@ -347,10 +347,10 @@ fst_group_get_peer_other_connection_2(struct fst_iface *iface, band_id != fst_iface_get_band_id(other_iface)) continue; cur_peer_addr = fst_iface_get_peer_first(other_iface, &ctx, - TRUE); + true); for (; cur_peer_addr; cur_peer_addr = fst_iface_get_peer_next(other_iface, &ctx, - TRUE)) { + true)) { cur_mbie = fst_iface_get_peer_mb_ie(other_iface, cur_peer_addr); if (!cur_mbie) @@ -493,9 +493,9 @@ void fst_group_delete(struct fst_group *group) } -Boolean fst_group_delete_if_empty(struct fst_group *group) +bool fst_group_delete_if_empty(struct fst_group *group) { - Boolean is_empty = !fst_group_has_ifaces(group) && + bool is_empty = !fst_group_has_ifaces(group) && !fst_session_global_get_first_by_group(group); if (is_empty) diff --git a/src/fst/fst_group.h b/src/fst/fst_group.h index 00aee9c8c..4a9ff3e82 100644 --- a/src/fst/fst_group.h +++ b/src/fst/fst_group.h @@ -29,7 +29,7 @@ void fst_group_delete(struct fst_group *g); void fst_group_update_ie(struct fst_group *g); -static inline Boolean fst_group_has_ifaces(struct fst_group *g) +static inline bool fst_group_has_ifaces(struct fst_group *g) { return !dl_list_empty(&g->ifaces); } @@ -44,7 +44,7 @@ static inline const char * fst_group_get_id(struct fst_group *g) return g->group_id; } -Boolean fst_group_delete_if_empty(struct fst_group *group); +bool fst_group_delete_if_empty(struct fst_group *group); struct fst_iface * fst_group_get_iface_by_name(struct fst_group *g, const char *ifname); struct fst_iface * diff --git a/src/fst/fst_iface.c b/src/fst/fst_iface.c index 35e83cb7b..90c5fc035 100644 --- a/src/fst/fst_iface.c +++ b/src/fst/fst_iface.c @@ -49,17 +49,17 @@ void fst_iface_delete(struct fst_iface *i) } -Boolean fst_iface_is_connected(struct fst_iface *iface, const u8 *addr, - Boolean mb_only) +bool fst_iface_is_connected(struct fst_iface *iface, const u8 *addr, + bool mb_only) { struct fst_get_peer_ctx *ctx; const u8 *a = fst_iface_get_peer_first(iface, &ctx, mb_only); for (; a != NULL; a = fst_iface_get_peer_next(iface, &ctx, mb_only)) if (os_memcmp(addr, a, ETH_ALEN) == 0) - return TRUE; + return true; - return FALSE; + return false; } diff --git a/src/fst/fst_iface.h b/src/fst/fst_iface.h index cbaa7d817..af7156cb2 100644 --- a/src/fst/fst_iface.h +++ b/src/fst/fst_iface.h @@ -111,20 +111,20 @@ static inline void fst_iface_update_mb_ie(struct fst_iface *i, static inline const u8 * fst_iface_get_peer_first(struct fst_iface *i, struct fst_get_peer_ctx **ctx, - Boolean mb_only) + bool mb_only) { return i->iface_obj.get_peer_first(i->iface_obj.ctx, ctx, mb_only); } static inline const u8 * fst_iface_get_peer_next(struct fst_iface *i, struct fst_get_peer_ctx **ctx, - Boolean mb_only) + bool mb_only) { return i->iface_obj.get_peer_next(i->iface_obj.ctx, ctx, mb_only); } -Boolean fst_iface_is_connected(struct fst_iface *iface, const u8 *addr, - Boolean mb_only); +bool fst_iface_is_connected(struct fst_iface *iface, const u8 *addr, + bool mb_only); void fst_iface_attach_mbie(struct fst_iface *i, struct wpabuf *mbie); enum mb_band_id fst_iface_get_band_id(struct fst_iface *i); diff --git a/src/fst/fst_session.c b/src/fst/fst_session.c index a02a93e76..e42a85c04 100644 --- a/src/fst/fst_session.c +++ b/src/fst/fst_session.c @@ -71,7 +71,7 @@ struct fst_session { * specific session object */ struct fst_group *group; enum fst_session_state state; - Boolean stt_armed; + bool stt_armed; }; static struct dl_list global_sessions_list; @@ -145,12 +145,12 @@ static u32 fst_find_free_session_id(void) struct fst_session *s; for (i = 0; i < (u32) -1; i++) { - Boolean in_use = FALSE; + bool in_use = false; foreach_fst_session(s) { if (s->id == global_session_id) { fst_session_global_inc_id(); - in_use = TRUE; + in_use = true; break; } } @@ -184,7 +184,7 @@ static void fst_session_stt_arm(struct fst_session *s) /* Action frames sometimes get delayed. Use relaxed timeout (2*) */ eloop_register_timeout(0, 2 * TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU), fst_session_timeout_handler, NULL, s); - s->stt_armed = TRUE; + s->stt_armed = true; } @@ -192,12 +192,12 @@ static void fst_session_stt_disarm(struct fst_session *s) { if (s->stt_armed) { eloop_cancel_timeout(fst_session_timeout_handler, NULL, s); - s->stt_armed = FALSE; + s->stt_armed = false; } } -static Boolean fst_session_is_in_transition(struct fst_session *s) +static bool fst_session_is_in_transition(struct fst_session *s) { /* See spec, 10.32.2.2 Transitioning between states */ return s->stt_armed; @@ -267,7 +267,7 @@ static void fst_session_reset_ex(struct fst_session *s, enum fst_reason reason) } -static int fst_session_send_action(struct fst_session *s, Boolean old_iface, +static int fst_session_send_action(struct fst_session *s, bool old_iface, const void *payload, size_t size, const struct wpabuf *extra_buf) { @@ -344,11 +344,11 @@ static int fst_session_send_tear_down(struct fst_session *s) td.action = FST_ACTION_TEAR_DOWN; td.fsts_id = host_to_le32(s->data.fsts_id); - res = fst_session_send_action(s, TRUE, &td, sizeof(td), NULL); + res = fst_session_send_action(s, true, &td, sizeof(td), NULL); if (!res) - fst_printf_sframe(s, TRUE, MSG_INFO, "FST TearDown sent"); + fst_printf_sframe(s, true, MSG_INFO, "FST TearDown sent"); else - fst_printf_sframe(s, TRUE, MSG_ERROR, + fst_printf_sframe(s, true, MSG_ERROR, "failed to send FST TearDown"); return res; @@ -481,10 +481,10 @@ static void fst_session_handle_setup_request(struct fst_iface *iface, return; } - fst_session_set_iface(s, iface, TRUE); - fst_session_set_peer_addr(s, mgmt->sa, TRUE); - fst_session_set_iface(s, new_iface, FALSE); - fst_session_set_peer_addr(s, new_iface_peer_addr, FALSE); + fst_session_set_iface(s, iface, true); + fst_session_set_peer_addr(s, mgmt->sa, true); + fst_session_set_iface(s, new_iface, false); + fst_session_set_peer_addr(s, new_iface_peer_addr, false); fst_session_set_llt(s, FST_LLT_VAL_TO_MS(le_to_host32(req->llt))); s->data.pending_setup_req_dlgt = req->dialog_token; s->data.fsts_id = le_to_host32(req->stie.fsts_id); @@ -687,8 +687,8 @@ static void fst_session_handle_ack_request(struct fst_session *s, res.dialog_token = req->dialog_token; res.fsts_id = req->fsts_id; - if (!fst_session_send_action(s, FALSE, &res, sizeof(res), NULL)) { - fst_printf_sframe(s, FALSE, MSG_INFO, "FST Ack Response sent"); + if (!fst_session_send_action(s, false, &res, sizeof(res), NULL)) { + fst_printf_sframe(s, false, MSG_INFO, "FST Ack Response sent"); fst_session_stt_disarm(s); fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_DONE, NULL); @@ -785,7 +785,7 @@ struct fst_session * fst_session_create(struct fst_group *g) void fst_session_set_iface(struct fst_session *s, struct fst_iface *iface, - Boolean is_old) + bool is_old) { if (is_old) s->data.old_iface = iface; @@ -802,7 +802,7 @@ void fst_session_set_llt(struct fst_session *s, u32 llt) void fst_session_set_peer_addr(struct fst_session *s, const u8 *addr, - Boolean is_old) + bool is_old) { u8 *a = is_old ? s->data.old_peer_addr : s->data.new_peer_addr; @@ -850,14 +850,14 @@ int fst_session_initiate_setup(struct fst_session *s) } if (!fst_iface_is_connected(s->data.old_iface, s->data.old_peer_addr, - FALSE)) { + false)) { fst_printf_session(s, MSG_ERROR, "The preset old peer address is not connected"); return -EINVAL; } if (!fst_iface_is_connected(s->data.new_iface, s->data.new_peer_addr, - FALSE)) { + false)) { fst_printf_session(s, MSG_ERROR, "The preset new peer address is not connected"); return -EINVAL; @@ -905,12 +905,12 @@ int fst_session_initiate_setup(struct fst_session *s) req.stie.old_band_op = 1; req.stie.old_band_setup = 0; - res = fst_session_send_action(s, TRUE, &req, sizeof(req), + res = fst_session_send_action(s, true, &req, sizeof(req), fst_iface_get_mbie(s->data.old_iface)); if (!res) { s->data.fsts_id = fsts_id; s->data.pending_setup_req_dlgt = dialog_token; - fst_printf_sframe(s, TRUE, MSG_INFO, "FST Setup Request sent"); + fst_printf_sframe(s, true, MSG_INFO, "FST Setup Request sent"); fst_session_set_state(s, FST_SESSION_STATE_SETUP_COMPLETION, NULL); @@ -955,7 +955,7 @@ int fst_session_respond(struct fst_session *s, u8 status_code) } if (!fst_iface_is_connected(s->data.old_iface, - s->data.old_peer_addr, FALSE)) { + s->data.old_peer_addr, false)) { fst_printf_session(s, MSG_ERROR, "The preset peer address is not in the peer list"); return -EINVAL; @@ -1000,15 +1000,15 @@ int fst_session_respond(struct fst_session *s, u8 status_code) status_code); } - if (fst_session_send_action(s, TRUE, &res, sizeof(res), + if (fst_session_send_action(s, true, &res, sizeof(res), fst_iface_get_mbie(s->data.old_iface))) { - fst_printf_sframe(s, TRUE, MSG_ERROR, + fst_printf_sframe(s, true, MSG_ERROR, "cannot send FST Setup Response with code %d", status_code); return -EINVAL; } - fst_printf_sframe(s, TRUE, MSG_INFO, "FST Setup Response sent"); + fst_printf_sframe(s, true, MSG_INFO, "FST Setup Response sent"); if (status_code != WLAN_STATUS_SUCCESS) { union fst_session_state_switch_extra evext = { @@ -1053,14 +1053,14 @@ int fst_session_initiate_switch(struct fst_session *s) req.dialog_token = dialog_token; req.fsts_id = host_to_le32(s->data.fsts_id); - res = fst_session_send_action(s, FALSE, &req, sizeof(req), NULL); + res = fst_session_send_action(s, false, &req, sizeof(req), NULL); if (!res) { - fst_printf_sframe(s, FALSE, MSG_INFO, "FST Ack Request sent"); + fst_printf_sframe(s, false, MSG_INFO, "FST Ack Request sent"); fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_DONE, NULL); fst_session_stt_arm(s); } else { - fst_printf_sframe(s, FALSE, MSG_ERROR, + fst_printf_sframe(s, false, MSG_ERROR, "Cannot send FST Ack Request"); } @@ -1091,7 +1091,7 @@ void fst_session_handle_action(struct fst_session *s, break; case FST_ACTION_ON_CHANNEL_TUNNEL: default: - fst_printf_sframe(s, FALSE, MSG_ERROR, + fst_printf_sframe(s, false, MSG_ERROR, "Unsupported FST Action frame"); break; } @@ -1137,7 +1137,7 @@ struct fst_group * fst_session_get_group(struct fst_session *s) } -struct fst_iface * fst_session_get_iface(struct fst_session *s, Boolean is_old) +struct fst_iface * fst_session_get_iface(struct fst_session *s, bool is_old) { return is_old ? s->data.old_iface : s->data.new_iface; } @@ -1149,7 +1149,7 @@ u32 fst_session_get_id(struct fst_session *s) } -const u8 * fst_session_get_peer_addr(struct fst_session *s, Boolean is_old) +const u8 * fst_session_get_peer_addr(struct fst_session *s, bool is_old) { return is_old ? s->data.old_peer_addr : s->data.new_peer_addr; } @@ -1232,7 +1232,7 @@ void fst_session_on_action_rx(struct fst_iface *iface, int fst_session_set_str_ifname(struct fst_session *s, const char *ifname, - Boolean is_old) + bool is_old) { struct fst_group *g = fst_session_get_group(s); struct fst_iface *i; @@ -1252,7 +1252,7 @@ int fst_session_set_str_ifname(struct fst_session *s, const char *ifname, int fst_session_set_str_peer_addr(struct fst_session *s, const char *mac, - Boolean is_old) + bool is_old) { u8 peer_addr[ETH_ALEN]; int res = fst_read_peer_addr(mac, peer_addr); @@ -1330,11 +1330,11 @@ static int get_group_fill_session(struct fst_group **g, struct fst_session *s) if (!s->data.old_iface) return -EINVAL; - old_addr = fst_iface_get_peer_first(s->data.old_iface, &ctx, TRUE); + old_addr = fst_iface_get_peer_first(s->data.old_iface, &ctx, true); if (!old_addr) return -EINVAL; - new_addr = fst_iface_get_peer_first(s->data.new_iface, &ctx, TRUE); + new_addr = fst_iface_get_peer_first(s->data.new_iface, &ctx, true); if (!new_addr) return -EINVAL; @@ -1350,7 +1350,7 @@ static int get_group_fill_session(struct fst_group **g, struct fst_session *s) int fst_test_req_send_fst_request(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_setup_req req; struct fst_session s; @@ -1394,7 +1394,7 @@ int fst_test_req_send_fst_request(const char *params) req.stie.new_band_id = req.stie.old_band_id; } - return fst_session_send_action(&s, TRUE, &req, sizeof(req), + return fst_session_send_action(&s, true, &req, sizeof(req), s.data.old_iface->mb_ie); } @@ -1402,7 +1402,7 @@ int fst_test_req_send_fst_request(const char *params) int fst_test_req_send_fst_response(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_setup_res res; struct fst_session s; @@ -1437,7 +1437,7 @@ int fst_test_req_send_fst_response(const char *params) * If some session has just received an FST Setup Request, then * use the correct dialog token copied from this request. */ - _s = fst_find_session_in_progress(fst_session_get_peer_addr(&s, TRUE), + _s = fst_find_session_in_progress(fst_session_get_peer_addr(&s, true), g); res.dialog_token = (_s && fst_session_is_ready_pending(_s)) ? _s->data.pending_setup_req_dlgt : g->dialog_token; @@ -1469,7 +1469,7 @@ int fst_test_req_send_fst_response(const char *params) res.stie.new_band_id = res.stie.old_band_id; } - return fst_session_send_action(&s, TRUE, &res, sizeof(res), + return fst_session_send_action(&s, true, &res, sizeof(res), s.data.old_iface->mb_ie); } @@ -1477,7 +1477,7 @@ int fst_test_req_send_fst_response(const char *params) int fst_test_req_send_ack_request(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_ack_req req; struct fst_session s; @@ -1498,14 +1498,14 @@ int fst_test_req_send_ack_request(const char *params) req.dialog_token = g->dialog_token; req.fsts_id = host_to_le32(fsts_id); - return fst_session_send_action(&s, FALSE, &req, sizeof(req), NULL); + return fst_session_send_action(&s, false, &req, sizeof(req), NULL); } int fst_test_req_send_ack_response(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_ack_res res; struct fst_session s; @@ -1526,14 +1526,14 @@ int fst_test_req_send_ack_response(const char *params) res.dialog_token = g->dialog_token; res.fsts_id = host_to_le32(fsts_id); - return fst_session_send_action(&s, FALSE, &res, sizeof(res), NULL); + return fst_session_send_action(&s, false, &res, sizeof(res), NULL); } int fst_test_req_send_tear_down(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_tear_down td; struct fst_session s; @@ -1553,14 +1553,14 @@ int fst_test_req_send_tear_down(const char *params) td.action = FST_ACTION_TEAR_DOWN; td.fsts_id = host_to_le32(fsts_id); - return fst_session_send_action(&s, TRUE, &td, sizeof(td), NULL); + return fst_session_send_action(&s, true, &td, sizeof(td), NULL); } u32 fst_test_req_get_fsts_id(const char *params) { int sid; - Boolean is_valid; + bool is_valid; char *endp; struct fst_session *s; diff --git a/src/fst/fst_session.h b/src/fst/fst_session.h index 1162de4b3..e43d0ea39 100644 --- a/src/fst/fst_session.h +++ b/src/fst/fst_session.h @@ -24,10 +24,10 @@ fst_session_global_get_first_by_group(struct fst_group *g); struct fst_session * fst_session_create(struct fst_group *g); void fst_session_set_iface(struct fst_session *s, struct fst_iface *iface, - Boolean is_old); + bool is_old); void fst_session_set_llt(struct fst_session *s, u32 llt); void fst_session_set_peer_addr(struct fst_session *s, const u8 *addr, - Boolean is_old); + bool is_old); int fst_session_initiate_setup(struct fst_session *s); int fst_session_respond(struct fst_session *s, u8 status_code); int fst_session_initiate_switch(struct fst_session *s); @@ -39,8 +39,8 @@ void fst_session_reset(struct fst_session *s); void fst_session_delete(struct fst_session *s); struct fst_group * fst_session_get_group(struct fst_session *s); -struct fst_iface * fst_session_get_iface(struct fst_session *s, Boolean is_old); -const u8 * fst_session_get_peer_addr(struct fst_session *s, Boolean is_old); +struct fst_iface * fst_session_get_iface(struct fst_session *s, bool is_old); +const u8 * fst_session_get_peer_addr(struct fst_session *s, bool is_old); u32 fst_session_get_id(struct fst_session *s); u32 fst_session_get_llt(struct fst_session *s); enum fst_session_state fst_session_get_state(struct fst_session *s); @@ -57,9 +57,9 @@ void fst_session_on_action_rx(struct fst_iface *iface, int fst_session_set_str_ifname(struct fst_session *s, const char *ifname, - Boolean is_old); + bool is_old); int fst_session_set_str_peer_addr(struct fst_session *s, const char *mac, - Boolean is_old); + bool is_old); int fst_session_set_str_llt(struct fst_session *s, const char *llt_str); #ifdef CONFIG_FST_TEST diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 50478c11e..5a503fe05 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -5475,7 +5475,7 @@ static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr, static const u8 * wpas_fst_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { struct wpa_supplicant *wpa_s = ctx; @@ -5489,7 +5489,7 @@ static const u8 * wpas_fst_get_peer_first(void *ctx, static const u8 * wpas_fst_get_peer_next(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { return NULL; } From da8478a1ab99028c6751c72cd5286fdf7da198fc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 00:51:11 +0300 Subject: [PATCH 0411/1105] EAPOL supp: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/eap_peer/eap.h | 5 +- src/eapol_supp/eapol_supp_sm.c | 200 ++++++++++++++++---------------- src/eapol_supp/eapol_supp_sm.h | 20 ++-- wpa_supplicant/ctrl_iface.c | 6 +- wpa_supplicant/eapol_test.c | 4 +- wpa_supplicant/events.c | 30 ++--- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wpa_supplicant.c | 18 +-- 8 files changed, 142 insertions(+), 143 deletions(-) diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h index acd70d05d..9aa74ef81 100644 --- a/src/eap_peer/eap.h +++ b/src/eap_peer/eap.h @@ -147,7 +147,7 @@ struct eapol_callbacks { * @variable: EAPOL boolean variable to get * Returns: Value of the EAPOL variable */ - Boolean (*get_bool)(void *ctx, enum eapol_bool_var variable); + bool (*get_bool)(void *ctx, enum eapol_bool_var variable); /** * set_bool - Set a boolean EAPOL state variable @@ -155,8 +155,7 @@ struct eapol_callbacks { * @variable: EAPOL boolean variable to set * @value: Value for the EAPOL variable */ - void (*set_bool)(void *ctx, enum eapol_bool_var variable, - Boolean value); + void (*set_bool)(void *ctx, enum eapol_bool_var variable, bool value); /** * get_int - Get an integer EAPOL state variable diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index 7f04b0107..861eea2ae 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -38,21 +38,21 @@ struct eapol_sm { int timer_tick_enabled; /* Global variables */ - Boolean eapFail; - Boolean eapolEap; - Boolean eapSuccess; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; + bool eapFail; + bool eapolEap; + bool eapSuccess; + bool initialize; + bool keyDone; + bool keyRun; PortControl portControl; - Boolean portEnabled; + bool portEnabled; PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */ - Boolean portValid; - Boolean suppAbort; - Boolean suppFail; - Boolean suppStart; - Boolean suppSuccess; - Boolean suppTimeout; + bool portValid; + bool suppAbort; + bool suppFail; + bool suppStart; + bool suppSuccess; + bool suppTimeout; /* Supplicant PAE state machine */ enum { @@ -69,10 +69,10 @@ struct eapol_sm { SUPP_PAE_S_FORCE_UNAUTH = 10 } SUPP_PAE_state; /* dot1xSuppPaeState */ /* Variables */ - Boolean userLogoff; - Boolean logoffSent; + bool userLogoff; + bool logoffSent; unsigned int startCount; - Boolean eapRestart; + bool eapRestart; PortControl sPortMode; /* Constants */ unsigned int heldPeriod; /* dot1xSuppHeldPeriod */ @@ -85,7 +85,7 @@ struct eapol_sm { KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE } KEY_RX_state; /* Variables */ - Boolean rxKey; + bool rxKey; /* Supplicant Backend state machine */ enum { @@ -100,9 +100,9 @@ struct eapol_sm { SUPP_BE_SUCCESS = 8 } SUPP_BE_state; /* dot1xSuppBackendPaeState */ /* Variables */ - Boolean eapNoResp; - Boolean eapReq; - Boolean eapResp; + bool eapNoResp; + bool eapReq; + bool eapResp; /* Constants */ unsigned int authPeriod; /* dot1xSuppAuthPeriod */ @@ -120,30 +120,30 @@ struct eapol_sm { unsigned char dot1xSuppLastEapolFrameSource[6]; /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */ - Boolean changed; + bool changed; struct eap_sm *eap; struct eap_peer_config *config; - Boolean initial_req; + bool initial_req; u8 *last_rx_key; size_t last_rx_key_len; struct wpabuf *eapReqData; /* for EAP */ - Boolean altAccept; /* for EAP */ - Boolean altReject; /* for EAP */ - Boolean eapTriggerStart; - Boolean replay_counter_valid; + bool altAccept; /* for EAP */ + bool altReject; /* for EAP */ + bool eapTriggerStart; + bool replay_counter_valid; u8 last_replay_counter[16]; struct eapol_config conf; struct eapol_ctx *ctx; enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE } cb_status; - Boolean cached_pmk; + bool cached_pmk; - Boolean unicast_key_received, broadcast_key_received; + bool unicast_key_received, broadcast_key_received; - Boolean force_authorized_update; + bool force_authorized_update; #ifdef CONFIG_EAP_PROXY - Boolean use_eap_proxy; + bool use_eap_proxy; struct eap_proxy_sm *eap_proxy; #endif /* CONFIG_EAP_PROXY */ }; @@ -224,7 +224,7 @@ SM_STATE(SUPP_PAE, LOGOFF) { SM_ENTRY(SUPP_PAE, LOGOFF); eapol_sm_txLogoff(sm); - sm->logoffSent = TRUE; + sm->logoffSent = true; eapol_sm_set_port_unauthorized(sm); } @@ -234,13 +234,13 @@ SM_STATE(SUPP_PAE, DISCONNECTED) SM_ENTRY(SUPP_PAE, DISCONNECTED); sm->sPortMode = Auto; sm->startCount = 0; - sm->eapTriggerStart = FALSE; - sm->logoffSent = FALSE; + sm->eapTriggerStart = false; + sm->logoffSent = false; eapol_sm_set_port_unauthorized(sm); - sm->suppAbort = TRUE; + sm->suppAbort = true; - sm->unicast_key_received = FALSE; - sm->broadcast_key_received = FALSE; + sm->unicast_key_received = false; + sm->broadcast_key_received = false; /* * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so @@ -263,7 +263,7 @@ SM_STATE(SUPP_PAE, CONNECTING) send_start = 1; if (sm->ctx->preauth) send_start = 1; - sm->eapTriggerStart = FALSE; + sm->eapTriggerStart = false; if (send_start) { sm->startWhen = sm->startPeriod; @@ -286,7 +286,7 @@ SM_STATE(SUPP_PAE, CONNECTING) } } eapol_enable_timer_tick(sm); - sm->eapolEap = FALSE; + sm->eapolEap = false; if (send_start) eapol_sm_txStart(sm); } @@ -296,12 +296,12 @@ SM_STATE(SUPP_PAE, AUTHENTICATING) { SM_ENTRY(SUPP_PAE, AUTHENTICATING); sm->startCount = 0; - sm->suppSuccess = FALSE; - sm->suppFail = FALSE; - sm->suppTimeout = FALSE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; - sm->suppStart = TRUE; + sm->suppSuccess = false; + sm->suppFail = false; + sm->suppTimeout = false; + sm->keyRun = false; + sm->keyDone = false; + sm->suppStart = true; } @@ -331,16 +331,16 @@ SM_STATE(SUPP_PAE, RESTART) } SM_ENTRY(SUPP_PAE, RESTART); - sm->eapRestart = TRUE; + sm->eapRestart = true; if (sm->altAccept) { /* * Prevent EAP peer state machine from failing due to prior - * external EAP success notification (altSuccess=TRUE in the + * external EAP success notification (altSuccess=true in the * IDLE state could result in a transition to the FAILURE state. */ wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE"); - sm->eapSuccess = FALSE; - sm->altAccept = FALSE; + sm->eapSuccess = false; + sm->altAccept = false; } } @@ -412,7 +412,7 @@ SM_STEP(SUPP_PAE) wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for " "plaintext connection; no EAPOL-Key frames " "required"); - sm->portValid = TRUE; + sm->portValid = true; if (sm->ctx->eapol_done_cb) sm->ctx->eapol_done_cb(sm->ctx->ctx); } @@ -459,7 +459,7 @@ SM_STATE(KEY_RX, KEY_RECEIVE) { SM_ENTRY(KEY_RX, KEY_RECEIVE); eapol_sm_processKey(sm); - sm->rxKey = FALSE; + sm->rxKey = false; } @@ -486,7 +486,7 @@ SM_STATE(SUPP_BE, REQUEST) { SM_ENTRY(SUPP_BE, REQUEST); sm->authWhile = 0; - sm->eapReq = TRUE; + sm->eapReq = true; eapol_sm_getSuppRsp(sm); } @@ -495,15 +495,15 @@ SM_STATE(SUPP_BE, RESPONSE) { SM_ENTRY(SUPP_BE, RESPONSE); eapol_sm_txSuppRsp(sm); - sm->eapResp = FALSE; + sm->eapResp = false; } SM_STATE(SUPP_BE, SUCCESS) { SM_ENTRY(SUPP_BE, SUCCESS); - sm->keyRun = TRUE; - sm->suppSuccess = TRUE; + sm->keyRun = true; + sm->suppSuccess = true; #ifdef CONFIG_EAP_PROXY if (sm->use_eap_proxy) { @@ -513,7 +513,7 @@ SM_STATE(SUPP_BE, SUCCESS) /* New key received - clear IEEE 802.1X EAPOL-Key replay * counter */ - sm->replay_counter_valid = FALSE; + sm->replay_counter_valid = false; session_id = eap_proxy_get_eap_session_id( sm->eap_proxy, &session_id_len); @@ -534,7 +534,7 @@ SM_STATE(SUPP_BE, SUCCESS) if (eap_key_available(sm->eap)) { /* New key received - clear IEEE 802.1X EAPOL-Key replay * counter */ - sm->replay_counter_valid = FALSE; + sm->replay_counter_valid = false; } } @@ -542,22 +542,22 @@ SM_STATE(SUPP_BE, SUCCESS) SM_STATE(SUPP_BE, FAIL) { SM_ENTRY(SUPP_BE, FAIL); - sm->suppFail = TRUE; + sm->suppFail = true; } SM_STATE(SUPP_BE, TIMEOUT) { SM_ENTRY(SUPP_BE, TIMEOUT); - sm->suppTimeout = TRUE; + sm->suppTimeout = true; } SM_STATE(SUPP_BE, IDLE) { SM_ENTRY(SUPP_BE, IDLE); - sm->suppStart = FALSE; - sm->initial_req = TRUE; + sm->suppStart = false; + sm->initial_req = true; } @@ -565,7 +565,7 @@ SM_STATE(SUPP_BE, INITIALIZE) { SM_ENTRY(SUPP_BE, INITIALIZE); eapol_sm_abortSupp(sm); - sm->suppAbort = FALSE; + sm->suppAbort = false; /* * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so @@ -583,9 +583,9 @@ SM_STATE(SUPP_BE, RECEIVE) SM_ENTRY(SUPP_BE, RECEIVE); sm->authWhile = sm->authPeriod; eapol_enable_timer_tick(sm); - sm->eapolEap = FALSE; - sm->eapNoResp = FALSE; - sm->initial_req = FALSE; + sm->eapolEap = false; + sm->eapNoResp = false; + sm->initial_req = false; } @@ -831,7 +831,7 @@ static void eapol_sm_processKey(struct eapol_sm *sm) return; } - sm->replay_counter_valid = TRUE; + sm->replay_counter_valid = true; os_memcpy(sm->last_replay_counter, key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); @@ -850,9 +850,9 @@ static void eapol_sm_processKey(struct eapol_sm *sm) " driver."); } else { if (key->key_index & IEEE8021X_KEY_INDEX_FLAG) - sm->unicast_key_received = TRUE; + sm->unicast_key_received = true; else - sm->broadcast_key_received = TRUE; + sm->broadcast_key_received = true; if ((sm->unicast_key_received || !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) && @@ -861,7 +861,7 @@ static void eapol_sm_processKey(struct eapol_sm *sm) { wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key " "frames received"); - sm->portValid = TRUE; + sm->portValid = true; if (sm->ctx->eapol_done_cb) sm->ctx->eapol_done_cb(sm->ctx->ctx); } @@ -949,7 +949,7 @@ static void eapol_sm_set_port_authorized(struct eapol_sm *sm) int cb; cb = sm->suppPortStatus != Authorized || sm->force_authorized_update; - sm->force_authorized_update = FALSE; + sm->force_authorized_update = false; sm->suppPortStatus = Authorized; if (cb && sm->ctx->port_cb) sm->ctx->port_cb(sm->ctx->ctx, 1); @@ -961,7 +961,7 @@ static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm) int cb; cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update; - sm->force_authorized_update = FALSE; + sm->force_authorized_update = false; sm->suppPortStatus = Unauthorized; if (cb && sm->ctx->port_cb) sm->ctx->port_cb(sm->ctx->ctx, 0); @@ -985,7 +985,7 @@ void eapol_sm_step(struct eapol_sm *sm) * allow events (e.g., SIGTERM) to stop the program cleanly if the * state machine were to generate a busy loop. */ for (i = 0; i < 100; i++) { - sm->changed = FALSE; + sm->changed = false; SM_STEP_RUN(SUPP_PAE); SM_STEP_RUN(KEY_RX); SM_STEP_RUN(SUPP_BE); @@ -993,11 +993,11 @@ void eapol_sm_step(struct eapol_sm *sm) if (sm->use_eap_proxy) { /* Drive the EAP proxy state machine */ if (eap_proxy_sm_step(sm->eap_proxy, sm->eap)) - sm->changed = TRUE; + sm->changed = true; } else #endif /* CONFIG_EAP_PROXY */ if (eap_peer_sm_step(sm->eap)) - sm->changed = TRUE; + sm->changed = true; if (!sm->changed) break; } @@ -1370,7 +1370,7 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, if (sm->eapReqData) { wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " "frame"); - sm->eapolEap = TRUE; + sm->eapolEap = true; #ifdef CONFIG_EAP_PROXY if (sm->use_eap_proxy) { eap_proxy_packet_update( @@ -1411,7 +1411,7 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, "frame"); os_memcpy(sm->last_rx_key, buf, data_len); sm->last_rx_key_len = data_len; - sm->rxKey = TRUE; + sm->rxKey = true; eapol_sm_step(sm); } break; @@ -1454,14 +1454,14 @@ void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) * * Notify EAPOL state machine about new portEnabled value. */ -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) +void eapol_sm_notify_portEnabled(struct eapol_sm *sm, bool enabled) { if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAPOL: External notification - " "portEnabled=%d", enabled); if (sm->portEnabled != enabled) - sm->force_authorized_update = TRUE; + sm->force_authorized_update = true; sm->portEnabled = enabled; eapol_sm_step(sm); } @@ -1474,7 +1474,7 @@ void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) * * Notify EAPOL state machine about new portValid value. */ -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) +void eapol_sm_notify_portValid(struct eapol_sm *sm, bool valid) { if (sm == NULL) return; @@ -1488,15 +1488,15 @@ void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) /** * eapol_sm_notify_eap_success - Notification of external EAP success trigger * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @success: %TRUE = set success, %FALSE = clear success + * @success: %true = set success, %false = clear success * * Notify the EAPOL state machine that external event has forced EAP state to - * success (success = %TRUE). This can be cleared by setting success = %FALSE. + * success (success = %true). This can be cleared by setting success = %false. * * This function is called to update EAP state when WPA-PSK key handshake has * been completed successfully since WPA-PSK does not use EAP state machine. */ -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) +void eapol_sm_notify_eap_success(struct eapol_sm *sm, bool success) { if (sm == NULL) return; @@ -1513,12 +1513,12 @@ void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) /** * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @fail: %TRUE = set failure, %FALSE = clear failure + * @fail: %true = set failure, %false = clear failure * * Notify EAPOL state machine that external event has forced EAP state to - * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE. + * failure (fail = %true). This can be cleared by setting fail = %false. */ -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) +void eapol_sm_notify_eap_fail(struct eapol_sm *sm, bool fail) { if (sm == NULL) return; @@ -1659,7 +1659,7 @@ const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len) * * Notify EAPOL state machines that user requested logon/logoff. */ -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) +void eapol_sm_notify_logoff(struct eapol_sm *sm, bool logoff) { if (sm) { sm->userLogoff = logoff; @@ -1684,7 +1684,7 @@ void eapol_sm_notify_cached(struct eapol_sm *sm) if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL"); - sm->eapSuccess = TRUE; + sm->eapSuccess = true; eap_notify_success(sm->eap); eapol_sm_step(sm); } @@ -1701,7 +1701,7 @@ void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm) if (sm == NULL) return; wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA"); - sm->cached_pmk = TRUE; + sm->cached_pmk = true; } @@ -1711,7 +1711,7 @@ static void eapol_sm_abort_cached(struct eapol_sm *sm) "doing full EAP authentication"); if (sm == NULL) return; - sm->cached_pmk = FALSE; + sm->cached_pmk = false; sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; eapol_sm_set_port_unauthorized(sm); @@ -1790,8 +1790,8 @@ void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) wpa_printf(MSG_DEBUG, "EAPOL: received control response (user " "input) notification - retrying pending EAP " "Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; + sm->eapolEap = true; + sm->eapReq = true; eapol_sm_step(sm); } } @@ -1860,11 +1860,11 @@ static struct wpabuf * eapol_sm_get_eapReqData(void *ctx) } -static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) +static bool eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) { struct eapol_sm *sm = ctx; if (sm == NULL) - return FALSE; + return false; switch (variable) { case EAPOL_eapSuccess: return sm->eapSuccess; @@ -1887,12 +1887,12 @@ static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) case EAPOL_eapTriggerStart: return sm->eapTriggerStart; } - return FALSE; + return false; } static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) + bool value) { struct eapol_sm *sm = ctx; if (sm == NULL) @@ -1994,8 +1994,8 @@ static void eapol_sm_notify_pending(void *ctx) if (sm->eapReqData && !sm->eapReq) { wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP " "state machine - retrying pending EAP Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; + sm->eapolEap = true; + sm->eapReq = true; eapol_sm_step(sm); } } @@ -2141,7 +2141,7 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) } #ifdef CONFIG_EAP_PROXY - sm->use_eap_proxy = FALSE; + sm->use_eap_proxy = false; sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx); if (sm->eap_proxy == NULL) { wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy"); @@ -2149,10 +2149,10 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) #endif /* CONFIG_EAP_PROXY */ /* Initialize EAPOL state machines */ - sm->force_authorized_update = TRUE; - sm->initialize = TRUE; + sm->force_authorized_update = true; + sm->initialize = true; eapol_sm_step(sm); - sm->initialize = FALSE; + sm->initialize = false; eapol_sm_step(sm); if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0) diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h index 67f82c60a..753b947ad 100644 --- a/src/eapol_supp/eapol_supp_sm.h +++ b/src/eapol_supp/eapol_supp_sm.h @@ -325,16 +325,16 @@ void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, size_t len); void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm); -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled); -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid); -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success); -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail); +void eapol_sm_notify_portEnabled(struct eapol_sm *sm, bool enabled); +void eapol_sm_notify_portValid(struct eapol_sm *sm, bool valid); +void eapol_sm_notify_eap_success(struct eapol_sm *sm, bool success); +void eapol_sm_notify_eap_fail(struct eapol_sm *sm, bool fail); void eapol_sm_notify_config(struct eapol_sm *sm, struct eap_peer_config *config, const struct eapol_config *conf); int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len); const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len); -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff); +void eapol_sm_notify_logoff(struct eapol_sm *sm, bool logoff); void eapol_sm_notify_cached(struct eapol_sm *sm); void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm); void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx); @@ -397,18 +397,18 @@ static inline void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) { } static inline void eapol_sm_notify_portEnabled(struct eapol_sm *sm, - Boolean enabled) + bool enabled) { } static inline void eapol_sm_notify_portValid(struct eapol_sm *sm, - Boolean valid) + bool valid) { } static inline void eapol_sm_notify_eap_success(struct eapol_sm *sm, - Boolean success) + bool success) { } -static inline void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) +static inline void eapol_sm_notify_eap_fail(struct eapol_sm *sm, bool fail) { } static inline void eapol_sm_notify_config(struct eapol_sm *sm, @@ -425,7 +425,7 @@ eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len) { return NULL; } -static inline void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) +static inline void eapol_sm_notify_logoff(struct eapol_sm *sm, bool logoff) { } static inline void eapol_sm_notify_cached(struct eapol_sm *sm) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 541de758e..e0547f16f 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8203,7 +8203,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200); wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70); wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60); - eapol_sm_notify_logoff(wpa_s->eapol, FALSE); + eapol_sm_notify_logoff(wpa_s->eapol, false); radio_remove_works(wpa_s, NULL, 1); wpa_s->ext_work_in_progress = 0; @@ -10217,9 +10217,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, reply, reply_size); } else if (os_strcmp(buf, "LOGON") == 0) { - eapol_sm_notify_logoff(wpa_s->eapol, FALSE); + eapol_sm_notify_logoff(wpa_s->eapol, false); } else if (os_strcmp(buf, "LOGOFF") == 0) { - eapol_sm_notify_logoff(wpa_s->eapol, TRUE); + eapol_sm_notify_logoff(wpa_s->eapol, true); } else if (os_strcmp(buf, "REASSOCIATE") == 0) { if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) reply_len = -1; diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c index 2fa496813..9f69736b7 100644 --- a/wpa_supplicant/eapol_test.c +++ b/wpa_supplicant/eapol_test.c @@ -644,9 +644,9 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s, eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portValid(wpa_s->eapol, false); /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); + eapol_sm_notify_portEnabled(wpa_s->eapol, true); return 0; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 19a883bee..61f875742 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -322,12 +322,12 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) if (bssid_changed) wpas_notify_bssid_changed(wpa_s); - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portEnabled(wpa_s->eapol, false); + eapol_sm_notify_portValid(wpa_s->eapol, false); if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || wpa_s->drv_authorized_port) - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, false); wpa_s->drv_authorized_port = 0; wpa_s->ap_ies_from_associnfo = 0; wpa_s->current_ssid = NULL; @@ -3033,7 +3033,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, already_authorized = data && data->assoc_info.authorized; /* - * Set portEnabled first to FALSE in order to get EAP state machine out + * Set portEnabled first to false in order to get EAP state machine out * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE * state machine may transit to AUTHENTICATING state based on obsolete * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to @@ -3041,16 +3041,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, * reset the state. */ if (!ft_completed && !already_authorized) { - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portEnabled(wpa_s->eapol, false); + eapol_sm_notify_portValid(wpa_s->eapol, false); } if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || ft_completed || already_authorized || wpa_s->drv_authorized_port) - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, false); /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); + eapol_sm_notify_portEnabled(wpa_s->eapol, true); wpa_s->eapol_received = 0; if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE || @@ -3082,8 +3082,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, */ wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); + eapol_sm_notify_eap_success(wpa_s->eapol, true); } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) && wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* @@ -3092,8 +3092,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, */ wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); + eapol_sm_notify_eap_success(wpa_s->eapol, true); } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) && wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { /* @@ -3101,7 +3101,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, * to allow EAPOL supplicant to complete its work without * waiting for WPA supplicant. */ - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); } wpa_s->last_eapol_matches_bssid = 0; @@ -4182,8 +4182,8 @@ static void wpa_supplicant_event_port_authorized(struct wpa_supplicant *wpa_s) if (wpa_s->wpa_state == WPA_ASSOCIATED) { wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); + eapol_sm_notify_eap_success(wpa_s->eapol, true); wpa_s->drv_authorized_port = 1; } } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 0cc81bf0c..4eaece05d 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -828,7 +828,7 @@ no_fils: " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portValid(wpa_s->eapol, false); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); if (old_ssid != wpa_s->current_ssid) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 5a503fe05..218f7e39a 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -319,14 +319,14 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) * per-BSSID EAPOL authentication. */ eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, true); + eapol_sm_notify_eap_fail(wpa_s->eapol, false); return; } #endif /* CONFIG_IBSS_RSN */ - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); - eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, false); + eapol_sm_notify_eap_fail(wpa_s->eapol, false); if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) @@ -1160,7 +1160,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) * Clear forced success to clear EAP state for next * authentication. */ - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, false); } eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); wpa_sm_set_config(wpa_s->wpa, NULL); @@ -4751,12 +4751,12 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { /* - * Set portValid = TRUE here since we are going to skip 4-way + * Set portValid = true here since we are going to skip 4-way * handshake processing which would normally set portValid. We * need this to allow the EAPOL state machines to be completed * without going through EAPOL-Key handshake. */ - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); } } @@ -6185,8 +6185,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, } /* RSNA Supplicant Key Management - INITIALIZE */ - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portEnabled(wpa_s->eapol, false); + eapol_sm_notify_portValid(wpa_s->eapol, false); /* Initialize driver interface and register driver event handler before * L2 receive handler so that association events are processed before From c9d70dd3298dc41cb2390f93c84cb8692c996783 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:04:24 +0300 Subject: [PATCH 0412/1105] RSN supp: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/rsn_supp/preauth.c | 4 ++-- src/rsn_supp/wpa.c | 20 +++++++++----------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index a10192172..d4d1307a9 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -252,9 +252,9 @@ int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6); os_memcpy(sm->preauth_bssid, dst, ETH_ALEN); - eapol_sm_notify_portValid(sm->preauth_eapol, TRUE); + eapol_sm_notify_portValid(sm->preauth_eapol, true); /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE); + eapol_sm_notify_portEnabled(sm->preauth_eapol, true); eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0, rsn_preauth_timeout, sm, NULL); diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 60084c6ab..6077aa60a 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -818,11 +818,11 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, wpa_sm_mlme_setprotection( sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - eapol_sm_notify_portValid(sm->eapol, TRUE); + eapol_sm_notify_portValid(sm->eapol, true); if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || sm->key_mgmt == WPA_KEY_MGMT_DPP || sm->key_mgmt == WPA_KEY_MGMT_OWE) - eapol_sm_notify_eap_success(sm->eapol, TRUE); + eapol_sm_notify_eap_success(sm->eapol, true); /* * Start preauthentication after a short wait to avoid a * possible race condition between the data receive and key @@ -1723,7 +1723,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, wpa_sm_mlme_setprotection( sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - eapol_sm_notify_portValid(sm->eapol, TRUE); + eapol_sm_notify_portValid(sm->eapol, true); } wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); @@ -2696,7 +2696,8 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm) int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) { char pmkid_txt[PMKID_LEN * 2 + 1]; - int rsna, ret; + bool rsna; + int ret; size_t len; if (sm->cur_pmksa) { @@ -2705,12 +2706,9 @@ int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) } else pmkid_txt[0] = '\0'; - if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) || - wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && - sm->proto == WPA_PROTO_RSN) - rsna = 1; - else - rsna = 0; + rsna = (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || + wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && + sm->proto == WPA_PROTO_RSN; ret = os_snprintf(buf, buflen, "dot11RSNAOptionImplemented=TRUE\n" @@ -2913,7 +2911,7 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) * Clear portValid to kick EAPOL state machine to re-enter * AUTHENTICATED state to get the EAPOL port Authorized. */ - eapol_sm_notify_portValid(sm->eapol, FALSE); + eapol_sm_notify_portValid(sm->eapol, false); wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); /* Prepare for the next transition */ From d15e109e29874bb19d854d9057f50cd5f066f1cd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:14:34 +0300 Subject: [PATCH 0413/1105] EAP peer: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/eap_peer/eap.c | 108 ++++++++++++++++----------------- src/eap_peer/eap.h | 8 +-- src/eap_peer/eap_aka.c | 14 ++--- src/eap_peer/eap_eke.c | 16 ++--- src/eap_peer/eap_fast.c | 4 +- src/eap_peer/eap_gpsk.c | 14 ++--- src/eap_peer/eap_gtc.c | 8 +-- src/eap_peer/eap_i.h | 34 +++++------ src/eap_peer/eap_ikev2.c | 28 ++++----- src/eap_peer/eap_leap.c | 44 +++++++------- src/eap_peer/eap_md5.c | 12 ++-- src/eap_peer/eap_mschapv2.c | 32 +++++----- src/eap_peer/eap_otp.c | 8 +-- src/eap_peer/eap_pax.c | 50 +++++++-------- src/eap_peer/eap_peap.c | 16 ++--- src/eap_peer/eap_psk.c | 22 +++---- src/eap_peer/eap_pwd.c | 22 +++---- src/eap_peer/eap_sake.c | 26 ++++---- src/eap_peer/eap_sim.c | 14 ++--- src/eap_peer/eap_teap.c | 4 +- src/eap_peer/eap_tls.c | 8 +-- src/eap_peer/eap_tls_common.c | 18 +++--- src/eap_peer/eap_tnc.c | 32 +++++----- src/eap_peer/eap_ttls.c | 6 +- src/eap_peer/eap_vendor_test.c | 16 ++--- src/eap_peer/eap_wsc.c | 24 ++++---- 26 files changed, 294 insertions(+), 294 deletions(-) diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index c78b21482..74c2ad361 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -37,8 +37,8 @@ #define EAP_CLIENT_TIMEOUT_DEFAULT 60 -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - enum eap_type method); +static bool eap_sm_allowMethod(struct eap_sm *sm, int vendor, + enum eap_type method); static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id); static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req); @@ -54,14 +54,14 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, -static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var) +static bool eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var) { return sm->eapol_cb->get_bool(sm->eapol_ctx, var); } static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var, - Boolean value) + bool value) { sm->eapol_cb->set_bool(sm->eapol_ctx, var, value); } @@ -210,8 +210,8 @@ static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi, /* * This state initializes state machine variables when the machine is - * activated (portEnabled = TRUE). This is also used when re-starting - * authentication (eapRestart == TRUE). + * activated (portEnabled = true). This is also used when re-starting + * authentication (eapRestart == true). */ SM_STATE(EAP, INITIALIZE) { @@ -229,17 +229,17 @@ SM_STATE(EAP, INITIALIZE) } sm->selectedMethod = EAP_TYPE_NONE; sm->methodState = METHOD_NONE; - sm->allowNotifications = TRUE; + sm->allowNotifications = true; sm->decision = DECISION_FAIL; sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT; eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); - eapol_set_bool(sm, EAPOL_eapFail, FALSE); + eapol_set_bool(sm, EAPOL_eapSuccess, false); + eapol_set_bool(sm, EAPOL_eapFail, false); eap_sm_free_key(sm); os_free(sm->eapSessionId); sm->eapSessionId = NULL; - sm->eapKeyAvailable = FALSE; - eapol_set_bool(sm, EAPOL_eapRestart, FALSE); + sm->eapKeyAvailable = false; + eapol_set_bool(sm, EAPOL_eapRestart, false); sm->lastId = -1; /* new session - make sure this does not match with * the first EAP-Packet */ /* @@ -247,16 +247,16 @@ SM_STATE(EAP, INITIALIZE) * seemed to be able to trigger cases where both were set and if EAPOL * state machine uses eapNoResp first, it may end up not sending a real * reply correctly. This occurred when the workaround in FAIL state set - * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do + * eapNoResp = true.. Maybe that workaround needs to be fixed to do * something else(?) */ - eapol_set_bool(sm, EAPOL_eapResp, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, FALSE); + eapol_set_bool(sm, EAPOL_eapResp, false); + eapol_set_bool(sm, EAPOL_eapNoResp, false); /* * RFC 4137 does not reset ignore here, but since it is possible for - * some method code paths to end up not setting ignore=FALSE, clear the + * some method code paths to end up not setting ignore=false, clear the * value here to avoid issues if a previous authentication attempt - * failed with ignore=TRUE being left behind in the last + * failed with ignore=true being left behind in the last * m.check(eapReqData) operation. */ sm->ignore = 0; @@ -264,7 +264,7 @@ SM_STATE(EAP, INITIALIZE) sm->num_rounds_short = 0; sm->prev_failure = 0; sm->expected_failure = 0; - sm->reauthInit = FALSE; + sm->reauthInit = false; sm->erp_seq = (u32) -1; sm->use_machine_cred = 0; } @@ -272,7 +272,7 @@ SM_STATE(EAP, INITIALIZE) /* * This state is reached whenever service from the lower layer is interrupted - * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE + * or unavailable (portEnabled == false). Immediate transition to INITIALIZE * occurs when the port becomes enabled. */ SM_STATE(EAP, DISABLED) @@ -301,7 +301,7 @@ SM_STATE(EAP, IDLE) /* - * This state is entered when an EAP packet is received (eapReq == TRUE) to + * This state is entered when an EAP packet is received (eapReq == true) to * parse the packet header. */ SM_STATE(EAP, RECEIVED) @@ -866,7 +866,7 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm, u8 eap_id) wpa_printf(MSG_DEBUG, "EAP: Sending EAP-Initiate/Re-auth"); wpabuf_free(sm->eapRespData); sm->eapRespData = msg; - sm->reauthInit = TRUE; + sm->reauthInit = true; return 0; } #endif /* CONFIG_ERP */ @@ -964,14 +964,14 @@ SM_STATE(EAP, SEND_RESPONSE) os_memcpy(sm->last_sha1, sm->req_sha1, 20); sm->lastId = sm->reqId; sm->lastRespData = wpabuf_dup(sm->eapRespData); - eapol_set_bool(sm, EAPOL_eapResp, TRUE); + eapol_set_bool(sm, EAPOL_eapResp, true); } else { wpa_printf(MSG_DEBUG, "EAP: No eapRespData available"); sm->lastRespData = NULL; } - eapol_set_bool(sm, EAPOL_eapReq, FALSE); + eapol_set_bool(sm, EAPOL_eapReq, false); eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); - sm->reauthInit = FALSE; + sm->reauthInit = false; } @@ -982,8 +982,8 @@ SM_STATE(EAP, SEND_RESPONSE) SM_STATE(EAP, DISCARD) { SM_ENTRY(EAP, DISCARD); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + eapol_set_bool(sm, EAPOL_eapReq, false); + eapol_set_bool(sm, EAPOL_eapNoResp, true); } @@ -1048,15 +1048,15 @@ SM_STATE(EAP, SUCCESS) SM_ENTRY(EAP, SUCCESS); if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); + sm->eapKeyAvailable = true; + eapol_set_bool(sm, EAPOL_eapSuccess, true); /* * RFC 4137 does not clear eapReq here, but this seems to be required * to avoid processing the same request twice when state machine is * initialized. */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); + eapol_set_bool(sm, EAPOL_eapReq, false); /* * RFC 4137 does not set eapNoResp here, but this seems to be required @@ -1064,7 +1064,7 @@ SM_STATE(EAP, SUCCESS) * addition, either eapResp or eapNoResp is required to be set after * processing the received EAP frame. */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + eapol_set_bool(sm, EAPOL_eapNoResp, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS "EAP authentication completed successfully"); @@ -1083,21 +1083,21 @@ SM_STATE(EAP, SUCCESS) SM_STATE(EAP, FAILURE) { SM_ENTRY(EAP, FAILURE); - eapol_set_bool(sm, EAPOL_eapFail, TRUE); + eapol_set_bool(sm, EAPOL_eapFail, true); /* * RFC 4137 does not clear eapReq here, but this seems to be required * to avoid processing the same request twice when state machine is * initialized. */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); + eapol_set_bool(sm, EAPOL_eapReq, false); /* * RFC 4137 does not set eapNoResp here. However, either eapResp or * eapNoResp is required to be set after processing the received EAP * frame. */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + eapol_set_bool(sm, EAPOL_eapNoResp, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE "EAP authentication failed"); @@ -1367,19 +1367,19 @@ SM_STEP(EAP) } -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - enum eap_type method) +static bool eap_sm_allowMethod(struct eap_sm *sm, int vendor, + enum eap_type method) { if (!eap_allowed_method(sm, vendor, method)) { wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: " "vendor %u method %u", vendor, method); - return FALSE; + return false; } if (eap_peer_get_eap_method(vendor, method)) - return TRUE; + return true; wpa_printf(MSG_DEBUG, "EAP: not included in build: " "vendor %u method %u", vendor, method); - return FALSE; + return false; } @@ -1802,7 +1802,7 @@ invalid: #endif /* CONFIG_ERP */ wpa_printf(MSG_DEBUG, "EAP: EAP-Initiate/Re-auth-Start - No suitable ERP keys available - try to start full EAP authentication"); - eapol_set_bool(sm, EAPOL_eapTriggerStart, TRUE); + eapol_set_bool(sm, EAPOL_eapTriggerStart, true); } @@ -1926,9 +1926,9 @@ no_auth_tag: if (flags & 0x80 || !auth_tag_ok) { wpa_printf(MSG_DEBUG, "EAP: EAP-Finish/Re-auth indicated failure"); - eapol_set_bool(sm, EAPOL_eapFail, TRUE); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + eapol_set_bool(sm, EAPOL_eapFail, true); + eapol_set_bool(sm, EAPOL_eapReq, false); + eapol_set_bool(sm, EAPOL_eapNoResp, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE "EAP authentication failed"); sm->prev_failure = 1; @@ -1957,10 +1957,10 @@ no_auth_tag: } wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK", sm->eapKeyData, sm->eapKeyDataLen); - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + sm->eapKeyAvailable = true; + eapol_set_bool(sm, EAPOL_eapSuccess, true); + eapol_set_bool(sm, EAPOL_eapReq, false); + eapol_set_bool(sm, EAPOL_eapNoResp, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS "EAP re-authentication completed successfully"); #endif /* CONFIG_ERP */ @@ -1973,7 +1973,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) size_t plen; const u8 *pos; - sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE; + sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = false; sm->reqId = 0; sm->reqMethod = EAP_TYPE_NONE; sm->reqVendor = EAP_VENDOR_IETF; @@ -2007,7 +2007,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) "no Type field"); return; } - sm->rxReq = TRUE; + sm->rxReq = true; pos = (const u8 *) (hdr + 1); sm->reqMethod = *pos++; if (sm->reqMethod == EAP_TYPE_EXPANDED) { @@ -2038,7 +2038,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) "EAP-Response - no Type field"); return; } - sm->rxResp = TRUE; + sm->rxResp = true; pos = (const u8 *) (hdr + 1); sm->reqMethod = *pos; wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for " @@ -2051,7 +2051,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) case EAP_CODE_SUCCESS: wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success"); eap_notify_status(sm, "completion", "success"); - sm->rxSuccess = TRUE; + sm->rxSuccess = true; break; case EAP_CODE_FAILURE: wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure"); @@ -2065,7 +2065,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) if (error_code != NO_EAP_METHOD_ERROR) eap_report_error(sm, error_code); } - sm->rxFailure = TRUE; + sm->rxFailure = true; break; case EAP_CODE_INITIATE: eap_peer_initiate(sm, hdr, plen); @@ -2233,7 +2233,7 @@ int eap_peer_sm_step(struct eap_sm *sm) { int res = 0; do { - sm->changed = FALSE; + sm->changed = false; SM_STEP_RUN(EAP); if (sm->changed) res = 1; @@ -2262,7 +2262,7 @@ void eap_sm_abort(struct eap_sm *sm) /* This is not clearly specified in the EAP statemachines draft, but * it seems necessary to make sure that some of the EAPOL variables get * cleared for the next authentication. */ - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); + eapol_set_bool(sm, EAPOL_eapSuccess, false); } @@ -3005,8 +3005,8 @@ void eap_notify_lower_layer_success(struct eap_sm *sm) return; if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); + sm->eapKeyAvailable = true; + eapol_set_bool(sm, EAPOL_eapSuccess, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS "EAP authentication completed successfully (based on lower " "layer success)"); diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h index 9aa74ef81..a40d007d9 100644 --- a/src/eap_peer/eap.h +++ b/src/eap_peer/eap.h @@ -44,7 +44,7 @@ enum eapol_bool_var { /** * EAPOL_eapRestart - Lower layer request to restart authentication * - * Set to TRUE in lower layer, FALSE in EAP state machine. + * Set to true in lower layer, false in EAP state machine. */ EAPOL_eapRestart, @@ -58,21 +58,21 @@ enum eapol_bool_var { /** * EAPOL_eapResp - Response to send * - * Set to TRUE in EAP state machine, FALSE in lower layer. + * Set to true in EAP state machine, false in lower layer. */ EAPOL_eapResp, /** * EAPOL_eapNoResp - Request has been process; no response to send * - * Set to TRUE in EAP state machine, FALSE in lower layer. + * Set to true in EAP state machine, false in lower layer. */ EAPOL_eapNoResp, /** * EAPOL_eapReq - EAP request available from lower layer * - * Set to TRUE in lower layer, FALSE in EAP state machine. + * Set to true in lower layer, false in EAP state machine. */ EAPOL_eapReq, diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c index d50bc6186..e57461a33 100644 --- a/src/eap_peer/eap_aka.c +++ b/src/eap_peer/eap_aka.c @@ -1365,24 +1365,24 @@ static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, if (eap_get_config_identity(sm, &len) == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); eap_sm_request_identity(sm); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, &len); if (pos == NULL || len < 3) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } req = wpabuf_head(reqData); id = req->identifier; len = be_to_host16(req->length); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; subtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); @@ -1441,14 +1441,14 @@ done: ret->methodState = METHOD_CONT; if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } return res; } -static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_aka_data *data = priv; return data->pseudonym || data->reauth_id; @@ -1497,7 +1497,7 @@ static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv, } -static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_aka_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c index 534af262e..902944270 100644 --- a/src/eap_peer/eap_eke.c +++ b/src/eap_peer/eap_eke.c @@ -211,7 +211,7 @@ static struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data, eap_eke_state(data, FAILURE); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } @@ -617,7 +617,7 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, eap_eke_state(data, SUCCESS); ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } @@ -656,7 +656,7 @@ static struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, reqData, &len); if (pos == NULL || len < 1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -666,10 +666,10 @@ static struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: exch %d", eke_exch); wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received Data", pos, end - pos); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; switch (eke_exch) { case EAP_EKE_ID: @@ -689,18 +689,18 @@ static struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv, break; default: wpa_printf(MSG_DEBUG, "EAP-EKE: Ignoring message with unknown EKE-Exch %d", eke_exch); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (ret->methodState == METHOD_DONE) - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } -static Boolean eap_eke_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_eke_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_eke_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 0ed4a2b70..b12cfee31 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -1688,7 +1688,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, #if 0 /* FIX */ -static Boolean eap_fast_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_fast_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_fast_data *data = priv; return tls_connection_established(sm->ssl_ctx, data->ssl.conn); @@ -1754,7 +1754,7 @@ static int eap_fast_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_fast_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_fast_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_fast_data *data = priv; return data->success; diff --git a/src/eap_peer/eap_gpsk.c b/src/eap_peer/eap_gpsk.c index f9c4d3773..20d96c139 100644 --- a/src/eap_peer/eap_gpsk.c +++ b/src/eap_peer/eap_gpsk.c @@ -280,7 +280,7 @@ static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, struct wpabuf *resp; if (data->state != GPSK_1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -588,7 +588,7 @@ static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, const u8 *pos, *end; if (data->state != GPSK_3) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -671,7 +671,7 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); if (pos == NULL || len < 1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -680,10 +680,10 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, len--; wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", opcode); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; switch (opcode) { case EAP_GPSK_OPCODE_GPSK_1: @@ -696,7 +696,7 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with unknown opcode %d", opcode); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -704,7 +704,7 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, } -static Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_gpsk_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_gtc.c b/src/eap_peer/eap_gtc.c index a519a780a..72c02cc19 100644 --- a/src/eap_peer/eap_gtc.c +++ b/src/eap_peer/eap_gtc.c @@ -54,7 +54,7 @@ static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } id = eap_get_id(reqData); @@ -85,15 +85,15 @@ static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, if (password == NULL) { wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); eap_sm_request_otp(sm, (const char *) pos, len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; plen = password_len; identity = eap_get_config_identity(sm, &identity_len); diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h index 8f29d4a26..f43891e39 100644 --- a/src/eap_peer/eap_i.h +++ b/src/eap_peer/eap_i.h @@ -38,7 +38,7 @@ struct eap_method_ret { /** * ignore - Whether method decided to drop the current packed (OUT) */ - Boolean ignore; + bool ignore; /** * methodState - Method-specific state (IN/OUT) @@ -53,7 +53,7 @@ struct eap_method_ret { /** * allowNotifications - Whether method allows notifications (OUT) */ - Boolean allowNotifications; + bool allowNotifications; }; @@ -123,9 +123,9 @@ struct eap_method { * isKeyAvailable - Find out whether EAP method has keying material * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @priv: Pointer to private EAP method data from eap_method::init() - * Returns: %TRUE if key material (eapKeyData) is available + * Returns: %true if key material (eapKeyData) is available */ - Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv); + bool (*isKeyAvailable)(struct eap_sm *sm, void *priv); /** * getKey - Get EAP method specific keying material (eapKeyData) @@ -161,13 +161,13 @@ struct eap_method { * has_reauth_data - Whether method is ready for fast reauthentication * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @priv: Pointer to private EAP method data from eap_method::init() - * Returns: %TRUE or %FALSE based on whether fast reauthentication is + * Returns: %true or %false based on whether fast reauthentication is * possible * * This function is an optional handler that only EAP methods * supporting fast re-authentication need to implement. */ - Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv); + bool (*has_reauth_data)(struct eap_sm *sm, void *priv); /** * deinit_for_reauth - Release data that is not needed for fast re-auth @@ -318,39 +318,39 @@ struct eap_sm { struct wpabuf *lastRespData; EapDecision decision; /* Short-term local variables */ - Boolean rxReq; - Boolean rxSuccess; - Boolean rxFailure; + bool rxReq; + bool rxSuccess; + bool rxFailure; int reqId; enum eap_type reqMethod; int reqVendor; u32 reqVendorMethod; - Boolean ignore; + bool ignore; /* Constants */ int ClientTimeout; /* Miscellaneous variables */ - Boolean allowNotifications; /* peer state machine <-> methods */ + bool allowNotifications; /* peer state machine <-> methods */ struct wpabuf *eapRespData; /* peer to lower layer */ - Boolean eapKeyAvailable; /* peer to lower layer */ + bool eapKeyAvailable; /* peer to lower layer */ u8 *eapKeyData; /* peer to lower layer */ size_t eapKeyDataLen; /* peer to lower layer */ u8 *eapSessionId; /* peer to lower layer */ size_t eapSessionIdLen; /* peer to lower layer */ const struct eap_method *m; /* selected EAP method */ /* not defined in RFC 4137 */ - Boolean changed; + bool changed; void *eapol_ctx; const struct eapol_callbacks *eapol_cb; void *eap_method_priv; int init_phase2; int fast_reauth; - Boolean reauthInit; /* send EAP-Identity/Re-auth */ + bool reauthInit; /* send EAP-Identity/Re-auth */ u32 erp_seq; - Boolean rxResp /* LEAP only */; - Boolean leap_done; - Boolean peap_done; + bool rxResp /* LEAP only */; + bool leap_done; + bool peap_done; u8 req_sha1[20]; /* SHA1() of the current EAP packet */ u8 last_sha1[20]; /* SHA1() of the previously received EAP packet; used * in duplicate request detection. */ diff --git a/src/eap_peer/eap_ikev2.c b/src/eap_peer/eap_ikev2.c index 6ddf50835..b49fe1672 100644 --- a/src/eap_peer/eap_ikev2.c +++ b/src/eap_peer/eap_ikev2.c @@ -138,9 +138,9 @@ static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 flags; size_t send_len, plen, icv_len = 0; - ret->ignore = FALSE; + ret->ignore = false; wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Response"); - ret->allowNotifications = TRUE; + ret->allowNotifications = true; flags = 0; send_len = wpabuf_len(data->out_buf) - data->out_used; @@ -293,7 +293,7 @@ static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data, if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in " "a fragmented packet"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -303,14 +303,14 @@ static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data, /* Limit maximum memory allocation */ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Ignore too long message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } data->in_buf = wpabuf_alloc(message_length); if (data->in_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for " "message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpabuf_put_data(data->in_buf, buf, len); @@ -320,7 +320,7 @@ static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data, (unsigned long) wpabuf_tailroom(data->in_buf)); } - ret->ignore = FALSE; + ret->ignore = false; return eap_ikev2_build_frag_ack(id, EAP_CODE_RESPONSE); } @@ -338,7 +338,7 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, reqData, &len); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -355,14 +355,14 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, if (eap_ikev2_process_icv(data, reqData, flags, pos, &end, data->state == WAIT_FRAG_ACK && len == 0) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } message_length = WPA_GET_BE32(pos); @@ -372,7 +372,7 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message " "Length (%d; %ld remaining in this msg)", message_length, (long) (end - pos)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } @@ -384,7 +384,7 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, if (len != 0) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload " "in WAIT_FRAG_ACK state"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged"); @@ -393,10 +393,10 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, } if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - + if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) { return eap_ikev2_process_fragment(data, ret, id, flags, message_length, pos, @@ -435,7 +435,7 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, } -static Boolean eap_ikev2_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_ikev2_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_ikev2_data *data = priv; return data->state == DONE && data->keymat_ok; diff --git a/src/eap_peer/eap_leap.c b/src/eap_peer/eap_leap.c index 34758e021..02daddfb4 100644 --- a/src/eap_peer/eap_leap.c +++ b/src/eap_peer/eap_leap.c @@ -45,7 +45,7 @@ static void * eap_leap_init(struct eap_sm *sm) return NULL; data->state = LEAP_WAIT_CHALLENGE; - sm->leap_done = FALSE; + sm->leap_done = false; return data; } @@ -77,14 +77,14 @@ static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (*pos != LEAP_VERSION) { wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " "%d", *pos); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos++; @@ -96,7 +96,7 @@ static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " "(challenge_len=%d reqDataLen=%lu)", challenge_len, (unsigned long) wpabuf_len(reqData)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } challenge = pos; @@ -119,7 +119,7 @@ static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, (!pwhash && nt_challenge_response(challenge, password, password_len, rpos))) { wpa_printf(MSG_DEBUG, "EAP-LEAP: Failed to derive response"); - ret->ignore = TRUE; + ret->ignore = true; wpabuf_free(resp); return NULL; } @@ -153,7 +153,7 @@ static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv, if (data->state != LEAP_WAIT_SUCCESS) { wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in " "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -170,7 +170,7 @@ static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv, wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data " "for challenge"); wpabuf_free(resp); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } os_memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN); @@ -204,14 +204,14 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (*pos != LEAP_VERSION) { wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " "%d", *pos); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos++; @@ -223,7 +223,7 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response " "(response_len=%d reqDataLen=%lu)", response_len, (unsigned long) wpabuf_len(reqData)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -233,23 +233,23 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, if (pwhash) { if (hash_nt_password_hash(password, pw_hash_hash)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } else { if (nt_password_hash(password, password_len, pw_hash) || hash_nt_password_hash(pw_hash, pw_hash_hash)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } if (challenge_response(data->ap_challenge, pw_hash_hash, expected)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } ret->methodState = METHOD_DONE; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; if (os_memcmp_const(pos, expected, LEAP_RESPONSE_LEN) != 0) { wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid " @@ -265,7 +265,7 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, /* LEAP is somewhat odd method since it sends EAP-Success in the middle * of the authentication. Use special variable to transit EAP state * machine to SUCCESS state. */ - sm->leap_done = TRUE; + sm->leap_done = true; data->state = LEAP_DONE; /* No more authentication messages expected; AP will send EAPOL-Key @@ -286,7 +286,7 @@ static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, if (password == NULL) { wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured"); eap_sm_request_password(sm); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -300,16 +300,16 @@ static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, if (wpabuf_len(reqData) < sizeof(*eap) || be_to_host16(eap->length) > wpabuf_len(reqData)) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; - ret->allowNotifications = TRUE; + ret->ignore = false; + ret->allowNotifications = true; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - sm->leap_done = FALSE; + sm->leap_done = false; switch (eap->code) { case EAP_CODE_REQUEST: @@ -321,13 +321,13 @@ static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, default: wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - " "ignored", eap->code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } -static Boolean eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_leap_data *data = priv; return data->state == LEAP_DONE; diff --git a/src/eap_peer/eap_md5.c b/src/eap_peer/eap_md5.c index efae8deba..14ac5696e 100644 --- a/src/eap_peer/eap_md5.c +++ b/src/eap_peer/eap_md5.c @@ -39,7 +39,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, if (password == NULL) { wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); eap_sm_request_password(sm); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -47,7 +47,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, if (pos == NULL || len == 0) { wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", pos, (unsigned long) len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -60,10 +60,10 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " "(challenge_len=%lu len=%lu)", (unsigned long) challenge_len, (unsigned long) len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; challenge = pos; wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", challenge, challenge_len); @@ -71,7 +71,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); ret->methodState = METHOD_DONE; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, EAP_CODE_RESPONSE, eap_get_id(reqData)); @@ -89,7 +89,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, if (chap_md5(id, password, password_len, challenge, challenge_len, rpos)) { wpa_printf(MSG_INFO, "EAP-MD5: CHAP MD5 operation failed"); - ret->ignore = TRUE; + ret->ignore = true; wpabuf_free(resp); return NULL; } diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c index 249baec88..8ad4d18b3 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -250,7 +250,7 @@ static struct wpabuf * eap_mschapv2_challenge( if (req_len < sizeof(*req) + 1) { wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge data " "(len %lu)", (unsigned long) req_len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos = (const u8 *) (req + 1); @@ -259,7 +259,7 @@ static struct wpabuf * eap_mschapv2_challenge( if (challenge_len != MSCHAPV2_CHAL_LEN) { wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length " "%lu", (unsigned long) challenge_len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -267,7 +267,7 @@ static struct wpabuf * eap_mschapv2_challenge( wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge" " packet: len=%lu challenge_len=%lu", (unsigned long) len, (unsigned long) challenge_len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -282,10 +282,10 @@ static struct wpabuf * eap_mschapv2_challenge( wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername", pos, len); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id, challenge); @@ -377,7 +377,7 @@ static struct wpabuf * eap_mschapv2_success(struct eap_sm *sm, if (resp == NULL) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " "buffer for success response"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -385,7 +385,7 @@ static struct wpabuf * eap_mschapv2_success(struct eap_sm *sm, ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; data->success = 1; if (data->prev_error == ERROR_PASSWD_EXPIRED) @@ -531,10 +531,10 @@ static struct wpabuf * eap_mschapv2_change_password( username = mschapv2_remove_domain(username, &username_len); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; ms_len = sizeof(*ms) + sizeof(*cp); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, @@ -672,10 +672,10 @@ static struct wpabuf * eap_mschapv2_failure(struct eap_sm *sm, os_free(buf); } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; if (data->prev_error == ERROR_PASSWD_EXPIRED && data->passwd_change_version == 3) { @@ -783,7 +783,7 @@ static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, u8 id; if (eap_mschapv2_check_config(sm)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -800,13 +800,13 @@ static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqData, &len); if (pos == NULL || len < sizeof(*ms) + 1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } ms = (const struct eap_mschapv2_hdr *) pos; if (eap_mschapv2_check_mslen(sm, len, ms)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -826,13 +826,13 @@ static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, default: wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored", ms->op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } -static Boolean eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_mschapv2_data *data = priv; return data->success && data->master_key_valid; diff --git a/src/eap_peer/eap_otp.c b/src/eap_peer/eap_otp.c index 0ab4c7907..87615c6a6 100644 --- a/src/eap_peer/eap_otp.c +++ b/src/eap_peer/eap_otp.c @@ -36,7 +36,7 @@ static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_OTP, reqData, &len); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-OTP: Request message", @@ -53,15 +53,15 @@ static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv, if (password == NULL) { wpa_printf(MSG_INFO, "EAP-OTP: Password not configured"); eap_sm_request_otp(sm, (const char *) pos, len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_DONE; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_OTP, password_len, EAP_CODE_RESPONSE, eap_get_id(reqData)); diff --git a/src/eap_peer/eap_pax.c b/src/eap_peer/eap_pax.c index 3cef1c880..a641d44c1 100644 --- a/src/eap_peer/eap_pax.c +++ b/src/eap_peer/eap_pax.c @@ -127,14 +127,14 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, if (data->state != PAX_INIT) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 received in " "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (req->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with CE flag set - " "ignored"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -143,7 +143,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, if (left < 2 + EAP_PAX_RAND_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with too short " "payload"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -152,7 +152,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with incorrect A " "length %d (expected %d)", WPA_GET_BE16(pos), EAP_PAX_RAND_LEN); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -171,7 +171,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, if (random_get_bytes(data->rand.r.y, EAP_PAX_RAND_LEN)) { wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", @@ -180,7 +180,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, if (eap_pax_initial_key_derivation(req->mac_id, data->ak, data->rand.e, data->mk, data->ck, data->ick, data->mid) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -243,14 +243,14 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, if (data->state != PAX_STD_2_SENT) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 received in " "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (req->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with CE flag set - " "ignored"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -259,7 +259,7 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, if (left < 2 + EAP_PAX_MAC_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with too short " "payload"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -268,7 +268,7 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with incorrect " "MAC_CK length %d (expected %d)", WPA_GET_BE16(pos), EAP_PAX_MAC_LEN); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos += 2; @@ -323,7 +323,7 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, data->state = PAX_DONE; ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } @@ -343,7 +343,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, reqData, &len); if (pos == NULL || len < sizeof(*req) + EAP_PAX_ICV_LEN) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } id = eap_get_id(reqData); @@ -363,7 +363,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-PAX: MAC ID changed during " "authentication (was 0x%d, is 0x%d)", data->mac_id, req->mac_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -371,7 +371,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-PAX: DH Group ID changed during " "authentication (was 0x%d, is 0x%d)", data->dh_group_id, req->dh_group_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -380,7 +380,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-PAX: Public Key ID changed during " "authentication (was 0x%d, is 0x%d)", data->public_key_id, req->public_key_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -388,21 +388,21 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, if (req->mac_id != EAP_PAX_MAC_HMAC_SHA1_128) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported MAC ID 0x%x", req->mac_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (req->dh_group_id != EAP_PAX_DH_GROUP_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported DH Group ID 0x%x", req->dh_group_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (req->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported Public Key ID 0x%x", req->public_key_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -410,7 +410,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, /* TODO: add support for reassembling fragments */ wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported - " "ignored packet"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -430,14 +430,14 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, "message"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV", icvbuf, EAP_PAX_ICV_LEN); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; switch (req->op_code) { case EAP_PAX_OP_STD_1: @@ -449,19 +449,19 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, default: wpa_printf(MSG_DEBUG, "EAP-PAX: ignoring message with unknown " "op_code %d", req->op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } return resp; } -static Boolean eap_pax_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_pax_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_pax_data *data = priv; return data->state == PAX_DONE; diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index 92b15ec34..7c3704369 100644 --- a/src/eap_peer/eap_peap.c +++ b/src/eap_peer/eap_peap.c @@ -137,7 +137,7 @@ static void * eap_peap_init(struct eap_sm *sm) data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; - sm->peap_done = FALSE; + sm->peap_done = false; data->peap_version = EAP_PEAP_VERSION; data->force_peap_version = -1; data->peap_outer_success = 2; @@ -920,7 +920,7 @@ continue_req: /* No EAP-Success expected for Phase 1 (outer, * unencrypted auth), so force EAP state * machine to SUCCESS state. */ - sm->peap_done = TRUE; + sm->peap_done = true; } } else { /* FIX: ? */ @@ -930,7 +930,7 @@ continue_req: wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); ret->decision = DECISION_FAIL; ret->methodState = METHOD_MAY_CONT; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; /* Reply with EAP-Failure within the TLS channel to complete * failure reporting. */ resp = wpabuf_alloc(sizeof(struct eap_hdr)); @@ -1014,7 +1014,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, data->force_peap_version); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", @@ -1166,7 +1166,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, } if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } if (res == 1) { @@ -1179,7 +1179,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, } -static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && @@ -1220,7 +1220,7 @@ static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) data->phase2_eap_started = 0; data->resuming = 1; data->reauth = 1; - sm->peap_done = FALSE; + sm->peap_done = false; return priv; } @@ -1245,7 +1245,7 @@ static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return data->key_data != NULL && data->phase2_success; diff --git a/src/eap_peer/eap_psk.c b/src/eap_peer/eap_psk.c index eea9430d2..4997e6a56 100644 --- a/src/eap_peer/eap_psk.c +++ b/src/eap_peer/eap_psk.c @@ -100,7 +100,7 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, "length (%lu; expected %lu or more)", (unsigned long) len, (unsigned long) sizeof(*hdr1)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); @@ -120,7 +120,7 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, if (data->id_s == NULL) { wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " "ID_S (len=%lu)", (unsigned long) data->id_s_len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", @@ -128,7 +128,7 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, if (random_get_bytes(data->rand_p, EAP_PSK_RAND_LEN)) { wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -198,7 +198,7 @@ static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, "length (%lu; expected %lu or more)", (unsigned long) len, (unsigned long) sizeof(*hdr3)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } left = len - sizeof(*hdr3); @@ -220,7 +220,7 @@ static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " "third message (len=%lu, expected 21)", (unsigned long) left); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -377,14 +377,14 @@ static struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; switch (data->state) { case PSK_INIT: @@ -396,19 +396,19 @@ static struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, case PSK_DONE: wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " "unexpected message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } return resp; } -static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_psk_data *data = priv; return data->state == PSK_DONE; diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c index 54f102a3b..605feb24f 100644 --- a/src/eap_peer/eap_pwd.c +++ b/src/eap_peer/eap_pwd.c @@ -257,13 +257,13 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data, struct eap_pwd_id *id; if (data->state != PWD_ID_Req) { - ret->ignore = TRUE; + ret->ignore = true; eap_pwd_state(data, FAILURE); return; } if (payload_len < sizeof(struct eap_pwd_id)) { - ret->ignore = TRUE; + ret->ignore = true; eap_pwd_state(data, FAILURE); return; } @@ -369,14 +369,14 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, int res; if (data->state != PWD_Commit_Req) { - ret->ignore = TRUE; + ret->ignore = true; goto fin; } if (!data->grp) { wpa_printf(MSG_DEBUG, "EAP-PWD (client): uninitialized EAP-pwd group"); - ret->ignore = TRUE; + ret->ignore = true; goto fin; } @@ -696,7 +696,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, size_t prime_len = 0, order_len = 0; if (data->state != PWD_Confirm_Req) { - ret->ignore = TRUE; + ret->ignore = true; goto fin; } @@ -878,14 +878,14 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, wpa_printf(MSG_DEBUG, "EAP-pwd: Got a frame but pos is %s and " "len is %d", pos == NULL ? "NULL" : "not NULL", (int) len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; lm_exch = *pos; pos++; /* skip over the bits and the exch */ @@ -951,7 +951,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, if (len < 2) { wpa_printf(MSG_DEBUG, "EAP-pwd: Frame too short to contain Total-Length field"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } tot_len = WPA_GET_BE16(pos); @@ -962,7 +962,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, if (data->inbuf) { wpa_printf(MSG_DEBUG, "EAP-pwd: Unexpected new fragment start when previous fragment is still in use"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } data->inbuf = wpabuf_alloc(tot_len); @@ -1107,7 +1107,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, } -static Boolean eap_pwd_key_available(struct eap_sm *sm, void *priv) +static bool eap_pwd_key_available(struct eap_sm *sm, void *priv) { struct eap_pwd_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_sake.c b/src/eap_peer/eap_sake.c index 255241f6d..39c195dfd 100644 --- a/src/eap_peer/eap_sake.c +++ b/src/eap_peer/eap_sake.c @@ -148,7 +148,7 @@ static struct wpabuf * eap_sake_process_identity(struct eap_sm *sm, struct wpabuf *resp; if (data->state != IDENTITY) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -195,7 +195,7 @@ static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm, if (data->state != IDENTITY && data->state != CHALLENGE) { wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Challenge received " "in unexpected state (%d)", data->state); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->state == IDENTITY) @@ -296,7 +296,7 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, u8 *rpos; if (data->state != CONFIRM) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -320,7 +320,7 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, eap_sake_state(data, FAILURE); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Auth-Reject"); return eap_sake_build_msg(data, id, 0, EAP_SAKE_SUBTYPE_AUTH_REJECT); @@ -330,7 +330,7 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, eap_sake_state(data, FAILURE); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending " "Response/Auth-Reject"); return eap_sake_build_msg(data, id, 0, @@ -361,7 +361,7 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, eap_sake_state(data, SUCCESS); ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } @@ -380,7 +380,7 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, reqData, &len); if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -399,16 +399,16 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, if (data->session_id_set && data->session_id != session_id) { wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", session_id, data->session_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } data->session_id = session_id; data->session_id_set = 1; - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; switch (subtype) { case EAP_SAKE_SUBTYPE_IDENTITY: @@ -426,18 +426,18 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, default: wpa_printf(MSG_DEBUG, "EAP-SAKE: Ignoring message with " "unknown subtype %d", subtype); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (ret->methodState == METHOD_DONE) - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } -static Boolean eap_sake_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_sake_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_sake_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c index dd9848ec6..eaa1ad715 100644 --- a/src/eap_peer/eap_sim.c +++ b/src/eap_peer/eap_sim.c @@ -1104,23 +1104,23 @@ static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv, if (eap_get_config_identity(sm, &len) == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); eap_sm_request_identity(sm); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len); if (pos == NULL || len < 3) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } req = wpabuf_head(reqData); id = req->identifier; len = be_to_host16(req->length); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; subtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype); @@ -1173,14 +1173,14 @@ done: ret->methodState = METHOD_CONT; if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } return res; } -static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; return data->pseudonym || data->reauth_id; @@ -1231,7 +1231,7 @@ static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv, } -static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_teap.c b/src/eap_peer/eap_teap.c index f751fbec3..76179a329 100644 --- a/src/eap_peer/eap_teap.c +++ b/src/eap_peer/eap_teap.c @@ -1985,7 +1985,7 @@ static struct wpabuf * eap_teap_process(struct eap_sm *sm, void *priv, #if 0 /* TODO */ -static Boolean eap_teap_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_teap_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_teap_data *data = priv; @@ -2048,7 +2048,7 @@ static int eap_teap_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_teap_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_teap_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_teap_data *data = priv; diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c index d9771f601..ad079a7b7 100644 --- a/src/eap_peer/eap_tls.c +++ b/src/eap_peer/eap_tls.c @@ -62,12 +62,12 @@ static void * eap_tls_init(struct eap_sm *sm) wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " "PIN"); eap_sm_request_pin(sm); - sm->ignore = TRUE; + sm->ignore = true; } else if (cert->private_key && !cert->private_key_passwd) { wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " "key passphrase"); eap_sm_request_passphrase(sm); - sm->ignore = TRUE; + sm->ignore = true; } return NULL; } @@ -326,7 +326,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, } -static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; return tls_connection_established(data->ssl_ctx, data->ssl.conn); @@ -364,7 +364,7 @@ static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; return data->key_data != NULL; diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c index 80e2d71e9..ab1067878 100644 --- a/src/eap_peer/eap_tls_common.c +++ b/src/eap_peer/eap_tls_common.c @@ -269,12 +269,12 @@ static int eap_tls_init_connection(struct eap_sm *sm, os_free(config->cert.pin); config->cert.pin = NULL; eap_sm_request_pin(sm); - sm->ignore = TRUE; + sm->ignore = true; } else if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { wpa_printf(MSG_INFO, "TLS: Failed to initialize engine"); } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - sm->ignore = TRUE; + sm->ignore = true; } if (res) { wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " @@ -913,7 +913,7 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm, if (tls_get_errors(data->ssl_ctx)) { wpa_printf(MSG_INFO, "SSL: TLS errors detected"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -929,14 +929,14 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm, pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, &left); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (left == 0) { wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags " "octet included"); if (!sm->workaround) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -954,7 +954,7 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm, if (left < 4) { wpa_printf(MSG_INFO, "SSL: Short frame with TLS " "length"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } tls_msg_len = WPA_GET_BE32(pos); @@ -973,15 +973,15 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm, wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d " "bytes) smaller than this fragment (%d " "bytes)", (int) tls_msg_len, (int) left); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; *len = left; return pos; diff --git a/src/eap_peer/eap_tnc.c b/src/eap_peer/eap_tnc.c index 726221e6b..af1777364 100644 --- a/src/eap_peer/eap_tnc.c +++ b/src/eap_peer/eap_tnc.c @@ -92,9 +92,9 @@ static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, u8 flags; size_t send_len, plen; - ret->ignore = FALSE; + ret->ignore = false; wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Response"); - ret->allowNotifications = TRUE; + ret->allowNotifications = true; flags = EAP_TNC_VERSION; send_len = wpabuf_len(data->out_buf) - data->out_used; @@ -174,7 +174,7 @@ static struct wpabuf * eap_tnc_process_fragment(struct eap_tnc_data *data, if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) { wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a " "fragmented packet"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -184,7 +184,7 @@ static struct wpabuf * eap_tnc_process_fragment(struct eap_tnc_data *data, if (data->in_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for " "message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpabuf_put_data(data->in_buf, buf, len); @@ -219,7 +219,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (pos=%p len=%lu)", pos, (unsigned long) len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -235,14 +235,14 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (len > 0 && (flags & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", flags & EAP_TNC_VERSION_MASK); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } message_length = WPA_GET_BE32(pos); @@ -253,7 +253,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message " "Length (%d; %ld remaining in this msg)", message_length, (long) (end - pos)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } @@ -265,7 +265,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (len > 1) { wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload in " "WAIT_FRAG_ACK state"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged"); @@ -274,10 +274,10 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, } if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - + if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) { return eap_tnc_process_fragment(data, ret, id, flags, message_length, pos, @@ -294,7 +294,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (!(flags & EAP_TNC_FLAGS_START)) { wpa_printf(MSG_DEBUG, "EAP-TNC: Server did not use " "start flag in the first message"); - ret->ignore = TRUE; + ret->ignore = true; goto fail; } @@ -307,7 +307,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (flags & EAP_TNC_FLAGS_START) { wpa_printf(MSG_DEBUG, "EAP-TNC: Server used start " "flag again"); - ret->ignore = TRUE; + ret->ignore = true; goto fail; } @@ -316,7 +316,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, wpabuf_len(data->in_buf)); switch (res) { case TNCCS_PROCESS_ERROR: - ret->ignore = TRUE; + ret->ignore = true; goto fail; case TNCCS_PROCESS_OK_NO_RECOMMENDATION: case TNCCS_RECOMMENDATION_ERROR: @@ -345,10 +345,10 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, wpabuf_free(data->in_buf); data->in_buf = NULL; - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; if (tncs_done) { resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c index 662676f8f..642d179c6 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -1578,7 +1578,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm, struct eap_method_ret *ret) { if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; if (ret->decision == DECISION_UNCOND_SUCC || ret->decision == DECISION_COND_SUCC) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " @@ -1673,7 +1673,7 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, } -static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && @@ -1764,7 +1764,7 @@ static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; return data->key_data != NULL && data->phase2_success; diff --git a/src/eap_peer/eap_vendor_test.c b/src/eap_peer/eap_vendor_test.c index 16e3c3956..431f44b65 100644 --- a/src/eap_peer/eap_vendor_test.c +++ b/src/eap_peer/eap_vendor_test.c @@ -75,28 +75,28 @@ static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len); if (pos == NULL || len < 1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->state == INIT && *pos != 1) { wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " "%d in INIT state", *pos); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->state == CONFIRM && *pos != 3) { wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " "%d in CONFIRM state", *pos); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->state == SUCCESS) { wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " "in SUCCESS state"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -105,17 +105,17 @@ static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, data->first_try = 0; wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing " "pending request"); - ret->ignore = TRUE; + ret->ignore = true; eloop_register_timeout(1, 0, eap_vendor_ready, sm, NULL); return NULL; } } - ret->ignore = FALSE; + ret->ignore = false; wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response"); - ret->allowNotifications = TRUE; + ret->allowNotifications = true; resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, EAP_CODE_RESPONSE, eap_get_id(reqData)); @@ -138,7 +138,7 @@ static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, } -static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_vendor_test_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c index 92d5a0235..a1e7bff19 100644 --- a/src/eap_peer/eap_wsc.c +++ b/src/eap_peer/eap_wsc.c @@ -304,9 +304,9 @@ static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 flags; size_t send_len, plen; - ret->ignore = FALSE; + ret->ignore = false; wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response"); - ret->allowNotifications = TRUE; + ret->allowNotifications = true; flags = 0; send_len = wpabuf_len(data->out_buf) - data->out_used; @@ -400,7 +400,7 @@ static struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a " "fragmented packet"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -410,7 +410,7 @@ static struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, if (data->in_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " "message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } data->in_op_code = op_code; @@ -441,7 +441,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData, &len); if (pos == NULL || len < 2) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -455,7 +455,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, if (flags & WSC_FLAGS_LF) { if (end - pos < 2) { wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } message_length = WPA_GET_BE16(pos); @@ -464,7 +464,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, if (message_length < end - pos || message_length > 50000) { wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " "Length"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } @@ -477,7 +477,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, if (op_code != WSC_FRAG_ACK) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " "in WAIT_FRAG_ACK state", op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); @@ -489,7 +489,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, op_code != WSC_Done && op_code != WSC_Start) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -497,7 +497,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, if (op_code != WSC_Start) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " "in WAIT_START state", op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-WSC: Received start"); @@ -507,13 +507,13 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, } else if (op_code == WSC_Start) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->in_buf && eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } From db81d814516a9beab9e8062ad91e59f4c01e9503 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:15:47 +0300 Subject: [PATCH 0414/1105] eap_example: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- eap_example/eap_example_peer.c | 35 ++++++++++++++++---------------- eap_example/eap_example_server.c | 6 +++--- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/eap_example/eap_example_peer.c b/eap_example/eap_example_peer.c index fcbfb12d8..5fe0cb7fa 100644 --- a/eap_example/eap_example_peer.c +++ b/eap_example/eap_example_peer.c @@ -18,16 +18,16 @@ void eap_example_server_rx(const u8 *data, size_t data_len); struct eap_peer_ctx { - Boolean eapSuccess; - Boolean eapRestart; - Boolean eapFail; - Boolean eapResp; - Boolean eapNoResp; - Boolean eapReq; - Boolean portEnabled; - Boolean altAccept; /* for EAP */ - Boolean altReject; /* for EAP */ - Boolean eapTriggerStart; + bool eapSuccess; + bool eapRestart; + bool eapFail; + bool eapResp; + bool eapNoResp; + bool eapReq; + bool portEnabled; + bool altAccept; /* for EAP */ + bool altReject; /* for EAP */ + bool eapTriggerStart; struct wpabuf *eapReqData; /* for EAP */ @@ -48,11 +48,11 @@ static struct eap_peer_config * peer_get_config(void *ctx) } -static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable) +static bool peer_get_bool(void *ctx, enum eapol_bool_var variable) { struct eap_peer_ctx *peer = ctx; if (peer == NULL) - return FALSE; + return false; switch (variable) { case EAPOL_eapSuccess: return peer->eapSuccess; @@ -75,12 +75,11 @@ static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable) case EAPOL_eapTriggerStart: return peer->eapTriggerStart; } - return FALSE; + return false; } -static void peer_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) +static void peer_set_bool(void *ctx, enum eapol_bool_var variable, bool value) { struct eap_peer_ctx *peer = ctx; if (peer == NULL) @@ -319,7 +318,7 @@ int eap_example_peer_init(void) return -1; /* Enable "port" to allow authentication */ - eap_ctx.portEnabled = TRUE; + eap_ctx.portEnabled = true; return 0; } @@ -344,7 +343,7 @@ int eap_example_peer_step(void) if (eap_ctx.eapResp) { struct wpabuf *resp; printf("==> Response\n"); - eap_ctx.eapResp = FALSE; + eap_ctx.eapResp = false; resp = eap_get_eapRespData(eap_ctx.eap); if (resp) { /* Send EAP response to the server */ @@ -372,7 +371,7 @@ int eap_example_peer_step(void) void eap_example_peer_rx(const u8 *data, size_t data_len) { /* Make received EAP message available to the EAP library */ - eap_ctx.eapReq = TRUE; + eap_ctx.eapReq = true; wpabuf_free(eap_ctx.eapReqData); eap_ctx.eapReqData = wpabuf_alloc_copy(data, data_len); } diff --git a/eap_example/eap_example_server.c b/eap_example/eap_example_server.c index 1e91fa8ed..3a132bb34 100644 --- a/eap_example/eap_example_server.c +++ b/eap_example/eap_example_server.c @@ -234,8 +234,8 @@ int eap_example_server_init(void) eap_ctx.eap_if = eap_get_interface(eap_ctx.eap); /* Enable "port" and request EAP to start authentication. */ - eap_ctx.eap_if->portEnabled = TRUE; - eap_ctx.eap_if->eapRestart = TRUE; + eap_ctx.eap_if->portEnabled = true; + eap_ctx.eap_if->eapRestart = true; return 0; } @@ -296,5 +296,5 @@ void eap_example_server_rx(const u8 *data, size_t data_len) wpabuf_free(eap_ctx.eap_if->eapRespData); eap_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len); if (eap_ctx.eap_if->eapRespData) - eap_ctx.eap_if->eapResp = TRUE; + eap_ctx.eap_if->eapResp = true; } From 5e5eb5a312ef435f146dbc84c98065c9898444b5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:27:57 +0300 Subject: [PATCH 0415/1105] MACsec: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/ap/wpa_auth_kay.c | 12 +- src/drivers/driver.h | 30 +-- src/drivers/driver_macsec_linux.c | 78 +++--- src/drivers/driver_macsec_qca.c | 34 +-- src/pae/ieee802_1x_cp.c | 144 +++++------ src/pae/ieee802_1x_cp.h | 10 +- src/pae/ieee802_1x_kay.c | 389 +++++++++++++++--------------- src/pae/ieee802_1x_kay.h | 68 +++--- src/pae/ieee802_1x_kay_i.h | 40 +-- src/pae/ieee802_1x_secy_ops.c | 22 +- src/pae/ieee802_1x_secy_ops.h | 8 +- wpa_supplicant/driver_i.h | 8 +- wpa_supplicant/wpas_kay.c | 12 +- 13 files changed, 427 insertions(+), 428 deletions(-) diff --git a/src/ap/wpa_auth_kay.c b/src/ap/wpa_auth_kay.c index b6e47979b..46d94b43f 100644 --- a/src/ap/wpa_auth_kay.c +++ b/src/ap/wpa_auth_kay.c @@ -52,7 +52,7 @@ static int hapd_macsec_get_capability(void *priv, enum macsec_cap *cap) } -static int hapd_enable_protect_frames(void *priv, Boolean enabled) +static int hapd_enable_protect_frames(void *priv, bool enabled) { struct hostapd_data *hapd = priv; @@ -62,7 +62,7 @@ static int hapd_enable_protect_frames(void *priv, Boolean enabled) } -static int hapd_enable_encrypt(void *priv, Boolean enabled) +static int hapd_enable_encrypt(void *priv, bool enabled) { struct hostapd_data *hapd = priv; @@ -72,7 +72,7 @@ static int hapd_enable_encrypt(void *priv, Boolean enabled) } -static int hapd_set_replay_protect(void *priv, Boolean enabled, u32 window) +static int hapd_set_replay_protect(void *priv, bool enabled, u32 window) { struct hostapd_data *hapd = priv; @@ -93,7 +93,7 @@ static int hapd_set_current_cipher_suite(void *priv, u64 cs) } -static int hapd_enable_controlled_port(void *priv, Boolean enabled) +static int hapd_enable_controlled_port(void *priv, bool enabled) { struct hostapd_data *hapd = priv; @@ -465,7 +465,7 @@ void * ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd, wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len); res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, EAP_EXCHANGE, - TRUE); + true); fail: bin_clear_free(msk, sizeof(*msk)); @@ -507,7 +507,7 @@ void * ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd, ckn->len = hapd->conf->mka_ckn_len;; os_memcpy(ckn->name, hapd->conf->mka_ckn, ckn->len); - res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, TRUE); + res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, true); if (res) goto free_cak; diff --git a/src/drivers/driver.h b/src/drivers/driver.h index c624c29c9..e3b13bc25 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2306,9 +2306,9 @@ struct wmm_params { #ifdef CONFIG_MACSEC struct macsec_init_params { - Boolean always_include_sci; - Boolean use_es; - Boolean use_scb; + bool always_include_sci; + bool use_es; + bool use_scb; }; #endif /* CONFIG_MACSEC */ @@ -4003,30 +4003,30 @@ struct wpa_driver_ops { /** * enable_protect_frames - Set protect frames status * @priv: Private driver interface data - * @enabled: TRUE = protect frames enabled - * FALSE = protect frames disabled + * @enabled: true = protect frames enabled + * false = protect frames disabled * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*enable_protect_frames)(void *priv, Boolean enabled); + int (*enable_protect_frames)(void *priv, bool enabled); /** * enable_encrypt - Set encryption status * @priv: Private driver interface data - * @enabled: TRUE = encrypt outgoing traffic - * FALSE = integrity-only protection on outgoing traffic + * @enabled: true = encrypt outgoing traffic + * false = integrity-only protection on outgoing traffic * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*enable_encrypt)(void *priv, Boolean enabled); + int (*enable_encrypt)(void *priv, bool enabled); /** * set_replay_protect - Set replay protect status and window size * @priv: Private driver interface data - * @enabled: TRUE = replay protect enabled - * FALSE = replay protect disabled + * @enabled: true = replay protect enabled + * false = replay protect disabled * @window: replay window size, valid only when replay protect enabled * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*set_replay_protect)(void *priv, Boolean enabled, u32 window); + int (*set_replay_protect)(void *priv, bool enabled, u32 window); /** * set_current_cipher_suite - Set current cipher suite @@ -4039,11 +4039,11 @@ struct wpa_driver_ops { /** * enable_controlled_port - Set controlled port status * @priv: Private driver interface data - * @enabled: TRUE = controlled port enabled - * FALSE = controlled port disabled + * @enabled: true = controlled port enabled + * false = controlled port disabled * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*enable_controlled_port)(void *priv, Boolean enabled); + int (*enable_controlled_port)(void *priv, bool enabled); /** * get_receive_lowest_pn - Get receive lowest pn diff --git a/src/drivers/driver_macsec_linux.c b/src/drivers/driver_macsec_linux.c index 5319ba2d0..36a0757fe 100644 --- a/src/drivers/driver_macsec_linux.c +++ b/src/drivers/driver_macsec_linux.c @@ -59,24 +59,24 @@ struct macsec_drv_data { int parent_ifi; int use_pae_group_addr; - Boolean created_link; + bool created_link; - Boolean controlled_port_enabled; - Boolean controlled_port_enabled_set; + bool controlled_port_enabled; + bool controlled_port_enabled_set; - Boolean protect_frames; - Boolean protect_frames_set; + bool protect_frames; + bool protect_frames_set; - Boolean encrypt; - Boolean encrypt_set; + bool encrypt; + bool encrypt_set; - Boolean replay_protect; - Boolean replay_protect_set; + bool replay_protect; + bool replay_protect_set; u32 replay_window; u8 encoding_sa; - Boolean encoding_sa_set; + bool encoding_sa_set; }; @@ -197,7 +197,7 @@ static int try_commit(struct macsec_drv_data *drv) rtnl_link_put(change); - drv->controlled_port_enabled_set = FALSE; + drv->controlled_port_enabled_set = false; } if (drv->protect_frames_set) { @@ -236,9 +236,9 @@ static int try_commit(struct macsec_drv_data *drv) if (err < 0) return err; - drv->protect_frames_set = FALSE; - drv->encrypt_set = FALSE; - drv->replay_protect_set = FALSE; + drv->protect_frames_set = false; + drv->encrypt_set = false; + drv->replay_protect_set = false; return 0; } @@ -390,17 +390,17 @@ static int macsec_drv_get_capability(void *priv, enum macsec_cap *cap) /** * macsec_drv_enable_protect_frames - Set protect frames status * @priv: Private driver interface data - * @enabled: TRUE = protect frames enabled - * FALSE = protect frames disabled + * @enabled: true = protect frames enabled + * false = protect frames disabled * Returns: 0 on success, -1 on failure (or if not supported) */ -static int macsec_drv_enable_protect_frames(void *priv, Boolean enabled) +static int macsec_drv_enable_protect_frames(void *priv, bool enabled) { struct macsec_drv_data *drv = priv; wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE"); - drv->protect_frames_set = TRUE; + drv->protect_frames_set = true; drv->protect_frames = enabled; return try_commit(drv); @@ -410,17 +410,17 @@ static int macsec_drv_enable_protect_frames(void *priv, Boolean enabled) /** * macsec_drv_enable_encrypt - Set protect frames status * @priv: Private driver interface data - * @enabled: TRUE = protect frames enabled - * FALSE = protect frames disabled + * @enabled: true = protect frames enabled + * false = protect frames disabled * Returns: 0 on success, -1 on failure (or if not supported) */ -static int macsec_drv_enable_encrypt(void *priv, Boolean enabled) +static int macsec_drv_enable_encrypt(void *priv, bool enabled) { struct macsec_drv_data *drv = priv; wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE"); - drv->encrypt_set = TRUE; + drv->encrypt_set = true; drv->encrypt = enabled; return try_commit(drv); @@ -430,12 +430,12 @@ static int macsec_drv_enable_encrypt(void *priv, Boolean enabled) /** * macsec_drv_set_replay_protect - Set replay protect status and window size * @priv: Private driver interface data - * @enabled: TRUE = replay protect enabled - * FALSE = replay protect disabled + * @enabled: true = replay protect enabled + * false = replay protect disabled * @window: replay window size, valid only when replay protect enabled * Returns: 0 on success, -1 on failure (or if not supported) */ -static int macsec_drv_set_replay_protect(void *priv, Boolean enabled, +static int macsec_drv_set_replay_protect(void *priv, bool enabled, u32 window) { struct macsec_drv_data *drv = priv; @@ -443,7 +443,7 @@ static int macsec_drv_set_replay_protect(void *priv, Boolean enabled, wpa_printf(MSG_DEBUG, "%s -> %s, %u", __func__, enabled ? "TRUE" : "FALSE", window); - drv->replay_protect_set = TRUE; + drv->replay_protect_set = true; drv->replay_protect = enabled; if (enabled) drv->replay_window = window; @@ -468,18 +468,18 @@ static int macsec_drv_set_current_cipher_suite(void *priv, u64 cs) /** * macsec_drv_enable_controlled_port - Set controlled port status * @priv: Private driver interface data - * @enabled: TRUE = controlled port enabled - * FALSE = controlled port disabled + * @enabled: true = controlled port enabled + * false = controlled port disabled * Returns: 0 on success, -1 on failure (or if not supported) */ -static int macsec_drv_enable_controlled_port(void *priv, Boolean enabled) +static int macsec_drv_enable_controlled_port(void *priv, bool enabled) { struct macsec_drv_data *drv = priv; wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE"); drv->controlled_port_enabled = enabled; - drv->controlled_port_enabled_set = TRUE; + drv->controlled_port_enabled_set = true; return try_commit(drv); } @@ -986,7 +986,7 @@ nla_put_failure: static int set_active_rx_sa(const struct macsec_genl_ctx *ctx, int ifindex, - u64 sci, unsigned char an, Boolean state) + u64 sci, unsigned char an, bool state) { struct nl_msg *msg; struct nlattr *nest; @@ -1036,7 +1036,7 @@ static int macsec_drv_enable_receive_sa(void *priv, struct receive_sa *sa) SCI2STR(sa->sc->sci.addr, sa->sc->sci.port)); return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci), - sa->an, TRUE); + sa->an, true); } @@ -1056,7 +1056,7 @@ static int macsec_drv_disable_receive_sa(void *priv, struct receive_sa *sa) SCI2STR(sa->sc->sci.addr, sa->sc->sci.port)); return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci), - sa->an, FALSE); + sa->an, false); } @@ -1117,13 +1117,13 @@ static int macsec_drv_create_transmit_sc( sci = mka_sci_u64(&sc->sci); rtnl_link_macsec_set_sci(link, sci); - drv->created_link = TRUE; + drv->created_link = true; err = rtnl_link_add(drv->sk, link, NLM_F_CREATE); if (err == -NLE_BUSY) { wpa_printf(MSG_INFO, DRV_PREFIX "link already exists, using it"); - drv->created_link = FALSE; + drv->created_link = false; } else if (err < 0) { rtnl_link_put(link); wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't create link: err %d", @@ -1296,7 +1296,7 @@ nla_put_failure: static int set_active_tx_sa(const struct macsec_genl_ctx *ctx, int ifindex, - unsigned char an, Boolean state) + unsigned char an, bool state) { struct nl_msg *msg; struct nlattr *nest; @@ -1344,13 +1344,13 @@ static int macsec_drv_enable_transmit_sa(void *priv, struct transmit_sa *sa) SCISTR, drv->ifname, sa->an, SCI2STR(sa->sc->sci.addr, sa->sc->sci.port)); - ret = set_active_tx_sa(ctx, drv->ifi, sa->an, TRUE); + ret = set_active_tx_sa(ctx, drv->ifi, sa->an, true); if (ret < 0) { wpa_printf(MSG_ERROR, DRV_PREFIX "failed to enable txsa"); return ret; } - drv->encoding_sa_set = TRUE; + drv->encoding_sa_set = true; drv->encoding_sa = sa->an; return try_commit(drv); @@ -1372,7 +1372,7 @@ static int macsec_drv_disable_transmit_sa(void *priv, struct transmit_sa *sa) SCISTR, drv->ifname, sa->an, SCI2STR(sa->sc->sci.addr, sa->sc->sci.port)); - return set_active_tx_sa(ctx, drv->ifi, sa->an, FALSE); + return set_active_tx_sa(ctx, drv->ifi, sa->an, false); } diff --git a/src/drivers/driver_macsec_qca.c b/src/drivers/driver_macsec_qca.c index f4e55d5d9..928f02499 100644 --- a/src/drivers/driver_macsec_qca.c +++ b/src/drivers/driver_macsec_qca.c @@ -70,11 +70,11 @@ struct macsec_qca_data { u32 secy_id; /* shadow */ - Boolean always_include_sci; - Boolean use_es; - Boolean use_scb; - Boolean protect_frames; - Boolean replay_protect; + bool always_include_sci; + bool use_es; + bool use_scb; + bool protect_frames; + bool replay_protect; u32 replay_window; struct channel_map receive_channel_map[MAXSC]; @@ -91,7 +91,7 @@ static void __macsec_drv_init(struct macsec_qca_data *drv) wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id); /* Enable Secy and Let EAPoL bypass */ - ret = nss_macsec_secy_en_set(drv->secy_id, TRUE); + ret = nss_macsec_secy_en_set(drv->secy_id, true); if (ret) wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL"); @@ -123,7 +123,7 @@ static void __macsec_drv_init(struct macsec_qca_data *drv) static void __macsec_drv_deinit(struct macsec_qca_data *drv) { - nss_macsec_secy_en_set(drv->secy_id, FALSE); + nss_macsec_secy_en_set(drv->secy_id, false); nss_macsec_secy_rx_sc_del_all(drv->secy_id); nss_macsec_secy_tx_sc_del_all(drv->secy_id); } @@ -422,7 +422,7 @@ static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap) } -static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled) +static int macsec_qca_enable_protect_frames(void *priv, bool enabled) { struct macsec_qca_data *drv = priv; int ret = 0; @@ -435,7 +435,7 @@ static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled) } -static int macsec_qca_set_replay_protect(void *priv, Boolean enabled, +static int macsec_qca_set_replay_protect(void *priv, bool enabled, unsigned int window) { struct macsec_qca_data *drv = priv; @@ -480,7 +480,7 @@ static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs) } -static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled) +static int macsec_qca_enable_controlled_port(void *priv, bool enabled) { struct macsec_qca_data *drv = priv; int ret = 0; @@ -560,7 +560,7 @@ static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa) struct macsec_qca_data *drv = priv; int ret = 0; u32 next_pn = 0; - bool enabled = FALSE; + bool enabled = false; u32 win; u32 channel; @@ -629,7 +629,7 @@ static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel) struct macsec_qca_data *drv = priv; int ret = 0; u32 sc_ch = 0; - bool in_use = FALSE; + bool in_use = false; for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch, @@ -794,7 +794,7 @@ static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa) sa->an); ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, - TRUE); + true); return ret; } @@ -814,7 +814,7 @@ static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa) sa->an); ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, - FALSE); + false); return ret; } @@ -824,7 +824,7 @@ static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel) { struct macsec_qca_data *drv = priv; u32 sc_ch = 0; - bool in_use = FALSE; + bool in_use = false; for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch, @@ -988,7 +988,7 @@ static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa) sa->an); ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, - TRUE); + true); return ret; } @@ -1008,7 +1008,7 @@ static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa) sa->an); ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, - FALSE); + false); return ret; } diff --git a/src/pae/ieee802_1x_cp.c b/src/pae/ieee802_1x_cp.c index 69e57587d..cf41d8dbf 100644 --- a/src/pae/ieee802_1x_cp.c +++ b/src/pae/ieee802_1x_cp.c @@ -31,50 +31,50 @@ struct ieee802_1x_cp_sm { CP_SECURED, CP_RECEIVE, CP_RECEIVING, CP_READY, CP_TRANSMIT, CP_TRANSMITTING, CP_ABANDON, CP_RETIRE } CP_state; - Boolean changed; + bool changed; /* CP -> Client */ - Boolean port_valid; + bool port_valid; /* Logon -> CP */ enum connect_type connect; /* KaY -> CP */ - Boolean chgd_server; /* clear by CP */ - Boolean elected_self; + bool chgd_server; /* clear by CP */ + bool elected_self; enum confidentiality_offset cipher_offset; u64 cipher_suite; - Boolean new_sak; /* clear by CP */ + bool new_sak; /* clear by CP */ struct ieee802_1x_mka_ki distributed_ki; u8 distributed_an; - Boolean using_receive_sas; - Boolean all_receiving; - Boolean server_transmitting; - Boolean using_transmit_sa; + bool using_receive_sas; + bool all_receiving; + bool server_transmitting; + bool using_transmit_sa; /* CP -> KaY */ struct ieee802_1x_mka_ki *lki; u8 lan; - Boolean ltx; - Boolean lrx; + bool ltx; + bool lrx; struct ieee802_1x_mka_ki *oki; u8 oan; - Boolean otx; - Boolean orx; + bool otx; + bool orx; /* CP -> SecY */ - Boolean protect_frames; + bool protect_frames; enum validate_frames validate_frames; - Boolean replay_protect; + bool replay_protect; u32 replay_window; u64 current_cipher_suite; enum confidentiality_offset confidentiality_offset; - Boolean controlled_port_enabled; + bool controlled_port_enabled; /* SecY -> CP */ - Boolean port_enabled; /* SecY->CP */ + bool port_enabled; /* SecY->CP */ /* private */ u32 transmit_when; @@ -109,23 +109,23 @@ SM_STATE(CP, INIT) { SM_ENTRY(CP, INIT); - sm->controlled_port_enabled = FALSE; + sm->controlled_port_enabled = false; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); - sm->port_valid = FALSE; + sm->port_valid = false; os_free(sm->lki); sm->lki = NULL; - sm->ltx = FALSE; - sm->lrx = FALSE; + sm->ltx = false; + sm->lrx = false; os_free(sm->oki); sm->oki = NULL; - sm->otx = FALSE; - sm->orx = FALSE; + sm->otx = false; + sm->orx = false; - sm->port_enabled = TRUE; - sm->chgd_server = FALSE; + sm->port_enabled = true; + sm->chgd_server = false; } @@ -133,8 +133,8 @@ SM_STATE(CP, CHANGE) { SM_ENTRY(CP, CHANGE); - sm->port_valid = FALSE; - sm->controlled_port_enabled = FALSE; + sm->port_valid = false; + sm->controlled_port_enabled = false; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); if (sm->lki) @@ -147,15 +147,15 @@ SM_STATE(CP, CHANGE) */ os_free(sm->oki); sm->oki = NULL; - sm->otx = FALSE; - sm->orx = FALSE; + sm->otx = false; + sm->orx = false; sm->oan = 0; ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan, sm->otx, sm->orx); os_free(sm->lki); sm->lki = NULL; - sm->lrx = FALSE; - sm->ltx = FALSE; + sm->lrx = false; + sm->ltx = false; sm->lan = 0; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); @@ -166,12 +166,12 @@ SM_STATE(CP, ALLOWED) { SM_ENTRY(CP, ALLOWED); - sm->protect_frames = FALSE; - sm->replay_protect = FALSE; + sm->protect_frames = false; + sm->replay_protect = false; sm->validate_frames = Checked; - sm->port_valid = FALSE; - sm->controlled_port_enabled = TRUE; + sm->port_valid = false; + sm->controlled_port_enabled = true; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); secy_cp_control_protect_frames(sm->kay, sm->protect_frames); @@ -185,12 +185,12 @@ SM_STATE(CP, AUTHENTICATED) { SM_ENTRY(CP, AUTHENTICATED); - sm->protect_frames = FALSE; - sm->replay_protect = FALSE; + sm->protect_frames = false; + sm->replay_protect = false; sm->validate_frames = Checked; - sm->port_valid = FALSE; - sm->controlled_port_enabled = TRUE; + sm->port_valid = false; + sm->controlled_port_enabled = true; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); secy_cp_control_protect_frames(sm->kay, sm->protect_frames); @@ -204,7 +204,7 @@ SM_STATE(CP, SECURED) { SM_ENTRY(CP, SECURED); - sm->chgd_server = FALSE; + sm->chgd_server = false; sm->protect_frames = sm->kay->macsec_protect; sm->replay_protect = sm->kay->macsec_replay_protect; @@ -216,7 +216,7 @@ SM_STATE(CP, SECURED) sm->confidentiality_offset = sm->cipher_offset; - sm->port_valid = TRUE; + sm->port_valid = true; secy_cp_control_confidentiality_offset(sm->kay, sm->confidentiality_offset); @@ -238,14 +238,14 @@ SM_STATE(CP, RECEIVE) } os_memcpy(sm->lki, &sm->distributed_ki, sizeof(*sm->lki)); sm->lan = sm->distributed_an; - sm->ltx = FALSE; - sm->lrx = FALSE; + sm->ltx = false; + sm->lrx = false; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); ieee802_1x_kay_create_sas(sm->kay, sm->lki); ieee802_1x_kay_enable_rx_sas(sm->kay, sm->lki); - sm->new_sak = FALSE; - sm->all_receiving = FALSE; + sm->new_sak = false; + sm->all_receiving = false; } @@ -253,7 +253,7 @@ SM_STATE(CP, RECEIVING) { SM_ENTRY(CP, RECEIVING); - sm->lrx = TRUE; + sm->lrx = true; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); sm->transmit_when = sm->transmit_delay; @@ -264,8 +264,8 @@ SM_STATE(CP, RECEIVING) * but the CP will transmit from RECEIVING to READY under * the !electedSelf when KaY is not key server */ ieee802_1x_cp_sm_step(sm); - sm->using_receive_sas = FALSE; - sm->server_transmitting = FALSE; + sm->using_receive_sas = false; + sm->server_transmitting = false; } @@ -281,14 +281,14 @@ SM_STATE(CP, TRANSMIT) { SM_ENTRY(CP, TRANSMIT); - sm->controlled_port_enabled = TRUE; + sm->controlled_port_enabled = true; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); - sm->ltx = TRUE; + sm->ltx = true; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); ieee802_1x_kay_enable_tx_sas(sm->kay, sm->lki); - sm->all_receiving = FALSE; - sm->server_transmitting = FALSE; + sm->all_receiving = false; + sm->server_transmitting = false; } @@ -296,21 +296,21 @@ SM_STATE(CP, TRANSMITTING) { SM_ENTRY(CP, TRANSMITTING); sm->retire_when = sm->orx ? sm->retire_delay : 0; - sm->otx = FALSE; + sm->otx = false; ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan, sm->otx, sm->orx); ieee802_1x_kay_enable_new_info(sm->kay); eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL); eloop_register_timeout(sm->retire_when / 1000, 0, ieee802_1x_cp_retire_when_timeout, sm, NULL); - sm->using_transmit_sa = FALSE; + sm->using_transmit_sa = false; } SM_STATE(CP, ABANDON) { SM_ENTRY(CP, ABANDON); - sm->lrx = FALSE; + sm->lrx = false; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); ieee802_1x_kay_delete_sas(sm->kay, sm->lki); @@ -337,8 +337,8 @@ SM_STATE(CP, RETIRE) ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan, sm->otx, sm->orx); sm->lki = NULL; - sm->ltx = FALSE; - sm->lrx = FALSE; + sm->ltx = false; + sm->lrx = false; sm->lan = 0; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); @@ -455,23 +455,23 @@ struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay) sm->kay = kay; - sm->port_valid = FALSE; + sm->port_valid = false; - sm->chgd_server = FALSE; + sm->chgd_server = false; sm->protect_frames = kay->macsec_protect; sm->validate_frames = kay->macsec_validate; sm->replay_protect = kay->macsec_replay_protect; sm->replay_window = kay->macsec_replay_window; - sm->controlled_port_enabled = FALSE; + sm->controlled_port_enabled = false; sm->lki = NULL; - sm->lrx = FALSE; - sm->ltx = FALSE; + sm->lrx = false; + sm->ltx = false; sm->oki = NULL; - sm->orx = FALSE; - sm->otx = FALSE; + sm->orx = false; + sm->otx = false; sm->current_cipher_suite = default_cs_id; sm->cipher_suite = default_cs_id; @@ -480,7 +480,7 @@ struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay) sm->transmit_delay = MKA_LIFE_TIME; sm->retire_delay = MKA_SAK_RETIRE_TIME; sm->CP_state = CP_BEGIN; - sm->changed = FALSE; + sm->changed = false; wpa_printf(MSG_DEBUG, "CP: state machine created"); @@ -588,14 +588,14 @@ void ieee802_1x_cp_signal_chgdserver(void *cp_ctx) { struct ieee802_1x_cp_sm *sm = cp_ctx; - sm->chgd_server = TRUE; + sm->chgd_server = true; } /** * ieee802_1x_cp_set_electedself - */ -void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_electedself(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->elected_self = status; @@ -628,7 +628,7 @@ void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset) void ieee802_1x_cp_signal_newsak(void *cp_ctx) { struct ieee802_1x_cp_sm *sm = cp_ctx; - sm->new_sak = TRUE; + sm->new_sak = true; } @@ -656,7 +656,7 @@ void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an) /** * ieee802_1x_cp_set_usingreceivesas - */ -void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->using_receive_sas = status; @@ -666,7 +666,7 @@ void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status) /** * ieee802_1x_cp_set_allreceiving - */ -void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_allreceiving(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->all_receiving = status; @@ -676,7 +676,7 @@ void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status) /** * ieee802_1x_cp_set_servertransmitting - */ -void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->server_transmitting = status; @@ -686,7 +686,7 @@ void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status) /** * ieee802_1x_cp_set_usingtransmitsas - */ -void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->using_transmit_sa = status; diff --git a/src/pae/ieee802_1x_cp.h b/src/pae/ieee802_1x_cp.h index a357b278f..94110c877 100644 --- a/src/pae/ieee802_1x_cp.h +++ b/src/pae/ieee802_1x_cp.h @@ -24,16 +24,16 @@ void ieee802_1x_cp_connect_unauthenticated(void *cp_ctx); void ieee802_1x_cp_connect_authenticated(void *cp_ctx); void ieee802_1x_cp_connect_secure(void *cp_ctx); void ieee802_1x_cp_signal_chgdserver(void *cp_ctx); -void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status); +void ieee802_1x_cp_set_electedself(void *cp_ctx, bool status); void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs); void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset); void ieee802_1x_cp_signal_newsak(void *cp_ctx); void ieee802_1x_cp_set_distributedki(void *cp_ctx, const struct ieee802_1x_mka_ki *dki); void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an); -void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status); -void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status); -void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status); -void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status); +void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, bool status); +void ieee802_1x_cp_set_allreceiving(void *cp_ctx, bool status); +void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, bool status); +void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, bool status); #endif /* IEEE802_1X_CP_H */ diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c index 3dbd3caa7..2fe88ac0c 100644 --- a/src/pae/ieee802_1x_kay.c +++ b/src/pae/ieee802_1x_kay.c @@ -354,7 +354,7 @@ ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant, /** * ieee802_1x_kay_is_in_potential_peer */ -static Boolean +static bool ieee802_1x_kay_is_in_potential_peer( struct ieee802_1x_mka_participant *participant, const u8 *mi) { @@ -365,7 +365,7 @@ ieee802_1x_kay_is_in_potential_peer( /** * ieee802_1x_kay_is_in_live_peer */ -static Boolean +static bool ieee802_1x_kay_is_in_live_peer( struct ieee802_1x_mka_participant *participant, const u8 *mi) { @@ -426,8 +426,8 @@ u64 mka_sci_u64(struct ieee802_1x_mka_sci *sci) } -static Boolean sci_equal(const struct ieee802_1x_mka_sci *a, - const struct ieee802_1x_mka_sci *b) +static bool sci_equal(const struct ieee802_1x_mka_sci *a, + const struct ieee802_1x_mka_sci *b) { return os_memcmp(a, b, sizeof(struct ieee802_1x_mka_sci)) == 0; } @@ -486,7 +486,7 @@ ieee802_1x_kay_init_receive_sa(struct receive_sc *psc, u8 an, u32 lowest_pn, psa->sc = psc; os_get_time(&psa->created_time); - psa->in_use = FALSE; + psa->in_use = false; dl_list_add(&psc->sa_list, &psa->list); wpa_printf(MSG_DEBUG, @@ -534,7 +534,7 @@ ieee802_1x_kay_init_receive_sc(const struct ieee802_1x_mka_sci *psci) os_memcpy(&psc->sci, psci, sizeof(psc->sci)); os_get_time(&psc->created_time); - psc->receiving = FALSE; + psc->receiving = false; dl_list_init(&psc->sa_list); wpa_printf(MSG_DEBUG, "KaY: Create receive SC: SCI %s", @@ -594,7 +594,7 @@ ieee802_1x_kay_create_peer(const u8 *mi, u32 mn) os_memcpy(peer->mi, mi, MI_LEN); peer->mn = mn; peer->expire = time(NULL) + MKA_LIFE_TIME / 1000; - peer->sak_used = FALSE; + peer->sak_used = false; peer->missing_sak_use_count = 0; return peer; @@ -706,11 +706,11 @@ ieee802_1x_kay_move_live_peer(struct ieee802_1x_mka_participant *participant, /** * ieee802_1x_mka_basic_body_present - */ -static Boolean +static bool ieee802_1x_mka_basic_body_present( struct ieee802_1x_mka_participant *participant) { - return TRUE; + return true; } @@ -774,14 +774,14 @@ ieee802_1x_mka_encode_basic_body( } -static Boolean +static bool reset_participant_mi(struct ieee802_1x_mka_participant *participant) { if (os_get_random(participant->mi, sizeof(participant->mi)) < 0) - return FALSE; + return false; participant->mn = 0; - return TRUE; + return true; } @@ -888,13 +888,13 @@ ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg, peer->macsec_desired = body->macsec_desired; peer->macsec_capability = body->macsec_capability; - peer->is_key_server = (Boolean) body->key_server; + peer->is_key_server = body->key_server; peer->key_server_priority = body->priority; } else if (peer->mn < be_to_host32(body->actor_mn)) { peer->mn = be_to_host32(body->actor_mn); peer->macsec_desired = body->macsec_desired; peer->macsec_capability = body->macsec_capability; - peer->is_key_server = (Boolean) body->key_server; + peer->is_key_server = body->key_server; peer->key_server_priority = body->priority; } else { wpa_printf(MSG_WARNING, @@ -909,7 +909,7 @@ ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg, /** * ieee802_1x_mka_live_peer_body_present */ -static Boolean +static bool ieee802_1x_mka_live_peer_body_present( struct ieee802_1x_mka_participant *participant) { @@ -969,7 +969,7 @@ ieee802_1x_mka_encode_live_peer_body( /** * ieee802_1x_mka_potential_peer_body_present */ -static Boolean +static bool ieee802_1x_mka_potential_peer_body_present( struct ieee802_1x_mka_participant *participant) { @@ -1030,7 +1030,7 @@ ieee802_1x_mka_encode_potential_peer_body( /** * ieee802_1x_mka_i_in_peerlist - */ -static Boolean +static bool ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant, const u8 *mka_msg, size_t msg_len) { @@ -1055,7 +1055,7 @@ ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant, left_len, MKA_HDR_LEN, MKA_ALIGN_LENGTH(body_len), DEFAULT_ICV_LEN); - return FALSE; + return false; } if (body_type != MKA_LIVE_PEER_LIST && @@ -1096,12 +1096,12 @@ ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant, if (mn == participant->mn || (participant->mn > 1 && mn == participant->mn - 1)) - return TRUE; + return true; } } } - return FALSE; + return false; } @@ -1116,7 +1116,7 @@ static int ieee802_1x_mka_decode_live_peer_body( struct ieee802_1x_kay_peer *peer; size_t body_len; size_t i; - Boolean is_included; + bool is_included; is_included = ieee802_1x_kay_is_in_live_peer( participant, participant->current_peer_id.mi); @@ -1209,7 +1209,7 @@ ieee802_1x_mka_decode_potential_peer_body( /** * ieee802_1x_mka_sak_use_body_present */ -static Boolean +static bool ieee802_1x_mka_sak_use_body_present( struct ieee802_1x_mka_participant *participant) { @@ -1296,12 +1296,12 @@ ieee802_1x_mka_encode_sak_use_body( set_mka_param_body_len(body, length - MKA_HDR_LEN); if (length == MKA_HDR_LEN) { - body->ptx = TRUE; - body->prx = TRUE; + body->ptx = true; + body->prx = true; body->lan = 0; - body->lrx = FALSE; - body->ltx = FALSE; - body->delay_protect = FALSE; + body->lrx = false; + body->ltx = false; + body->delay_protect = false; return 0; } @@ -1321,13 +1321,13 @@ ieee802_1x_mka_encode_sak_use_body( if (llpn > kay->pn_exhaustion) { wpa_printf(MSG_WARNING, "KaY: My LLPN exhaustion"); - participant->new_sak = TRUE; + participant->new_sak = true; } } else { if (olpn > kay->pn_exhaustion) { wpa_printf(MSG_WARNING, "KaY: My OLPN exhaustion"); - participant->new_sak = TRUE; + participant->new_sak = true; } } } @@ -1347,23 +1347,23 @@ ieee802_1x_mka_encode_sak_use_body( body->oan = participant->oan; if (participant->oki.kn != participant->lki.kn && participant->oki.kn != 0) { - body->otx = TRUE; - body->orx = TRUE; + body->otx = true; + body->orx = true; os_memcpy(body->osrv_mi, participant->oki.mi, sizeof(body->osrv_mi)); body->okn = host_to_be32(participant->oki.kn); } else { - body->otx = FALSE; - body->orx = FALSE; + body->otx = false; + body->orx = false; } /* set CP's variable */ if (body->ltx) { - kay->tx_enable = TRUE; - kay->port_enable = TRUE; + kay->tx_enable = true; + kay->port_enable = true; } if (body->lrx) - kay->rx_enable = TRUE; + kay->rx_enable = true; ieee802_1x_mka_dump_sak_use_body(body); return 0; @@ -1485,26 +1485,26 @@ ieee802_1x_mka_decode_sak_use_body( */ if (participant->is_key_server) { struct ieee802_1x_kay_peer *peer_iter; - Boolean all_receiving = TRUE; + bool all_receiving = true; /* Distributed keys are equal from above comparison. */ - peer->sak_used = TRUE; + peer->sak_used = true; dl_list_for_each(peer_iter, &participant->live_peers, struct ieee802_1x_kay_peer, list) { if (!peer_iter->sak_used) { - all_receiving = FALSE; + all_receiving = false; break; } } if (all_receiving) { - participant->to_dist_sak = FALSE; - ieee802_1x_cp_set_allreceiving(kay->cp, TRUE); + participant->to_dist_sak = false; + ieee802_1x_cp_set_allreceiving(kay->cp, true); ieee802_1x_cp_sm_step(kay->cp); } } else if (peer->is_key_server) { if (body->ltx) { - ieee802_1x_cp_set_servertransmitting(kay->cp, TRUE); + ieee802_1x_cp_set_servertransmitting(kay->cp, true); ieee802_1x_cp_sm_step(kay->cp); } } @@ -1516,7 +1516,7 @@ ieee802_1x_mka_decode_sak_use_body( * has already been exhausted. */ if (participant->is_key_server && lpn > kay->pn_exhaustion) { - participant->new_sak = TRUE; + participant->new_sak = true; wpa_printf(MSG_WARNING, "KaY: Peer LPN exhaustion"); } @@ -1528,14 +1528,14 @@ ieee802_1x_mka_decode_sak_use_body( if (body->delay_protect) { struct receive_sc *rxsc; struct receive_sa *rxsa; - Boolean found = FALSE; + bool found = false; dl_list_for_each(rxsc, &participant->rxsc_list, struct receive_sc, list) { dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) { if (sa_key && rxsa->pkey == sa_key) { - found = TRUE; + found = true; break; } } @@ -1570,7 +1570,7 @@ ieee802_1x_mka_decode_sak_use_body( /** * ieee802_1x_mka_dist_sak_body_present */ -static Boolean +static bool ieee802_1x_mka_dist_sak_body_present( struct ieee802_1x_mka_participant *participant) { @@ -1663,8 +1663,8 @@ ieee802_1x_mka_encode_dist_sak_body( */ static void ieee802_1x_kay_init_data_key(struct data_key *pkey) { - pkey->transmits = TRUE; - pkey->receives = TRUE; + pkey->transmits = true; + pkey->receives = true; os_get_time(&pkey->created_time); pkey->next_pn = 1; @@ -1730,21 +1730,21 @@ ieee802_1x_mka_decode_dist_sak_body( } if (body_len == 0) { - kay->authenticated = TRUE; - kay->secured = FALSE; - kay->failed = FALSE; - participant->advised_desired = FALSE; + kay->authenticated = true; + kay->secured = false; + kay->failed = false; + participant->advised_desired = false; ieee802_1x_cp_connect_authenticated(kay->cp); ieee802_1x_cp_sm_step(kay->cp); wpa_printf(MSG_WARNING, "KaY: The Key server advise no MACsec"); - participant->to_use_sak = FALSE; + participant->to_use_sak = false; return 0; } - participant->advised_desired = TRUE; - kay->authenticated = FALSE; - kay->secured = TRUE; - kay->failed = FALSE; + participant->advised_desired = true; + kay->authenticated = false; + kay->secured = true; + kay->failed = false; ieee802_1x_cp_connect_secure(kay->cp); ieee802_1x_cp_sm_step(kay->cp); @@ -1825,7 +1825,7 @@ ieee802_1x_mka_decode_dist_sak_body( ieee802_1x_cp_sm_step(kay->cp); kay->rcvd_keys++; - participant->to_use_sak = TRUE; + participant->to_use_sak = true; return 0; } @@ -1834,10 +1834,10 @@ ieee802_1x_mka_decode_dist_sak_body( /** * ieee802_1x_mka_icv_body_present */ -static Boolean +static bool ieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant *participant) { - return TRUE; + return true; } @@ -2002,7 +2002,7 @@ struct mka_param_body_handler { int (*body_rx)(struct ieee802_1x_mka_participant *participant, const u8 *mka_msg, size_t msg_len); int (*body_length)(struct ieee802_1x_mka_participant *participant); - Boolean (*body_present)(struct ieee802_1x_mka_participant *participant); + bool (*body_present)(struct ieee802_1x_mka_participant *participant); }; @@ -2229,7 +2229,7 @@ ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant) dl_list_for_each(peer, &participant->live_peers, struct ieee802_1x_kay_peer, list) - peer->sak_used = FALSE; + peer->sak_used = false; kay->dist_kn++; kay->dist_an++; @@ -2269,13 +2269,13 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) struct ieee802_1x_kay_peer *peer; struct ieee802_1x_kay_peer *key_server = NULL; struct ieee802_1x_kay *kay = participant->kay; - Boolean i_is_key_server; + bool i_is_key_server; int priority_comparison; if (participant->is_obliged_key_server) { - participant->new_sak = TRUE; - participant->to_dist_sak = FALSE; - ieee802_1x_cp_set_electedself(kay->cp, TRUE); + participant->new_sak = true; + participant->to_dist_sak = false; + ieee802_1x_cp_set_electedself(kay->cp, true); return 0; } @@ -2295,7 +2295,7 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) } /* elect the key server between me and the above elected peer */ - i_is_key_server = FALSE; + i_is_key_server = false; if (key_server && participant->can_be_key_server) { struct ieee802_1x_kay_peer tmp; @@ -2303,29 +2303,29 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) os_memcpy(&tmp.sci, &kay->actor_sci, sizeof(tmp.sci)); priority_comparison = compare_priorities(&tmp, key_server); if (priority_comparison < 0) { - i_is_key_server = TRUE; + i_is_key_server = true; } else if (priority_comparison == 0) { wpa_printf(MSG_WARNING, "KaY: Cannot elect key server between me and peer, duplicate MAC detected"); key_server = NULL; } } else if (participant->can_be_key_server) { - i_is_key_server = TRUE; + i_is_key_server = true; } if (i_is_key_server) { - ieee802_1x_cp_set_electedself(kay->cp, TRUE); + ieee802_1x_cp_set_electedself(kay->cp, true); if (!sci_equal(&kay->key_server_sci, &kay->actor_sci)) { ieee802_1x_cp_signal_chgdserver(kay->cp); ieee802_1x_cp_sm_step(kay->cp); } - participant->is_key_server = TRUE; - participant->principal = TRUE; - participant->new_sak = TRUE; + participant->is_key_server = true; + participant->principal = true; + participant->new_sak = true; wpa_printf(MSG_DEBUG, "KaY: I am elected as key server"); - participant->to_dist_sak = FALSE; - participant->is_elected = TRUE; + participant->to_dist_sak = false; + participant->is_elected = true; os_memcpy(&kay->key_server_sci, &kay->actor_sci, sizeof(kay->key_server_sci)); @@ -2334,23 +2334,23 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) wpa_printf(MSG_DEBUG, "KaY: Peer %s was elected as the key server", mi_txt(key_server->mi)); - ieee802_1x_cp_set_electedself(kay->cp, FALSE); + ieee802_1x_cp_set_electedself(kay->cp, false); if (!sci_equal(&kay->key_server_sci, &key_server->sci)) { ieee802_1x_cp_signal_chgdserver(kay->cp); ieee802_1x_cp_sm_step(kay->cp); } - participant->is_key_server = FALSE; - participant->principal = TRUE; - participant->is_elected = TRUE; + participant->is_key_server = false; + participant->principal = true; + participant->is_elected = true; os_memcpy(&kay->key_server_sci, &key_server->sci, sizeof(kay->key_server_sci)); kay->key_server_priority = key_server->key_server_priority; } else { - participant->principal = FALSE; - participant->is_key_server = FALSE; - participant->is_elected = FALSE; + participant->principal = false; + participant->is_key_server = false; + participant->is_elected = false; } return 0; @@ -2370,24 +2370,24 @@ ieee802_1x_kay_decide_macsec_use( struct ieee802_1x_kay *kay = participant->kay; struct ieee802_1x_kay_peer *peer; enum macsec_cap less_capability; - Boolean has_peer; + bool has_peer; if (!participant->is_key_server) return -1; /* key server self is MACsec-desired and requesting MACsec */ if (!kay->macsec_desired) { - participant->advised_desired = FALSE; + participant->advised_desired = false; return -1; } if (kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) { - participant->advised_desired = FALSE; + participant->advised_desired = false; return -1; } less_capability = kay->macsec_capable; /* at least one of peers is MACsec-desired and requesting MACsec */ - has_peer = FALSE; + has_peer = false; dl_list_for_each(peer, &participant->live_peers, struct ieee802_1x_kay_peer, list) { if (!peer->macsec_desired) @@ -2398,24 +2398,24 @@ ieee802_1x_kay_decide_macsec_use( less_capability = (less_capability < peer->macsec_capability) ? less_capability : peer->macsec_capability; - has_peer = TRUE; + has_peer = true; } if (has_peer) { - participant->advised_desired = TRUE; + participant->advised_desired = true; participant->advised_capability = less_capability; - kay->authenticated = FALSE; - kay->secured = TRUE; - kay->failed = FALSE; + kay->authenticated = false; + kay->secured = true; + kay->failed = false; ieee802_1x_cp_connect_secure(kay->cp); ieee802_1x_cp_sm_step(kay->cp); } else { - participant->advised_desired = FALSE; + participant->advised_desired = false; participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED; - participant->to_use_sak = FALSE; - kay->authenticated = TRUE; - kay->secured = FALSE; - kay->failed = FALSE; + participant->to_use_sak = false; + kay->authenticated = true; + kay->secured = false; + kay->failed = false; kay->ltx_kn = 0; kay->ltx_an = 0; kay->lrx_kn = 0; @@ -2514,8 +2514,8 @@ ieee802_1x_participant_send_mkpdu( l2_packet_send(kay->l2_mka, NULL, 0, wpabuf_head(buf), wpabuf_len(buf)); wpabuf_free(buf); - kay->active = TRUE; - participant->active = TRUE; + kay->active = true; + participant->active = true; return 0; } @@ -2541,7 +2541,7 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) struct ieee802_1x_kay *kay; struct ieee802_1x_kay_peer *peer, *pre_peer; time_t now = time(NULL); - Boolean lp_changed; + bool lp_changed; struct receive_sc *rxsc, *pre_rxsc; struct transmit_sa *txsa, *pre_txsa; @@ -2565,7 +2565,7 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) } } - lp_changed = FALSE; + lp_changed = false; dl_list_for_each_safe(peer, pre_peer, &participant->live_peers, struct ieee802_1x_kay_peer, list) { if (now > peer->expire) { @@ -2583,25 +2583,25 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) } dl_list_del(&peer->list); os_free(peer); - lp_changed = TRUE; + lp_changed = true; } } if (lp_changed) { if (dl_list_empty(&participant->live_peers)) { - participant->advised_desired = FALSE; + participant->advised_desired = false; participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED; - participant->to_use_sak = FALSE; - participant->ltx = FALSE; - participant->lrx = FALSE; - participant->otx = FALSE; - participant->orx = FALSE; - participant->is_key_server = FALSE; - participant->is_elected = FALSE; - kay->authenticated = FALSE; - kay->secured = FALSE; - kay->failed = FALSE; + participant->to_use_sak = false; + participant->ltx = false; + participant->lrx = false; + participant->otx = false; + participant->orx = false; + participant->is_key_server = false; + participant->is_elected = false; + kay->authenticated = false; + kay->secured = false; + kay->failed = false; kay->ltx_kn = 0; kay->ltx_an = 0; kay->lrx_kn = 0; @@ -2638,9 +2638,9 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) if (participant->new_sak && participant->is_key_server) { if (!ieee802_1x_kay_generate_new_sak(participant)) - participant->to_dist_sak = TRUE; + participant->to_dist_sak = true; - participant->new_sak = FALSE; + participant->new_sak = false; } if (participant->retry_count < MAX_RETRY_CNT || @@ -2656,9 +2656,9 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) return; delete_mka: - kay->authenticated = FALSE; - kay->secured = FALSE; - kay->failed = TRUE; + kay->authenticated = false; + kay->secured = false; + kay->failed = true; ieee802_1x_kay_delete_mka(kay, &participant->ckn); } @@ -2672,8 +2672,8 @@ ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN, { struct transmit_sa *psa; - key->tx_latest = TRUE; - key->rx_latest = TRUE; + key->tx_latest = true; + key->rx_latest = true; psa = os_zalloc(sizeof(*psa)); if (!psa) { @@ -2683,9 +2683,9 @@ ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN, if (key->confidentiality_offset >= CONFIDENTIALITY_OFFSET_0 && key->confidentiality_offset <= CONFIDENTIALITY_OFFSET_50) - psa->confidentiality = TRUE; + psa->confidentiality = true; else - psa->confidentiality = FALSE; + psa->confidentiality = false; psa->an = an; ieee802_1x_kay_use_data_key(key); @@ -2694,7 +2694,7 @@ ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN, psa->sc = psc; os_get_time(&psa->created_time); - psa->in_use = FALSE; + psa->in_use = false; dl_list_add(&psc->sa_list, &psa->list); wpa_printf(MSG_DEBUG, @@ -2736,9 +2736,9 @@ ieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci *sci) os_memcpy(&psc->sci, sci, sizeof(psc->sci)); os_get_time(&psc->created_time); - psc->transmitting = FALSE; - psc->encoding_sa = FALSE; - psc->enciphering_sa = FALSE; + psc->transmitting = false; + psc->encoding_sa = false; + psc->enciphering_sa = false; dl_list_init(&psc->sa_list); wpa_printf(MSG_DEBUG, "KaY: Create transmit SC - SCI: %s", @@ -2772,7 +2772,7 @@ ieee802_1x_kay_deinit_transmit_sc( */ int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *lki, u8 lan, - Boolean ltx, Boolean lrx) + bool ltx, bool lrx) { struct ieee802_1x_mka_participant *principal; @@ -2807,7 +2807,7 @@ int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay, */ int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *oki, - u8 oan, Boolean otx, Boolean orx) + u8 oan, bool otx, bool orx) { struct ieee802_1x_mka_participant *principal; @@ -2883,13 +2883,13 @@ int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay, latest_sak = NULL; dl_list_for_each(sa_key, &principal->sak_list, struct data_key, list) { if (is_ki_equal(&sa_key->key_identifier, lki)) { - sa_key->rx_latest = TRUE; - sa_key->tx_latest = TRUE; + sa_key->rx_latest = true; + sa_key->tx_latest = true; latest_sak = sa_key; - principal->to_use_sak = TRUE; + principal->to_use_sak = true; } else { - sa_key->rx_latest = FALSE; - sa_key->tx_latest = FALSE; + sa_key->rx_latest = false; + sa_key->tx_latest = false; } } if (!latest_sak) { @@ -2993,10 +2993,10 @@ int ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay *kay, dl_list_for_each(txsa, &principal->txsc->sa_list, struct transmit_sa, list) { if (is_ki_equal(&txsa->pkey->key_identifier, lki)) { - txsa->in_use = TRUE; + txsa->in_use = true; secy_enable_transmit_sa(kay, txsa); ieee802_1x_cp_set_usingtransmitas( - principal->kay->cp, TRUE); + principal->kay->cp, true); ieee802_1x_cp_sm_step(principal->kay->cp); } } @@ -3023,10 +3023,10 @@ int ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay *kay, dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) { if (is_ki_equal(&rxsa->pkey->key_identifier, lki)) { - rxsa->in_use = TRUE; + rxsa->in_use = true; secy_enable_receive_sa(kay, rxsa); ieee802_1x_cp_set_usingreceivesas( - principal->kay->cp, TRUE); + principal->kay->cp, true); ieee802_1x_cp_sm_step(principal->kay->cp); } } @@ -3208,10 +3208,10 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, u8 body_type; int i; const u8 *pos; - Boolean handled[256]; - Boolean bad_sak_use = FALSE; /* Error detected while processing SAK Use - * parameter set */ - Boolean i_in_peerlist, is_in_live_peer, is_in_potential_peer; + bool handled[256]; + bool bad_sak_use = false; /* Error detected while processing SAK Use + * parameter set */ + bool i_in_peerlist, is_in_live_peer, is_in_potential_peer; wpa_printf(MSG_DEBUG, "KaY: Decode received MKPDU (ifname=%s)", kay->if_name); @@ -3268,9 +3268,9 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, * Each parameter set should be present only once. */ for (i = 0; i < 256; i++) - handled[i] = FALSE; + handled[i] = false; - handled[0] = TRUE; + handled[0] = true; for (; left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN; pos += body_len + MKA_HDR_LEN, left_len -= body_len + MKA_HDR_LEN) { @@ -3296,7 +3296,7 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, continue; } - handled[body_type] = TRUE; + handled[body_type] = true; if (body_type < ARRAY_SIZE(mka_body_handler) && mka_body_handler[body_type].body_rx) { if (mka_body_handler[body_type].body_rx @@ -3317,7 +3317,7 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, * that it somehow processes DIST-SAK before * SAK-USE, just ignore SAK-USE failures if * DIST-SAK is also present in this MKPDU. */ - bad_sak_use = TRUE; + bad_sak_use = true; } } else { wpa_printf(MSG_ERROR, @@ -3386,9 +3386,9 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, * from 'potential_peers' to 'live_peers'. */ } - kay->active = TRUE; + kay->active = true; participant->retry_count = 0; - participant->active = TRUE; + participant->active = true; return 0; } @@ -3455,7 +3455,7 @@ static void kay_l2_receive(void *ctx, const u8 *src_addr, const u8 *buf, */ struct ieee802_1x_kay * ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, - Boolean macsec_replay_protect, u32 macsec_replay_window, + bool macsec_replay_protect, u32 macsec_replay_window, u16 port, u8 priority, const char *ifname, const u8 *addr) { struct ieee802_1x_kay *kay; @@ -3472,12 +3472,12 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, kay->ctx = ctx; - kay->enable = TRUE; - kay->active = FALSE; + kay->enable = true; + kay->active = false; - kay->authenticated = FALSE; - kay->secured = FALSE; - kay->failed = FALSE; + kay->authenticated = false; + kay->secured = false; + kay->failed = false; kay->policy = policy; os_strlcpy(kay->if_name, ifname, IFNAMSIZ); @@ -3509,23 +3509,23 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, if (policy == DO_NOT_SECURE || kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) { kay->macsec_capable = MACSEC_CAP_NOT_IMPLEMENTED; - kay->macsec_desired = FALSE; - kay->macsec_protect = FALSE; - kay->macsec_encrypt = FALSE; + kay->macsec_desired = false; + kay->macsec_protect = false; + kay->macsec_encrypt = false; kay->macsec_validate = Disabled; - kay->macsec_replay_protect = FALSE; + kay->macsec_replay_protect = false; kay->macsec_replay_window = 0; kay->macsec_confidentiality = CONFIDENTIALITY_NONE; kay->mka_hello_time = MKA_HELLO_TIME; } else { - kay->macsec_desired = TRUE; - kay->macsec_protect = TRUE; + kay->macsec_desired = true; + kay->macsec_protect = true; if (kay->macsec_capable >= MACSEC_CAP_INTEG_AND_CONF && policy == SHOULD_ENCRYPT) { - kay->macsec_encrypt = TRUE; + kay->macsec_encrypt = true; kay->macsec_confidentiality = CONFIDENTIALITY_OFFSET_0; } else { /* SHOULD_SECURE */ - kay->macsec_encrypt = FALSE; + kay->macsec_encrypt = false; kay->macsec_confidentiality = CONFIDENTIALITY_NONE; } kay->macsec_validate = Strict; @@ -3623,7 +3623,7 @@ struct ieee802_1x_mka_participant * ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, const struct mka_key_name *ckn, const struct mka_key *cak, u32 life, - enum mka_created_mode mode, Boolean is_authenticator) + enum mka_created_mode mode, bool is_authenticator) { struct ieee802_1x_mka_participant *participant; unsigned int usecs; @@ -3671,40 +3671,40 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, switch (mode) { case EAP_EXCHANGE: if (is_authenticator) { - participant->is_obliged_key_server = TRUE; - participant->can_be_key_server = TRUE; - participant->is_key_server = TRUE; - participant->principal = TRUE; + participant->is_obliged_key_server = true; + participant->can_be_key_server = true; + participant->is_key_server = true; + participant->principal = true; os_memcpy(&kay->key_server_sci, &kay->actor_sci, sizeof(kay->key_server_sci)); kay->key_server_priority = kay->actor_priority; - participant->is_elected = TRUE; + participant->is_elected = true; } else { - participant->is_obliged_key_server = FALSE; - participant->can_be_key_server = FALSE; - participant->is_key_server = FALSE; - participant->is_elected = TRUE; + participant->is_obliged_key_server = false; + participant->can_be_key_server = false; + participant->is_key_server = false; + participant->is_elected = true; } break; default: - participant->is_obliged_key_server = FALSE; - participant->can_be_key_server = TRUE; - participant->is_key_server = TRUE; - participant->is_elected = FALSE; + participant->is_obliged_key_server = false; + participant->can_be_key_server = true; + participant->is_key_server = true; + participant->is_elected = false; break; } - participant->cached = FALSE; + participant->cached = false; - participant->active = FALSE; - participant->participant = FALSE; - participant->retain = FALSE; + participant->active = false; + participant->participant = false; + participant->retain = false; participant->activate = DEFAULT; if (participant->is_key_server) - participant->principal = TRUE; + participant->principal = true; dl_list_init(&participant->live_peers); dl_list_init(&participant->potential_peers); @@ -3717,13 +3717,13 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, wpa_printf(MSG_DEBUG, "KaY: Selected random MI: %s", mi_txt(participant->mi)); - participant->lrx = FALSE; - participant->ltx = FALSE; - participant->orx = FALSE; - participant->otx = FALSE; - participant->to_dist_sak = FALSE; - participant->to_use_sak = FALSE; - participant->new_sak = FALSE; + participant->lrx = false; + participant->ltx = false; + participant->orx = false; + participant->otx = false; + participant->to_dist_sak = false; + participant->to_use_sak = false; + participant->new_sak = false; dl_list_init(&participant->sak_list); participant->new_key = NULL; dl_list_init(&participant->rxsc_list); @@ -3856,8 +3856,7 @@ ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn) * ieee802_1x_kay_mka_participate - */ void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay, - struct mka_key_name *ckn, - Boolean status) + struct mka_key_name *ckn, bool status) { struct ieee802_1x_mka_participant *participant; @@ -3887,7 +3886,7 @@ ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay) if (!participant) return -1; - participant->new_sak = TRUE; + participant->new_sak = true; wpa_printf(MSG_DEBUG, "KaY: new SAK signal"); return 0; @@ -3916,7 +3915,7 @@ ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, return -2; if (cs_index == 0) - kay->macsec_desired = FALSE; + kay->macsec_desired = false; kay->macsec_csindex = cs_index; kay->macsec_capable = cipher_suite_tbl[kay->macsec_csindex].capable; @@ -3930,7 +3929,7 @@ ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, participant = ieee802_1x_kay_get_principal_participant(kay); if (participant) { wpa_printf(MSG_INFO, "KaY: Cipher Suite changed"); - participant->new_sak = TRUE; + participant->new_sak = true; } return 0; @@ -4044,7 +4043,7 @@ int ieee802_1x_kay_get_status(struct ieee802_1x_kay *kay, char *buf, } -static const char * true_false(Boolean val) +static const char * true_false(bool val) { return val ? "true" : "false"; } @@ -4067,7 +4066,7 @@ static const char * activate_control_txt(enum activate_ctrl activate) } -static char * mka_mib_peer(struct dl_list *peers, Boolean live, char *buf, +static char * mka_mib_peer(struct dl_list *peers, bool live, char *buf, char *end) { char *pos = buf; @@ -4134,8 +4133,8 @@ int ieee802_1x_kay_get_mib(struct ieee802_1x_kay *kay, char *buf, pos2 += res; pos = pos2; - pos = mka_mib_peer(&p->live_peers, TRUE, pos, end); - pos = mka_mib_peer(&p->potential_peers, FALSE, pos, end); + pos = mka_mib_peer(&p->live_peers, true, pos, end); + pos = mka_mib_peer(&p->potential_peers, false, pos, end); } return pos - buf; diff --git a/src/pae/ieee802_1x_kay.h b/src/pae/ieee802_1x_kay.h index 3367d3aaa..1d3c2acb7 100644 --- a/src/pae/ieee802_1x_kay.h +++ b/src/pae/ieee802_1x_kay.h @@ -62,14 +62,14 @@ struct data_key { struct ieee802_1x_mka_ki key_identifier; enum confidentiality_offset confidentiality_offset; u8 an; - Boolean transmits; - Boolean receives; + bool transmits; + bool receives; struct os_time created_time; u32 next_pn; /* not defined data */ - Boolean rx_latest; - Boolean tx_latest; + bool rx_latest; + bool tx_latest; int user; @@ -79,7 +79,7 @@ struct data_key { /* TransmitSC in IEEE Std 802.1AE-2006, Figure 10-6 */ struct transmit_sc { struct ieee802_1x_mka_sci sci; /* const SCI sci */ - Boolean transmitting; /* bool transmitting (read only) */ + bool transmitting; /* bool transmitting (read only) */ struct os_time created_time; /* Time createdTime */ @@ -93,14 +93,14 @@ struct transmit_sc { /* TransmitSA in IEEE Std 802.1AE-2006, Figure 10-6 */ struct transmit_sa { - Boolean in_use; /* bool inUse (read only) */ + bool in_use; /* bool inUse (read only) */ u32 next_pn; /* PN nextPN (read only) */ struct os_time created_time; /* Time createdTime */ - Boolean enable_transmit; /* bool EnableTransmit */ + bool enable_transmit; /* bool EnableTransmit */ u8 an; - Boolean confidentiality; + bool confidentiality; struct data_key *pkey; struct transmit_sc *sc; @@ -110,7 +110,7 @@ struct transmit_sa { /* ReceiveSC in IEEE Std 802.1AE-2006, Figure 10-6 */ struct receive_sc { struct ieee802_1x_mka_sci sci; /* const SCI sci */ - Boolean receiving; /* bool receiving (read only) */ + bool receiving; /* bool receiving (read only) */ struct os_time created_time; /* Time createdTime */ @@ -120,8 +120,8 @@ struct receive_sc { /* ReceiveSA in IEEE Std 802.1AE-2006, Figure 10-6 */ struct receive_sa { - Boolean enable_receive; /* bool enableReceive */ - Boolean in_use; /* bool inUse (read only) */ + bool enable_receive; /* bool enableReceive */ + bool in_use; /* bool inUse (read only) */ u32 next_pn; /* PN nextPN (read only) */ u32 lowest_pn; /* PN lowestPN (read only) */ @@ -142,11 +142,11 @@ struct ieee802_1x_kay_ctx { int (*macsec_init)(void *ctx, struct macsec_init_params *params); int (*macsec_deinit)(void *ctx); int (*macsec_get_capability)(void *priv, enum macsec_cap *cap); - int (*enable_protect_frames)(void *ctx, Boolean enabled); - int (*enable_encrypt)(void *ctx, Boolean enabled); - int (*set_replay_protect)(void *ctx, Boolean enabled, u32 window); + int (*enable_protect_frames)(void *ctx, bool enabled); + int (*enable_encrypt)(void *ctx, bool enabled); + int (*set_replay_protect)(void *ctx, bool enabled, u32 window); int (*set_current_cipher_suite)(void *ctx, u64 cs); - int (*enable_controlled_port)(void *ctx, Boolean enabled); + int (*enable_controlled_port)(void *ctx, bool enabled); int (*get_receive_lowest_pn)(void *ctx, struct receive_sa *sa); int (*get_transmit_next_pn)(void *ctx, struct transmit_sa *sa); int (*set_transmit_next_pn)(void *ctx, struct transmit_sa *sa); @@ -169,12 +169,12 @@ struct ieee802_1x_kay_ctx { }; struct ieee802_1x_kay { - Boolean enable; - Boolean active; + bool enable; + bool active; - Boolean authenticated; - Boolean secured; - Boolean failed; + bool authenticated; + bool secured; + bool failed; struct ieee802_1x_mka_sci actor_sci; u8 actor_priority; @@ -182,10 +182,10 @@ struct ieee802_1x_kay { u8 key_server_priority; enum macsec_cap macsec_capable; - Boolean macsec_desired; - Boolean macsec_protect; - Boolean macsec_encrypt; - Boolean macsec_replay_protect; + bool macsec_desired; + bool macsec_protect; + bool macsec_encrypt; + bool macsec_replay_protect; u32 macsec_replay_window; enum validate_frames macsec_validate; enum confidentiality_offset macsec_confidentiality; @@ -203,8 +203,8 @@ struct ieee802_1x_kay { /* not defined in IEEE802.1X */ struct ieee802_1x_kay_ctx *ctx; - Boolean is_key_server; - Boolean is_obliged_key_server; + bool is_key_server; + bool is_obliged_key_server; char if_name[IFNAMSIZ]; unsigned int macsec_csindex; /* MACsec cipher suite table index */ @@ -219,9 +219,9 @@ struct ieee802_1x_kay { u8 algo_agility[4]; u32 pn_exhaustion; - Boolean port_enable; - Boolean rx_enable; - Boolean tx_enable; + bool port_enable; + bool rx_enable; + bool tx_enable; struct dl_list participant_list; enum macsec_policy policy; @@ -239,7 +239,7 @@ u64 mka_sci_u64(struct ieee802_1x_mka_sci *sci); struct ieee802_1x_kay * ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, - Boolean macsec_replay_protect, u32 macsec_replay_window, + bool macsec_replay_protect, u32 macsec_replay_window, u16 port, u8 priority, const char *ifname, const u8 *addr); void ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay); @@ -248,22 +248,22 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, const struct mka_key_name *ckn, const struct mka_key *cak, u32 life, enum mka_created_mode mode, - Boolean is_authenticator); + bool is_authenticator); void ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn); void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay, struct mka_key_name *ckn, - Boolean status); + bool status); int ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay); int ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, unsigned int cs_index); int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *lki, u8 lan, - Boolean ltx, Boolean lrx); + bool ltx, bool lrx); int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *oki, - u8 oan, Boolean otx, Boolean orx); + u8 oan, bool otx, bool orx); int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *lki); int ieee802_1x_kay_delete_sas(struct ieee802_1x_kay *kay, diff --git a/src/pae/ieee802_1x_kay_i.h b/src/pae/ieee802_1x_kay_i.h index f9cd3f41b..7a041692a 100644 --- a/src/pae/ieee802_1x_kay_i.h +++ b/src/pae/ieee802_1x_kay_i.h @@ -46,11 +46,11 @@ struct ieee802_1x_kay_peer { u8 mi[MI_LEN]; u32 mn; time_t expire; - Boolean is_key_server; + bool is_key_server; u8 key_server_priority; - Boolean macsec_desired; + bool macsec_desired; enum macsec_cap macsec_capability; - Boolean sak_used; + bool sak_used; int missing_sak_use_count; struct dl_list list; }; @@ -87,18 +87,18 @@ struct ieee802_1x_mka_participant { /* used for active and potential participant */ struct mka_key_name ckn; struct mka_key cak; - Boolean cached; + bool cached; /* used by management to monitor and control activation */ - Boolean active; - Boolean participant; - Boolean retain; + bool active; + bool participant; + bool retain; enum mka_created_mode mode; enum activate_ctrl { DEFAULT, DISABLED, ON_OPER_UP, ALWAYS } activate; /* used for active participant */ - Boolean principal; + bool principal; struct dl_list live_peers; struct dl_list potential_peers; @@ -110,18 +110,18 @@ struct ieee802_1x_mka_participant { struct ieee802_1x_mka_ki lki; u8 lan; - Boolean ltx; - Boolean lrx; + bool ltx; + bool lrx; struct ieee802_1x_mka_ki oki; u8 oan; - Boolean otx; - Boolean orx; + bool otx; + bool orx; - Boolean is_key_server; - Boolean is_obliged_key_server; - Boolean can_be_key_server; - Boolean is_elected; + bool is_key_server; + bool is_obliged_key_server; + bool can_be_key_server; + bool is_elected; struct dl_list sak_list; struct dl_list rxsc_list; @@ -137,11 +137,11 @@ struct ieee802_1x_mka_participant { time_t cak_life; time_t mka_life; - Boolean to_dist_sak; - Boolean to_use_sak; - Boolean new_sak; + bool to_dist_sak; + bool to_use_sak; + bool new_sak; - Boolean advised_desired; + bool advised_desired; enum macsec_cap advised_capability; struct data_key *new_key; diff --git a/src/pae/ieee802_1x_secy_ops.c b/src/pae/ieee802_1x_secy_ops.c index 84ee42b05..0f36e6b53 100644 --- a/src/pae/ieee802_1x_secy_ops.c +++ b/src/pae/ieee802_1x_secy_ops.c @@ -25,7 +25,7 @@ int secy_cp_control_validate_frames(struct ieee802_1x_kay *kay, } -int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, Boolean enabled) +int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, bool enabled) { struct ieee802_1x_kay_ctx *ops; @@ -45,7 +45,7 @@ int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, Boolean enabled) } -int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, Boolean enabled) +int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, bool enabled) { struct ieee802_1x_kay_ctx *ops; @@ -65,7 +65,7 @@ int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, Boolean enabled) } -int secy_cp_control_replay(struct ieee802_1x_kay *kay, Boolean enabled, u32 win) +int secy_cp_control_replay(struct ieee802_1x_kay *kay, bool enabled, u32 win) { struct ieee802_1x_kay_ctx *ops; @@ -113,7 +113,7 @@ int secy_cp_control_confidentiality_offset(struct ieee802_1x_kay *kay, } -int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, Boolean enabled) +int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, bool enabled) { struct ieee802_1x_kay_ctx *ops; @@ -333,7 +333,7 @@ int secy_enable_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa) return -1; } - rxsa->enable_receive = TRUE; + rxsa->enable_receive = true; return ops->enable_receive_sa(ops->ctx, rxsa); } @@ -355,7 +355,7 @@ int secy_disable_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa) return -1; } - rxsa->enable_receive = FALSE; + rxsa->enable_receive = false; return ops->disable_receive_sa(ops->ctx, rxsa); } @@ -462,7 +462,7 @@ int secy_enable_transmit_sa(struct ieee802_1x_kay *kay, return -1; } - txsa->enable_transmit = TRUE; + txsa->enable_transmit = true; return ops->enable_transmit_sa(ops->ctx, txsa); } @@ -485,7 +485,7 @@ int secy_disable_transmit_sa(struct ieee802_1x_kay *kay, return -1; } - txsa->enable_transmit = FALSE; + txsa->enable_transmit = false; return ops->disable_transmit_sa(ops->ctx, txsa); } @@ -509,9 +509,9 @@ int secy_init_macsec(struct ieee802_1x_kay *kay) return -1; } - params.use_es = FALSE; - params.use_scb = FALSE; - params.always_include_sci = TRUE; + params.use_es = false; + params.use_scb = false; + params.always_include_sci = true; ret = ops->macsec_init(ops->ctx, ¶ms); diff --git a/src/pae/ieee802_1x_secy_ops.h b/src/pae/ieee802_1x_secy_ops.h index 2d112ba7c..18c06f665 100644 --- a/src/pae/ieee802_1x_secy_ops.h +++ b/src/pae/ieee802_1x_secy_ops.h @@ -20,13 +20,13 @@ int secy_deinit_macsec(struct ieee802_1x_kay *kay); /****** CP -> SecY ******/ int secy_cp_control_validate_frames(struct ieee802_1x_kay *kay, enum validate_frames vf); -int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, Boolean flag); -int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, Boolean enabled); -int secy_cp_control_replay(struct ieee802_1x_kay *kay, Boolean flag, u32 win); +int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, bool flag); +int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, bool enabled); +int secy_cp_control_replay(struct ieee802_1x_kay *kay, bool flag, u32 win); int secy_cp_control_current_cipher_suite(struct ieee802_1x_kay *kay, u64 cs); int secy_cp_control_confidentiality_offset(struct ieee802_1x_kay *kay, enum confidentiality_offset co); -int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, Boolean flag); +int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, bool flag); /****** KaY -> SecY *******/ int secy_get_capability(struct ieee802_1x_kay *kay, enum macsec_cap *cap); diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index d0bcc6c00..54ae03b5a 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -778,7 +778,7 @@ static inline int wpa_drv_macsec_get_capability(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s, - Boolean enabled) + bool enabled) { if (!wpa_s->driver->enable_protect_frames) return -1; @@ -786,7 +786,7 @@ static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_enable_encrypt(struct wpa_supplicant *wpa_s, - Boolean enabled) + bool enabled) { if (!wpa_s->driver->enable_encrypt) return -1; @@ -794,7 +794,7 @@ static inline int wpa_drv_enable_encrypt(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_set_replay_protect(struct wpa_supplicant *wpa_s, - Boolean enabled, u32 window) + bool enabled, u32 window) { if (!wpa_s->driver->set_replay_protect) return -1; @@ -811,7 +811,7 @@ static inline int wpa_drv_set_current_cipher_suite(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_enable_controlled_port(struct wpa_supplicant *wpa_s, - Boolean enabled) + bool enabled) { if (!wpa_s->driver->enable_controlled_port) return -1; diff --git a/wpa_supplicant/wpas_kay.c b/wpa_supplicant/wpas_kay.c index 41477d514..defd0f2f7 100644 --- a/wpa_supplicant/wpas_kay.c +++ b/wpa_supplicant/wpas_kay.c @@ -44,19 +44,19 @@ static int wpas_macsec_get_capability(void *priv, enum macsec_cap *cap) } -static int wpas_enable_protect_frames(void *wpa_s, Boolean enabled) +static int wpas_enable_protect_frames(void *wpa_s, bool enabled) { return wpa_drv_enable_protect_frames(wpa_s, enabled); } -static int wpas_enable_encrypt(void *wpa_s, Boolean enabled) +static int wpas_enable_encrypt(void *wpa_s, bool enabled) { return wpa_drv_enable_encrypt(wpa_s, enabled); } -static int wpas_set_replay_protect(void *wpa_s, Boolean enabled, u32 window) +static int wpas_set_replay_protect(void *wpa_s, bool enabled, u32 window) { return wpa_drv_set_replay_protect(wpa_s, enabled, window); } @@ -68,7 +68,7 @@ static int wpas_set_current_cipher_suite(void *wpa_s, u64 cs) } -static int wpas_enable_controlled_port(void *wpa_s, Boolean enabled) +static int wpas_enable_controlled_port(void *wpa_s, bool enabled) { return wpa_drv_enable_controlled_port(wpa_s, enabled); } @@ -376,7 +376,7 @@ void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s, wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len); res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, - EAP_EXCHANGE, FALSE); + EAP_EXCHANGE, false); fail: if (msk) { @@ -424,7 +424,7 @@ void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s, ckn->len = ssid->mka_ckn_len; os_memcpy(ckn->name, ssid->mka_ckn, ckn->len); - res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, PSK, FALSE); + res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, PSK, false); if (res) goto free_cak; From 0365458eb8c88b8972517c981ed86597cb2ab279 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:33:16 +0300 Subject: [PATCH 0416/1105] HE: Replace Boolean with C99 bool Signed-off-by: Jouni Malinen --- src/ap/ap_config.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 0503400b5..cffa636cc 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -865,9 +865,9 @@ struct hostapd_bss_config { * struct he_phy_capabilities_info - HE PHY capabilities */ struct he_phy_capabilities_info { - Boolean he_su_beamformer; - Boolean he_su_beamformee; - Boolean he_mu_beamformer; + bool he_su_beamformer; + bool he_su_beamformee; + bool he_mu_beamformer; }; /** From f75a0339d50bc87b10d3af20a8b7330b99a0f6c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:36:42 +0300 Subject: [PATCH 0417/1105] state_machine: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/utils/state_machine.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/state_machine.h b/src/utils/state_machine.h index a51431578..204c8a85a 100644 --- a/src/utils/state_machine.h +++ b/src/utils/state_machine.h @@ -9,7 +9,7 @@ * implement a state machine. In addition to including this header file, each * file implementing a state machine must define STATE_MACHINE_DATA to be the * data structure including state variables (enum machine_state, - * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used + * bool changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define * a group of state machines with shared data structure, STATE_MACHINE_ADDR * needs to be defined to point to the MAC address used in debug output. @@ -45,7 +45,7 @@ static void sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \ */ #define SM_ENTRY(machine, state) \ if (!global || sm->machine ## _state != machine ## _ ## state) { \ - sm->changed = TRUE; \ + sm->changed = true; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \ " entering state " #state); \ } \ @@ -64,7 +64,7 @@ sm->machine ## _state = machine ## _ ## state; */ #define SM_ENTRY_M(machine, _state, data) \ if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ - sm->changed = TRUE; \ + sm->changed = true; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \ #machine " entering state " #_state); \ } \ @@ -82,7 +82,7 @@ sm->data ## _ ## state = machine ## _ ## _state; */ #define SM_ENTRY_MA(machine, _state, data) \ if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ - sm->changed = TRUE; \ + sm->changed = true; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \ #machine " entering state " #_state, \ MAC2STR(STATE_MACHINE_ADDR)); \ From 2c55e67aaf2ca2c40d71c2005f57ee50ecc43b50 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:38:10 +0300 Subject: [PATCH 0418/1105] airtime_policy: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/ap/airtime_policy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ap/airtime_policy.c b/src/ap/airtime_policy.c index f56ca5bdd..1e67f0d59 100644 --- a/src/ap/airtime_policy.c +++ b/src/ap/airtime_policy.c @@ -134,8 +134,8 @@ static void update_airtime_weights(void *eloop_data, void *user_data) unsigned int num_sta_min = 0, num_sta_prod = 1, num_sta_sum = 0, wt_sum = 0; unsigned int quantum; - Boolean all_div_min = TRUE; - Boolean apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC; + bool all_div_min = true; + bool apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC; int wt, num_bss = 0, max_wt = 0; size_t i; @@ -169,7 +169,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data) * integers. */ if (bss->num_backlogged_sta && bss->num_backlogged_sta % num_sta_min > 0) - all_div_min = FALSE; + all_div_min = false; /* If we're in LIMIT mode, we only apply the weight * scaling when the BSS(es) marked as limited would a @@ -178,7 +178,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data) if (!apply_limit && bss->conf->airtime_limit) { if (bss->num_backlogged_sta * wt_sum > bss->conf->airtime_weight * num_sta_sum) - apply_limit = TRUE; + apply_limit = true; } } if (all_div_min) From 71140cd5b1a1ddde2d37bd58a2b99af10955c4c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:39:02 +0300 Subject: [PATCH 0419/1105] RADIUS: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- src/radius/radius_server.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c index c17e53b14..971fe91b1 100644 --- a/src/radius/radius_server.c +++ b/src/radius/radius_server.c @@ -657,8 +657,8 @@ radius_server_get_new_session(struct radius_server_data *data, return NULL; } sess->eap_if = eap_get_interface(sess->eap); - sess->eap_if->eapRestart = TRUE; - sess->eap_if->portEnabled = TRUE; + sess->eap_if->eapRestart = true; + sess->eap_if->portEnabled = true; RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id); @@ -909,13 +909,13 @@ radius_server_encapsulate_eap(struct radius_server_data *data, u16 reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED; if (sess->eap_if->eapFail) { - sess->eap_if->eapFail = FALSE; + sess->eap_if->eapFail = false; code = RADIUS_CODE_ACCESS_REJECT; } else if (sess->eap_if->eapSuccess) { - sess->eap_if->eapSuccess = FALSE; + sess->eap_if->eapSuccess = false; code = RADIUS_CODE_ACCESS_ACCEPT; } else { - sess->eap_if->eapReq = FALSE; + sess->eap_if->eapReq = false; code = RADIUS_CODE_ACCESS_CHALLENGE; } @@ -1443,7 +1443,7 @@ static int radius_server_request(struct radius_server_data *data, wpabuf_free(sess->eap_if->eapRespData); sess->eap_if->eapRespData = eap; - sess->eap_if->eapResp = TRUE; + sess->eap_if->eapResp = true; eap_server_sm_step(sess->eap); if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || @@ -2207,7 +2207,7 @@ radius_server_init(struct radius_server_conf *conf) dl_list_init(&data->erp_keys); os_get_reltime(&data->start_time); data->conf_ctx = conf->conf_ctx; - conf->eap_cfg->backend_auth = TRUE; + conf->eap_cfg->backend_auth = true; conf->eap_cfg->eap_server = 1; data->ipv6 = conf->ipv6; data->get_eap_user = conf->get_eap_user; From 86ea761e93319acec19ad61684c61ca61cf93bf2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:40:03 +0300 Subject: [PATCH 0420/1105] mesh: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- wpa_supplicant/mesh_mpm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 4925b5cde..12aafcb97 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -147,13 +147,13 @@ static u16 copy_supp_rates(struct wpa_supplicant *wpa_s, /* return true if elems from a neighbor match this MBSS */ -static Boolean matches_local(struct wpa_supplicant *wpa_s, - struct ieee802_11_elems *elems) +static bool matches_local(struct wpa_supplicant *wpa_s, + struct ieee802_11_elems *elems) { struct mesh_conf *mconf = wpa_s->ifmsh->mconf; if (elems->mesh_config_len < 5) - return FALSE; + return false; return (mconf->meshid_len == elems->mesh_id_len && os_memcmp(mconf->meshid, elems->mesh_id, @@ -167,17 +167,17 @@ static Boolean matches_local(struct wpa_supplicant *wpa_s, /* check if local link id is already used with another peer */ -static Boolean llid_in_use(struct wpa_supplicant *wpa_s, u16 llid) +static bool llid_in_use(struct wpa_supplicant *wpa_s, u16 llid) { struct sta_info *sta; struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; for (sta = hapd->sta_list; sta; sta = sta->next) { if (sta->my_lid == llid) - return TRUE; + return true; } - return FALSE; + return false; } From 3d58e8286f50cf88a803d6addb477a9f9860c280 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:43:32 +0300 Subject: [PATCH 0421/1105] FILS: Convert Boolean to C99 bool Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 218f7e39a..d3e8a0580 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -894,7 +894,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, { enum wpa_states old_state = wpa_s->wpa_state; #if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) - Boolean update_fils_connect_params = FALSE; + bool update_fils_connect_params = false; #endif /* CONFIG_FILS && IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s", @@ -993,7 +993,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, #if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) if (!fils_hlp_sent && ssid && ssid->eap.erp) - update_fils_connect_params = TRUE; + update_fils_connect_params = true; #endif /* CONFIG_FILS && IEEE8021X_EAPOL */ #ifdef CONFIG_OWE if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE)) From e81e2091b3876635395b6fe90f27b9b19df13bba Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 01:35:36 +0300 Subject: [PATCH 0422/1105] Remove now unused Boolean/TRUE/FALSE definitions The previous users were converted to C99 bool. Signed-off-by: Jouni Malinen --- src/common/defs.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/common/defs.h b/src/common/defs.h index f62c3ceee..bcf6f543b 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -9,15 +9,6 @@ #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) From 05abebaa06e2095b74f61dc96cef3c01659b1287 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Apr 2020 17:03:32 +0300 Subject: [PATCH 0423/1105] tests: Fix sigma_dut_sae_h2e_enabled_group_rejected to clear sae_pwe This test case was using sigma_dut to set sae_pwe=2, but that value was not cleared in the end. This could result in following SAE test cases failing due to unexpected behavior. Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index a115da12a..33a4b5751 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3955,6 +3955,7 @@ def test_sigma_dut_sae_h2e_enabled_group_rejected(dev, apdev): raise Exception("Unexpected connection reported") finally: stop_sigma_dut(sigma) + dev[0].set("sae_pwe", "0") def test_sigma_dut_sae_h2e_rsnxe_mismatch(dev, apdev): """sigma_dut controlled SAE H2E misbehavior with RSNXE""" From a39e9af9086e7c988ac9cd68c04bcf913b73d6d8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 20 Apr 2020 23:53:21 +0300 Subject: [PATCH 0424/1105] nl80211: DPP listen mode callback Update frame processing registration for DPP Public Action frames to include multicast reception when in DPP listen mode and the driver indicates support for this type of explicit request. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 50 ++++++++++++++++++++++++------- src/drivers/driver_nl80211.h | 1 + src/drivers/driver_nl80211_capa.c | 4 +++ 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 75792f340..d48f8cb76 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2165,7 +2165,8 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname, static int nl80211_register_frame(struct i802_bss *bss, struct nl_sock *nl_handle, - u16 type, const u8 *match, size_t match_len) + u16 type, const u8 *match, size_t match_len, + bool multicast) { struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; @@ -2174,10 +2175,12 @@ static int nl80211_register_frame(struct i802_bss *bss, buf[0] = '\0'; wpa_snprintf_hex(buf, sizeof(buf), match, match_len); - wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s", - type, fc2str(type), nl_handle, buf); + wpa_printf(MSG_DEBUG, + "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s multicast=%d", + type, fc2str(type), nl_handle, buf, multicast); if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REGISTER_FRAME)) || + (multicast && nla_put_flag(msg, NL80211_ATTR_RECEIVE_MULTICAST)) || nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, type) || nla_put(msg, NL80211_ATTR_FRAME_MATCH, match_len, match)) { nlmsg_free(msg); @@ -2225,7 +2228,7 @@ static int nl80211_register_action_frame(struct i802_bss *bss, { u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); return nl80211_register_frame(bss, bss->nl_mgmt, - type, match, match_len); + type, match, match_len, false); } @@ -2242,12 +2245,12 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) if (drv->nlmode == NL80211_IFTYPE_ADHOC) { /* register for any AUTH message */ - nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0); + nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0, false); } else if ((drv->capa.flags & WPA_DRIVER_FLAGS_SAE) && !(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { /* register for SAE Authentication frames */ nl80211_register_frame(bss, bss->nl_mgmt, type, - (u8 *) "\x03\x00", 2); + (u8 *) "\x03\x00", 2, false); } #ifdef CONFIG_INTERWORKING @@ -2389,7 +2392,7 @@ static int nl80211_mgmt_subscribe_mesh(struct i802_bss *bss) if (nl80211_register_frame(bss, bss->nl_mgmt, (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4), - NULL, 0) < 0) + NULL, 0, false) < 0) ret = -1; /* Mesh peering open */ @@ -2495,7 +2498,7 @@ static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss) if (nl80211_register_frame(bss, bss->nl_mgmt, (WLAN_FC_TYPE_MGMT << 2) | (stypes[i] << 4), - NULL, 0) < 0) { + NULL, 0, false) < 0) { goto out_err; } } @@ -2529,8 +2532,8 @@ static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss) u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4); /* Register for all Authentication frames */ - if (nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0) - < 0) + if (nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0, + false) < 0) wpa_printf(MSG_DEBUG, "nl80211: Failed to subscribe to handle Authentication frames - SAE offload may not work"); } @@ -7931,7 +7934,7 @@ static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report) if (nl80211_register_frame(bss, bss->nl_preq, (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_PROBE_REQ << 4), - NULL, 0) < 0) + NULL, 0, false) < 0) goto out_err; nl80211_register_eloop_read(&bss->nl_preq, @@ -11433,6 +11436,28 @@ fail: } +#ifdef CONFIG_DPP +static int nl80211_dpp_listen(void *priv, bool enable) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); + struct nl_sock *handle; + + if (!drv->multicast_registrations || !bss->nl_mgmt) + return 0; /* cannot do more than hope broadcast RX works */ + + wpa_printf(MSG_DEBUG, + "nl80211: Update DPP Public Action frame registration (%s multicast RX)", + enable ? "enable" : "disable"); + handle = (void *) (((intptr_t) bss->nl_mgmt) ^ ELOOP_SOCKET_INVALID); + return nl80211_register_frame(bss, handle, type, + (u8 *) "\x04\x09\x50\x6f\x9a\x1a", 6, + enable); +} +#endif /* CONFIG_DPP */ + + const struct wpa_driver_ops wpa_driver_nl80211_ops = { .name = "nl80211", .desc = "Linux nl80211/cfg80211", @@ -11568,4 +11593,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .update_connect_params = nl80211_update_connection_params, .send_external_auth_status = nl80211_send_external_auth_status, .set_4addr_mode = nl80211_set_4addr_mode, +#ifdef CONFIG_DPP + .dpp_listen = nl80211_dpp_listen, +#endif /* CONFIG_DPP */ }; diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 19ac44a42..dc80a17b8 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -172,6 +172,7 @@ struct wpa_driver_nl80211_data { unsigned int get_supported_akm_suites_avail:1; unsigned int add_sta_node_vendor_cmd_avail:1; unsigned int control_port_ap:1; + unsigned int multicast_registrations:1; u64 vendor_scan_cookie; u64 remain_on_chan_cookie; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index f0335912c..f997577db 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -460,6 +460,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_EXT_KEY_ID)) capa->flags |= WPA_DRIVER_FLAGS_EXTENDED_KEY_ID; + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) + info->drv->multicast_registrations = 1; } From ff0b87304ced3864e40cf626ec74acd47f3153d0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2020 16:06:32 +0300 Subject: [PATCH 0425/1105] nl80211: Process unprotected Beacon frame RX events Convert driver indications to internal events to allow invalid Beacon frames to be reported to the AP. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211_event.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 17a06d8f8..1152312a8 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -137,6 +137,7 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd) C2S(NL80211_CMD_STA_OPMODE_CHANGED) C2S(NL80211_CMD_CONTROL_PORT_FRAME) C2S(NL80211_CMD_UPDATE_OWE_INFO) + C2S(NL80211_CMD_UNPROT_BEACON) default: return "NL80211_CMD_UNKNOWN"; } @@ -893,6 +894,23 @@ static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv, } +static void mlme_event_unprot_beacon(struct wpa_driver_nl80211_data *drv, + const u8 *frame, size_t len) +{ + const struct ieee80211_mgmt *mgmt; + union wpa_event_data event; + + if (len < 24) + return; + + mgmt = (const struct ieee80211_mgmt *) frame; + + os_memset(&event, 0, sizeof(event)); + event.unprot_beacon.sa = mgmt->sa; + wpa_supplicant_event(drv->ctx, EVENT_UNPROT_BEACON, &event); +} + + static void mlme_event(struct i802_bss *bss, enum nl80211_commands cmd, struct nlattr *frame, struct nlattr *addr, struct nlattr *timed_out, @@ -974,6 +992,9 @@ static void mlme_event(struct i802_bss *bss, mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC, nla_data(frame), nla_len(frame)); break; + case NL80211_CMD_UNPROT_BEACON: + mlme_event_unprot_beacon(drv, nla_data(frame), nla_len(frame)); + break; default: break; } @@ -2541,6 +2562,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, { struct wpa_driver_nl80211_data *drv = bss->drv; int external_scan_event = 0; + struct nlattr *frame = tb[NL80211_ATTR_FRAME]; wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s", cmd, nl80211_command_to_string(cmd), bss->ifname); @@ -2751,6 +2773,11 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, case NL80211_CMD_UPDATE_OWE_INFO: mlme_event_dh_event(drv, bss, tb); break; + case NL80211_CMD_UNPROT_BEACON: + if (frame) + mlme_event_unprot_beacon(drv, nla_data(frame), + nla_len(frame)); + break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", cmd); From c794bdf9c81d9da05133fd0c3afacf15d0a5e633 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 1 Apr 2020 16:07:00 +0300 Subject: [PATCH 0426/1105] tests: Beacon frame protection mismatch Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_pmf.py | 61 +++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index fc1529b9e..594c0c884 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -989,7 +989,6 @@ def check_mac80211_bigtk(dev, hapd): def test_ap_pmf_beacon_protection_bip(dev, apdev): """WPA2-PSK Beacon protection (BIP)""" - """WPA2-PSK AP with PMF required and Beacon protection enabled (BIP)""" run_ap_pmf_beacon_protection(dev, apdev, "AES-128-CMAC") def test_ap_pmf_beacon_protection_bip_cmac_256(dev, apdev): @@ -1042,3 +1041,63 @@ def run_ap_pmf_beacon_protection(dev, apdev, cipher): logger.info("wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) if valid_bip < 0 or invalid_bip > 0 or missing_bip > 0: raise Exception("Unexpected wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) + +def test_ap_pmf_beacon_protection_mismatch(dev, apdev): + """WPA2-PSK Beacon protection MIC mismatch""" + run_ap_pmf_beacon_protection_mismatch(dev, apdev, False) + +def test_ap_pmf_beacon_protection_missing(dev, apdev): + """WPA2-PSK Beacon protection MME missing""" + run_ap_pmf_beacon_protection_mismatch(dev, apdev, True) + +def run_ap_pmf_beacon_protection_mismatch(dev, apdev, clear): + ssid = "test-beacon-prot" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["beacon_prot"] = "1" + params["group_mgmt_cipher"] = "AES-128-CMAC" + try: + hapd = hostapd.add_ap(apdev[0], params) + except Exception as e: + if "Failed to enable hostapd interface" in str(e): + raise HwsimSkip("Beacon protection not supported") + raise + + bssid = hapd.own_addr() + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1", + key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") + + WPA_ALG_NONE = 0 + WPA_ALG_IGTK = 4 + KEY_FLAG_DEFAULT = 0x02 + KEY_FLAG_TX = 0x08 + KEY_FLAG_GROUP = 0x10 + KEY_FLAG_GROUP_TX_DEFAULT = KEY_FLAG_GROUP | KEY_FLAG_TX | KEY_FLAG_DEFAULT + + addr = "ff:ff:ff:ff:ff:ff" + + if clear: + res = hapd.request("SET_KEY %d %s %d %d %s %s %d" % (WPA_ALG_NONE, addr, 6, 1, 6*"00", "", KEY_FLAG_GROUP)) + else: + res = hapd.request("SET_KEY %d %s %d %d %s %s %d" % (WPA_ALG_IGTK, addr, 6, 1, 6*"00", 16*"00", KEY_FLAG_GROUP_TX_DEFAULT)) + if "OK" not in res: + raise Exception("SET_KEY failed") + + ev = dev[0].wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5) + if ev is None: + raise Exception("Unprotected Beacon frame not reported") + + ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=5) + if ev is None: + raise Exception("Beacon loss not reported") + + ev = hapd.wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5) + if ev is None: + raise Exception("WNM-Notification Request frame not reported") From 83c9b69b01e2673319de7d5d036faa5dffc46c69 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 25 Apr 2020 17:23:24 +0300 Subject: [PATCH 0427/1105] tests: Wait a bit to get Beacon frames into capture The ap_beacon_rate_* test cases could end up terminating before the very first Beacon frame is captured, so wait a bit after the connection to make sure at least one Beacon frame is going to be in the capture file. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_params.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py index 8b5fdea82..791805743 100644 --- a/tests/hwsim/test_ap_params.py +++ b/tests/hwsim/test_ap_params.py @@ -601,6 +601,7 @@ def test_ap_beacon_rate_legacy(dev, apdev): hapd.set('beacon_rate', '55') hapd.enable() dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="2412") + time.sleep(0.5) def test_ap_beacon_rate_legacy2(dev, apdev): """Open AP with Beacon frame TX rate 12 Mbps in VHT BSS""" @@ -623,6 +624,7 @@ def test_ap_beacon_rate_legacy2(dev, apdev): hapd.enable() dev[0].scan_for_bss(hapd.own_addr(), freq="5180") dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="5180") + time.sleep(0.5) finally: dev[0].request("DISCONNECT") hapd.request("DISABLE") @@ -639,6 +641,7 @@ def test_ap_beacon_rate_ht(dev, apdev): hapd.set('beacon_rate', 'ht:0') hapd.enable() dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="2412") + time.sleep(0.5) def test_ap_beacon_rate_ht2(dev, apdev): """Open AP with Beacon frame TX rate HT-MCS 1 in VHT BSS""" @@ -661,6 +664,7 @@ def test_ap_beacon_rate_ht2(dev, apdev): hapd.enable() dev[0].scan_for_bss(hapd.own_addr(), freq="5180") dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="5180") + time.sleep(0.5) finally: dev[0].request("DISCONNECT") hapd.request("DISABLE") @@ -688,6 +692,7 @@ def test_ap_beacon_rate_vht(dev, apdev): hapd.enable() dev[0].scan_for_bss(hapd.own_addr(), freq="5180") dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="5180") + time.sleep(0.5) finally: dev[0].request("DISCONNECT") hapd.request("DISABLE") From a803ba4f9d41d72650f04ae9f43df5ffa2d9a5dc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 29 Apr 2020 13:00:53 +0300 Subject: [PATCH 0428/1105] Use more specific reason codes for 4-way handshake timeouts IEEE 802.11 defines reason codes for indicating 4-way handshake and group key handshake timeouts. Use those reason codes instead of the more generic one for these particular cases in the Authenticator state machine. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 4881357f5..30e725864 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3655,6 +3655,8 @@ SM_STEP(WPA_PTK) wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, "PTKSTART: Retry limit %u reached", conf->wpa_pairwise_update_count); + sm->disconnect_reason = + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT; SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKSTART); @@ -3685,6 +3687,8 @@ SM_STEP(WPA_PTK) wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, "PTKINITNEGOTIATING: Retry limit %u reached", conf->wpa_pairwise_update_count); + sm->disconnect_reason = + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT; SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); @@ -3867,6 +3871,7 @@ SM_STATE(WPA_PTK_GROUP, KEYERROR) sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = false; sm->Disconnect = true; + sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, "group key handshake failed (%s) after %u tries", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN", From c54a5e96b505e0b7c4909b1a1259f9efc0b64722 Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Thu, 23 Apr 2020 15:13:27 -0700 Subject: [PATCH 0429/1105] Randomize GAS dialog token Randomize GAS dialog token field, instead of using an incremental counter with predictable values. This change will make this field unuseful for user fingerprinting. Signed-off-by: Hai Shalom --- wpa_supplicant/gas_query.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c index 759b9b9cd..4b3fcfcfa 100644 --- a/wpa_supplicant/gas_query.c +++ b/wpa_supplicant/gas_query.c @@ -729,19 +729,24 @@ static void gas_query_tx_initial_req(struct gas_query *gas, static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst) { - static int next_start = 0; - int dialog_token; + u8 dialog_token; + int i; - for (dialog_token = 0; dialog_token < 256; dialog_token++) { - if (gas_query_dialog_token_available( - gas, dst, (next_start + dialog_token) % 256)) + /* There should never be more than couple active GAS queries in + * progress, so it should be very likely to find an available dialog + * token by checking random values. Use a limit on the number of + * iterations to handle the unexpected case of large number of pending + * queries cleanly. */ + for (i = 0; i < 256; i++) { + /* Get a random number and check if the slot is available */ + if (os_get_random(&dialog_token, sizeof(dialog_token)) < 0) break; + if (gas_query_dialog_token_available(gas, dst, dialog_token)) + return dialog_token; } - if (dialog_token == 256) - return -1; /* Too many pending queries */ - dialog_token = (next_start + dialog_token) % 256; - next_start = (dialog_token + 1) % 256; - return dialog_token; + + /* No dialog token value available */ + return -1; } From a7d6098fb455fd5c41c08d30bed5427472d4c368 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 May 2020 20:25:21 +0300 Subject: [PATCH 0430/1105] Add PRINTF_FORMAT for printf wrapper functions This avoids compiler format-nonliteral warnings ("format string is not a string literal"). Signed-off-by: Jouni Malinen --- src/ap/wpa_auth_i.h | 3 ++- src/eapol_auth/eapol_auth_sm.c | 1 + src/utils/common.h | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index af0aaca1b..ba08ac257 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -277,7 +277,8 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len); void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, logger_level level, const char *txt); void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, - logger_level level, const char *fmt, ...); + logger_level level, const char *fmt, ...) + PRINTF_FORMAT(4, 5); void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int key_info, const u8 *key_rsc, const u8 *nonce, diff --git a/src/eapol_auth/eapol_auth_sm.c b/src/eapol_auth/eapol_auth_sm.c index e3a57e7db..1c11cb613 100644 --- a/src/eapol_auth/eapol_auth_sm.c +++ b/src/eapol_auth/eapol_auth_sm.c @@ -56,6 +56,7 @@ static void eapol_auth_logger(struct eapol_authenticator *eapol, } +PRINTF_FORMAT(4, 5) static void eapol_auth_vlogger(struct eapol_authenticator *eapol, const u8 *addr, eapol_logger_level level, const char *fmt, ...) diff --git a/src/utils/common.h b/src/utils/common.h index 8e5cfe16a..45f72bb30 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -482,7 +482,8 @@ int hexstr2bin(const char *hex, u8 *buf, size_t len); void inc_byte_array(u8 *counter, size_t len); void buf_shift_right(u8 *buf, size_t len, size_t bits); void wpa_get_ntp_timestamp(u8 *buf); -int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...); +int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...) + PRINTF_FORMAT(3, 4); int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, char sep); int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len); From 674758ed5994daa0620b69dd7a610b2006b6efdb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 3 May 2020 11:43:23 +0300 Subject: [PATCH 0431/1105] tests: Provide digestmod to hmac.new() for Python 3.8 Python 3.8 removed the previously used default of MD5 algorithm, so provide the explicit digestmod=hashlib.md5 parameter to the couple of places that were missing it. Signed-off-by: Jouni Malinen --- tests/hwsim/test_eap_proto.py | 2 +- tests/hwsim/test_radius.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/test_eap_proto.py b/tests/hwsim/test_eap_proto.py index 59519bd6b..7494b429a 100644 --- a/tests/hwsim/test_eap_proto.py +++ b/tests/hwsim/test_eap_proto.py @@ -106,7 +106,7 @@ def start_radius_server(eap_handler): logger.info("No EAP request available") reply.code = pyrad.packet.AccessChallenge - hmac_obj = hmac.new(reply.secret) + hmac_obj = hmac.new(reply.secret, digestmod=hashlib.md5) hmac_obj.update(struct.pack("B", reply.code)) hmac_obj.update(struct.pack("B", reply.id)) diff --git a/tests/hwsim/test_radius.py b/tests/hwsim/test_radius.py index 84163f36d..16a29ec85 100644 --- a/tests/hwsim/test_radius.py +++ b/tests/hwsim/test_radius.py @@ -760,7 +760,7 @@ def test_radius_das_disconnect(dev, apdev): def add_message_auth_req(req): req.authenticator = req.CreateAuthenticator() - hmac_obj = hmac.new(req.secret) + hmac_obj = hmac.new(req.secret, digestmod=hashlib.md5) hmac_obj.update(struct.pack("B", req.code)) hmac_obj.update(struct.pack("B", req.id)) @@ -1046,7 +1046,7 @@ def test_radius_protocol(dev, apdev): pw = b"incorrect" else: pw = reply.secret - hmac_obj = hmac.new(pw) + hmac_obj = hmac.new(pw, digestmod=hashlib.md5) hmac_obj.update(struct.pack("B", reply.code)) hmac_obj.update(struct.pack("B", reply.id)) @@ -1389,7 +1389,7 @@ def test_radius_auth_force_invalid_client_addr(dev, apdev): def add_message_auth(req): req.authenticator = req.CreateAuthenticator() - hmac_obj = hmac.new(req.secret) + hmac_obj = hmac.new(req.secret, digestmod=hashlib.md5) hmac_obj.update(struct.pack("B", req.code)) hmac_obj.update(struct.pack("B", req.id)) From 96b6dd21a022130c3f8a36101e8a50ea3c3d43bf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 May 2020 21:58:59 +0300 Subject: [PATCH 0432/1105] Increase wpa_supplicant control interface buffer size Increase the maximum command length from 4 kB to 8 kB mainly to allow larger certificate blobs to be configured. Use heap memory to avoid inconveniently large stack requirements. In addition, reject potentially truncated commands instead of trying to process them. The maximum length of the request can now be determined with "GET max_command_len". Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 4 +- wpa_supplicant/ctrl_iface.h | 6 ++- wpa_supplicant/ctrl_iface_named_pipe.c | 2 +- wpa_supplicant/ctrl_iface_udp.c | 55 +++++++++++++++++++++++--- wpa_supplicant/ctrl_iface_unix.c | 30 +++++++++++--- 5 files changed, 83 insertions(+), 14 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index e0547f16f..90504948a 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / Control interface (shared code for all backends) - * Copyright (c) 2004-2019, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -891,6 +891,8 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, if (os_strcmp(cmd, "version") == 0) { res = os_snprintf(buf, buflen, "%s", VERSION_STR); + } else if (os_strcasecmp(cmd, "max_command_len") == 0) { + res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN); } else if (os_strcasecmp(cmd, "country") == 0) { if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) res = os_snprintf(buf, buflen, "%c%c", diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h index d54cc076c..510668d49 100644 --- a/wpa_supplicant/ctrl_iface.h +++ b/wpa_supplicant/ctrl_iface.h @@ -1,6 +1,6 @@ /* * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2005, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -11,6 +11,10 @@ #ifdef CONFIG_CTRL_IFACE +#ifndef CTRL_IFACE_MAX_LEN +#define CTRL_IFACE_MAX_LEN 8192 +#endif /* CTRL_IFACE_MAX_LEN */ + /* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */ /** diff --git a/wpa_supplicant/ctrl_iface_named_pipe.c b/wpa_supplicant/ctrl_iface_named_pipe.c index 9c0a47e63..79ff7871d 100644 --- a/wpa_supplicant/ctrl_iface_named_pipe.c +++ b/wpa_supplicant/ctrl_iface_named_pipe.c @@ -45,7 +45,7 @@ ConvertStringSecurityDescriptorToSecurityDescriptorA /* Per-interface ctrl_iface */ -#define REQUEST_BUFSIZE 256 +#define REQUEST_BUFSIZE CTRL_IFACE_MAX_LEN #define REPLY_BUFSIZE 4096 struct ctrl_iface_priv; diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c index 1e92b9752..1512080d6 100644 --- a/wpa_supplicant/ctrl_iface_udp.c +++ b/wpa_supplicant/ctrl_iface_udp.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / UDP socket -based control interface - * Copyright (c) 2004-2016, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -219,7 +219,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_supplicant *wpa_s = eloop_ctx; struct ctrl_iface_priv *priv = sock_ctx; - char buf[4096], *pos; + char *buf, *pos; int res; #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 struct sockaddr_in6 from; @@ -235,11 +235,15 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, int new_attached = 0; u8 cookie[COOKIE_LEN]; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); return; } @@ -249,6 +253,8 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strcmp(addr, "::1")) { wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", addr); + os_free(buf); + return; } #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { @@ -260,11 +266,17 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, */ wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " "source %s", inet_ntoa(from.sin_addr)); + os_free(buf); return; } #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); + return; + } buf[res] = '\0'; if (os_strcmp(buf, "GET_COOKIE") == 0) { @@ -282,18 +294,21 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strncmp(buf, "COOKIE=", 7) != 0) { wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " "drop request"); + os_free(buf); return; } if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " "request - drop request"); + os_free(buf); return; } if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " "drop request"); + os_free(buf); return; } @@ -339,6 +354,8 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, fromlen); } + os_free(buf); + if (new_attached) eapol_sm_notify_ctrl_attached(wpa_s->eapol); } @@ -600,10 +617,13 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_global *global = eloop_ctx; struct ctrl_iface_global_priv *priv = sock_ctx; - char buf[4096], *pos; + char *buf, *pos; int res; #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 struct sockaddr_in6 from; +#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE + char addr[INET6_ADDRSTRLEN]; +#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ struct sockaddr_in from; #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ @@ -612,16 +632,28 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, size_t reply_len; u8 cookie[COOKIE_LEN]; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); return; } #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE -#ifndef CONFIG_CTRL_IFACE_UDP_IPV6 +#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 + inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from)); + if (os_strcmp(addr, "::1")) { + wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", + addr); + os_free(buf); + return; + } +#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { /* * The OS networking stack is expected to drop this kind of @@ -631,11 +663,17 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, */ wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " "source %s", inet_ntoa(from.sin_addr)); + os_free(buf); return; } #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); + return; + } buf[res] = '\0'; if (os_strcmp(buf, "GET_COOKIE") == 0) { @@ -646,18 +684,21 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strncmp(buf, "COOKIE=", 7) != 0) { wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " "drop request"); + os_free(buf); return; } if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " "request - drop request"); + os_free(buf); return; } if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " "drop request"); + os_free(buf); return; } @@ -694,6 +735,8 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen); } + + os_free(buf); } diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c index 71fe7ed6b..35a38c95f 100644 --- a/wpa_supplicant/ctrl_iface_unix.c +++ b/wpa_supplicant/ctrl_iface_unix.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2014, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -131,7 +131,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_supplicant *wpa_s = eloop_ctx; struct ctrl_iface_priv *priv = sock_ctx; - char buf[4096]; + char *buf; int res; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); @@ -139,11 +139,20 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, size_t reply_len = 0; int new_attached = 0; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); + return; + } + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); return; } buf[res] = '\0'; @@ -221,6 +230,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, } } os_free(reply_buf); + os_free(buf); if (new_attached) eapol_sm_notify_ctrl_attached(wpa_s->eapol); @@ -1046,18 +1056,27 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_global *global = eloop_ctx; struct ctrl_iface_global_priv *priv = sock_ctx; - char buf[4096]; + char *buf; int res; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); char *reply = NULL, *reply_buf = NULL; size_t reply_len; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); + return; + } + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); return; } buf[res] = '\0'; @@ -1105,6 +1124,7 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, } } os_free(reply_buf); + os_free(buf); } From 82f2e3ddce28412ed1aff82f62156106b223cd71 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 May 2020 20:58:40 +0300 Subject: [PATCH 0433/1105] tests: Move from 1024 bit private keys to 2048 bit keys Crypto libraries are starting to refuse to accept the old shorter keys, so move all test certificates and DH to use 2048 bit (or longer) keys. Signed-off-by: Jouni Malinen --- tests/hwsim/auth_serv/ca-and-crl-expired.pem | 117 +++++--- tests/hwsim/auth_serv/ca-and-crl.pem | 118 +++++--- tests/hwsim/auth_serv/ca-incorrect-key.pem | 28 ++ tests/hwsim/auth_serv/ca-incorrect.der | Bin 0 -> 902 bytes tests/hwsim/auth_serv/ca-incorrect.pem | 102 ++++--- tests/hwsim/auth_serv/ca-key.pem | 43 ++- tests/hwsim/auth_serv/ca.der | Bin 560 -> 868 bytes tests/hwsim/auth_serv/ca.pem | 102 ++++--- tests/hwsim/auth_serv/dh.conf | 9 +- tests/hwsim/auth_serv/dsaparam.pem | 21 +- .../auth_serv/iCA-server/ca-and-root.pem | 213 ++++++++------ tests/hwsim/auth_serv/iCA-server/cacert.pem | 111 ++++---- tests/hwsim/auth_serv/iCA-server/careq.pem | 24 +- tests/hwsim/auth_serv/iCA-server/index.txt | 4 +- .../hwsim/auth_serv/iCA-server/index.txt.attr | 2 +- .../iCA-server/newcerts/8020A0407F798AB8.pem | 84 ------ .../iCA-server/newcerts/8020A0407F798AB9.pem | 85 ------ .../auth_serv/iCA-server/private/cakey.pem | 52 ++-- tests/hwsim/auth_serv/iCA-server/serial | 2 +- .../auth_serv/iCA-server/server-revoked.key | 52 ++-- .../auth_serv/iCA-server/server-revoked.pem | 121 ++++---- .../auth_serv/iCA-server/server-revoked.req | 24 +- .../iCA-server/server-revoked_and_ica.pem | 232 ++++++++------- tests/hwsim/auth_serv/iCA-server/server.key | 52 ++-- tests/hwsim/auth_serv/iCA-server/server.pem | 120 ++++---- tests/hwsim/auth_serv/iCA-server/server.req | 24 +- .../auth_serv/iCA-server/server_and_ica.pem | 269 +++++++++--------- .../hwsim/auth_serv/iCA-user/ca-and-root.pem | 213 ++++++++------ tests/hwsim/auth_serv/iCA-user/cacert.pem | 111 ++++---- tests/hwsim/auth_serv/iCA-user/careq.pem | 24 +- tests/hwsim/auth_serv/iCA-user/index.txt | 2 +- tests/hwsim/auth_serv/iCA-user/index.txt.attr | 2 +- .../iCA-user/newcerts/E153BA3A7605DA1E.pem | 84 ------ .../auth_serv/iCA-user/private/cakey.pem | 52 ++-- tests/hwsim/auth_serv/iCA-user/serial | 2 +- tests/hwsim/auth_serv/iCA-user/user.key | 52 ++-- tests/hwsim/auth_serv/iCA-user/user.pem | 119 ++++---- tests/hwsim/auth_serv/iCA-user/user.req | 24 +- .../hwsim/auth_serv/iCA-user/user_and_ica.pem | 230 ++++++++------- tests/hwsim/auth_serv/index.txt | 2 +- .../auth_serv/ocsp-multi-server-cache.der | Bin 346 -> 493 bytes tests/hwsim/auth_serv/ocsp-req.der | Bin 76 -> 76 bytes tests/hwsim/auth_serv/ocsp-responder.csr | 16 ++ tests/hwsim/auth_serv/ocsp-responder.key | 40 ++- tests/hwsim/auth_serv/ocsp-responder.pem | 92 +++--- tests/hwsim/auth_serv/ocsp-server-cache.der | Bin 343 -> 490 bytes tests/hwsim/auth_serv/openssl2.cnf | 2 +- tests/hwsim/auth_serv/rootCA/index.txt | 4 + tests/hwsim/auth_serv/rootCA/serial | 2 +- tests/hwsim/auth_serv/server-certpol.pem | 78 ++--- tests/hwsim/auth_serv/server-certpol2.pem | 78 ++--- .../auth_serv/server-eku-client-server.csr | 23 +- .../auth_serv/server-eku-client-server.key | 40 ++- .../auth_serv/server-eku-client-server.pem | 98 ++++--- tests/hwsim/auth_serv/server-eku-client.csr | 23 +- tests/hwsim/auth_serv/server-eku-client.key | 40 ++- tests/hwsim/auth_serv/server-eku-client.pem | 98 ++++--- tests/hwsim/auth_serv/server-expired.csr | 16 ++ tests/hwsim/auth_serv/server-expired.key | 40 ++- tests/hwsim/auth_serv/server-expired.pem | 103 ++++--- tests/hwsim/auth_serv/server-extra.pkcs12 | Bin 2426 -> 3418 bytes .../hwsim/auth_serv/server-long-duration.csr | 27 ++ .../hwsim/auth_serv/server-long-duration.key | 100 +++---- .../hwsim/auth_serv/server-long-duration.pem | 157 +++++----- tests/hwsim/auth_serv/server-no-dnsname.csr | 23 +- tests/hwsim/auth_serv/server-no-dnsname.key | 40 ++- tests/hwsim/auth_serv/server-no-dnsname.pem | 98 ++++--- tests/hwsim/auth_serv/server.csr | 23 +- tests/hwsim/auth_serv/server.key | 40 ++- tests/hwsim/auth_serv/server.pem | 98 ++++--- tests/hwsim/auth_serv/server.pkcs12 | Bin 1685 -> 2549 bytes tests/hwsim/auth_serv/test-ca/cacert.pem | 102 ++++--- tests/hwsim/auth_serv/test-ca/crlnumber | 1 + tests/hwsim/auth_serv/test-ca/index.txt | 67 +++++ .../hwsim/auth_serv/test-ca/private/cakey.pem | 43 ++- tests/hwsim/auth_serv/test-ca/serial | 2 +- tests/hwsim/auth_serv/update.sh | 96 ++++++- tests/hwsim/auth_serv/user.csr | 23 +- tests/hwsim/auth_serv/user.key | 40 ++- tests/hwsim/auth_serv/user.key.pkcs8 | 43 ++- tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 | 42 ++- tests/hwsim/auth_serv/user.pem | 98 ++++--- tests/hwsim/auth_serv/user.pkcs12 | Bin 1653 -> 2517 bytes tests/hwsim/auth_serv/user.rsa-key | 38 ++- tests/hwsim/auth_serv/user2.pkcs12 | Bin 2414 -> 3558 bytes tests/hwsim/auth_serv/user3.pkcs12 | Bin 2356 -> 3524 bytes tests/hwsim/test_ap_eap.py | 4 +- 87 files changed, 2771 insertions(+), 2155 deletions(-) create mode 100644 tests/hwsim/auth_serv/ca-incorrect-key.pem create mode 100644 tests/hwsim/auth_serv/ca-incorrect.der delete mode 100644 tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB8.pem delete mode 100644 tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB9.pem delete mode 100644 tests/hwsim/auth_serv/iCA-user/newcerts/E153BA3A7605DA1E.pem create mode 100644 tests/hwsim/auth_serv/ocsp-responder.csr create mode 100644 tests/hwsim/auth_serv/server-expired.csr create mode 100644 tests/hwsim/auth_serv/server-long-duration.csr create mode 100644 tests/hwsim/auth_serv/test-ca/crlnumber diff --git a/tests/hwsim/auth_serv/ca-and-crl-expired.pem b/tests/hwsim/auth_serv/ca-and-crl-expired.pem index 8c65fbe7e..dc7bf98c1 100644 --- a/tests/hwsim/auth_serv/ca-and-crl-expired.pem +++ b/tests/hwsim/auth_serv/ca-and-crl-expired.pem @@ -1,63 +1,90 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- -----BEGIN X509 CRL----- -MIIBBjBxAgEBMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQRcNMTkwODExMDc1ODM0WhcNMTkwODEx -MDg1ODM0WqAOMAwwCgYDVR0UBAMCARIwDQYJKoZIhvcNAQELBQADgYEAOTijPynY -c8ACRpu0+uIRjI6xIXDZqRubRvp/qrQVWtWHJWP2d6CbtaQVhZIfYFJLrLVfKyJv -WyzkLNdLw/l6rbVN5ctb+fByjjV6H99IExeYiGIuoXN++m8CTUqt77cim0TA1WkQ -bEwEY9aIN8zsXqioLvg5OBlWUfxnKmi2sQI= +MIIBmjCBgwIBATANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJGSTEQMA4GA1UE +BwwHVHV1c3VsYTEOMAwGA1UECgwFdzEuZmkxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIw +MDUwMjE1MDYwN1oXDTIwMDUwMjE2MDYwN1qgDjAMMAoGA1UdFAQDAgEHMA0GCSqG +SIb3DQEBCwUAA4IBAQBpgpd1hBcONRssjbezGJDE4WC4gSpW9ufS7OgzWXky9AIq +ea5engK/LCTn0GZVwRvuDkHn0H/dS68pFoQSnrbyS7Alz8oJf/T41vKgG8sxkfra +tvezWu7x8Kaz6QQuoxoGERZhudyNoPTUYKQpqnUjlz0088j+HqBuy6uSQsDlOXI7 +dxbXU25JvJlebJEeMxd/R+8SkVmXN6OR9RO+kkm0BIjhuUc2BOToxZhPj4PS7If0 +RO5S7WSgZOyg1d0yq/EMNvfm8gT5RioC0rceBlt5FIbjg+xn4VExyg73CbeMjC8O +CRblHL1o5GK7zHTyKFZ/KUdKIc9sdB/Eehcyvo+Z -----END X509 CRL----- diff --git a/tests/hwsim/auth_serv/ca-and-crl.pem b/tests/hwsim/auth_serv/ca-and-crl.pem index ba79339e6..4e8367884 100644 --- a/tests/hwsim/auth_serv/ca-and-crl.pem +++ b/tests/hwsim/auth_serv/ca-and-crl.pem @@ -1,64 +1,90 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- -----BEGIN X509 CRL----- -MIIBJTCBjwIBATANBgkqhkiG9w0BAQsFADAvMQswCQYDVQQGEwJGSTEOMAwGA1UE -CgwFdzEuZmkxEDAOBgNVBAMMB1Jvb3QgQ0EXDTE1MDYyOTE5MDU1OVoXDTIzMDYy -NzE5MDU1OVowHDAaAgkA2NPjpsvjzMMXDTEzMDYyOTE2NDEyMlqgDjAMMAoGA1Ud -FAQDAgEKMA0GCSqGSIb3DQEBCwUAA4GBALN3DQj9bNTuulU/o8MH2wAATisnDSYt -WD7W9S/26AgQDK2qySvp0+vz/Li0BMafbUd+opMu1smdyirjA6rDSjC8scaoVwUo -kY2fFo7qNuUU1N3T25/UCfGu3/E3ynrBZWiQoSCX/8NvY+pzEEf8ZOKt5837VKmk -EB1U3PrnNi7m +MIIBmjCBgwIBATANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJGSTEQMA4GA1UE +BwwHVHV1c3VsYTEOMAwGA1UECgwFdzEuZmkxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIw +MDUwMzE0NTY1M1oXDTI4MDUwMzE0NTY1M1qgDjAMMAoGA1UdFAQDAgECMA0GCSqG +SIb3DQEBCwUAA4IBAQCaoYj8yLx4eF+bupRl0YQ7h8MlZ3nFmEJFCXlRrPurWLC0 +tUC/8mMA4GJR6CUGUTZ70pfxKoC1Uca5uMJjNkfOJu0UAnMoiGk7W3Fqbbihigku +KU48HHieHoKBFc1+95I1TDVHnaDUkoDpT5W9J9yk5XHzJC7xZC411CM2tRZrKo/h +DRyooWZ5KPT+fthgzDvGSngbMXWumWYMv33PhiMrRlwQgxdt5ECXMbsIN9nY6Sz2 +RFbR9gVA3DwQ5TCMC3UFvHOEn5WcsEeMlNGdoTEb0LbGLnAIxnvHN626HeAgfruj +6Zec54XKEBnpwBlpfENL6eWJZ+NNVkedrSYdcVM0 -----END X509 CRL----- diff --git a/tests/hwsim/auth_serv/ca-incorrect-key.pem b/tests/hwsim/auth_serv/ca-incorrect-key.pem new file mode 100644 index 000000000..ae28d447c --- /dev/null +++ b/tests/hwsim/auth_serv/ca-incorrect-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCorkTzjidMmpUN +G78W6HDErNBhAgZVX6grzX+v1l9YxzUitpwgQP319PlMdHGDtY7E1h0kwlrmifsA +6p6Ejk1o4BYzLnZtcC/nhu8zjyCakDhgvpwbzL5m6TwVsJHyAhUsmdpOZOFH/yVY +zgmN1jnKi7MTnEUgXafts5ZJ9+yf1ju1G/pMynZpcayln2ffMaiAz7YGbefjGLKe +kjgOX82UfZqqvkMu6b5u+hSRRRexDEqsQZxOT/X8iO4VL6tWu8LVU+PJ+bKSiIfW +oNgqpzAddrv0kAW59u8RCjI/eyXceywsCcEQ2V2JwjL7p4Oil4yyyxHHAi5nmQ7Z +225UszcJAgMBAAECggEAEaLGysAeE8BFvS0deYOr5qQ61SmlB+AMcSf3JadAKMQL +Jin5gNXKt6B5QCkchSzCVIoeWe2IG3ppp9rf3/QQ29ox9//vmdmU6JwO/lEEk6Ro +gJTtNWrerVvNUGc5mxfkptkfHfsmIqTmfrZsAUxYlnisrGw2PgAMwql4GRu2va84 +8ZVUVG6+WNizMetsDU1ZuGLVYL7e7YHQG34xW898mdjojv0pJ/XO0mkJvjWMnVCA ++gQrct7k3G+59ap5p9hd/1kCtFqV4E6XkdqW4bP8W+jXPwyReAxLSibU6VYZVoAV +VYpkH0f6vDxn8mfEX4llSnOADeYlahO1QkCJE7xxUQKBgQDTCMCIfrmzrfMZo/s7 +68EjGjmBYipaXIZRtIptk//2FmWkm6VHKi5rWO01BUFXFoTEP3syc6BbWhdgRawi +iM4yS/83sogE8Zl8UKKAv1kcm+HRqrJ+o02b2glcqRmLQPOKcHjNgyWV/yZYbHX0 +BE8yMXlJDBVRcNkGWBtcDuEQ7wKBgQDMn0VBUZyv6ud7vpeLa2RNl7vMyvYAu+Vo +73lWbvwldAY8md4/Oh9ZWsznpSXer0Kx0cHgGfaZw0yzazg9P25RVOmXt01t21l0 +atz82CTAkWDKT7NdXscW5aAtmsCNIpNLcScU94F9jtNKidMB+FUGhcX1gvNQoFQo +kHp0cr9HhwKBgDYGxZOsLcqMO/JSgt0iS/26lwJCqWkcyt5cBBxtiVfs//SWTEfd +yqh8ya2LPOEYyMCdJ+MQqvr4I4foDluA/pjtz9bog94QJCUpV5Dya9PhLHzK4It/ +Lz05IrBwMjPuWusURDkI3DR8b8qvabsg502IUO6cg1CoPUdcgxScUo5NAoGAbExH +nUCSi1DqX0YKcxHNrnuGO+eXt9+6lYVZVPO8pB36Rwyw4gnjGanDFT8FAg0EYZTA +5dkX+V2yNKukwlXWD1m/oDq10lTrzX/ZokDLgtfuwGTaa6qD+Ixj8H8dNhV8m8sx +ghlVAZ0cGzFC6qICbkdS9JPwL1YL9MQy63rn3fUCgYEAj3kgp+ByZJjA4fEk+CkB +V6VL+3GKEq0oc910O4flUfIRO7bOh9XOcrPyhES9Kxj5hh8UP4OTiTmnQmtqEMq0 +K5/8FojDEnh3DmCC6ZDe79vYXQB4c2MRJg1DApZiklpsLJSIjO4ZQ4H3aQQEKCQe +DOd7egyPAkD7rmwgWBvF3Nk= +-----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/ca-incorrect.der b/tests/hwsim/auth_serv/ca-incorrect.der new file mode 100644 index 0000000000000000000000000000000000000000..75bb94d71aef7c11520ace6b9abb8a6d3e57b1a7 GIT binary patch literal 902 zcmXqLVs0{MV#->;%*4pVBocXhgNt=kSj!Fd(lQMd4dg+5 zW*&(U*WeHZT?Nm)O7HZdw8dySEmfw_s1pTVGsk&CH`k&$7=I+xFV>OQlk@=EU)dr@#?&4olJw$S($ z+Gp$6UyF}8ZmP6xj)KGAuU~%ploU2^?K^T!R^?FCv(DcPujaM%`DQ#2GuA81Ezp17 z_TIQ(Vb%nTgne_Q&+JQkX(PH};wL6iotd}%QXabhSB*Hw*?Z0MRQG1#Ij#z^%inIE z=K1~2{A<=*rGNRHD$6Wfvvhv?eZv(E=eM!tK7TB+Y2G9YzWB3KYG&|cQ1-Xpu zt5xq*>*#PE6u24NdC2JZ^5#X;dp4aGJkF$-K9ld}?Yxl9=A2B-j0}v60}T8OWP#Bq z%f}+dBElV3aPg?jz2%?P*^^%VG}?P?>fJza?8+*$NEnDUU{?T24zj{5tOm@CjQ^3t z9GIMdVa~`f|E|~@wba|yo=wf)i#%Ig=52rT%QX0B&EJP|8{X`3am{mAn{|bG;?p8k z+qTIMX3csu_0vn+aJ4ISTxRoce<rv20*~*%=`kb0gxx6VCRTs}TdoBIo1B=8F&C7bn(}jN7 z$~QjNiB?VSIUzH9@3VtSCrrfurdZhSj!Fd(lTKxn0eTP z^7Bg+oE;71#CeSj3``A-3@uG8O)R3sd5sMWOpFbnTxwX+#HfVqa7I=J<|amd27@L> zE~X|%Mut6K-nk^zC;2aIblY`gmE2#y3vWNVpH_`dt7@~Hcxr3n@;ZH+Jt1_%|C+$}78gHg-CA+x)wPf%@Arwj zNX;`Y2w(D!3~ zNztKx)ljdjS1+3M_tsY!E{VEsv^&MaP5J$alaE>$!irvahfGbfiW01R=iod~Oy|rq z*Dt%9G!8YJ>V%rjj1=4`dV%@iQuBxMyPc13*=c-Ff+9!Yr%?%#4ixk;5FASb$;9$l&<%@Zxg8NukfZy^OL9 zZw8)cTWa~rV8)JKf0d&qe~--&h%~AT|JuJR{p25)jLkJ4*IUK&_AmVBsL1z{V{x)) znu*uhb7>{+2H)>A%~T9)`mZZAp|&bTX~ElHNjIY|PoKuavfRDnR`51sQPH2b-mOu6 z$wUmE8JPEzC`FA+3Ic<1IJf}KQ zSZvnqlt1zAEw-2RZgbDuCfCYx@acg~x&5DJGFVBiW;*X$rFL+G{ILxee7^?)02Db+ Ak^lez literal 560 zcmXqLV$v~aVw}2wnTe5!iId^R<;TlTKR$ENfR~L^tIebBJ1-+6D=UM6z9F{(CmVAp z3!5;Lo2Mb40S}17#lu=|sF#*$C}6+`;xqHG2j%CNC^$PB$cghB8XK4ySsI#|7#bNx ziSrtPxaLqU=>|5=M|KkC#qWv{R6 z+II2zW>Kb{Ow5c7jEe&d{0wA)!63`WBE}-JW7569T@srO4$lw$Y#h7ggl3nch=Dvv zTA4+{K&%0~0#LBZ3bU{pFf%g#NA@r<5}1KLl{#OZ;NpBFlyByP&Q&`vR~v1QnNxG> zU(b~($KpOWOU7$PW-Rf)!=ksN@IbEhI>skEJ7%6a*R(H7oszR56QpXZL3Mur7VjQ4@e+iaZLY>cd|>;{aCEKQ7OfI=q>8aFO85o!v7#Uicni^X~8AKX{8#n>= zuxj%$GfA;Bu!z(tpFVxmHGTH;ONKw?Pj_v66}eoPMP$j}otDy#n^(Q=kiF8la;sp$ zndJ|eI2mqSe!T4T2n{AzwP3E z`!+G5=z4a=te2BIr`!{tBgAKXP9V5dBR~7`g%_uz)85VcT<4h6%>8wy%x)L``j4>% z7c6a;o?Oh%w%dSPlyUyES=~B^_HEJeuWMK#v2f?BV{`pI7e-A_3U_mRbZotUM(!^*96f!kvoWIb}K;Mwt zfRl|ml!Z;0$<1@3w_3fSrJ;d=iJ`H9k&$tfL8L*rffG;#t2Q4qlN2ihi^!RR0R0`C zw{6_#$De#~WmBrtBj$P*ksXun{q2(2Y;bsf=x5{DEhjX)97UKo8E#yDyzKPjv+@lL z68uI6s7CX$acZ@Bw0-AgWaMULU~X(=(6jxoUn6n(uIiRmKUe?H?YbzpTIq*h{EtqV zzv5k2#J8VK-rpR_=PjghT1vG(m2IY$xq!Vne~g6eg@#R2gq38F)^BrIL>D^mp&U3b0e0PpnFaL^8o5&gge}+q8^72O=4y)DZ-uJt5Wu@wylYd@J IT3>Vt025bmO#lD@ diff --git a/tests/hwsim/auth_serv/ocsp-req.der b/tests/hwsim/auth_serv/ocsp-req.der index 92ae0993069398c735a21af7586a91f086411e60..ebab4a025204c5f2b64df99a9c5231413a314f3c 100644 GIT binary patch delta 58 zcmV-A0LA}IOpq5fek04v#YJbE=h89xAIpld>RG1~1QewGxj7qwv#RTe9n^uTwGnX4 Qr{Mw#0NB&xrpx2aUst{!k^lez delta 58 zcmV-A0LA}IOpq5f%y3XIxU;sgzD^Hg!Ks2}LgE8|1QfWE-u;RgvoOP-Rr51lw8$xn QK@>;J4#icok6V24>jSLJ-4U7yeO-+q0q6{Jp!VR2&dRVpj zn3<$l8CXQ>luw^N>Y6_L`6a`j@~68tzKUEf%p$Vn?@mkU#?7liiEC`{JC9qThD$zI~gR zP;@=JV%Ez^om1|K&k^D?J|_^|s*#`l_`-|R(P{5yeXeuNY3BYqQ)ah|e*MSTf(w?m zOHVFlXWMPSEy_6m*{p7zL;JSq_}4Y8kXX3$)v>w$o(rR5lk58>$cunl&t_dZT2g(Fe zH`|9TaB%jEt``%vC~ovsaJO9R{W(t8V(Y}N^J+5}aj?9R+22w6T_-N)XTp@Vvn&8Y Cw6-$< delta 315 zcmaFGe4WY6pouYA}XS&Bn;e%5K2O$kN1U2^2ClXq>;$&_Lgi+klge zIh2J>n90p^qK8_&p{1dLfr+89fsv7MltH9HxPcQ;1*WYDwyuU{i^`L61gRXw_53kU;K|wnZM#) zSH!oUP2S%e$>%Mkaau~XK9y~zmbrkvIe(0V?1hF+Q-qx*T(bV!l#0mRuSw|Uyy_H&Z|ML4 diff --git a/tests/hwsim/auth_serv/openssl2.cnf b/tests/hwsim/auth_serv/openssl2.cnf index 121982bea..5c67c4f04 100644 --- a/tests/hwsim/auth_serv/openssl2.cnf +++ b/tests/hwsim/auth_serv/openssl2.cnf @@ -52,7 +52,7 @@ commonName = supplied emailAddress = optional [ req ] -default_bits = 1024 +default_bits = 2048 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes diff --git a/tests/hwsim/auth_serv/rootCA/index.txt b/tests/hwsim/auth_serv/rootCA/index.txt index 8575df948..7f364381b 100644 --- a/tests/hwsim/auth_serv/rootCA/index.txt +++ b/tests/hwsim/auth_serv/rootCA/index.txt @@ -1,2 +1,6 @@ V 251222193736Z D8D3E3A6CBE3CCF3 unknown /C=FI/O=w1.fi/CN=Server Intermediate CA V 251222193736Z D8D3E3A6CBE3CCF4 unknown /C=FI/O=w1.fi/CN=User Intermediate CA +V 300503151922Z D8D3E3A6CBE3CCF5 unknown /C=FI/O=w1.fi/CN=Server Intermediate CA +V 300503151922Z D8D3E3A6CBE3CCF6 unknown /C=FI/O=w1.fi/CN=User Intermediate CA +V 300503152010Z D8D3E3A6CBE3CCF7 unknown /C=FI/O=w1.fi/CN=Server Intermediate CA +V 300503152010Z D8D3E3A6CBE3CCF8 unknown /C=FI/O=w1.fi/CN=User Intermediate CA diff --git a/tests/hwsim/auth_serv/rootCA/serial b/tests/hwsim/auth_serv/rootCA/serial index b0de706e5..4c71e29e2 100644 --- a/tests/hwsim/auth_serv/rootCA/serial +++ b/tests/hwsim/auth_serv/rootCA/serial @@ -1 +1 @@ -D8D3E3A6CBE3CCF5 +D8D3E3A6CBE3CCF9 diff --git a/tests/hwsim/auth_serv/server-certpol.pem b/tests/hwsim/auth_serv/server-certpol.pem index 2c8111388..d01454264 100644 --- a/tests/hwsim/auth_serv/server-certpol.pem +++ b/tests/hwsim/auth_serv/server-certpol.pem @@ -2,12 +2,12 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:23 + d8:d3:e3:a6:cb:e3:cd:63 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server-policies.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -46,7 +46,7 @@ Certificate: X509v3 Subject Key Identifier: 3E:AD:0D:4D:7E:FA:A2:4A:D5:F5:31:EA:B6:B4:BF:83:B1:55:7E:C7 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -59,34 +59,44 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 6d:bc:df:42:16:4b:a1:22:ba:a6:06:f3:70:ce:f7:37:7b:4d: - cf:e5:37:cc:5d:e4:b0:6c:09:09:b1:eb:32:3b:54:ab:95:41: - ef:6a:0b:d9:ab:0d:23:8f:39:cf:1e:93:a2:f4:65:a6:ae:e2: - 75:35:63:7b:8f:45:08:e3:00:5a:28:a1:26:e3:19:0f:bf:08: - 12:2d:c0:7b:72:2a:48:af:a6:a6:82:1d:b5:7a:f3:ac:6e:0b: - 85:47:7a:54:2c:25:a6:38:68:4d:5c:80:6b:79:0a:70:db:aa: - 8a:ee:10:61:2c:e5:14:26:e5:52:bc:a9:fc:88:a9:6e:f9:ab: - 09:cf + b8:ef:8e:09:f5:67:a3:d6:5c:92:d2:55:f8:f2:52:e4:cd:ea: + 87:a6:aa:42:73:b2:b4:30:d8:80:3f:aa:d5:f2:65:32:b9:88: + 7d:f1:b2:c2:c1:fe:17:c7:76:7e:d9:7b:4b:1a:87:dc:1f:f6: + 57:0d:8b:5f:2a:5d:e2:7f:f4:8d:39:3a:a4:9e:9d:f3:c1:58: + cf:04:fd:72:40:c2:9a:ef:98:b2:6a:67:86:27:2c:f6:e6:dd: + b1:a0:20:b1:c0:cf:fb:00:43:1f:6f:ac:b2:3f:02:a6:87:80: + 18:74:6b:0b:26:07:d3:7a:72:1c:c7:1d:a7:dc:13:cb:70:ac: + 24:2e:45:9c:bf:53:de:ea:eb:50:4a:60:87:26:8a:28:4e:16: + 76:91:b1:b3:e2:4d:66:fd:12:60:ed:24:59:f4:f9:47:59:d1: + 4c:6e:d1:9d:55:d4:72:d8:c4:da:2f:b4:73:20:d3:7e:f7:9f: + 6e:99:b8:06:1d:5f:8c:18:ab:a3:a8:fa:50:52:50:e5:2b:c9: + fa:1d:fe:f0:ce:33:19:d5:38:e6:ba:90:c9:5e:e6:67:60:e0: + 50:16:7c:4c:08:89:d2:e2:fe:bc:57:0f:ef:83:75:ec:1d:f3: + 10:07:ce:c2:d6:30:44:f2:ec:b9:78:71:c2:41:8d:78:e4:d6: + 67:42:d7:f5 -----BEGIN CERTIFICATE----- -MIIDxTCCAy6gAwIBAgIJANjT46bL480jMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMD0xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEeMBwGA1UEAwwVc2VydmVyLXBvbGljaWVzLncxLmZpMIIBojANBgkq -hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA0qbvm71gY6F1rUvTb1lehPpkoGQkC3hI -/I1miy9uHUQrrsNtlLrLozS+C05HjVvZmaaoBwmHVbI3fkdnXHRfLIN5sghHtOxP -73VYZ8ZYTE9owRgahE14I0iaFDhuW0oS64bE90w4rGOnYfqzZHyJDin3n/h1w++Q -wnGWoatp08J0E8/o9wmY7Tp51sRGSZN4Oxalqd3w671Ep9xOzvenyT94CIsFxhcu -7t8RoPf1WIB2wjTvuXi+xFy+X17Xt82jEsTjdvxkhWRla9pcyThQOYly5SDvuQvM -MiY8eV5KjXiNat1zOshCJ0MN3QUfvITfVi1+mFCei3iw5/2oOQdXBRL8AO+J8D8D -9pNbsERXYWFHBWzEFphhuJMyRTn7u447hxhfOgdX0ZiJHYW3XuobUXmUXNj6vbp1 -AAPj9APNXNsWoay39JN+7Jqw5pxOXTy6ATLMcMpJPJL+0oiBndv0u4D+74lQ6oCV -vcT6KNjAhmE315krjrkGeJoIRBfaGTWXAgMBAAGjgdYwgdMwCQYDVR0TBAIwADAd -BgNVHQ4EFgQUPq0NTX76okrV9THqtrS/g7FVfscwHwYDVR0jBBgwFoAUuJLe/YoY -szDDn1XzM120yCmKQRQwNQYIKwYBBQUHAQEEKTAnMCUGCCsGAQUFBzABhhlodHRw -Oi8vc2VydmVyLncxLmZpOjg4ODgvMCAGA1UdEQQZMBeCFXNlcnZlci1wb2xpY2ll -cy53MS5maTAYBgNVHSAEETAPMA0GCysGAQQBgr5oAQMBMBMGA1UdJQQMMAoGCCsG -AQUFBwMBMA0GCSqGSIb3DQEBCwUAA4GBAG2830IWS6EiuqYG83DO9zd7Tc/lN8xd -5LBsCQmx6zI7VKuVQe9qC9mrDSOPOc8ek6L0Zaau4nU1Y3uPRQjjAFoooSbjGQ+/ -CBItwHtyKkivpqaCHbV686xuC4VHelQsJaY4aE1cgGt5CnDbqoruEGEs5RQm5VK8 -qfyIqW75qwnP +MIIEWDCCA0CgAwIBAgIJANjT46bL481jMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMD0xCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEeMBwGA1UEAwwVc2VydmVyLXBvbGlj +aWVzLncxLmZpMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA0qbvm71g +Y6F1rUvTb1lehPpkoGQkC3hI/I1miy9uHUQrrsNtlLrLozS+C05HjVvZmaaoBwmH +VbI3fkdnXHRfLIN5sghHtOxP73VYZ8ZYTE9owRgahE14I0iaFDhuW0oS64bE90w4 +rGOnYfqzZHyJDin3n/h1w++QwnGWoatp08J0E8/o9wmY7Tp51sRGSZN4Oxalqd3w +671Ep9xOzvenyT94CIsFxhcu7t8RoPf1WIB2wjTvuXi+xFy+X17Xt82jEsTjdvxk +hWRla9pcyThQOYly5SDvuQvMMiY8eV5KjXiNat1zOshCJ0MN3QUfvITfVi1+mFCe +i3iw5/2oOQdXBRL8AO+J8D8D9pNbsERXYWFHBWzEFphhuJMyRTn7u447hxhfOgdX +0ZiJHYW3XuobUXmUXNj6vbp1AAPj9APNXNsWoay39JN+7Jqw5pxOXTy6ATLMcMpJ +PJL+0oiBndv0u4D+74lQ6oCVvcT6KNjAhmE315krjrkGeJoIRBfaGTWXAgMBAAGj +gdYwgdMwCQYDVR0TBAIwADAdBgNVHQ4EFgQUPq0NTX76okrV9THqtrS/g7FVfscw +HwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDMp+EwNQYIKwYBBQUHAQEEKTAn +MCUGCCsGAQUFBzABhhlodHRwOi8vc2VydmVyLncxLmZpOjg4ODgvMCAGA1UdEQQZ +MBeCFXNlcnZlci1wb2xpY2llcy53MS5maTAYBgNVHSAEETAPMA0GCysGAQQBgr5o +AQMBMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQC4744J +9Wej1lyS0lX48lLkzeqHpqpCc7K0MNiAP6rV8mUyuYh98bLCwf4Xx3Z+2XtLGofc +H/ZXDYtfKl3if/SNOTqknp3zwVjPBP1yQMKa75iyameGJyz25t2xoCCxwM/7AEMf +b6yyPwKmh4AYdGsLJgfTenIcxx2n3BPLcKwkLkWcv1Pe6utQSmCHJoooThZ2kbGz +4k1m/RJg7SRZ9PlHWdFMbtGdVdRy2MTaL7RzINN+959umbgGHV+MGKujqPpQUlDl +K8n6Hf7wzjMZ1TjmupDJXuZnYOBQFnxMCInS4v68Vw/vg3XsHfMQB87C1jBE8uy5 +eHHCQY145NZnQtf1 -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-certpol2.pem b/tests/hwsim/auth_serv/server-certpol2.pem index d96af29e1..92c853da2 100644 --- a/tests/hwsim/auth_serv/server-certpol2.pem +++ b/tests/hwsim/auth_serv/server-certpol2.pem @@ -2,12 +2,12 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:24 + d8:d3:e3:a6:cb:e3:cd:64 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server-policies2.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -46,7 +46,7 @@ Certificate: X509v3 Subject Key Identifier: 4E:01:8B:7E:C2:77:94:E1:68:B3:C4:29:35:24:05:0B:DE:84:4A:89 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -59,34 +59,44 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 2c:96:45:a3:b5:47:2d:b8:0e:f9:e2:d8:5d:a5:0c:99:cb:3f: - 82:e8:81:2a:ec:c8:82:e2:c4:0a:16:b8:19:87:7d:b8:bb:e8: - e6:3c:bc:24:63:f0:82:98:23:1b:eb:39:89:01:b6:d0:e2:e0: - 53:67:14:a3:34:76:af:ef:4a:7e:50:bb:be:9b:64:14:dc:04: - 27:08:d2:9e:ef:16:2e:33:c1:fa:8a:29:0b:78:9e:e4:4f:c4: - 14:8b:cd:fb:cd:98:2c:d9:f9:66:e1:1a:25:80:b9:c7:53:84: - 80:b6:40:88:09:6a:1f:04:1c:fa:b7:c2:7c:90:8e:bc:da:84: - b3:e1 + 7d:38:98:e6:21:03:e4:1a:44:08:91:ca:21:31:5c:97:66:74: + 4c:0a:84:21:83:92:22:63:53:8d:06:1f:48:62:c1:e3:ce:e9: + 74:2a:63:0b:2b:f9:b5:d0:63:37:39:4c:b4:29:9e:98:49:48: + 1f:cd:bc:28:5f:81:56:ee:d9:d9:f7:51:6b:31:62:3a:a4:59: + 98:f3:18:3d:f9:c1:d8:71:6d:85:e1:67:0e:d6:cc:ab:61:22: + 46:f1:38:11:53:74:41:44:22:63:ac:e7:6b:12:b6:39:20:7f: + fe:e2:c7:aa:e6:80:64:d7:24:92:4e:79:fa:9d:41:75:45:30: + 4b:2b:ce:d9:b0:38:25:79:81:b3:c4:4b:60:a1:24:9f:ad:c7: + 37:b9:44:d5:02:7c:2a:05:7f:d3:f1:76:21:6a:67:d7:a9:ab: + e0:3e:4c:90:30:28:8a:75:58:ae:6a:98:39:b6:6c:f6:eb:9f: + c8:24:11:a3:33:0f:aa:30:05:23:ab:1f:4f:f4:55:f3:b8:6b: + c5:dc:dc:32:15:58:fd:cc:cf:ba:f5:9a:1b:4e:58:68:85:b7: + eb:b0:db:e9:a9:87:f9:b0:4e:c9:43:79:26:97:75:ff:d4:55: + 01:f7:c6:f5:21:56:8b:f7:f3:80:a2:f4:3f:50:2a:e3:60:52: + b6:5c:83:14 -----BEGIN CERTIFICATE----- -MIIDxzCCAzCgAwIBAgIJANjT46bL480kMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEfMB0GA1UEAwwWc2VydmVyLXBvbGljaWVzMi53MS5maTCCAaIwDQYJ -KoZIhvcNAQEBBQADggGPADCCAYoCggGBAOZQ0SgFJ2zUQtNCx8xTqWvCo6sgbxc0 -neQdMdDEaGVC1ei9qrjk6fbuLnXNaoz2jqqvbHzrNVBVscKz+KfQHqMzJmhAIBN0 -CIfvtjrxfz71f5NEdDeLw4mnul9COUoiIEBmxm93z1Q/BWHeq3H6n3htl0roYKAR -qmy6nURlGOjgj9Hf2pWrQSxjZfZCQuYfQqQcdCBJ9NSSDuO+O1X9OGh0OuTfmiuV -v+nROIsWJCA127jQFTAuL2okueHp57a1veYPWd3flZyrA7TFQoFIYcw8BheFY24o -y9eI0c5Ax/9hUay7uiPJQqd9Jw0eU5DPIj9X9f8aBQycehv74kdfRcvuiKWgVHGD -99PTxbyyfoWnsRrPkcuLObp8LJ2yxXnD4IBzBjBPXYFS4r9DVYVdZMSXrOktfjC1 -4VJQUwysJI57oleN/7EFuiMzpgijtDhC9lzZvF11lYL/TZrbVi8bONJRBSyQYvGO -TO7qG66qU3SFusbDwkswveAuyKx+JcwyXwIDAQABo4HXMIHUMAkGA1UdEwQCMAAw -HQYDVR0OBBYEFE4Bi37Cd5ThaLPEKTUkBQvehEqJMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0 -cDovL3NlcnZlci53MS5maTo4ODg4LzAhBgNVHREEGjAYghZzZXJ2ZXItcG9saWNp -ZXMyLncxLmZpMBgGA1UdIAQRMA8wDQYLKwYBBAGCvmgBAwIwEwYDVR0lBAwwCgYI -KwYBBQUHAwEwDQYJKoZIhvcNAQELBQADgYEALJZFo7VHLbgO+eLYXaUMmcs/guiB -KuzIguLECha4GYd9uLvo5jy8JGPwgpgjG+s5iQG20OLgU2cUozR2r+9KflC7vptk -FNwEJwjSnu8WLjPB+oopC3ie5E/EFIvN+82YLNn5ZuEaJYC5x1OEgLZAiAlqHwQc -+rfCfJCOvNqEs+E= +MIIEWjCCA0KgAwIBAgIJANjT46bL481kMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMD4xCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWc2VydmVyLXBvbGlj +aWVzMi53MS5maTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAOZQ0SgF +J2zUQtNCx8xTqWvCo6sgbxc0neQdMdDEaGVC1ei9qrjk6fbuLnXNaoz2jqqvbHzr +NVBVscKz+KfQHqMzJmhAIBN0CIfvtjrxfz71f5NEdDeLw4mnul9COUoiIEBmxm93 +z1Q/BWHeq3H6n3htl0roYKARqmy6nURlGOjgj9Hf2pWrQSxjZfZCQuYfQqQcdCBJ +9NSSDuO+O1X9OGh0OuTfmiuVv+nROIsWJCA127jQFTAuL2okueHp57a1veYPWd3f +lZyrA7TFQoFIYcw8BheFY24oy9eI0c5Ax/9hUay7uiPJQqd9Jw0eU5DPIj9X9f8a +BQycehv74kdfRcvuiKWgVHGD99PTxbyyfoWnsRrPkcuLObp8LJ2yxXnD4IBzBjBP +XYFS4r9DVYVdZMSXrOktfjC14VJQUwysJI57oleN/7EFuiMzpgijtDhC9lzZvF11 +lYL/TZrbVi8bONJRBSyQYvGOTO7qG66qU3SFusbDwkswveAuyKx+JcwyXwIDAQAB +o4HXMIHUMAkGA1UdEwQCMAAwHQYDVR0OBBYEFE4Bi37Cd5ThaLPEKTUkBQvehEqJ +MB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMDUGCCsGAQUFBwEBBCkw +JzAlBggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzAhBgNVHREE +GjAYghZzZXJ2ZXItcG9saWNpZXMyLncxLmZpMBgGA1UdIAQRMA8wDQYLKwYBBAGC +vmgBAwIwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAH04 +mOYhA+QaRAiRyiExXJdmdEwKhCGDkiJjU40GH0hiwePO6XQqYwsr+bXQYzc5TLQp +nphJSB/NvChfgVbu2dn3UWsxYjqkWZjzGD35wdhxbYXhZw7WzKthIkbxOBFTdEFE +ImOs52sStjkgf/7ix6rmgGTXJJJOefqdQXVFMEsrztmwOCV5gbPES2ChJJ+txze5 +RNUCfCoFf9PxdiFqZ9epq+A+TJAwKIp1WK5qmDm2bPbrn8gkEaMzD6owBSOrH0/0 +VfO4a8Xc3DIVWP3Mz7r1mhtOWGiFt+uw2+mph/mwTslDeSaXdf/UVQH3xvUhVov3 +84Ci9D9QKuNgUrZcgxQ= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-eku-client-server.csr b/tests/hwsim/auth_serv/server-eku-client-server.csr index e4a7a856e..5546903e5 100644 --- a/tests/hwsim/auth_serv/server-eku-client-server.csr +++ b/tests/hwsim/auth_serv/server-eku-client-server.csr @@ -1,11 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBhjCB8AIBADBHMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwHVHV1c3VsYTEOMAwG -A1UECgwFdzEuZmkxFjAUBgNVBAMMDXNlcnZlcjYudzEuZmkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBAMowHv0TagIoUZoOqR5yfudayMsMfoqZgY0FswmwqYbn -rkT64Mfu8xi0MWXjBW9mTuPkhYGbR39ftRYrsFmRnMVV09PKLIHO8CeoVN4OT9jw -Eb0LEFY4Jt+pOpUVk6YW7dIetLXAqGGOrhAE/eYmykoNkEu5rMmU8rFrl2tgJOq9 -AgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQA9gLu0fMZobrP6pkMTQFB/e8iDxeEl -LlTqNoZ1hMJ5CQHHB/CLK5D0D+oGrheb/7WA9kT9aMnk1KVFHFmNb0rGMHMLHIWb -PBb7d1xEFskl/iB1VshJX0DhYhkgwxuQzPF3fQCJV+pUf7hOI0tzY4yXgLykO5Us -qzQNeSKKXD3XbQ== +MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI2LncxLmZpMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0CP0gBK+SmRNr5mvUu+N9XOaGigrkujUkCU+ +hUefycS5ejUkhC8eURZm06wx6vFjpEzqJvD6Ycef8nRpangJxcmJdNttuse2sfBh +H+86HNXG/JVdmzfWW8s3k1ntUPJqogFcniKvOjHZ7uszSZNORu6de4aG2isd+fOi +AX0NVRw7Z+nJ+7ypUkxKIYVoUC/kBcE/4LOjJdRsLmF8ndXak7sZ/uq/8sj53N5I +VOH+1LWUWj8sK4yxbO86sNIMLBN1YduXa/pr+Z33FKo1cthMC6FcCMWH1OSHHWsK +UB+1Dj+7NovG4L0eGuEc8zekkWVMQ7SezBthaAm9HqthvcGRcQIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBABgknYle2ID7r8gu0VCYupOKsdU0CIfxqozbW2REuWnO +W5EYv/oma1ONr3DPr/pLfeCVxtqRLNBC4UAi6Pxsn4A8kxm93voZ2/9b+fvwfrqo +yKgo2X2+fn/k3IeRvKdq8o3frVzdBZmVv1irbrXeel7IRyjvG6nqwoT5jhCI4F8m +iAht0otWVPdyuIXmHsofB6wgkmFw8AqHIuKS2gl8zeByGkfO/bCFrv1G2rEacyjt +/pLaeI2VYZW5i+JvoAXSqAzV6xpc13Tts4MlQhSw8diE/NVsw7uBuJQaiE+vpgvm +1jmcmIttnkZmvkhvdW3P62OttNVGiyBfq/GVPhOfeKE= -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server-eku-client-server.key b/tests/hwsim/auth_serv/server-eku-client-server.key index ce2e5f237..42103e4ae 100644 --- a/tests/hwsim/auth_serv/server-eku-client-server.key +++ b/tests/hwsim/auth_serv/server-eku-client-server.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMowHv0TagIoUZoO -qR5yfudayMsMfoqZgY0FswmwqYbnrkT64Mfu8xi0MWXjBW9mTuPkhYGbR39ftRYr -sFmRnMVV09PKLIHO8CeoVN4OT9jwEb0LEFY4Jt+pOpUVk6YW7dIetLXAqGGOrhAE -/eYmykoNkEu5rMmU8rFrl2tgJOq9AgMBAAECgYAdONdBvIyVwz4IBhZrUCEHTxe2 -QRgI8CbJOwmlXOMjnFiTn67dNqvr5h89mpIuh5rfVSf2k3rB7hM+IRJb36/Ik7qg -GdktPSEIK/ktUcfofVLaLn+ehG7vXhkkB6juBR7jaXDZRBPvFM+TCtirlaZ5sQ0u -TbSw7m9NcFD2APxgAQJBAPIoCxZCJGpMvh+5ta8EJQVQKhJeMWmDlUQvscKTauWb -aTz0z+OMBGpZH7DWCTww4+/3fjqZt/TURuPSh0ZcACUCQQDVvyPTO3h3R5fig/zV -NV8E0/dCYH6kwsFk0AUIRbMHdaN3sEHWszKG9nTNyPyHhDo8i9jguSjkb9MwdgR7 -BJC5AkBB6/bAs3bYXVXwqwyzvWwamy0o3O2UrNaIvnck4h7arMkkZ/zkFCzriqGe -8VWIRkL3A6ggadJzWwqFYL2kwMzlAkEAhfEdFgUyXCy09PEYwtKLFI9vZlzpf327 -it0ACksDAS2qnhoJZ+0rQH+4eiv0c0dc5wwLf+cHxP5+LOQHsr8NoQJAcsRe+KyX -G0TLKZg/J5E+zJMH6M19BZ4BC32UIMTJWe1xzp+9XrCWflagRJMJ+DOWtHzu/Opo -Ty4OiT0uZUxcMw== +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQI/SAEr5KZE2v +ma9S7431c5oaKCuS6NSQJT6FR5/JxLl6NSSELx5RFmbTrDHq8WOkTOom8Pphx5/y +dGlqeAnFyYl02226x7ax8GEf7zoc1cb8lV2bN9ZbyzeTWe1Q8mqiAVyeIq86Mdnu +6zNJk05G7p17hobaKx3586IBfQ1VHDtn6cn7vKlSTEohhWhQL+QFwT/gs6Ml1Gwu +YXyd1dqTuxn+6r/yyPnc3khU4f7UtZRaPywrjLFs7zqw0gwsE3Vh25dr+mv5nfcU +qjVy2EwLoVwIxYfU5IcdawpQH7UOP7s2i8bgvR4a4RzzN6SRZUxDtJ7MG2FoCb0e +q2G9wZFxAgMBAAECggEAL7pO8p9Zq01c0wt2vJnZ/5LGn4DenQ1u0K75qy5FYcsO +jQtqmDUFyqpMYfV2bN11b9ODTfKsN4fDEaHIGnX0J7qTHozCmLX7Gsp4Ow5sUPhk +bL8De/hN2za6Q7u3Q3yTHxsY1do2PC36P2MHm7N/m5xT2GN8wMJqWUqYt6apS/6H +c2UkjhopRH17WhIEIvWLhZ6IYahRpaDk6zlYTwbVJ/0T/mmK/Wmpmr/aeSVkG980 +MQUHugdOrrkV8+WFxlzzpIRa+3XFmxXNOuhXemz23tS4JEBsD0gdesvoWuszqysd +1n+W5j+OpksiF1DFWSuMKFFqurd91yjOhAsM5ex1kQKBgQDnjTpvSBTMDGNGm8qo +9POjIqa/8zS0yzwYLB4/pzym5eaIEOAq+H0W+EU8h5zes3E1lGLKO/2iT3lWTxzo +E7Fq9I2AbzMSgyZiEJq6IfiLMRhh51sPTGX+KIjC44fdfofdTc2GNePsf/IP+JGy +DPv/8mU+j0heSwyLZJCSvoNdCwKBgQDmHe2z6MIb2Rze3vgJERIrTRfxyRjwKRUd +xI7QEe/fRjhlCNyzP9sQZzJFXNean4qNg0SOGy8+KjTgI+n9HxUTvLADxnVtey3I +G78JVu5QJ4onJ3iAlCSlY6exiY9ZQjI6akCC748t03WNLQXO6lUsopLZqOx8oP+M +84UFoNjA8wKBgERiTj6tQA8fHXat7gVGCmpEgpCv6AH4/6934BsWbfAwd4v5x+qI +5pCRFAmTV33h6u5S+3YUj4yPAhu+U6AqqLwYq22h6ahu+Tf/BWMxQzEAd936MMds +3bZZDELaZbbBdqiiIK+hXMXs53VWCNlXwljNop7+O/Y1HehQ8+2SvEMPAoGBAJhn +5//Iv46MHBfr2qC+oqb1F0+2nYKp4udlQCTETHc23bDkzq8VMrRJdL0FwXISCkSx +VN09Weu1LnHot1dCl8YLqRPHBAzvkSHAZqT74zhJB7Ho7WFTPHYha3YlIkC+m9+e +cX2GxfBW5bsLv5YMEz9NqS7pNz9PrhEfU9GndwdLAoGAJ4f7qIUTweLL+295Q/dx +lGlBzkTkfw0kiEEOgWwjXbox1NJnsfrneGvPgccTeMtimtkGk/vTUtIuo4EDwjJ7 +mcUnhXIgHGngx8bOzt4G3RGOLAaf1l+IcBhxqLJFhArDZYSVYMQ6vwwRuyXfO+I9 +4It3NqEusGrCV/ydOmKtXEg= -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server-eku-client-server.pem b/tests/hwsim/auth_serv/server-eku-client-server.pem index 2d299aed4..b44f82c54 100644 --- a/tests/hwsim/auth_serv/server-eku-client-server.pem +++ b/tests/hwsim/auth_serv/server-eku-client-server.pem @@ -2,34 +2,43 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:22 + d8:d3:e3:a6:cb:e3:cd:62 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server6.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:ca:30:1e:fd:13:6a:02:28:51:9a:0e:a9:1e:72: - 7e:e7:5a:c8:cb:0c:7e:8a:99:81:8d:05:b3:09:b0: - a9:86:e7:ae:44:fa:e0:c7:ee:f3:18:b4:31:65:e3: - 05:6f:66:4e:e3:e4:85:81:9b:47:7f:5f:b5:16:2b: - b0:59:91:9c:c5:55:d3:d3:ca:2c:81:ce:f0:27:a8: - 54:de:0e:4f:d8:f0:11:bd:0b:10:56:38:26:df:a9: - 3a:95:15:93:a6:16:ed:d2:1e:b4:b5:c0:a8:61:8e: - ae:10:04:fd:e6:26:ca:4a:0d:90:4b:b9:ac:c9:94: - f2:b1:6b:97:6b:60:24:ea:bd + 00:d0:23:f4:80:12:be:4a:64:4d:af:99:af:52:ef: + 8d:f5:73:9a:1a:28:2b:92:e8:d4:90:25:3e:85:47: + 9f:c9:c4:b9:7a:35:24:84:2f:1e:51:16:66:d3:ac: + 31:ea:f1:63:a4:4c:ea:26:f0:fa:61:c7:9f:f2:74: + 69:6a:78:09:c5:c9:89:74:db:6d:ba:c7:b6:b1:f0: + 61:1f:ef:3a:1c:d5:c6:fc:95:5d:9b:37:d6:5b:cb: + 37:93:59:ed:50:f2:6a:a2:01:5c:9e:22:af:3a:31: + d9:ee:eb:33:49:93:4e:46:ee:9d:7b:86:86:da:2b: + 1d:f9:f3:a2:01:7d:0d:55:1c:3b:67:e9:c9:fb:bc: + a9:52:4c:4a:21:85:68:50:2f:e4:05:c1:3f:e0:b3: + a3:25:d4:6c:2e:61:7c:9d:d5:da:93:bb:19:fe:ea: + bf:f2:c8:f9:dc:de:48:54:e1:fe:d4:b5:94:5a:3f: + 2c:2b:8c:b1:6c:ef:3a:b0:d2:0c:2c:13:75:61:db: + 97:6b:fa:6b:f9:9d:f7:14:aa:35:72:d8:4c:0b:a1: + 5c:08:c5:87:d4:e4:87:1d:6b:0a:50:1f:b5:0e:3f: + bb:36:8b:c6:e0:bd:1e:1a:e1:1c:f3:37:a4:91:65: + 4c:43:b4:9e:cc:1b:61:68:09:bd:1e:ab:61:bd:c1: + 91:71 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - C7:C6:EF:F5:61:D2:A0:08:81:6A:6B:44:2C:F5:72:F7:DA:DE:5B:B9 + AB:D2:88:CA:9C:44:26:89:2E:C0:B9:8D:46:DD:5C:69:02:9E:01:CB X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -37,27 +46,40 @@ Certificate: X509v3 Extended Key Usage: TLS Web Client Authentication, TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 1c:47:3b:a1:09:82:7d:f8:84:e2:b4:0c:26:5b:bb:f2:9a:62: - 80:ae:8e:fa:c6:4d:4b:83:73:b9:b1:d4:f8:61:5b:bb:ff:00: - e4:86:a1:c9:9d:a2:99:e8:70:6b:41:81:4c:12:22:74:60:54: - 8c:34:e8:01:a3:d5:4d:47:11:ec:39:71:2b:dc:b4:dc:2b:5d: - 49:df:49:bf:ad:de:e6:e6:6a:76:06:74:a5:50:9c:bc:46:ce: - a4:4f:5c:f3:0c:bc:08:c5:f7:a8:aa:bf:4a:60:d6:a1:30:82: - 6f:94:f1:68:09:0d:d5:94:64:e5:3f:ee:be:5d:ce:5d:91:99: - 60:c2 + 5f:6e:13:f9:af:c4:47:4d:78:19:5e:d2:bb:21:55:c3:4b:64: + 42:94:fe:37:7b:3a:4a:fc:42:f1:fc:b3:c3:05:93:46:39:cd: + a3:40:c9:90:47:a2:6b:af:d8:21:a9:1e:11:02:c8:84:e2:b2: + 8b:52:ad:30:49:e7:80:16:98:d2:0c:01:56:c2:f5:6c:a4:98: + b0:a2:af:6c:e8:6e:6d:9b:31:21:22:91:51:81:e1:f0:0d:eb: + 97:96:98:58:84:b3:29:a6:8f:d2:b5:ce:37:a7:64:b8:7f:fb: + f7:15:3c:c0:c7:2a:7f:bb:50:67:a0:5b:55:65:5d:1f:0a:90: + 10:16:c1:93:cd:a3:ab:8b:4b:9a:f0:e2:e7:ac:e6:5a:fd:bf: + 46:37:92:3e:f7:f5:d8:57:87:c2:88:cc:b1:40:06:92:d5:f0: + f2:3d:c5:d0:fd:48:5c:bf:bf:5b:da:82:11:55:6d:95:17:f2: + 43:be:8e:e7:f5:0e:d3:b3:de:65:ea:8c:85:4b:bd:4d:93:f0: + 6f:8b:2f:0e:fb:9f:cb:65:e8:72:68:92:43:08:1d:3e:1f:5a: + e5:1c:5d:7e:16:06:04:23:9e:c0:82:8a:a6:33:66:c3:3f:2a: + ad:1a:5a:90:02:56:3a:e6:45:d9:f1:02:a5:cd:16:63:03:04: + 42:85:1c:49 -----BEGIN CERTIFICATE----- -MIIChzCCAfCgAwIBAgIJANjT46bL480iMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNi53MS5maTCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEAyjAe/RNqAihRmg6pHnJ+51rIywx+ipmBjQWzCbCphueuRPrg -x+7zGLQxZeMFb2ZO4+SFgZtHf1+1FiuwWZGcxVXT08osgc7wJ6hU3g5P2PARvQsQ -Vjgm36k6lRWTphbt0h60tcCoYY6uEAT95ibKSg2QS7msyZTysWuXa2Ak6r0CAwEA -AaOBpDCBoTAJBgNVHRMEAjAAMB0GA1UdDgQWBBTHxu/1YdKgCIFqa0Qs9XL32t5b -uTAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp -MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wHQYDVR0l -BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4GBABxHO6EJ -gn34hOK0DCZbu/KaYoCujvrGTUuDc7mx1PhhW7v/AOSGocmdopnocGtBgUwSInRg -VIw06AGj1U1HEew5cSvctNwrXUnfSb+t3ubmanYGdKVQnLxGzqRPXPMMvAjF96iq -v0pg1qEwgm+U8WgJDdWUZOU/7r5dzl2RmWDC +MIIDnjCCAoagAwIBAgIJANjT46bL481iMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMDUxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNi53MS5m +aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAj9IASvkpkTa+Zr1Lv +jfVzmhooK5Lo1JAlPoVHn8nEuXo1JIQvHlEWZtOsMerxY6RM6ibw+mHHn/J0aWp4 +CcXJiXTbbbrHtrHwYR/vOhzVxvyVXZs31lvLN5NZ7VDyaqIBXJ4irzox2e7rM0mT +TkbunXuGhtorHfnzogF9DVUcO2fpyfu8qVJMSiGFaFAv5AXBP+CzoyXUbC5hfJ3V +2pO7Gf7qv/LI+dzeSFTh/tS1lFo/LCuMsWzvOrDSDCwTdWHbl2v6a/md9xSqNXLY +TAuhXAjFh9Tkhx1rClAftQ4/uzaLxuC9HhrhHPM3pJFlTEO0nswbYWgJvR6rYb3B +kXECAwEAAaOBpDCBoTAJBgNVHRMEAjAAMB0GA1UdDgQWBBSr0ojKnEQmiS7AuY1G +3VxpAp4ByzAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TA1BggrBgEF +BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8w +HQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IB +AQBfbhP5r8RHTXgZXtK7IVXDS2RClP43ezpK/ELx/LPDBZNGOc2jQMmQR6Jrr9gh +qR4RAsiE4rKLUq0wSeeAFpjSDAFWwvVspJiwoq9s6G5tmzEhIpFRgeHwDeuXlphY +hLMppo/Stc43p2S4f/v3FTzAxyp/u1BnoFtVZV0fCpAQFsGTzaOri0ua8OLnrOZa +/b9GN5I+9/XYV4fCiMyxQAaS1fDyPcXQ/Uhcv79b2oIRVW2VF/JDvo7n9Q7Ts95l +6oyFS71Nk/Bviy8O+5/LZehyaJJDCB0+H1rlHF1+FgYEI57AgoqmM2bDPyqtGlqQ +AlY65kXZ8QKlzRZjAwRChRxJ -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-eku-client.csr b/tests/hwsim/auth_serv/server-eku-client.csr index 72ab7903c..8fe7071e1 100644 --- a/tests/hwsim/auth_serv/server-eku-client.csr +++ b/tests/hwsim/auth_serv/server-eku-client.csr @@ -1,11 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBhjCB8AIBADBHMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwHVHV1c3VsYTEOMAwG -A1UECgwFdzEuZmkxFjAUBgNVBAMMDXNlcnZlcjUudzEuZmkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBAKOZ6eLhF2A7cDQadFxG47i9u6rJ8+77EjCgacN0OIA6 -uiNSx8Fqz7rdQePSaTWkpmBsMR+FvVZsewljzadRa4RAkHd+l2h7OLXEFTt0NzQo -unri14RTeHZNFre43wly54cmdCwEysXOKfW0ztso60VHQo/tiFqjI0mbe7w54QFT -AgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQBtsWMoDQr3miJluL8rnbsu7t7HhGn8 -BBJ393C6P8UHYJTlfMPfg+H2zfyrP68EV76lym5jmNOltZUv14joZjpYX9VOT+5r -e4wq697O7BDG7aBt2BR2BgYCMQiiAXisL0bOs6crYxapqCh3tyzkhxwOyqdqRO7R -+1BujmtweBGlBQ== +MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI1LncxLmZpMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZRggLjIYRiMAp3czMR00Re1O0ecOA87knT7 +6idFRIqaKk0QJY53zhoJyXMZ/txwNl6M+o9MhLv3cuSUT/xHKn2JkqMrWmmcyFoQ +OTJhfQp4GbQ266xM1q91ABROFS9fg+5i9ax7DIG6ogg2e/DvYzFi+4amz9o2g0SN +dSi25BDzMt2KbFvuT/EeUwsTfMe8954ygB5jPpJ1L8UhXvAqrOI05BeyNPfoKhKK +IbgD57bY+DK1/nFFUpjeuT1B9ZCldoPBGMpQXSxSi25Pp1u72OMUJXDe0cedWc8k +Rsf1bm+DZu0bHT5RBJRnZN9RIjzA4SQKN2rcaov9RVuWLQOsYwIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBAGDFw8louhTAswtYHa+aFvsSEB209lYFdHxn3wohbK1r +q3IPcuTiQdZR2jEllGVaXZC6eAkYO8iD+NL/iCteUivY6Jqrd5cM0IAzPLuNe89O +SSnPqUep59LObZUAsW/KaOB75xsLbm68fG2NmwOBB+8ZCRvQowcbY6nEAgaFM46V +UxOHr3ZdluhAyVIikmZLmXEbv5OaXZfc3PiifJIDgAmMf9ePjm6QZEQJ5RdBxlWT +IhU0rz9haagA13hXWurUCo8gWZoQqqCinjxLu0dV62kVCgq5Bk8HE4gvswJvCqME +TKEpPJBjmKGTeU1BbFWy6nrirsCVPybj841pMQkSWHY= -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server-eku-client.key b/tests/hwsim/auth_serv/server-eku-client.key index f2a99cd1b..a43976ccd 100644 --- a/tests/hwsim/auth_serv/server-eku-client.key +++ b/tests/hwsim/auth_serv/server-eku-client.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKOZ6eLhF2A7cDQa -dFxG47i9u6rJ8+77EjCgacN0OIA6uiNSx8Fqz7rdQePSaTWkpmBsMR+FvVZsewlj -zadRa4RAkHd+l2h7OLXEFTt0NzQounri14RTeHZNFre43wly54cmdCwEysXOKfW0 -ztso60VHQo/tiFqjI0mbe7w54QFTAgMBAAECgYAngwCtvtc6cqCCtPDtaGGPOKOe -d+/mA9U80UE551POBGD4LwH3gKhy5QUI1MR8JCvalca3akF0IfcFKYl9o3hnsZ73 -3wGzxM8BEf9wEVtVC2CTRVoIupleaEk3j8dgaUs/O54WkmAoHF1avXAMSGOUDxCO -Ggpn2tei78Csdj78IQJBANF7a7RaJsXh6xMI7hlrVrUsIbBvsBo1wbbGCwNRvgzL -I1mq1O+Go7Aao0pDK7sOUa86j6ECZ5pzqcdPaF22tJ8CQQDH7kTy6ERBbLFxs/Wd -YLDEh1GIGyGW10tuJTOl2R1TKSBXRzPAeI+jcC+AC00238p4MO899WOVeLvaERZa -IuLNAkAtlxXGp4Qett9JQj1HbPPu9A7U7km+OorRM2K8MzMQZ7lmz2YORxgiwHlf -NSU0TZZ7c1xE51gS5i9CAEcvdg7zAkAKIZfa20xCKHjhcyYaIIE0pErMY9uS4jwP -S9FPMS5cPXRHF/OWaEWXGaM+kNQL2NFQv+IPuLSgKWsThNQmIyhtAkEAiQq1HdN7 -3l8YhUuJtxg7nrh2s0V4UcSNOZxVf/85AKrTu1IfjdwmXFeoRB/y9Ef4h1bcXgzj -clIVhie7r0JNLw== +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCllGCAuMhhGIwC +ndzMxHTRF7U7R5w4DzuSdPvqJ0VEipoqTRAljnfOGgnJcxn+3HA2Xoz6j0yEu/dy +5JRP/EcqfYmSoytaaZzIWhA5MmF9CngZtDbrrEzWr3UAFE4VL1+D7mL1rHsMgbqi +CDZ78O9jMWL7hqbP2jaDRI11KLbkEPMy3YpsW+5P8R5TCxN8x7z3njKAHmM+knUv +xSFe8Cqs4jTkF7I09+gqEoohuAPnttj4MrX+cUVSmN65PUH1kKV2g8EYylBdLFKL +bk+nW7vY4xQlcN7Rx51ZzyRGx/Vub4Nm7RsdPlEElGdk31EiPMDhJAo3atxqi/1F +W5YtA6xjAgMBAAECggEAJ+QYX8qk0+ejC5pWsKp/7kQE8JQvCb55vq4aZu4xHPM7 +cwd/5VxudqQFSZhGYgVfr2mWE2NkrvHOCssRBDgmORFnjIFtF2osUISKNg1yOTrF +doPZW2v2Ux6QVIWPzkDMhS9wffmg54F1okXSQofoVIB4dVqaY6cRzQw9/ETj0wvz +JwSstS76VbTZSzXl/IMMiIlGLq2o4SVmTDgK5Uz8ouOIIzoVG4tQCjtAPCfu1pG9 +VYTCfE1gnGFx1bl3p1yoh468h1PqyYqDgo9heyU+aYk21v/Rm0ARj2TSkJcSF5Cv +Y3JUg1oaIMw7HxXEnkw+L3sqy9alGkJ33pbOAzva6QKBgQDO9H7ToPJysx2cO2/a +Jk7OvoyQ0AMNG7lNS4crG9SvL0SbxfDdif9yaDlasT3T18uTMuRJRo6vF8v820LY +HIdmBT6FxC+zwBRKnXMFtSrZIsl4zpOeHW2pOTM4So92K9NlSGOogQulzQyE8yeL +kHAJmnAevUMyxgQ/S8xpTJrzfQKBgQDM0blWZ91B4VvqP7MzdjPHI1yXt5miEY9P +ltTtTnmjFjvLweheoyYPW64tvxyRueEPNQB39BbYax3Zweg7TPng/lOMEwMG40dT +a4LBMK74r0OLvPfds6jSGnENmyNkUZhTCf+hgXOMeiXGqjFAIPQoA+23tNNaDPRG +emIjx69lXwKBgE4QmfqYPnwXpna1UObYBmgkJn/FhzEdoRNQByeystJ2IQola0sV +796nA+N68hiD0Q2wZ75gOBhCALdbueYtNMG9/qyUqW3DaaQPqkCf6w7G+Xpxaet9 +rEzl/7UfIuhvdalB2h3It60OIMfRtLwHesuUjvB5ceyoFxgNLokV1Wk9AoGANMRD +L1OK2RIqD+thS3zEUiV2EVAnsG09so91Q73X8IAl35SRPPBjOcmw0fBOd+yfYr+Q +41ZrHE5cXmFqZvyp06Ex/QBY40licsdb5FGagk8E49dHNEK414ggYBT7xTiQObR1 +uzIShrphSRFHpvHWdQiuEYnweV6lABM/fWBQe5kCgYBJWEJSAkyp8L4TIlt41ctK +MSjXuSwO1ktUYxQwIRZn/qcTxAAZLeE4Ow50Eoz7qtdMpn9/UdogpVpeZ9ZbSFSh +2OD15rQJWVWs9ftgV8Ny3LzCdchmIw4/pRFMkK1ECog6F2WecwYUspEWgfGTy50V +JyZlR6lQlgsLo0xLZJYyYA== -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server-eku-client.pem b/tests/hwsim/auth_serv/server-eku-client.pem index 5e39ec0c9..2e6afa287 100644 --- a/tests/hwsim/auth_serv/server-eku-client.pem +++ b/tests/hwsim/auth_serv/server-eku-client.pem @@ -2,34 +2,43 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:21 + d8:d3:e3:a6:cb:e3:cd:61 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server5.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:a3:99:e9:e2:e1:17:60:3b:70:34:1a:74:5c:46: - e3:b8:bd:bb:aa:c9:f3:ee:fb:12:30:a0:69:c3:74: - 38:80:3a:ba:23:52:c7:c1:6a:cf:ba:dd:41:e3:d2: - 69:35:a4:a6:60:6c:31:1f:85:bd:56:6c:7b:09:63: - cd:a7:51:6b:84:40:90:77:7e:97:68:7b:38:b5:c4: - 15:3b:74:37:34:28:ba:7a:e2:d7:84:53:78:76:4d: - 16:b7:b8:df:09:72:e7:87:26:74:2c:04:ca:c5:ce: - 29:f5:b4:ce:db:28:eb:45:47:42:8f:ed:88:5a:a3: - 23:49:9b:7b:bc:39:e1:01:53 + 00:a5:94:60:80:b8:c8:61:18:8c:02:9d:dc:cc:c4: + 74:d1:17:b5:3b:47:9c:38:0f:3b:92:74:fb:ea:27: + 45:44:8a:9a:2a:4d:10:25:8e:77:ce:1a:09:c9:73: + 19:fe:dc:70:36:5e:8c:fa:8f:4c:84:bb:f7:72:e4: + 94:4f:fc:47:2a:7d:89:92:a3:2b:5a:69:9c:c8:5a: + 10:39:32:61:7d:0a:78:19:b4:36:eb:ac:4c:d6:af: + 75:00:14:4e:15:2f:5f:83:ee:62:f5:ac:7b:0c:81: + ba:a2:08:36:7b:f0:ef:63:31:62:fb:86:a6:cf:da: + 36:83:44:8d:75:28:b6:e4:10:f3:32:dd:8a:6c:5b: + ee:4f:f1:1e:53:0b:13:7c:c7:bc:f7:9e:32:80:1e: + 63:3e:92:75:2f:c5:21:5e:f0:2a:ac:e2:34:e4:17: + b2:34:f7:e8:2a:12:8a:21:b8:03:e7:b6:d8:f8:32: + b5:fe:71:45:52:98:de:b9:3d:41:f5:90:a5:76:83: + c1:18:ca:50:5d:2c:52:8b:6e:4f:a7:5b:bb:d8:e3: + 14:25:70:de:d1:c7:9d:59:cf:24:46:c7:f5:6e:6f: + 83:66:ed:1b:1d:3e:51:04:94:67:64:df:51:22:3c: + c0:e1:24:0a:37:6a:dc:6a:8b:fd:45:5b:96:2d:03: + ac:63 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 33:16:9D:3B:17:15:82:2B:34:6E:38:E8:CC:22:BF:49:A7:5E:2A:2B + 32:9F:9F:30:24:73:73:CB:8D:53:3A:80:23:EB:5B:5D:4C:DD:06:01 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -37,27 +46,40 @@ Certificate: X509v3 Extended Key Usage: TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 96:f9:cb:e1:73:60:40:d6:85:d1:ed:a5:14:fc:c1:98:15:2a: - bd:02:dd:54:bf:69:ac:9d:b7:af:5c:62:b0:85:32:a2:04:27: - d4:98:98:d0:99:53:a9:03:88:33:fa:41:7f:a2:e8:ca:7f:6d: - f0:ad:7a:b2:49:1c:be:43:5a:dd:58:1b:bc:32:ae:86:10:00: - 30:44:f8:44:85:34:dc:fb:05:a3:8a:ab:f4:48:6e:f3:c4:6e: - c7:a0:39:82:bd:15:3b:0b:ea:78:10:2d:43:6c:73:c0:60:f8: - 1c:ad:c1:bf:df:6e:05:b9:db:3f:0c:3e:72:23:bd:56:f6:2a: - a5:e6 + 22:02:38:3d:90:2f:5d:54:b9:36:61:fd:29:40:c0:88:5d:eb: + 63:ec:b3:6d:9b:55:8f:10:6b:b7:4b:8a:3f:89:79:fa:52:87: + 8d:91:3b:2e:ee:84:ae:f8:2d:8e:1d:35:72:cd:b8:7d:9d:98: + d3:88:9d:05:c7:85:e7:1a:29:4d:cb:00:da:a3:21:a0:f5:f3: + 52:f5:80:88:cb:2a:4f:d9:9b:56:c0:37:13:61:74:64:61:fb: + 8c:25:18:9c:96:e2:f8:bb:e2:48:60:e3:12:d8:a9:d9:9e:93: + e8:cd:46:f5:eb:b3:17:62:66:d1:5d:ea:c2:09:d1:7a:34:d2: + e0:88:1d:7f:6f:71:25:70:50:d8:51:93:61:8e:70:da:c2:ba: + f0:44:81:be:81:54:d6:3c:da:a6:54:62:40:bd:d1:2e:ce:1c: + dd:29:49:ba:b5:12:7e:42:64:54:b2:99:93:60:67:6e:1a:63: + 4b:da:b4:96:28:90:81:c4:28:05:28:64:ff:c6:7a:b3:8c:68: + 12:e3:28:64:00:82:88:bc:75:46:d2:e7:f9:0a:93:4c:5d:c8: + 99:27:4c:40:65:0d:ec:b2:86:ea:76:e2:28:c5:77:6b:3d:fc: + 91:30:89:0a:0b:e0:d4:59:cf:30:de:5f:f6:50:15:5a:40:01: + e2:a5:39:cf -----BEGIN CERTIFICATE----- -MIICfTCCAeagAwIBAgIJANjT46bL480hMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNS53MS5maTCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEAo5np4uEXYDtwNBp0XEbjuL27qsnz7vsSMKBpw3Q4gDq6I1LH -wWrPut1B49JpNaSmYGwxH4W9Vmx7CWPNp1FrhECQd36XaHs4tcQVO3Q3NCi6euLX -hFN4dk0Wt7jfCXLnhyZ0LATKxc4p9bTO2yjrRUdCj+2IWqMjSZt7vDnhAVMCAwEA -AaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQzFp07FxWCKzRuOOjMIr9Jp14q -KzAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp -MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wEwYDVR0l -BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADgYEAlvnL4XNgQNaF0e2lFPzB -mBUqvQLdVL9prJ23r1xisIUyogQn1JiY0JlTqQOIM/pBf6Loyn9t8K16skkcvkNa -3VgbvDKuhhAAMET4RIU03PsFo4qr9Ehu88Rux6A5gr0VOwvqeBAtQ2xzwGD4HK3B -v99uBbnbPww+ciO9VvYqpeY= +MIIDlDCCAnygAwIBAgIJANjT46bL481hMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMDUxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNS53MS5m +aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKWUYIC4yGEYjAKd3MzE +dNEXtTtHnDgPO5J0++onRUSKmipNECWOd84aCclzGf7ccDZejPqPTIS793LklE/8 +Ryp9iZKjK1ppnMhaEDkyYX0KeBm0NuusTNavdQAUThUvX4PuYvWsewyBuqIINnvw +72MxYvuGps/aNoNEjXUotuQQ8zLdimxb7k/xHlMLE3zHvPeeMoAeYz6SdS/FIV7w +KqziNOQXsjT36CoSiiG4A+e22Pgytf5xRVKY3rk9QfWQpXaDwRjKUF0sUotuT6db +u9jjFCVw3tHHnVnPJEbH9W5vg2btGx0+UQSUZ2TfUSI8wOEkCjdq3GqL/UVbli0D +rGMCAwEAAaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQyn58wJHNzy41TOoAj +61tdTN0GATAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TA1BggrBgEF +BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8w +EwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBACICOD2QL11U +uTZh/SlAwIhd62Pss22bVY8Qa7dLij+JefpSh42ROy7uhK74LY4dNXLNuH2dmNOI +nQXHhecaKU3LANqjIaD181L1gIjLKk/Zm1bANxNhdGRh+4wlGJyW4vi74khg4xLY +qdmek+jNRvXrsxdiZtFd6sIJ0Xo00uCIHX9vcSVwUNhRk2GOcNrCuvBEgb6BVNY8 +2qZUYkC90S7OHN0pSbq1En5CZFSymZNgZ24aY0vatJYokIHEKAUoZP/GerOMaBLj +KGQAgoi8dUbS5/kKk0xdyJknTEBlDeyyhup24ijFd2s9/JEwiQoL4NRZzzDeX/ZQ +FVpAAeKlOc8= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-expired.csr b/tests/hwsim/auth_serv/server-expired.csr new file mode 100644 index 000000000..f06a33da1 --- /dev/null +++ b/tests/hwsim/auth_serv/server-expired.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI0LncxLmZpMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsHfxPmbn/AtR+dijri/2SnU4PtRHe9YkMrTI +2eDQpRL0iaeJAdlUQ86BSr3tFvN8wWc2i3NNIZHnS350xTsVuMZGfqmikcP1kLPP ++Qzrum/uuat3PQOenXcHv5dq1E222v02VCXjCSaJf6ERwfbcvlxXqOZFVz2YFAZy +rOnIgQY4nM/NCg54Tp57EMJhpUPvNBbfPOCjRHdIzb7kecsxOZ9T3aMOdlpsJF5W +NZuifbOeQvFhnOieHLiaEB4yKSHLMBbgAxH5iPKPBKXmp5xz4ZPYUS27RYOPtpNB +OUGEX0utACWRPRYK6/C4kuBcdWWFF9KA5l5moqTfxwh2M0nPHQIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBAIeunczvT7br/9Jk6zARkS7gZpAeRckiMMPFHD1HLiFM +ngU/PL4RD0TRF0cHGn+qJex7Ch97ZMHsGl0ECjXEL84UYnAdWGPddLv72XpeNX+d +f/QTWg9jVrZGspI1he6jN9JghZatKDEPYrXhFv0JbxrA4LoUzV2qGgh2ALpmP0LV +Xqje+tAoZbf8J7mba/Z2yqjJuJMxkOC+2cCUvN07+ndCGbixtzT2wZfPlVkp/af2 +HJyduA6qkLJWcrAER6jHaI3Cxq92u/H7D6Z++7v0vN8fV6inyZNadurUGY/VsIUn +jorEWeP7v1UKgLXXqBTdP5YA0Gi3O0dx7iLGalbHV9s= +-----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server-expired.key b/tests/hwsim/auth_serv/server-expired.key index 882d645f1..545beab67 100644 --- a/tests/hwsim/auth_serv/server-expired.key +++ b/tests/hwsim/auth_serv/server-expired.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANA7a4aeP7QOYEhU -Tcbci7lrddDkYPChQwuv+cR3aRGEUr6efXG0qoAf6+bAN95J9IVDrk1S8+swc67m -GAQUj8JjMKQM6/XWy/SvHU/WOkN4FDLe5YilNL6rmqSj3muE43iTHBwpx/xrzGjX -7sBd1z2RiIFWulQRnk7ogIPgbMrxAgMBAAECgYEArWSNSO+FRD2kVxY8HZeQkbm1 -xVgmkLj3x0elx79XMkrpS+lVs9UpFL+ABAmTe/pBLqcJAUJN8k3KRp066krk2QyQ -uilRkugON0vBJzLse9HryXilx0aWEVl3xZBKu1E3G4mcCl2LoPaASCZtjQXd/XCd -zdBR24qe123ofMpIo0ECQQDooUnHsruInBX9bRP11xXs7bI5298ZLCWHFAhGa/Tb -KvVXkXnzPVYhRi2w0Leqb0lht/4GX9MB06xcHs5TLvltAkEA5SasURCjxXc7svGJ -yP1s779DxYWoEBvGiRPygtyO40cnkOuupXKLaSkSuNUGag+6UxNzxGSUx9aiadse -oxOJFQJAL6y2SSXZBxMt8oUDPTO6O5cvGmp0G12Px1IUrBH92VjBdRPMUUw1tZYD -USRFL7mk6VDiz32d6dbukOaDVErhNQJASwnoAb/WMXLDHO0VtriudLAIbGVBTM0b -rYXXs1yweeKyJTXYghtJZc1qcRZpPFAcLto+3cAmLG6vzsRPew2JpQJBAN8krD5c -RYAGuXtslPkH7BWypJXI+K3brZkKBiyXVB/fbwnpXI1KTbzeBSly60JrjuymY9+X -NKs5A4HSiCtQjSk= +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCwd/E+Zuf8C1H5 +2KOuL/ZKdTg+1Ed71iQytMjZ4NClEvSJp4kB2VRDzoFKve0W83zBZzaLc00hkedL +fnTFOxW4xkZ+qaKRw/WQs8/5DOu6b+65q3c9A56ddwe/l2rUTbba/TZUJeMJJol/ +oRHB9ty+XFeo5kVXPZgUBnKs6ciBBjicz80KDnhOnnsQwmGlQ+80Ft884KNEd0jN +vuR5yzE5n1Pdow52WmwkXlY1m6J9s55C8WGc6J4cuJoQHjIpIcswFuADEfmI8o8E +peannHPhk9hRLbtFg4+2k0E5QYRfS60AJZE9Fgrr8LiS4Fx1ZYUX0oDmXmaipN/H +CHYzSc8dAgMBAAECggEBAJjiMQUJDm6UOB8nCxd7wfrb9zCnpI6rBY1QhroMRXbe +JzGjDdWmPZTJMcZZKTC7HhhInT7PU8GDsEj9c5j0CWudi7FsscVrajJFNibkhM1u +7/m3jYQ0wJRXbUUVn53y/jpXKVxZvopM8s658rKCdtgNFHzlkql0WW7v7yXTHLx6 +AM+559Y+LZZ3jAndrHdEpM1vCAG0VE85Ycv+1lBqlFEOthrWDL16UX6BBK5mjUsZ +QtSUzn8q5OfX8DVKOlZNA85+kdJAK2ysx13DApmFr9unvH0kKfp06sFMOLbV09dF +kJSNmzWGthVU5oo9rln7L2ctLzjwYfYCC2x36WREI5kCgYEA29J6FYwptBCWBiep +UnRmGD/9UWr77jyNfYSZpYq5WZZ5swHTdkIeBu6f/u43adLjqcggsWtDZKEMbaZG +pE3K+8NRUvw2NOt0oBVtYvSyAuDLlOroA3CcEu8089dnojSnENQe6vSsUh54qe5i +LS7VdJGv2LyT7828Df0JhLL93CcCgYEAzYLk9DTZ5rIQ7AIhyW+IoduQUWhnfS/j +usueMnvkpuYf+mVtbl1Xn8HiJPaiLrjwu/VSE5zim1tHEXRRhw4euG6p5s1V28S+ +mSOHr+jgLFZQ2hRKZKaV/8ayWJYYtLQ6E7n61mwvoeXUfOnRrP2/drWjJ9MUYt+/ +oTfS7eATERsCgYBfIYVoEdJydMMYQs3KO0l7sSWluJDylw38hgggVhrEpJRiXaXw +BckM4vQm1Vzx1Sxla5CKd4sg33mLcmwb6vavYeWt7ixfVo6QQPWn35GyISq5dbeW +1YMVxqO56zyUPAkZBVOkBuMUXs+Fav7d4ujJm8roFyRGoViDDUCzRusJ/QKBgQDF +z0zjRg/K/vBMyoyM4D8qVDVoNk8Ob08KmDzwKNJgVzbGhGQ9i7jwu+UZYQ+gW0DU +GgBjgmmX0dbpFQX4Mf4d1d7RmikfPROcQVe0WTmVU4vFLSyiDrpolG9L10V2gdc4 +75ViWIXMlnTduw2oLiHheFnP1ltUBDvmSN5NOpX/qwKBgQCmAR9C6xL68ZFO6HR1 +wswgZEDks4Da1ibWm8uw54YmdT5nG8CakhGwzLcS0Np3xvQ1WgUA1ic2XnHXHwuI +piU5MbI8+O0hdPQLG4meuZeWINt3QDH5OzuwPCwhZCZkrpG9IfrIAaaaltKHaLMC +bBd+f4vilJMr+V+VPOKFoUBibg== -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server-expired.pem b/tests/hwsim/auth_serv/server-expired.pem index f279aae62..308d57fad 100644 --- a/tests/hwsim/auth_serv/server-expired.pem +++ b/tests/hwsim/auth_serv/server-expired.pem @@ -1,62 +1,85 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162826 (0xd8d3e3a6cbe3ccca) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cd:66 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Jan 1 00:00:00 2014 GMT - Not After : Jan 2 00:00:00 2014 GMT + Not Before: Jan 1 00:00:00 2020 GMT + Not After : Jan 2 00:00:00 2020 GMT Subject: C=FI, O=w1.fi, CN=server4.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:d0:3b:6b:86:9e:3f:b4:0e:60:48:54:4d:c6:dc: - 8b:b9:6b:75:d0:e4:60:f0:a1:43:0b:af:f9:c4:77: - 69:11:84:52:be:9e:7d:71:b4:aa:80:1f:eb:e6:c0: - 37:de:49:f4:85:43:ae:4d:52:f3:eb:30:73:ae:e6: - 18:04:14:8f:c2:63:30:a4:0c:eb:f5:d6:cb:f4:af: - 1d:4f:d6:3a:43:78:14:32:de:e5:88:a5:34:be:ab: - 9a:a4:a3:de:6b:84:e3:78:93:1c:1c:29:c7:fc:6b: - cc:68:d7:ee:c0:5d:d7:3d:91:88:81:56:ba:54:11: - 9e:4e:e8:80:83:e0:6c:ca:f1 + 00:b0:77:f1:3e:66:e7:fc:0b:51:f9:d8:a3:ae:2f: + f6:4a:75:38:3e:d4:47:7b:d6:24:32:b4:c8:d9:e0: + d0:a5:12:f4:89:a7:89:01:d9:54:43:ce:81:4a:bd: + ed:16:f3:7c:c1:67:36:8b:73:4d:21:91:e7:4b:7e: + 74:c5:3b:15:b8:c6:46:7e:a9:a2:91:c3:f5:90:b3: + cf:f9:0c:eb:ba:6f:ee:b9:ab:77:3d:03:9e:9d:77: + 07:bf:97:6a:d4:4d:b6:da:fd:36:54:25:e3:09:26: + 89:7f:a1:11:c1:f6:dc:be:5c:57:a8:e6:45:57:3d: + 98:14:06:72:ac:e9:c8:81:06:38:9c:cf:cd:0a:0e: + 78:4e:9e:7b:10:c2:61:a5:43:ef:34:16:df:3c:e0: + a3:44:77:48:cd:be:e4:79:cb:31:39:9f:53:dd:a3: + 0e:76:5a:6c:24:5e:56:35:9b:a2:7d:b3:9e:42:f1: + 61:9c:e8:9e:1c:b8:9a:10:1e:32:29:21:cb:30:16: + e0:03:11:f9:88:f2:8f:04:a5:e6:a7:9c:73:e1:93: + d8:51:2d:bb:45:83:8f:b6:93:41:39:41:84:5f:4b: + ad:00:25:91:3d:16:0a:eb:f0:b8:92:e0:5c:75:65: + 85:17:d2:80:e6:5e:66:a2:a4:df:c7:08:76:33:49: + cf:1d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 75:B0:65:1F:2F:A9:BE:D7:D0:EE:9D:42:8F:8B:13:5F:D0:AD:13:7B + 21:B0:31:C6:14:D4:BD:5C:DF:70:24:51:34:9E:93:F5:18:B3:1C:A1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ X509v3 Extended Key Usage: TLS Web Server Authentication - Signature Algorithm: sha1WithRSAEncryption - 12:e7:8a:e1:3d:d9:fd:36:ce:71:66:b3:74:48:c1:f0:38:75: - 30:56:c7:2c:9c:0d:da:d0:68:19:47:a2:37:38:0d:db:4f:f9: - b9:cc:0d:25:b1:35:ed:df:19:8c:4b:bd:f0:08:11:13:4b:e9: - a7:d7:50:2e:fa:7a:16:e1:4f:0f:5a:b4:42:34:ff:43:08:5c: - 3c:04:6a:f8:44:8d:f6:e5:a7:82:38:60:d0:5c:d1:59:f9:02: - 84:7f:da:ae:6c:e9:55:c8:f5:0e:da:55:70:f3:77:48:30:1f: - ab:60:39:a1:77:49:29:e3:51:54:62:72:c7:78:ae:17:14:c5: - dd:2c + Signature Algorithm: sha256WithRSAEncryption + 89:4d:ee:04:3e:50:fc:a2:6e:4c:3e:4a:9e:3b:9c:2e:74:29: + 06:86:1b:bb:96:01:70:f7:46:21:b4:ef:6f:73:93:31:bd:58: + f5:2f:40:61:f1:53:86:20:75:cf:0e:75:70:2c:94:b8:c5:4e: + ec:24:0f:42:d6:8b:80:b9:fa:b5:48:83:d6:cf:c8:47:3d:09: + 50:11:4a:5d:83:c5:41:8b:4b:4e:1e:ff:96:95:f0:14:7a:7e: + cd:a6:4f:ce:0b:37:e8:f2:27:a2:72:e2:6b:18:d7:f8:86:f0: + 14:db:4c:c5:8a:76:9b:fc:55:15:49:3f:eb:df:5c:c7:7a:64: + 86:70:44:97:7e:ba:83:39:25:3b:23:8e:dc:b3:9e:59:cb:e0: + a2:ac:7e:9f:d2:60:91:a7:de:a9:a9:30:e1:97:81:e3:13:91: + 75:68:08:11:e0:ca:f9:eb:39:28:72:ab:8c:18:d2:3c:2c:cc: + 38:e5:73:1a:4e:7f:e6:74:25:8b:a2:40:45:59:28:b4:ec:ec: + 5f:c9:f5:6f:ab:02:03:70:0d:11:9b:62:df:73:7b:e0:c6:c1: + c1:ee:da:69:9a:91:a3:6b:2b:15:d6:fb:e4:35:38:86:fe:ac: + ad:77:a5:a3:03:a5:9f:f4:e7:34:91:83:9e:5b:1e:88:e1:48: + 5f:15:d8:de -----BEGIN CERTIFICATE----- -MIICfTCCAeagAwIBAgIJANjT46bL48zKMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNDAx -MDEwMDAwMDBaFw0xNDAxMDIwMDAwMDBaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNC53MS5maTCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEA0Dtrhp4/tA5gSFRNxtyLuWt10ORg8KFDC6/5xHdpEYRSvp59 -cbSqgB/r5sA33kn0hUOuTVLz6zBzruYYBBSPwmMwpAzr9dbL9K8dT9Y6Q3gUMt7l -iKU0vquapKPea4TjeJMcHCnH/GvMaNfuwF3XPZGIgVa6VBGeTuiAg+BsyvECAwEA -AaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBR1sGUfL6m+19DunUKPixNf0K0T -ezAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp -MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wEwYDVR0l -BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQEFBQADgYEAEueK4T3Z/TbOcWazdEjB -8Dh1MFbHLJwN2tBoGUeiNzgN20/5ucwNJbE17d8ZjEu98AgRE0vpp9dQLvp6FuFP -D1q0QjT/QwhcPARq+ESN9uWngjhg0FzRWfkChH/armzpVcj1DtpVcPN3SDAfq2A5 -oXdJKeNRVGJyx3iuFxTF3Sw= +MIIDlDCCAnygAwIBAgIJANjT46bL481mMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDAxMDEwMDAwMDBaFw0yMDAxMDIwMDAwMDBaMDUxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNC53MS5m +aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALB38T5m5/wLUfnYo64v +9kp1OD7UR3vWJDK0yNng0KUS9ImniQHZVEPOgUq97RbzfMFnNotzTSGR50t+dMU7 +FbjGRn6popHD9ZCzz/kM67pv7rmrdz0Dnp13B7+XatRNttr9NlQl4wkmiX+hEcH2 +3L5cV6jmRVc9mBQGcqzpyIEGOJzPzQoOeE6eexDCYaVD7zQW3zzgo0R3SM2+5HnL +MTmfU92jDnZabCReVjWbon2znkLxYZzonhy4mhAeMikhyzAW4AMR+YjyjwSl5qec +c+GT2FEtu0WDj7aTQTlBhF9LrQAlkT0WCuvwuJLgXHVlhRfSgOZeZqKk38cIdjNJ +zx0CAwEAAaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQhsDHGFNS9XN9wJFE0 +npP1GLMcoTAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TA1BggrBgEF +BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8w +EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAIlN7gQ+UPyi +bkw+Sp47nC50KQaGG7uWAXD3RiG0729zkzG9WPUvQGHxU4Ygdc8OdXAslLjFTuwk +D0LWi4C5+rVIg9bPyEc9CVARSl2DxUGLS04e/5aV8BR6fs2mT84LN+jyJ6Jy4msY +1/iG8BTbTMWKdpv8VRVJP+vfXMd6ZIZwRJd+uoM5JTsjjtyznlnL4KKsfp/SYJGn +3qmpMOGXgeMTkXVoCBHgyvnrOShyq4wY0jwszDjlcxpOf+Z0JYuiQEVZKLTs7F/J +9W+rAgNwDRGbYt9ze+DGwcHu2mmakaNrKxXW++Q1OIb+rK13paMDpZ/05zSRg55b +HojhSF8V2N4= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-extra.pkcs12 b/tests/hwsim/auth_serv/server-extra.pkcs12 index 7c963a642a8406d2be7a53aa66c75529d7ae5e98..47231039647a4193fb4edde168a961ae3c761960 100644 GIT binary patch delta 3380 zcmV-44a@TS651L-FoF$M0s#Xsf(;x72`Yw2hW8Bt2LYgh4Gjc>4GA!U4FxcQ2cHHB zDuzgg_YDCD2B3lmkT8M=i~<1wFoFk#kw6`PN%p=x{hoet0s;sCfPx2D*sXz(g8<0y zC~Vz+J_;3Y+mLW++v_XOP%fUm0ET~zNxb)`&j-Rn^hMYd?AfgwNu*0|#I;%#7(WFr z40YC|$THTK3mDUQzVq;p#4ns5%(f|3hT*1x~^d8w}F6${L#T;f|;+s6FHvC0cd^wyFpr}zeW4(t)B!222PSDM8 zjTRbwRAq95zT@W-ka+hDa#G;9h#lDL6s1%aO)CZqZP+$q_+%B4!);fCtocxnLhn_% z04nK?rr6sCek3guhy9SE5B)MGv=6s`>$Dn0{KW5QQvgW20X1@|#HXwr{JiNPi`Uu6 zL;1jLe~C!A<1_o@DJKeTxoC2K8zGRDnirNh4nuOU94X#=I;OpVp2ROx9s&WZ7;UG3 zOI|+qjSDpfc>Z>=J^X1!9%xSXPIU)_J?#b$cvX6zoGangKlw9RndcOL3STFGhozyN z@iB%B)(+|w*;KGlkiL$zkBm`o6dv$8Y+r0>1xwYI_-ntA*LJh%6-Y}ZVN(3X2&WOY zqIb@~?u|FHUk#|JMm*HE$}#E}?wdXKr`N#qSo`t2-8iIiv9e6HGCa6d;UM+Ub(rZH zO;nrPO+H+|F|UIfsimk7+6G&HX9>9OJcxYS&9-@;jj(18xau(q#63zxEXfcAHpc zI&Y704$y)UYr*1nX$x0gy&jFSas0&FG7Kw?@t!aa|1;OmHcYJis6miagHv~L=@%{Q zuYuJ3J9>jzS$$lCEDXNB)Z0NT#tJAo6=r9NAK40RNaRo|6_fk~@@#gA3Xl)6EX0ou zp6f)TMIRjUvQ0(v7$5b2!3Gdp6IPbo8CltOnH8sTG>d|xs=XJ`y7#!BtD3=>?!73L zWZ5@yGl6VR9QkI4Z#QO~@_``TA_}(%lJ0gt$55d$$qiMhIy`(XkRcF6am{Hl^WD!E z3^orJkZ?ogOd&9kK8G+0DpNk`XxM(*ryqLG`%m-$5}OmF&~Bg@THa`PwRP%=e>awIfdHPtk~AQp@brDF6~ z$T|_$L=EJ2OA9dF9;)k*7}h{Au(4}&lz-AqIg;v(c-0=Neo|iWC$fuZF|V{=^XW)M z=U4dg;sQb1^j#mQvh@o0pPViK6o4q z42*0N6=?+=YO7|?<&E97$ghHSM0`A68=Ros5YkCwc7Nmp$yh^>7i4$u=CCp2%W3Q++{~sq}KqNpPvxi$O@k{~`8g#7gHXf~qx@9{hI z13uV=Y!I&}|@O@&>e=h>wG>$S?6PQR}>PQWF19ZcxJ7&Hc}0 z{jQpS;$6$7SIxS1E6cJ78&;U$0XC_#QT5GsJu85PQu%pgVu2*02liO6xezFmj zu%H{JDb=s~;@PbI&!ygT_4QJq9u=xBoW`)M9o&WRnE7th$iG>rmQ-Y==~kdFd>TJ( zDdGA9TWOT#74|J+P`_m)R#W7&WEMA?l|qnzVKZ~G7i!5z8(Sw+n%<~u7oBX&f=dwK z*U?89aB%c0iBzo#=nj8yf2}pR$(!RGA{%T{L3cvr+(?~cZVb8KG2HvjCME)^KT7b= z8$#BTmbJn@ds;Yu>%=Jqd$2_230|zQUNm}Vlu9Ri?3nsY*c(Ln1`=|nRu!j}(i;9n zW%5r$oZ}V zS)AdTE-BviV{EcCb)c*;cK~XzTlyQ6+*6)>3|iBD@Klg#Fo)8SL=AKTJ89{EtVRvZ z0$=$Kch7KAVKi8p0Zlg}B6M!13tkwa&S}r!Tq#Qx`>Y5TanqRcxBupwL|ENTwx@&z zNjZVGxt-88l#s-SmYj`3tZvbWCVC9Z$VNhwCG@+e{emMzuJXE=VyoGwkmmMar zNy)_!%Y=cO2vwHa<2_QCi>JrGnw0f?H*er_}E0=&S z6u9n;XEz2J&~+7yc}BB;vgKya;HBBE1HiFp?J}+J5`M zncV`|5Uy0qISAT|jZ~A`MX6y-fj6JWMaGHxYTSZl$a|km2~|^n#9d@gnaPduh!@-P zr?fp*+3ouSNZpdWwJv-X(wDAe#G-L+(a6EvP%z`8;iJ}oEaO`#uvgV^D#ApGjxW4Y zvX}Rqc=Bbz=k=XCXZ?>-c4V40r2AMzk~UsOzalhfAEnkhS!bnoOhE4P)W$gjHc1|} z!DdLU7u(~-6~QbxJc~L5k8;SBajRGf=qYW5C1Ppk&;wUi)MTH zvgXz}x@M0vqJ*&=yoJ_KXh-%NGC>g@p-#f1MnyMz0Uaz+oeTj?Sve9f_DghF6r`tG zst>}HKBavC&#rh-O3#w^td&ql-Rn$IGSNmW{O7;^+pbK1;Cy8GY>QKk73K-utddb0 zK*aU!ZNgshBX@Gr0{!S@zrV6%Ab6oHgEi6jID=RTMBb5ZMn-t(=7o!@h81QHV$FbN zfxn32ZO{M?6py3xECS=go*v);clL~#A*b3mH)rL;A6wxWw_=sFReC+(PJH+vFadjAGRwXpC=n#yWr%dgD)2f`RY3*27+n{6@R))H8r>x}S=;LuA$ zibj2LCPR~iFflM8FbM_)D-Ht!8U+9Z6k#=QXD%7Wa>?H=J`mRFdW6pd8w3cN`uHE> KzK9P30tf&XBwA(w delta 2380 zcmV-S3A6Uv8u}7IFoFqo0s#Xsf(bkZ2`Yw2hW8Bt2LYgh2`vPI2`Mmw2_-Os1_uTS zDuzgg_YDCD2B3lk_%MP6^a23@FoFf`kw6`P(;PJ}jT!Q}0s;sCfPw|UVAJf&2Ndk7 z!J~>UjmR)k6n$Q8t$S(f&&XTc=Wg8kO_q4gstY;cqRV^`3;mAD%^EJ|aZ&OpJ7xCP z)soS{MmPiV|ImjE*LXtkl*D*tjogybyD2}9y(;IY${xsLms8tHNv%Z(41RjYl?Fk#7N55~vqub8_m0P${grjP zcAQ9H3k_30YJ7bUMAvyZ^%$Ky7-XFX(r2-pb9%%FkIYJEKVc|Cgav&lW2&}f-ZY`{ z=7aLFc56!VbiGi-82<`{7nXRo%GeT58Q}e}&1FX`bWa}QQa<^73py~V^fh{a=L&7} zwb;-z*pgG%FW@D7jUE>F{tLv$B}(PN(9N~@LF6AiCm{+mto!mr7@;z}-S{gGg+q!^ zwQ&=R$3|;3bdL@_M@X3~LO-CGlIS9d2Gj^!lj1t@NVhUvpWDWsbs`U$rTZ-c$nF8v z-Zp9zXC-F94hemoMB1@zLM=3Z<&MbMK42{ZNg-`E^9Upy!y%#qI*ACzG--qJ(iPKD zdCSaOV1wzp&WqXAEepV5qOPrHcL?BY%gLh*+-<3z!#9U)#PJ4;HOR}~H-sk)6nG^mm>1tST9K3Yv4ky= z2I^l|(B`H;#=La_SlHixA$D8>7DcnOlKI<{ZnJ;8$SFZW3S+s#c5eAFiP*Ux*xbzL=(}#y@_rWW0!QCJM3N9)_r>ZosrA;L7Gn6IR|*X>KTOyXCy5DAEC+ z58THwzIj1j?aWhu%|ON&4S~|w2i4FQ?25+>bTnAy1But}%4bc^P=e75=(yk7*kyc7 zm~P7E>4@WkGj)GQxASy%i(0O9aLW*9$JMmQu@Jk`G>W84^ht|5V&U2()O8FB7>F&} zI8r#@hr^0G1G1-B9Kty!4Uhm7S<^+mHU#d8mz18;NnHn^nS0&QMnjYQ zx7WN%%V|<#wsS_(kjb@IR|iT1X*v|%d&Qm^vKwLca6WJ<|Dt^&XZXauL&zjy!%uzY zZLeu9vt)RGt+;~tfedE@XwkRp%?%+N)@;*a+q6uv;QcvPtU|vFLzuy$9Fg(z4Xv2k z$M|*z1<^PXhcTQ3tQ`|4(9H%Ne#e0VgBt9p3jgqI1|j6MT~0`8z;8RV>K@uLBmqvS z77IR`S=px9$XX`z#@MUfP|fFtuo*^?3ATWgCVw@5a6SwB$-0~@C&$gu2u{PH&MMOu zvWQ=|_Lq#(Tk^&q{ymKMJe;St9?Y_ZW%mtV{2**8oT0)S(GedUqxZ_GiQ9-?kBgPDJDwW~_o`%aui z?N>uQhK0i6t`HRZQdY*6>#udR72dXwVKweyXY!6AmjcQb29namxWbvq_CLbJfL$3)nl$kopr)h=4!ci zsw)^&KG_K^4^GcpH{F^cDMZ;{lXj$}DpjJ|^ypp z2aZcXjJLCd)fUU1D2@A&bZjG&?>YQmS@7Oc%UmuKsk>5&R-B9MFQ6q;@Ro{DvhR#H z3kiN$B5*Aw1>*ls@ji901E7^7SO(=YAg(^ggrYWNs)ZPcA=8&+jCeD<5xo|FAAIa$ zIW>Y}etbmr189%DsAfKR5Dy_S{v_Pv$*uWeg>hmiga(Q$-gv{C)4WV z8uoWovVbughO7m%u7$F(>3J*Z*@SsLIzT|k1d<89-vp_azFE#&7y}uvv}6v`-BqwN zfMLacyS4{nJ`9$^6|=AC%q{FUn?&dpinm?eV(w;Upl7%pQ~4t>+Dtnq-~ClBw3A67 zt*Ke$5_XipNAxHgnvTZ2;iaW1rQzC>;|wrID=IKq=^1HVV&f)<&h4o2%$5vnFflM8 yFbM_)D-Ht!8U+9Z6xmff13bV(PwC_C$)8c)t-lc^!vqM)-^#&jc;ajV0tf)Qr)z`bulp_>4+owPsT*My;wns+J*%XPd-@1q8`EKfZthiHcw25i&PMhl1F4B-y_b- zi7a2`C)E$k&yYM7UK%Ikt=?YL9lCPYV6P20bBbKnmlvhYGjJc$IfaHw$^?BX6VUqe zZNREt3Fy0>gS#zvlZ?INXt=LPZ1v59H^b&HL|Thk%#0j&(7QjjMEHO0HZ(P&H7wbr zGLbwn5q5p`dwIQ$(OwBi_MruJRdffzCbqzV19+nB4w%bfu$p77wz54vY3xC%@jtj3 z;g4`92J@-Szk2*rQyz@dtJJ&k@jAol>TJ<4$zkmNiA`FsQuCBHcZr5Xy}X?Z$doIl zqNeffAg^D^np1}-3qy(h4XVk~lkrhTp|r0L$hK74xWA5*o3g!CeH`Z_mHY^MEQAQK zx<=lb5fWGP>})1KmW7 z%&Va>l*6YfOf(0w%m+U9Ecz0wbw~%Vr;5zPfZKvS&AJmZOKkQE5>iN9<;JwaJrSl5 zvAb7e`0bqKbwW)WWZzXJ1>VIKuBeDs&sBhifpSUqP4%EG2aA|pHfpMOEzj^i;WS<) zY(9E(iyX9J_DU+8^(r8}bhOTX;PMfwa>JD;XA!Bk6IAM@6lvLg|2uc3<J!Zu4(J5kdU?-+uIXO&RhHajnvsy! zgM=PS-;uDn+Zr(143mk|%0#bVpgot-$HrAkL3wraH^XyzJP*e$)EhFID?6C;whkgY z_S6eD{TPhAwfD50S(6rl>G}_a+6oXZv3enQJQpMIKw+xxvaCBdSctln4Zg7q7Fai@zl4nfp&TLnI{Sc*IB3%tviX8C}iX) z?=xM!0TX;(;V^l7L_IWknvF-JKU#sSCC*k07Q03a6FnmD^XBF=fB2{_DJLnLUw11! zFh>5b*|KAY-72d0K3#6iB^fr{%&B;~KzClU00|(T@O+E%$Vz3T@;0XNP^fxQanfJ2 zfZr{+C&^EA2cyUs>)RjWa?L=)3L+wLrSReBGZ&T8u8!Co)llE5o~(TrlI~#s+ASO$ z3r779Ab2bo3BrPJoX4W)Cj`0pA5LHZ;JG_L&cRv#KV@itE3*)F41uvvp8Qq@ga!44 ze(#rRta-drvmTRe^UJ?%ElR^c(lEAl7v`EVrjCet_jkya?%%0zKB*<8r2A*3Vhk<9 z{YK@Um)@hOcF0C!4}MVlxwA$>ZvPEzA8e&0846!8=45`T6%@^x>AZ17AG9&vbdQ=4 z5!-uz+r^ZkJ-&Q>!6~$wN0c1UrFy`-P3AgQo&)_n?p#}mCQ9YEU6AU2v$%m#l$^k4 zC$?xPu%-;4O5#$Ytj+xu-*haz7il!B44~?XP#uGCP}12zh=Eh+SLY$UbfDF`;*gBv zuIYQ>g2_pY>O5YNp+$jBGhIUm%Z?_L>gFVTNOwqVT1tCi?JQScgm3&=#?IP4VSc*w zfu=J}B&;PhDx>GxhW)s6FiR0|`pKM$jgfSkbSh-0d|0hygOv!-fSt3!89?# z$c>%W>AE}<)MOWVA`Z5l`Kq52WLs=eoYsg`6+Rp!`brDTXG@RS>q5e3d9Jm6d!m5w zj}TY@XhNFnEb=!UuuDG}#MyE4rIumCcO=|dc1IIysnT!?(NxwD=ObjLEkTxPbXlNN zs2pT+EWc$;UJy|j2okI;u9B^>&kx}hG1(MeB}H6Z&jBwwMSdK3P+&eYF4o-@s@3^8 zZXqs(?8M(}QOwc(f~J*>BW`mP7v0n4l+PV942-Ai`B?OHi;=>mc^}7UAyqII>hL~F z&(tq#Q5@Xz^305>+&+$oXWfIab%WJsdmc}XA9fYAeM*7evXm-aVz#zi*Zt)y9~UBA zQglXY?`Qrv^Vm*rC>Nf%RLo@GEWmq``T<8=eoJ;XZ`96y@I8 zcb;~$RZrXss>$|ePo8+YBoM1VeFC7V^FJY{?1D z0d~T{*fopAIU;zU2|?FR5cOf9zx+0|hM9>ztiy4(;4j8Y=KL4}2dVGoU}by3vgViG ziM`22%-q^-mXLN1?DZ2N0e4H^ctP~Y%C!Ez(k93MDVu-&(wC z`NSB*kjIT~sI^Y6=k|#ZR;QQIV=Ww6{*e4`)p?GO7jNaNt!Os(<@1xAjH7JnA2AC{ zPH{Sm7lkXC`mC2Dk|sus=U6tazxqpj(tVq(_F(Mn&+QGzoXBSOE?TCAPpm--BHZ5$ z1cLWchPf7}jSiE)f7PvhYQ~zLx$T<9OEM)qQyS9pdzoF{{or+BdyzbG1|{&FY!rVf z-u&1ZoR&=P;CmrJc{Qv|KlG=VmBF3c<`o+IDqHL+!oQrf*MdFo_|YFKQE3tb#bTpY zjr5HgC{?AEUeM3O$lN38Oy2YmO@v*Qo8Xp|QZ@BH3?yp)^aGf9C-5dcw6_f1Q{}~+ zbW-2xp!4(Vr6^MI*^1w|94%d?dxL4e;!5CigdkktzdAxMBiKP~{xdV>8;RQqvm_nW zc#Uu$A=Q*pK!u%$) I?!T4%7x#L-lK=n! delta 1677 zcmV;826FlJ6O|1>FoFh=0s#Xsf(BOx2`Yw2hW8Bt2LYgh21o>g21GD|20$=^13v}{ zDuzgg_YDCD2B3liFff7xECK-lFoFXmkw6`PlGWDcvh7^o0s;sCfPw<}r)sSVcsqqi zcc`U%s8YyY37QiqHRN0A9fuOS>DAd-$;mb->`%r~|DEjUw&Ha?0mJIzIuUJD-6Ds9 zaUA=tyV8QNCF&G8Y<+erO<4M~FzW!AtgJ#X8(pc0&DJ{@jrGaco8lo2+kWGvgGgV0 z*Mr(4FyoENBRv44;)Z6DuS-Mf z2)UPw4wrAI2^AjdJpq3FBJK-p;gsL?lvZALrnR`vvbQ-;d6nGB&?!BETEYBKdwD0R zo%sIi?l&8IFY_5nBQ)TbCt`a`HO+Q^4x};P$-DmQ>|MZd7cQOyfHP?CJ;RcKac@ww-EdO{ zeq>zFd?@My#-GKAT=httXCuHy{NR5}2sO@gX3S}<-To$PQuoXu65hFKj?EH(_^P@) z8*Al*mK;nhKGn-Thep_->kJV+t^jm0VrC3k;&!#l$frr4Rty& zat~!Ve)}+TpAtXAWxoG0@{ex^Y{LQjtSpXwb^LHqN+A0kEMLO7ULq*>_8VX)jz_W? z%6$)=t~>m&wtfi&>gr5ZEj#6Z7FOplFi_x};+2`LOOH{xbx|?|d`%iOfi6bdhj{?q zte!r)eYdH-5752(uSd$NkAC3}Rq{;cyJFA~gQM&H4b;MzoE02VHY?V67MvCDnvvkn z6QG+MMZJ{IKglvDh1i=x65b({{l(b59TpI^6LK@)&IJPzQN>9&X5R;Y?tA2wVU`pJ zwL9Hn=mgfZoCj>C(Z z|IpN|D8SvOODSMC@qV{|-cRHxbc@8wQ}B($O(Zaa0{I3BDuzgg_YDCD0ic2c>I8xU z<}iW+;xK{&-UbUQhDe6@4FL=a0Ro_c0;Vv60-`V+1_~;MNQUuO_Aw*Oi%+-|n74G@q85fClJC5*{yD0BdwtWw7 zbCdV?#YgXwv2H*5%HlmQCw)=0oA`r_bm&5dqb^sh>6kP%XyF+^rIWczdJz*iHe!Di z=R9iP5apm`edBi6?grgWjw}0%Hfp%#VU<5tXhE(!*?4Pzyndjz63;qp5z9Hrb9Yvx z!k}XEB6i3EL};KV?;d2ArZfU9N|K1{njcBrC(sQS{xCIMCsPX>;F(I2in9zZj5`RI zC>vrYVmbD`P!S2|Rh*qZB`7t~M2Blpe1fh5F~WgMqKL)bt9&8TzSm_`_ z)UZ^rsb*fKsg6sf^+Ji=PuLSxeIGK6lCUP7N^lQ<7?IDtz*HK+>p1#nk(D~yJ*GG= zq*L}&Qav<2>!GLd4!a+%A_#dw;G*{qBeg%c28{pR<=ziL zb#**s8eVQO&82G)AIH=Y7eiF^1Dme^KYe_{lSaIj1TiHrBL)d7hDe6@4FL%iF%|?A zD=IKVS?L*RU1H-VhtBP&@ywPCY%nn}AutIB1uG5%0vZJX1QguBi$HPAeaR+@?O^>+ XPsfC%a|i?ovkvjNQO{HK0s;sCG$$WZ diff --git a/tests/hwsim/auth_serv/test-ca/cacert.pem b/tests/hwsim/auth_serv/test-ca/cacert.pem index b128893a1..7fcbdf767 100644 --- a/tests/hwsim/auth_serv/test-ca/cacert.pem +++ b/tests/hwsim/auth_serv/test-ca/cacert.pem @@ -1,55 +1,79 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/test-ca/crlnumber b/tests/hwsim/auth_serv/test-ca/crlnumber new file mode 100644 index 000000000..adb9de8ee --- /dev/null +++ b/tests/hwsim/auth_serv/test-ca/crlnumber @@ -0,0 +1 @@ +08 diff --git a/tests/hwsim/auth_serv/test-ca/index.txt b/tests/hwsim/auth_serv/test-ca/index.txt index 6c94cb66d..b53182613 100644 --- a/tests/hwsim/auth_serv/test-ca/index.txt +++ b/tests/hwsim/auth_serv/test-ca/index.txt @@ -51,3 +51,70 @@ V 201003130223Z D8D3E3A6CBE3CD22 unknown /C=FI/O=w1.fi/CN=server6.w1.fi V 201003130223Z D8D3E3A6CBE3CD23 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi V 201003130223Z D8D3E3A6CBE3CD24 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi V 201003130223Z D8D3E3A6CBE3CD25 unknown /C=FI/O=w1.fi/CN=Test User +V 210502173804Z D8D3E3A6CBE3CD26 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502173804Z D8D3E3A6CBE3CD27 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502173804Z D8D3E3A6CBE3CD28 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502173804Z D8D3E3A6CBE3CD29 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502173804Z D8D3E3A6CBE3CD2A unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502173804Z D8D3E3A6CBE3CD2B unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502173804Z D8D3E3A6CBE3CD2C unknown /C=FI/O=w1.fi/CN=Test User +V 210502174431Z D8D3E3A6CBE3CD2D unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502174431Z D8D3E3A6CBE3CD2E unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502174431Z D8D3E3A6CBE3CD2F unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502174431Z D8D3E3A6CBE3CD30 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502174431Z D8D3E3A6CBE3CD31 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502174431Z D8D3E3A6CBE3CD32 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502174431Z D8D3E3A6CBE3CD33 unknown /C=FI/O=w1.fi/CN=Test User +V 210502175131Z D8D3E3A6CBE3CD34 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502175131Z D8D3E3A6CBE3CD35 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502175131Z D8D3E3A6CBE3CD36 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502175131Z D8D3E3A6CBE3CD37 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502175131Z D8D3E3A6CBE3CD38 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502175131Z D8D3E3A6CBE3CD39 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502175131Z D8D3E3A6CBE3CD3A unknown /C=FI/O=w1.fi/CN=Test User +V 210502175312Z D8D3E3A6CBE3CD3B unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502175312Z D8D3E3A6CBE3CD3C unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502175312Z D8D3E3A6CBE3CD3D unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502175312Z D8D3E3A6CBE3CD3E unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502175312Z D8D3E3A6CBE3CD3F unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502175312Z D8D3E3A6CBE3CD40 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502175312Z D8D3E3A6CBE3CD41 unknown /C=FI/O=w1.fi/CN=Test User +V 210502175515Z D8D3E3A6CBE3CD42 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502175515Z D8D3E3A6CBE3CD43 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502175515Z D8D3E3A6CBE3CD44 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502175515Z D8D3E3A6CBE3CD45 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502175515Z D8D3E3A6CBE3CD46 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502175515Z D8D3E3A6CBE3CD47 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502175515Z D8D3E3A6CBE3CD48 unknown /C=FI/O=w1.fi/CN=User +V 210502175516Z D8D3E3A6CBE3CD49 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4A unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4B unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4C unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4D unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4E unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4F unknown /C=FI/O=w1.fi/CN=User +V 210502190331Z D8D3E3A6CBE3CD50 unknown /C=FI/O=w1.fi/CN=User +V 210502190432Z D8D3E3A6CBE3CD51 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502190432Z D8D3E3A6CBE3CD52 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502190432Z D8D3E3A6CBE3CD53 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502190432Z D8D3E3A6CBE3CD54 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502190432Z D8D3E3A6CBE3CD55 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502190432Z D8D3E3A6CBE3CD56 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502190432Z D8D3E3A6CBE3CD57 unknown /C=FI/O=w1.fi/CN=Test User +V 210502195156Z D8D3E3A6CBE3CD58 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502195156Z D8D3E3A6CBE3CD59 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5A unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5B unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5C unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5D unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5E unknown /C=FI/O=w1.fi/CN=Test User +V 210502195538Z D8D3E3A6CBE3CD5F unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502195538Z D8D3E3A6CBE3CD60 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502195538Z D8D3E3A6CBE3CD61 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502195538Z D8D3E3A6CBE3CD62 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502195538Z D8D3E3A6CBE3CD63 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502195538Z D8D3E3A6CBE3CD64 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502195538Z D8D3E3A6CBE3CD65 unknown /C=FI/O=w1.fi/CN=Test User +V 200102000000Z D8D3E3A6CBE3CD66 unknown /C=FI/O=w1.fi/CN=server4.w1.fi +V 210503140118Z D8D3E3A6CBE3CD67 unknown /C=FI/O=w1.fi/CN=ocsp.w1.fi +V 20700421140741Z D8D3E3A6CBE3CD68 unknown /C=FI/O=w1.fi/CN=server7.w1.fi diff --git a/tests/hwsim/auth_serv/test-ca/private/cakey.pem b/tests/hwsim/auth_serv/test-ca/private/cakey.pem index cddf6b1cf..b66e03802 100644 --- a/tests/hwsim/auth_serv/test-ca/private/cakey.pem +++ b/tests/hwsim/auth_serv/test-ca/private/cakey.pem @@ -1,15 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC+HobkeQPB0ZTV1LOxKJB2+7imzW0c0Uj0CJpn//mmVLEZKd8p -G83xb2YB59t5zsA5KiUTJpQMLHtaLIEPlO5R0HXmRtsXRqcViw5XD7BUdmMSyoYY -vBrDFsBwCdZrQzm4mClGrMtqrTiIOwfcgc069h32L+8d166KttHnsxUCuQIDAQAB -AoGAEPKDr8Yh0ZsvG0iUpAwrpI+XzDavrUvypt5FdVPaGzudddLHs9BosUbu3uie -JeOKOw5Is8ZSmCs267jf4FW0UKtgpnHGK2H0ba0iramzz07oK48V4y7C7nS3eJr/ -Oen6H9BW4DNXreFZ5yTRFOiQ4eD1pHqR/M/bBieDfRjakgECQQDfgiYYInio4TmM -9q/h1q5T1bGgajz5U4GInd0K2diNqVoGhSTAyRRGauH+68tPQuX7WCM1VE/lZfZL -4/dlOaRhAkEA2cHNkrFh4CAlXgtCub+psmT032AIFDEpNNT0K22XIE8savYNqs8w -aGPurrwGQflxCB19boiaKEcW5FQDkff9WQJAbUznNiw9V1D05OOKNWXX0HWTLMBn -WwIkOVwByZmo1fX4aXHY/FIZESqZpCFJRlSPxS9f4Gd/vs3y+T/dLupWYQJAJDGX -RrOfDg6px1jdzVvzC8jF/r7KePi23aYrs3Ayt1cRjfG50dNAO4moqXhtHdglFnE4 -YP/ph5pRTsA8G635eQJBAKbh0zB4HqFI2PmnKsShFBPNkK5x17nAZlYNJf2Ip4Ii -2Gjxyx4H0iBVgFYLsLB6hRBkOPpx6Jl8mJXOtFXb8lE= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC89O5EYn9iT6GB +RrrEqh79TtDt8UfLJVtmeoY5kcq1Yad+LzxjfTm4Gp7LbTIykd5JSYTaFb4r3ca8 +H9xuwC138tB7LEAZB2BVsP98Ue840fAq2qjM6tZUpO++F0QanjNwV6TzBqw97kst +5UYlLTMJ9kmoAjGkZZsyCmf1AuE7R6au5PaF610+AmbdEZisNHLCjyVVSmrq6IIv +vX94MaRa1zK7ZEhGI+/IyeKEAFZy6EtUlWI6WhF57kBDnhYszOZF9LuCKMKDNSxV +NplZEbEV0APBpTfhH7tDx7S5M94U13yZRQ/BBv62JRBZt3J2f5FL6tG5amrt3Rup +DqcpSLdNAgMBAAECggEBAJ9YofITaj8aziT545jjqfyN0c1G0vdyinCSVM0JsHtj +Xd8gsHlp6hnigRUmAdX5gw4krJ9JBLVzchvFdpwC/pUPtFabC3bP7KJ3AAzz/5vY +FwPcn8snIxYAfZi9gBY+YTyU/KphbzFO2iFbHttNEaSOCLFhIEH12XnKor5Q7mWQ +5HHlTdCzvRlGQwSdrmYctQmekdSgffF56ebZzlkwrJAF+o8NX44mcNWSausnEuds +S7Cah4dxT3Hm8luXfd1u3fCiT/p0ubMT66OVjo2cB0CIQxSpGWoIMuVrVrlzQbNt +gtQ2cred2HKizlYpCjNd2zrRHauIc2koqQTP0+yNE5UCgYEA6Fuc4Wrq/maMQiOT +QI46K5PktWArxFO152chdLpjy9qKmm0o7MjBZubRRW0kYHvtUwu15wcCH8Ctwucn +JGrvtS3lMbNy14kQG7OrT87u2J5VyXNbGxOIhoeDRxEKCbDfyA+4c7sGHMxczxPc +q6tWJ8cZeXLl8TMLacyG5aWF1WMCgYEA0C7RtPZh6J4XfsgZjO/7FoVgBp5yoche +Hc6gwHiT7qYAbDQgOq7g41jEtYoO/e8qRsxsJHJlVzYIe3WlK5IC78sk6ZS7hZ6M +LjfhnBPV1Ddtdq4w2VKY7fDYPvZK3DOc0FOIlaPicxWXUUDt0Tfud2qgYbebz+R6 +wmxqqcYM948CgYEAq6C/yGFJIpBsmY3dfpmPrhCXpsFakrGic0JiG+5xOGo8ZsSq +rfu7n15uxXFQpVPkgKrtubAbiYiw0H4dE3FJjfJQkN2TvlCnbU7RAyo+khKiGyLx +8JYFChmehie32mCjawrxm8pRQYRSKULqhIMSKF+QGX0dC4RAse041vfkWzECgYAr +tAh2EtsO+FE6Xktu2No/KhS0jwLFj8iiPURl42o6yUKBdJfnedrgHzx8V9U53cFk +R3nUVOeNXVx+fn4EHYzcRisjlgOf017ePQDxwQA8or4qEftTRBGyscLTxOSGQZeD +7GVZ9KOPQVMYzaafKzy2eP3eRatCA1b6BcSGi3shZQKBgQDA1h0rSoFoXsel8MAV +MPkGt6gzUdzKb/Qt3BOolnsIcd4Vn19uLCcLdhxRkD37MW/9/mgV+Q57DYyvS9OC +xi6q7ukgDE3YTK5WChmqJ4p0aEP4bEt6N1VIo55HCFoJy01NIJLs4VAW4y88CzDp +otex1UmIWQdfnDbIVW9NNFVTiQ== +-----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/test-ca/serial b/tests/hwsim/auth_serv/test-ca/serial index 1394bbfd8..0cf1e4210 100644 --- a/tests/hwsim/auth_serv/test-ca/serial +++ b/tests/hwsim/auth_serv/test-ca/serial @@ -1 +1 @@ -D8D3E3A6CBE3CD26 +D8D3E3A6CBE3CD69 diff --git a/tests/hwsim/auth_serv/update.sh b/tests/hwsim/auth_serv/update.sh index 585bca632..b2296b2fb 100755 --- a/tests/hwsim/auth_serv/update.sh +++ b/tests/hwsim/auth_serv/update.sh @@ -4,6 +4,47 @@ OPENSSL=openssl mkdir -p test-ca/newcerts +echo +echo "---[ DH parameters ]----------------------------------------------------" +echo + +if [ -r dh.conf ]; then + echo "Use already generated dh.conf" +else + openssl dhparam -out dh.conf 2048 +fi + +echo +echo "---[ Root CA ]----------------------------------------------------------" +echo + +if [ -r ca-key.pem ]; then + echo "Use already generated Root CA" +else + cat openssl2.cnf | + sed "s/#@CN@/commonName_default = TEST - Incorrect Root CA/" \ + > ca-openssl.cnf.tmp + $OPENSSL req -config ca-openssl.cnf.tmp -batch -x509 -new -newkey rsa:2048 -nodes -keyout ca-incorrect-key.pem -out ca-incorrect.der -outform DER -days 3650 -sha256 + $OPENSSL x509 -in ca-incorrect.der -inform DER -out ca-incorrect.pem -outform PEM -text + + cat openssl2.cnf | + sed "s/#@CN@/commonName_default = Root CA/" \ + > ca-openssl.cnf.tmp + $OPENSSL req -config ca-openssl.cnf.tmp -batch -x509 -new -newkey rsa:2048 -nodes -keyout ca-key.pem -out ca.der -outform DER -days 3650 -sha256 + $OPENSSL x509 -in ca.der -inform DER -out ca.pem -outform PEM -text + mkdir -p test-ca/certs test-ca/crl test-ca/newcerts test-ca/private + touch test-ca/index.txt + echo 01 > test-ca/crlnumber + cp ca.pem test-ca/cacert.pem + cp ca-key.pem test-ca/private/cakey.pem + $OPENSSL ca -config ca-openssl.cnf.tmp -gencrl -crldays 2922 -out crl.pem + cat ca.pem crl.pem > ca-and-crl.pem + faketime yesterday $OPENSSL ca -config ca-openssl.cnf.tmp -gencrl -crlhours 1 -out crl.pem + cat ca.pem crl.pem > ca-and-crl-expired.pem + rm crl.pem + rm ca-openssl.cnf.tmp +fi + echo echo "---[ Update server certificates ]---------------------------------------" echo @@ -12,6 +53,9 @@ cat openssl2.cnf | sed "s/#@CN@/commonName_default = server.w1.fi/" | sed "s/#@ALTNAME@/subjectAltName=DNS:server.w1.fi/" \ > openssl.cnf.tmp +if [ ! -r server.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server.csr -out server.pem -extensions ext_server $OPENSSL pkcs12 -export -out server.pkcs12 -in server.pem -inkey server.key -passout pass: @@ -20,24 +64,51 @@ $OPENSSL pkcs12 -export -out server-extra.pkcs12 -in server.pem -inkey server.ke cat openssl2.cnf | sed "s/#@CN@/commonName_default = server3.w1.fi/" \ > openssl.cnf.tmp +if [ ! -r server-no-dnsname.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server-no-dnsname.key -out server-no-dnsname.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-no-dnsname.csr -out server-no-dnsname.pem -extensions ext_server +cat openssl2.cnf | + sed "s/#@CN@/commonName_default = server4.w1.fi/" \ + > openssl.cnf.tmp +if [ ! -r server-expired.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server-expired.key -out server-expired.csr -outform PEM -sha256 +fi +$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-expired.csr -out server-expired.pem -extensions ext_server -startdate 200101000000Z -enddate 200102000000Z + cat openssl2.cnf | sed "s/#@CN@/commonName_default = server5.w1.fi/" \ > openssl.cnf.tmp +if [ ! -r server-eku-client.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server-eku-client.key -out server-eku-client.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-eku-client.csr -out server-eku-client.pem -extensions ext_client cat openssl2.cnf | sed "s/#@CN@/commonName_default = server6.w1.fi/" \ > openssl.cnf.tmp +if [ ! -r server-eku-client-server.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server-eku-client-server.key -out server-eku-client-server.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-eku-client-server.csr -out server-eku-client-server.pem -extensions ext_client_server +cat openssl2.cnf | + sed "s/#@CN@/commonName_default = server7.w1.fi/" \ + > openssl.cnf.tmp +if [ ! -r server-long-duration.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:4096 -nodes -keyout server-long-duration.key -out server-long-duration.csr -outform PEM -sha256 +fi +$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-long-duration.csr -out server-long-duration.pem -extensions ext_server -days 18250 + cat openssl2.cnf | sed "s/#@CN@/commonName_default = server-policies.w1.fi/" | sed "s/#@ALTNAME@/subjectAltName=DNS:server-policies.w1.fi/" | sed "s/#@CERTPOL@/certificatePolicies = 1.3.6.1.4.1.40808.1.3.1/" \ > openssl.cnf.tmp -#$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout server-certpol.key -out server-certpol.csr -outform PEM -sha256 +if [ ! -r server-certpol.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout server-certpol.key -out server-certpol.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-certpol.csr -out server-certpol.pem -extensions ext_server cat openssl2.cnf | @@ -45,14 +116,23 @@ cat openssl2.cnf | sed "s/#@ALTNAME@/subjectAltName=DNS:server-policies2.w1.fi/" | sed "s/#@CERTPOL@/certificatePolicies = 1.3.6.1.4.1.40808.1.3.2/" \ > openssl.cnf.tmp -#$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout server-certpol2.key -out server-certpol2.csr -outform PEM -sha256 +if [ ! -r server-certpol2.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout server-certpol2.key -out server-certpol2.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-certpol2.csr -out server-certpol2.pem -extensions ext_server echo echo "---[ Update user certificates ]-----------------------------------------" echo -cat openssl2.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp +cat openssl2.cnf | sed "s/#@CN@/commonName_default = Test User/" > openssl.cnf.tmp +if [ ! -r user.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout user.key -out user.csr -outform PEM -sha256 + $OPENSSL rsa -in user.key -out user.rsa-key + $OPENSSL pkcs8 -topk8 -in user.key -out user.key.pkcs8 -inform PEM -v2 des-ede3-cbc -v2prf hmacWithSHA1 -passout pass:whatever + $OPENSSL pkcs8 -topk8 -in user.key -out user.key.pkcs8.pkcs5v15 -inform PEM -v1 pbeWithMD5AndDES-CBC -passout pass:whatever +fi + $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in user.csr -out user.pem -extensions ext_client rm openssl.cnf.tmp @@ -64,6 +144,14 @@ echo echo "---[ Update OCSP ]------------------------------------------------------" echo +cat openssl2.cnf | + sed "s/#@CN@/commonName_default = ocsp.w1.fi/" \ + > openssl.cnf.tmp +if [ ! -r ocsp-responder.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout ocsp-responder.key -out ocsp-responder.csr -outform PEM -sha256 +fi +$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in ocsp-responder.csr -out ocsp-responder.pem -extensions v3_OCSP + $OPENSSL ocsp -CAfile test-ca/cacert.pem -issuer test-ca/cacert.pem -cert server.pem -reqout ocsp-req.der -no_nonce $OPENSSL ocsp -index test-ca/index.txt -rsigner test-ca/cacert.pem -rkey test-ca/private/cakey.pem -CA test-ca/cacert.pem -resp_no_certs -reqin ocsp-req.der -respout ocsp-server-cache.der SIZ=`ls -l ocsp-server-cache.der | cut -f5 -d' '` @@ -90,4 +178,4 @@ mv index.txt.new index.txt echo "start.sh: openssl ocsp -reqout serial" SERIAL=`grep CN=server.w1.fi test-ca/index.txt | tail -1 | cut -f4` -sed -i "s/serial 0x[^ ]* -no_nonce/serial 0x$SERIAL -no_nonce/" ../start.sh +sed -i "s/'-serial', '0x[^']*'/'-serial', '0x$SERIAL'/" ../test_ap_eap.py diff --git a/tests/hwsim/auth_serv/user.csr b/tests/hwsim/auth_serv/user.csr index 921eb68a1..49c179f26 100644 --- a/tests/hwsim/auth_serv/user.csr +++ b/tests/hwsim/auth_serv/user.csr @@ -1,11 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBgjCB7AIBADBDMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwHVHV1c3VsYTEOMAwG -A1UECgwFdzEuZmkxEjAQBgNVBAMMCVRlc3QgVXNlcjCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEAppYumyKM35S+i4lJ9nh2omB+FJXzlv6rGSUDNGR0AT6on3zx -R2FgTIKSKHwroA7Lh79Z69fzYSI7FPOrMfZalR+4ergsPKlhU3ib6D5Q7MLWROdD -zbw+TudG/pKew5gPKVjIy4kBdUfplVcPdsUvBV7HHg3yPBJjXblUGa9/QGsCAwEA -AaAAMA0GCSqGSIb3DQEBCwUAA4GBACZXujbQL1Y5fOWK2pRyckyk92NAwgPXWqo7 -8d9FF2bIDBfautK2GYd74SDdUOzjNjGLoEO9tIhB3jWQp8qaC/HiWwbDGd6Ugo8g -WnuLTf2vfL67IdVzG26IAdflrEF4XX3HjuHJO1NxtXKw/u5hm6qiJAu9tkA+2zEM -bbG4Bg/+ +MIICiDCCAXACAQAwQzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRIwEAYDVQQDDAlUZXN0IFVzZXIwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC8JAjZB20ZDpRca9mKhBsDIuIaBkLTC2CNXzEEBvqi +QGoMJClYzYO/Op1/Nw1NJ13VV1cc8751PzpMRG8CL1uLLLBcRykZMQjRKPUenFuc +t+drQDUQPn9mZxahTmiKccwyWOMIh6IqBy1/c/ZD5X/09nSuJ+jSXK6bgtmlKnJ2 +hC/jYqpBHt4zt2T4eW/6CbW8sIzNNIItxBBViepsOJL+YdZkhATUCjcyN43DVdH8 +q7hVBqkATzHiQvHntC6cRQ3cqfmtsnfB8LHDolomkL0ZL0YdpSE98DVilMjPMz/Y +ol3fzFgACI3tsQTFKz8aFfaSCNTxQs1s2/L/4G5phNiLAgMBAAGgADANBgkqhkiG +9w0BAQsFAAOCAQEAJB2hPF8r/cPO7+4fPf3oXwEwf0YsXHzVwUnawgtMNyU10rJX +qqQIi2elEJfgYqmUhmXBrBIm06bRXlcR+QoWwX4sHk3rmHQYPy190bNpTaHVN9bZ +kZndOcdaog1a3Lbui+e/brpzo0kGskW9TsDsOkYjzgIzQHGQtfcPfLhnLj4+sRyq +tnV0vvHl3SyPmsVxrazRO4LgMBmwGx6QC4Yf3w25Us3aLzJqsZHDBRsVRdoHyLYd +Jwt2fE2dLzGNkGFUP3BeJMHze1CqRybfoVlBU1IZRYlRQ8yOO/IpO7pa363Xx5Ar +DsD2xcG7WvAjQ08vVgW2ShQRIIeX0Luhd6fqQg== -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/user.key b/tests/hwsim/auth_serv/user.key index b9fd702d5..1e114958a 100644 --- a/tests/hwsim/auth_serv/user.key +++ b/tests/hwsim/auth_serv/user.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKaWLpsijN+UvouJ -SfZ4dqJgfhSV85b+qxklAzRkdAE+qJ988UdhYEyCkih8K6AOy4e/WevX82EiOxTz -qzH2WpUfuHq4LDypYVN4m+g+UOzC1kTnQ828Pk7nRv6SnsOYDylYyMuJAXVH6ZVX -D3bFLwVexx4N8jwSY125VBmvf0BrAgMBAAECgYEAkEoS0kKJ3Hqc1IW0r6xFrX2A -l1oOpCGvl1bswKuloxJfwczZu+cHHx4VdMWgj8Fg3xKJ03K4FtEsdYhdJyhn6c6G -YsKF7HHGo2WA61VHxgqRB/CZzALy2JR/3rzElvrVQ5ZVh15DipNpwfwP9bW6P99A -omPQVnZ3p1HgU5WK68kCQQDXHbFUYX3I9SYlR4JhPy5ov2Q8WHu4p9rWXGBO75uS -7f3FZCbGULKZEOsiVFbloyUdpvLId7wvb343a1EAOnC9AkEAxj9UqsKMAdlXTDrT -9NcQmJKWt568gEV4/45fjpTzbdndEOtCMwWBWEv/SyiWgWdwPeBViRGEyPrkLV/S -teesRwJBAIfN6QuaWKyrh591W6xFFOlwGrm2KrVS0ucNfoeW4SKLOPCK36fHflj/ -w1Hy6MEkk+P6Z7+DR7yyqH4YNBTu0AkCQA7uZioWTQU2oWSUabJfIFjdcYyS4A+p -K9vTlU7f2RXE+ulzTqEZIQzNbIT0oaFNcR637rlMIHwiqVzhgrVApbECQQDK5QqX -E6Z2VHTNEnCki9YvkgjPhLxSihQMDSaR0ENkre0OctFUufbwzH7DEhzV6CQ1Uw+9 -Au5AOFzcb1tfGczP +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8JAjZB20ZDpRc +a9mKhBsDIuIaBkLTC2CNXzEEBvqiQGoMJClYzYO/Op1/Nw1NJ13VV1cc8751PzpM +RG8CL1uLLLBcRykZMQjRKPUenFuct+drQDUQPn9mZxahTmiKccwyWOMIh6IqBy1/ +c/ZD5X/09nSuJ+jSXK6bgtmlKnJ2hC/jYqpBHt4zt2T4eW/6CbW8sIzNNIItxBBV +iepsOJL+YdZkhATUCjcyN43DVdH8q7hVBqkATzHiQvHntC6cRQ3cqfmtsnfB8LHD +olomkL0ZL0YdpSE98DVilMjPMz/Yol3fzFgACI3tsQTFKz8aFfaSCNTxQs1s2/L/ +4G5phNiLAgMBAAECggEAAVFTSonVxsYmXdtXg7PXKJd28+21TBsZSwQuqLOPz9EZ +rQoXzApscMttTPXKvw6Whqb88jP20oVl2CDmkiJYxsnCVnMdI5MHV8esp9E6hwd2 +tHaXqIx3gfUY4HpXGxke7/9VX7rrdNXmCK18PQ9/bOzI9mtLIyYJBwfMlG6OrKvP +QoeLwoZiMDvA3nS8a/TeTPNXI1md7GHfPXqOumAngV0E4FuT7XfkaeBVzataUStY +D9WEhjtiEahCJWqtN7U/Zq4qKB6XrrVye8BixDNRf/Qnz5SPrhWk3rWPEAqPBcqO +EirQapQAI+e974irowq1WOUV4xDYWq8QoXrMWFwFEQKBgQDjwxs+i+P33efaeTXG +AjK/qieLn7JvnHIxAOPK+qzPY75b01U0JH9qRKs1J2dxUQQFWu2rWtbLAVDf8et/ +URL8ZAqCy2U8HOUJuu+x9kNoLRxREuY9EhMeQ6P6clTGx1fgIc9BXsT+UjMK6I+R +3JwZEwLYf3E81KU9CmKpCfUZwwKBgQDTd2TRu9fIbmIrAf6StvsSD2OWQ/RBavNE +pISLH5/orvt3kXy9I6bAyW+FyHZ4620CE24fzstWH8l3F1jIvCf32wa8cTi1EA7l +Rh8gVRC0s2CdETse7lUHTqqoqO6ckT9p0ZLLHfbALsy0jIOZUno0uVgYPzbWkvXW +j76Q27uRmQKBgG38qgtqQoxP/MbkAbO9HASyhqZGWETNp9dCNr6ujwUXhbWSOHMV +rPIEdykT/kAaf3aWkm9NTqx51jRO/wpcfG6lYO4IirqcuX4ZZ+bopWSJZENCfSzA +rbrPr0AiNg5H9YemzA8lVLv7tepuo+YsQrVZGOazpFtb1O/FNB+tT09BAoGBAMlG +zCyhOasp/cBn3pJxHhq7kROWzKdzj+cXHJ17VW5ZFztgvDUe+PppAQB6pOFFXHVs +XxZhc8Me8FitXTF7fiN5UzkMH2ifxz3Nd5UDwqnsTppRq08ulLom02NDoBJgYdZr +xugUNigIo4l6cUv/aBhFDifOC3lDWkGGgmFI9IiJAoGAUMIiyteV7zqrc3ncrnYu +Nvg90VeA7CMa0SvmOMYS0M8fUUHtbthfr64c2fWM9JFflApRtVkHSclRMI1RqmVW +SvDqS4kxb0NC5HiWioRHb3PlEqL8F076lySD/25sNwWwHwMq1MJPOi7cEXc1YtWS +26WD/C6dauV5FnMa7eX1D3I= -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/user.key.pkcs8 b/tests/hwsim/auth_serv/user.key.pkcs8 index 655503da9..8302fbbbf 100644 --- a/tests/hwsim/auth_serv/user.key.pkcs8 +++ b/tests/hwsim/auth_serv/user.key.pkcs8 @@ -1,17 +1,30 @@ -----BEGIN ENCRYPTED PRIVATE KEY----- -MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIt5s8O/vC7Z0CAggA -MBQGCCqGSIb3DQMHBAh1l9fSi61IRASCAoDGCULhl5nYsWTyimj9idh/1z78xJu6 -Q+Ap6u/UiEQh3riX5DYojJPZfYTJ44IOh/Jfbv/ipr4IynDnAiZyhs8NWYAXTk2i -U5yb1Zsf3lRxKQG8u8BhkxDdUs9GSbajvF81fWkZVpMQw1aBWVxRfXlNrqx0ObZD -HdxyJX/wGMlV41r50LlyMOH9fiULX0ylGI9HtTNkxmUWtj9F7ATHp7qPdFGMoWzV -LOoR5KqGmi4WhE3t+02wmlyeSXe4T4kiLGZ6T7sR6szjNHUFkWgwe2oFfd0HZDvO -wC1HoUKeRM/c4bP+HtNo6ZeudSbXd4p822WvqbKgDldXqeq5KUHye6hQfF06E/mH -2GnHLiGBvgMIOERitm9OTW4V2hPDGOVsyfu/fUdWoo0AoLmfDStRk7zqt8mkpRyZ -sfqltTvbCYA9E1GT86WjF+Ugq2iEITf9rQZAyAb6pNM2CWyLGihjKhXRvR19w0rQ -33KlccnDwbZMCwBV6njWnNYF5ir3gWMDvTaC+DGUbACNHo3hVQyHWEi7X5YdbBy/ -1Y94+5pbGohTQRWuMmwzc5sFWeweewoXWBsauK4EU5P4WxT3D8iCr96qsftmTn2V -tD3k2W4vXBcqZkIswllqSQDYSnaxnSe/cUoYm3iehZRQutZ0PaBWmOy6jmJpEU/Q -RTWsu7zyD/18o+yxkZR68eQn11zbIuBWjj1xDeqmjbYkh8XDC1Q6fVeFJxF9mhyF -ttK/SPXuqyBi8eX13ViPEbIVOLpsr6S2ig3hN0/OIWVPblchYEXy1+VV4nwhA8Np -J89pD8vfbcVTDjHCu9HhcMdT/zFsWehe8yw5zM3WsGx6NB/xJS2onRhs +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI2spAA/WpqE0CAggA +MBQGCCqGSIb3DQMHBAi7csj8UwjU3ASCBMgK0/gob5gOgeDoZVERabnAazadQ7I9 +/QuAc75PEkl99YfjhiRXJyWWiOKNkGjgqTsXEfGp73/c3ilzKeoOtg/lhppZJ8VZ +z2ePXO+BOx/xlgeLj+fEmXAjKZZBJ76FCUH/P6sWe8MTLMN1g67QeK6akwj7KCzO +yPNOtL9FJbcq/Y0HxDy+266G2Y9ZVwtY45uOFXClWli1aRMz0/FRt7ijr5x7JsZj +kqUgB7qPl2+wMEXLhU/m8Gn2JdkxRsrDn7Hq86TOAF+CpWpjxGTEZFqzrMcVXJ2I +2oXntqwQdq9clLaMjPNP7eGZ7tmu3cQX6IypScZirJWgsb2+t3Hv3108wS9WZ7ZS +eTvg8rVgrorP8lMPFqCuljEZyIWryN5EZ85/WlxjgpZQnnvEmNgckPcQM9KfjT9l +UXsd3yaS+K6vA/NMgutSEQSFXLilpgr6wz19IvzIEeaGIU78GbBfSK/7kFWSb3WD +mmub9LN9CKgwGMc640hHHY7EUX71QIxLitcA/lIxftnjPQ5brh7P+0gwray01i1Y +SGaqLPNbgU+tLC7WnbadanTYRuMheTLmMgf8aIOiU9IT+JFiwm1s0jcVLlZyIsWF +HH9xNcf4SYz1lUGcHnn/IlMd6PGucicmd17Qewi5Y/vil48r799Fr1KO/GCbxtkP +qMjVqql1vRIo6tY++n9uwnTgg5NGrgLsFAWusulvEaC2BCTh1XqwtIC09zaonhy5 +30nadFWDnmR4MpPksjCBs5MCt2dBNF72JH/cFSTH7JpqDuthMJcprKc9b3MhQEqK +srSr2HnDlOir6Ubvz2LCyAsuKui1B4UOnZ8q3lHPjIXHCZBWcdj+hLCmgncf/Sjq +xvh0AmwPvn+kcG7W1DQ/ZfG7uh5oui4F9laVV3nuyOPzxdiuNFqYjHLb7rVgQOvK +jjHYhd2pJAYDO13GrXVG1H2ipEUr8u/uDlr7HLdtvAZqsTSNMQZk3t2/TI2nJDli +BPyJO72LVvwV0Jy5yH24qFwrzOmOcnNv1H14hPdwOOvhEQIWbAXRPTdf/ukC7HEb +mKBfToPHALxnKPmcp9iERkcNZ8OfLqRdjCvZoD7K1caZFqv9Uc3U2kaQT0b9lm+1 +3UDd1n0YfxA/iJ0S2/KSroDAt/wWnznuJ9PlzpQfZ2BqlAxeFQ0RH1K97D6be5IW +bxFxwkOwVK98j/g0+Y8/I0P2kNYH7WZ0ipkyM16TuhzUMKIuaoFxywwWaZg16F1x +YJsKjjpDCAWAl1fARvMiUHko28drBRGbFzrRzBwtE9+jxGWAF48xStswrzQV2/Ct +8Vll5BAfzSW8MLlvgJUECxFMOgsjS1GveHDcmEQ3z3JWBxGEXrYOYj0iDFNprrYu +Q5e7q41R4BL7CxN6JYiLWJXw3K5hXEzaS8vB96r+2CCRMw2IQ2n7OTBBsEIqIV5f +v++PKOwtZKpasnA7lblRZp8M/XFSOj591EBzwKGsXkOme7StZTngKjZKzf2xE56p +TRPpxNeyi4Y9U7QuO0q/AOcQG0spI0c4X8QlIPwByL1CvVLiWnnmlCiU9g8fl0pk +pVFASYyQPe0wAMU5C+zogf6K5N6rEcLbM3kNbvNE1zvPgzZpkAT6W41UZmB2828C +Dx8= -----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 b/tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 index 2626d3be8..028177658 100644 --- a/tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 +++ b/tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 @@ -1,17 +1,29 @@ -----BEGIN ENCRYPTED PRIVATE KEY----- -MIICoTAbBgkqhkiG9w0BBQMwDgQIJ5xD8pUUfDsCAggABIICgKaalc1M4urq1NJ8 -AJoiuAcp1sNon6FUdDUtcQNFnG9H9/nt5FseYBA4tlRtJq1Qj9ow04VViJB9guTp -kxEt2onIyPSwblGtwkM0mboyVilmqyWEPWzI2T59nphWTnLfSmBSs756k581duks -qtaIm+yvUyI1cA1BHHaOhMApgNFzI7OFkAto55OG7kfJgcmMj1gSjSpNJ6XsofEp -BYLl9yPzbAF/Cxci7zTiKhYe/FbvW6qEJw+EKk5L+nKx+UlP7Ssjr+rhmeB142pb -7x4Zbelyo4SipWSpru7dZEyKFd/ZcXByoORjQT8sQaF36zVXmmv6gURKrWlznfFz -WwaeeI+4erld98A4tXuRjwmGbkzYnUNjq1cz2y7zvW34Dgse6KaP1iOsvmHA7K+j -hJI4jJFHvCRDGxIFZm4qZPBapPWqlN6vRJSVAX7YASqRcaNO2m6Y0umUgCtab2uF -k4D3ahHMg0XtcLvEr0HaklGWT5YIkcDuH+Los2NwSn1z5Q4nLnmLBfmfm75oKv1O -X/f627b4MLQxAnrcjQ2Wk0sL4a+Rnbenbi7MlyqA7Gz9fxLQdB7qrRehAiJxo+3e -ddhvsZ9pgZeUY+o/QkX4t4oxG09BhGVF5l+d46FU6hgPjFeRiSt7st5SdU2MK4la -Kqw6a7rDpfhb6WLMsnJyN0JwOaoOoy4UOpZYrdvSHwDvHur8YScd2DsPLMQMs0Zo -1mjfsYiElQLRk/wSjpyqBw/3ULFTsM17Z4mTgvTdDzBd5UycvbGJ/tnDV0cpXuJg -FVboPYqrGk5ChPePubyRa2e57HFQVu7kjzuS9NSdnKr/IVEr9Qn9OkRmprpm5Y6J -PgfA5wA= +MIIE6TAbBgkqhkiG9w0BBQMwDgQIuIvpaVfmxx8CAggABIIEyMeuOVWbTSBwOkM1 +W3SdLlK0quEYilKanms32+3L7esusdyVU2u8J8tiiAvh84/xaCet99V7g/qYIYE7 +7wHTuB77BPGHRMZCKX2GOwJWxNVWUimB+kUX0yYIUwJx3CO3SExVPd2lcjnTMq5D +PtaIHgJsPLU8wE3A1sVEGnfjE+73JtU/NJ7tS49WXNvQGd9ZeL4z3SqWt4HWmDdE +TVOiAcQ2V7xrpfLP71ElW3D9oiL5Ba7NTCSYtLNfpQOKTiz8QQWzpkT1+IXNZvig +yyYsNEZDzHQLmZXJVPsbHL8eoqzEpeH7mz/guQPBv1Rl8/PoiNY1bT8RV+EIp0Ne +6FNv2OiQtV50XNRlM5c3gS9RvWEYwZ8PCCc3ZCaRw5dH1dghiBk91i17//GLkyV1 +gZUNrT7YqlwPBiksOwFYsGPgWP7tT1aKeEXaLXXtx7pIhRqUN9IJFSVs5hmSkSmk +a4IuZGWEhhXpPm8cKsmrrMOXH3t48qR7OwUaERhcC4Qr23J1/8Whh8xNabIO0VXY +HCiAdtlMO70GPlYq06lM+L5eF697qB/065Pf4bhjav8rs5QNvt5GzWWYo9uDaEib +8n6tuOTxcf6yoe2fWgEpRk6jh9G9IS89pksusKDfizQg68q/Na1kmor7zT2FJAbC +S/VCOfs8MH2zd8ZnEsvoUhR5ibjBU8aUe9ir5OT5vjaazRLpod2X7LKWdcb7irZA +MvR9e1L+Z3RPLPoR8moYxLXZjd4F78rDDTYVFrYJGZTRmkJ9ukNzsI2ZzeRzNhqN +kHDsSsjMYCI/QkTOFCOmoNrUOGiH1cXqRc0JD5PY7FRS+8qvw73uAFV7yTAmxikQ +5IeNZvD+zJ6cvDb2ZR5iCmTA2f5uxsKl2hBe6uCdLLDPtlYHS0ZSmUolco6JrkDP +ns5BR3e06C6YeHwM694dTGeffIFfKmVEkYBaJ8Hcuey9I2L2N69222pPcrUT947o +TCXgZdjTNKSQEvEBPDHo9GRoJimnZODomJ9f/Da7BBIp+gHfE2rTS2+rUsU+5Kby +AXJnaLpWu9zgSri6lNAtQZkmk3haL255AtycyLGuITxKTxjVSmZBQV/6zQQwcJNv +e9PGNpI+EccjdjcI/UxDnW9ShuBbPTClrFmrE0jQjg4LZIR87pSO8jaBpg/2Q5ws +nUnLrHbXuHuJqeFR1gg0zfkvulS5ldPdqDYeTEOpATmTcFHYTolwUa+cdJbeeo3P +6s2RAyY9eGOgkgW8P0/nmfaHhVe8JBaHATx9liB3CFQ6kiU63YcBdgGdyzsYcIOK +MR20MT9dq4l+Sij3EZABFqgCEypMgt+TUlzIXZbWBSaWmi8ScFAlQw9LmVuaOMMV +hpTIuCenWVJVtWaHUIZkT316uENX3rQnDm1jR6UBSxFhKIsh+afeQMS6F656giAe +rcwqkIDbglfvhN6NmjQppbfMpmiFE71XFmPBzofC3MvIh/2hB9tvEBnYKoJCMy1c +XEbHynt7bRDm47Ev6gjAVWMZ1h40r79vvavK/vCA1b6Nd/F4gU+lGdB0tj/Pv2di +4jvhiyE90tDCSHAe0BOnPFdWkLvru9BU2xixb/pegRT722jZj9PJb4jY79wT3PdM +QHb1ZpXzRuidMI1ICQ== -----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/user.pem b/tests/hwsim/auth_serv/user.pem index f0b0962b0..66be8f81a 100644 --- a/tests/hwsim/auth_serv/user.pem +++ b/tests/hwsim/auth_serv/user.pem @@ -2,34 +2,43 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:25 + d8:d3:e3:a6:cb:e3:cd:65 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=Test User Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:a6:96:2e:9b:22:8c:df:94:be:8b:89:49:f6:78: - 76:a2:60:7e:14:95:f3:96:fe:ab:19:25:03:34:64: - 74:01:3e:a8:9f:7c:f1:47:61:60:4c:82:92:28:7c: - 2b:a0:0e:cb:87:bf:59:eb:d7:f3:61:22:3b:14:f3: - ab:31:f6:5a:95:1f:b8:7a:b8:2c:3c:a9:61:53:78: - 9b:e8:3e:50:ec:c2:d6:44:e7:43:cd:bc:3e:4e:e7: - 46:fe:92:9e:c3:98:0f:29:58:c8:cb:89:01:75:47: - e9:95:57:0f:76:c5:2f:05:5e:c7:1e:0d:f2:3c:12: - 63:5d:b9:54:19:af:7f:40:6b + 00:bc:24:08:d9:07:6d:19:0e:94:5c:6b:d9:8a:84: + 1b:03:22:e2:1a:06:42:d3:0b:60:8d:5f:31:04:06: + fa:a2:40:6a:0c:24:29:58:cd:83:bf:3a:9d:7f:37: + 0d:4d:27:5d:d5:57:57:1c:f3:be:75:3f:3a:4c:44: + 6f:02:2f:5b:8b:2c:b0:5c:47:29:19:31:08:d1:28: + f5:1e:9c:5b:9c:b7:e7:6b:40:35:10:3e:7f:66:67: + 16:a1:4e:68:8a:71:cc:32:58:e3:08:87:a2:2a:07: + 2d:7f:73:f6:43:e5:7f:f4:f6:74:ae:27:e8:d2:5c: + ae:9b:82:d9:a5:2a:72:76:84:2f:e3:62:aa:41:1e: + de:33:b7:64:f8:79:6f:fa:09:b5:bc:b0:8c:cd:34: + 82:2d:c4:10:55:89:ea:6c:38:92:fe:61:d6:64:84: + 04:d4:0a:37:32:37:8d:c3:55:d1:fc:ab:b8:55:06: + a9:00:4f:31:e2:42:f1:e7:b4:2e:9c:45:0d:dc:a9: + f9:ad:b2:77:c1:f0:b1:c3:a2:5a:26:90:bd:19:2f: + 46:1d:a5:21:3d:f0:35:62:94:c8:cf:33:3f:d8:a2: + 5d:df:cc:58:00:08:8d:ed:b1:04:c5:2b:3f:1a:15: + f6:92:08:d4:f1:42:cd:6c:db:f2:ff:e0:6e:69:84: + d8:8b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 81:DE:DF:E9:5A:00:1A:CA:67:D6:06:DD:65:B2:4E:C5:9A:04:43:7D + FB:85:00:A8:DF:D6:0C:0E:A7:E3:39:61:D9:BE:CE:2A:EF:6D:28:D8 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -37,27 +46,40 @@ Certificate: X509v3 Extended Key Usage: TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 98:05:c3:45:76:9e:87:4b:6b:68:56:71:81:6c:3d:99:29:02: - 6e:00:9d:fd:2b:8a:81:c3:d4:57:f7:43:34:08:df:4a:f0:59: - a4:3c:aa:86:a2:e2:06:3f:2c:41:b8:db:aa:e1:25:b3:8f:ab: - 85:ff:da:de:e4:3c:a6:12:3a:25:27:c5:17:f5:6c:9e:4d:54: - 36:60:df:f1:95:8f:dd:a6:97:13:ab:9f:d8:39:1f:88:29:3a: - 90:73:65:08:78:e9:64:b3:c0:34:a2:b4:a9:8e:b7:f9:f8:3f: - fb:b6:cb:58:2d:55:2a:57:55:b9:08:c1:6b:b8:f2:25:a2:9a: - 95:a2 + 94:10:ec:75:db:4d:98:80:bd:b7:b2:b1:4d:b8:99:0a:ba:e1: + 47:d4:ef:50:48:5b:89:97:8b:ee:ee:56:2e:e6:ba:2d:0c:90: + 59:29:a1:c9:10:08:9a:c7:e9:57:42:5a:f6:7e:72:cd:d9:ff: + 8b:b2:13:6f:6e:e1:49:04:a5:82:cd:10:59:37:a5:9a:b2:2c: + 6e:a7:9e:ba:1f:e3:b7:79:79:37:65:a8:9b:49:39:c2:13:7d: + 6d:a8:37:23:c4:10:c9:73:25:67:1f:78:fb:b6:86:00:c1:1a: + 60:d7:5e:b9:63:c6:43:41:dd:37:0f:39:c9:fa:ff:8a:f9:62: + 59:00:e6:91:cd:79:28:82:db:30:88:c5:b8:79:8e:63:4c:65: + 50:3d:d2:65:b3:45:62:e5:d1:6f:1c:c1:1f:c2:b5:1a:0f:31: + 75:62:b3:7d:0b:8d:36:f9:43:eb:26:59:59:29:39:ad:37:0c: + 4f:95:7e:86:05:f5:70:fa:45:de:3c:f5:7e:e1:29:bc:82:d3: + a0:63:73:a3:e1:25:f3:5a:14:2d:c7:78:da:aa:e2:8a:df:08: + c5:be:1f:d3:9f:70:0b:7d:ea:5b:f4:2d:22:94:e6:95:92:50: + e2:55:72:13:c5:a1:3a:44:c4:25:18:9d:9d:a9:c8:c0:ea:7a: + d6:76:91:4e -----BEGIN CERTIFICATE----- -MIICeTCCAeKgAwIBAgIJANjT46bL480lMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMDExCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTESMBAGA1UEAwwJVGVzdCBVc2VyMIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQCmli6bIozflL6LiUn2eHaiYH4UlfOW/qsZJQM0ZHQBPqiffPFHYWBM -gpIofCugDsuHv1nr1/NhIjsU86sx9lqVH7h6uCw8qWFTeJvoPlDswtZE50PNvD5O -50b+kp7DmA8pWMjLiQF1R+mVVw92xS8FXsceDfI8EmNduVQZr39AawIDAQABo4Ga -MIGXMAkGA1UdEwQCMAAwHQYDVR0OBBYEFIHe3+laABrKZ9YG3WWyTsWaBEN9MB8G -A1UdIwQYMBaAFLiS3v2KGLMww59V8zNdtMgpikEUMDUGCCsGAQUFBwEBBCkwJzAl -BggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzATBgNVHSUEDDAK -BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOBgQCYBcNFdp6HS2toVnGBbD2ZKQJu -AJ39K4qBw9RX90M0CN9K8FmkPKqGouIGPyxBuNuq4SWzj6uF/9re5DymEjolJ8UX -9WyeTVQ2YN/xlY/dppcTq5/YOR+IKTqQc2UIeOlks8A0orSpjrf5+D/7tstYLVUq -V1W5CMFruPIlopqVog== +MIIDkDCCAnigAwIBAgIJANjT46bL481lMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMDExCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTESMBAGA1UEAwwJVGVzdCBVc2VyMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvCQI2QdtGQ6UXGvZioQbAyLi +GgZC0wtgjV8xBAb6okBqDCQpWM2DvzqdfzcNTSdd1VdXHPO+dT86TERvAi9biyyw +XEcpGTEI0Sj1HpxbnLfna0A1ED5/ZmcWoU5oinHMMljjCIeiKgctf3P2Q+V/9PZ0 +rifo0lyum4LZpSpydoQv42KqQR7eM7dk+Hlv+gm1vLCMzTSCLcQQVYnqbDiS/mHW +ZIQE1Ao3MjeNw1XR/Ku4VQapAE8x4kLx57QunEUN3Kn5rbJ3wfCxw6JaJpC9GS9G +HaUhPfA1YpTIzzM/2KJd38xYAAiN7bEExSs/GhX2kgjU8ULNbNvy/+BuaYTYiwID +AQABo4GaMIGXMAkGA1UdEwQCMAAwHQYDVR0OBBYEFPuFAKjf1gwOp+M5Ydm+zirv +bSjYMB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMDUGCCsGAQUFBwEB +BCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzATBgNV +HSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAlBDsddtNmIC9t7Kx +TbiZCrrhR9TvUEhbiZeL7u5WLua6LQyQWSmhyRAImsfpV0Ja9n5yzdn/i7ITb27h +SQSlgs0QWTelmrIsbqeeuh/jt3l5N2Wom0k5whN9bag3I8QQyXMlZx94+7aGAMEa +YNdeuWPGQ0HdNw85yfr/ivliWQDmkc15KILbMIjFuHmOY0xlUD3SZbNFYuXRbxzB +H8K1Gg8xdWKzfQuNNvlD6yZZWSk5rTcMT5V+hgX1cPpF3jz1fuEpvILToGNzo+El +81oULcd42qriit8Ixb4f059wC33qW/QtIpTmlZJQ4lVyE8WhOkTEJRidnanIwOp6 +1naRTg== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/user.pkcs12 b/tests/hwsim/auth_serv/user.pkcs12 index 30fd179696476b6cf1e4994635c0376a06be4445..13d97acc9db0440fcbeb16bdf9fe95caa856aded 100644 GIT binary patch literal 2517 zcmZY9cQhM}8U}D8iG<>_8m(Po1+^Ph4MmNjwy&rvY8Ib8ni4UqR%wk;rM3{eiCNTM ztxc8EPO$9^6BDEq98K`Ngv$4=< zAQl>a5o4sVz#IQm;A|{VmVz;TA0A;91OeIBW_E9;r}&jrt>{uoqV8v z$sCrv8OcU6C45`orq z(v54XURkM;Fgu$vVz`TJ-tV6#?^LG9T5OiZ9@+9+$_47gdqB2YmR{%lVGAzoG zVoN!b$br{|4=UX@n^Q(&f;xGEkgVS`J$uyo>9Z`F!DcO9#R>s|AF^Eoi9=$m(W=z6 z@0~@Oi7_0vr&mYPqMSrpPAtT1Wg&IAAqJZ#Wx56%6o_FzAIxGrV<^|ux4nQ&sf?5_ z+A0^Anx-{yPnrw+88^iPo}F>$s9?0=-&6zD=}fHe{So!uiAZ=lSvCL6M>3Q6_8>P? z2Hip!^>o-MG*Yxq{4%zQoAe0w#y8&%X#)>jne-L%;TLN?}2&{{uue79<12f+R0uv5OM|)BlGHI%>d$E1MUf ztp2|uJk2wKZ9eUNe=7pS0=uJi%-=@&00)=fnXaXW0J4#{k`dB&~Cwy za9SdOk>hLcy*Q00)j1#QX@!+TTC?h&RXPx2Q0e`sAH)h)!1Vwxu}tmNOUUJ%1Bwme zvuR=JFPEc65qTNoD7{w*0*j&2C|#U6$$o2=64(C~@fUMQ%*eZyk$d+S^~MY5Z&nT> ziG~he%NgQi7FeNjq$8^}U93I~cM5Tdvv-lpb7C5mO)#zs6+gPiR=Vl^Yd7+0w4v1z za#2+Ktd-HQWDX7Xhi>aOAW~!jKJrS5u;@us)>Gu_R&`h?g(DoqRyyXL6aPlxJgIRF zdDqCDO+-7ArY_b0HB;lru!6>8|G53WW&H>3eGaa%_*BFKz=%#0O^b4&+1L|!QShJ% z=wW9u?~yZYcI@k+oVzH?jf-YFwPcgK0cD#1U_{6Y!4*TcQHLx88F@w3{#25@KJrW4 zmb*(!!8fXAx1v#gJCnVwuhQB~PO=gn%#uWd@rkr69#i{QKrXTxqU*D*nu8}5LWRDD z2E?~1&NSxRQz<c);2w{Z|u-q-+Qm;FBMy>1;^;rlwJYNH~L_LiFBEd8_Nb% z90#TvA`E28?GVmK)wyF~msNP4hc)ab^6J<4z^(p-sTDoMxTazhqDXtfnU^>P?76J% zvkI7Y0!HUO^IeWZm{AIXawdX)P_k{&nK9ou$lgFp!~BhzeX=6iyZ!u=n5E}v2vwdn zx<@&&_yu`A`O;>rzI*u%niT18vstt36uN+{r#>&&vWNX46H=UfHuaBWq(iKFlcJq= zYvL)31-A1-%y|ayMV*1I8zhqXDQ+cor}-#Fj=$1Ak@;3fjY~efwuF4bDL-A_vNyDD znFQ0oy+h;X5=?(&bZtVm>dyWo8NGVY@Asivv7oou8>VBUxTzK%y|wfvoFH5oc$3Mh z>d7_z$B_0o45zXau@9Rvg zqTSz>udRcOO4c%FqWPsAQxBQYu1#Zwu~TO}J0fm~!1m52UNo|Vp8EMfcFovWNefdMlU!(v<&}la7DwUQk6n5=|_s~idf6SPq0iEy+)fyufK+j(pxGW_SuS|{u zI55=N-9D6=A57P69~}_umu5-Aq1@VEf=breHbY_s=vN}Cd%**lhdHWww2CU)mbsh1 z4mG1PzG$e}CVzr6qxR#giWujC&X~ej&O1Hv4fL*fnQ|_$m~T2YzUd=Qf_0cS_0=g0 zQEemLB_jRS5F4tJePKC3xa4fD)XT!>(W%TXe{874In`L9x5SGA8pD8_ZhSsJ2O&y@ zwFPzp#^S>|5fP;c{hvnmF{ryXE{bP;G|^G*6Sv8enp6|A8oT3ns@lV);Zg$s)e*`r zeHqB+{0g_f-GcaSmQZ8GrCjR%8ZNsbB`w7-1qFi;j5L6&ASxhR6D2poz+lQDHi?z3 Z=Yybp?>9~Y5Tet?-8PdE$nv+6{{le)5cIJ0s;sCfPw z+nnu>RAgI}qo&FwGBp)sD%*=}Br&LCrw9V3f&r^VYdll~`XCKc++APw zWLZ=pAWNI>=!SwXC@keiI#Hy)P&(Gqy3QlXeAh7~d!&T>Fd~KW4=u>=Sdj@!8B)K0 zx5nh`L&6t%;*}y$Ynlv-FZob_5>UxxJSe4SXDIU%Fqdjkx=(oqR{2T1%lb~AasnqF zM2fUDfPjVO<4}3BN|iy)&9l;v2Cga?x#>lANx6Qe3EL5jIXoqVffBc2|%)s_+0IQf+S)*A* z__E}Pt3C7et)NPCe48q1#t+%iPEH*D8OVMEOf+6w+tAM@|8;RB-(|IaSHQe~oHmQT zCf=OhA_bNLx*C5KGL1kcgCLUJZR@8#^I3z`Ue|s@5f9y?xl5stYT3|F`_1UFnTp^> zjCCSceuW>_QteYdNcZ-vQ00kXe76?7&=f`Z9WOEN2PTZr!!R;{N>Co16rm~h!vhQxiX%~NSADk4p)WT9dB$=?(kfMdL{ZuH$oA9Q z+wTSZh0Ek^#1}K1TO;GqWzmU1-M8%k=6KJB*vWB!Mg6o7aFB>+VAdMkfcErib0CXM zD-UTl&|M8?jDiyij05@SxfBasCN9BK)gOp7I8xU<}iW+;xK{&-UbUQhDe6@4FL=a0Ro_c0;Vv60-`V+ z1_~;MNQUyb z{p)X*2sJVfxYLwpklPp=gSPS6Okl;^El{>R_PM6&D?0@6Z%FLqBCI4^etwJd4R z)YUyA?lrPaMlk2XbYC6EC%?&!i2%?Zty73hx$JaqlF7n&E`)>1A^hs=rw6LR4dMyf zM*d~hnY0zy6+GO%SC(u{L^Wa-dImEanP>dz;ENW!f#2(`!ff~1>vUZjcfPTQF3wl& z3vA1>56cHt%`0$!>sI&fBrs^oaI5)iKJS2tqrN4|)}Qkhn(Kc84*wEwJ8MyF=6RRT&bR`&R_z z0=V+@s+GO$#j0~u`(UWex$}K9K_}GYp@pe;sbFTvO7o$AYLcYs_hxg$U5J%7h!^`H zwc7*>NswDD{K5IM<%^?7jZfWNRPH;5?4;7_D=oIC&wFN7Q8uPnLkaQe^gYRJTIoGA zy;qozvcxzKRV-%e9;1Yel6DK$M^wCu8)XDVyQ*G-9zB`OLG`|5%`1EHCPip|NXgM_ zrVsDp^g;lC4Ph4Fs)n_vcB`SU0TWIu#2?BNlaUajBylje5@$jx*TT8lY=nmDj4-?smFXQEwIDs;5%)Eydm2K>XF2|d-h1H-`o^j#N(Q>LYFhp&ogW@ z_iT1Kw*QlC*QLI7`1F*=G*EnJJl@0|@q@=yP->@t2rN(BckjWO+O8?>UXirn%L2p@ zDjkb?;b5xau|^etqIr^KK zH!&qJBL)d7hDe6@4FL%iF%|?Ag}l#`rBO@Ah@NLL|0g-m0s;sC2C4#b diff --git a/tests/hwsim/auth_serv/user.rsa-key b/tests/hwsim/auth_serv/user.rsa-key index 4c3cfbfb9..c77924a3e 100644 --- a/tests/hwsim/auth_serv/user.rsa-key +++ b/tests/hwsim/auth_serv/user.rsa-key @@ -1,15 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQCmli6bIozflL6LiUn2eHaiYH4UlfOW/qsZJQM0ZHQBPqiffPFH -YWBMgpIofCugDsuHv1nr1/NhIjsU86sx9lqVH7h6uCw8qWFTeJvoPlDswtZE50PN -vD5O50b+kp7DmA8pWMjLiQF1R+mVVw92xS8FXsceDfI8EmNduVQZr39AawIDAQAB -AoGBAJBKEtJCidx6nNSFtK+sRa19gJdaDqQhr5dW7MCrpaMSX8HM2bvnBx8eFXTF -oI/BYN8SidNyuBbRLHWIXScoZ+nOhmLChexxxqNlgOtVR8YKkQfwmcwC8tiUf968 -xJb61UOWVYdeQ4qTacH8D/W1uj/fQKJj0FZ2d6dR4FOViuvJAkEA1x2xVGF9yPUm -JUeCYT8uaL9kPFh7uKfa1lxgTu+bku39xWQmxlCymRDrIlRW5aMlHabyyHe8L29+ -N2tRADpwvQJBAMY/VKrCjAHZV0w60/TXEJiSlreevIBFeP+OX46U823Z3RDrQjMF -gVhL/0soloFncD3gVYkRhMj65C1f0rXnrEcCQQCHzekLmlisq4efdVusRRTpcBq5 -tiq1UtLnDX6HluEiizjwit+nx35Y/8NR8ujBJJPj+me/g0e8sqh+GDQU7tAJAkAO -7mYqFk0FNqFklGmyXyBY3XGMkuAPqSvb05VO39kVxPrpc06hGSEMzWyE9KGhTXEe -t+65TCB8Iqlc4YK1QKWxAkEAyuUKlxOmdlR0zRJwpIvWL5IIz4S8UooUDA0mkdBD -ZK3tDnLRVLn28Mx+wxIc1egkNVMPvQLuQDhc3G9bXxnMzw== +MIIEowIBAAKCAQEAvCQI2QdtGQ6UXGvZioQbAyLiGgZC0wtgjV8xBAb6okBqDCQp +WM2DvzqdfzcNTSdd1VdXHPO+dT86TERvAi9biyywXEcpGTEI0Sj1HpxbnLfna0A1 +ED5/ZmcWoU5oinHMMljjCIeiKgctf3P2Q+V/9PZ0rifo0lyum4LZpSpydoQv42Kq +QR7eM7dk+Hlv+gm1vLCMzTSCLcQQVYnqbDiS/mHWZIQE1Ao3MjeNw1XR/Ku4VQap +AE8x4kLx57QunEUN3Kn5rbJ3wfCxw6JaJpC9GS9GHaUhPfA1YpTIzzM/2KJd38xY +AAiN7bEExSs/GhX2kgjU8ULNbNvy/+BuaYTYiwIDAQABAoIBAAFRU0qJ1cbGJl3b +V4Oz1yiXdvPttUwbGUsELqizj8/RGa0KF8wKbHDLbUz1yr8Oloam/PIz9tKFZdgg +5pIiWMbJwlZzHSOTB1fHrKfROocHdrR2l6iMd4H1GOB6VxsZHu//VV+663TV5git +fD0Pf2zsyPZrSyMmCQcHzJRujqyrz0KHi8KGYjA7wN50vGv03kzzVyNZnexh3z16 +jrpgJ4FdBOBbk+135GngVc2rWlErWA/VhIY7YhGoQiVqrTe1P2auKigel661cnvA +YsQzUX/0J8+Uj64VpN61jxAKjwXKjhIq0GqUACPnve+Iq6MKtVjlFeMQ2FqvEKF6 +zFhcBRECgYEA48MbPovj993n2nk1xgIyv6oni5+yb5xyMQDjyvqsz2O+W9NVNCR/ +akSrNSdncVEEBVrtq1rWywFQ3/Hrf1ES/GQKgstlPBzlCbrvsfZDaC0cURLmPRIT +HkOj+nJUxsdX4CHPQV7E/lIzCuiPkdycGRMC2H9xPNSlPQpiqQn1GcMCgYEA03dk +0bvXyG5iKwH+krb7Eg9jlkP0QWrzRKSEix+f6K77d5F8vSOmwMlvhch2eOttAhNu +H87LVh/JdxdYyLwn99sGvHE4tRAO5UYfIFUQtLNgnRE7Hu5VB06qqKjunJE/adGS +yx32wC7MtIyDmVJ6NLlYGD821pL11o++kNu7kZkCgYBt/KoLakKMT/zG5AGzvRwE +soamRlhEzafXQja+ro8FF4W1kjhzFazyBHcpE/5AGn92lpJvTU6sedY0Tv8KXHxu +pWDuCIq6nLl+GWfm6KVkiWRDQn0swK26z69AIjYOR/WHpswPJVS7+7XqbqPmLEK1 +WRjms6RbW9TvxTQfrU9PQQKBgQDJRswsoTmrKf3AZ96ScR4au5ETlsync4/nFxyd +e1VuWRc7YLw1Hvj6aQEAeqThRVx1bF8WYXPDHvBYrV0xe34jeVM5DB9on8c9zXeV +A8Kp7E6aUatPLpS6JtNjQ6ASYGHWa8boFDYoCKOJenFL/2gYRQ4nzgt5Q1pBhoJh +SPSIiQKBgFDCIsrXle86q3N53K52Ljb4PdFXgOwjGtEr5jjGEtDPH1FB7W7YX6+u +HNn1jPSRX5QKUbVZB0nJUTCNUaplVkrw6kuJMW9DQuR4loqER29z5RKi/BdO+pck +g/9ubDcFsB8DKtTCTzou3BF3NWLVktulg/wunWrleRZzGu3l9Q9y -----END RSA PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/user2.pkcs12 b/tests/hwsim/auth_serv/user2.pkcs12 index f2eeed8f62eb21f618a1bc00c54382339312f6f4..8957a56556a620489f337cf14220196f53476688 100644 GIT binary patch delta 3525 zcmV;$4Lb7f66PB~FoF%@0s#Xsf(@t!2`Yw2hW8Bt2LYgh4VeUj4V5s04UsT{2rmW+ zDuzgg_YDCD2B3lnATWXm90CCVFoFmbkw6`P>R~mktsj^i0s;sCfPx3;5(sVs`QIx^ z@kK+Lb`_(aj z@LSPf<9VQ!-)#v|B6Qc|0EsRKgJ!@4J5tw?SZB+Ba6y}ex(AEuZJ0;}Mu((&&PGjN zAKbV^J6@*z+i|0&Qolk@Vh7rfG#dggh^$CB^sJQa;yvXrU-k!V@OO-6HfhYfai4)! zymn<9ai(PXeold9eS&qRfp-Kt!Po46w^y<>?e(>2EwY^dqcRRtI;2N?yr~C-FEY`q z_KpGWTQwM#VU4g^r@4}@4#4%dUsgOSnTYygpDV5bt=Mq+2^1 zstwq^;*4teWIVH}Ms0Ta(Q7;Ai=LuR|YaNiuJr z_`aW+_?fe#Iqj-5#=ks%Fdp@Po0ABFN~uRJQ$7?>Cr{1zsj~GA)-cZo97{8qrtze% zYm;<74z1%(sPkF`xxKso22>#yPO1c-9zA^onI2kyb(y4%FP_R& zLdYK}COdDcJOb{{osj+W)m4lWWqy3yI=ixk`tp2&O+QFL(wmP;-|qf4E_w14U|QQw-H>A<(L{c;Bykb}u< ztgURG@}ou#H|YVMnsr_%bDMT2!MDGDX!{{AkZA*jWOOZmR4RMNS6Q4Y%e)ZNXguxi zsQ*y^jM008WPZHKBKqZ&Npwt;X#L0CLBZmXZj`sHiy#vGkwdiOFn(KOu^1gEa*@aw`>4_5NKkv`53`ZCJ*NWrDf*}34j`nMi>?f@D zut>L!!3mIg#l;L+`L$g6DpmCDOgsKgE3E592c~gKVI}pbf6u#zLAuqW`}P}cBz%D+ zm}Lv|zQh{w8UZiXpJ@TwJqUwD+&q4tJ@}x1VORc&&AVPS$7E&;#TBsIY+le%vL(SY zAx=|X@*1;0Kqb44l7Xi-Ut^Rw1f_*#Mud#pmOLt5!-hnOi+R?Z{+P!_TZld@R{(n^ z*Uh9*oTwSzr?yto@dOI(B7sY%@_FfANpgky6W&9u6eC;2z5Z0!rg(5lli=7wdt#k` z0B$-~(p0jcRjMyJUb4vkES%?Vkx7vaw@oBWti$xXh@!z@w$OQufgvBUW_WZahUJh1 z_mtNGrUX){a$OaYbzQ|WSA^w|th);VP%p@ef%hrXV9_uApY8ZFi><-Iv+K$7i6h%| z-Xk2}O=*lXEZ|N(H3DpVB^0k>A@|sSETIr-8%)(QS2q9!;!*`D;fKn;C&49YYfJj= z&LNQUi+MC3%$hKAa3m3>b zHI3b=>f(~)ANzWENo4w-mCks7sAinU>SSMkU;bzU;i41VthQv53p#Odfd!Ac%`EqN z;ueF!YCXdy^omMphmuxK=$raI)*9)WuEJPsPmoxfQ#J|^&IMfp5;B+z)UIr zitO`BFFCJ_fN&*mTP4LQqrLE_QYy89C-$GbK(lV7e#GI2@Y*UvtosLlN?Z+347m4L z++(b}YN$4Mq6rdKhp?1Jc<7U!$n}G{+A+m_-*RqLcC-4R<}GliJ0RsLC@JZ&qD2yU zYOje)77SZb54a2lPSO2gbUjdCJ?MP-)fb&ndFC~C#_z5i=))*<{Hu1Nj&Px*SG8_1 z8&5>F{d#4~?J@o@IG}QWg_j6UIuCt;>v9lDrB@ip3xjdzN`Am?guX5***-TyyT3Zl z)A?#aQDR@^5xb>JRXOGLt-Hk-Z)N2Zx$;IyC`9OMbaXgI=Kp-;+jJsgmZ}IC?Zu*Pmrne2JRJ>0KE)<5Jk!Mn40eibCRgp zbtSje?xvTemr7~crSbUuTZX#XkB7+@tpX$y25cc1m2(J1;6H?$2v1R>$!;)o5uEAQ zs$4g1W`${FFZn#OY_Ggp(j>8MBd@Y7DX_vQ^&#uQT`qY-Up0eE+6LGtxSK|`+CD>C zIr^BQ;{D}cw@P?_87Q)AGr@a?mj<{*kK1j4VGNF4=&}uLtJl(?5Ry@|$-LrHW%uoD zomp5)ZBbyIo7c=lWqBjN-6LbI8%sb*x^}_@aL3a2i2WL2Ej*5;kBX%9Xbp*5OFiFI*pV)^+!h9Wm;;gi1Vbc80hM2D$-l)31GobP-XP?%20CDTtb&~HG&w=XyEJ+L7kZ$E}b`9Z{6f>Dk|p;)Th#141f^& zX4SK(LBBM7Gt?bX3gRI|M%EbtfllG`Hrq_T3ix<`cz@0mc0qH^DGMtcmi`K#M86>< zFO?CDlnsz}cPiT|c}KmeTiAOfXU+skOtq0MIg(Czx{o%|J=abHi6rJ3wVL$Z1IZ-p zDI|7-z!|j00n+-iLhH){skw0G88X^7CDd5eg2-TqxnDa8F9#!zIfkb42l%^{lVcm& z(h0qPr!I{~$;XD3@~0}mWo_m`5LLbd2(CyZMD2exo>F>=J)Ozo$57f{t!kto}=T+%%JA5NpNoh>LYP5AVwg%Okp#Ul(NF>dphEM{``NMQQ z%!Pz&?Af}edqCdOO>F$oJdbxPc6?JzMg zAutIB1uG5%0vZJX1Qdnf&y73RfET=|M)M}*u00Bd2a5y;eG*FoFf;kw6`Pj@Z1!@#h)T0s;sCfPw|MVuplA(eh6~ zLk%&~H{s$n$7PbM{+)EE#U*TkNOdYWJn7L9_R#~eBoxNa$Ssp})7y^G$Tt0F*%7i= zhPi$hLSun-6SrF`wtiFlmOwy=sJeE<;;DljV}0L_JaXNhO}s5C(+-xjDDcpkxda1$ zW_%uGoEgfn3EctVkd4?Pi^%SoJ3Fpm?4`!U??KWDM|$!vHiEu;ZW7>5YnZfZ>N;#i zcr1vuVJX(1mS~k+%xR-mNDm*#6l8;F-;0NSZ9D12VH*5NeImP$7)HTy&PZCz#yzxQ zwPp9tQG9K^(^#;GBvE{f78^w9UZzfeg$=ZHQGl=u0rTJ7enA70_VZ(I5HooY@Qh;~8ZR`+;qNu-ZDY21mFokxCQcbD@t1H_Q^7XP0m6 zs}(my4t9Uo=4Kz1l;2=CkC};9_jc?urCv#zTr{@qor$_Vf8_uALw)62WWP`H?1?;5 zDO(&LV=ly}zHFx>mt`P9G^=$b-M$Q{UQ5uro#~sVhmQd%NK0Zn#M3u_Fc&=2#5O4o zIk-KjOYQVH5c3)vn$!*C?VCy2@3&#H$m&0k@k@yXd1>*$#*XhKEcanfGM%azHP(h$ zo6{7A7qod zB0K-l8yyDOKd)wjo?Gc%sCiD)BuVv=yOKEniYC0|&$H9zOC+VNfF zwhh~sw2uv^|EqrPX2U^$fqJ&P*}<5rl~%klFqNPutaRva%RknCxbL?)W~yn3Lu8W% zl#Fez?r7)RNIzH0LwXg^2!$UKocz)991R?=6PW}b-$fvOvkUKZ;)HFhWN%=1ZSJ-d zUX{&;j~~>;gRi!LL?}H0G4QPb2PRH{fy1@omImCRZHvsI@e#^j=)Zb=0-q2A zrEI4n%0W#7MW3O6>U+wBqwdGWxZZ7FG>?2a{1+Z>bR}=^BZ$~j?&lgASK$P1s?(J< zq>rE-a6N}Vxmk~S99clfqCF%Tju?e_U!JZhySP}h2GX$#I3_F71d2$t)p9#)ca~YL z9-bw`)OF4z`hHi7>+dBOv{8CzHU~B$RtCzd21a;+>;u|=75@{n+8Za?kYHe^MxGL! zC8yXz%VhtTM`-gnwm)D8P!$06u6gp;?i7{&h`N6l4Oe85!(BqN%Hb*fog-CiKK?D{ z4gm*a%The|7oZCgb09UXk z?9@9I293<;=k3NeL~o9j_rmgVvGc)wKqgJycRI&^t=XTi^;^J}M=(P};9xOFqfEJp z;0Evf)BxFn5f1xqVeTmw;P+@xz%B{?_YyU}cGmLin~b`?=*`Xj-6e7+#sOq*9&CcASC6vFbK&v#2C1CyK}&ptm3Bya z`1t}bw7L{xPmGiu+O&kJ#Bucw>GMBk6cDk0Mp41nnxQ#)L!e)REIT-Ig6hy`DPbnz zosDrYlLAa{c6g3{s+NM>C`%KUPBs#LeUp7%)wmI|adKLWB(2T{Y-CyJjk-E;6NMC+ zHhA0g0lm7qQ#dnvPa*SEs$uYrgkK?J&ou!A$6rFX->M|KnEi4DEi1Ok83{=nD=5Z zlK!bJCfcl@U*%ELDe(LlBamhiO&WlIkSB|9YIJ;iPk`?lmssW7KkI%3fb1zW?-g}1 zVMDH^Kpx@}z1k4O%~;7)K}ZcKaxTKt`YJChA|9+h8*!{^1{&Fk3>VgP&P6%`t~F=z zkk!5VsX5|>9GMT@UY|Jtkk~p-rDMN2`?KjkTn1(Xfm#ATgvDs5TGm^mmYF+$v<7pJ zLL*;cHHl^~sK8BJ1mIUc)@fIwbG5XIRV)D&c)j?Q>5>MrL>Q(aD4*~j7-m64aI z(Ey6PCnuOG5`RKUAcnL3&|W_;&%#swBdx?ELch?LY_^#C*#z2hN$EzV>qiF}wUz{w z>i=0M=l<&EZlxB!;k&<+a}6v~{=$uCa<<#ANmS1dK}XLR5;2 zj~h5`ZDN;O!lM1G7|Yc|I)#d+DL#|1y7OsSr8(kpYV!e0RLY#Y_3BL>k51Aay;d!M z29*gMR0>!?A7Jq{DGIguQrz?lcha!fOaW(n{TOI`JRVyDghcyedzH2etoQG^%3>{* zrMtjQ>qjz9AAPOBkZxOk31AJRTDP@%dyy&QvKIM*bE~=Y-5!gFEFtEy%+1hGmt-P! zl}UKfQ}u7&%T&6RrH1XAeimU7fvHV@MFLgD4rfeuptS3=B#?=j(UqJ_q}Xq&Q98Wh z5+7WzMqMOdLD|>p8E;+R35iy|6hjbEEWG@kKB5-0*m-Z9PpPl-Z1Q=Cm zdqTA_Jq=c}`$_5q$w*<}tQ^SkvA! zm38G(xPk?1e@uCe5I%mYOyh-2Fzq2E3yFh^eTI(zNNZ*9@4~n=6#cWlUInrpEmYuZ zmvto?>T4%l&|m^7VV(817=~!yCmO$Pl$XMzbR0;(k8XD;>va7z~{@GgKol@he z$GRWd5cBQ;J&HUA0fV)bSVejn6byer*GSo5WJ5{|b>1UV$F48-utAJ}nJV&78(R-A z1YP~p8-1&)WRlYr2kQ6#!IWpQH6?E6?-_<)K8{i|He##C&BCnRVi27(5_}R;Ih!_- zN~VFG)RY{5v5y_TF)$(WVO`MA^U%?bm>r@O7CK5DiRcZSWBdy-Wxw0)L0f^q1f0y- zbeXU%Ho=O^bQ^C~j6D8-AqdoB_8GWzmbUSr=_2^*w>KkKJ-w`Qp(wWgtdCY%df#bB zXbQ{r=c(q1l{bV<&ay;^5f!_y*{jLs%NkUeZyzB6<~!0zD8Tj;A{TvJX6%%J z7xEQc(DWh1Sxk5QUcQ`J4bbfAvAG)k&<%1a<{?OeLf_A+-TxII+KSq8LhBd zHJ?SKE2nrZ5)S{G^7jG~&>e@RbyX{@KI+xaLXYYX>dCr$+QJUM!B;^S>%Q^5FX)P; z&Mrfup*ozVEBzzBW@TIjf<=dAmhVRX^v*Eq@wDlBIPBAiOzA%aj;^{WY+dwsmWsaA zR>ts~;`a@_9@JESqFw;vN^32~%p`=VSts5iu$9DXLCyy=>vC+>n@0GiCs%$u)0I3K zgSwSKeZL%h-T9M{^ft7RWpR5%XGadFXJPa3jwLp$_f%hvhGcZ@W0j*>#S0JvJE@S* zL$_VevLFq8cmB!!uCvN{)k@cs;jXglGQ^36WA?+kFLv-<_yfBBE)gI-f;ye42)YgbXMhiG1Je5-R;%z8M)SAu?N>2OM7YB2x z`(e~4dULN1uYJZ$7QcSE;NKTW?s8T{c|vzT)mfY@S*)~Kh|!jd#Dv}{UuhX^FrCm+ zPOPN^t+v;Hd`Yz~C^t9?XEEQeCH#lH2JmY?G+tk>N5LzlBmUHi;E-dfbR`k^#T9`n z?cF#QGLPVBbeoQxRD}6(y?EG4pGCiC)#n{+4H(|{bz9~mRB!O!Amz~~GH60)64Lo__ZXhxS(%96tdZSCXybK{6Q9fb7bh2l|<=9qMr)k4&VAbJ zGF1c8yDpeI(u3PWwl$AHwrb&l zhP)LCK@NKn&W${*NDg!UX)qKX&+2KmVCK-T$}9bhfVuUzLW0#nc6DGuLJbI!o}nHH zIQ~iBwnv$|-_@W;!~V#Y-Uf8Us!*I)DQw0`_!e09OwPv7H#2{@4o4V#yQs-kS9&&WY|)mP;RoOR$fbg zEC{Boz^;q7Uc(^iKHIbY{qGNQkg5ug5=3T zJ4>|}>64LYvmmv`wwDesUZRASq9mh#hq`aVA(maEVDuB{!f-7o2)@^g=4SO#^`Q=o zf2#f5<6XMXK&xD$=7hpue;U6%3yhry^wydYcbC~z>W|rT$4IJ6IORZcp3-my*)Xjz zf(38}2`Yw2hW8Bt2LYgh1z`k&1zj+L1z9kH1yu$MDuzgg_YDCI3IPJ3f&}h=FoFc? zFdPO7Duzgg_YDCI0Ru1&1PH!t^`+Yp@OlCQ2ml0v1jw#~Mq94GcgZ*j7RfbVk9KT* z<4+$lB7apM)*0WnvsFTXFi)^QXRjNL_OQ-Bpk4*WvKEm&44>C0$r4ef2kZMm=2(_` zh;d(0h?ctw_}jhS3`sZm&cM%qjO)0L%mr8q+kop=y(Nyp$xY@n^cC5yw~k1-ya1Rd z*{V+Zf@`Lo&xeIB^J^viU+~rK4BSg}p3yYgQB1FCNftfCbR3_-+dPKGtPcBG z{z)nd|J!XF&U9*vI)`zwlzEF9A@d^)bqQsAwMO>KNPk?x%#OZ)xJ9y{3jx z%$K{6GCGxJ##VJF{f@ckL;2Yla%d#`sDfUya3PUtVZ<1jBdL*t_#a-&<3b~KDlCu#c#>(B2$b~h(D$2 z84Y*$@hFekwSCX!<3?X5F=Q0$gq{3}5dUi7v5)HIc3!v``b1+}3Ct-%Wa#N$M`rEA z+C{nV22p~2Ze80dFI0NYL|3SD(dyj$(I5!PzuGaN`EGx2nDKn#-nt5K0U)0O`sKtk8pq?qbfR3#Q9nnoG;dX_pU`Kd=c7XFQ zy=Vb(I58>PWi!f-Y=In1_xc^y`{o}wIE1q5{rL?6;7i3Ea~kvkyIgL6pR6;bg$Dgm zgVWdyS`c|xM-h#1i8cL*V{5FD5T^QnsvqHg*aNEOPX}f(nO&yq7+V@s( zD`ol#iXY8}6;wQQ9IHhKy}-AoBKSq=cctqA0&$y-b~FBA%}R7s=u8V-sIsH=oevYeav9Pu!0n6%~q71INYz znBy9^EEAMaX{kfwt#L;NPZWVMR4^k32`YvkNQU`f6NtU3>Zx3}Lj*$rsOS)#cm2-Q0O>*mY2z&b`%9{!2gzLu$%YyzF^wX^7 zbnxbtWqgpQjI!tX7Qh*wvbj-F4ga1vYiCA0t6L+T+;A!oNIg=CK0n2+u=8+#8~1Jp zzq@Um82ex>{$7zwrpdNUrT|JW6&iXb%u4Y)Dq&}=|DKYJ81U0u@8(mnoqSbQp(sUj zT$ChdE3##z4+>cje{Uceqvh(P*TLi_7n*{aP}!gt3F#JC<8mmW{KfgRbfJfF{h3*woJH>^nP%SOiZ%HoSKE4dP!?}f7oB_$1Dor&fM zPu{}rp27==F~P@^xzhvgrgB!5L=|j+9m*K54??MWR0_t|&rn9p>N>1gO>up7i`QSn zCyOKDCG>{92M2P1sqVIUTh6Z>a7BH1AhvYK3w~FT9R5&FuYBLwcZ3UnPY;EFs-mF& ztYQ3zMsO(iG7}T@yX!qvYS~}jE!VP>u8-&UW3Dg$EfEmCzO%Mnw19hX+VS# zW9Kl=)A<)=OkryLQP+D>#O31IS;y9YAA-2)Tjh$@>0VEG9v>xM#RvJ>2b|I*@v#en zF|Y#kN>B|>e{~;6U<1H^&Lw|Z=}Af|H(&TgoBCx`#diS<&QjF}%X(qzy2(ssu6+dR z8g;0-zPmYs_bED)_1+5fRKVeqLD!ewXXN}xu~V>~lP(Qaxqs;g!Gz%<8|J~f0SZ?< z;cIYbJZzf1fiIgL3KAofq^*` zl`L`Cviy40I^#z8K!9?ajCb?J5W`;&5E?-2e2n25l<3v-5hU|H*uKs?5#bz^8`4KK zLyN;7lm-)OZrMnJvjPME`w}9O6V5}ObCM5;D`BtMI+f1Wh}l+M7v{*I_KlN&f8Rbz zS6UGssxH&A3(#vYCYolAM6OsfgQHQyRf>if)H%}}`Q-}bN=N*Nsx1*OM6T2Vrtef1 zaIO|{eyir0^m12eu$y!>QIb8TIGrMQm_Z!xik$$lz692&?c^ zQi04Y#PFSe8XCu3o3gjr(hDM7b<12tzl!y<0VxBrd?h{lQPF*-=-6moJ6D1=3A|u_ zNjDs(_5?Tgl(go|!E>8j(LGXu+WNx3$S)G?{ik+5jBGr9LNNhd(mIh_*An)tA5&S9 znc>P`khTORJyAwvIp_=~e}r*Dy!3zW^ZAzglWyOC!K}tGf&(Z92`Yw2hW8Bt2LYgh z0~rK@0~IiW0}(KS0}TcXDuzgg_YDCI3IPJ3f&!*6f&!v290m$1hDe6@4FL=R127H* z2n%rt!Y@ss(EpfZHs#f@!HM@QT>E+?FZxdc3h@&r?T)F~XGs8zmOq1tQtcVJmUf-unq1 z*W$rdLv`fvYW%i5Y1A;kz~-LI<|=GvxuGZXpZ%A1kDM!ssB5C{GrAP4>q4-ZC)v=| zuQPyT+zpC>gpAy;5|6H5u0{iz1d3g>C%t}u+;K;SA4+zHVmh zoP>xn7`GMSm1(@=h3g)Wrg^uwLmXzLNLqtzVN{uj(Fm!aVZZU~!%)dIG(-FZVevdE z>qW!u7@nRF92i(l9zr2sZmb-ODURmvf&@UlK{;e+PU{ZFT006Fk z$$n+4B4rfr;DXIe@PP#gD!8cFurGs#ByEXLx|JDM7+F{~pI-&7-@3u1Y=^^cH{IB-!)Q~WidZG<*!KP+1*Hb% zNB=>Q^6!=N5~R3`28X!y{99KC@umuYejGJ!D?|jS2d9}6hz8;rb(MRUsUvmlnHE{e z;Y^}VF<^=ly}V)}yyC4Bzj1iB9a))tR@r83eJQ(JD{2}#4SVa`1_m5^H!xgSt=HRP zrtY9(UU^XvLkUc&T&iuI&Xwt@y{*wIf?xL$>krdW9nPg;!tBuWTjWNjv?Tt2i?|c; zRN&aZI^MA#UCn!@f^WJ*aX{yo!|k2GvWFIJwgh4|#0~6xukp2*zEM{$_U9&# Date: Fri, 1 May 2020 14:02:10 -0700 Subject: [PATCH 0434/1105] tests: Skip proxyarp tests properly if ebtables rule install fails Otherwise the test will continue on and fail later due to unexpected foreign ARP request. The try/except design here did not work properly to detect this. Signed-off-by: Thomas Pedersen --- tests/hwsim/test_ap_hs20.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index c484b5003..863567eb1 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -4672,9 +4672,12 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): if ebtables: for chain in ['FORWARD', 'OUTPUT']: try: - subprocess.call(['ebtables', '-A', chain, '-p', 'ARP', - '-d', 'Broadcast', '-o', apdev[0]['ifname'], - '-j', 'DROP']) + err = subprocess.call(['ebtables', '-A', chain, '-p', 'ARP', + '-d', 'Broadcast', + '-o', apdev[0]['ifname'], + '-j', 'DROP']) + if err != 0: + raise except: raise HwsimSkip("No ebtables available") @@ -4998,10 +5001,15 @@ def _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=False): if ebtables: for chain in ['FORWARD', 'OUTPUT']: try: - subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast', - '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp', - '--ip6-icmp-type', 'neighbor-solicitation', - '-o', apdev[0]['ifname'], '-j', 'DROP']) + err = subprocess.call(['ebtables', '-A', chain, + '-d', 'Multicast', + '-p', 'IPv6', + '--ip6-protocol', 'ipv6-icmp', + '--ip6-icmp-type', + 'neighbor-solicitation', + '-o', apdev[0]['ifname'], '-j', 'DROP']) + if err != 0: + raise subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast', '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp', '--ip6-icmp-type', 'neighbor-advertisement', From 42acf1292dd52e12e059c4f82070b2a7e4d7fc09 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 17:06:59 +0300 Subject: [PATCH 0435/1105] DPP2: Add Protocol Version attribute to network introduction messages This can be used to determine whether to try to negotiate PFS (only available with version 2 or higher). Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 15 +++++++++++++-- wpa_supplicant/dpp_supplicant.c | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index c86f01ba7..77518cbdf 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1206,9 +1206,13 @@ static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd, enum dpp_status_error status) { struct wpabuf *msg; + size_t len; - msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, - 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector)); + len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector); +#ifdef CONFIG_DPP2 + len += 5; +#endif /* CONFIG_DPP2 */ + msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len); if (!msg) return; @@ -1281,6 +1285,13 @@ skip_status: skip_connector: #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP2 + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, 2); +#endif /* CONFIG_DPP2 */ + wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR " status=%d", MAC2STR(src), status); wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 291b96b75..b8fd95bee 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2474,6 +2474,7 @@ int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, unsigned int wait_time; const u8 *rsn; struct wpa_ie_data ied; + size_t len; if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss) return 0; /* Not using DPP AKM - continue */ @@ -2507,8 +2508,11 @@ int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, "DPP: Starting network introduction protocol to derive PMKSA for " MACSTR, MAC2STR(bss->bssid)); - msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, - 5 + 4 + os_strlen(ssid->dpp_connector)); + len = 5 + 4 + os_strlen(ssid->dpp_connector); +#ifdef CONFIG_DPP2 + len += 5; +#endif /* CONFIG_DPP2 */ + msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len); if (!msg) return -1; @@ -2563,6 +2567,13 @@ skip_trans_id: skip_connector: #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP2 + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, 2); +#endif /* CONFIG_DPP2 */ + /* TODO: Timeout on AP response */ wait_time = wpa_s->max_remain_on_chan; if (wait_time > 2000) From f6c22dcdead99f968e11f6eea071f28613d60617 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 17:20:33 +0300 Subject: [PATCH 0436/1105] Use a local pointer to simply current_ssid accesses in sme_associate() It is simpler to assign wpa_s->current_ssid to a local pointer now that there are numerous dereferences of current_ssid within sme_associate(). Signed-off-by: Jouni Malinen --- wpa_supplicant/sme.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 4eaece05d..38c46016f 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1646,6 +1646,7 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, { struct wpa_driver_associate_params params; struct ieee802_11_elems elems; + struct wpa_ssid *ssid = wpa_s->current_ssid; #ifdef CONFIG_FILS u8 nonces[2 * FILS_NONCE_LEN]; #endif /* CONFIG_FILS */ @@ -1755,8 +1756,8 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, struct wpabuf *owe_ie; u16 group; - if (wpa_s->current_ssid && wpa_s->current_ssid->owe_group) { - group = wpa_s->current_ssid->owe_group; + if (ssid && ssid->owe_group) { + group = ssid->owe_group; } else if (wpa_s->assoc_status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { if (wpa_s->last_owe_group == 19) @@ -1792,12 +1793,9 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP2 - if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid && - wpa_s->current_ssid->dpp_netaccesskey && - wpa_s->current_ssid->dpp_pfs != 2 && - !wpa_s->current_ssid->dpp_pfs_fallback) { - struct wpa_ssid *ssid = wpa_s->current_ssid; - + if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid && + ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 && + !ssid->dpp_pfs_fallback) { dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); @@ -1823,7 +1821,7 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, pfs_fail: #endif /* CONFIG_DPP2 */ - if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) { + if (ssid && ssid->multi_ap_backhaul_sta) { size_t multi_ap_ie_len; multi_ap_ie_len = add_multi_ap_ie( @@ -1843,8 +1841,7 @@ pfs_fail: params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; params.freq.freq = wpa_s->sme.freq; - params.bg_scan_period = wpa_s->current_ssid ? - wpa_s->current_ssid->bg_scan_period : -1; + params.bg_scan_period = ssid ? ssid->bg_scan_period : -1; params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? wpa_s->sme.assoc_req_ie : NULL; params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; @@ -1860,17 +1857,17 @@ pfs_fail: os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); params.htcaps = (u8 *) &htcaps; params.htcaps_mask = (u8 *) &htcaps_mask; - wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); + wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_VHT_OVERRIDES os_memset(&vhtcaps, 0, sizeof(vhtcaps)); os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask)); params.vhtcaps = &vhtcaps; params.vhtcaps_mask = &vhtcaps_mask; - wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); + wpa_supplicant_apply_vht_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_VHT_OVERRIDES */ #ifdef CONFIG_HE_OVERRIDES - wpa_supplicant_apply_he_overrides(wpa_s, wpa_s->current_ssid, ¶ms); + wpa_supplicant_apply_he_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_HE_OVERRIDES */ #ifdef CONFIG_IEEE80211R if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies && @@ -1992,7 +1989,7 @@ pfs_fail: elems.rsnxe_len + 2); else wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0); - if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) + if (ssid && ssid->p2p_group) params.p2p = 1; if (wpa_s->p2pdev->set_sta_uapsd) From 1f5f0000865ca5f2935a85ec25cf942984a983d5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 17:30:03 +0300 Subject: [PATCH 0437/1105] DPP2: Try to negotiate PFS only if AP supports version 2 or newer Check AP's DPP Protocol Version during network introduction and mark the PMKSA cache as suitable for PFS use with version 2 or newer. This avoids unnecessary attempt of negotiating PFS with version 1 APs. Signed-off-by: Jouni Malinen --- src/rsn_supp/pmksa_cache.h | 1 + wpa_supplicant/dpp_supplicant.c | 14 +++++++++++++- wpa_supplicant/sme.c | 6 ++++++ wpa_supplicant/wpa_supplicant.c | 6 ++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h index 6c49fa924..83faa0584 100644 --- a/src/rsn_supp/pmksa_cache.h +++ b/src/rsn_supp/pmksa_cache.h @@ -28,6 +28,7 @@ struct rsn_pmksa_cache_entry { */ u8 fils_cache_id[2]; unsigned int fils_cache_id_set:1; + unsigned int dpp_pfs:1; os_time_t reauth_time; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index b8fd95bee..a846c7c65 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1771,6 +1771,11 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid; const u8 *connector, *trans_id, *status; u16 connector_len, trans_id_len, status_len; +#ifdef CONFIG_DPP2 + const u8 *version; + u16 version_len; +#endif /* CONFIG_DPP2 */ + u8 peer_version = 1; struct dpp_introduction intro; struct rsn_pmksa_cache_entry *entry; struct os_time now; @@ -1871,6 +1876,13 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s, os_memcpy(entry->pmk, intro.pmk, intro.pmk_len); entry->pmk_len = intro.pmk_len; entry->akmp = WPA_KEY_MGMT_DPP; +#ifdef CONFIG_DPP2 + version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (version && version_len >= 1) + peer_version = version[0]; + entry->dpp_pfs = peer_version >= 2; +#endif /* CONFIG_DPP2 */ if (expiry) { os_get_time(&now); seconds = expiry - now.sec; @@ -1884,7 +1896,7 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s, wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR - " status=%u", MAC2STR(src), status[0]); + " status=%u version=%u", MAC2STR(src), status[0], peer_version); wpa_printf(MSG_DEBUG, "DPP: Try connection again after successful network introduction"); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 38c46016f..c7e5fcd5a 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1796,6 +1796,12 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid && ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) { + struct rsn_pmksa_cache_entry *pmksa; + + pmksa = pmksa_cache_get_current(wpa_s->wpa); + if (!pmksa || !pmksa->dpp_pfs) + goto pfs_fail; + dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index d3e8a0580..bac3d9796 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3087,6 +3087,12 @@ static u8 * wpas_populate_assoc_ies( if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP && ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) { + struct rsn_pmksa_cache_entry *pmksa; + + pmksa = pmksa_cache_get_current(wpa_s->wpa); + if (!pmksa || !pmksa->dpp_pfs) + goto pfs_fail; + dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); From 85d5456997bb76d7ba8e5cddcffd4fbbcf87a2c6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 17:36:59 +0300 Subject: [PATCH 0438/1105] DPP2: Indicate if PFS was used in control interface STATUS The new "dpp_pfs=1" entry can be used to determine whether PFS was used during derivation of PTK when DPP AKM is negotiated for an association. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 6077aa60a..605d40863 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3292,6 +3292,15 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, return pos - buf; pos += ret; +#ifdef CONFIG_DPP2 + if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) { + ret = os_snprintf(pos, end - pos, "dpp_pfs=1\n"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_DPP2 */ + if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) { struct wpa_ie_data rsn; if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) From 6c67ad0a525e53c6ea6f7d233c1f028325b2bab4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 17:43:07 +0300 Subject: [PATCH 0439/1105] tests: Check DPP PFS negotiation result Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 02329e088..5f0bff7ad 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5193,7 +5193,7 @@ def start_dpp_pfs_ap(apdev, pfs): raise HwsimSkip("DPP not supported") return hapd -def run_dpp_pfs_sta(dev, pfs, fail=False): +def run_dpp_pfs_sta(dev, pfs, fail=False, pfs_expected=None): dev.connect("dpp", key_mgmt="DPP", scan_freq="2412", ieee80211w="2", dpp_pfs=str(pfs), dpp_csign=params1_csign, @@ -5210,6 +5210,11 @@ def run_dpp_pfs_sta(dev, pfs, fail=False): raise Exception("Unexpected connection") dev.request("REMOVE_NETWORK all") else: + if pfs_expected is not None: + res = dev.get_status_field("dpp_pfs") + pfs_used = res == "1" + if pfs_expected != pfs_used: + raise Exception("Unexpected PFS negotiation result") dev.request("REMOVE_NETWORK all") dev.wait_disconnected() dev.dump_monitor() @@ -5218,25 +5223,25 @@ def test_dpp_pfs_ap_0(dev, apdev): """DPP PFS AP default""" check_dpp_capab(dev[0]) hapd = start_dpp_pfs_ap(apdev[0], 0) - run_dpp_pfs_sta(dev[0], 0) - run_dpp_pfs_sta(dev[0], 1) - run_dpp_pfs_sta(dev[0], 2) + run_dpp_pfs_sta(dev[0], 0, pfs_expected=True) + run_dpp_pfs_sta(dev[0], 1, pfs_expected=True) + run_dpp_pfs_sta(dev[0], 2, pfs_expected=False) def test_dpp_pfs_ap_1(dev, apdev): """DPP PFS AP required""" check_dpp_capab(dev[0]) hapd = start_dpp_pfs_ap(apdev[0], 1) - run_dpp_pfs_sta(dev[0], 0) - run_dpp_pfs_sta(dev[0], 1) + run_dpp_pfs_sta(dev[0], 0, pfs_expected=True) + run_dpp_pfs_sta(dev[0], 1, pfs_expected=True) run_dpp_pfs_sta(dev[0], 2, fail=True) def test_dpp_pfs_ap_2(dev, apdev): """DPP PFS AP not allowed""" check_dpp_capab(dev[0]) hapd = start_dpp_pfs_ap(apdev[0], 2) - run_dpp_pfs_sta(dev[0], 0) + run_dpp_pfs_sta(dev[0], 0, pfs_expected=False) run_dpp_pfs_sta(dev[0], 1, fail=True) - run_dpp_pfs_sta(dev[0], 2) + run_dpp_pfs_sta(dev[0], 2, pfs_expected=False) def test_dpp_reconfig_connector(dev, apdev): """DPP reconfiguration connector""" From 61e22e45c881317b0c8a7f37df70de59fcebfd8b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 17:45:58 +0300 Subject: [PATCH 0440/1105] tests: DPP PFS and cfg80211 connect command Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 5f0bff7ad..76bdd5689 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5243,6 +5243,16 @@ def test_dpp_pfs_ap_2(dev, apdev): run_dpp_pfs_sta(dev[0], 1, fail=True) run_dpp_pfs_sta(dev[0], 2, pfs_expected=False) +def test_dpp_pfs_connect_cmd(dev, apdev): + """DPP PFS and cfg80211 connect command""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + check_dpp_capab(wpas) + hapd = start_dpp_pfs_ap(apdev[0], 0) + run_dpp_pfs_sta(wpas, 0, pfs_expected=True) + run_dpp_pfs_sta(wpas, 1, pfs_expected=True) + run_dpp_pfs_sta(wpas, 2, pfs_expected=False) + def test_dpp_reconfig_connector(dev, apdev): """DPP reconfiguration connector""" try: From f11415680438f58e70c7fc4e7b2267037be19b1a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 20:51:49 +0300 Subject: [PATCH 0441/1105] tests: Disable PFS in dpp_akm_sha* These test cases are using externally generated PMKSA cache entry which does not support use of PFS. This will start failing if the station claims to support PFS in such cases, so explicitly disable PFS functionality in these test cases for now. Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 76bdd5689..0b69d8281 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -1420,7 +1420,7 @@ def run_dpp_akm(dev, apdev, pmk_len): raise HwsimSkip("DPP not supported") id = dev[0].connect("dpp", key_mgmt="DPP", ieee80211w="2", scan_freq="2412", - wait_connect=False) + dpp_pfs="2", wait_connect=False) ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=2) if not ev: raise Exception("Network mismatch not reported") From b11a12401a36f733f7fca3a89ca290cd18cf6762 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 19:51:34 +0300 Subject: [PATCH 0442/1105] DPP2: Add DPP KDE into EAPOL-Key msg 3/4 when using DPP AKM Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 21 +++++++++++++++++++++ src/common/wpa_common.h | 5 +++++ 2 files changed, 26 insertions(+) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 30e725864..fad0623b0 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3397,6 +3397,11 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (conf->transition_disable) kde_len += 2 + RSN_SELECTOR_LEN + 1; +#ifdef CONFIG_DPP2 + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) + kde_len += 2 + RSN_SELECTOR_LEN + 2; +#endif /* CONFIG_DPP2 */ + kde = os_malloc(kde_len); if (!kde) goto done; @@ -3492,6 +3497,22 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE, &conf->transition_disable, 1, NULL, 0); +#ifdef CONFIG_DPP2 + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { + u8 payload[2]; + + payload[0] = 2; /* Protocol Version */ + payload[1] = 0; /* Flags */ + if (conf->dpp_pfs == 0) + payload[1] |= DPP_KDE_PFS_ALLOWED; + else if (conf->dpp_pfs == 1) + payload[1] |= DPP_KDE_PFS_ALLOWED | + DPP_KDE_PFS_REQUIRED; + pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP, + payload, sizeof(payload), NULL, 0); + } +#endif /* CONFIG_DPP2 */ + wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index c0ef689c6..9ad9edc73 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -124,6 +124,7 @@ WPA_CIPHER_BIP_CMAC_256) #define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4) #define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5) #define WFA_KEY_DATA_TRANSITION_DISABLE RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x20) +#define WFA_KEY_DATA_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x21) #define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) @@ -362,6 +363,10 @@ struct rsn_rdie { #define TRANSITION_DISABLE_WPA3_ENTERPRISE BIT(2) #define TRANSITION_DISABLE_ENHANCED_OPEN BIT(3) +/* DPP KDE Flags */ +#define DPP_KDE_PFS_ALLOWED BIT(0) +#define DPP_KDE_PFS_REQUIRED BIT(1) + #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ From 143e3d8bc5cb1c7a497cccd85281c06f02d5c5c8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 19:53:07 +0300 Subject: [PATCH 0443/1105] DPP2: Add DPP KDE into EAPOL-Key msg 2/4 when using DPP AKM Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 29 ++++++++++++++++++++++++++++- src/rsn_supp/wpa.h | 1 + src/rsn_supp/wpa_i.h | 1 + wpa_supplicant/wpa_supplicant.c | 3 +++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 605d40863..22dd542f3 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -737,7 +737,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 3 + sm->assoc_rsnxe_len + - 2 + RSN_SELECTOR_LEN + 1); + 2 + RSN_SELECTOR_LEN + 1 + + 2 + RSN_SELECTOR_LEN + 2); if (!kde_buf) goto failed; os_memcpy(kde_buf, kde, kde_len); @@ -782,6 +783,27 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, } #endif /* CONFIG_P2P */ +#ifdef CONFIG_DPP2 + if (sm->key_mgmt == WPA_KEY_MGMT_DPP) { + u8 *pos; + + wpa_printf(MSG_DEBUG, "DPP: Add DPP KDE into EAPOL-Key 2/4"); + pos = kde + kde_len; + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = RSN_SELECTOR_LEN + 2; + RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_DPP); + pos += RSN_SELECTOR_LEN; + *pos++ = 2; /* Protocol Version */ + *pos = 0; /* Flags */ + if (sm->dpp_pfs == 0) + *pos |= DPP_KDE_PFS_ALLOWED; + else if (sm->dpp_pfs == 1) + *pos |= DPP_KDE_PFS_ALLOWED | DPP_KDE_PFS_REQUIRED; + pos++; + kde_len = pos - kde; + } +#endif /* CONFIG_DPP2 */ + if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, kde, kde_len, ptk) < 0) goto failed; @@ -3255,6 +3277,11 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, sm->ft_rsnxe_used = value; break; #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP2 + case WPA_PARAM_DPP_PFS: + sm->dpp_pfs = value; + break; +#endif /* CONFIG_DPP2 */ default: break; } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 0986c6c61..dfc156b55 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -107,6 +107,7 @@ enum wpa_sm_conf_params { WPA_PARAM_EXT_KEY_ID, WPA_PARAM_USE_EXT_KEY_ID, WPA_PARAM_FT_RSNXE_USED, + WPA_PARAM_DPP_PFS, }; struct rsn_supp_config { diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 497d12885..f7d9f6255 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -183,6 +183,7 @@ struct wpa_sm { #ifdef CONFIG_DPP2 struct wpabuf *dpp_z; + int dpp_pfs; #endif /* CONFIG_DPP2 */ }; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index bac3d9796..53f8c9466 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1685,6 +1685,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) { /* Use PMK from DPP network introduction (PMKSA entry) */ wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); +#ifdef CONFIG_DPP2 + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs); +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) { int psk_set = 0; From 68422fedbf1d2be71f726b6a2a90fae510e513ee Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 19:52:31 +0300 Subject: [PATCH 0444/1105] DPP2: Parse DPP KDE in EAPOL-Key Key Data field Signed-off-by: Jouni Malinen --- src/common/wpa_common.c | 9 +++++++++ src/common/wpa_common.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index eb1861a87..bddc696cf 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2801,6 +2801,15 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie) return 0; } + if (pos[1] >= RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_DPP) { + ie->dpp_kde = pos + 2 + RSN_SELECTOR_LEN; + ie->dpp_kde_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: DPP KDE in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + return 2; } diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 9ad9edc73..065dc7113 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -533,6 +533,8 @@ struct wpa_eapol_ie_parse { const u8 *ip_addr_alloc; const u8 *transition_disable; size_t transition_disable_len; + const u8 *dpp_kde; + size_t dpp_kde_len; const u8 *oci; size_t oci_len; const u8 *osen; From 9561925b4d95fa5e463bbfe165792e4eb52b61e5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 20:02:48 +0300 Subject: [PATCH 0445/1105] DPP2: Detect PFS downgrade attack while processing EAPOL-Key msg 2/4 Do not allow association to continue if the local configuration enables PFS and the station indicates it supports PFS, but PFS was not negotiated for the association. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index fad0623b0..cbaf9f738 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3079,6 +3079,24 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) } #endif /* CONFIG_P2P */ +#ifdef CONFIG_DPP2 + if (kde.dpp_kde) { + wpa_printf(MSG_DEBUG, + "DPP: peer Protocol Version %u Flags 0x%x", + kde.dpp_kde[0], kde.dpp_kde[1]); + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && + wpa_auth->conf.dpp_pfs != 2 && + (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) && + !sm->dpp_z) { + wpa_printf(MSG_INFO, + "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association"); + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + } +#endif /* CONFIG_DPP2 */ + #ifdef CONFIG_IEEE80211R_AP if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { /* From c3c38bc8b908f2719387acb65fabe805dd205587 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 20:06:57 +0300 Subject: [PATCH 0446/1105] DPP2: Detect PFS downgrade attack while processing EAPOL-Key msg 3/4 Do not allow association to continue if the local configuration enables PFS and the station indicates it supports PFS, but PFS was not negotiated for the association. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 22dd542f3..84ff1e1bd 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1715,6 +1715,20 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, } #endif /* CONFIG_OCV */ +#ifdef CONFIG_DPP2 + if (ie.dpp_kde) { + wpa_printf(MSG_DEBUG, + "DPP: peer Protocol Version %u Flags 0x%x", + ie.dpp_kde[0], ie.dpp_kde[1]); + if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_pfs != 2 && + (ie.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) && !sm->dpp_z) { + wpa_printf(MSG_INFO, + "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association"); + goto failed; + } + } +#endif /* CONFIG_DPP2 */ + if (sm->use_ext_key_id && wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX)) goto failed; From 12c8eacf73f67112e739a2d609221d5fc6876dd5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 21:07:42 +0300 Subject: [PATCH 0447/1105] DPP: Allow version number to be overridden for testing purposes "SET dpp_version_override " can now be used to request wpa_supplicant and hostapd to support a subset of DPP versions. In practice, the only valid case for now is to fall back from DPP version 2 support to version 1 in builds that include CONFIG_DPP2=y. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 7 +++++++ src/ap/dpp_hostapd.c | 10 ++++++---- src/ap/ieee802_11.c | 5 +++-- src/ap/wpa_auth.c | 7 ++++--- src/common/dpp.c | 13 +++++++++---- src/common/dpp.h | 11 +++++++++++ src/rsn_supp/wpa.c | 7 ++++--- wpa_supplicant/ctrl_iface.c | 7 +++++++ wpa_supplicant/dpp_supplicant.c | 10 ++++++---- wpa_supplicant/events.c | 5 +++-- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wpa_supplicant.c | 3 ++- 12 files changed, 63 insertions(+), 24 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 6e8352f2f..87f2cb17e 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1428,6 +1428,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) hapd->dpp_ignore_netaccesskey_mismatch = atoi(value); } else if (os_strcasecmp(cmd, "dpp_test") == 0) { dpp_test = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) { + dpp_version_override = atoi(value); #endif /* CONFIG_DPP */ #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_MBO @@ -4193,6 +4195,11 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) #ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_DPP dpp_test = DPP_TEST_DISABLED; +#ifdef CONFIG_DPP2 + dpp_version_override = 2; +#else /* CONFIG_DPP2 */ + dpp_version_override = 1; +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 77518cbdf..0926a7659 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1286,10 +1286,12 @@ skip_connector: #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_DPP2 - /* Protocol Version */ - wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); - wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, 2); + if (DPP_VERSION > 1) { + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } #endif /* CONFIG_DPP2 */ wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 28ac7aa4b..15e44b912 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3365,7 +3365,8 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, dpp_pfs_free(sta->dpp_pfs); sta->dpp_pfs = NULL; - if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && + if (DPP_VERSION > 1 && + (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && hapd->conf->dpp_netaccesskey && sta->wpa_sm && wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP && elems.owe_dh) { @@ -3843,7 +3844,7 @@ rsnxe_done: #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP2 - if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && + if (DPP_VERSION > 1 && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS && wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) { os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie), diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index cbaf9f738..019e5357e 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -14,6 +14,7 @@ #include "utils/bitfield.h" #include "common/ieee802_11_defs.h" #include "common/ocv.h" +#include "common/dpp.h" #include "crypto/aes.h" #include "crypto/aes_wrap.h" #include "crypto/aes_siv.h" @@ -3080,7 +3081,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) #endif /* CONFIG_P2P */ #ifdef CONFIG_DPP2 - if (kde.dpp_kde) { + if (DPP_VERSION > 1 && kde.dpp_kde) { wpa_printf(MSG_DEBUG, "DPP: peer Protocol Version %u Flags 0x%x", kde.dpp_kde[0], kde.dpp_kde[1]); @@ -3516,10 +3517,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) &conf->transition_disable, 1, NULL, 0); #ifdef CONFIG_DPP2 - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { + if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { u8 payload[2]; - payload[0] = 2; /* Protocol Version */ + payload[0] = DPP_VERSION; /* Protocol Version */ payload[1] = 0; /* Flags */ if (conf->dpp_pfs == 0) payload[1] |= DPP_KDE_PFS_ALLOWED; diff --git a/src/common/dpp.c b/src/common/dpp.c index 080c86aab..f8b13d6f5 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -37,6 +37,11 @@ static const char * dpp_netrole_str(enum dpp_netrole netrole); #ifdef CONFIG_TESTING_OPTIONS +#ifdef CONFIG_DPP2 +int dpp_version_override = 2; +#else +int dpp_version_override = 1; +#endif enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED; u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; @@ -1850,7 +1855,7 @@ static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, /* Protocol Version */ wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, 2); + wpabuf_put_u8(msg, DPP_VERSION); #endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS @@ -2014,7 +2019,7 @@ static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, if (auth->peer_version >= 2) { wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, 2); + wpabuf_put_u8(msg, DPP_VERSION); } #endif /* CONFIG_DPP2 */ @@ -3352,7 +3357,7 @@ dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles, #ifdef CONFIG_DPP2 version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, &version_len); - if (version) { + if (version && DPP_VERSION > 1) { if (version_len < 1 || version[0] == 0) { dpp_auth_fail(auth, "Invalid Protocol Version attribute"); @@ -3968,7 +3973,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, #ifdef CONFIG_DPP2 version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, &version_len); - if (version) { + if (version && DPP_VERSION > 1) { if (version_len < 1 || version[0] == 0) { dpp_auth_fail(auth, "Invalid Protocol Version attribute"); diff --git a/src/common/dpp.h b/src/common/dpp.h index afbedc554..e6cdf1103 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -21,6 +21,17 @@ struct crypto_ecdh; struct hostapd_ip_addr; struct dpp_global; +#ifdef CONFIG_TESTING_OPTIONS +#define DPP_VERSION (dpp_version_override) +extern int dpp_version_override; +#else /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP2 +#define DPP_VERSION 2 +#else +#define DPP_VERSION 1 +#endif +#endif /* CONFIG_TESTING_OPTIONS */ + #define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */ #define DPP_TCP_PORT 7871 diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 84ff1e1bd..a9e2e2474 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -21,6 +21,7 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/ocv.h" +#include "common/dpp.h" #include "eap_common/eap_defs.h" #include "eapol_supp/eapol_supp_sm.h" #include "drivers/driver.h" @@ -784,7 +785,7 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, #endif /* CONFIG_P2P */ #ifdef CONFIG_DPP2 - if (sm->key_mgmt == WPA_KEY_MGMT_DPP) { + if (DPP_VERSION > 1 && sm->key_mgmt == WPA_KEY_MGMT_DPP) { u8 *pos; wpa_printf(MSG_DEBUG, "DPP: Add DPP KDE into EAPOL-Key 2/4"); @@ -793,7 +794,7 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, *pos++ = RSN_SELECTOR_LEN + 2; RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_DPP); pos += RSN_SELECTOR_LEN; - *pos++ = 2; /* Protocol Version */ + *pos++ = DPP_VERSION; /* Protocol Version */ *pos = 0; /* Flags */ if (sm->dpp_pfs == 0) *pos |= DPP_KDE_PFS_ALLOWED; @@ -1716,7 +1717,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, #endif /* CONFIG_OCV */ #ifdef CONFIG_DPP2 - if (ie.dpp_kde) { + if (DPP_VERSION > 1 && ie.dpp_kde) { wpa_printf(MSG_DEBUG, "DPP: peer Protocol Version %u Flags 0x%x", ie.dpp_kde[0], ie.dpp_kde[1]); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 90504948a..6e673fe36 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -696,6 +696,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = -1; else dpp_nonce_override_len = hex_len / 2; + } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) { + dpp_version_override = atoi(value); #endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_DPP */ #ifdef CONFIG_TESTING_OPTIONS @@ -8160,6 +8162,11 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) dpp_pkex_ephemeral_key_override_len = 0; dpp_protocol_key_override_len = 0; dpp_nonce_override_len = 0; +#ifdef CONFIG_DPP2 + dpp_version_override = 2; +#else /* CONFIG_DPP2 */ + dpp_version_override = 1; +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_DPP */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index a846c7c65..eae62e289 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2580,10 +2580,12 @@ skip_connector: #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_DPP2 - /* Protocol Version */ - wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); - wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, 2); + if (DPP_VERSION > 1) { + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } #endif /* CONFIG_DPP2 */ /* TODO: Timeout on AP response */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 61f875742..a25b43db0 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2703,7 +2703,8 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, #ifdef CONFIG_DPP2 wpa_sm_set_dpp_z(wpa_s->wpa, NULL); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->dpp_pfs) { + if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && + wpa_s->dpp_pfs) { struct ieee802_11_elems elems; if (ieee802_11_parse_elems(data->assoc_info.resp_ies, @@ -4373,7 +4374,7 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, * the status code defined in the DPP R2 tech spec. * WLAN_STATUS_AKMP_NOT_VALID is addressed in the same manner as an * interoperability workaround with older hostapd implementation. */ - if (wpa_s->current_ssid && + if (DPP_VERSION > 1 && wpa_s->current_ssid && wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid->dpp_pfs == 0 && (data->assoc_reject.status_code == diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index c7e5fcd5a..d06f6e298 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1793,7 +1793,7 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP2 - if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid && + if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid && ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) { struct rsn_pmksa_cache_entry *pmksa; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 53f8c9466..af4e7eb3a 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3087,7 +3087,8 @@ static u8 * wpas_populate_assoc_ies( #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP2 - if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP && + if (DPP_VERSION > 1 && + wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP && ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) { struct rsn_pmksa_cache_entry *pmksa; From 1a59ebf2e57cda8c4fcc67956ed20aa430a4d117 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 21:28:45 +0300 Subject: [PATCH 0448/1105] tests: DPP version override Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 44 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 0b69d8281..b9709e5a5 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -1770,7 +1770,36 @@ def test_dpp_auto_connect_2_connect_cmd(dev, apdev): finally: wpas.set("dpp_config_processing", "0", allow_fail=True) -def run_dpp_auto_connect(dev, apdev, processing): +def test_dpp_auto_connect_2_sta_ver1(dev, apdev): + """DPP and auto connect (2; STA using ver 1)""" + try: + run_dpp_auto_connect(dev, apdev, 2, sta_version=1) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def test_dpp_auto_connect_2_ap_ver1(dev, apdev): + """DPP and auto connect (2; AP using ver 1)""" + try: + run_dpp_auto_connect(dev, apdev, 2, ap_version=1) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def test_dpp_auto_connect_2_ver1(dev, apdev): + """DPP and auto connect (2; AP and STA using ver 1)""" + try: + run_dpp_auto_connect(dev, apdev, 2, ap_version=1, sta_version=1) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def test_dpp_auto_connect_2_conf_ver1(dev, apdev): + """DPP and auto connect (2; Configurator using ver 1)""" + try: + run_dpp_auto_connect(dev, apdev, 2, sta1_version=1) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_auto_connect(dev, apdev, processing, ap_version=0, sta_version=0, + sta1_version=0): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) @@ -1789,9 +1818,15 @@ def run_dpp_auto_connect(dev, apdev, processing): "dpp_netaccesskey": ap_netaccesskey} try: hapd = hostapd.add_ap(apdev[0], params) + if ap_version: + hapd.set("dpp_version_override", str(ap_version)) except: raise HwsimSkip("DPP not supported") + if sta_version: + dev[0].set("dpp_version_override", str(sta_version)) + if sta1_version: + dev[1].set("dpp_version_override", str(sta1_version)) conf_id = dev[1].dpp_configurator_add(key=csign) dev[0].set("dpp_config_processing", str(processing)) id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) @@ -5253,6 +5288,13 @@ def test_dpp_pfs_connect_cmd(dev, apdev): run_dpp_pfs_sta(wpas, 1, pfs_expected=True) run_dpp_pfs_sta(wpas, 2, pfs_expected=False) +def test_dpp_pfs_ap_0_sta_ver1(dev, apdev): + """DPP PFS AP default with version 1 STA""" + check_dpp_capab(dev[0]) + dev[0].set("dpp_version_override", "1") + hapd = start_dpp_pfs_ap(apdev[0], 0) + run_dpp_pfs_sta(dev[0], 0, pfs_expected=False) + def test_dpp_reconfig_connector(dev, apdev): """DPP reconfiguration connector""" try: From 8a8001989aa68093ed2a1013356551f71f30c0c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 23:01:11 +0300 Subject: [PATCH 0449/1105] tests: Clear power save configuration in ap_open_sta_ps It looks like this test case was supposed to set power_save off at the end instead of repeating the same setting twice. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_open.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_open.py b/tests/hwsim/test_ap_open.py index 2919cda52..442868273 100644 --- a/tests/hwsim/test_ap_open.py +++ b/tests/hwsim/test_ap_open.py @@ -506,7 +506,7 @@ def test_ap_open_sta_ps(dev, apdev): run_ap_open_sta_ps(dev, hapd) finally: dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, - 'set', 'power_save', 'on']) + 'set', 'power_save', 'off']) def run_ap_open_sta_ps(dev, hapd): hwsim_utils.test_connectivity(dev[0], hapd) From ccca850898371eea0b84391e11b90bfbd700ae48 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 23:02:33 +0300 Subject: [PATCH 0450/1105] tests: Disable power saving explicitly for pmksa_cache_ap_expiration This test case seems to be failing every now and then due to the AP not getting out the Deauthentication frame after PMKSA expiration if the STA is in power save mode. Signed-off-by: Jouni Malinen --- tests/hwsim/test_pmksa_cache.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/hwsim/test_pmksa_cache.py b/tests/hwsim/test_pmksa_cache.py index c334b48dd..22db7e8d4 100644 --- a/tests/hwsim/test_pmksa_cache.py +++ b/tests/hwsim/test_pmksa_cache.py @@ -663,6 +663,8 @@ def test_pmksa_cache_ap_expiration(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) bssid = apdev[0]['bssid'] + dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, + 'set', 'power_save', 'off']) dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP", eap="GPSK", identity="gpsk-user-session-timeout", password="abcdefghijklmnop0123456789abcdef", From bb8e191cca60756aa45500ac9c1ded30876bf406 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 1 May 2020 23:06:33 +0300 Subject: [PATCH 0451/1105] tests: Verify Deauthentication frame transmission to STA in PS mode Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_open.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/hwsim/test_ap_open.py b/tests/hwsim/test_ap_open.py index 442868273..62b44461b 100644 --- a/tests/hwsim/test_ap_open.py +++ b/tests/hwsim/test_ap_open.py @@ -528,6 +528,11 @@ def run_ap_open_sta_ps(dev, hapd): if not ok: raise Exception("STA did not enter power save") + + dev[0].dump_monitor() + hapd.dump_monitor() + hapd.request("DEAUTHENTICATE " + dev[0].own_addr()) + dev[0].wait_disconnected() except FileNotFoundError: raise HwsimSkip("Kernel does not support inspecting HW PS state") From fad64b416806c15dd646f0d9a6f439f5e5e43885 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 May 2020 19:43:10 +0300 Subject: [PATCH 0452/1105] DPP: Move dppCon signing to a set of helper functions This simplifies dpp_build_conf_obj_dpp() and makes it easier to share the signing functionality for other purposes like reconfiguration where the Configurator needs to sign a dppCon object for itself without generating the encapsulating config object. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 248 ++++++++++++++++++++++++++++------------------- 1 file changed, 150 insertions(+), 98 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index f8b13d6f5..8a7ed4bcc 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -4948,17 +4948,38 @@ static const char * dpp_netrole_str(enum dpp_netrole netrole) } -static struct wpabuf * -dpp_build_conf_obj_dpp(struct dpp_authentication *auth, - struct dpp_configuration *conf) +static char * +dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) { - struct wpabuf *buf = NULL; - char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; - size_t tailroom; - const struct dpp_curve_params *curve; struct wpabuf *jws_prot_hdr; - size_t signed1_len, signed2_len, signed3_len; - struct wpabuf *dppcon = NULL; + char *signed1; + + jws_prot_hdr = wpabuf_alloc(100); + if (!jws_prot_hdr) + return NULL; + json_start_object(jws_prot_hdr, NULL); + json_add_string(jws_prot_hdr, "typ", "dppCon"); + json_value_sep(jws_prot_hdr); + json_add_string(jws_prot_hdr, "kid", conf->kid); + json_value_sep(jws_prot_hdr); + json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg); + json_end_object(jws_prot_hdr); + signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), + wpabuf_len(jws_prot_hdr), + signed1_len); + wpabuf_free(jws_prot_hdr); + return signed1; +} + + +static char * +dpp_build_conn_signature(struct dpp_configurator *conf, + const char *signed1, size_t signed1_len, + const char *signed2, size_t signed2_len, + size_t *signed3_len) +{ + const struct dpp_curve_params *curve; + char *signed3 = NULL; unsigned char *signature = NULL; const unsigned char *p; size_t signature_len; @@ -4967,6 +4988,121 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth, char *dot = "."; const EVP_MD *sign_md; const BIGNUM *r, *s; + + curve = conf->curve; + if (curve->hash_len == SHA256_MAC_LEN) { + sign_md = EVP_sha256(); + } else if (curve->hash_len == SHA384_MAC_LEN) { + sign_md = EVP_sha384(); + } else if (curve->hash_len == SHA512_MAC_LEN) { + sign_md = EVP_sha512(); + } else { + wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); + goto fail; + } + + md_ctx = EVP_MD_CTX_create(); + if (!md_ctx) + goto fail; + + ERR_clear_error(); + if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, conf->csign) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 || + EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 || + EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + signature = os_malloc(signature_len); + if (!signature) + goto fail; + if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)", + signature, signature_len); + /* Convert to raw coordinates r,s */ + p = signature; + sig = d2i_ECDSA_SIG(NULL, &p, signature_len); + if (!sig) + goto fail; + ECDSA_SIG_get0(sig, &r, &s); + if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 || + dpp_bn2bin_pad(s, signature + curve->prime_len, + curve->prime_len) < 0) + goto fail; + signature_len = 2 * curve->prime_len; + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", + signature, signature_len); + signed3 = base64_url_encode(signature, signature_len, signed3_len); +fail: + EVP_MD_CTX_destroy(md_ctx); + ECDSA_SIG_free(sig); + os_free(signature); + return signed3; +} + +static char * +dpp_sign_connector(struct dpp_configurator *conf, const struct wpabuf *dppcon) +{ + char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; + char *signed_conn = NULL, *pos; + size_t signed1_len, signed2_len, signed3_len; + + signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len); + signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), + &signed2_len); + if (!signed1 || !signed2) + goto fail; + + signed3 = dpp_build_conn_signature(conf, signed1, signed1_len, + signed2, signed2_len, &signed3_len); + if (!signed3) + goto fail; + + signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3); + if (!signed_conn) + goto fail; + pos = signed_conn; + os_memcpy(pos, signed1, signed1_len); + pos += signed1_len; + *pos++ = '.'; + os_memcpy(pos, signed2, signed2_len); + pos += signed2_len; + *pos++ = '.'; + os_memcpy(pos, signed3, signed3_len); + pos += signed3_len; + *pos = '\0'; + +fail: + os_free(signed1); + os_free(signed2); + os_free(signed3); + return signed_conn; +} + + +static struct wpabuf * +dpp_build_conf_obj_dpp(struct dpp_authentication *auth, + struct dpp_configuration *conf) +{ + struct wpabuf *buf = NULL; + char *signed_conn = NULL; + size_t tailroom; + const struct dpp_curve_params *curve; + struct wpabuf *dppcon = NULL; size_t extra_len = 1000; int incl_legacy; enum dpp_akm akm; @@ -4978,16 +5114,6 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth, goto fail; } curve = auth->conf->curve; - if (curve->hash_len == SHA256_MAC_LEN) { - sign_md = EVP_sha256(); - } else if (curve->hash_len == SHA384_MAC_LEN) { - sign_md = EVP_sha384(); - } else if (curve->hash_len == SHA512_MAC_LEN) { - sign_md = EVP_sha512(); - } else { - wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); - goto fail; - } akm = conf->akm; if (dpp_akm_ver2(akm) && auth->peer_version < 2) { @@ -5060,79 +5186,14 @@ skip_groups: wpa_printf(MSG_DEBUG, "DPP: dppCon: %s", (const char *) wpabuf_head(dppcon)); - jws_prot_hdr = wpabuf_alloc(100); - if (!jws_prot_hdr) - goto fail; - json_start_object(jws_prot_hdr, NULL); - json_add_string(jws_prot_hdr, "typ", "dppCon"); - json_value_sep(jws_prot_hdr); - json_add_string(jws_prot_hdr, "kid", auth->conf->kid); - json_value_sep(jws_prot_hdr); - json_add_string(jws_prot_hdr, "alg", curve->jws_alg); - json_end_object(jws_prot_hdr); - signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), - wpabuf_len(jws_prot_hdr), - &signed1_len); - wpabuf_free(jws_prot_hdr); - signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), - &signed2_len); - if (!signed1 || !signed2) - goto fail; - - md_ctx = EVP_MD_CTX_create(); - if (!md_ctx) - goto fail; - - ERR_clear_error(); - if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, - auth->conf->csign) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 || - EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 || - EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - signature = os_malloc(signature_len); - if (!signature) - goto fail; - if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)", - signature, signature_len); - /* Convert to raw coordinates r,s */ - p = signature; - sig = d2i_ECDSA_SIG(NULL, &p, signature_len); - if (!sig) - goto fail; - ECDSA_SIG_get0(sig, &r, &s); - if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 || - dpp_bn2bin_pad(s, signature + curve->prime_len, - curve->prime_len) < 0) - goto fail; - signature_len = 2 * curve->prime_len; - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", - signature, signature_len); - signed3 = base64_url_encode(signature, signature_len, &signed3_len); - if (!signed3) + signed_conn = dpp_sign_connector(auth->conf, dppcon); + if (!signed_conn) goto fail; incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm); tailroom = 1000; tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid); - tailroom += signed1_len + signed2_len + signed3_len; + tailroom += os_strlen(signed_conn); if (incl_legacy) tailroom += 1000; buf = dpp_build_conf_start(auth, conf, tailroom); @@ -5151,11 +5212,7 @@ skip_groups: json_value_sep(buf); } wpabuf_put_str(buf, "\"signedConnector\":\""); - wpabuf_put_str(buf, signed1); - wpabuf_put_u8(buf, '.'); - wpabuf_put_str(buf, signed2); - wpabuf_put_u8(buf, '.'); - wpabuf_put_str(buf, signed3); + wpabuf_put_str(buf, signed_conn); wpabuf_put_str(buf, "\""); json_value_sep(buf); if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid, @@ -5171,12 +5228,7 @@ skip_groups: wpabuf_head(buf), wpabuf_len(buf)); out: - EVP_MD_CTX_destroy(md_ctx); - ECDSA_SIG_free(sig); - os_free(signed1); - os_free(signed2); - os_free(signed3); - os_free(signature); + os_free(signed_conn); wpabuf_free(dppcon); return buf; fail: From 769139c490754b1963e86e5edf70760cb7350112 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 4 May 2020 13:11:00 +0300 Subject: [PATCH 0453/1105] DPP2: Do not include Protocol Version in Auth Req when testing v1 When DPP v2 implementation is hardcoded to behave as v1 for testing purposes, leave out the Protocol Version attribute form Authentication Request instead of including it there with indication for v1. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 8a7ed4bcc..0d6dcd1fb 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1853,9 +1853,11 @@ static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, #ifdef CONFIG_DPP2 /* Protocol Version */ - wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); - wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, DPP_VERSION); + if (DPP_VERSION > 1) { + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } #endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS From 1d4a1a819adc87aeb7fe485dc39f2f0be4baf51e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 4 May 2020 15:07:23 +0300 Subject: [PATCH 0454/1105] tests: sigma_dut DPP chirping Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 69 +++++++++++++++++++++++++++++++++++ tests/hwsim/wpasupplicant.py | 5 ++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 33a4b5751..a336d45f7 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -2121,6 +2121,75 @@ def test_sigma_dut_dpp_incompatible_roles_resp(dev, apdev): finally: stop_sigma_dut(sigma) +def test_sigma_dut_dpp_qr_enrollee_chirp(dev, apdev): + """sigma_dut DPP/QR as chirping Enrollee""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + hapd = start_dpp_ap(apdev[0]) + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + try: + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,DPP" % ifname) + cmd = "dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPCryptoIdentifier,P-256,DPPBS,QR" + res = sigma_dut_cmd_check(cmd) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + hex = res.split(',')[3] + uri = from_hex(hex) + logger.info("URI from sigma_dut: " + uri) + + conf_id = dev[1].dpp_configurator_add(key=csign) + idc = dev[1].dpp_qr_code(uri) + dev[1].dpp_bootstrap_set(idc, conf="sta-dpp", configurator=conf_id, + ssid="DPPNET01") + dev[1].dpp_listen(2437) + + res = sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Responder,DPPAuthDirection,Single,DPPProvisioningRole,Enrollee,DPPBS,QR,DPPTimeout,16,DPPWaitForConnect,Yes,DPPChirp,Enable", timeout=20) + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,DPP" % ifname) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK" not in res: + raise Exception("Unexpected result: " + res) + finally: + dev[0].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + +def dpp_enrollee_chirp(dev, id1): + logger.info("Starting chirping Enrollee in a thread") + time.sleep(0.1) + cmd = "DPP_CHIRP own=%d" % id1 + if "OK" not in dev.request(cmd): + raise Exception("Failed to initiate DPP chirping") + ev = dev.wait_event(["DPP-CONF-RECEIVED"], timeout=15) + if ev is None: + raise Exception("DPP configuration not completed (Enrollee)") + logger.info("DPP enrollee done") + +def test_sigma_dut_dpp_qr_configurator_chirp(dev, apdev): + """sigma_dut DPP/QR as Configurator waiting for chirp""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + try: + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,DPP" % ifname) + + id1 = dev[1].dpp_bootstrap_gen(chan="81/1") + uri = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + + res = sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,QR" % to_hex(uri)) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + + t = threading.Thread(target=dpp_enrollee_chirp, args=(dev[1], id1)) + t.start() + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPAuthDirection,Single,DPPProvisioningRole,Configurator,DPPConfIndex,1,DPPConfEnrolleeRole,STA,DPPBS,QR,DPPTimeout,16,DPPChirp,Enable,DPPChirpChannel,6", timeout=20) + t.join() + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,DPP" % ifname) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: + raise Exception("Unexpected result: " + res) + finally: + dev[0].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + def test_sigma_dut_dpp_pkex_init_configurator(dev, apdev): """sigma_dut DPP/PKEX initiator as Configurator""" check_dpp_capab(dev[0]) diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index e273084ac..0ed043802 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1490,8 +1490,11 @@ class WpaSupplicant: raise Exception("Failed to generate bootstrapping info") return int(res) - def dpp_bootstrap_set(self, id, conf=None, configurator=None, extra=None): + def dpp_bootstrap_set(self, id, conf=None, configurator=None, ssid=None, + extra=None): cmd = "DPP_BOOTSTRAP_SET %d" % id + if ssid: + cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode() if extra: cmd += " " + extra if conf: From 5a0718a19c58af1a6a072b6325c4fdde57ebd967 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 4 May 2020 15:31:14 +0300 Subject: [PATCH 0455/1105] DPP2: Report MUD URL and bandSupport in control interface events Report MUD URL and bandSupport from config request if those optional nodes are included. For now, these are mainly for testing purposes since there is no mechanism to delay sending of config response. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 31 ++++++++++++++++++++++++++++--- src/common/wpa_ctrl.h | 2 ++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 0d6dcd1fb..49f638099 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -6081,23 +6081,48 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, } token = json_get_member(root, "mudurl"); - if (token && token->type == JSON_STRING) + if (token && token->type == JSON_STRING) { wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string); + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s", + token->string); + } token = json_get_member(root, "bandSupport"); if (token && token->type == JSON_ARRAY) { + int *opclass = NULL; + char txt[200], *pos, *end; + int i, res; + wpa_printf(MSG_DEBUG, "DPP: bandSupport"); token = token->child; while (token) { - if (token->type != JSON_NUMBER) + if (token->type != JSON_NUMBER) { wpa_printf(MSG_DEBUG, "DPP: Invalid bandSupport array member type"); - else + } else { wpa_printf(MSG_DEBUG, "DPP: Supported global operating class: %d", token->number); + int_array_add_unique(&opclass, token->number); + } token = token->sibling; } + + txt[0] = '\0'; + pos = txt; + end = txt + sizeof(txt); + for (i = 0; opclass && opclass[i]; i++) { + res = os_snprintf(pos, end - pos, "%s%d", + pos == txt ? "" : ",", opclass[i]); + if (os_snprintf_error(end - pos, res)) { + *pos = '\0'; + break; + } + pos += res; + } + os_free(opclass); + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s", + txt); } resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole); diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index ca1c35f85..354de2854 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -190,6 +190,8 @@ extern "C" { #define DPP_EVENT_INTRO "DPP-INTRO " #define DPP_EVENT_CONF_REQ_RX "DPP-CONF-REQ-RX " #define DPP_EVENT_CHIRP_STOPPED "DPP-CHIRP-STOPPED " +#define DPP_EVENT_MUD_URL "DPP-MUD-URL " +#define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT " /* MESH events */ #define MESH_GROUP_STARTED "MESH-GROUP-STARTED " From c32c3bcc6bf8a5df283c74e2230394fd3b4bfeb2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 4 May 2020 15:32:35 +0300 Subject: [PATCH 0456/1105] tests: sigma_dut and DPP MUD URL Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index a336d45f7..1d072af2e 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -1716,13 +1716,20 @@ def test_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev): run_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev, extra="DPPAuthDirection,Mutual,") -def run_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev, extra=''): +def test_sigma_dut_dpp_qr_mutual_init_enrollee_mud_url(dev, apdev): + """sigma_dut DPP/QR (mutual) initiator as Enrollee (MUD URL)""" + run_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev, + mud_url="https://example.com/mud") + +def run_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev, extra='', + mud_url=None): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) hapd = start_dpp_ap(apdev[0]) - sigma = start_sigma_dut(dev[0].ifname) + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) try: - dev[0].set("dpp_config_processing", "2") + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,DPP" % ifname) cmd = "DPP_CONFIGURATOR_ADD key=" + csign res = dev[1].request(cmd) @@ -1752,9 +1759,20 @@ def run_sigma_dut_dpp_qr_mutual_init_enrollee_check(dev, apdev, extra=''): if "status,COMPLETE" not in res: raise Exception("dev_exec_action did not succeed: " + res) - res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,%sDPPProvisioningRole,Enrollee,DPPBS,QR,DPPTimeout,6,DPPWaitForConnect,Yes" % extra, timeout=10) + cmd = "dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,%sDPPProvisioningRole,Enrollee,DPPBS,QR,DPPTimeout,6,DPPWaitForConnect,Yes" % extra + if mud_url: + cmd += ",MUDURL," + mud_url + res = sigma_dut_cmd_check(cmd, timeout=10) + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,DPP" % ifname) if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK" not in res: raise Exception("Unexpected result: " + res) + + if mud_url: + ev = dev[1].wait_event(["DPP-MUD-URL"], timeout=1) + if ev is None: + raise Exception("DPP MUD URL not reported") + if ev.split(' ')[1] != mud_url: + raise Exception("Unexpected MUD URL value: " + ev) finally: dev[0].set("dpp_config_processing", "0") stop_sigma_dut(sigma) From cbafc8ef4b01b92e97a9a1e2829a0197ee805c73 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 5 May 2020 00:18:29 +0300 Subject: [PATCH 0457/1105] Fix truncated control interface command detection The recvfrom() calls were supposed to use the full allocated buffer size (max+1) to match the res > max check. Fixes: 96b6dd21a022 ("Increase wpa_supplicant control interface buffer size") Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface_unix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c index 35a38c95f..953fd2ccf 100644 --- a/wpa_supplicant/ctrl_iface_unix.c +++ b/wpa_supplicant/ctrl_iface_unix.c @@ -142,7 +142,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); if (!buf) return; - res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN + 1, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", @@ -1066,7 +1066,7 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); if (!buf) return; - res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN + 1, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", From 7dd768c3ca768d52c3bb4c74b58bbf1259568c2c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 5 May 2020 20:48:23 +0300 Subject: [PATCH 0458/1105] DPP2: Version information in bootstrapping info URI Add the local supported version information into the bootstrapping information (V=2 in the URI) and parse this from received URI. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 36 +++++++++++++++++++++++++++++++++--- src/common/dpp.h | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 49f638099..bdcb0be4d 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1042,6 +1042,26 @@ int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info) } +int dpp_parse_uri_version(struct dpp_bootstrap_info *bi, const char *version) +{ +#ifdef CONFIG_DPP2 + if (!version || DPP_VERSION < 2) + return 0; + + if (*version == '1') + bi->version = 1; + else if (*version == '2') + bi->version = 2; + else + wpa_printf(MSG_DEBUG, "DPP: Unknown URI version"); + + wpa_printf(MSG_DEBUG, "DPP: URI version: %d", bi->version); +#endif /* CONFIG_DPP2 */ + + return 0; +} + + static const struct dpp_curve_params * dpp_get_curve_oid(const ASN1_OBJECT *poid) { @@ -1239,6 +1259,7 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) const char *pos = uri; const char *end; const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL; + const char *version = NULL; struct dpp_bootstrap_info *bi; wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri)); @@ -1269,6 +1290,8 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) info = pos + 2; else if (pos[0] == 'K' && pos[1] == ':' && !pk) pk = pos + 2; + else if (pos[0] == 'V' && pos[1] == ':' && !version) + version = pos + 2; else wpa_hexdump_ascii(MSG_DEBUG, "DPP: Ignore unrecognized URI parameter", @@ -1289,6 +1312,7 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) dpp_parse_uri_chan_list(bi, chan_list) < 0 || dpp_parse_uri_mac(bi, mac) < 0 || dpp_parse_uri_info(bi, info) < 0 || + dpp_parse_uri_version(bi, info) < 0 || dpp_parse_uri_pk(bi, pk) < 0) { dpp_bootstrap_info_free(bi); bi = NULL; @@ -2327,18 +2351,22 @@ static int dpp_gen_uri(struct dpp_bootstrap_info *bi) len += os_strlen(macstr); /* M:...; */ if (bi->info) len += 3 + os_strlen(bi->info); /* I:...; */ +#ifdef CONFIG_DPP2 + len += 4; /* V:2; */ +#endif /* CONFIG_DPP2 */ len += 4 + os_strlen(bi->pk); /* K:...;; */ os_free(bi->uri); bi->uri = os_malloc(len + 1); if (!bi->uri) return -1; - os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%sK:%s;;", + os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%sK:%s;;", bi->chan ? "C:" : "", bi->chan ? bi->chan : "", bi->chan ? ";" : "", macstr, bi->info ? "I:" : "", bi->info ? bi->info : "", bi->info ? ";" : "", + DPP_VERSION == 2 ? "V:2;" : "", bi->pk); return 0; } @@ -10660,14 +10688,16 @@ int dpp_bootstrap_info(struct dpp_global *dpp, int id, "num_freq=%u\n" "use_freq=%u\n" "curve=%s\n" - "pkhash=%s\n", + "pkhash=%s\n" + "version=%d\n", dpp_bootstrap_type_txt(bi->type), MAC2STR(bi->mac_addr), bi->info ? bi->info : "", bi->num_freq, bi->num_freq == 1 ? bi->freq[0] : 0, bi->curve->name, - pkhash); + pkhash, + bi->version); } diff --git a/src/common/dpp.h b/src/common/dpp.h index e6cdf1103..de987dd93 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -142,6 +142,7 @@ struct dpp_bootstrap_info { char *pk; unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; unsigned int num_freq; + u8 version; int own; EVP_PKEY *pubkey; u8 pubkey_hash[SHA256_MAC_LEN]; From 6b8dde4ec9988d648d3f8471e062a808271ece60 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 6 May 2020 01:14:13 +0300 Subject: [PATCH 0459/1105] tests: sigma_dut controlled AP doing DPP on offchannel Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 1d072af2e..dd3f35fb9 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -2302,6 +2302,61 @@ def run_sigma_dut_ap_dpp_qr(dev, apdev, params, ap_conf, sta_conf, extra=""): dev[1].set("dpp_config_processing", "0") stop_sigma_dut(sigma) +def test_sigma_dut_ap_dpp_offchannel(dev, apdev, params): + """sigma_dut controlled AP doing DPP on offchannel""" + check_dpp_capab(dev[0]) + logdir = params['prefix'] + ".sigma-hostapd" + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default,program,DPP") + sigma_dut_cmd_check("ap_preset_testparameters,Program,DPP,Oper_Chn,3") + res = sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPCryptoIdentifier,P-256,DPPBS,QR") + hex = res.split(',')[3] + uri = from_hex(hex) + logger.info("URI from sigma_dut: " + uri) + if "C:81/3;" not in uri: + raise Exception("Unexpected channel in AP's URI: " + uri) + + cmd = "DPP_CONFIGURATOR_ADD" + res = dev[0].request(cmd) + if "FAIL" in res: + raise Exception("Failed to add configurator") + conf_id = int(res) + + id0 = dev[0].dpp_bootstrap_gen(chan="81/7", mac=True) + uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + dev[0].set("dpp_configurator_params", + "conf=ap-dpp ssid=%s configurator=%d" % (to_hex("DPPNET01"), conf_id)) + dev[0].dpp_listen(2442) + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,QR" % to_hex(uri0)) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPAuthDirection,Single,DPPProvisioningRole,Enrollee,DPPBS,QR,DPPTimeout,6") + if "ConfResult,OK" not in res: + raise Exception("Unexpected result: " + res) + + id1 = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True) + uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + + id0b = dev[0].dpp_qr_code(uri1) + + dev[1].set("dpp_config_processing", "2") + cmd = "DPP_LISTEN 2412" + if "OK" not in dev[1].request(cmd): + raise Exception("Failed to start listen operation") + cmd = "DPP_AUTH_INIT peer=%d conf=sta-dpp ssid=%s configurator=%d" % (id0b, to_hex("DPPNET01"), conf_id) + if "OK" not in dev[0].request(cmd): + raise Exception("Failed to initiate DPP Authentication") + dev[1].wait_connected() + + sigma_dut_cmd_check("ap_reset_default") + finally: + dev[1].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + def test_sigma_dut_ap_dpp_pkex_responder(dev, apdev, params): """sigma_dut controlled AP as DPP PKEX responder""" check_dpp_capab(dev[0]) From 481fdfc462dda6929a895b7df7b935efa35ccd83 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 6 May 2020 11:58:04 +0300 Subject: [PATCH 0460/1105] DPP2: Fix URI version parser Fix a copy-paste error in parsing the version info. Fixes: 7dd768c3ca76 ("DPP2: Version information in bootstrapping info URI") Signed-off-by: Jouni Malinen --- src/common/dpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index bdcb0be4d..518c00b8d 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1312,7 +1312,7 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) dpp_parse_uri_chan_list(bi, chan_list) < 0 || dpp_parse_uri_mac(bi, mac) < 0 || dpp_parse_uri_info(bi, info) < 0 || - dpp_parse_uri_version(bi, info) < 0 || + dpp_parse_uri_version(bi, version) < 0 || dpp_parse_uri_pk(bi, pk) < 0) { dpp_bootstrap_info_free(bi); bi = NULL; From 046f2d1fb9aad0bf2ee68296e2de105a3f7c37fe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 6 May 2020 11:59:11 +0300 Subject: [PATCH 0461/1105] tests: DPP URI version information Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index b9709e5a5..fe307288d 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -110,6 +110,33 @@ def test_dpp_qr_code_parsing(dev, apdev): dev[0].dpp_qr_code(uri) +def test_dpp_uri_version(dev, apdev): + """DPP URI version information""" + check_dpp_capab(dev[0], min_ver=2) + + id0 = dev[0].dpp_bootstrap_gen() + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + logger.info("Generated URI: " + uri) + + id1 = dev[0].dpp_qr_code(uri) + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id1) + logger.info("Parsed URI info:\n" + info) + if "version=2" not in info.splitlines(): + raise Exception("Unexpected version information (v2)") + + dev[0].set("dpp_version_override", "1") + id0 = dev[0].dpp_bootstrap_gen() + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + logger.info("Generated URI: " + uri) + + id1 = dev[0].dpp_qr_code(uri) + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id1) + logger.info("Parsed URI info:\n" + info) + if "version=0" not in info.splitlines(): + raise Exception("Unexpected version information (without indication)") + def test_dpp_qr_code_parsing_fail(dev, apdev): """DPP QR Code parsing local failure""" check_dpp_capab(dev[0]) From 0a488ef35c28970c561d84787067a3350b563784 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 9 May 2020 17:30:48 +0300 Subject: [PATCH 0462/1105] DPP: Track ending time for remain-on-channel operations This may be needed to optimize use of offchannel TX operations with wait-for-response when near the end of a pending remain-on-channel operation. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 18 ++++++++++++++++++ wpa_supplicant/dpp_supplicant.h | 2 ++ wpa_supplicant/events.c | 5 +++++ wpa_supplicant/wpa_supplicant_i.h | 1 + 4 files changed, 26 insertions(+) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index eae62e289..837ddbe04 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -938,6 +938,24 @@ void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s) } +void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq, unsigned int duration) +{ + if (wpa_s->dpp_listen_freq != freq) + return; + + wpa_printf(MSG_DEBUG, + "DPP: Remain-on-channel started for listen on %u MHz for %u ms", + freq, duration); + os_get_reltime(&wpa_s->dpp_listen_end); + wpa_s->dpp_listen_end.usec += duration * 1000; + while (wpa_s->dpp_listen_end.usec >= 1000000) { + wpa_s->dpp_listen_end.sec++; + wpa_s->dpp_listen_end.usec -= 1000000; + } +} + + void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, unsigned int freq) { diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h index 2ce378dc1..6d70874c4 100644 --- a/wpa_supplicant/dpp_supplicant.h +++ b/wpa_supplicant/dpp_supplicant.h @@ -19,6 +19,8 @@ int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd); void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s); +void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq, unsigned int duration); void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, unsigned int freq); void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index a25b43db0..46341e936 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -5005,6 +5005,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, wpas_p2p_remain_on_channel_cb( wpa_s, data->remain_on_channel.freq, data->remain_on_channel.duration); +#ifdef CONFIG_DPP + wpas_dpp_remain_on_channel_cb( + wpa_s, data->remain_on_channel.freq, + data->remain_on_channel.duration); +#endif /* CONFIG_DPP */ break; case EVENT_CANCEL_REMAIN_ON_CHANNEL: #ifdef CONFIG_OFFCHANNEL diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 619ae42b6..2ed8e2f85 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1249,6 +1249,7 @@ struct wpa_supplicant { struct wpa_radio_work *dpp_listen_work; unsigned int dpp_pending_listen_freq; unsigned int dpp_listen_freq; + struct os_reltime dpp_listen_end; u8 dpp_allowed_roles; int dpp_qr_mutual; int dpp_netrole; From 76029c6e119f36ec10716d2b199bee951734437f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 10 May 2020 15:42:47 +0300 Subject: [PATCH 0463/1105] DPP: Use EVP_PKEY_get0_EC_KEY() when a const reference is sufficient This removes unnecessary allocations and simplifies the implementation by not having to remember to free the cloned reference. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 60 +++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 37 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 518c00b8d..b668e8f41 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -79,14 +79,12 @@ static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, } -#ifdef CONFIG_DPP2 static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { if (pkey->type != EVP_PKEY_EC) return NULL; return pkey->pkey.ec; } -#endif /* CONFIG_DPP2 */ #endif @@ -673,14 +671,14 @@ fail: static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len) { - EC_KEY *eckey; + const EC_KEY *eckey; const EC_GROUP *group; EVP_PKEY *pkey = NULL; if (len & 1) return NULL; - eckey = EVP_PKEY_get1_EC_KEY(group_key); + eckey = EVP_PKEY_get0_EC_KEY(group_key); if (!eckey) { wpa_printf(MSG_ERROR, "DPP: Could not get EC_KEY from group_key"); @@ -694,7 +692,6 @@ static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, else wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); - EC_KEY_free(eckey); return pkey; } @@ -1519,7 +1516,7 @@ static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) { unsigned char *der = NULL; int der_len; - EC_KEY *eckey; + const EC_KEY *eckey; struct wpabuf *ret = NULL; size_t len; const EC_GROUP *group; @@ -1529,7 +1526,7 @@ static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) int nid; ctx = BN_CTX_new(); - eckey = EVP_PKEY_get1_EC_KEY(key); + eckey = EVP_PKEY_get0_EC_KEY(key); if (!ctx || !eckey) goto fail; @@ -1576,7 +1573,6 @@ static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) fail: DPP_BOOTSTRAPPING_KEY_free(bootstrap); OPENSSL_free(der); - EC_KEY_free(eckey); BN_CTX_free(ctx); return ret; } @@ -2956,7 +2952,7 @@ static int dpp_auth_derive_l_responder(struct dpp_authentication *auth) { const EC_GROUP *group; EC_POINT *l = NULL; - EC_KEY *BI = NULL, *bR = NULL, *pR = NULL; + const EC_KEY *BI, *bR, *pR; const EC_POINT *BI_point; BN_CTX *bnctx; BIGNUM *lx, *sum, *q; @@ -2971,7 +2967,7 @@ static int dpp_auth_derive_l_responder(struct dpp_authentication *auth) lx = BN_new(); if (!bnctx || !sum || !q || !lx) goto fail; - BI = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey); + BI = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); if (!BI) goto fail; BI_point = EC_KEY_get0_public_key(BI); @@ -2979,8 +2975,8 @@ static int dpp_auth_derive_l_responder(struct dpp_authentication *auth) if (!group) goto fail; - bR = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey); - pR = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key); + bR = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); + pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); if (!bR || !pR) goto fail; bR_bn = EC_KEY_get0_private_key(bR); @@ -3008,9 +3004,6 @@ static int dpp_auth_derive_l_responder(struct dpp_authentication *auth) ret = 0; fail: EC_POINT_clear_free(l); - EC_KEY_free(BI); - EC_KEY_free(bR); - EC_KEY_free(pR); BN_clear_free(lx); BN_clear_free(sum); BN_free(q); @@ -3023,7 +3016,7 @@ static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) { const EC_GROUP *group; EC_POINT *l = NULL, *sum = NULL; - EC_KEY *bI = NULL, *BR = NULL, *PR = NULL; + const EC_KEY *bI, *BR, *PR; const EC_POINT *BR_point, *PR_point; BN_CTX *bnctx; BIGNUM *lx; @@ -3036,14 +3029,14 @@ static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) lx = BN_new(); if (!bnctx || !lx) goto fail; - BR = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey); - PR = EVP_PKEY_get1_EC_KEY(auth->peer_protocol_key); + BR = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); + PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); if (!BR || !PR) goto fail; BR_point = EC_KEY_get0_public_key(BR); PR_point = EC_KEY_get0_public_key(PR); - bI = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey); + bI = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); if (!bI) goto fail; group = EC_KEY_get0_group(bI); @@ -3071,9 +3064,6 @@ static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) fail: EC_POINT_clear_free(l); EC_POINT_clear_free(sum); - EC_KEY_free(bI); - EC_KEY_free(BR); - EC_KEY_free(PR); BN_clear_free(lx); BN_CTX_free(bnctx); return ret; @@ -6635,11 +6625,11 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, ECDSA_SIG *sig = NULL; BIGNUM *r = NULL, *s = NULL; const struct dpp_curve_params *curve; - EC_KEY *eckey; + const EC_KEY *eckey; const EC_GROUP *group; int nid; - eckey = EVP_PKEY_get1_EC_KEY(csign_pub); + eckey = EVP_PKEY_get0_EC_KEY(csign_pub); if (!eckey) goto fail; group = EC_KEY_get0_group(eckey); @@ -6768,7 +6758,6 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, ret = DPP_STATUS_OK; fail: - EC_KEY_free(eckey); EVP_MD_CTX_destroy(md_ctx); os_free(prot_hdr); wpabuf_free(kid); @@ -8788,7 +8777,7 @@ static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, unsigned int num_elem = 0; EC_POINT *Qi = NULL; EVP_PKEY *Pi = NULL; - EC_KEY *Pi_ec = NULL; + const EC_KEY *Pi_ec; const EC_POINT *Pi_point; BIGNUM *hash_bn = NULL; const EC_GROUP *group = NULL; @@ -8820,7 +8809,7 @@ static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, if (!Pi) goto fail; dpp_debug_print_key("DPP: Pi", Pi); - Pi_ec = EVP_PKEY_get1_EC_KEY(Pi); + Pi_ec = EVP_PKEY_get0_EC_KEY(Pi); if (!Pi_ec) goto fail; Pi_point = EC_KEY_get0_public_key(Pi_ec); @@ -8846,7 +8835,6 @@ static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, } dpp_debug_print_point("DPP: Qi", group, Qi); out: - EC_KEY_free(Pi_ec); EVP_PKEY_free(Pi); BN_clear_free(hash_bn); if (ret_group && Qi) @@ -8872,7 +8860,7 @@ static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, unsigned int num_elem = 0; EC_POINT *Qr = NULL; EVP_PKEY *Pr = NULL; - EC_KEY *Pr_ec = NULL; + const EC_KEY *Pr_ec; const EC_POINT *Pr_point; BIGNUM *hash_bn = NULL; const EC_GROUP *group = NULL; @@ -8904,7 +8892,7 @@ static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, if (!Pr) goto fail; dpp_debug_print_key("DPP: Pr", Pr); - Pr_ec = EVP_PKEY_get1_EC_KEY(Pr); + Pr_ec = EVP_PKEY_get0_EC_KEY(Pr); if (!Pr_ec) goto fail; Pr_point = EC_KEY_get0_public_key(Pr_ec); @@ -8930,7 +8918,6 @@ static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, } dpp_debug_print_point("DPP: Qr", group, Qr); out: - EC_KEY_free(Pr_ec); EVP_PKEY_free(Pr); BN_clear_free(hash_bn); if (ret_group && Qr) @@ -9014,7 +9001,7 @@ fail: static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex) { - EC_KEY *X_ec = NULL; + const EC_KEY *X_ec; const EC_POINT *X_point; BN_CTX *bnctx = NULL; EC_GROUP *group = NULL; @@ -9056,7 +9043,7 @@ static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex) goto fail; /* M = X + Qi */ - X_ec = EVP_PKEY_get1_EC_KEY(pkex->x); + X_ec = EVP_PKEY_get0_EC_KEY(pkex->x); if (!X_ec) goto fail; X_point = EC_KEY_get0_public_key(X_ec); @@ -9133,7 +9120,6 @@ skip_finite_cyclic_group: out: wpabuf_free(M_buf); - EC_KEY_free(X_ec); EC_POINT_free(M); EC_POINT_free(Qi); BN_clear_free(Mx); @@ -9386,7 +9372,8 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx, BN_CTX *bnctx = NULL; EC_GROUP *group = NULL; BIGNUM *Mx = NULL, *My = NULL; - EC_KEY *Y_ec = NULL, *X_ec = NULL;; + const EC_KEY *Y_ec; + EC_KEY *X_ec = NULL; const EC_POINT *Y_point; BIGNUM *Nx = NULL, *Ny = NULL; u8 Kx[DPP_MAX_SHARED_SECRET_LEN]; @@ -9536,7 +9523,7 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx, goto fail; /* N = Y + Qr */ - Y_ec = EVP_PKEY_get1_EC_KEY(pkex->y); + Y_ec = EVP_PKEY_get0_EC_KEY(pkex->y); if (!Y_ec) goto fail; Y_point = EC_KEY_get0_public_key(Y_ec); @@ -9588,7 +9575,6 @@ out: EC_POINT_free(N); EC_POINT_free(X); EC_KEY_free(X_ec); - EC_KEY_free(Y_ec); EC_GROUP_free(group); return pkex; fail: From 16626dff9b110f86584d6c4198c00a857e0d5727 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 8 May 2020 21:13:32 +0300 Subject: [PATCH 0464/1105] DPP2: Derive bk ("base key") Split ke derivation into two parts so that the previously used internal-only PRK gets stored as the bk in the authentication state. This new key will be needed for deriving additional keys with DPP R2. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 35 +++++++++++++++++------------------ src/common/dpp.h | 1 + 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index b668e8f41..76580d642 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1713,13 +1713,12 @@ static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, } -static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke, - unsigned int hash_len) +static int dpp_derive_bk_ke(struct dpp_authentication *auth) { - size_t nonce_len; + unsigned int hash_len = auth->curve->hash_len; + size_t nonce_len = auth->curve->nonce_len; u8 nonces[2 * DPP_MAX_NONCE_LEN]; const char *info_ke = "DPP Key"; - u8 prk[DPP_MAX_HASH_LEN]; int res; const u8 *addr[3]; size_t len[3]; @@ -1731,10 +1730,7 @@ static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke, return -1; } - /* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */ - - /* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ - nonce_len = auth->curve->nonce_len; + /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ os_memcpy(nonces, auth->i_nonce, nonce_len); os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); addr[num_elem] = auth->Mx; @@ -1754,20 +1750,23 @@ static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke, num_elem++; } res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, - num_elem, addr, len, prk); + num_elem, addr, len, auth->bk); if (res < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", - prk, hash_len); + wpa_hexdump_key(MSG_DEBUG, + "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])", + auth->bk, hash_len); - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len); - os_memset(prk, 0, hash_len); + /* ke = HKDF-Expand(bkK, "DPP Key", length) */ + res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke, + hash_len); if (res < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)", - ke, hash_len); + wpa_hexdump_key(MSG_DEBUG, + "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)", + auth->ke, hash_len); + return 0; } @@ -3153,7 +3152,7 @@ static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) goto fail; } - if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0) + if (dpp_derive_bk_ke(auth) < 0) goto fail; /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ @@ -4160,7 +4159,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", wrapped2, wrapped2_len); - if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0) + if (dpp_derive_bk_ke(auth) < 0) goto fail; unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE; diff --git a/src/common/dpp.h b/src/common/dpp.h index de987dd93..e81526fc8 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -264,6 +264,7 @@ struct dpp_authentication { u8 k1[DPP_MAX_HASH_LEN]; u8 k2[DPP_MAX_HASH_LEN]; u8 ke[DPP_MAX_HASH_LEN]; + u8 bk[DPP_MAX_HASH_LEN]; int initiator; int waiting_auth_resp; int waiting_auth_conf; From 6eb03715e31a6218e73210da76c6de2e0fcb4435 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 9 May 2020 17:39:15 +0300 Subject: [PATCH 0465/1105] tests: Update dpp_pkex_test_fail to match implementation dpp_derive_ke() was renamed to dpp_derive_bk_ke(). Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index fe307288d..d832b98d4 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -3719,8 +3719,8 @@ def test_dpp_pkex_test_fail(dev, apdev): (1, "aes_siv_encrypt;dpp_auth_build_conf"), (1, "dpp_derive_k2;dpp_auth_resp_rx"), (1, "dpp_hkdf_expand;dpp_derive_k2;dpp_auth_resp_rx"), - (1, "dpp_derive_ke;dpp_auth_resp_rx"), - (1, "dpp_hkdf_expand;dpp_derive_ke;dpp_auth_resp_rx"), + (1, "dpp_derive_bk_ke;dpp_auth_resp_rx"), + (1, "dpp_hkdf_expand;dpp_derive_bk_ke;dpp_auth_resp_rx"), (1, "dpp_gen_r_auth;dpp_auth_resp_rx"), (1, "aes_siv_encrypt;dpp_build_conf_resp"), (1, "dpp_pkex_derive_Qi;dpp_pkex_build_exchange_req"), @@ -3755,7 +3755,7 @@ def test_dpp_pkex_test_fail(dev, apdev): (1, "aes_siv_encrypt;dpp_build_conf_req"), (1, "os_get_random;dpp_auth_build_resp_ok"), (1, "dpp_derive_k2;dpp_auth_build_resp_ok"), - (1, "dpp_derive_ke;dpp_auth_build_resp_ok"), + (1, "dpp_derive_bk_ke;dpp_auth_build_resp_ok"), (1, "dpp_gen_r_auth;dpp_auth_build_resp_ok"), (1, "aes_siv_encrypt;dpp_auth_build_resp_ok"), (1, "dpp_derive_k1;dpp_auth_req_rx"), From 87b65726169cc53a614ab3755f8dd98e7c0d54fe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 10 May 2020 16:25:42 +0300 Subject: [PATCH 0466/1105] DPP: Move crypto routines into a separate source code file This is an initial step in splitting the overly long dpp.c into smaller pieces. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 1 + hostapd/Makefile | 1 + src/common/dpp.c | 2563 +------------------------------- src/common/dpp_crypto.c | 2551 +++++++++++++++++++++++++++++++ src/common/dpp_i.h | 91 ++ tests/fuzzing/dpp-uri/Makefile | 1 + wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + 8 files changed, 2662 insertions(+), 2548 deletions(-) create mode 100644 src/common/dpp_crypto.c create mode 100644 src/common/dpp_i.h diff --git a/hostapd/Android.mk b/hostapd/Android.mk index d47b64f4e..e8eca2e89 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -537,6 +537,7 @@ endif ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c +OBJS += src/common/dpp_crypto.c OBJS += src/ap/dpp_hostapd.c OBJS += src/ap/gas_query_ap.c NEED_AES_SIV=y diff --git a/hostapd/Makefile b/hostapd/Makefile index 9475f2e84..92ffdeeb1 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -568,6 +568,7 @@ endif ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o +OBJS += ../src/common/dpp_crypto.o OBJS += ../src/ap/dpp_hostapd.o OBJS += ../src/ap/gas_query_ap.o NEED_AES_SIV=y diff --git a/src/common/dpp.c b/src/common/dpp.c index 76580d642..b8e1d7866 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include "utils/common.h" #include "utils/base64.h" @@ -20,18 +18,16 @@ #include "utils/ip_addr.h" #include "utils/eloop.h" #include "common/ieee802_11_common.h" -#include "common/ieee802_11_defs.h" #include "common/wpa_ctrl.h" #include "common/gas.h" #include "crypto/crypto.h" #include "crypto/random.h" #include "crypto/aes.h" #include "crypto/aes_siv.h" -#include "crypto/sha384.h" -#include "crypto/sha512.h" #include "tls/asn1.h" #include "drivers/driver.h" #include "dpp.h" +#include "dpp_i.h" static const char * dpp_netrole_str(enum dpp_netrole netrole); @@ -51,9 +47,6 @@ u8 dpp_protocol_key_override[600]; size_t dpp_protocol_key_override_len = 0; u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; size_t dpp_nonce_override_len = 0; - -static int dpp_test_gen_invalid_key(struct wpabuf *msg, - const struct dpp_curve_params *curve); #endif /* CONFIG_TESTING_OPTIONS */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ @@ -61,24 +54,6 @@ static int dpp_test_gen_invalid_key(struct wpabuf *msg, LIBRESSL_VERSION_NUMBER < 0x20700000L) /* Compatibility wrappers for older versions. */ -static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) -{ - sig->r = r; - sig->s = s; - return 1; -} - - -static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, - const BIGNUM **ps) -{ - if (pr) - *pr = sig->r; - if (ps) - *ps = sig->s; -} - - static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { if (pkey->type != EVP_PKEY_EC) @@ -148,638 +123,6 @@ struct dpp_global { #endif /* CONFIG_DPP2 */ }; -static const struct dpp_curve_params dpp_curves[] = { - /* The mandatory to support and the default NIST P-256 curve needs to - * be the first entry on this list. */ - { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" }, - { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, - { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, - { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, - { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, - { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, - { NULL, 0, 0, 0, 0, NULL, 0, NULL } -}; - - -/* Role-specific elements for PKEX */ - -/* NIST P-256 */ -static const u8 pkex_init_x_p256[32] = { - 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, - 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, - 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, - 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25 - }; -static const u8 pkex_init_y_p256[32] = { - 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, - 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, - 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, - 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 - }; -static const u8 pkex_resp_x_p256[32] = { - 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, - 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, - 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, - 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76 -}; -static const u8 pkex_resp_y_p256[32] = { - 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, - 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, - 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, - 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 -}; - -/* NIST P-384 */ -static const u8 pkex_init_x_p384[48] = { - 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa, - 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68, - 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53, - 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac, - 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12, - 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3 -}; -static const u8 pkex_init_y_p384[48] = { - 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29, - 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56, - 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7, - 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6, - 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94, - 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18 -}; -static const u8 pkex_resp_x_p384[48] = { - 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98, - 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97, - 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92, - 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44, - 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf, - 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf -}; -static const u8 pkex_resp_y_p384[48] = { - 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c, - 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c, - 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3, - 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1, - 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63, - 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06 -}; - -/* NIST P-521 */ -static const u8 pkex_init_x_p521[66] = { - 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23, - 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0, - 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76, - 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5, - 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38, - 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01, - 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e, - 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d, - 0x97, 0x76 -}; -static const u8 pkex_init_y_p521[66] = { - 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59, - 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99, - 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b, - 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd, - 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f, - 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf, - 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02, - 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d, - 0x03, 0xa8 -}; -static const u8 pkex_resp_x_p521[66] = { - 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a, - 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44, - 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f, - 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb, - 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48, - 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e, - 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a, - 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97, - 0x84, 0xb4 -}; -static const u8 pkex_resp_y_p521[66] = { - 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d, - 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20, - 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3, - 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84, - 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9, - 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2, - 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80, - 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53, - 0xce, 0xe1 -}; - -/* Brainpool P-256r1 */ -static const u8 pkex_init_x_bp_p256r1[32] = { - 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10, - 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca, - 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75, - 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8 -}; -static const u8 pkex_init_y_bp_p256r1[32] = { - 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd, - 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30, - 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe, - 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b -}; -static const u8 pkex_resp_x_bp_p256r1[32] = { - 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f, - 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a, - 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a, - 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3 -}; -static const u8 pkex_resp_y_bp_p256r1[32] = { - 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd, - 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2, - 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e, - 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64 -}; - -/* Brainpool P-384r1 */ -static const u8 pkex_init_x_bp_p384r1[48] = { - 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd, - 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19, - 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06, - 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62, - 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30, - 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe -}; -static const u8 pkex_init_y_bp_p384r1[48] = { - 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99, - 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86, - 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32, - 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9, - 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e, - 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52 -}; -static const u8 pkex_resp_x_bp_p384r1[48] = { - 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0, - 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25, - 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b, - 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71, - 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce, - 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c -}; -static const u8 pkex_resp_y_bp_p384r1[48] = { - 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65, - 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04, - 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70, - 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c, - 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb, - 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1 -}; - -/* Brainpool P-512r1 */ -static const u8 pkex_init_x_bp_p512r1[64] = { - 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c, - 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51, - 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc, - 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95, - 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d, - 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff, - 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc, - 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f -}; -static const u8 pkex_init_y_bp_p512r1[64] = { - 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94, - 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8, - 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3, - 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45, - 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e, - 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58, - 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71, - 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99 -}; -static const u8 pkex_resp_x_bp_p512r1[64] = { - 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72, - 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76, - 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19, - 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e, - 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9, - 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88, - 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29, - 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e -}; -static const u8 pkex_resp_y_bp_p512r1[64] = { - 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81, - 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68, - 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa, - 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d, - 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c, - 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09, - 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56, - 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7 -}; - - -static void dpp_debug_print_point(const char *title, const EC_GROUP *group, - const EC_POINT *point) -{ - BIGNUM *x, *y; - BN_CTX *ctx; - char *x_str = NULL, *y_str = NULL; - - if (!wpa_debug_show_keys) - return; - - ctx = BN_CTX_new(); - x = BN_new(); - y = BN_new(); - if (!ctx || !x || !y || - EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1) - goto fail; - - x_str = BN_bn2hex(x); - y_str = BN_bn2hex(y); - if (!x_str || !y_str) - goto fail; - - wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str); - -fail: - OPENSSL_free(x_str); - OPENSSL_free(y_str); - BN_free(x); - BN_free(y); - BN_CTX_free(ctx); -} - - -static int dpp_hash_vector(const struct dpp_curve_params *curve, - size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - if (curve->hash_len == 32) - return sha256_vector(num_elem, addr, len, mac); - if (curve->hash_len == 48) - return sha384_vector(num_elem, addr, len, mac); - if (curve->hash_len == 64) - return sha512_vector(num_elem, addr, len, mac); - return -1; -} - - -static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, - const char *label, u8 *out, size_t outlen) -{ - if (hash_len == 32) - return hmac_sha256_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); - if (hash_len == 48) - return hmac_sha384_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); - if (hash_len == 64) - return hmac_sha512_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); - return -1; -} - - -static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac) -{ - if (hash_len == 32) - return hmac_sha256_vector(key, key_len, num_elem, addr, len, - mac); - if (hash_len == 48) - return hmac_sha384_vector(key, key_len, num_elem, addr, len, - mac); - if (hash_len == 64) - return hmac_sha512_vector(key, key_len, num_elem, addr, len, - mac); - return -1; -} - - -static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, u8 *mac) -{ - if (hash_len == 32) - return hmac_sha256(key, key_len, data, data_len, mac); - if (hash_len == 48) - return hmac_sha384(key, key_len, data, data_len, mac); - if (hash_len == 64) - return hmac_sha512(key, key_len, data, data_len, mac); - return -1; -} - - -#ifdef CONFIG_DPP2 - -static int dpp_pbkdf2_f(size_t hash_len, - const u8 *password, size_t password_len, - const u8 *salt, size_t salt_len, - unsigned int iterations, unsigned int count, u8 *digest) -{ - unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN]; - unsigned int i; - size_t j; - u8 count_buf[4]; - const u8 *addr[2]; - size_t len[2]; - - addr[0] = salt; - len[0] = salt_len; - addr[1] = count_buf; - len[1] = 4; - - /* F(P, S, c, i) = U1 xor U2 xor ... Uc - * U1 = PRF(P, S || i) - * U2 = PRF(P, U1) - * Uc = PRF(P, Uc-1) - */ - - WPA_PUT_BE32(count_buf, count); - if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len, - tmp)) - return -1; - os_memcpy(digest, tmp, hash_len); - - for (i = 1; i < iterations; i++) { - if (dpp_hmac(hash_len, password, password_len, tmp, hash_len, - tmp2)) - return -1; - os_memcpy(tmp, tmp2, hash_len); - for (j = 0; j < hash_len; j++) - digest[j] ^= tmp2[j]; - } - - return 0; -} - - -static int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, - const u8 *salt, size_t salt_len, unsigned int iterations, - u8 *buf, size_t buflen) -{ - unsigned int count = 0; - unsigned char *pos = buf; - size_t left = buflen, plen; - unsigned char digest[DPP_MAX_HASH_LEN]; - - while (left > 0) { - count++; - if (dpp_pbkdf2_f(hash_len, password, password_len, - salt, salt_len, iterations, count, digest)) - return -1; - plen = left > hash_len ? hash_len : left; - os_memcpy(pos, digest, plen); - pos += plen; - left -= plen; - } - - return 0; -} - -#endif /* CONFIG_DPP2 */ - - -static int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len) -{ - int num_bytes, offset; - - num_bytes = BN_num_bytes(bn); - if ((size_t) num_bytes > len) - return -1; - offset = len - num_bytes; - os_memset(pos, 0, offset); - BN_bn2bin(bn, pos + offset); - return 0; -} - - -static struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix) -{ - int len, res; - EC_KEY *eckey; - struct wpabuf *buf; - unsigned char *pos; - - eckey = EVP_PKEY_get1_EC_KEY(pkey); - if (!eckey) - return NULL; - EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); - len = i2o_ECPublicKey(eckey, NULL); - if (len <= 0) { - wpa_printf(MSG_ERROR, - "DDP: Failed to determine public key encoding length"); - EC_KEY_free(eckey); - return NULL; - } - - buf = wpabuf_alloc(len); - if (!buf) { - EC_KEY_free(eckey); - return NULL; - } - - pos = wpabuf_put(buf, len); - res = i2o_ECPublicKey(eckey, &pos); - EC_KEY_free(eckey); - if (res != len) { - wpa_printf(MSG_ERROR, - "DDP: Failed to encode public key (res=%d/%d)", - res, len); - wpabuf_free(buf); - return NULL; - } - - if (!prefix) { - /* Remove 0x04 prefix to match DPP definition */ - pos = wpabuf_mhead(buf); - os_memmove(pos, pos + 1, len - 1); - buf->used--; - } - - return buf; -} - - -static EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, - const u8 *buf_x, const u8 *buf_y, - size_t len) -{ - EC_KEY *eckey = NULL; - BN_CTX *ctx; - EC_POINT *point = NULL; - BIGNUM *x = NULL, *y = NULL; - EVP_PKEY *pkey = NULL; - - ctx = BN_CTX_new(); - if (!ctx) { - wpa_printf(MSG_ERROR, "DPP: Out of memory"); - return NULL; - } - - point = EC_POINT_new(group); - x = BN_bin2bn(buf_x, len, NULL); - y = BN_bin2bn(buf_y, len, NULL); - if (!point || !x || !y) { - wpa_printf(MSG_ERROR, "DPP: Out of memory"); - goto fail; - } - - if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { - wpa_printf(MSG_ERROR, - "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (!EC_POINT_is_on_curve(group, point, ctx) || - EC_POINT_is_at_infinity(group, point)) { - wpa_printf(MSG_ERROR, "DPP: Invalid point"); - goto fail; - } - dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point); - - eckey = EC_KEY_new(); - if (!eckey || - EC_KEY_set_group(eckey, group) != 1 || - EC_KEY_set_public_key(eckey, point) != 1) { - wpa_printf(MSG_ERROR, - "DPP: Failed to set EC_KEY: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); - - pkey = EVP_PKEY_new(); - if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { - wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); - goto fail; - } - -out: - BN_free(x); - BN_free(y); - EC_KEY_free(eckey); - EC_POINT_free(point); - BN_CTX_free(ctx); - return pkey; -fail: - EVP_PKEY_free(pkey); - pkey = NULL; - goto out; -} - - -static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, - const u8 *buf, size_t len) -{ - const EC_KEY *eckey; - const EC_GROUP *group; - EVP_PKEY *pkey = NULL; - - if (len & 1) - return NULL; - - eckey = EVP_PKEY_get0_EC_KEY(group_key); - if (!eckey) { - wpa_printf(MSG_ERROR, - "DPP: Could not get EC_KEY from group_key"); - return NULL; - } - - group = EC_KEY_get0_group(eckey); - if (group) - pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2, - len / 2); - else - wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); - - return pkey; -} - - -static int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, - u8 *secret, size_t *secret_len) -{ - EVP_PKEY_CTX *ctx; - int ret = -1; - - ERR_clear_error(); - *secret_len = 0; - - ctx = EVP_PKEY_CTX_new(own, NULL); - if (!ctx) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - if (EVP_PKEY_derive_init(ctx) != 1) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) { - wpa_printf(MSG_ERROR, - "DPP: EVP_PKEY_derive_set_peet failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { - u8 buf[200]; - int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG; - - /* It looks like OpenSSL can return unexpectedly large buffer - * need for shared secret from EVP_PKEY_derive(NULL) in some - * cases. For example, group 19 has shown cases where secret_len - * is set to 72 even though the actual length ends up being - * updated to 32 when EVP_PKEY_derive() is called with a buffer - * for the value. Work around this by trying to fetch the value - * and continue if it is within supported range even when the - * initial buffer need is claimed to be larger. */ - wpa_printf(level, - "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", - (int) *secret_len); - if (*secret_len > 200) - goto fail; - if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { - wpa_printf(MSG_ERROR, - "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", - (int) *secret_len); - goto fail; - } - wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change", - buf, *secret_len); - os_memcpy(secret, buf, *secret_len); - forced_memzero(buf, sizeof(buf)); - goto done; - } - - if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - -done: - ret = 0; - -fail: - EVP_PKEY_CTX_free(ctx); - return ret; -} - static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) { @@ -1059,86 +402,12 @@ int dpp_parse_uri_version(struct dpp_bootstrap_info *bi, const char *version) } -static const struct dpp_curve_params * -dpp_get_curve_oid(const ASN1_OBJECT *poid) -{ - ASN1_OBJECT *oid; - int i; - - for (i = 0; dpp_curves[i].name; i++) { - oid = OBJ_txt2obj(dpp_curves[i].name, 0); - if (oid && OBJ_cmp(poid, oid) == 0) - return &dpp_curves[i]; - } - return NULL; -} - - -static const struct dpp_curve_params * dpp_get_curve_nid(int nid) -{ - int i, tmp; - - if (!nid) - return NULL; - for (i = 0; dpp_curves[i].name; i++) { - tmp = OBJ_txt2nid(dpp_curves[i].name); - if (tmp == nid) - return &dpp_curves[i]; - } - return NULL; -} - - -static int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, - const u8 *data, size_t data_len) -{ - const u8 *addr[2]; - size_t len[2]; - - addr[0] = data; - len[0] = data_len; - if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0) - return -1; - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", - bi->pubkey_hash, SHA256_MAC_LEN); - - addr[0] = (const u8 *) "chirp"; - len[0] = 5; - addr[1] = data; - len[1] = data_len; - if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0) - return -1; - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)", - bi->pubkey_hash_chirp, SHA256_MAC_LEN); - - return 0; -} - - static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) { - const char *end; u8 *data; size_t data_len; - EVP_PKEY *pkey; - const unsigned char *p; int res; - X509_PUBKEY *pub = NULL; - ASN1_OBJECT *ppkalg; - const unsigned char *pk; - int ppklen; - X509_ALGOR *pa; -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && \ - LIBRESSL_VERSION_NUMBER < 0x20800000L) - ASN1_OBJECT *pa_oid; -#else - const ASN1_OBJECT *pa_oid; -#endif - const void *pval; - int ptype; - const ASN1_OBJECT *poid; - char buf[100]; + const char *end; end = os_strchr(info, ';'); if (!end) @@ -1153,101 +422,9 @@ static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key", data, data_len); - if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - os_free(data); - return -1; - } - - /* DER encoded ASN.1 SubjectPublicKeyInfo - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - * - * subjectPublicKey = compressed format public key per ANSI X9.63 - * algorithm = ecPublicKey (1.2.840.10045.2.1) - * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., - * prime256v1 (1.2.840.10045.3.1.7) - */ - - p = data; - pkey = d2i_PUBKEY(NULL, &p, data_len); + res = dpp_get_subject_public_key(bi, data, data_len); os_free(data); - - if (!pkey) { - wpa_printf(MSG_DEBUG, - "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); - return -1; - } - - if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) { - wpa_printf(MSG_DEBUG, - "DPP: SubjectPublicKeyInfo does not describe an EC key"); - EVP_PKEY_free(pkey); - return -1; - } - - res = X509_PUBKEY_set(&pub, pkey); - if (res != 1) { - wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey"); - goto fail; - } - - res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub); - if (res != 1) { - wpa_printf(MSG_DEBUG, - "DPP: Could not extract SubjectPublicKeyInfo parameters"); - goto fail; - } - res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0); - if (res < 0 || (size_t) res >= sizeof(buf)) { - wpa_printf(MSG_DEBUG, - "DPP: Could not extract SubjectPublicKeyInfo algorithm"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf); - if (os_strcmp(buf, "id-ecPublicKey") != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported SubjectPublicKeyInfo algorithm"); - goto fail; - } - - X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa); - if (ptype != V_ASN1_OBJECT) { - wpa_printf(MSG_DEBUG, - "DPP: SubjectPublicKeyInfo parameters did not contain an OID"); - goto fail; - } - poid = pval; - res = OBJ_obj2txt(buf, sizeof(buf), poid, 0); - if (res < 0 || (size_t) res >= sizeof(buf)) { - wpa_printf(MSG_DEBUG, - "DPP: Could not extract SubjectPublicKeyInfo parameters OID"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf); - bi->curve = dpp_get_curve_oid(poid); - if (!bi->curve) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported SubjectPublicKeyInfo curve: %s", - buf); - goto fail; - } - - wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen); - - X509_PUBKEY_free(pub); - bi->pubkey = pkey; - return 0; -fail: - X509_PUBKEY_free(pub); - EVP_PKEY_free(pkey); - return -1; + return res; } @@ -1319,458 +496,6 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) } -static void dpp_debug_print_key(const char *title, EVP_PKEY *key) -{ - EC_KEY *eckey; - BIO *out; - size_t rlen; - char *txt; - int res; - unsigned char *der = NULL; - int der_len; - const EC_GROUP *group; - const EC_POINT *point; - - out = BIO_new(BIO_s_mem()); - if (!out) - return; - - EVP_PKEY_print_private(out, key, 0, NULL); - rlen = BIO_ctrl_pending(out); - txt = os_malloc(rlen + 1); - if (txt) { - res = BIO_read(out, txt, rlen); - if (res > 0) { - txt[res] = '\0'; - wpa_printf(MSG_DEBUG, "%s: %s", title, txt); - } - os_free(txt); - } - BIO_free(out); - - eckey = EVP_PKEY_get1_EC_KEY(key); - if (!eckey) - return; - - group = EC_KEY_get0_group(eckey); - point = EC_KEY_get0_public_key(eckey); - if (group && point) - dpp_debug_print_point(title, group, point); - - der_len = i2d_ECPrivateKey(eckey, &der); - if (der_len > 0) - wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len); - OPENSSL_free(der); - if (der_len <= 0) { - der = NULL; - der_len = i2d_EC_PUBKEY(eckey, &der); - if (der_len > 0) - wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len); - OPENSSL_free(der); - } - - EC_KEY_free(eckey); -} - - -static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve) -{ - EVP_PKEY_CTX *kctx = NULL; - EC_KEY *ec_params = NULL; - EVP_PKEY *params = NULL, *key = NULL; - int nid; - - wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); - - nid = OBJ_txt2nid(curve->name); - if (nid == NID_undef) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name); - return NULL; - } - - ec_params = EC_KEY_new_by_curve_name(nid); - if (!ec_params) { - wpa_printf(MSG_ERROR, - "DPP: Failed to generate EC_KEY parameters"); - goto fail; - } - EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); - params = EVP_PKEY_new(); - if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { - wpa_printf(MSG_ERROR, - "DPP: Failed to generate EVP_PKEY parameters"); - goto fail; - } - - kctx = EVP_PKEY_CTX_new(params, NULL); - if (!kctx || - EVP_PKEY_keygen_init(kctx) != 1 || - EVP_PKEY_keygen(kctx, &key) != 1) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key"); - key = NULL; - goto fail; - } - - if (wpa_debug_show_keys) - dpp_debug_print_key("Own generated key", key); - -fail: - EC_KEY_free(ec_params); - EVP_PKEY_free(params); - EVP_PKEY_CTX_free(kctx); - return key; -} - - -static const struct dpp_curve_params * -dpp_get_curve_name(const char *name) -{ - int i; - - for (i = 0; dpp_curves[i].name; i++) { - if (os_strcmp(name, dpp_curves[i].name) == 0 || - (dpp_curves[i].jwk_crv && - os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) - return &dpp_curves[i]; - } - return NULL; -} - - -static const struct dpp_curve_params * -dpp_get_curve_jwk_crv(const char *name) -{ - int i; - - for (i = 0; dpp_curves[i].name; i++) { - if (dpp_curves[i].jwk_crv && - os_strcmp(name, dpp_curves[i].jwk_crv) == 0) - return &dpp_curves[i]; - } - return NULL; -} - - -static EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve, - const u8 *privkey, size_t privkey_len) -{ - EVP_PKEY *pkey; - EC_KEY *eckey; - const EC_GROUP *group; - int nid; - - pkey = EVP_PKEY_new(); - if (!pkey) - return NULL; - eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len); - if (!eckey) { - wpa_printf(MSG_INFO, - "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - EVP_PKEY_free(pkey); - return NULL; - } - group = EC_KEY_get0_group(eckey); - if (!group) { - EC_KEY_free(eckey); - EVP_PKEY_free(pkey); - return NULL; - } - nid = EC_GROUP_get_curve_name(group); - *curve = dpp_get_curve_nid(nid); - if (!*curve) { - wpa_printf(MSG_INFO, - "DPP: Unsupported curve (nid=%d) in pre-assigned key", - nid); - EC_KEY_free(eckey); - EVP_PKEY_free(pkey); - return NULL; - } - - if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { - EC_KEY_free(eckey); - EVP_PKEY_free(pkey); - return NULL; - } - return pkey; -} - - -typedef struct { - /* AlgorithmIdentifier ecPublicKey with optional parameters present - * as an OID identifying the curve */ - X509_ALGOR *alg; - /* Compressed format public key per ANSI X9.63 */ - ASN1_BIT_STRING *pub_key; -} DPP_BOOTSTRAPPING_KEY; - -ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { - ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), - ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) -} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY); - -IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY); - - -static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) -{ - unsigned char *der = NULL; - int der_len; - const EC_KEY *eckey; - struct wpabuf *ret = NULL; - size_t len; - const EC_GROUP *group; - const EC_POINT *point; - BN_CTX *ctx; - DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; - int nid; - - ctx = BN_CTX_new(); - eckey = EVP_PKEY_get0_EC_KEY(key); - if (!ctx || !eckey) - goto fail; - - group = EC_KEY_get0_group(eckey); - point = EC_KEY_get0_public_key(eckey); - if (!group || !point) - goto fail; - dpp_debug_print_point("DPP: bootstrap public key", group, point); - nid = EC_GROUP_get_curve_name(group); - - bootstrap = DPP_BOOTSTRAPPING_KEY_new(); - if (!bootstrap || - X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), - V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1) - goto fail; - - len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, - NULL, 0, ctx); - if (len == 0) - goto fail; - - der = OPENSSL_malloc(len); - if (!der) - goto fail; - len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, - der, len, ctx); - - OPENSSL_free(bootstrap->pub_key->data); - bootstrap->pub_key->data = der; - der = NULL; - bootstrap->pub_key->length = len; - /* No unused bits */ - bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; - - der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der); - if (der_len <= 0) { - wpa_printf(MSG_ERROR, - "DDP: Failed to build DER encoded public key"); - goto fail; - } - - ret = wpabuf_alloc_copy(der, der_len); -fail: - DPP_BOOTSTRAPPING_KEY_free(bootstrap); - OPENSSL_free(der); - BN_CTX_free(ctx); - return ret; -} - - -static int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) -{ - struct wpabuf *der; - int res; - - der = dpp_bootstrap_key_der(bi->pubkey); - if (!der) - return -1; - wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", - der); - res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)); - if (res < 0) - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - wpabuf_free(der); - return res; -} - - -static int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, - const u8 *privkey, size_t privkey_len) -{ - char *base64 = NULL; - char *pos, *end; - size_t len; - struct wpabuf *der = NULL; - - if (!curve) { - bi->curve = &dpp_curves[0]; - } else { - bi->curve = dpp_get_curve_name(curve); - if (!bi->curve) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", - curve); - return -1; - } - } - if (privkey) - bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); - else - bi->pubkey = dpp_gen_keypair(bi->curve); - if (!bi->pubkey) - goto fail; - bi->own = 1; - - der = dpp_bootstrap_key_der(bi->pubkey); - if (!der) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", - der); - - if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - goto fail; - } - - base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); - wpabuf_free(der); - der = NULL; - if (!base64) - goto fail; - pos = base64; - end = pos + len; - for (;;) { - pos = os_strchr(pos, '\n'); - if (!pos) - break; - os_memmove(pos, pos + 1, end - pos); - } - os_free(bi->pk); - bi->pk = base64; - return 0; -fail: - os_free(base64); - wpabuf_free(der); - return -1; -} - - -static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, - unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "first intermediate key"; - int res; - - /* k1 = HKDF(<>, "first intermediate key", M.x) */ - - /* HKDF-Extract(<>, M.x) */ - os_memset(salt, 0, hash_len); - if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", - k1, hash_len); - return 0; -} - - -static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, - unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "second intermediate key"; - int res; - - /* k2 = HKDF(<>, "second intermediate key", N.x) */ - - /* HKDF-Extract(<>, N.x) */ - os_memset(salt, 0, hash_len); - res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); - if (res < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", - k2, hash_len); - return 0; -} - - -static int dpp_derive_bk_ke(struct dpp_authentication *auth) -{ - unsigned int hash_len = auth->curve->hash_len; - size_t nonce_len = auth->curve->nonce_len; - u8 nonces[2 * DPP_MAX_NONCE_LEN]; - const char *info_ke = "DPP Key"; - int res; - const u8 *addr[3]; - size_t len[3]; - size_t num_elem = 0; - - if (!auth->Mx_len || !auth->Nx_len) { - wpa_printf(MSG_DEBUG, - "DPP: Mx/Nx not available - cannot derive ke"); - return -1; - } - - /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ - os_memcpy(nonces, auth->i_nonce, nonce_len); - os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); - addr[num_elem] = auth->Mx; - len[num_elem] = auth->Mx_len; - num_elem++; - addr[num_elem] = auth->Nx; - len[num_elem] = auth->Nx_len; - num_elem++; - if (auth->peer_bi && auth->own_bi) { - if (!auth->Lx_len) { - wpa_printf(MSG_DEBUG, - "DPP: Lx not available - cannot derive ke"); - return -1; - } - addr[num_elem] = auth->Lx; - len[num_elem] = auth->secret_len; - num_elem++; - } - res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, - num_elem, addr, len, auth->bk); - if (res < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, - "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])", - auth->bk, hash_len); - - /* ke = HKDF-Expand(bkK, "DPP Key", length) */ - res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke, - hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, - "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)", - auth->ke, hash_len); - - return 0; -} - - static void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status) { @@ -2785,290 +1510,6 @@ static void dpp_auth_success(struct dpp_authentication *auth) } -static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) -{ - struct wpabuf *pix, *prx, *bix, *brx; - const u8 *addr[7]; - size_t len[7]; - size_t i, num_elem = 0; - size_t nonce_len; - u8 zero = 0; - int res = -1; - - /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ - nonce_len = auth->curve->nonce_len; - - if (auth->initiator) { - pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - if (auth->own_bi) - bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - else - bix = NULL; - brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - } else { - pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (auth->peer_bi) - bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - else - bix = NULL; - brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - } - if (!pix || !prx || !brx) - goto fail; - - addr[num_elem] = auth->i_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = auth->r_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = wpabuf_head(pix); - len[num_elem] = wpabuf_len(pix) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(prx); - len[num_elem] = wpabuf_len(prx) / 2; - num_elem++; - - if (bix) { - addr[num_elem] = wpabuf_head(bix); - len[num_elem] = wpabuf_len(bix) / 2; - num_elem++; - } - - addr[num_elem] = wpabuf_head(brx); - len[num_elem] = wpabuf_len(brx) / 2; - num_elem++; - - addr[num_elem] = &zero; - len[num_elem] = 1; - num_elem++; - - wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); - for (i = 0; i < num_elem; i++) - wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); - res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); - if (res == 0) - wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, - auth->curve->hash_len); -fail: - wpabuf_free(pix); - wpabuf_free(prx); - wpabuf_free(bix); - wpabuf_free(brx); - return res; -} - - -static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) -{ - struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; - const u8 *addr[7]; - size_t len[7]; - size_t i, num_elem = 0; - size_t nonce_len; - u8 one = 1; - int res = -1; - - /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ - nonce_len = auth->curve->nonce_len; - - if (auth->initiator) { - pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - if (auth->own_bi) - bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - else - bix = NULL; - if (!auth->peer_bi) - goto fail; - brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - } else { - pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (auth->peer_bi) - bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - else - bix = NULL; - if (!auth->own_bi) - goto fail; - brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - } - if (!pix || !prx || !brx) - goto fail; - - addr[num_elem] = auth->r_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = auth->i_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = wpabuf_head(prx); - len[num_elem] = wpabuf_len(prx) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(pix); - len[num_elem] = wpabuf_len(pix) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(brx); - len[num_elem] = wpabuf_len(brx) / 2; - num_elem++; - - if (bix) { - addr[num_elem] = wpabuf_head(bix); - len[num_elem] = wpabuf_len(bix) / 2; - num_elem++; - } - - addr[num_elem] = &one; - len[num_elem] = 1; - num_elem++; - - wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); - for (i = 0; i < num_elem; i++) - wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); - res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); - if (res == 0) - wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, - auth->curve->hash_len); -fail: - wpabuf_free(pix); - wpabuf_free(prx); - wpabuf_free(bix); - wpabuf_free(brx); - return res; -} - - -static int dpp_auth_derive_l_responder(struct dpp_authentication *auth) -{ - const EC_GROUP *group; - EC_POINT *l = NULL; - const EC_KEY *BI, *bR, *pR; - const EC_POINT *BI_point; - BN_CTX *bnctx; - BIGNUM *lx, *sum, *q; - const BIGNUM *bR_bn, *pR_bn; - int ret = -1; - - /* L = ((bR + pR) modulo q) * BI */ - - bnctx = BN_CTX_new(); - sum = BN_new(); - q = BN_new(); - lx = BN_new(); - if (!bnctx || !sum || !q || !lx) - goto fail; - BI = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); - if (!BI) - goto fail; - BI_point = EC_KEY_get0_public_key(BI); - group = EC_KEY_get0_group(BI); - if (!group) - goto fail; - - bR = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); - pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); - if (!bR || !pR) - goto fail; - bR_bn = EC_KEY_get0_private_key(bR); - pR_bn = EC_KEY_get0_private_key(pR); - if (!bR_bn || !pR_bn) - goto fail; - if (EC_GROUP_get_order(group, q, bnctx) != 1 || - BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1) - goto fail; - l = EC_POINT_new(group); - if (!l || - EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, - bnctx) != 1) { - wpa_printf(MSG_ERROR, - "OpenSSL: failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); - auth->Lx_len = auth->secret_len; - ret = 0; -fail: - EC_POINT_clear_free(l); - BN_clear_free(lx); - BN_clear_free(sum); - BN_free(q); - BN_CTX_free(bnctx); - return ret; -} - - -static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) -{ - const EC_GROUP *group; - EC_POINT *l = NULL, *sum = NULL; - const EC_KEY *bI, *BR, *PR; - const EC_POINT *BR_point, *PR_point; - BN_CTX *bnctx; - BIGNUM *lx; - const BIGNUM *bI_bn; - int ret = -1; - - /* L = bI * (BR + PR) */ - - bnctx = BN_CTX_new(); - lx = BN_new(); - if (!bnctx || !lx) - goto fail; - BR = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); - PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); - if (!BR || !PR) - goto fail; - BR_point = EC_KEY_get0_public_key(BR); - PR_point = EC_KEY_get0_public_key(PR); - - bI = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); - if (!bI) - goto fail; - group = EC_KEY_get0_group(bI); - bI_bn = EC_KEY_get0_private_key(bI); - if (!group || !bI_bn) - goto fail; - sum = EC_POINT_new(group); - l = EC_POINT_new(group); - if (!sum || !l || - EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 || - EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, - bnctx) != 1) { - wpa_printf(MSG_ERROR, - "OpenSSL: failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); - auth->Lx_len = auth->secret_len; - ret = 0; -fail: - EC_POINT_clear_free(l); - EC_POINT_clear_free(sum); - BN_clear_free(lx); - BN_CTX_free(bnctx); - return ret; -} - - static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) { size_t nonce_len; @@ -4967,152 +3408,6 @@ static const char * dpp_netrole_str(enum dpp_netrole netrole) } -static char * -dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) -{ - struct wpabuf *jws_prot_hdr; - char *signed1; - - jws_prot_hdr = wpabuf_alloc(100); - if (!jws_prot_hdr) - return NULL; - json_start_object(jws_prot_hdr, NULL); - json_add_string(jws_prot_hdr, "typ", "dppCon"); - json_value_sep(jws_prot_hdr); - json_add_string(jws_prot_hdr, "kid", conf->kid); - json_value_sep(jws_prot_hdr); - json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg); - json_end_object(jws_prot_hdr); - signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), - wpabuf_len(jws_prot_hdr), - signed1_len); - wpabuf_free(jws_prot_hdr); - return signed1; -} - - -static char * -dpp_build_conn_signature(struct dpp_configurator *conf, - const char *signed1, size_t signed1_len, - const char *signed2, size_t signed2_len, - size_t *signed3_len) -{ - const struct dpp_curve_params *curve; - char *signed3 = NULL; - unsigned char *signature = NULL; - const unsigned char *p; - size_t signature_len; - EVP_MD_CTX *md_ctx = NULL; - ECDSA_SIG *sig = NULL; - char *dot = "."; - const EVP_MD *sign_md; - const BIGNUM *r, *s; - - curve = conf->curve; - if (curve->hash_len == SHA256_MAC_LEN) { - sign_md = EVP_sha256(); - } else if (curve->hash_len == SHA384_MAC_LEN) { - sign_md = EVP_sha384(); - } else if (curve->hash_len == SHA512_MAC_LEN) { - sign_md = EVP_sha512(); - } else { - wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); - goto fail; - } - - md_ctx = EVP_MD_CTX_create(); - if (!md_ctx) - goto fail; - - ERR_clear_error(); - if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, conf->csign) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 || - EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 || - EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - signature = os_malloc(signature_len); - if (!signature) - goto fail; - if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)", - signature, signature_len); - /* Convert to raw coordinates r,s */ - p = signature; - sig = d2i_ECDSA_SIG(NULL, &p, signature_len); - if (!sig) - goto fail; - ECDSA_SIG_get0(sig, &r, &s); - if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 || - dpp_bn2bin_pad(s, signature + curve->prime_len, - curve->prime_len) < 0) - goto fail; - signature_len = 2 * curve->prime_len; - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", - signature, signature_len); - signed3 = base64_url_encode(signature, signature_len, signed3_len); -fail: - EVP_MD_CTX_destroy(md_ctx); - ECDSA_SIG_free(sig); - os_free(signature); - return signed3; -} - -static char * -dpp_sign_connector(struct dpp_configurator *conf, const struct wpabuf *dppcon) -{ - char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; - char *signed_conn = NULL, *pos; - size_t signed1_len, signed2_len, signed3_len; - - signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len); - signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), - &signed2_len); - if (!signed1 || !signed2) - goto fail; - - signed3 = dpp_build_conn_signature(conf, signed1, signed1_len, - signed2, signed2_len, &signed3_len); - if (!signed3) - goto fail; - - signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3); - if (!signed_conn) - goto fail; - pos = signed_conn; - os_memcpy(pos, signed1, signed1_len); - pos += signed1_len; - *pos++ = '.'; - os_memcpy(pos, signed2, signed2_len); - pos += signed2_len; - *pos++ = '.'; - os_memcpy(pos, signed3, signed3_len); - pos += signed3_len; - *pos = '\0'; - -fail: - os_free(signed1); - os_free(signed2); - os_free(signed3); - return signed_conn; -} - - static struct wpabuf * dpp_build_conf_obj_dpp(struct dpp_authentication *auth, struct dpp_configuration *conf) @@ -6151,86 +4446,6 @@ fail: } -static struct wpabuf * -dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, - const u8 *prot_hdr, u16 prot_hdr_len, - const EVP_MD **ret_md) -{ - struct json_token *root, *token; - struct wpabuf *kid = NULL; - - root = json_parse((const char *) prot_hdr, prot_hdr_len); - if (!root) { - wpa_printf(MSG_DEBUG, - "DPP: JSON parsing failed for JWS Protected Header"); - goto fail; - } - - if (root->type != JSON_OBJECT) { - wpa_printf(MSG_DEBUG, - "DPP: JWS Protected Header root is not an object"); - goto fail; - } - - token = json_get_member(root, "typ"); - if (!token || token->type != JSON_STRING) { - wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", - token->string); - if (os_strcmp(token->string, "dppCon") != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported JWS Protected Header typ=%s", - token->string); - goto fail; - } - - token = json_get_member(root, "alg"); - if (!token || token->type != JSON_STRING) { - wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", - token->string); - if (os_strcmp(token->string, curve->jws_alg) != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", - token->string, curve->jws_alg); - goto fail; - } - if (os_strcmp(token->string, "ES256") == 0 || - os_strcmp(token->string, "BS256") == 0) - *ret_md = EVP_sha256(); - else if (os_strcmp(token->string, "ES384") == 0 || - os_strcmp(token->string, "BS384") == 0) - *ret_md = EVP_sha384(); - else if (os_strcmp(token->string, "ES512") == 0 || - os_strcmp(token->string, "BS512") == 0) - *ret_md = EVP_sha512(); - else - *ret_md = NULL; - if (!*ret_md) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported JWS Protected Header alg=%s", - token->string); - goto fail; - } - - kid = json_get_member_base64url(root, "kid"); - if (!kid) { - wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); - goto fail; - } - wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", - kid); - -fail: - json_free(root); - return kid; -} - - static int dpp_parse_cred_legacy(struct dpp_config_obj *conf, struct json_token *cred) { @@ -6533,38 +4748,6 @@ fail: } -static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash) -{ - struct wpabuf *uncomp; - int res; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[1]; - size_t len[1]; - - if (wpabuf_len(r_hash) != SHA256_MAC_LEN) - return -1; - uncomp = dpp_get_pubkey_point(pub, 1); - if (!uncomp) - return -1; - addr[0] = wpabuf_head(uncomp); - len[0] = wpabuf_len(uncomp); - wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", - addr[0], len[0]); - res = sha256_vector(1, addr, len, hash); - wpabuf_free(uncomp); - if (res < 0) - return -1; - if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Received hash value does not match calculated public key hash value"); - wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", - hash, SHA256_MAC_LEN); - return -1; - } - return 0; -} - - static void dpp_copy_csign(struct dpp_config_obj *conf, EVP_PKEY *csign) { unsigned char *der = NULL; @@ -6602,173 +4785,6 @@ static void dpp_copy_netaccesskey(struct dpp_authentication *auth, } -struct dpp_signed_connector_info { - unsigned char *payload; - size_t payload_len; -}; - -static enum dpp_status_error -dpp_process_signed_connector(struct dpp_signed_connector_info *info, - EVP_PKEY *csign_pub, const char *connector) -{ - enum dpp_status_error ret = 255; - const char *pos, *end, *signed_start, *signed_end; - struct wpabuf *kid = NULL; - unsigned char *prot_hdr = NULL, *signature = NULL; - size_t prot_hdr_len = 0, signature_len = 0; - const EVP_MD *sign_md = NULL; - unsigned char *der = NULL; - int der_len; - int res; - EVP_MD_CTX *md_ctx = NULL; - ECDSA_SIG *sig = NULL; - BIGNUM *r = NULL, *s = NULL; - const struct dpp_curve_params *curve; - const EC_KEY *eckey; - const EC_GROUP *group; - int nid; - - eckey = EVP_PKEY_get0_EC_KEY(csign_pub); - if (!eckey) - goto fail; - group = EC_KEY_get0_group(eckey); - if (!group) - goto fail; - nid = EC_GROUP_get_curve_name(group); - curve = dpp_get_curve_nid(nid); - if (!curve) - goto fail; - wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); - os_memset(info, 0, sizeof(*info)); - - signed_start = pos = connector; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); - if (!prot_hdr) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector JWS Protected Header"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump_ascii(MSG_DEBUG, - "DPP: signedConnector - JWS Protected Header", - prot_hdr, prot_hdr_len); - kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md); - if (!kid) { - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - if (wpabuf_len(kid) != SHA256_MAC_LEN) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", - (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - - pos = end + 1; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, - "DPP: Missing dot(2) in signedConnector"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - signed_end = end - 1; - info->payload = base64_url_decode(pos, end - pos, &info->payload_len); - if (!info->payload) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector JWS Payload"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump_ascii(MSG_DEBUG, - "DPP: signedConnector - JWS Payload", - info->payload, info->payload_len); - pos = end + 1; - signature = base64_url_decode(pos, os_strlen(pos), &signature_len); - if (!signature) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector signature"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", - signature, signature_len); - - if (dpp_check_pubkey_match(csign_pub, kid) < 0) { - ret = DPP_STATUS_NO_MATCH; - goto fail; - } - - if (signature_len & 0x01) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected signedConnector signature length (%d)", - (int) signature_len); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - - /* JWS Signature encodes the signature (r,s) as two octet strings. Need - * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ - r = BN_bin2bn(signature, signature_len / 2, NULL); - s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL); - sig = ECDSA_SIG_new(); - if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1) - goto fail; - r = NULL; - s = NULL; - - der_len = i2d_ECDSA_SIG(sig, &der); - if (der_len <= 0) { - wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len); - md_ctx = EVP_MD_CTX_create(); - if (!md_ctx) - goto fail; - - ERR_clear_error(); - if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestVerifyUpdate(md_ctx, signed_start, - signed_end - signed_start + 1) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - res = EVP_DigestVerifyFinal(md_ctx, der, der_len); - if (res != 1) { - wpa_printf(MSG_DEBUG, - "DPP: EVP_DigestVerifyFinal failed (res=%d): %s", - res, ERR_error_string(ERR_get_error(), NULL)); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - - ret = DPP_STATUS_OK; -fail: - EVP_MD_CTX_destroy(md_ctx); - os_free(prot_hdr); - wpabuf_free(kid); - os_free(signature); - ECDSA_SIG_free(sig); - BN_free(r); - BN_free(s); - OPENSSL_free(der); - return ret; -} - - static int dpp_parse_cred_dpp(struct dpp_authentication *auth, struct dpp_config_obj *conf, struct json_token *cred) @@ -8323,17 +6339,13 @@ dpp_keygen_configurator(const char *curve, const u8 *privkey, if (!conf) return NULL; - if (!curve) { - conf->curve = &dpp_curves[0]; - } else { - conf->curve = dpp_get_curve_name(curve); - if (!conf->curve) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", - curve); - os_free(conf); - return NULL; - } + conf->curve = dpp_get_curve_name(curve); + if (!conf->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); + os_free(conf); + return NULL; } + if (privkey) conf->csign = dpp_set_keypair(&conf->curve, privkey, privkey_len); @@ -8363,16 +6375,12 @@ int dpp_configurator_own_config(struct dpp_authentication *auth, return -1; } - if (!curve) { - auth->curve = &dpp_curves[0]; - } else { - auth->curve = dpp_get_curve_name(curve); - if (!auth->curve) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", - curve); - return -1; - } + auth->curve = dpp_get_curve_name(curve); + if (!auth->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); + return -1; } + wpa_printf(MSG_DEBUG, "DPP: Building own configuration/connector with curve %s", auth->curve->name); @@ -8482,74 +6490,6 @@ static int dpp_connector_match_groups(struct json_token *own_root, } -static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, - unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "DPP PMK"; - int res; - - /* PMK = HKDF(<>, "DPP PMK", N.x) */ - - /* HKDF-Extract(<>, N.x) */ - os_memset(salt, 0, hash_len); - if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", - pmk, hash_len); - return 0; -} - - -static int dpp_derive_pmkid(const struct dpp_curve_params *curve, - EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid) -{ - struct wpabuf *nkx, *pkx; - int ret = -1, res; - const u8 *addr[2]; - size_t len[2]; - u8 hash[SHA256_MAC_LEN]; - - /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ - nkx = dpp_get_pubkey_point(own_key, 0); - pkx = dpp_get_pubkey_point(peer_key, 0); - if (!nkx || !pkx) - goto fail; - addr[0] = wpabuf_head(nkx); - len[0] = wpabuf_len(nkx) / 2; - addr[1] = wpabuf_head(pkx); - len[1] = wpabuf_len(pkx) / 2; - if (len[0] != len[1]) - goto fail; - if (os_memcmp(addr[0], addr[1], len[0]) > 0) { - addr[0] = wpabuf_head(pkx); - addr[1] = wpabuf_head(nkx); - } - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); - res = sha256_vector(2, addr, len, hash); - if (res < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); - os_memcpy(pmkid, hash, PMKID_LEN); - wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); - ret = 0; -fail: - wpabuf_free(nkx); - wpabuf_free(pkx); - return ret; -} - - enum dpp_status_error dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, const u8 *net_access_key, size_t net_access_key_len, @@ -8719,285 +6659,6 @@ fail: } -static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, - int init) -{ - EC_GROUP *group; - size_t len = curve->prime_len; - const u8 *x, *y; - EVP_PKEY *res; - - switch (curve->ike_group) { - case 19: - x = init ? pkex_init_x_p256 : pkex_resp_x_p256; - y = init ? pkex_init_y_p256 : pkex_resp_y_p256; - break; - case 20: - x = init ? pkex_init_x_p384 : pkex_resp_x_p384; - y = init ? pkex_init_y_p384 : pkex_resp_y_p384; - break; - case 21: - x = init ? pkex_init_x_p521 : pkex_resp_x_p521; - y = init ? pkex_init_y_p521 : pkex_resp_y_p521; - break; - case 28: - x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1; - y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1; - break; - case 29: - x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1; - y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1; - break; - case 30: - x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1; - y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1; - break; - default: - return NULL; - } - - group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); - if (!group) - return NULL; - res = dpp_set_pubkey_point_group(group, x, y, len); - EC_GROUP_free(group); - return res; -} - - -static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, - const u8 *mac_init, const char *code, - const char *identifier, BN_CTX *bnctx, - EC_GROUP **ret_group) -{ - u8 hash[DPP_MAX_HASH_LEN]; - const u8 *addr[3]; - size_t len[3]; - unsigned int num_elem = 0; - EC_POINT *Qi = NULL; - EVP_PKEY *Pi = NULL; - const EC_KEY *Pi_ec; - const EC_POINT *Pi_point; - BIGNUM *hash_bn = NULL; - const EC_GROUP *group = NULL; - EC_GROUP *group2 = NULL; - - /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ - - wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init)); - addr[num_elem] = mac_init; - len[num_elem] = ETH_ALEN; - num_elem++; - if (identifier) { - wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", - identifier); - addr[num_elem] = (const u8 *) identifier; - len[num_elem] = os_strlen(identifier); - num_elem++; - } - wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); - addr[num_elem] = (const u8 *) code; - len[num_elem] = os_strlen(code); - num_elem++; - if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, - "DPP: H(MAC-Initiator | [identifier |] code)", - hash, curve->hash_len); - Pi = dpp_pkex_get_role_elem(curve, 1); - if (!Pi) - goto fail; - dpp_debug_print_key("DPP: Pi", Pi); - Pi_ec = EVP_PKEY_get0_EC_KEY(Pi); - if (!Pi_ec) - goto fail; - Pi_point = EC_KEY_get0_public_key(Pi_ec); - - group = EC_KEY_get0_group(Pi_ec); - if (!group) - goto fail; - group2 = EC_GROUP_dup(group); - if (!group2) - goto fail; - Qi = EC_POINT_new(group2); - if (!Qi) { - EC_GROUP_free(group2); - goto fail; - } - hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); - if (!hash_bn || - EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1) - goto fail; - if (EC_POINT_is_at_infinity(group, Qi)) { - wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity"); - goto fail; - } - dpp_debug_print_point("DPP: Qi", group, Qi); -out: - EVP_PKEY_free(Pi); - BN_clear_free(hash_bn); - if (ret_group && Qi) - *ret_group = group2; - else - EC_GROUP_free(group2); - return Qi; -fail: - EC_POINT_free(Qi); - Qi = NULL; - goto out; -} - - -static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, - const u8 *mac_resp, const char *code, - const char *identifier, BN_CTX *bnctx, - EC_GROUP **ret_group) -{ - u8 hash[DPP_MAX_HASH_LEN]; - const u8 *addr[3]; - size_t len[3]; - unsigned int num_elem = 0; - EC_POINT *Qr = NULL; - EVP_PKEY *Pr = NULL; - const EC_KEY *Pr_ec; - const EC_POINT *Pr_point; - BIGNUM *hash_bn = NULL; - const EC_GROUP *group = NULL; - EC_GROUP *group2 = NULL; - - /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ - - wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp)); - addr[num_elem] = mac_resp; - len[num_elem] = ETH_ALEN; - num_elem++; - if (identifier) { - wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", - identifier); - addr[num_elem] = (const u8 *) identifier; - len[num_elem] = os_strlen(identifier); - num_elem++; - } - wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); - addr[num_elem] = (const u8 *) code; - len[num_elem] = os_strlen(code); - num_elem++; - if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, - "DPP: H(MAC-Responder | [identifier |] code)", - hash, curve->hash_len); - Pr = dpp_pkex_get_role_elem(curve, 0); - if (!Pr) - goto fail; - dpp_debug_print_key("DPP: Pr", Pr); - Pr_ec = EVP_PKEY_get0_EC_KEY(Pr); - if (!Pr_ec) - goto fail; - Pr_point = EC_KEY_get0_public_key(Pr_ec); - - group = EC_KEY_get0_group(Pr_ec); - if (!group) - goto fail; - group2 = EC_GROUP_dup(group); - if (!group2) - goto fail; - Qr = EC_POINT_new(group2); - if (!Qr) { - EC_GROUP_free(group2); - goto fail; - } - hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); - if (!hash_bn || - EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1) - goto fail; - if (EC_POINT_is_at_infinity(group, Qr)) { - wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity"); - goto fail; - } - dpp_debug_print_point("DPP: Qr", group, Qr); -out: - EVP_PKEY_free(Pr); - BN_clear_free(hash_bn); - if (ret_group && Qr) - *ret_group = group2; - else - EC_GROUP_free(group2); - return Qr; -fail: - EC_POINT_free(Qr); - Qr = NULL; - goto out; -} - - -#ifdef CONFIG_TESTING_OPTIONS -static int dpp_test_gen_invalid_key(struct wpabuf *msg, - const struct dpp_curve_params *curve) -{ - BN_CTX *ctx; - BIGNUM *x, *y; - int ret = -1; - EC_GROUP *group; - EC_POINT *point; - - group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); - if (!group) - return -1; - - ctx = BN_CTX_new(); - point = EC_POINT_new(group); - x = BN_new(); - y = BN_new(); - if (!ctx || !point || !x || !y) - goto fail; - - if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1) - goto fail; - - /* Generate a random y coordinate that results in a point that is not - * on the curve. */ - for (;;) { - if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1) - goto fail; - - if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y, - ctx) != 1) { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL) - /* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL - * return an error from EC_POINT_set_affine_coordinates_GFp() - * when the point is not on the curve. */ - break; -#else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */ - goto fail; -#endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */ - } - - if (!EC_POINT_is_on_curve(group, point, ctx)) - break; - } - - if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0 || - dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0) - goto fail; - - ret = 0; -fail: - if (ret < 0) - wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key"); - BN_free(x); - BN_free(y); - EC_POINT_free(point); - BN_CTX_free(ctx); - EC_GROUP_free(group); - - return ret; -} -#endif /* CONFIG_TESTING_OPTIONS */ - - static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex) { const EC_KEY *X_ec; @@ -9269,65 +6930,6 @@ fail: } -static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, - const u8 *Mx, size_t Mx_len, - const u8 *Nx, size_t Nx_len, - const char *code, - const u8 *Kx, size_t Kx_len, - u8 *z, unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - int res; - u8 *info, *pos; - size_t info_len; - - /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) - */ - - /* HKDF-Extract(<>, IKM=K.x) */ - os_memset(salt, 0, hash_len); - if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", - prk, hash_len); - info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code); - info = os_malloc(info_len); - if (!info) - return -1; - pos = info; - os_memcpy(pos, mac_init, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, mac_resp, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, Mx, Mx_len); - pos += Mx_len; - os_memcpy(pos, Nx, Nx_len); - pos += Nx_len; - os_memcpy(pos, code, os_strlen(code)); - - /* HKDF-Expand(PRK, info, L) */ - if (hash_len == 32) - res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len, - z, hash_len); - else if (hash_len == 48) - res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len, - z, hash_len); - else if (hash_len == 64) - res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len, - z, hash_len); - else - res = -1; - os_free(info); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)", - z, hash_len); - return 0; -} - - static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len, const char *identifier) { @@ -10312,141 +7914,6 @@ void dpp_pkex_free(struct dpp_pkex *pkex) } -#ifdef CONFIG_TESTING_OPTIONS -char * dpp_corrupt_connector_signature(const char *connector) -{ - char *tmp, *pos, *signed3 = NULL; - unsigned char *signature = NULL; - size_t signature_len = 0, signed3_len; - - tmp = os_zalloc(os_strlen(connector) + 5); - if (!tmp) - goto fail; - os_memcpy(tmp, connector, os_strlen(connector)); - - pos = os_strchr(tmp, '.'); - if (!pos) - goto fail; - - pos = os_strchr(pos + 1, '.'); - if (!pos) - goto fail; - pos++; - - wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", - pos); - signature = base64_url_decode(pos, os_strlen(pos), &signature_len); - if (!signature || signature_len == 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", - signature, signature_len); - signature[signature_len - 1] ^= 0x01; - wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", - signature, signature_len); - signed3 = base64_url_encode(signature, signature_len, &signed3_len); - if (!signed3) - goto fail; - os_memcpy(pos, signed3, signed3_len); - pos[signed3_len] = '\0'; - wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", - pos); - -out: - os_free(signature); - os_free(signed3); - return tmp; -fail: - os_free(tmp); - tmp = NULL; - goto out; -} -#endif /* CONFIG_TESTING_OPTIONS */ - - -#ifdef CONFIG_DPP2 - -struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, - size_t net_access_key_len) -{ - struct wpabuf *pub = NULL; - EVP_PKEY *own_key; - struct dpp_pfs *pfs; - - pfs = os_zalloc(sizeof(*pfs)); - if (!pfs) - return NULL; - - own_key = dpp_set_keypair(&pfs->curve, net_access_key, - net_access_key_len); - if (!own_key) { - wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); - goto fail; - } - EVP_PKEY_free(own_key); - - pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group); - if (!pfs->ecdh) - goto fail; - - pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0); - pub = wpabuf_zeropad(pub, pfs->curve->prime_len); - if (!pub) - goto fail; - - pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub)); - if (!pfs->ie) - goto fail; - wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION); - wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub)); - wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM); - wpabuf_put_le16(pfs->ie, pfs->curve->ike_group); - wpabuf_put_buf(pfs->ie, pub); - wpabuf_free(pub); - wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element", - pfs->ie); - - return pfs; -fail: - wpabuf_free(pub); - dpp_pfs_free(pfs); - return NULL; -} - - -int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len) -{ - if (peer_ie_len < 2) - return -1; - if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) { - wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS"); - return -1; - } - - pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2, - peer_ie_len - 2); - pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len); - if (!pfs->secret) { - wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key"); - return -1; - } - wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret); - return 0; -} - - -void dpp_pfs_free(struct dpp_pfs *pfs) -{ - if (!pfs) - return; - crypto_ecdh_deinit(pfs->ecdh); - wpabuf_free(pfs->ie); - wpabuf_clear_free(pfs->secret); - os_free(pfs); -} - -#endif /* CONFIG_DPP2 */ - - static unsigned int dpp_next_id(struct dpp_global *dpp) { struct dpp_bootstrap_info *bi; diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c new file mode 100644 index 000000000..3d1109f02 --- /dev/null +++ b/src/common/dpp_crypto.c @@ -0,0 +1,2551 @@ +/* + * DPP crypto functionality + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include +#include +#include +#include + +#include "utils/common.h" +#include "utils/base64.h" +#include "utils/json.h" +#include "common/ieee802_11_defs.h" +#include "crypto/crypto.h" +#include "crypto/sha384.h" +#include "crypto/sha512.h" +#include "dpp.h" +#include "dpp_i.h" + + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +/* Compatibility wrappers for older versions. */ + +static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + sig->r = r; + sig->s = s; + return 1; +} + + +static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, + const BIGNUM **ps) +{ + if (pr) + *pr = sig->r; + if (ps) + *ps = sig->s; +} + + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + +#endif + +static const struct dpp_curve_params dpp_curves[] = { + /* The mandatory to support and the default NIST P-256 curve needs to + * be the first entry on this list. */ + { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" }, + { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, + { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, + { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, + { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, + { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, + { NULL, 0, 0, 0, 0, NULL, 0, NULL } +}; + + +const struct dpp_curve_params * dpp_get_curve_name(const char *name) +{ + int i; + + if (!name) + return &dpp_curves[0]; + + for (i = 0; dpp_curves[i].name; i++) { + if (os_strcmp(name, dpp_curves[i].name) == 0 || + (dpp_curves[i].jwk_crv && + os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) + return &dpp_curves[i]; + } + return NULL; +} + + +const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (dpp_curves[i].jwk_crv && + os_strcmp(name, dpp_curves[i].jwk_crv) == 0) + return &dpp_curves[i]; + } + return NULL; +} + + +const struct dpp_curve_params * dpp_get_curve_oid(const ASN1_OBJECT *poid) +{ + ASN1_OBJECT *oid; + int i; + + for (i = 0; dpp_curves[i].name; i++) { + oid = OBJ_txt2obj(dpp_curves[i].name, 0); + if (oid && OBJ_cmp(poid, oid) == 0) + return &dpp_curves[i]; + } + return NULL; +} + + +const struct dpp_curve_params * dpp_get_curve_nid(int nid) +{ + int i, tmp; + + if (!nid) + return NULL; + for (i = 0; dpp_curves[i].name; i++) { + tmp = OBJ_txt2nid(dpp_curves[i].name); + if (tmp == nid) + return &dpp_curves[i]; + } + return NULL; +} + + +void dpp_debug_print_point(const char *title, const EC_GROUP *group, + const EC_POINT *point) +{ + BIGNUM *x, *y; + BN_CTX *ctx; + char *x_str = NULL, *y_str = NULL; + + if (!wpa_debug_show_keys) + return; + + ctx = BN_CTX_new(); + x = BN_new(); + y = BN_new(); + if (!ctx || !x || !y || + EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1) + goto fail; + + x_str = BN_bn2hex(x); + y_str = BN_bn2hex(y); + if (!x_str || !y_str) + goto fail; + + wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str); + +fail: + OPENSSL_free(x_str); + OPENSSL_free(y_str); + BN_free(x); + BN_free(y); + BN_CTX_free(ctx); +} + + +void dpp_debug_print_key(const char *title, EVP_PKEY *key) +{ + EC_KEY *eckey; + BIO *out; + size_t rlen; + char *txt; + int res; + unsigned char *der = NULL; + int der_len; + const EC_GROUP *group; + const EC_POINT *point; + + out = BIO_new(BIO_s_mem()); + if (!out) + return; + + EVP_PKEY_print_private(out, key, 0, NULL); + rlen = BIO_ctrl_pending(out); + txt = os_malloc(rlen + 1); + if (txt) { + res = BIO_read(out, txt, rlen); + if (res > 0) { + txt[res] = '\0'; + wpa_printf(MSG_DEBUG, "%s: %s", title, txt); + } + os_free(txt); + } + BIO_free(out); + + eckey = EVP_PKEY_get1_EC_KEY(key); + if (!eckey) + return; + + group = EC_KEY_get0_group(eckey); + point = EC_KEY_get0_public_key(eckey); + if (group && point) + dpp_debug_print_point(title, group, point); + + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len > 0) + wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len); + OPENSSL_free(der); + if (der_len <= 0) { + der = NULL; + der_len = i2d_EC_PUBKEY(eckey, &der); + if (der_len > 0) + wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len); + OPENSSL_free(der); + } + + EC_KEY_free(eckey); +} + + +int dpp_hash_vector(const struct dpp_curve_params *curve, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + if (curve->hash_len == 32) + return sha256_vector(num_elem, addr, len, mac); + if (curve->hash_len == 48) + return sha384_vector(num_elem, addr, len, mac); + if (curve->hash_len == 64) + return sha512_vector(num_elem, addr, len, mac); + return -1; +} + + +int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, + const char *label, u8 *out, size_t outlen) +{ + if (hash_len == 32) + return hmac_sha256_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + if (hash_len == 48) + return hmac_sha384_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + if (hash_len == 64) + return hmac_sha512_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + return -1; +} + + +int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + if (hash_len == 32) + return hmac_sha256_vector(key, key_len, num_elem, addr, len, + mac); + if (hash_len == 48) + return hmac_sha384_vector(key, key_len, num_elem, addr, len, + mac); + if (hash_len == 64) + return hmac_sha512_vector(key, key_len, num_elem, addr, len, + mac); + return -1; +} + + +int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, + const u8 *data, size_t data_len, u8 *mac) +{ + if (hash_len == 32) + return hmac_sha256(key, key_len, data, data_len, mac); + if (hash_len == 48) + return hmac_sha384(key, key_len, data, data_len, mac); + if (hash_len == 64) + return hmac_sha512(key, key_len, data, data_len, mac); + return -1; +} + + +#ifdef CONFIG_DPP2 + +static int dpp_pbkdf2_f(size_t hash_len, + const u8 *password, size_t password_len, + const u8 *salt, size_t salt_len, + unsigned int iterations, unsigned int count, u8 *digest) +{ + unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN]; + unsigned int i; + size_t j; + u8 count_buf[4]; + const u8 *addr[2]; + size_t len[2]; + + addr[0] = salt; + len[0] = salt_len; + addr[1] = count_buf; + len[1] = 4; + + /* F(P, S, c, i) = U1 xor U2 xor ... Uc + * U1 = PRF(P, S || i) + * U2 = PRF(P, U1) + * Uc = PRF(P, Uc-1) + */ + + WPA_PUT_BE32(count_buf, count); + if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len, + tmp)) + return -1; + os_memcpy(digest, tmp, hash_len); + + for (i = 1; i < iterations; i++) { + if (dpp_hmac(hash_len, password, password_len, tmp, hash_len, + tmp2)) + return -1; + os_memcpy(tmp, tmp2, hash_len); + for (j = 0; j < hash_len; j++) + digest[j] ^= tmp2[j]; + } + + return 0; +} + + +int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, + const u8 *salt, size_t salt_len, unsigned int iterations, + u8 *buf, size_t buflen) +{ + unsigned int count = 0; + unsigned char *pos = buf; + size_t left = buflen, plen; + unsigned char digest[DPP_MAX_HASH_LEN]; + + while (left > 0) { + count++; + if (dpp_pbkdf2_f(hash_len, password, password_len, + salt, salt_len, iterations, count, digest)) + return -1; + plen = left > hash_len ? hash_len : left; + os_memcpy(pos, digest, plen); + pos += plen; + left -= plen; + } + + return 0; +} + +#endif /* CONFIG_DPP2 */ + + +int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len) +{ + int num_bytes, offset; + + num_bytes = BN_num_bytes(bn); + if ((size_t) num_bytes > len) + return -1; + offset = len - num_bytes; + os_memset(pos, 0, offset); + BN_bn2bin(bn, pos + offset); + return 0; +} + + +struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix) +{ + int len, res; + EC_KEY *eckey; + struct wpabuf *buf; + unsigned char *pos; + + eckey = EVP_PKEY_get1_EC_KEY(pkey); + if (!eckey) + return NULL; + EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); + len = i2o_ECPublicKey(eckey, NULL); + if (len <= 0) { + wpa_printf(MSG_ERROR, + "DDP: Failed to determine public key encoding length"); + EC_KEY_free(eckey); + return NULL; + } + + buf = wpabuf_alloc(len); + if (!buf) { + EC_KEY_free(eckey); + return NULL; + } + + pos = wpabuf_put(buf, len); + res = i2o_ECPublicKey(eckey, &pos); + EC_KEY_free(eckey); + if (res != len) { + wpa_printf(MSG_ERROR, + "DDP: Failed to encode public key (res=%d/%d)", + res, len); + wpabuf_free(buf); + return NULL; + } + + if (!prefix) { + /* Remove 0x04 prefix to match DPP definition */ + pos = wpabuf_mhead(buf); + os_memmove(pos, pos + 1, len - 1); + buf->used--; + } + + return buf; +} + + +EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, + const u8 *buf_x, const u8 *buf_y, + size_t len) +{ + EC_KEY *eckey = NULL; + BN_CTX *ctx; + EC_POINT *point = NULL; + BIGNUM *x = NULL, *y = NULL; + EVP_PKEY *pkey = NULL; + + ctx = BN_CTX_new(); + if (!ctx) { + wpa_printf(MSG_ERROR, "DPP: Out of memory"); + return NULL; + } + + point = EC_POINT_new(group); + x = BN_bin2bn(buf_x, len, NULL); + y = BN_bin2bn(buf_y, len, NULL); + if (!point || !x || !y) { + wpa_printf(MSG_ERROR, "DPP: Out of memory"); + goto fail; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { + wpa_printf(MSG_ERROR, + "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (!EC_POINT_is_on_curve(group, point, ctx) || + EC_POINT_is_at_infinity(group, point)) { + wpa_printf(MSG_ERROR, "DPP: Invalid point"); + goto fail; + } + dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point); + + eckey = EC_KEY_new(); + if (!eckey || + EC_KEY_set_group(eckey, group) != 1 || + EC_KEY_set_public_key(eckey, point) != 1) { + wpa_printf(MSG_ERROR, + "DPP: Failed to set EC_KEY: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { + wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); + goto fail; + } + +out: + BN_free(x); + BN_free(y); + EC_KEY_free(eckey); + EC_POINT_free(point); + BN_CTX_free(ctx); + return pkey; +fail: + EVP_PKEY_free(pkey); + pkey = NULL; + goto out; +} + + +EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len) +{ + const EC_KEY *eckey; + const EC_GROUP *group; + EVP_PKEY *pkey = NULL; + + if (len & 1) + return NULL; + + eckey = EVP_PKEY_get0_EC_KEY(group_key); + if (!eckey) { + wpa_printf(MSG_ERROR, + "DPP: Could not get EC_KEY from group_key"); + return NULL; + } + + group = EC_KEY_get0_group(eckey); + if (group) + pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2, + len / 2); + else + wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); + + return pkey; +} + + +EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve) +{ + EVP_PKEY_CTX *kctx = NULL; + EC_KEY *ec_params = NULL; + EVP_PKEY *params = NULL, *key = NULL; + int nid; + + wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); + + nid = OBJ_txt2nid(curve->name); + if (nid == NID_undef) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name); + return NULL; + } + + ec_params = EC_KEY_new_by_curve_name(nid); + if (!ec_params) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate EC_KEY parameters"); + goto fail; + } + EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); + params = EVP_PKEY_new(); + if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate EVP_PKEY parameters"); + goto fail; + } + + kctx = EVP_PKEY_CTX_new(params, NULL); + if (!kctx || + EVP_PKEY_keygen_init(kctx) != 1 || + EVP_PKEY_keygen(kctx, &key) != 1) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key"); + key = NULL; + goto fail; + } + + if (wpa_debug_show_keys) + dpp_debug_print_key("Own generated key", key); + +fail: + EC_KEY_free(ec_params); + EVP_PKEY_free(params); + EVP_PKEY_CTX_free(kctx); + return key; +} + + +EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len) +{ + EVP_PKEY *pkey; + EC_KEY *eckey; + const EC_GROUP *group; + int nid; + + pkey = EVP_PKEY_new(); + if (!pkey) + return NULL; + eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len); + if (!eckey) { + wpa_printf(MSG_INFO, + "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + EVP_PKEY_free(pkey); + return NULL; + } + group = EC_KEY_get0_group(eckey); + if (!group) { + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + nid = EC_GROUP_get_curve_name(group); + *curve = dpp_get_curve_nid(nid); + if (!*curve) { + wpa_printf(MSG_INFO, + "DPP: Unsupported curve (nid=%d) in pre-assigned key", + nid); + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + + if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + return pkey; +} + + +typedef struct { + /* AlgorithmIdentifier ecPublicKey with optional parameters present + * as an OID identifying the curve */ + X509_ALGOR *alg; + /* Compressed format public key per ANSI X9.63 */ + ASN1_BIT_STRING *pub_key; +} DPP_BOOTSTRAPPING_KEY; + +ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY); + +IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY); + + +static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) +{ + unsigned char *der = NULL; + int der_len; + const EC_KEY *eckey; + struct wpabuf *ret = NULL; + size_t len; + const EC_GROUP *group; + const EC_POINT *point; + BN_CTX *ctx; + DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; + int nid; + + ctx = BN_CTX_new(); + eckey = EVP_PKEY_get0_EC_KEY(key); + if (!ctx || !eckey) + goto fail; + + group = EC_KEY_get0_group(eckey); + point = EC_KEY_get0_public_key(eckey); + if (!group || !point) + goto fail; + dpp_debug_print_point("DPP: bootstrap public key", group, point); + nid = EC_GROUP_get_curve_name(group); + + bootstrap = DPP_BOOTSTRAPPING_KEY_new(); + if (!bootstrap || + X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), + V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1) + goto fail; + + len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + NULL, 0, ctx); + if (len == 0) + goto fail; + + der = OPENSSL_malloc(len); + if (!der) + goto fail; + len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + der, len, ctx); + + OPENSSL_free(bootstrap->pub_key->data); + bootstrap->pub_key->data = der; + der = NULL; + bootstrap->pub_key->length = len; + /* No unused bits */ + bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + + der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der); + if (der_len <= 0) { + wpa_printf(MSG_ERROR, + "DDP: Failed to build DER encoded public key"); + goto fail; + } + + ret = wpabuf_alloc_copy(der, der_len); +fail: + DPP_BOOTSTRAPPING_KEY_free(bootstrap); + OPENSSL_free(der); + BN_CTX_free(ctx); + return ret; +} + + +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) +{ + struct wpabuf *der; + int res; + + der = dpp_bootstrap_key_der(bi->pubkey); + if (!der) + return -1; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", + der); + res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)); + if (res < 0) + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + wpabuf_free(der); + return res; +} + + +int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + const u8 *privkey, size_t privkey_len) +{ + char *base64 = NULL; + char *pos, *end; + size_t len; + struct wpabuf *der = NULL; + + bi->curve = dpp_get_curve_name(curve); + if (!bi->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); + return -1; + } + + if (privkey) + bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); + else + bi->pubkey = dpp_gen_keypair(bi->curve); + if (!bi->pubkey) + goto fail; + bi->own = 1; + + der = dpp_bootstrap_key_der(bi->pubkey); + if (!der) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", + der); + + if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + goto fail; + } + + base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); + wpabuf_free(der); + der = NULL; + if (!base64) + goto fail; + pos = base64; + end = pos + len; + for (;;) { + pos = os_strchr(pos, '\n'); + if (!pos) + break; + os_memmove(pos, pos + 1, end - pos); + } + os_free(bi->pk); + bi->pk = base64; + return 0; +fail: + os_free(base64); + wpabuf_free(der); + return -1; +} + + +int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "first intermediate key"; + int res; + + /* k1 = HKDF(<>, "first intermediate key", M.x) */ + + /* HKDF-Extract(<>, M.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", + k1, hash_len); + return 0; +} + + +int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "second intermediate key"; + int res; + + /* k2 = HKDF(<>, "second intermediate key", N.x) */ + + /* HKDF-Extract(<>, N.x) */ + os_memset(salt, 0, hash_len); + res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", + k2, hash_len); + return 0; +} + + +int dpp_derive_bk_ke(struct dpp_authentication *auth) +{ + unsigned int hash_len = auth->curve->hash_len; + size_t nonce_len = auth->curve->nonce_len; + u8 nonces[2 * DPP_MAX_NONCE_LEN]; + const char *info_ke = "DPP Key"; + int res; + const u8 *addr[3]; + size_t len[3]; + size_t num_elem = 0; + + if (!auth->Mx_len || !auth->Nx_len) { + wpa_printf(MSG_DEBUG, + "DPP: Mx/Nx not available - cannot derive ke"); + return -1; + } + + /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ + os_memcpy(nonces, auth->i_nonce, nonce_len); + os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); + addr[num_elem] = auth->Mx; + len[num_elem] = auth->Mx_len; + num_elem++; + addr[num_elem] = auth->Nx; + len[num_elem] = auth->Nx_len; + num_elem++; + if (auth->peer_bi && auth->own_bi) { + if (!auth->Lx_len) { + wpa_printf(MSG_DEBUG, + "DPP: Lx not available - cannot derive ke"); + return -1; + } + addr[num_elem] = auth->Lx; + len[num_elem] = auth->secret_len; + num_elem++; + } + res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, + num_elem, addr, len, auth->bk); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, + "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])", + auth->bk, hash_len); + + /* ke = HKDF-Expand(bkK, "DPP Key", length) */ + res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke, + hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, + "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)", + auth->ke, hash_len); + + return 0; +} + + +int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len) +{ + EVP_PKEY_CTX *ctx; + int ret = -1; + + ERR_clear_error(); + *secret_len = 0; + + ctx = EVP_PKEY_CTX_new(own, NULL); + if (!ctx) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + + if (EVP_PKEY_derive_init(ctx) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) { + wpa_printf(MSG_ERROR, + "DPP: EVP_PKEY_derive_set_peet failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { + u8 buf[200]; + int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG; + + /* It looks like OpenSSL can return unexpectedly large buffer + * need for shared secret from EVP_PKEY_derive(NULL) in some + * cases. For example, group 19 has shown cases where secret_len + * is set to 72 even though the actual length ends up being + * updated to 32 when EVP_PKEY_derive() is called with a buffer + * for the value. Work around this by trying to fetch the value + * and continue if it is within supported range even when the + * initial buffer need is claimed to be larger. */ + wpa_printf(level, + "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", + (int) *secret_len); + if (*secret_len > 200) + goto fail; + if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { + wpa_printf(MSG_ERROR, + "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", + (int) *secret_len); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change", + buf, *secret_len); + os_memcpy(secret, buf, *secret_len); + forced_memzero(buf, sizeof(buf)); + goto done; + } + + if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + +done: + ret = 0; + +fail: + EVP_PKEY_CTX_free(ctx); + return ret; +} + + +int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len) +{ + const u8 *addr[2]; + size_t len[2]; + + addr[0] = data; + len[0] = data_len; + if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", + bi->pubkey_hash, SHA256_MAC_LEN); + + addr[0] = (const u8 *) "chirp"; + len[0] = 5; + addr[1] = data; + len[1] = data_len; + if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)", + bi->pubkey_hash_chirp, SHA256_MAC_LEN); + + return 0; +} + + +int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len) +{ + EVP_PKEY *pkey; + const unsigned char *p; + int res; + X509_PUBKEY *pub = NULL; + ASN1_OBJECT *ppkalg; + const unsigned char *pk; + int ppklen; + X509_ALGOR *pa; +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20800000L) + ASN1_OBJECT *pa_oid; +#else + const ASN1_OBJECT *pa_oid; +#endif + const void *pval; + int ptype; + const ASN1_OBJECT *poid; + char buf[100]; + + if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + return -1; + } + + /* DER encoded ASN.1 SubjectPublicKeyInfo + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * subjectPublicKey = compressed format public key per ANSI X9.63 + * algorithm = ecPublicKey (1.2.840.10045.2.1) + * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., + * prime256v1 (1.2.840.10045.3.1.7) + */ + + p = data; + pkey = d2i_PUBKEY(NULL, &p, data_len); + + if (!pkey) { + wpa_printf(MSG_DEBUG, + "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); + return -1; + } + + if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) { + wpa_printf(MSG_DEBUG, + "DPP: SubjectPublicKeyInfo does not describe an EC key"); + EVP_PKEY_free(pkey); + return -1; + } + + res = X509_PUBKEY_set(&pub, pkey); + if (res != 1) { + wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey"); + goto fail; + } + + res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub); + if (res != 1) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo parameters"); + goto fail; + } + res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0); + if (res < 0 || (size_t) res >= sizeof(buf)) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo algorithm"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf); + if (os_strcmp(buf, "id-ecPublicKey") != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported SubjectPublicKeyInfo algorithm"); + goto fail; + } + + X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa); + if (ptype != V_ASN1_OBJECT) { + wpa_printf(MSG_DEBUG, + "DPP: SubjectPublicKeyInfo parameters did not contain an OID"); + goto fail; + } + poid = pval; + res = OBJ_obj2txt(buf, sizeof(buf), poid, 0); + if (res < 0 || (size_t) res >= sizeof(buf)) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo parameters OID"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf); + bi->curve = dpp_get_curve_oid(poid); + if (!bi->curve) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported SubjectPublicKeyInfo curve: %s", + buf); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen); + + X509_PUBKEY_free(pub); + bi->pubkey = pkey; + return 0; +fail: + X509_PUBKEY_free(pub); + EVP_PKEY_free(pkey); + return -1; +} + + +static struct wpabuf * +dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, + const u8 *prot_hdr, u16 prot_hdr_len, + const EVP_MD **ret_md) +{ + struct json_token *root, *token; + struct wpabuf *kid = NULL; + + root = json_parse((const char *) prot_hdr, prot_hdr_len); + if (!root) { + wpa_printf(MSG_DEBUG, + "DPP: JSON parsing failed for JWS Protected Header"); + goto fail; + } + + if (root->type != JSON_OBJECT) { + wpa_printf(MSG_DEBUG, + "DPP: JWS Protected Header root is not an object"); + goto fail; + } + + token = json_get_member(root, "typ"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", + token->string); + if (os_strcmp(token->string, "dppCon") != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported JWS Protected Header typ=%s", + token->string); + goto fail; + } + + token = json_get_member(root, "alg"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", + token->string); + if (os_strcmp(token->string, curve->jws_alg) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", + token->string, curve->jws_alg); + goto fail; + } + if (os_strcmp(token->string, "ES256") == 0 || + os_strcmp(token->string, "BS256") == 0) + *ret_md = EVP_sha256(); + else if (os_strcmp(token->string, "ES384") == 0 || + os_strcmp(token->string, "BS384") == 0) + *ret_md = EVP_sha384(); + else if (os_strcmp(token->string, "ES512") == 0 || + os_strcmp(token->string, "BS512") == 0) + *ret_md = EVP_sha512(); + else + *ret_md = NULL; + if (!*ret_md) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported JWS Protected Header alg=%s", + token->string); + goto fail; + } + + kid = json_get_member_base64url(root, "kid"); + if (!kid) { + wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); + goto fail; + } + wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", + kid); + +fail: + json_free(root); + return kid; +} + + +static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash) +{ + struct wpabuf *uncomp; + int res; + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[1]; + size_t len[1]; + + if (wpabuf_len(r_hash) != SHA256_MAC_LEN) + return -1; + uncomp = dpp_get_pubkey_point(pub, 1); + if (!uncomp) + return -1; + addr[0] = wpabuf_head(uncomp); + len[0] = wpabuf_len(uncomp); + wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", + addr[0], len[0]); + res = sha256_vector(1, addr, len, hash); + wpabuf_free(uncomp); + if (res < 0) + return -1; + if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Received hash value does not match calculated public key hash value"); + wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", + hash, SHA256_MAC_LEN); + return -1; + } + return 0; +} + + +enum dpp_status_error +dpp_process_signed_connector(struct dpp_signed_connector_info *info, + EVP_PKEY *csign_pub, const char *connector) +{ + enum dpp_status_error ret = 255; + const char *pos, *end, *signed_start, *signed_end; + struct wpabuf *kid = NULL; + unsigned char *prot_hdr = NULL, *signature = NULL; + size_t prot_hdr_len = 0, signature_len = 0; + const EVP_MD *sign_md = NULL; + unsigned char *der = NULL; + int der_len; + int res; + EVP_MD_CTX *md_ctx = NULL; + ECDSA_SIG *sig = NULL; + BIGNUM *r = NULL, *s = NULL; + const struct dpp_curve_params *curve; + const EC_KEY *eckey; + const EC_GROUP *group; + int nid; + + eckey = EVP_PKEY_get0_EC_KEY(csign_pub); + if (!eckey) + goto fail; + group = EC_KEY_get0_group(eckey); + if (!group) + goto fail; + nid = EC_GROUP_get_curve_name(group); + curve = dpp_get_curve_nid(nid); + if (!curve) + goto fail; + wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); + os_memset(info, 0, sizeof(*info)); + + signed_start = pos = connector; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); + if (!prot_hdr) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector JWS Protected Header"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, + "DPP: signedConnector - JWS Protected Header", + prot_hdr, prot_hdr_len); + kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md); + if (!kid) { + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + if (wpabuf_len(kid) != SHA256_MAC_LEN) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", + (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + + pos = end + 1; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, + "DPP: Missing dot(2) in signedConnector"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + signed_end = end - 1; + info->payload = base64_url_decode(pos, end - pos, &info->payload_len); + if (!info->payload) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector JWS Payload"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, + "DPP: signedConnector - JWS Payload", + info->payload, info->payload_len); + pos = end + 1; + signature = base64_url_decode(pos, os_strlen(pos), &signature_len); + if (!signature) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector signature"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", + signature, signature_len); + + if (dpp_check_pubkey_match(csign_pub, kid) < 0) { + ret = DPP_STATUS_NO_MATCH; + goto fail; + } + + if (signature_len & 0x01) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected signedConnector signature length (%d)", + (int) signature_len); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + + /* JWS Signature encodes the signature (r,s) as two octet strings. Need + * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ + r = BN_bin2bn(signature, signature_len / 2, NULL); + s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL); + sig = ECDSA_SIG_new(); + if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1) + goto fail; + r = NULL; + s = NULL; + + der_len = i2d_ECDSA_SIG(sig, &der); + if (der_len <= 0) { + wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len); + md_ctx = EVP_MD_CTX_create(); + if (!md_ctx) + goto fail; + + ERR_clear_error(); + if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestVerifyUpdate(md_ctx, signed_start, + signed_end - signed_start + 1) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + res = EVP_DigestVerifyFinal(md_ctx, der, der_len); + if (res != 1) { + wpa_printf(MSG_DEBUG, + "DPP: EVP_DigestVerifyFinal failed (res=%d): %s", + res, ERR_error_string(ERR_get_error(), NULL)); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + + ret = DPP_STATUS_OK; +fail: + EVP_MD_CTX_destroy(md_ctx); + os_free(prot_hdr); + wpabuf_free(kid); + os_free(signature); + ECDSA_SIG_free(sig); + BN_free(r); + BN_free(s); + OPENSSL_free(der); + return ret; +} + + +int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) +{ + struct wpabuf *pix, *prx, *bix, *brx; + const u8 *addr[7]; + size_t len[7]; + size_t i, num_elem = 0; + size_t nonce_len; + u8 zero = 0; + int res = -1; + + /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + nonce_len = auth->curve->nonce_len; + + if (auth->initiator) { + pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + if (auth->own_bi) + bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + else + bix = NULL; + brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + } else { + pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (auth->peer_bi) + bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + else + bix = NULL; + brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + } + if (!pix || !prx || !brx) + goto fail; + + addr[num_elem] = auth->i_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = auth->r_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = wpabuf_head(pix); + len[num_elem] = wpabuf_len(pix) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(prx); + len[num_elem] = wpabuf_len(prx) / 2; + num_elem++; + + if (bix) { + addr[num_elem] = wpabuf_head(bix); + len[num_elem] = wpabuf_len(bix) / 2; + num_elem++; + } + + addr[num_elem] = wpabuf_head(brx); + len[num_elem] = wpabuf_len(brx) / 2; + num_elem++; + + addr[num_elem] = &zero; + len[num_elem] = 1; + num_elem++; + + wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); + for (i = 0; i < num_elem; i++) + wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); + res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); + if (res == 0) + wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, + auth->curve->hash_len); +fail: + wpabuf_free(pix); + wpabuf_free(prx); + wpabuf_free(bix); + wpabuf_free(brx); + return res; +} + + +int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) +{ + struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; + const u8 *addr[7]; + size_t len[7]; + size_t i, num_elem = 0; + size_t nonce_len; + u8 one = 1; + int res = -1; + + /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ + nonce_len = auth->curve->nonce_len; + + if (auth->initiator) { + pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + if (auth->own_bi) + bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + else + bix = NULL; + if (!auth->peer_bi) + goto fail; + brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + } else { + pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (auth->peer_bi) + bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + else + bix = NULL; + if (!auth->own_bi) + goto fail; + brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + } + if (!pix || !prx || !brx) + goto fail; + + addr[num_elem] = auth->r_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = auth->i_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = wpabuf_head(prx); + len[num_elem] = wpabuf_len(prx) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(pix); + len[num_elem] = wpabuf_len(pix) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(brx); + len[num_elem] = wpabuf_len(brx) / 2; + num_elem++; + + if (bix) { + addr[num_elem] = wpabuf_head(bix); + len[num_elem] = wpabuf_len(bix) / 2; + num_elem++; + } + + addr[num_elem] = &one; + len[num_elem] = 1; + num_elem++; + + wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); + for (i = 0; i < num_elem; i++) + wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); + res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); + if (res == 0) + wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, + auth->curve->hash_len); +fail: + wpabuf_free(pix); + wpabuf_free(prx); + wpabuf_free(bix); + wpabuf_free(brx); + return res; +} + + +int dpp_auth_derive_l_responder(struct dpp_authentication *auth) +{ + const EC_GROUP *group; + EC_POINT *l = NULL; + const EC_KEY *BI, *bR, *pR; + const EC_POINT *BI_point; + BN_CTX *bnctx; + BIGNUM *lx, *sum, *q; + const BIGNUM *bR_bn, *pR_bn; + int ret = -1; + + /* L = ((bR + pR) modulo q) * BI */ + + bnctx = BN_CTX_new(); + sum = BN_new(); + q = BN_new(); + lx = BN_new(); + if (!bnctx || !sum || !q || !lx) + goto fail; + BI = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); + if (!BI) + goto fail; + BI_point = EC_KEY_get0_public_key(BI); + group = EC_KEY_get0_group(BI); + if (!group) + goto fail; + + bR = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); + pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); + if (!bR || !pR) + goto fail; + bR_bn = EC_KEY_get0_private_key(bR); + pR_bn = EC_KEY_get0_private_key(pR); + if (!bR_bn || !pR_bn) + goto fail; + if (EC_GROUP_get_order(group, q, bnctx) != 1 || + BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1) + goto fail; + l = EC_POINT_new(group); + if (!l || + EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, + bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); + auth->Lx_len = auth->secret_len; + ret = 0; +fail: + EC_POINT_clear_free(l); + BN_clear_free(lx); + BN_clear_free(sum); + BN_free(q); + BN_CTX_free(bnctx); + return ret; +} + + +int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) +{ + const EC_GROUP *group; + EC_POINT *l = NULL, *sum = NULL; + const EC_KEY *bI, *BR, *PR; + const EC_POINT *BR_point, *PR_point; + BN_CTX *bnctx; + BIGNUM *lx; + const BIGNUM *bI_bn; + int ret = -1; + + /* L = bI * (BR + PR) */ + + bnctx = BN_CTX_new(); + lx = BN_new(); + if (!bnctx || !lx) + goto fail; + BR = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); + PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); + if (!BR || !PR) + goto fail; + BR_point = EC_KEY_get0_public_key(BR); + PR_point = EC_KEY_get0_public_key(PR); + + bI = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); + if (!bI) + goto fail; + group = EC_KEY_get0_group(bI); + bI_bn = EC_KEY_get0_private_key(bI); + if (!group || !bI_bn) + goto fail; + sum = EC_POINT_new(group); + l = EC_POINT_new(group); + if (!sum || !l || + EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 || + EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, + bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); + auth->Lx_len = auth->secret_len; + ret = 0; +fail: + EC_POINT_clear_free(l); + EC_POINT_clear_free(sum); + BN_clear_free(lx); + BN_CTX_free(bnctx); + return ret; +} + + +int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "DPP PMK"; + int res; + + /* PMK = HKDF(<>, "DPP PMK", N.x) */ + + /* HKDF-Extract(<>, N.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", + pmk, hash_len); + return 0; +} + + +int dpp_derive_pmkid(const struct dpp_curve_params *curve, + EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid) +{ + struct wpabuf *nkx, *pkx; + int ret = -1, res; + const u8 *addr[2]; + size_t len[2]; + u8 hash[SHA256_MAC_LEN]; + + /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ + nkx = dpp_get_pubkey_point(own_key, 0); + pkx = dpp_get_pubkey_point(peer_key, 0); + if (!nkx || !pkx) + goto fail; + addr[0] = wpabuf_head(nkx); + len[0] = wpabuf_len(nkx) / 2; + addr[1] = wpabuf_head(pkx); + len[1] = wpabuf_len(pkx) / 2; + if (len[0] != len[1]) + goto fail; + if (os_memcmp(addr[0], addr[1], len[0]) > 0) { + addr[0] = wpabuf_head(pkx); + addr[1] = wpabuf_head(nkx); + } + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); + res = sha256_vector(2, addr, len, hash); + if (res < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); + os_memcpy(pmkid, hash, PMKID_LEN); + wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); + ret = 0; +fail: + wpabuf_free(nkx); + wpabuf_free(pkx); + return ret; +} + + +/* Role-specific elements for PKEX */ + +/* NIST P-256 */ +static const u8 pkex_init_x_p256[32] = { + 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, + 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, + 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, + 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25 + }; +static const u8 pkex_init_y_p256[32] = { + 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, + 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, + 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, + 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 + }; +static const u8 pkex_resp_x_p256[32] = { + 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, + 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, + 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, + 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76 +}; +static const u8 pkex_resp_y_p256[32] = { + 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, + 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, + 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, + 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 +}; + +/* NIST P-384 */ +static const u8 pkex_init_x_p384[48] = { + 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa, + 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68, + 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53, + 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac, + 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12, + 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3 +}; +static const u8 pkex_init_y_p384[48] = { + 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29, + 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56, + 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7, + 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6, + 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94, + 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18 +}; +static const u8 pkex_resp_x_p384[48] = { + 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98, + 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97, + 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92, + 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44, + 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf, + 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf +}; +static const u8 pkex_resp_y_p384[48] = { + 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c, + 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c, + 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3, + 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1, + 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63, + 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06 +}; + +/* NIST P-521 */ +static const u8 pkex_init_x_p521[66] = { + 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23, + 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0, + 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76, + 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5, + 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38, + 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01, + 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e, + 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d, + 0x97, 0x76 +}; +static const u8 pkex_init_y_p521[66] = { + 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59, + 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99, + 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b, + 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd, + 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f, + 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf, + 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02, + 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d, + 0x03, 0xa8 +}; +static const u8 pkex_resp_x_p521[66] = { + 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a, + 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44, + 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f, + 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb, + 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48, + 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e, + 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a, + 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97, + 0x84, 0xb4 +}; +static const u8 pkex_resp_y_p521[66] = { + 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d, + 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20, + 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3, + 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84, + 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9, + 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2, + 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80, + 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53, + 0xce, 0xe1 +}; + +/* Brainpool P-256r1 */ +static const u8 pkex_init_x_bp_p256r1[32] = { + 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10, + 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca, + 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75, + 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8 +}; +static const u8 pkex_init_y_bp_p256r1[32] = { + 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd, + 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30, + 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe, + 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b +}; +static const u8 pkex_resp_x_bp_p256r1[32] = { + 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f, + 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a, + 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a, + 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3 +}; +static const u8 pkex_resp_y_bp_p256r1[32] = { + 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd, + 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2, + 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e, + 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64 +}; + +/* Brainpool P-384r1 */ +static const u8 pkex_init_x_bp_p384r1[48] = { + 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd, + 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19, + 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06, + 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62, + 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30, + 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe +}; +static const u8 pkex_init_y_bp_p384r1[48] = { + 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99, + 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86, + 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32, + 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9, + 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e, + 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52 +}; +static const u8 pkex_resp_x_bp_p384r1[48] = { + 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0, + 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25, + 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b, + 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71, + 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce, + 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c +}; +static const u8 pkex_resp_y_bp_p384r1[48] = { + 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65, + 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04, + 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70, + 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c, + 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb, + 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1 +}; + +/* Brainpool P-512r1 */ +static const u8 pkex_init_x_bp_p512r1[64] = { + 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c, + 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51, + 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc, + 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95, + 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d, + 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff, + 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc, + 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f +}; +static const u8 pkex_init_y_bp_p512r1[64] = { + 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94, + 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8, + 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3, + 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45, + 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e, + 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58, + 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71, + 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99 +}; +static const u8 pkex_resp_x_bp_p512r1[64] = { + 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72, + 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76, + 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19, + 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e, + 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9, + 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88, + 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29, + 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e +}; +static const u8 pkex_resp_y_bp_p512r1[64] = { + 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81, + 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68, + 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa, + 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d, + 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c, + 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09, + 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56, + 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7 +}; + + +static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, + int init) +{ + EC_GROUP *group; + size_t len = curve->prime_len; + const u8 *x, *y; + EVP_PKEY *res; + + switch (curve->ike_group) { + case 19: + x = init ? pkex_init_x_p256 : pkex_resp_x_p256; + y = init ? pkex_init_y_p256 : pkex_resp_y_p256; + break; + case 20: + x = init ? pkex_init_x_p384 : pkex_resp_x_p384; + y = init ? pkex_init_y_p384 : pkex_resp_y_p384; + break; + case 21: + x = init ? pkex_init_x_p521 : pkex_resp_x_p521; + y = init ? pkex_init_y_p521 : pkex_resp_y_p521; + break; + case 28: + x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1; + y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1; + break; + case 29: + x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1; + y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1; + break; + case 30: + x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1; + y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1; + break; + default: + return NULL; + } + + group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); + if (!group) + return NULL; + res = dpp_set_pubkey_point_group(group, x, y, len); + EC_GROUP_free(group); + return res; +} + + +EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, + const u8 *mac_init, const char *code, + const char *identifier, BN_CTX *bnctx, + EC_GROUP **ret_group) +{ + u8 hash[DPP_MAX_HASH_LEN]; + const u8 *addr[3]; + size_t len[3]; + unsigned int num_elem = 0; + EC_POINT *Qi = NULL; + EVP_PKEY *Pi = NULL; + const EC_KEY *Pi_ec; + const EC_POINT *Pi_point; + BIGNUM *hash_bn = NULL; + const EC_GROUP *group = NULL; + EC_GROUP *group2 = NULL; + + /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ + + wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init)); + addr[num_elem] = mac_init; + len[num_elem] = ETH_ALEN; + num_elem++; + if (identifier) { + wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", + identifier); + addr[num_elem] = (const u8 *) identifier; + len[num_elem] = os_strlen(identifier); + num_elem++; + } + wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); + addr[num_elem] = (const u8 *) code; + len[num_elem] = os_strlen(code); + num_elem++; + if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: H(MAC-Initiator | [identifier |] code)", + hash, curve->hash_len); + Pi = dpp_pkex_get_role_elem(curve, 1); + if (!Pi) + goto fail; + dpp_debug_print_key("DPP: Pi", Pi); + Pi_ec = EVP_PKEY_get0_EC_KEY(Pi); + if (!Pi_ec) + goto fail; + Pi_point = EC_KEY_get0_public_key(Pi_ec); + + group = EC_KEY_get0_group(Pi_ec); + if (!group) + goto fail; + group2 = EC_GROUP_dup(group); + if (!group2) + goto fail; + Qi = EC_POINT_new(group2); + if (!Qi) { + EC_GROUP_free(group2); + goto fail; + } + hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); + if (!hash_bn || + EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1) + goto fail; + if (EC_POINT_is_at_infinity(group, Qi)) { + wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity"); + goto fail; + } + dpp_debug_print_point("DPP: Qi", group, Qi); +out: + EVP_PKEY_free(Pi); + BN_clear_free(hash_bn); + if (ret_group && Qi) + *ret_group = group2; + else + EC_GROUP_free(group2); + return Qi; +fail: + EC_POINT_free(Qi); + Qi = NULL; + goto out; +} + + +EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, + const u8 *mac_resp, const char *code, + const char *identifier, BN_CTX *bnctx, + EC_GROUP **ret_group) +{ + u8 hash[DPP_MAX_HASH_LEN]; + const u8 *addr[3]; + size_t len[3]; + unsigned int num_elem = 0; + EC_POINT *Qr = NULL; + EVP_PKEY *Pr = NULL; + const EC_KEY *Pr_ec; + const EC_POINT *Pr_point; + BIGNUM *hash_bn = NULL; + const EC_GROUP *group = NULL; + EC_GROUP *group2 = NULL; + + /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ + + wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp)); + addr[num_elem] = mac_resp; + len[num_elem] = ETH_ALEN; + num_elem++; + if (identifier) { + wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", + identifier); + addr[num_elem] = (const u8 *) identifier; + len[num_elem] = os_strlen(identifier); + num_elem++; + } + wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); + addr[num_elem] = (const u8 *) code; + len[num_elem] = os_strlen(code); + num_elem++; + if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: H(MAC-Responder | [identifier |] code)", + hash, curve->hash_len); + Pr = dpp_pkex_get_role_elem(curve, 0); + if (!Pr) + goto fail; + dpp_debug_print_key("DPP: Pr", Pr); + Pr_ec = EVP_PKEY_get0_EC_KEY(Pr); + if (!Pr_ec) + goto fail; + Pr_point = EC_KEY_get0_public_key(Pr_ec); + + group = EC_KEY_get0_group(Pr_ec); + if (!group) + goto fail; + group2 = EC_GROUP_dup(group); + if (!group2) + goto fail; + Qr = EC_POINT_new(group2); + if (!Qr) { + EC_GROUP_free(group2); + goto fail; + } + hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); + if (!hash_bn || + EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1) + goto fail; + if (EC_POINT_is_at_infinity(group, Qr)) { + wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity"); + goto fail; + } + dpp_debug_print_point("DPP: Qr", group, Qr); +out: + EVP_PKEY_free(Pr); + BN_clear_free(hash_bn); + if (ret_group && Qr) + *ret_group = group2; + else + EC_GROUP_free(group2); + return Qr; +fail: + EC_POINT_free(Qr); + Qr = NULL; + goto out; +} + + +int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, + const u8 *Mx, size_t Mx_len, + const u8 *Nx, size_t Nx_len, + const char *code, + const u8 *Kx, size_t Kx_len, + u8 *z, unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + int res; + u8 *info, *pos; + size_t info_len; + + /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) + */ + + /* HKDF-Extract(<>, IKM=K.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", + prk, hash_len); + info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code); + info = os_malloc(info_len); + if (!info) + return -1; + pos = info; + os_memcpy(pos, mac_init, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, mac_resp, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, Mx, Mx_len); + pos += Mx_len; + os_memcpy(pos, Nx, Nx_len); + pos += Nx_len; + os_memcpy(pos, code, os_strlen(code)); + + /* HKDF-Expand(PRK, info, L) */ + if (hash_len == 32) + res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len, + z, hash_len); + else if (hash_len == 48) + res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len, + z, hash_len); + else if (hash_len == 64) + res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len, + z, hash_len); + else + res = -1; + os_free(info); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)", + z, hash_len); + return 0; +} + + +static char * +dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) +{ + struct wpabuf *jws_prot_hdr; + char *signed1; + + jws_prot_hdr = wpabuf_alloc(100); + if (!jws_prot_hdr) + return NULL; + json_start_object(jws_prot_hdr, NULL); + json_add_string(jws_prot_hdr, "typ", "dppCon"); + json_value_sep(jws_prot_hdr); + json_add_string(jws_prot_hdr, "kid", conf->kid); + json_value_sep(jws_prot_hdr); + json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg); + json_end_object(jws_prot_hdr); + signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), + wpabuf_len(jws_prot_hdr), + signed1_len); + wpabuf_free(jws_prot_hdr); + return signed1; +} + + +static char * +dpp_build_conn_signature(struct dpp_configurator *conf, + const char *signed1, size_t signed1_len, + const char *signed2, size_t signed2_len, + size_t *signed3_len) +{ + const struct dpp_curve_params *curve; + char *signed3 = NULL; + unsigned char *signature = NULL; + const unsigned char *p; + size_t signature_len; + EVP_MD_CTX *md_ctx = NULL; + ECDSA_SIG *sig = NULL; + char *dot = "."; + const EVP_MD *sign_md; + const BIGNUM *r, *s; + + curve = conf->curve; + if (curve->hash_len == SHA256_MAC_LEN) { + sign_md = EVP_sha256(); + } else if (curve->hash_len == SHA384_MAC_LEN) { + sign_md = EVP_sha384(); + } else if (curve->hash_len == SHA512_MAC_LEN) { + sign_md = EVP_sha512(); + } else { + wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); + goto fail; + } + + md_ctx = EVP_MD_CTX_create(); + if (!md_ctx) + goto fail; + + ERR_clear_error(); + if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, conf->csign) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 || + EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 || + EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + signature = os_malloc(signature_len); + if (!signature) + goto fail; + if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)", + signature, signature_len); + /* Convert to raw coordinates r,s */ + p = signature; + sig = d2i_ECDSA_SIG(NULL, &p, signature_len); + if (!sig) + goto fail; + ECDSA_SIG_get0(sig, &r, &s); + if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 || + dpp_bn2bin_pad(s, signature + curve->prime_len, + curve->prime_len) < 0) + goto fail; + signature_len = 2 * curve->prime_len; + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", + signature, signature_len); + signed3 = base64_url_encode(signature, signature_len, signed3_len); +fail: + EVP_MD_CTX_destroy(md_ctx); + ECDSA_SIG_free(sig); + os_free(signature); + return signed3; +} + +char * dpp_sign_connector(struct dpp_configurator *conf, + const struct wpabuf *dppcon) +{ + char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; + char *signed_conn = NULL, *pos; + size_t signed1_len, signed2_len, signed3_len; + + signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len); + signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), + &signed2_len); + if (!signed1 || !signed2) + goto fail; + + signed3 = dpp_build_conn_signature(conf, signed1, signed1_len, + signed2, signed2_len, &signed3_len); + if (!signed3) + goto fail; + + signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3); + if (!signed_conn) + goto fail; + pos = signed_conn; + os_memcpy(pos, signed1, signed1_len); + pos += signed1_len; + *pos++ = '.'; + os_memcpy(pos, signed2, signed2_len); + pos += signed2_len; + *pos++ = '.'; + os_memcpy(pos, signed3, signed3_len); + pos += signed3_len; + *pos = '\0'; + +fail: + os_free(signed1); + os_free(signed2); + os_free(signed3); + return signed_conn; +} + + +#ifdef CONFIG_DPP2 + +struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, + size_t net_access_key_len) +{ + struct wpabuf *pub = NULL; + EVP_PKEY *own_key; + struct dpp_pfs *pfs; + + pfs = os_zalloc(sizeof(*pfs)); + if (!pfs) + return NULL; + + own_key = dpp_set_keypair(&pfs->curve, net_access_key, + net_access_key_len); + if (!own_key) { + wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); + goto fail; + } + EVP_PKEY_free(own_key); + + pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group); + if (!pfs->ecdh) + goto fail; + + pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0); + pub = wpabuf_zeropad(pub, pfs->curve->prime_len); + if (!pub) + goto fail; + + pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub)); + if (!pfs->ie) + goto fail; + wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION); + wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub)); + wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM); + wpabuf_put_le16(pfs->ie, pfs->curve->ike_group); + wpabuf_put_buf(pfs->ie, pub); + wpabuf_free(pub); + wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element", + pfs->ie); + + return pfs; +fail: + wpabuf_free(pub); + dpp_pfs_free(pfs); + return NULL; +} + + +int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len) +{ + if (peer_ie_len < 2) + return -1; + if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) { + wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS"); + return -1; + } + + pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2, + peer_ie_len - 2); + pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len); + if (!pfs->secret) { + wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key"); + return -1; + } + wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret); + return 0; +} + + +void dpp_pfs_free(struct dpp_pfs *pfs) +{ + if (!pfs) + return; + crypto_ecdh_deinit(pfs->ecdh); + wpabuf_free(pfs->ie); + wpabuf_clear_free(pfs->secret); + os_free(pfs); +} + +#endif /* CONFIG_DPP2 */ + + +#ifdef CONFIG_TESTING_OPTIONS + +int dpp_test_gen_invalid_key(struct wpabuf *msg, + const struct dpp_curve_params *curve) +{ + BN_CTX *ctx; + BIGNUM *x, *y; + int ret = -1; + EC_GROUP *group; + EC_POINT *point; + + group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); + if (!group) + return -1; + + ctx = BN_CTX_new(); + point = EC_POINT_new(group); + x = BN_new(); + y = BN_new(); + if (!ctx || !point || !x || !y) + goto fail; + + if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1) + goto fail; + + /* Generate a random y coordinate that results in a point that is not + * on the curve. */ + for (;;) { + if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1) + goto fail; + + if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y, + ctx) != 1) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL) + /* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL + * return an error from EC_POINT_set_affine_coordinates_GFp() + * when the point is not on the curve. */ + break; +#else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */ + goto fail; +#endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */ + } + + if (!EC_POINT_is_on_curve(group, point, ctx)) + break; + } + + if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0 || + dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0) + goto fail; + + ret = 0; +fail: + if (ret < 0) + wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key"); + BN_free(x); + BN_free(y); + EC_POINT_free(point); + BN_CTX_free(ctx); + EC_GROUP_free(group); + + return ret; +} + + +char * dpp_corrupt_connector_signature(const char *connector) +{ + char *tmp, *pos, *signed3 = NULL; + unsigned char *signature = NULL; + size_t signature_len = 0, signed3_len; + + tmp = os_zalloc(os_strlen(connector) + 5); + if (!tmp) + goto fail; + os_memcpy(tmp, connector, os_strlen(connector)); + + pos = os_strchr(tmp, '.'); + if (!pos) + goto fail; + + pos = os_strchr(pos + 1, '.'); + if (!pos) + goto fail; + pos++; + + wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", + pos); + signature = base64_url_decode(pos, os_strlen(pos), &signature_len); + if (!signature || signature_len == 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", + signature, signature_len); + signature[signature_len - 1] ^= 0x01; + wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", + signature, signature_len); + signed3 = base64_url_encode(signature, signature_len, &signed3_len); + if (!signed3) + goto fail; + os_memcpy(pos, signed3, signed3_len); + pos[signed3_len] = '\0'; + wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", + pos); + +out: + os_free(signature); + os_free(signed3); + return tmp; +fail: + os_free(tmp); + tmp = NULL; + goto out; +} + +#endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h new file mode 100644 index 000000000..a0af5f9fc --- /dev/null +++ b/src/common/dpp_i.h @@ -0,0 +1,91 @@ +/* + * DPP module internal definitions + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DPP_I_H +#define DPP_I_H + +#ifdef CONFIG_DPP + +/* dpp_crypto.c */ + +struct dpp_signed_connector_info { + unsigned char *payload; + size_t payload_len; +}; + +enum dpp_status_error +dpp_process_signed_connector(struct dpp_signed_connector_info *info, + EVP_PKEY *csign_pub, const char *connector); +const struct dpp_curve_params * dpp_get_curve_name(const char *name); +const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name); +const struct dpp_curve_params * dpp_get_curve_oid(const ASN1_OBJECT *poid); +const struct dpp_curve_params * dpp_get_curve_nid(int nid); +int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len); +struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix); +EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, + const u8 *buf_x, const u8 *buf_y, + size_t len); +EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len); +int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len); +int dpp_hash_vector(const struct dpp_curve_params *curve, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, + const char *label, u8 *out, size_t outlen); +int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, + const u8 *data, size_t data_len, u8 *mac); +int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); +int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len); +void dpp_debug_print_point(const char *title, const EC_GROUP *group, + const EC_POINT *point); +void dpp_debug_print_key(const char *title, EVP_PKEY *key); +int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, + const u8 *salt, size_t salt_len, unsigned int iterations, + u8 *buf, size_t buflen); +int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len); +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); +int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + const u8 *privkey, size_t privkey_len); +EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len); +EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve); +int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len); +int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len); +int dpp_derive_bk_ke(struct dpp_authentication *auth); +int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth); +int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth); +int dpp_auth_derive_l_responder(struct dpp_authentication *auth); +int dpp_auth_derive_l_initiator(struct dpp_authentication *auth); +int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len); +int dpp_derive_pmkid(const struct dpp_curve_params *curve, + EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid); +EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, + const u8 *mac_init, const char *code, + const char *identifier, BN_CTX *bnctx, + EC_GROUP **ret_group); +EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, + const u8 *mac_resp, const char *code, + const char *identifier, BN_CTX *bnctx, + EC_GROUP **ret_group); +int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, + const u8 *Mx, size_t Mx_len, + const u8 *Nx, size_t Nx_len, + const char *code, + const u8 *Kx, size_t Kx_len, + u8 *z, unsigned int hash_len); +char * dpp_sign_connector(struct dpp_configurator *conf, + const struct wpabuf *dppcon); +int dpp_test_gen_invalid_key(struct wpabuf *msg, + const struct dpp_curve_params *curve); + +#endif /* CONFIG_DPP */ +#endif /* DPP_I_H */ diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index 10c4ea2f4..1ed0c8941 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -21,6 +21,7 @@ OBJS += $(SRC)/crypto/sha384-kdf.o OBJS += $(SRC)/crypto/sha512-kdf.o OBJS += $(SRC)/tls/asn1.o OBJS += $(SRC)/common/dpp.o +OBJS += $(SRC)/common/dpp_crypto.o dpp-uri: dpp-uri.o $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index a08da4d64..671535904 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -247,6 +247,7 @@ endif ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c +OBJS += src/common/dpp_crypto.c OBJS += dpp_supplicant.c NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 7a02027e2..14e32eeab 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -279,6 +279,7 @@ endif ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o +OBJS += ../src/common/dpp_crypto.o OBJS += dpp_supplicant.o NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y From d4ae12355a65b7aa1648b9bd54ce2c1d6916232a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 10 May 2020 16:51:46 +0300 Subject: [PATCH 0467/1105] DPP: Move PKEX functionality into a separate source code file This continues splitting dpp.c into smaller pieces. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 1 + hostapd/Makefile | 1 + src/common/dpp.c | 1307 +------------------------------ src/common/dpp_i.h | 19 + src/common/dpp_pkex.c | 1324 ++++++++++++++++++++++++++++++++ tests/fuzzing/dpp-uri/Makefile | 1 + wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + 8 files changed, 1352 insertions(+), 1303 deletions(-) create mode 100644 src/common/dpp_pkex.c diff --git a/hostapd/Android.mk b/hostapd/Android.mk index e8eca2e89..c581f5d89 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -538,6 +538,7 @@ ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c OBJS += src/common/dpp_crypto.c +OBJS += src/common/dpp_pkex.c OBJS += src/ap/dpp_hostapd.c OBJS += src/ap/gas_query_ap.c NEED_AES_SIV=y diff --git a/hostapd/Makefile b/hostapd/Makefile index 92ffdeeb1..c20a1a822 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -569,6 +569,7 @@ ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o OBJS += ../src/common/dpp_crypto.o +OBJS += ../src/common/dpp_pkex.o OBJS += ../src/ap/dpp_hostapd.o OBJS += ../src/ap/gas_query_ap.o NEED_AES_SIV=y diff --git a/src/common/dpp.c b/src/common/dpp.c index b8e1d7866..1d6d488ad 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -39,10 +39,6 @@ int dpp_version_override = 2; int dpp_version_override = 1; #endif enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED; -u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -u8 dpp_pkex_ephemeral_key_override[600]; -size_t dpp_pkex_ephemeral_key_override_len = 0; u8 dpp_protocol_key_override[600]; size_t dpp_protocol_key_override_len = 0; u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; @@ -54,12 +50,14 @@ size_t dpp_nonce_override_len = 0; LIBRESSL_VERSION_NUMBER < 0x20700000L) /* Compatibility wrappers for older versions. */ +#ifdef CONFIG_DPP2 static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { if (pkey->type != EVP_PKEY_EC) return NULL; return pkey->pkey.ec; } +#endif /* CONFIG_DPP2 */ #endif @@ -109,20 +107,6 @@ struct dpp_controller { char *configurator_params; }; -struct dpp_global { - void *msg_ctx; - struct dl_list bootstrap; /* struct dpp_bootstrap_info */ - struct dl_list configurator; /* struct dpp_configurator */ -#ifdef CONFIG_DPP2 - struct dl_list controllers; /* struct dpp_relay_controller */ - struct dpp_controller *controller; - struct dl_list tcp_init; /* struct dpp_connection */ - void *cb_ctx; - int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); - void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); -#endif /* CONFIG_DPP2 */ -}; - static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) { @@ -496,8 +480,7 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) } -static void dpp_build_attr_status(struct wpabuf *msg, - enum dpp_status_error status) +void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status) { wpa_printf(MSG_DEBUG, "DPP: Status %d", status); wpabuf_put_le16(msg, DPP_ATTR_STATUS); @@ -6659,1262 +6642,7 @@ fail: } -static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex) -{ - const EC_KEY *X_ec; - const EC_POINT *X_point; - BN_CTX *bnctx = NULL; - EC_GROUP *group = NULL; - EC_POINT *Qi = NULL, *M = NULL; - struct wpabuf *M_buf = NULL; - BIGNUM *Mx = NULL, *My = NULL; - struct wpabuf *msg = NULL; - size_t attr_len; - const struct dpp_curve_params *curve = pkex->own_bi->curve; - - wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request"); - - /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ - bnctx = BN_CTX_new(); - if (!bnctx) - goto fail; - Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code, - pkex->identifier, bnctx, &group); - if (!Qi) - goto fail; - - /* Generate a random ephemeral keypair x/X */ -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_pkex_ephemeral_key_override_len) { - const struct dpp_curve_params *tmp_curve; - - wpa_printf(MSG_INFO, - "DPP: TESTING - override ephemeral key x/X"); - pkex->x = dpp_set_keypair(&tmp_curve, - dpp_pkex_ephemeral_key_override, - dpp_pkex_ephemeral_key_override_len); - } else { - pkex->x = dpp_gen_keypair(curve); - } -#else /* CONFIG_TESTING_OPTIONS */ - pkex->x = dpp_gen_keypair(curve); -#endif /* CONFIG_TESTING_OPTIONS */ - if (!pkex->x) - goto fail; - - /* M = X + Qi */ - X_ec = EVP_PKEY_get0_EC_KEY(pkex->x); - if (!X_ec) - goto fail; - X_point = EC_KEY_get0_public_key(X_ec); - if (!X_point) - goto fail; - dpp_debug_print_point("DPP: X", group, X_point); - M = EC_POINT_new(group); - Mx = BN_new(); - My = BN_new(); - if (!M || !Mx || !My || - EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1) - goto fail; - dpp_debug_print_point("DPP: M", group, M); - - /* Initiator -> Responder: group, [identifier,] M */ - attr_len = 4 + 2; - if (pkex->identifier) - attr_len += 4 + os_strlen(pkex->identifier); - attr_len += 4 + 2 * curve->prime_len; - msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len); - if (!msg) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group"); - goto skip_finite_cyclic_group; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Finite Cyclic Group attribute */ - wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); - wpabuf_put_le16(msg, 2); - wpabuf_put_le16(msg, curve->ike_group); - -#ifdef CONFIG_TESTING_OPTIONS -skip_finite_cyclic_group: -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Code Identifier attribute */ - if (pkex->identifier) { - wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER); - wpabuf_put_le16(msg, os_strlen(pkex->identifier)); - wpabuf_put_str(msg, pkex->identifier); - } - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key"); - goto out; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* M in Encrypted Key attribute */ - wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY); - wpabuf_put_le16(msg, 2 * curve->prime_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key"); - if (dpp_test_gen_invalid_key(msg, curve) < 0) - goto fail; - goto out; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0 || - dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 || - dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0) - goto fail; - -out: - wpabuf_free(M_buf); - EC_POINT_free(M); - EC_POINT_free(Qi); - BN_clear_free(Mx); - BN_clear_free(My); - BN_CTX_free(bnctx); - EC_GROUP_free(group); - return msg; -fail: - wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request"); - wpabuf_free(msg); - msg = NULL; - goto out; -} - - -static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt) -{ - wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); -} - - -struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi, - const u8 *own_mac, - const char *identifier, - const char *code) -{ - struct dpp_pkex *pkex; - -#ifdef CONFIG_TESTING_OPTIONS - if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) { - wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR, - MAC2STR(dpp_pkex_own_mac_override)); - own_mac = dpp_pkex_own_mac_override; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - pkex = os_zalloc(sizeof(*pkex)); - if (!pkex) - return NULL; - pkex->msg_ctx = msg_ctx; - pkex->initiator = 1; - pkex->own_bi = bi; - os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); - if (identifier) { - pkex->identifier = os_strdup(identifier); - if (!pkex->identifier) - goto fail; - } - pkex->code = os_strdup(code); - if (!pkex->code) - goto fail; - pkex->exchange_req = dpp_pkex_build_exchange_req(pkex); - if (!pkex->exchange_req) - goto fail; - return pkex; -fail: - dpp_pkex_free(pkex); - return NULL; -} - - -static struct wpabuf * -dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex, - enum dpp_status_error status, - const BIGNUM *Nx, const BIGNUM *Ny) -{ - struct wpabuf *msg = NULL; - size_t attr_len; - const struct dpp_curve_params *curve = pkex->own_bi->curve; - - /* Initiator -> Responder: DPP Status, [identifier,] N */ - attr_len = 4 + 1; - if (pkex->identifier) - attr_len += 4 + os_strlen(pkex->identifier); - attr_len += 4 + 2 * curve->prime_len; - msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len); - if (!msg) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); - goto skip_status; - } - - if (dpp_test == DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); - status = 255; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* DPP Status */ - dpp_build_attr_status(msg, status); - -#ifdef CONFIG_TESTING_OPTIONS -skip_status: -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Code Identifier attribute */ - if (pkex->identifier) { - wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER); - wpabuf_put_le16(msg, os_strlen(pkex->identifier)); - wpabuf_put_str(msg, pkex->identifier); - } - - if (status != DPP_STATUS_OK) - goto skip_encrypted_key; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key"); - goto skip_encrypted_key; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* N in Encrypted Key attribute */ - wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY); - wpabuf_put_le16(msg, 2 * curve->prime_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key"); - if (dpp_test_gen_invalid_key(msg, curve) < 0) - goto fail; - goto skip_encrypted_key; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (dpp_bn2bin_pad(Nx, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0 || - dpp_bn2bin_pad(Nx, pkex->Nx, curve->prime_len) < 0 || - dpp_bn2bin_pad(Ny, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0) - goto fail; - -skip_encrypted_key: - if (status == DPP_STATUS_BAD_GROUP) { - /* Finite Cyclic Group attribute */ - wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); - wpabuf_put_le16(msg, 2); - wpabuf_put_le16(msg, curve->ike_group); - } - - return msg; -fail: - wpabuf_free(msg); - return NULL; -} - - -static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len, - const char *identifier) -{ - if (!attr_id && identifier) { - wpa_printf(MSG_DEBUG, - "DPP: No PKEX code identifier received, but expected one"); - return 0; - } - - if (attr_id && !identifier) { - wpa_printf(MSG_DEBUG, - "DPP: PKEX code identifier received, but not expecting one"); - return 0; - } - - if (attr_id && identifier && - (os_strlen(identifier) != attr_id_len || - os_memcmp(identifier, attr_id, attr_id_len) != 0)) { - wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch"); - return 0; - } - - return 1; -} - - -struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx, - struct dpp_bootstrap_info *bi, - const u8 *own_mac, - const u8 *peer_mac, - const char *identifier, - const char *code, - const u8 *buf, size_t len) -{ - const u8 *attr_group, *attr_id, *attr_key; - u16 attr_group_len, attr_id_len, attr_key_len; - const struct dpp_curve_params *curve = bi->curve; - u16 ike_group; - struct dpp_pkex *pkex = NULL; - EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL; - BN_CTX *bnctx = NULL; - EC_GROUP *group = NULL; - BIGNUM *Mx = NULL, *My = NULL; - const EC_KEY *Y_ec; - EC_KEY *X_ec = NULL; - const EC_POINT *Y_point; - BIGNUM *Nx = NULL, *Ny = NULL; - u8 Kx[DPP_MAX_SHARED_SECRET_LEN]; - size_t Kx_len; - int res; - - if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "PKEX counter t limit reached - ignore message"); - return NULL; - } - -#ifdef CONFIG_TESTING_OPTIONS - if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { - wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, - MAC2STR(dpp_pkex_peer_mac_override)); - peer_mac = dpp_pkex_peer_mac_override; - } - if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) { - wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR, - MAC2STR(dpp_pkex_own_mac_override)); - own_mac = dpp_pkex_own_mac_override; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - attr_id_len = 0; - attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER, - &attr_id_len); - if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier)) - return NULL; - - attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, - &attr_group_len); - if (!attr_group || attr_group_len != 2) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Missing or invalid Finite Cyclic Group attribute"); - return NULL; - } - ike_group = WPA_GET_LE16(attr_group); - if (ike_group != curve->ike_group) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Mismatching PKEX curve: peer=%u own=%u", - ike_group, curve->ike_group); - pkex = os_zalloc(sizeof(*pkex)); - if (!pkex) - goto fail; - pkex->own_bi = bi; - pkex->failed = 1; - pkex->exchange_resp = dpp_pkex_build_exchange_resp( - pkex, DPP_STATUS_BAD_GROUP, NULL, NULL); - if (!pkex->exchange_resp) - goto fail; - return pkex; - } - - /* M in Encrypted Key attribute */ - attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY, - &attr_key_len); - if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 || - attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Missing Encrypted Key attribute"); - return NULL; - } - - /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ - bnctx = BN_CTX_new(); - if (!bnctx) - goto fail; - Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx, - &group); - if (!Qi) - goto fail; - - /* X' = M - Qi */ - X = EC_POINT_new(group); - M = EC_POINT_new(group); - Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL); - My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL); - if (!X || !M || !Mx || !My || - EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 || - EC_POINT_is_at_infinity(group, M) || - !EC_POINT_is_on_curve(group, M, bnctx) || - EC_POINT_invert(group, Qi, bnctx) != 1 || - EC_POINT_add(group, X, M, Qi, bnctx) != 1 || - EC_POINT_is_at_infinity(group, X) || - !EC_POINT_is_on_curve(group, X, bnctx)) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Invalid Encrypted Key value"); - bi->pkex_t++; - goto fail; - } - dpp_debug_print_point("DPP: M", group, M); - dpp_debug_print_point("DPP: X'", group, X); - - pkex = os_zalloc(sizeof(*pkex)); - if (!pkex) - goto fail; - pkex->t = bi->pkex_t; - pkex->msg_ctx = msg_ctx; - pkex->own_bi = bi; - os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); - os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); - if (identifier) { - pkex->identifier = os_strdup(identifier); - if (!pkex->identifier) - goto fail; - } - pkex->code = os_strdup(code); - if (!pkex->code) - goto fail; - - os_memcpy(pkex->Mx, attr_key, attr_key_len / 2); - - X_ec = EC_KEY_new(); - if (!X_ec || - EC_KEY_set_group(X_ec, group) != 1 || - EC_KEY_set_public_key(X_ec, X) != 1) - goto fail; - pkex->x = EVP_PKEY_new(); - if (!pkex->x || - EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1) - goto fail; - - /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ - Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL); - if (!Qr) - goto fail; - - /* Generate a random ephemeral keypair y/Y */ -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_pkex_ephemeral_key_override_len) { - const struct dpp_curve_params *tmp_curve; - - wpa_printf(MSG_INFO, - "DPP: TESTING - override ephemeral key y/Y"); - pkex->y = dpp_set_keypair(&tmp_curve, - dpp_pkex_ephemeral_key_override, - dpp_pkex_ephemeral_key_override_len); - } else { - pkex->y = dpp_gen_keypair(curve); - } -#else /* CONFIG_TESTING_OPTIONS */ - pkex->y = dpp_gen_keypair(curve); -#endif /* CONFIG_TESTING_OPTIONS */ - if (!pkex->y) - goto fail; - - /* N = Y + Qr */ - Y_ec = EVP_PKEY_get0_EC_KEY(pkex->y); - if (!Y_ec) - goto fail; - Y_point = EC_KEY_get0_public_key(Y_ec); - if (!Y_point) - goto fail; - dpp_debug_print_point("DPP: Y", group, Y_point); - N = EC_POINT_new(group); - Nx = BN_new(); - Ny = BN_new(); - if (!N || !Nx || !Ny || - EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1) - goto fail; - dpp_debug_print_point("DPP: N", group, N); - - pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK, - Nx, Ny); - if (!pkex->exchange_resp) - goto fail; - - /* K = y * X' */ - if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", - Kx, Kx_len); - - /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) - */ - res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac, - pkex->Mx, curve->prime_len, - pkex->Nx, curve->prime_len, pkex->code, - Kx, Kx_len, pkex->z, curve->hash_len); - os_memset(Kx, 0, Kx_len); - if (res < 0) - goto fail; - - pkex->exchange_done = 1; - -out: - BN_CTX_free(bnctx); - EC_POINT_free(Qi); - EC_POINT_free(Qr); - BN_free(Mx); - BN_free(My); - BN_free(Nx); - BN_free(Ny); - EC_POINT_free(M); - EC_POINT_free(N); - EC_POINT_free(X); - EC_KEY_free(X_ec); - EC_GROUP_free(group); - return pkex; -fail: - wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed"); - dpp_pkex_free(pkex); - pkex = NULL; - goto out; -} - - -static struct wpabuf * -dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex, - const struct wpabuf *A_pub, const u8 *u) -{ - const struct dpp_curve_params *curve = pkex->own_bi->curve; - struct wpabuf *msg = NULL; - size_t clear_len, attr_len; - struct wpabuf *clear = NULL; - u8 *wrapped; - u8 octet; - const u8 *addr[2]; - size_t len[2]; - - /* {A, u, [bootstrapping info]}z */ - clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; - clear = wpabuf_alloc(clear_len); - attr_len = 4 + clear_len + AES_BLOCK_SIZE; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len); - if (!clear || !msg) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); - goto skip_bootstrap_key; - } - if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); - wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); - wpabuf_put_le16(clear, 2 * curve->prime_len); - if (dpp_test_gen_invalid_key(clear, curve) < 0) - goto fail; - goto skip_bootstrap_key; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* A in Bootstrap Key attribute */ - wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); - wpabuf_put_le16(clear, wpabuf_len(A_pub)); - wpabuf_put_buf(clear, A_pub); - -#ifdef CONFIG_TESTING_OPTIONS -skip_bootstrap_key: - if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag"); - goto skip_i_auth_tag; - } - if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch"); - wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); - wpabuf_put_le16(clear, curve->hash_len); - wpabuf_put_data(clear, u, curve->hash_len - 1); - wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01); - goto skip_i_auth_tag; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* u in I-Auth tag attribute */ - wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); - wpabuf_put_le16(clear, curve->hash_len); - wpabuf_put_data(clear, u, curve->hash_len); - -#ifdef CONFIG_TESTING_OPTIONS -skip_i_auth_tag: - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); - goto skip_wrapped_data; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = DPP_HDR_LEN; - octet = 0; - addr[1] = &octet; - len[1] = sizeof(octet); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); - wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); - - wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); - if (aes_siv_encrypt(pkex->z, curve->hash_len, - wpabuf_head(clear), wpabuf_len(clear), - 2, addr, len, wrapped) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - -out: - wpabuf_free(clear); - return msg; - -fail: - wpabuf_free(msg); - msg = NULL; - goto out; -} - - -struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex, - const u8 *peer_mac, - const u8 *buf, size_t buflen) -{ - const u8 *attr_status, *attr_id, *attr_key, *attr_group; - u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len; - EC_GROUP *group = NULL; - BN_CTX *bnctx = NULL; - struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; - const struct dpp_curve_params *curve = pkex->own_bi->curve; - EC_POINT *Qr = NULL, *Y = NULL, *N = NULL; - BIGNUM *Nx = NULL, *Ny = NULL; - EC_KEY *Y_ec = NULL; - size_t Jx_len, Kx_len; - u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN]; - const u8 *addr[4]; - size_t len[4]; - u8 u[DPP_MAX_HASH_LEN]; - int res; - - if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) - return NULL; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at PKEX Exchange Response"); - pkex->failed = 1; - return NULL; - } - - if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { - wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, - MAC2STR(dpp_pkex_peer_mac_override)); - peer_mac = dpp_pkex_peer_mac_override; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); - - attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS, - &attr_status_len); - if (!attr_status || attr_status_len != 1) { - dpp_pkex_fail(pkex, "No DPP Status attribute"); - return NULL; - } - wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]); - - if (attr_status[0] == DPP_STATUS_BAD_GROUP) { - attr_group = dpp_get_attr(buf, buflen, - DPP_ATTR_FINITE_CYCLIC_GROUP, - &attr_group_len); - if (attr_group && attr_group_len == 2) { - wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Peer indicated mismatching PKEX group - proposed %u", - WPA_GET_LE16(attr_group)); - return NULL; - } - } - - if (attr_status[0] != DPP_STATUS_OK) { - dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)"); - return NULL; - } - - attr_id_len = 0; - attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER, - &attr_id_len); - if (!dpp_pkex_identifier_match(attr_id, attr_id_len, - pkex->identifier)) { - dpp_pkex_fail(pkex, "PKEX code identifier mismatch"); - return NULL; - } - - /* N in Encrypted Key attribute */ - attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY, - &attr_key_len); - if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) { - dpp_pkex_fail(pkex, "Missing Encrypted Key attribute"); - return NULL; - } - - /* Qr = H(MAC-Responder | [identifier |] code) * Pr */ - bnctx = BN_CTX_new(); - if (!bnctx) - goto fail; - Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code, - pkex->identifier, bnctx, &group); - if (!Qr) - goto fail; - - /* Y' = N - Qr */ - Y = EC_POINT_new(group); - N = EC_POINT_new(group); - Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL); - Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL); - if (!Y || !N || !Nx || !Ny || - EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 || - EC_POINT_is_at_infinity(group, N) || - !EC_POINT_is_on_curve(group, N, bnctx) || - EC_POINT_invert(group, Qr, bnctx) != 1 || - EC_POINT_add(group, Y, N, Qr, bnctx) != 1 || - EC_POINT_is_at_infinity(group, Y) || - !EC_POINT_is_on_curve(group, Y, bnctx)) { - dpp_pkex_fail(pkex, "Invalid Encrypted Key value"); - pkex->t++; - goto fail; - } - dpp_debug_print_point("DPP: N", group, N); - dpp_debug_print_point("DPP: Y'", group, Y); - - pkex->exchange_done = 1; - - /* ECDH: J = a * Y’ */ - Y_ec = EC_KEY_new(); - if (!Y_ec || - EC_KEY_set_group(Y_ec, group) != 1 || - EC_KEY_set_public_key(Y_ec, Y) != 1) - goto fail; - pkex->y = EVP_PKEY_new(); - if (!pkex->y || - EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1) - goto fail; - if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", - Jx, Jx_len); - - /* u = HMAC(J.x, MAC-Initiator | A.x | Y’.x | X.x ) */ - A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0); - Y_pub = dpp_get_pubkey_point(pkex->y, 0); - X_pub = dpp_get_pubkey_point(pkex->x, 0); - if (!A_pub || !Y_pub || !X_pub) - goto fail; - addr[0] = pkex->own_mac; - len[0] = ETH_ALEN; - addr[1] = wpabuf_head(A_pub); - len[1] = wpabuf_len(A_pub) / 2; - addr[2] = wpabuf_head(Y_pub); - len[2] = wpabuf_len(Y_pub) / 2; - addr[3] = wpabuf_head(X_pub); - len[3] = wpabuf_len(X_pub) / 2; - if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len); - - /* K = x * Y’ */ - if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", - Kx, Kx_len); - - /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) - */ - res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac, - pkex->Mx, curve->prime_len, - attr_key /* N.x */, attr_key_len / 2, - pkex->code, Kx, Kx_len, - pkex->z, curve->hash_len); - os_memset(Kx, 0, Kx_len); - if (res < 0) - goto fail; - - msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u); - if (!msg) - goto fail; - -out: - wpabuf_free(A_pub); - wpabuf_free(X_pub); - wpabuf_free(Y_pub); - EC_POINT_free(Qr); - EC_POINT_free(Y); - EC_POINT_free(N); - BN_free(Nx); - BN_free(Ny); - EC_KEY_free(Y_ec); - BN_CTX_free(bnctx); - EC_GROUP_free(group); - return msg; -fail: - wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed"); - goto out; -} - - -static struct wpabuf * -dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex, - const struct wpabuf *B_pub, const u8 *v) -{ - const struct dpp_curve_params *curve = pkex->own_bi->curve; - struct wpabuf *msg = NULL; - const u8 *addr[2]; - size_t len[2]; - u8 octet; - u8 *wrapped; - struct wpabuf *clear = NULL; - size_t clear_len, attr_len; - - /* {B, v [bootstrapping info]}z */ - clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; - clear = wpabuf_alloc(clear_len); - attr_len = 4 + clear_len + AES_BLOCK_SIZE; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len); - if (!clear || !msg) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); - goto skip_bootstrap_key; - } - if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); - wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); - wpabuf_put_le16(clear, 2 * curve->prime_len); - if (dpp_test_gen_invalid_key(clear, curve) < 0) - goto fail; - goto skip_bootstrap_key; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* B in Bootstrap Key attribute */ - wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); - wpabuf_put_le16(clear, wpabuf_len(B_pub)); - wpabuf_put_buf(clear, B_pub); - -#ifdef CONFIG_TESTING_OPTIONS -skip_bootstrap_key: - if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag"); - goto skip_r_auth_tag; - } - if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch"); - wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); - wpabuf_put_le16(clear, curve->hash_len); - wpabuf_put_data(clear, v, curve->hash_len - 1); - wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01); - goto skip_r_auth_tag; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* v in R-Auth tag attribute */ - wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); - wpabuf_put_le16(clear, curve->hash_len); - wpabuf_put_data(clear, v, curve->hash_len); - -#ifdef CONFIG_TESTING_OPTIONS -skip_r_auth_tag: - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); - goto skip_wrapped_data; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = DPP_HDR_LEN; - octet = 1; - addr[1] = &octet; - len[1] = sizeof(octet); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); - wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); - - wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); - if (aes_siv_encrypt(pkex->z, curve->hash_len, - wpabuf_head(clear), wpabuf_len(clear), - 2, addr, len, wrapped) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - -out: - wpabuf_free(clear); - return msg; - -fail: - wpabuf_free(msg); - msg = NULL; - goto out; -} - - -struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex, - const u8 *hdr, - const u8 *buf, size_t buflen) -{ - const struct dpp_curve_params *curve = pkex->own_bi->curve; - size_t Jx_len, Lx_len; - u8 Jx[DPP_MAX_SHARED_SECRET_LEN]; - u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; - const u8 *wrapped_data, *b_key, *peer_u; - u16 wrapped_data_len, b_key_len, peer_u_len = 0; - const u8 *addr[4]; - size_t len[4]; - u8 octet; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; - struct wpabuf *B_pub = NULL; - u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN]; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at PKEX CR Request"); - pkex->failed = 1; - return NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!pkex->exchange_done || pkex->failed || - pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator) - goto fail; - - wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - dpp_pkex_fail(pkex, - "Missing or invalid required Wrapped Data attribute"); - goto fail; - } - - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - octet = 0; - addr[1] = &octet; - len[1] = sizeof(octet); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - if (aes_siv_decrypt(pkex->z, curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_pkex_fail(pkex, - "AES-SIV decryption failed - possible PKEX code mismatch"); - pkex->failed = 1; - pkex->t++; - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); - goto fail; - } - - b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, - &b_key_len); - if (!b_key || b_key_len != 2 * curve->prime_len) { - dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); - goto fail; - } - pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, - b_key_len); - if (!pkex->peer_bootstrap_key) { - dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); - goto fail; - } - dpp_debug_print_key("DPP: Peer bootstrap public key", - pkex->peer_bootstrap_key); - - /* ECDH: J' = y * A' */ - if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", - Jx, Jx_len); - - /* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */ - A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0); - Y_pub = dpp_get_pubkey_point(pkex->y, 0); - X_pub = dpp_get_pubkey_point(pkex->x, 0); - if (!A_pub || !Y_pub || !X_pub) - goto fail; - addr[0] = pkex->peer_mac; - len[0] = ETH_ALEN; - addr[1] = wpabuf_head(A_pub); - len[1] = wpabuf_len(A_pub) / 2; - addr[2] = wpabuf_head(Y_pub); - len[2] = wpabuf_len(Y_pub) / 2; - addr[3] = wpabuf_head(X_pub); - len[3] = wpabuf_len(X_pub) / 2; - if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0) - goto fail; - - peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, - &peer_u_len); - if (!peer_u || peer_u_len != curve->hash_len || - os_memcmp(peer_u, u, curve->hash_len) != 0) { - dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found"); - wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'", - u, curve->hash_len); - wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len); - pkex->t++; - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received"); - - /* ECDH: L = b * X' */ - if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", - Lx, Lx_len); - - /* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */ - B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0); - if (!B_pub) - goto fail; - addr[0] = pkex->own_mac; - len[0] = ETH_ALEN; - addr[1] = wpabuf_head(B_pub); - len[1] = wpabuf_len(B_pub) / 2; - addr[2] = wpabuf_head(X_pub); - len[2] = wpabuf_len(X_pub) / 2; - addr[3] = wpabuf_head(Y_pub); - len[3] = wpabuf_len(Y_pub) / 2; - if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len); - - msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v); - if (!msg) - goto fail; - -out: - os_free(unwrapped); - wpabuf_free(A_pub); - wpabuf_free(B_pub); - wpabuf_free(X_pub); - wpabuf_free(Y_pub); - return msg; -fail: - wpa_printf(MSG_DEBUG, - "DPP: PKEX Commit-Reveal Request processing failed"); - goto out; -} - - -int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr, - const u8 *buf, size_t buflen) -{ - const struct dpp_curve_params *curve = pkex->own_bi->curve; - const u8 *wrapped_data, *b_key, *peer_v; - u16 wrapped_data_len, b_key_len, peer_v_len = 0; - const u8 *addr[4]; - size_t len[4]; - u8 octet; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - int ret = -1; - u8 v[DPP_MAX_HASH_LEN]; - size_t Lx_len; - u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; - struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at PKEX CR Response"); - pkex->failed = 1; - goto fail; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!pkex->exchange_done || pkex->failed || - pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) - goto fail; - - wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - dpp_pkex_fail(pkex, - "Missing or invalid required Wrapped Data attribute"); - goto fail; - } - - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - octet = 1; - addr[1] = &octet; - len[1] = sizeof(octet); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - if (aes_siv_decrypt(pkex->z, curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_pkex_fail(pkex, - "AES-SIV decryption failed - possible PKEX code mismatch"); - pkex->t++; - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); - goto fail; - } - - b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, - &b_key_len); - if (!b_key || b_key_len != 2 * curve->prime_len) { - dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); - goto fail; - } - pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, - b_key_len); - if (!pkex->peer_bootstrap_key) { - dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); - goto fail; - } - dpp_debug_print_key("DPP: Peer bootstrap public key", - pkex->peer_bootstrap_key); - - /* ECDH: L' = x * B' */ - if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", - Lx, Lx_len); - - /* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */ - B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0); - X_pub = dpp_get_pubkey_point(pkex->x, 0); - Y_pub = dpp_get_pubkey_point(pkex->y, 0); - if (!B_pub || !X_pub || !Y_pub) - goto fail; - addr[0] = pkex->peer_mac; - len[0] = ETH_ALEN; - addr[1] = wpabuf_head(B_pub); - len[1] = wpabuf_len(B_pub) / 2; - addr[2] = wpabuf_head(X_pub); - len[2] = wpabuf_len(X_pub) / 2; - addr[3] = wpabuf_head(Y_pub); - len[3] = wpabuf_len(Y_pub) / 2; - if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0) - goto fail; - - peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG, - &peer_v_len); - if (!peer_v || peer_v_len != curve->hash_len || - os_memcmp(peer_v, v, curve->hash_len) != 0) { - dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found"); - wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'", - v, curve->hash_len); - wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len); - pkex->t++; - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received"); - - ret = 0; -out: - wpabuf_free(B_pub); - wpabuf_free(X_pub); - wpabuf_free(Y_pub); - os_free(unwrapped); - return ret; -fail: - goto out; -} - - -void dpp_pkex_free(struct dpp_pkex *pkex) -{ - if (!pkex) - return; - - os_free(pkex->identifier); - os_free(pkex->code); - EVP_PKEY_free(pkex->x); - EVP_PKEY_free(pkex->y); - EVP_PKEY_free(pkex->peer_bootstrap_key); - wpabuf_free(pkex->exchange_req); - wpabuf_free(pkex->exchange_resp); - os_free(pkex); -} - - -static unsigned int dpp_next_id(struct dpp_global *dpp) +unsigned int dpp_next_id(struct dpp_global *dpp) { struct dpp_bootstrap_info *bi; unsigned int max_id = 0; @@ -8085,33 +6813,6 @@ int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id) } -struct dpp_bootstrap_info * -dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer, - unsigned int freq) -{ - struct dpp_bootstrap_info *bi; - - bi = os_zalloc(sizeof(*bi)); - if (!bi) - return NULL; - bi->id = dpp_next_id(dpp); - bi->type = DPP_BOOTSTRAP_PKEX; - os_memcpy(bi->mac_addr, peer, ETH_ALEN); - bi->num_freq = 1; - bi->freq[0] = freq; - bi->curve = pkex->own_bi->curve; - bi->pubkey = pkex->peer_bootstrap_key; - pkex->peer_bootstrap_key = NULL; - if (dpp_bootstrap_key_hash(bi) < 0) { - dpp_bootstrap_info_free(bi); - return NULL; - } - dpp_pkex_free(pkex); - dl_list_add(&dpp->bootstrap, &bi->list); - return bi; -} - - const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id) { struct dpp_bootstrap_info *bi; diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index a0af5f9fc..fa7c922bf 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -12,6 +12,25 @@ #ifdef CONFIG_DPP +struct dpp_global { + void *msg_ctx; + struct dl_list bootstrap; /* struct dpp_bootstrap_info */ + struct dl_list configurator; /* struct dpp_configurator */ +#ifdef CONFIG_DPP2 + struct dl_list controllers; /* struct dpp_relay_controller */ + struct dpp_controller *controller; + struct dl_list tcp_init; /* struct dpp_connection */ + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); +#endif /* CONFIG_DPP2 */ +}; + +/* dpp.c */ + +void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status); +unsigned int dpp_next_id(struct dpp_global *dpp); + /* dpp_crypto.c */ struct dpp_signed_connector_info { diff --git a/src/common/dpp_pkex.c b/src/common/dpp_pkex.c new file mode 100644 index 000000000..807ab7d0a --- /dev/null +++ b/src/common/dpp_pkex.c @@ -0,0 +1,1324 @@ +/* + * DPP PKEX functionality + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include +#include + +#include "utils/common.h" +#include "common/wpa_ctrl.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "crypto/crypto.h" +#include "dpp.h" +#include "dpp_i.h" + + +#ifdef CONFIG_TESTING_OPTIONS +u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; +u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; +u8 dpp_pkex_ephemeral_key_override[600]; +size_t dpp_pkex_ephemeral_key_override_len = 0; +#endif /* CONFIG_TESTING_OPTIONS */ + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +/* Compatibility wrappers for older versions. */ + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + +#endif + + +static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex) +{ + const EC_KEY *X_ec; + const EC_POINT *X_point; + BN_CTX *bnctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *Qi = NULL, *M = NULL; + struct wpabuf *M_buf = NULL; + BIGNUM *Mx = NULL, *My = NULL; + struct wpabuf *msg = NULL; + size_t attr_len; + const struct dpp_curve_params *curve = pkex->own_bi->curve; + + wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request"); + + /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ + bnctx = BN_CTX_new(); + if (!bnctx) + goto fail; + Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code, + pkex->identifier, bnctx, &group); + if (!Qi) + goto fail; + + /* Generate a random ephemeral keypair x/X */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_pkex_ephemeral_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override ephemeral key x/X"); + pkex->x = dpp_set_keypair(&tmp_curve, + dpp_pkex_ephemeral_key_override, + dpp_pkex_ephemeral_key_override_len); + } else { + pkex->x = dpp_gen_keypair(curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + pkex->x = dpp_gen_keypair(curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!pkex->x) + goto fail; + + /* M = X + Qi */ + X_ec = EVP_PKEY_get0_EC_KEY(pkex->x); + if (!X_ec) + goto fail; + X_point = EC_KEY_get0_public_key(X_ec); + if (!X_point) + goto fail; + dpp_debug_print_point("DPP: X", group, X_point); + M = EC_POINT_new(group); + Mx = BN_new(); + My = BN_new(); + if (!M || !Mx || !My || + EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1) + goto fail; + dpp_debug_print_point("DPP: M", group, M); + + /* Initiator -> Responder: group, [identifier,] M */ + attr_len = 4 + 2; + if (pkex->identifier) + attr_len += 4 + os_strlen(pkex->identifier); + attr_len += 4 + 2 * curve->prime_len; + msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len); + if (!msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group"); + goto skip_finite_cyclic_group; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Finite Cyclic Group attribute */ + wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); + wpabuf_put_le16(msg, 2); + wpabuf_put_le16(msg, curve->ike_group); + +#ifdef CONFIG_TESTING_OPTIONS +skip_finite_cyclic_group: +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Code Identifier attribute */ + if (pkex->identifier) { + wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER); + wpabuf_put_le16(msg, os_strlen(pkex->identifier)); + wpabuf_put_str(msg, pkex->identifier); + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key"); + goto out; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* M in Encrypted Key attribute */ + wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY); + wpabuf_put_le16(msg, 2 * curve->prime_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key"); + if (dpp_test_gen_invalid_key(msg, curve) < 0) + goto fail; + goto out; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0 || + dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 || + dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0) + goto fail; + +out: + wpabuf_free(M_buf); + EC_POINT_free(M); + EC_POINT_free(Qi); + BN_clear_free(Mx); + BN_clear_free(My); + BN_CTX_free(bnctx); + EC_GROUP_free(group); + return msg; +fail: + wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request"); + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt) +{ + wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); +} + + +struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi, + const u8 *own_mac, + const char *identifier, + const char *code) +{ + struct dpp_pkex *pkex; + +#ifdef CONFIG_TESTING_OPTIONS + if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) { + wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR, + MAC2STR(dpp_pkex_own_mac_override)); + own_mac = dpp_pkex_own_mac_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + pkex = os_zalloc(sizeof(*pkex)); + if (!pkex) + return NULL; + pkex->msg_ctx = msg_ctx; + pkex->initiator = 1; + pkex->own_bi = bi; + os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); + if (identifier) { + pkex->identifier = os_strdup(identifier); + if (!pkex->identifier) + goto fail; + } + pkex->code = os_strdup(code); + if (!pkex->code) + goto fail; + pkex->exchange_req = dpp_pkex_build_exchange_req(pkex); + if (!pkex->exchange_req) + goto fail; + return pkex; +fail: + dpp_pkex_free(pkex); + return NULL; +} + + +static struct wpabuf * +dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex, + enum dpp_status_error status, + const BIGNUM *Nx, const BIGNUM *Ny) +{ + struct wpabuf *msg = NULL; + size_t attr_len; + const struct dpp_curve_params *curve = pkex->own_bi->curve; + + /* Initiator -> Responder: DPP Status, [identifier,] N */ + attr_len = 4 + 1; + if (pkex->identifier) + attr_len += 4 + os_strlen(pkex->identifier); + attr_len += 4 + 2 * curve->prime_len; + msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len); + if (!msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + goto skip_status; + } + + if (dpp_test == DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 255; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* DPP Status */ + dpp_build_attr_status(msg, status); + +#ifdef CONFIG_TESTING_OPTIONS +skip_status: +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Code Identifier attribute */ + if (pkex->identifier) { + wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER); + wpabuf_put_le16(msg, os_strlen(pkex->identifier)); + wpabuf_put_str(msg, pkex->identifier); + } + + if (status != DPP_STATUS_OK) + goto skip_encrypted_key; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key"); + goto skip_encrypted_key; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* N in Encrypted Key attribute */ + wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY); + wpabuf_put_le16(msg, 2 * curve->prime_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key"); + if (dpp_test_gen_invalid_key(msg, curve) < 0) + goto fail; + goto skip_encrypted_key; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (dpp_bn2bin_pad(Nx, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0 || + dpp_bn2bin_pad(Nx, pkex->Nx, curve->prime_len) < 0 || + dpp_bn2bin_pad(Ny, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0) + goto fail; + +skip_encrypted_key: + if (status == DPP_STATUS_BAD_GROUP) { + /* Finite Cyclic Group attribute */ + wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); + wpabuf_put_le16(msg, 2); + wpabuf_put_le16(msg, curve->ike_group); + } + + return msg; +fail: + wpabuf_free(msg); + return NULL; +} + + +static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len, + const char *identifier) +{ + if (!attr_id && identifier) { + wpa_printf(MSG_DEBUG, + "DPP: No PKEX code identifier received, but expected one"); + return 0; + } + + if (attr_id && !identifier) { + wpa_printf(MSG_DEBUG, + "DPP: PKEX code identifier received, but not expecting one"); + return 0; + } + + if (attr_id && identifier && + (os_strlen(identifier) != attr_id_len || + os_memcmp(identifier, attr_id, attr_id_len) != 0)) { + wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch"); + return 0; + } + + return 1; +} + + +struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx, + struct dpp_bootstrap_info *bi, + const u8 *own_mac, + const u8 *peer_mac, + const char *identifier, + const char *code, + const u8 *buf, size_t len) +{ + const u8 *attr_group, *attr_id, *attr_key; + u16 attr_group_len, attr_id_len, attr_key_len; + const struct dpp_curve_params *curve = bi->curve; + u16 ike_group; + struct dpp_pkex *pkex = NULL; + EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL; + BN_CTX *bnctx = NULL; + EC_GROUP *group = NULL; + BIGNUM *Mx = NULL, *My = NULL; + const EC_KEY *Y_ec; + EC_KEY *X_ec = NULL; + const EC_POINT *Y_point; + BIGNUM *Nx = NULL, *Ny = NULL; + u8 Kx[DPP_MAX_SHARED_SECRET_LEN]; + size_t Kx_len; + int res; + + if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "PKEX counter t limit reached - ignore message"); + return NULL; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { + wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, + MAC2STR(dpp_pkex_peer_mac_override)); + peer_mac = dpp_pkex_peer_mac_override; + } + if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) { + wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR, + MAC2STR(dpp_pkex_own_mac_override)); + own_mac = dpp_pkex_own_mac_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + attr_id_len = 0; + attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER, + &attr_id_len); + if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier)) + return NULL; + + attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &attr_group_len); + if (!attr_group || attr_group_len != 2) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid Finite Cyclic Group attribute"); + return NULL; + } + ike_group = WPA_GET_LE16(attr_group); + if (ike_group != curve->ike_group) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Mismatching PKEX curve: peer=%u own=%u", + ike_group, curve->ike_group); + pkex = os_zalloc(sizeof(*pkex)); + if (!pkex) + goto fail; + pkex->own_bi = bi; + pkex->failed = 1; + pkex->exchange_resp = dpp_pkex_build_exchange_resp( + pkex, DPP_STATUS_BAD_GROUP, NULL, NULL); + if (!pkex->exchange_resp) + goto fail; + return pkex; + } + + /* M in Encrypted Key attribute */ + attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY, + &attr_key_len); + if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 || + attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing Encrypted Key attribute"); + return NULL; + } + + /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ + bnctx = BN_CTX_new(); + if (!bnctx) + goto fail; + Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx, + &group); + if (!Qi) + goto fail; + + /* X' = M - Qi */ + X = EC_POINT_new(group); + M = EC_POINT_new(group); + Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL); + My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL); + if (!X || !M || !Mx || !My || + EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 || + EC_POINT_is_at_infinity(group, M) || + !EC_POINT_is_on_curve(group, M, bnctx) || + EC_POINT_invert(group, Qi, bnctx) != 1 || + EC_POINT_add(group, X, M, Qi, bnctx) != 1 || + EC_POINT_is_at_infinity(group, X) || + !EC_POINT_is_on_curve(group, X, bnctx)) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Invalid Encrypted Key value"); + bi->pkex_t++; + goto fail; + } + dpp_debug_print_point("DPP: M", group, M); + dpp_debug_print_point("DPP: X'", group, X); + + pkex = os_zalloc(sizeof(*pkex)); + if (!pkex) + goto fail; + pkex->t = bi->pkex_t; + pkex->msg_ctx = msg_ctx; + pkex->own_bi = bi; + os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); + os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); + if (identifier) { + pkex->identifier = os_strdup(identifier); + if (!pkex->identifier) + goto fail; + } + pkex->code = os_strdup(code); + if (!pkex->code) + goto fail; + + os_memcpy(pkex->Mx, attr_key, attr_key_len / 2); + + X_ec = EC_KEY_new(); + if (!X_ec || + EC_KEY_set_group(X_ec, group) != 1 || + EC_KEY_set_public_key(X_ec, X) != 1) + goto fail; + pkex->x = EVP_PKEY_new(); + if (!pkex->x || + EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1) + goto fail; + + /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ + Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL); + if (!Qr) + goto fail; + + /* Generate a random ephemeral keypair y/Y */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_pkex_ephemeral_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override ephemeral key y/Y"); + pkex->y = dpp_set_keypair(&tmp_curve, + dpp_pkex_ephemeral_key_override, + dpp_pkex_ephemeral_key_override_len); + } else { + pkex->y = dpp_gen_keypair(curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + pkex->y = dpp_gen_keypair(curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!pkex->y) + goto fail; + + /* N = Y + Qr */ + Y_ec = EVP_PKEY_get0_EC_KEY(pkex->y); + if (!Y_ec) + goto fail; + Y_point = EC_KEY_get0_public_key(Y_ec); + if (!Y_point) + goto fail; + dpp_debug_print_point("DPP: Y", group, Y_point); + N = EC_POINT_new(group); + Nx = BN_new(); + Ny = BN_new(); + if (!N || !Nx || !Ny || + EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1) + goto fail; + dpp_debug_print_point("DPP: N", group, N); + + pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK, + Nx, Ny); + if (!pkex->exchange_resp) + goto fail; + + /* K = y * X' */ + if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", + Kx, Kx_len); + + /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) + */ + res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac, + pkex->Mx, curve->prime_len, + pkex->Nx, curve->prime_len, pkex->code, + Kx, Kx_len, pkex->z, curve->hash_len); + os_memset(Kx, 0, Kx_len); + if (res < 0) + goto fail; + + pkex->exchange_done = 1; + +out: + BN_CTX_free(bnctx); + EC_POINT_free(Qi); + EC_POINT_free(Qr); + BN_free(Mx); + BN_free(My); + BN_free(Nx); + BN_free(Ny); + EC_POINT_free(M); + EC_POINT_free(N); + EC_POINT_free(X); + EC_KEY_free(X_ec); + EC_GROUP_free(group); + return pkex; +fail: + wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed"); + dpp_pkex_free(pkex); + pkex = NULL; + goto out; +} + + +static struct wpabuf * +dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex, + const struct wpabuf *A_pub, const u8 *u) +{ + const struct dpp_curve_params *curve = pkex->own_bi->curve; + struct wpabuf *msg = NULL; + size_t clear_len, attr_len; + struct wpabuf *clear = NULL; + u8 *wrapped; + u8 octet; + const u8 *addr[2]; + size_t len[2]; + + /* {A, u, [bootstrapping info]}z */ + clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; + clear = wpabuf_alloc(clear_len); + attr_len = 4 + clear_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len); + if (!clear || !msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); + goto skip_bootstrap_key; + } + if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); + wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); + wpabuf_put_le16(clear, 2 * curve->prime_len); + if (dpp_test_gen_invalid_key(clear, curve) < 0) + goto fail; + goto skip_bootstrap_key; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* A in Bootstrap Key attribute */ + wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); + wpabuf_put_le16(clear, wpabuf_len(A_pub)); + wpabuf_put_buf(clear, A_pub); + +#ifdef CONFIG_TESTING_OPTIONS +skip_bootstrap_key: + if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag"); + goto skip_i_auth_tag; + } + if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch"); + wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); + wpabuf_put_le16(clear, curve->hash_len); + wpabuf_put_data(clear, u, curve->hash_len - 1); + wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01); + goto skip_i_auth_tag; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* u in I-Auth tag attribute */ + wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); + wpabuf_put_le16(clear, curve->hash_len); + wpabuf_put_data(clear, u, curve->hash_len); + +#ifdef CONFIG_TESTING_OPTIONS +skip_i_auth_tag: + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = DPP_HDR_LEN; + octet = 0; + addr[1] = &octet; + len[1] = sizeof(octet); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(pkex->z, curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 2, addr, len, wrapped) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + +out: + wpabuf_free(clear); + return msg; + +fail: + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex, + const u8 *peer_mac, + const u8 *buf, size_t buflen) +{ + const u8 *attr_status, *attr_id, *attr_key, *attr_group; + u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len; + EC_GROUP *group = NULL; + BN_CTX *bnctx = NULL; + struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; + const struct dpp_curve_params *curve = pkex->own_bi->curve; + EC_POINT *Qr = NULL, *Y = NULL, *N = NULL; + BIGNUM *Nx = NULL, *Ny = NULL; + EC_KEY *Y_ec = NULL; + size_t Jx_len, Kx_len; + u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN]; + const u8 *addr[4]; + size_t len[4]; + u8 u[DPP_MAX_HASH_LEN]; + int res; + + if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) + return NULL; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at PKEX Exchange Response"); + pkex->failed = 1; + return NULL; + } + + if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { + wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, + MAC2STR(dpp_pkex_peer_mac_override)); + peer_mac = dpp_pkex_peer_mac_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); + + attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS, + &attr_status_len); + if (!attr_status || attr_status_len != 1) { + dpp_pkex_fail(pkex, "No DPP Status attribute"); + return NULL; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]); + + if (attr_status[0] == DPP_STATUS_BAD_GROUP) { + attr_group = dpp_get_attr(buf, buflen, + DPP_ATTR_FINITE_CYCLIC_GROUP, + &attr_group_len); + if (attr_group && attr_group_len == 2) { + wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Peer indicated mismatching PKEX group - proposed %u", + WPA_GET_LE16(attr_group)); + return NULL; + } + } + + if (attr_status[0] != DPP_STATUS_OK) { + dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)"); + return NULL; + } + + attr_id_len = 0; + attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER, + &attr_id_len); + if (!dpp_pkex_identifier_match(attr_id, attr_id_len, + pkex->identifier)) { + dpp_pkex_fail(pkex, "PKEX code identifier mismatch"); + return NULL; + } + + /* N in Encrypted Key attribute */ + attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY, + &attr_key_len); + if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) { + dpp_pkex_fail(pkex, "Missing Encrypted Key attribute"); + return NULL; + } + + /* Qr = H(MAC-Responder | [identifier |] code) * Pr */ + bnctx = BN_CTX_new(); + if (!bnctx) + goto fail; + Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code, + pkex->identifier, bnctx, &group); + if (!Qr) + goto fail; + + /* Y' = N - Qr */ + Y = EC_POINT_new(group); + N = EC_POINT_new(group); + Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL); + Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL); + if (!Y || !N || !Nx || !Ny || + EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 || + EC_POINT_is_at_infinity(group, N) || + !EC_POINT_is_on_curve(group, N, bnctx) || + EC_POINT_invert(group, Qr, bnctx) != 1 || + EC_POINT_add(group, Y, N, Qr, bnctx) != 1 || + EC_POINT_is_at_infinity(group, Y) || + !EC_POINT_is_on_curve(group, Y, bnctx)) { + dpp_pkex_fail(pkex, "Invalid Encrypted Key value"); + pkex->t++; + goto fail; + } + dpp_debug_print_point("DPP: N", group, N); + dpp_debug_print_point("DPP: Y'", group, Y); + + pkex->exchange_done = 1; + + /* ECDH: J = a * Y' */ + Y_ec = EC_KEY_new(); + if (!Y_ec || + EC_KEY_set_group(Y_ec, group) != 1 || + EC_KEY_set_public_key(Y_ec, Y) != 1) + goto fail; + pkex->y = EVP_PKEY_new(); + if (!pkex->y || + EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1) + goto fail; + if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", + Jx, Jx_len); + + /* u = HMAC(J.x, MAC-Initiator | A.x | Y'.x | X.x) */ + A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0); + Y_pub = dpp_get_pubkey_point(pkex->y, 0); + X_pub = dpp_get_pubkey_point(pkex->x, 0); + if (!A_pub || !Y_pub || !X_pub) + goto fail; + addr[0] = pkex->own_mac; + len[0] = ETH_ALEN; + addr[1] = wpabuf_head(A_pub); + len[1] = wpabuf_len(A_pub) / 2; + addr[2] = wpabuf_head(Y_pub); + len[2] = wpabuf_len(Y_pub) / 2; + addr[3] = wpabuf_head(X_pub); + len[3] = wpabuf_len(X_pub) / 2; + if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len); + + /* K = x * Y' */ + if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", + Kx, Kx_len); + + /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) + */ + res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac, + pkex->Mx, curve->prime_len, + attr_key /* N.x */, attr_key_len / 2, + pkex->code, Kx, Kx_len, + pkex->z, curve->hash_len); + os_memset(Kx, 0, Kx_len); + if (res < 0) + goto fail; + + msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u); + if (!msg) + goto fail; + +out: + wpabuf_free(A_pub); + wpabuf_free(X_pub); + wpabuf_free(Y_pub); + EC_POINT_free(Qr); + EC_POINT_free(Y); + EC_POINT_free(N); + BN_free(Nx); + BN_free(Ny); + EC_KEY_free(Y_ec); + BN_CTX_free(bnctx); + EC_GROUP_free(group); + return msg; +fail: + wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed"); + goto out; +} + + +static struct wpabuf * +dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex, + const struct wpabuf *B_pub, const u8 *v) +{ + const struct dpp_curve_params *curve = pkex->own_bi->curve; + struct wpabuf *msg = NULL; + const u8 *addr[2]; + size_t len[2]; + u8 octet; + u8 *wrapped; + struct wpabuf *clear = NULL; + size_t clear_len, attr_len; + + /* {B, v [bootstrapping info]}z */ + clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; + clear = wpabuf_alloc(clear_len); + attr_len = 4 + clear_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len); + if (!clear || !msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); + goto skip_bootstrap_key; + } + if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); + wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); + wpabuf_put_le16(clear, 2 * curve->prime_len); + if (dpp_test_gen_invalid_key(clear, curve) < 0) + goto fail; + goto skip_bootstrap_key; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* B in Bootstrap Key attribute */ + wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); + wpabuf_put_le16(clear, wpabuf_len(B_pub)); + wpabuf_put_buf(clear, B_pub); + +#ifdef CONFIG_TESTING_OPTIONS +skip_bootstrap_key: + if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag"); + goto skip_r_auth_tag; + } + if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch"); + wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); + wpabuf_put_le16(clear, curve->hash_len); + wpabuf_put_data(clear, v, curve->hash_len - 1); + wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01); + goto skip_r_auth_tag; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* v in R-Auth tag attribute */ + wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); + wpabuf_put_le16(clear, curve->hash_len); + wpabuf_put_data(clear, v, curve->hash_len); + +#ifdef CONFIG_TESTING_OPTIONS +skip_r_auth_tag: + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = DPP_HDR_LEN; + octet = 1; + addr[1] = &octet; + len[1] = sizeof(octet); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(pkex->z, curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 2, addr, len, wrapped) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + +out: + wpabuf_free(clear); + return msg; + +fail: + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex, + const u8 *hdr, + const u8 *buf, size_t buflen) +{ + const struct dpp_curve_params *curve = pkex->own_bi->curve; + size_t Jx_len, Lx_len; + u8 Jx[DPP_MAX_SHARED_SECRET_LEN]; + u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; + const u8 *wrapped_data, *b_key, *peer_u; + u16 wrapped_data_len, b_key_len, peer_u_len = 0; + const u8 *addr[4]; + size_t len[4]; + u8 octet; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; + struct wpabuf *B_pub = NULL; + u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN]; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at PKEX CR Request"); + pkex->failed = 1; + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!pkex->exchange_done || pkex->failed || + pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator) + goto fail; + + wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_pkex_fail(pkex, + "Missing or invalid required Wrapped Data attribute"); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + octet = 0; + addr[1] = &octet; + len[1] = sizeof(octet); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + if (aes_siv_decrypt(pkex->z, curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_pkex_fail(pkex, + "AES-SIV decryption failed - possible PKEX code mismatch"); + pkex->failed = 1; + pkex->t++; + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); + goto fail; + } + + b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, + &b_key_len); + if (!b_key || b_key_len != 2 * curve->prime_len) { + dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); + goto fail; + } + pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, + b_key_len); + if (!pkex->peer_bootstrap_key) { + dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); + goto fail; + } + dpp_debug_print_key("DPP: Peer bootstrap public key", + pkex->peer_bootstrap_key); + + /* ECDH: J' = y * A' */ + if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", + Jx, Jx_len); + + /* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */ + A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0); + Y_pub = dpp_get_pubkey_point(pkex->y, 0); + X_pub = dpp_get_pubkey_point(pkex->x, 0); + if (!A_pub || !Y_pub || !X_pub) + goto fail; + addr[0] = pkex->peer_mac; + len[0] = ETH_ALEN; + addr[1] = wpabuf_head(A_pub); + len[1] = wpabuf_len(A_pub) / 2; + addr[2] = wpabuf_head(Y_pub); + len[2] = wpabuf_len(Y_pub) / 2; + addr[3] = wpabuf_head(X_pub); + len[3] = wpabuf_len(X_pub) / 2; + if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0) + goto fail; + + peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, + &peer_u_len); + if (!peer_u || peer_u_len != curve->hash_len || + os_memcmp(peer_u, u, curve->hash_len) != 0) { + dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found"); + wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'", + u, curve->hash_len); + wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len); + pkex->t++; + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received"); + + /* ECDH: L = b * X' */ + if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", + Lx, Lx_len); + + /* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */ + B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0); + if (!B_pub) + goto fail; + addr[0] = pkex->own_mac; + len[0] = ETH_ALEN; + addr[1] = wpabuf_head(B_pub); + len[1] = wpabuf_len(B_pub) / 2; + addr[2] = wpabuf_head(X_pub); + len[2] = wpabuf_len(X_pub) / 2; + addr[3] = wpabuf_head(Y_pub); + len[3] = wpabuf_len(Y_pub) / 2; + if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len); + + msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v); + if (!msg) + goto fail; + +out: + os_free(unwrapped); + wpabuf_free(A_pub); + wpabuf_free(B_pub); + wpabuf_free(X_pub); + wpabuf_free(Y_pub); + return msg; +fail: + wpa_printf(MSG_DEBUG, + "DPP: PKEX Commit-Reveal Request processing failed"); + goto out; +} + + +int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr, + const u8 *buf, size_t buflen) +{ + const struct dpp_curve_params *curve = pkex->own_bi->curve; + const u8 *wrapped_data, *b_key, *peer_v; + u16 wrapped_data_len, b_key_len, peer_v_len = 0; + const u8 *addr[4]; + size_t len[4]; + u8 octet; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + int ret = -1; + u8 v[DPP_MAX_HASH_LEN]; + size_t Lx_len; + u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; + struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at PKEX CR Response"); + pkex->failed = 1; + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!pkex->exchange_done || pkex->failed || + pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) + goto fail; + + wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_pkex_fail(pkex, + "Missing or invalid required Wrapped Data attribute"); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + octet = 1; + addr[1] = &octet; + len[1] = sizeof(octet); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + if (aes_siv_decrypt(pkex->z, curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_pkex_fail(pkex, + "AES-SIV decryption failed - possible PKEX code mismatch"); + pkex->t++; + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); + goto fail; + } + + b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, + &b_key_len); + if (!b_key || b_key_len != 2 * curve->prime_len) { + dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); + goto fail; + } + pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, + b_key_len); + if (!pkex->peer_bootstrap_key) { + dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); + goto fail; + } + dpp_debug_print_key("DPP: Peer bootstrap public key", + pkex->peer_bootstrap_key); + + /* ECDH: L' = x * B' */ + if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", + Lx, Lx_len); + + /* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */ + B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0); + X_pub = dpp_get_pubkey_point(pkex->x, 0); + Y_pub = dpp_get_pubkey_point(pkex->y, 0); + if (!B_pub || !X_pub || !Y_pub) + goto fail; + addr[0] = pkex->peer_mac; + len[0] = ETH_ALEN; + addr[1] = wpabuf_head(B_pub); + len[1] = wpabuf_len(B_pub) / 2; + addr[2] = wpabuf_head(X_pub); + len[2] = wpabuf_len(X_pub) / 2; + addr[3] = wpabuf_head(Y_pub); + len[3] = wpabuf_len(Y_pub) / 2; + if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0) + goto fail; + + peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG, + &peer_v_len); + if (!peer_v || peer_v_len != curve->hash_len || + os_memcmp(peer_v, v, curve->hash_len) != 0) { + dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found"); + wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'", + v, curve->hash_len); + wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len); + pkex->t++; + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received"); + + ret = 0; +out: + wpabuf_free(B_pub); + wpabuf_free(X_pub); + wpabuf_free(Y_pub); + os_free(unwrapped); + return ret; +fail: + goto out; +} + + +struct dpp_bootstrap_info * +dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer, + unsigned int freq) +{ + struct dpp_bootstrap_info *bi; + + bi = os_zalloc(sizeof(*bi)); + if (!bi) + return NULL; + bi->id = dpp_next_id(dpp); + bi->type = DPP_BOOTSTRAP_PKEX; + os_memcpy(bi->mac_addr, peer, ETH_ALEN); + bi->num_freq = 1; + bi->freq[0] = freq; + bi->curve = pkex->own_bi->curve; + bi->pubkey = pkex->peer_bootstrap_key; + pkex->peer_bootstrap_key = NULL; + if (dpp_bootstrap_key_hash(bi) < 0) { + dpp_bootstrap_info_free(bi); + return NULL; + } + dpp_pkex_free(pkex); + dl_list_add(&dpp->bootstrap, &bi->list); + return bi; +} + + +void dpp_pkex_free(struct dpp_pkex *pkex) +{ + if (!pkex) + return; + + os_free(pkex->identifier); + os_free(pkex->code); + EVP_PKEY_free(pkex->x); + EVP_PKEY_free(pkex->y); + EVP_PKEY_free(pkex->peer_bootstrap_key); + wpabuf_free(pkex->exchange_req); + wpabuf_free(pkex->exchange_resp); + os_free(pkex); +} diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index 1ed0c8941..e5788a833 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -22,6 +22,7 @@ OBJS += $(SRC)/crypto/sha512-kdf.o OBJS += $(SRC)/tls/asn1.o OBJS += $(SRC)/common/dpp.o OBJS += $(SRC)/common/dpp_crypto.o +OBJS += $(SRC)/common/dpp_pkex.o dpp-uri: dpp-uri.o $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 671535904..a589b2774 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -248,6 +248,7 @@ ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c OBJS += src/common/dpp_crypto.c +OBJS += src/common/dpp_pkex.c OBJS += dpp_supplicant.c NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 14e32eeab..441a7db1a 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -280,6 +280,7 @@ ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o OBJS += ../src/common/dpp_crypto.o +OBJS += ../src/common/dpp_pkex.o OBJS += dpp_supplicant.o NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y From 94a28a49400b2e31159a901f313fad2162458a7e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 9 May 2020 16:35:21 +0300 Subject: [PATCH 0468/1105] DPP: Move parsing of own connector into a helper function This can be used for reconfiguration as well. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 62 +++++++++++++++++++++++++++------------------- src/common/dpp_i.h | 1 + 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 1d6d488ad..9c2acef53 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -6473,6 +6473,40 @@ static int dpp_connector_match_groups(struct json_token *own_root, } +struct json_token * dpp_parse_own_connector(const char *own_connector) +{ + unsigned char *own_conn; + size_t own_conn_len; + const char *pos, *end; + struct json_token *own_root; + + pos = os_strchr(own_connector, '.'); + if (!pos) { + wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)"); + return NULL; + } + pos++; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)"); + return NULL; + } + own_conn = base64_url_decode(pos, end - pos, &own_conn_len); + if (!own_conn) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode own signedConnector JWS Payload"); + return NULL; + } + + own_root = json_parse((const char *) own_conn, own_conn_len); + os_free(own_conn); + if (!own_root) + wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector"); + + return own_root; +} + + enum dpp_status_error dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, const u8 *net_access_key, size_t net_access_key_len, @@ -6490,9 +6524,6 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, const unsigned char *p; EVP_PKEY *csign = NULL; char *signed_connector = NULL; - const char *pos, *end; - unsigned char *own_conn = NULL; - size_t own_conn_len; size_t Nx_len; u8 Nx[DPP_MAX_SHARED_SECRET_LEN]; @@ -6516,29 +6547,9 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, goto fail; } - pos = os_strchr(own_connector, '.'); - if (!pos) { - wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)"); + own_root = dpp_parse_own_connector(own_connector); + if (!own_root) goto fail; - } - pos++; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)"); - goto fail; - } - own_conn = base64_url_decode(pos, end - pos, &own_conn_len); - if (!own_conn) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode own signedConnector JWS Payload"); - goto fail; - } - - own_root = json_parse((const char *) own_conn, own_conn_len); - if (!own_root) { - wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector"); - goto fail; - } wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", peer_connector, peer_connector_len); @@ -6629,7 +6640,6 @@ fail: if (ret != DPP_STATUS_OK) os_memset(intro, 0, sizeof(*intro)); os_memset(Nx, 0, sizeof(Nx)); - os_free(own_conn); os_free(signed_connector); os_free(info.payload); EVP_PKEY_free(own_key); diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index fa7c922bf..1ac239f06 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -30,6 +30,7 @@ struct dpp_global { void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status); unsigned int dpp_next_id(struct dpp_global *dpp); +struct json_token * dpp_parse_own_connector(const char *own_connector); /* dpp_crypto.c */ From 94f73f90efb8dcb30bd7df1b0578f3370b2c4abb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 10 May 2020 13:41:51 +0300 Subject: [PATCH 0469/1105] DPP: Move signed connector checking into a helper function This can be reused for similar need with reconfiguration. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 24 ++---------------------- src/common/dpp_crypto.c | 33 +++++++++++++++++++++++++++++++++ src/common/dpp_i.h | 4 ++++ 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 9c2acef53..d2bf5cf92 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -6521,9 +6521,6 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, struct wpabuf *own_key_pub = NULL; const struct dpp_curve_params *curve, *own_curve; struct dpp_signed_connector_info info; - const unsigned char *p; - EVP_PKEY *csign = NULL; - char *signed_connector = NULL; size_t Nx_len; u8 Nx[DPP_MAX_SHARED_SECRET_LEN]; @@ -6532,14 +6529,6 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, if (expiry) *expiry = 0; - p = csign_key; - csign = d2i_PUBKEY(NULL, &p, csign_key_len); - if (!csign) { - wpa_printf(MSG_ERROR, - "DPP: Failed to parse local C-sign-key information"); - goto fail; - } - own_key = dpp_set_keypair(&own_curve, net_access_key, net_access_key_len); if (!own_key) { @@ -6551,15 +6540,8 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, if (!own_root) goto fail; - wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", - peer_connector, peer_connector_len); - signed_connector = os_malloc(peer_connector_len + 1); - if (!signed_connector) - goto fail; - os_memcpy(signed_connector, peer_connector, peer_connector_len); - signed_connector[peer_connector_len] = '\0'; - - res = dpp_process_signed_connector(&info, csign, signed_connector); + res = dpp_check_signed_connector(&info, csign_key, csign_key_len, + peer_connector, peer_connector_len); if (res != DPP_STATUS_OK) { ret = res; goto fail; @@ -6640,12 +6622,10 @@ fail: if (ret != DPP_STATUS_OK) os_memset(intro, 0, sizeof(*intro)); os_memset(Nx, 0, sizeof(Nx)); - os_free(signed_connector); os_free(info.payload); EVP_PKEY_free(own_key); wpabuf_free(own_key_pub); EVP_PKEY_free(peer_key); - EVP_PKEY_free(csign); json_free(root); json_free(own_root); return ret; diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 3d1109f02..224d2871f 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -1370,6 +1370,39 @@ fail: } +enum dpp_status_error +dpp_check_signed_connector(struct dpp_signed_connector_info *info, + const u8 *csign_key, size_t csign_key_len, + const u8 *peer_connector, size_t peer_connector_len) +{ + const unsigned char *p; + EVP_PKEY *csign = NULL; + char *signed_connector = NULL; + enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR; + + p = csign_key; + csign = d2i_PUBKEY(NULL, &p, csign_key_len); + if (!csign) { + wpa_printf(MSG_ERROR, + "DPP: Failed to parse local C-sign-key information"); + goto fail; + } + + wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", + peer_connector, peer_connector_len); + signed_connector = os_malloc(peer_connector_len + 1); + if (!signed_connector) + goto fail; + os_memcpy(signed_connector, peer_connector, peer_connector_len); + signed_connector[peer_connector_len] = '\0'; + res = dpp_process_signed_connector(info, csign, signed_connector); +fail: + os_free(signed_connector); + EVP_PKEY_free(csign); + return res; +} + + int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) { struct wpabuf *pix, *prx, *bix, *brx; diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index 1ac239f06..5a8fa9454 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -42,6 +42,10 @@ struct dpp_signed_connector_info { enum dpp_status_error dpp_process_signed_connector(struct dpp_signed_connector_info *info, EVP_PKEY *csign_pub, const char *connector); +enum dpp_status_error +dpp_check_signed_connector(struct dpp_signed_connector_info *info, + const u8 *csign_key, size_t csign_key_len, + const u8 *peer_connector, size_t peer_connector_len); const struct dpp_curve_params * dpp_get_curve_name(const char *name); const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name); const struct dpp_curve_params * dpp_get_curve_oid(const ASN1_OBJECT *poid); From b227515fae40583b04b41a9abd335241c53c3365 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 10 May 2020 15:36:24 +0300 Subject: [PATCH 0470/1105] tests: Update dpp_peer_intro_local_failures to match implementation The memory allocation in dpp_peer_intro() was moved into a helper function dpp_check_signed_connector(), so update the test case to match. Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index d832b98d4..ff3faaa0f 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -4214,7 +4214,7 @@ def test_dpp_peer_intro_local_failures(dev, apdev): tests = [(1, "base64_gen_decode;dpp_peer_intro"), (1, "json_parse;dpp_peer_intro"), (50, "json_parse;dpp_peer_intro"), - (1, "=dpp_peer_intro"), + (1, "=dpp_check_signed_connector;dpp_peer_intro"), (1, "dpp_parse_jwk")] for count, func in tests: with alloc_fail(dev[0], count, func): From 961435097bd46a7cf144826e2d117daa4f15d465 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 9 May 2020 16:40:44 +0300 Subject: [PATCH 0471/1105] DPP2: Move connStatus object building into a helper function Allow the same helper function to be used for reconfiguration. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 46 +++++++++++++++++++++++++++++++--------------- src/common/dpp_i.h | 3 +++ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index d2bf5cf92..4b34b4f05 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -6165,6 +6165,36 @@ fail: } +struct wpabuf * dpp_build_conn_status(enum dpp_status_error result, + const u8 *ssid, size_t ssid_len, + const char *channel_list) +{ + struct wpabuf *json; + + json = wpabuf_alloc(1000); + if (!json) + return NULL; + json_start_object(json, NULL); + json_add_int(json, "result", result); + if (ssid) { + json_value_sep(json); + if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0) { + wpabuf_free(json); + return NULL; + } + } + if (channel_list) { + json_value_sep(json); + json_add_string(json, "channelList", channel_list); + } + json_end_object(json); + wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON", + wpabuf_head(json), wpabuf_len(json)); + + return json; +} + + struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth, enum dpp_status_error result, const u8 *ssid, size_t ssid_len, @@ -6176,23 +6206,9 @@ struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth, size_t len[2]; u8 *wrapped; - json = wpabuf_alloc(1000); + json = dpp_build_conn_status(result, ssid, ssid_len, channel_list); if (!json) return NULL; - json_start_object(json, NULL); - json_add_int(json, "result", result); - if (ssid) { - json_value_sep(json); - if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0) - goto fail; - } - if (channel_list) { - json_value_sep(json); - json_add_string(json, "channelList", channel_list); - } - json_end_object(json); - wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON", - wpabuf_head(json), wpabuf_len(json)); nonce_len = auth->curve->nonce_len; clear_len = 5 + 4 + nonce_len + 4 + wpabuf_len(json); diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index 5a8fa9454..402b7cbfe 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -30,6 +30,9 @@ struct dpp_global { void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status); unsigned int dpp_next_id(struct dpp_global *dpp); +struct wpabuf * dpp_build_conn_status(enum dpp_status_error result, + const u8 *ssid, size_t ssid_len, + const char *channel_list); struct json_token * dpp_parse_own_connector(const char *own_connector); /* dpp_crypto.c */ From 92492dd3ac1a036324f1d40b518c8349cc342f42 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 9 May 2020 16:42:37 +0300 Subject: [PATCH 0472/1105] DPP2: Extend connector matching for reconfiguration Allow the same helper functions to be used with reconfiguration connector. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 15 +++++++++------ src/common/dpp_i.h | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 4b34b4f05..938e96248 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -6415,7 +6415,8 @@ static int dpp_compatible_netrole(const char *role1, const char *role2) static int dpp_connector_compatible_group(struct json_token *root, const char *group_id, - const char *net_role) + const char *net_role, + bool reconfig) { struct json_token *groups, *token; @@ -6439,7 +6440,9 @@ static int dpp_connector_compatible_group(struct json_token *root, os_strcmp(id->string, group_id) != 0) continue; - if (dpp_compatible_netrole(role->string, net_role)) + if (reconfig && os_strcmp(net_role, "configurator") == 0) + return 1; + if (!reconfig && dpp_compatible_netrole(role->string, net_role)) return 1; } @@ -6447,8 +6450,8 @@ static int dpp_connector_compatible_group(struct json_token *root, } -static int dpp_connector_match_groups(struct json_token *own_root, - struct json_token *peer_root) +int dpp_connector_match_groups(struct json_token *own_root, + struct json_token *peer_root, bool reconfig) { struct json_token *groups, *token; @@ -6478,7 +6481,7 @@ static int dpp_connector_match_groups(struct json_token *own_root, "DPP: peer connector group: groupId='%s' netRole='%s'", id->string, role->string); if (dpp_connector_compatible_group(own_root, id->string, - role->string)) { + role->string, reconfig)) { wpa_printf(MSG_DEBUG, "DPP: Compatible group/netRole in own connector"); return 1; @@ -6570,7 +6573,7 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, goto fail; } - if (!dpp_connector_match_groups(own_root, root)) { + if (!dpp_connector_match_groups(own_root, root, false)) { wpa_printf(MSG_DEBUG, "DPP: Peer connector does not include compatible group netrole with own connector"); ret = DPP_STATUS_NO_MATCH; diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index 402b7cbfe..dd66617fd 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -34,6 +34,8 @@ struct wpabuf * dpp_build_conn_status(enum dpp_status_error result, const u8 *ssid, size_t ssid_len, const char *channel_list); struct json_token * dpp_parse_own_connector(const char *own_connector); +int dpp_connector_match_groups(struct json_token *own_root, + struct json_token *peer_root, bool reconfig); /* dpp_crypto.c */ From 0c043d9de71f1ea8b9ddcc4acb02b223711d4ead Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 May 2020 00:02:15 +0300 Subject: [PATCH 0473/1105] DPP2: Reconfig Announcement transmission Extend DPP chirping mechanism to allow Reconfig Announcement frames to be transmitted instead of the Presence Announcement frames. Add a new wpa_supplicant control interface command "DPP_RECONFIG " to initiate reconfiguration for a specific network profile. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 1 + hostapd/Makefile | 1 + src/common/dpp.h | 5 ++ src/common/dpp_reconfig.c | 76 +++++++++++++++++++++++++++++++ tests/fuzzing/dpp-uri/Makefile | 1 + wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + wpa_supplicant/ctrl_iface.c | 6 +++ wpa_supplicant/dpp_supplicant.c | 56 +++++++++++++++++++---- wpa_supplicant/dpp_supplicant.h | 1 + wpa_supplicant/wpa_supplicant_i.h | 3 ++ 11 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 src/common/dpp_reconfig.c diff --git a/hostapd/Android.mk b/hostapd/Android.mk index c581f5d89..f33163057 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -539,6 +539,7 @@ L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c OBJS += src/common/dpp_crypto.c OBJS += src/common/dpp_pkex.c +OBJS += src/common/dpp_reconfig.c OBJS += src/ap/dpp_hostapd.c OBJS += src/ap/gas_query_ap.c NEED_AES_SIV=y diff --git a/hostapd/Makefile b/hostapd/Makefile index c20a1a822..ded784f03 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -570,6 +570,7 @@ CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o OBJS += ../src/common/dpp_crypto.o OBJS += ../src/common/dpp_pkex.o +OBJS += ../src/common/dpp_reconfig.o OBJS += ../src/ap/dpp_hostapd.o OBJS += ../src/ap/gas_query_ap.o NEED_AES_SIV=y diff --git a/src/common/dpp.h b/src/common/dpp.h index e81526fc8..988c6fc2c 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -626,5 +626,10 @@ struct dpp_global * dpp_global_init(struct dpp_global_config *config); void dpp_global_clear(struct dpp_global *dpp); void dpp_global_deinit(struct dpp_global *dpp); +/* dpp_reconfig.c */ + +struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, + size_t csign_key_len); + #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c new file mode 100644 index 000000000..597963f3c --- /dev/null +++ b/src/common/dpp_reconfig.c @@ -0,0 +1,76 @@ +/* + * DPP reconfiguration + * Copyright (c) 2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "crypto/crypto.h" +#include "dpp.h" +#include "dpp_i.h" + + +#ifdef CONFIG_DPP2 + +static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash) +{ + if (hash) { + wpa_printf(MSG_DEBUG, "DPP: Configurator C-sign key Hash"); + wpabuf_put_le16(msg, DPP_ATTR_C_SIGN_KEY_HASH); + wpabuf_put_le16(msg, SHA256_MAC_LEN); + wpabuf_put_data(msg, hash, SHA256_MAC_LEN); + } +} + + +struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, + size_t csign_key_len) +{ + struct wpabuf *msg; + EVP_PKEY *csign = NULL; + const unsigned char *p; + struct wpabuf *uncomp; + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[1]; + size_t len[1]; + int res; + + wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame"); + + p = csign_key; + csign = d2i_PUBKEY(NULL, &p, csign_key_len); + if (!csign) { + wpa_printf(MSG_ERROR, + "DPP: Failed to parse local C-sign-key information"); + return NULL; + } + + uncomp = dpp_get_pubkey_point(csign, 1); + EVP_PKEY_free(csign); + if (!uncomp) + return NULL; + addr[0] = wpabuf_head(uncomp); + len[0] = wpabuf_len(uncomp); + wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed C-sign key", addr[0], len[0]); + res = sha256_vector(1, addr, len, hash); + wpabuf_free(uncomp); + if (res < 0) + return NULL; + wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)", + hash, SHA256_MAC_LEN); + + msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, 4 + SHA256_MAC_LEN); + if (!msg) + return NULL; + + /* Configurator C-sign key Hash */ + dpp_build_attr_csign_key_hash(msg, hash); + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Reconfig Announcement frame attributes", msg); + return msg; +} +#endif /* CONFIG_DPP2 */ diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index e5788a833..6125e4b36 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -23,6 +23,7 @@ OBJS += $(SRC)/tls/asn1.o OBJS += $(SRC)/common/dpp.o OBJS += $(SRC)/common/dpp_crypto.o OBJS += $(SRC)/common/dpp_pkex.o +OBJS += $(SRC)/common/dpp_reconfig.o dpp-uri: dpp-uri.o $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index a589b2774..0b091d756 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -249,6 +249,7 @@ L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c OBJS += src/common/dpp_crypto.c OBJS += src/common/dpp_pkex.c +OBJS += src/common/dpp_reconfig.c OBJS += dpp_supplicant.c NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 441a7db1a..d2bdbc47c 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -281,6 +281,7 @@ CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o OBJS += ../src/common/dpp_crypto.o OBJS += ../src/common/dpp_pkex.o +OBJS += ../src/common/dpp_reconfig.o OBJS += dpp_supplicant.o NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 6e673fe36..5c99735c8 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11013,6 +11013,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { wpas_dpp_chirp_stop(wpa_s); + } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) { + struct wpa_ssid *ssid; + + ssid = wpa_config_get_network(wpa_s->conf, atoi(buf + 13)); + if (!ssid || wpas_dpp_reconfig(wpa_s, ssid) < 0) + reply_len = -1; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ } else { diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 837ddbe04..f74f1d695 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2878,15 +2878,24 @@ static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s, static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s) { + struct wpabuf *msg; + int type; + + msg = wpa_s->dpp_presence_announcement; + type = DPP_PA_PRESENCE_ANNOUNCEMENT; + if (!msg) { + msg = wpa_s->dpp_reconfig_announcement; + if (!msg) + return; + type = DPP_PA_RECONFIG_ANNOUNCEMENT; + } wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", - MAC2STR(broadcast), wpa_s->dpp_chirp_freq, - DPP_PA_PRESENCE_ANNOUNCEMENT); + MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type); if (offchannel_send_action( wpa_s, wpa_s->dpp_chirp_freq, broadcast, wpa_s->own_addr, broadcast, - wpabuf_head(wpa_s->dpp_presence_announcement), - wpabuf_len(wpa_s->dpp_presence_announcement), + wpabuf_head(msg), wpabuf_len(msg), 2000, wpas_dpp_chirp_tx_status, 0) < 0) wpas_dpp_chirp_stop(wpa_s); } @@ -2901,7 +2910,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, int c; struct wpa_bss *bss; - if (!bi) + if (!bi && !wpa_s->dpp_reconfig_announcement) return; wpa_s->dpp_chirp_scan_done = 1; @@ -2910,8 +2919,11 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, wpa_s->dpp_chirp_freqs = NULL; /* Channels from own bootstrapping info */ - for (i = 0; i < bi->num_freq; i++) - int_array_add_unique(&wpa_s->dpp_chirp_freqs, bi->freq[i]); + if (bi) { + for (i = 0; i < bi->num_freq; i++) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, + bi->freq[i]); + } /* Preferred chirping channels */ int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437); @@ -3085,13 +3097,16 @@ int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd) void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s) { - if (wpa_s->dpp_presence_announcement) { + if (wpa_s->dpp_presence_announcement || + wpa_s->dpp_reconfig_announcement) { offchannel_send_action_done(wpa_s); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED); } wpa_s->dpp_chirp_bi = NULL; wpabuf_free(wpa_s->dpp_presence_announcement); wpa_s->dpp_presence_announcement = NULL; + wpabuf_free(wpa_s->dpp_reconfig_announcement); + wpa_s->dpp_reconfig_announcement = NULL; if (wpa_s->dpp_chirp_listen) wpas_dpp_listen_stop(wpa_s); wpa_s->dpp_chirp_listen = 0; @@ -3106,4 +3121,29 @@ void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s) } } + +int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) +{ + if (!ssid->dpp_connector || !ssid->dpp_netaccesskey || + !ssid->dpp_csign) + return -1; + + wpas_dpp_chirp_stop(wpa_s); + wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; + wpa_s->dpp_qr_mutual = 0; + wpa_s->dpp_reconfig_announcement = + dpp_build_reconfig_announcement(ssid->dpp_csign, + ssid->dpp_csign_len); + if (!wpa_s->dpp_reconfig_announcement) + return -1; + wpa_s->dpp_reconfig_ssid = ssid; + wpa_s->dpp_reconfig_ssid_id = ssid->id; + wpa_s->dpp_chirp_iter = 1; + wpa_s->dpp_chirp_round = 0; + wpa_s->dpp_chirp_scan_done = 0; + wpa_s->dpp_chirp_listen = 0; + + return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL); +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h index 6d70874c4..2dc86e09e 100644 --- a/wpa_supplicant/dpp_supplicant.h +++ b/wpa_supplicant/dpp_supplicant.h @@ -39,5 +39,6 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s, enum dpp_status_error result); int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd); void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s); +int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); #endif /* DPP_SUPPLICANT_H */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 2ed8e2f85..734ba0797 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1277,6 +1277,7 @@ struct wpa_supplicant { #ifdef CONFIG_DPP2 struct dpp_pfs *dpp_pfs; int dpp_pfs_fallback; + struct wpabuf *dpp_reconfig_announcement; struct wpabuf *dpp_presence_announcement; struct dpp_bootstrap_info *dpp_chirp_bi; int dpp_chirp_freq; @@ -1285,6 +1286,8 @@ struct wpa_supplicant { int dpp_chirp_round; int dpp_chirp_scan_done; int dpp_chirp_listen; + struct wpa_ssid *dpp_reconfig_ssid; + int dpp_reconfig_ssid_id; #endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS char *dpp_config_obj_override; From 66ac616cdb31c7ffd086a99aa6aab757cb181646 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 May 2020 00:16:05 +0300 Subject: [PATCH 0474/1105] DPP2: Process received Reconfig Announcement frame Check if there is a matching Configurator and be ready to initiate Reconfig Authentication (which itself is not included in this commit). Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 43 ++++++++++++++++++++++ src/common/dpp.c | 64 +++++++++++++++++++++++++++++++-- src/common/dpp.h | 3 ++ wpa_supplicant/dpp_supplicant.c | 45 +++++++++++++++++++++++ 4 files changed, 152 insertions(+), 3 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 0926a7659..a5e53cbd8 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1197,6 +1197,45 @@ hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src, } } + +static void +hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *csign_hash; + u16 csign_hash_len; + struct dpp_configurator *conf; + + if (hapd->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Reconfig Announcement during ongoing Authentication"); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR, + MAC2STR(src)); + + csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, + &csign_hash_len); + if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Configurator C-sign key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", + csign_hash, csign_hash_len); + conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp, + csign_hash); + if (!conf) { + wpa_printf(MSG_DEBUG, + "DPP: No matching Configurator information found"); + return; + } + + /* TODO: Initiate Reconfig Authentication */ +} + #endif /* CONFIG_DPP2 */ @@ -1663,6 +1702,10 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len, freq); break; + case DPP_PA_RECONFIG_ANNOUNCEMENT: + hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len, + freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, diff --git a/src/common/dpp.c b/src/common/dpp.c index 938e96248..b9b5d53aa 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -6301,7 +6301,6 @@ int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, static int dpp_configurator_gen_kid(struct dpp_configurator *conf) { struct wpabuf *csign_pub = NULL; - u8 kid_hash[SHA256_MAC_LEN]; const u8 *addr[1]; size_t len[1]; int res; @@ -6315,7 +6314,7 @@ static int dpp_configurator_gen_kid(struct dpp_configurator *conf) /* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */ addr[0] = wpabuf_head(csign_pub); len[0] = wpabuf_len(csign_pub); - res = sha256_vector(1, addr, len, kid_hash); + res = sha256_vector(1, addr, len, conf->kid_hash); wpabuf_free(csign_pub); if (res < 0) { wpa_printf(MSG_DEBUG, @@ -6323,7 +6322,8 @@ static int dpp_configurator_gen_kid(struct dpp_configurator *conf) return -1; } - conf->kid = base64_url_encode(kid_hash, sizeof(kid_hash), NULL); + conf->kid = base64_url_encode(conf->kid_hash, sizeof(conf->kid_hash), + NULL); return conf->kid ? 0 : -1; } @@ -7167,6 +7167,23 @@ int dpp_configurator_from_backup(struct dpp_global *dpp, } +struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp, + const u8 *kid) +{ + struct dpp_configurator *conf; + + if (!dpp) + return NULL; + + dl_list_for_each(conf, &dpp->configurator, + struct dpp_configurator, list) { + if (os_memcmp(conf->kid_hash, kid, SHA256_MAC_LEN) == 0) + return conf; + } + return NULL; +} + + static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, void *timeout_ctx); @@ -8010,6 +8027,44 @@ static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, } +static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + const u8 *csign_hash; + u16 csign_hash_len; + struct dpp_configurator *conf; + struct dpp_global *dpp = conn->ctrl->global; + + if (conn->auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Reconfig Announcement during ongoing Authentication"); + return -1; + } + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement"); + + csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, + &csign_hash_len); + if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { + wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Configurator C-sign key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", + csign_hash, csign_hash_len); + conf = dpp_configurator_find_kid(dpp, csign_hash); + if (!conf) { + wpa_printf(MSG_DEBUG, + "DPP: No matching Configurator information found"); + return -1; + } + + /* TODO: Initiate Reconfig Authentication */ + return -1; +} + + static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, size_t len) { @@ -8063,6 +8118,9 @@ static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, case DPP_PA_PRESENCE_ANNOUNCEMENT: return dpp_controller_rx_presence_announcement(conn, msg, pos, end - pos); + case DPP_PA_RECONFIG_ANNOUNCEMENT: + return dpp_controller_rx_reconfig_announcement(conn, msg, pos, + end - pos); default: /* TODO: missing messages types */ wpa_printf(MSG_DEBUG, diff --git a/src/common/dpp.h b/src/common/dpp.h index 988c6fc2c..f560b34ef 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -317,6 +317,7 @@ struct dpp_configurator { unsigned int id; int own; EVP_PKEY *csign; + u8 kid_hash[SHA256_MAC_LEN]; char *kid; const struct dpp_curve_params *curve; }; @@ -601,6 +602,8 @@ int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id, char *buf, size_t buflen); int dpp_configurator_from_backup(struct dpp_global *dpp, struct dpp_asymmetric_key *key); +struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp, + const u8 *kid); int dpp_relay_add_controller(struct dpp_global *dpp, struct dpp_relay_config *config); int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index f74f1d695..a0e47a8b7 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1779,6 +1779,47 @@ wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src, } } + +static void +wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *csign_hash; + u16 csign_hash_len; + struct dpp_configurator *conf; + + if (!wpa_s->dpp) + return; + + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Reconfig Announcement during ongoing Authentication"); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR, + MAC2STR(src)); + + csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, + &csign_hash_len); + if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Configurator C-sign key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", + csign_hash, csign_hash_len); + conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash); + if (!conf) { + wpa_printf(MSG_DEBUG, + "DPP: No matching Configurator information found"); + return; + } + + /* TODO: Initiate Reconfig Authentication */ +} + #endif /* CONFIG_DPP2 */ @@ -2340,6 +2381,10 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len, freq); break; + case DPP_PA_RECONFIG_ANNOUNCEMENT: + wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len, + freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, From 3774b6bd033029d33cf69214767b6876519c5256 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 May 2020 20:10:12 +0300 Subject: [PATCH 0475/1105] DPP2: Reconfig Authentication Request generation and transmission Extend Configurator functionality to sign a special Connector for reconfiguration and reply with Reconfig Authentication Request frame when Reconfig Announcement frame is received with a matching C-sign key hash value. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 70 ++++++++++++++++- src/common/dpp.c | 21 ++--- src/common/dpp.h | 8 ++ src/common/dpp_i.h | 5 ++ src/common/dpp_reconfig.c | 134 ++++++++++++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.c | 99 ++++++++++++++++++++++- 6 files changed, 326 insertions(+), 11 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index a5e53cbd8..42f992e50 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -26,6 +26,10 @@ static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx); static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator); static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx); static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd); +#ifdef CONFIG_DPP2 +static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, + void *timeout_ctx); +#endif /* CONFIG_DPP2 */ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -237,6 +241,10 @@ void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); +#ifdef CONFIG_DPP2 + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); +#endif /* CONFIG_DPP2 */ hostapd_drv_send_action_cancel_wait(hapd); dpp_auth_deinit(hapd->dpp_auth); hapd->dpp_auth = NULL; @@ -539,6 +547,10 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) hapd, NULL); eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); +#ifdef CONFIG_DPP2 + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); +#endif /* CONFIG_DPP2 */ hostapd_drv_send_action_cancel_wait(hapd); dpp_auth_deinit(hapd->dpp_auth); } @@ -1198,6 +1210,22 @@ hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src, } +static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, + void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct dpp_authentication *auth = hapd->dpp_auth; + + if (!auth) + return; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout"); + hostapd_dpp_listen_stop(hapd); + dpp_auth_deinit(auth); + hapd->dpp_auth = NULL; +} + + static void hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, @@ -1206,6 +1234,8 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, const u8 *csign_hash; u16 csign_hash_len; struct dpp_configurator *conf; + struct dpp_authentication *auth; + unsigned int wait_time, max_wait_time; if (hapd->dpp_auth) { wpa_printf(MSG_DEBUG, @@ -1233,7 +1263,41 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, return; } - /* TODO: Initiate Reconfig Authentication */ + auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, + conf, freq); + if (!auth) + return; + hostapd_dpp_set_testing_options(hapd, auth); + if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); + hapd->dpp_auth = auth; + + hapd->dpp_in_response_listen = 0; + hapd->dpp_auth_ok_on_ack = 0; + wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */ + max_wait_time = hapd->dpp_resp_wait_time ? + hapd->dpp_resp_wait_time : 2000; + if (wait_time > max_wait_time) + wait_time = max_wait_time; + wait_time += 10; /* give the driver some extra time to complete */ + eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, + hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); + wait_time -= 10; + + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ); + if (hostapd_drv_send_action(hapd, freq, wait_time, src, + wpabuf_head(auth->reconfig_req_msg), + wpabuf_len(auth->reconfig_req_msg)) < 0) { + dpp_auth_deinit(hapd->dpp_auth); + hapd->dpp_auth = NULL; + } } #endif /* CONFIG_DPP2 */ @@ -1771,6 +1835,8 @@ void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok) eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); #ifdef CONFIG_DPP2 + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); if (ok && auth->peer_version >= 2 && auth->conf_resp_status == DPP_STATUS_OK) { wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); @@ -2015,6 +2081,8 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd) eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); #ifdef CONFIG_DPP2 + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd, diff --git a/src/common/dpp.c b/src/common/dpp.c index b9b5d53aa..c7e4421eb 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -989,10 +989,9 @@ static int dpp_channel_local_list(struct dpp_authentication *auth, } -static int dpp_prepare_channel_list(struct dpp_authentication *auth, - unsigned int neg_freq, - struct hostapd_hw_modes *own_modes, - u16 num_modes) +int dpp_prepare_channel_list(struct dpp_authentication *auth, + unsigned int neg_freq, + struct hostapd_hw_modes *own_modes, u16 num_modes) { int res; char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end; @@ -2339,7 +2338,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, } #endif /* CONFIG_TESTING_OPTIONS */ - if (!auth->initiator || !auth->peer_bi) { + if (!auth->initiator || !auth->peer_bi || auth->reconfig) { dpp_auth_fail(auth, "Unexpected Authentication Response"); return NULL; } @@ -2741,7 +2740,8 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, } #endif /* CONFIG_TESTING_OPTIONS */ - if (auth->initiator || !auth->own_bi || !auth->waiting_auth_conf) { + if (auth->initiator || !auth->own_bi || !auth->waiting_auth_conf || + auth->reconfig) { wpa_printf(MSG_DEBUG, "DPP: initiator=%d own_bi=%d waiting_auth_conf=%d", auth->initiator, !!auth->own_bi, @@ -3195,7 +3195,7 @@ int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd) wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd); pos = os_strstr(cmd, " configurator="); - if (pos) { + if (!auth->conf && pos) { pos += 14; auth->conf = dpp_configurator_get_id(auth->global, atoi(pos)); if (!auth->conf) { @@ -3258,6 +3258,7 @@ void dpp_auth_deinit(struct dpp_authentication *auth) wpabuf_free(auth->req_msg); wpabuf_free(auth->resp_msg); wpabuf_free(auth->conf_req); + wpabuf_free(auth->reconfig_req_msg); for (i = 0; i < auth->num_conf_obj; i++) { struct dpp_config_obj *conf = &auth->conf_obj[i]; @@ -3324,8 +3325,8 @@ dpp_build_conf_start(struct dpp_authentication *auth, } -static int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key, - const char *kid, const struct dpp_curve_params *curve) +int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key, + const char *kid, const struct dpp_curve_params *curve) { struct wpabuf *pub; const u8 *pos; @@ -6270,6 +6271,8 @@ void dpp_configurator_free(struct dpp_configurator *conf) return; EVP_PKEY_free(conf->csign); os_free(conf->kid); + os_free(conf->connector); + EVP_PKEY_free(conf->connector_key); os_free(conf); } diff --git a/src/common/dpp.h b/src/common/dpp.h index f560b34ef..7e3952d14 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -235,6 +235,7 @@ struct dpp_authentication { struct dpp_bootstrap_info *tmp_own_bi; u8 waiting_pubkey_hash[SHA256_MAC_LEN]; int response_pending; + int reconfig; enum dpp_status_error auth_resp_status; enum dpp_status_error conf_resp_status; u8 peer_mac_addr[ETH_ALEN]; @@ -247,6 +248,7 @@ struct dpp_authentication { EVP_PKEY *peer_protocol_key; struct wpabuf *req_msg; struct wpabuf *resp_msg; + struct wpabuf *reconfig_req_msg; /* Intersection of possible frequencies for initiating DPP * Authentication exchange */ unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; @@ -304,6 +306,7 @@ struct dpp_authentication { int conn_status_requested; int akm_use_selector; int configurator_set; + u8 transaction_id; #ifdef CONFIG_TESTING_OPTIONS char *config_obj_override; char *discovery_override; @@ -320,6 +323,8 @@ struct dpp_configurator { u8 kid_hash[SHA256_MAC_LEN]; char *kid; const struct dpp_curve_params *curve; + char *connector; /* own Connector for reconfiguration */ + EVP_PKEY *connector_key; }; struct dpp_introduction { @@ -633,6 +638,9 @@ void dpp_global_deinit(struct dpp_global *dpp); struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, size_t csign_key_len); +struct dpp_authentication * +dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, + struct dpp_configurator *conf, unsigned int freq); #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index dd66617fd..300bf5ce9 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -36,6 +36,11 @@ struct wpabuf * dpp_build_conn_status(enum dpp_status_error result, struct json_token * dpp_parse_own_connector(const char *own_connector); int dpp_connector_match_groups(struct json_token *own_root, struct json_token *peer_root, bool reconfig); +int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key, + const char *kid, const struct dpp_curve_params *curve); +int dpp_prepare_channel_list(struct dpp_authentication *auth, + unsigned int neg_freq, + struct hostapd_hw_modes *own_modes, u16 num_modes); /* dpp_crypto.c */ diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 597963f3c..5a11b1e8b 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -9,7 +9,9 @@ #include "utils/includes.h" #include "utils/common.h" +#include "utils/json.h" #include "crypto/crypto.h" +#include "crypto/random.h" #include "dpp.h" #include "dpp_i.h" @@ -73,4 +75,136 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, "DPP: Reconfig Announcement frame attributes", msg); return msg; } + + +static struct wpabuf * dpp_reconfig_build_req(struct dpp_authentication *auth) +{ + struct wpabuf *msg; + size_t attr_len; + + /* Build DPP Reconfig Authentication Request frame attributes */ + attr_len = 4 + 1 + 4 + 1 + 4 + os_strlen(auth->conf->connector) + + 4 + auth->curve->nonce_len; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_REQ, attr_len); + if (!msg) + return NULL; + + /* Transaction ID */ + wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, auth->transaction_id); + + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + + /* DPP Connector */ + wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); + wpabuf_put_le16(msg, os_strlen(auth->conf->connector)); + wpabuf_put_str(msg, auth->conf->connector); + + /* I-nonce */ + wpabuf_put_le16(msg, DPP_ATTR_I_NONCE); + wpabuf_put_le16(msg, auth->curve->nonce_len); + wpabuf_put_data(msg, auth->i_nonce, auth->curve->nonce_len); + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Reconfig Authentication Request frame attributes", + msg); + + return msg; +} + + +static int dpp_configurator_build_own_connector(struct dpp_configurator *conf) +{ + struct wpabuf *dppcon = NULL; + int ret = -1; + + if (conf->connector) + return 0; /* already generated */ + + wpa_printf(MSG_DEBUG, + "DPP: Sign own Configurator Connector for reconfiguration with curve %s", + conf->curve->name); + conf->connector_key = dpp_gen_keypair(conf->curve); + if (!conf->connector_key) + goto fail; + + /* Connector (JSON dppCon object) */ + dppcon = wpabuf_alloc(1000 + 2 * conf->curve->prime_len * 4 / 3); + if (!dppcon) + goto fail; + json_start_object(dppcon, NULL); + json_start_array(dppcon, "groups"); + json_start_object(dppcon, NULL); + json_add_string(dppcon, "groupId", "*"); + json_value_sep(dppcon); + json_add_string(dppcon, "netRole", "configurator"); + json_end_object(dppcon); + json_end_array(dppcon); + json_value_sep(dppcon); + if (dpp_build_jwk(dppcon, "netAccessKey", conf->connector_key, NULL, + conf->curve) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); + goto fail; + } + json_end_object(dppcon); + wpa_printf(MSG_DEBUG, "DPP: dppCon: %s", + (const char *) wpabuf_head(dppcon)); + + conf->connector = dpp_sign_connector(conf, dppcon); + if (!conf->connector) + goto fail; + wpa_printf(MSG_DEBUG, "DPP: signedConnector: %s", conf->connector); + + ret = 0; +fail: + wpabuf_free(dppcon); + return ret; +} + + +struct dpp_authentication * +dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, + struct dpp_configurator *conf, unsigned int freq) +{ + struct dpp_authentication *auth; + + auth = dpp_alloc_auth(dpp, msg_ctx); + if (!auth) + return NULL; + + auth->conf = conf; + auth->reconfig = 1; + auth->initiator = 1; + auth->waiting_auth_resp = 1; + auth->allowed_roles = DPP_CAPAB_CONFIGURATOR; + auth->configurator = 1; + auth->curve = conf->curve; + auth->transaction_id = 1; + if (dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) + goto fail; + + if (dpp_configurator_build_own_connector(conf) < 0) + goto fail; + + if (random_get_bytes(auth->i_nonce, auth->curve->nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); + goto fail; + } + + auth->reconfig_req_msg = dpp_reconfig_build_req(auth); + if (!auth->reconfig_req_msg) + goto fail; + +out: + return auth; +fail: + dpp_auth_deinit(auth); + auth = NULL; + goto out; +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index a0e47a8b7..4a32d57c6 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -45,6 +45,10 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *bssid, const u8 *data, size_t data_len, enum offchannel_send_action_result result); +#ifdef CONFIG_DPP2 +static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, + void *timeout_ctx); +#endif /* CONFIG_DPP2 */ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -246,6 +250,35 @@ static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s) #ifdef CONFIG_DPP2 +static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s, + unsigned int freq, + unsigned int wait_time) +{ + struct os_reltime now, res; + unsigned int remaining; + + if (!wpa_s->dpp_listen_freq) + return; + + os_get_reltime(&now); + if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) { + os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res); + remaining = res.sec * 1000 + res.usec / 1000; + } else { + remaining = 0; + } + if (wpa_s->dpp_listen_freq == freq && remaining > wait_time) + return; + + wpa_printf(MSG_DEBUG, + "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms", + wpa_s->dpp_listen_freq, remaining, freq, wait_time); + wpas_dpp_listen_stop(wpa_s); + + /* TODO: Restart listen in some cases after TX? */ +} + + static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx, void *timeout_ctx) { @@ -434,6 +467,10 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s, eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); +#ifdef CONFIG_DPP2 + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, + wpa_s, NULL); +#endif /* CONFIG_DPP2 */ offchannel_send_action_done(wpa_s); dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; @@ -766,6 +803,10 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); +#ifdef CONFIG_DPP2 + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, + wpa_s, NULL); +#endif /* CONFIG_DPP2 */ offchannel_send_action_done(wpa_s); dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; @@ -1780,6 +1821,23 @@ wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src, } +static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, + void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct dpp_authentication *auth = wpa_s->dpp_auth; + + if (!auth) + return; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout"); + offchannel_send_action_done(wpa_s); + wpas_dpp_listen_stop(wpa_s); + dpp_auth_deinit(auth); + wpa_s->dpp_auth = NULL; +} + + static void wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, @@ -1788,6 +1846,8 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *csign_hash; u16 csign_hash_len; struct dpp_configurator *conf; + struct dpp_authentication *auth; + unsigned int wait_time, max_wait_time; if (!wpa_s->dpp) return; @@ -1817,7 +1877,42 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, return; } - /* TODO: Initiate Reconfig Authentication */ + auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq); + if (!auth) + return; + wpas_dpp_set_testing_options(wpa_s, auth); + if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); + wpa_s->dpp_auth = auth; + + wpa_s->dpp_in_response_listen = 0; + wpa_s->dpp_auth_ok_on_ack = 0; + wait_time = wpa_s->max_remain_on_chan; + max_wait_time = wpa_s->dpp_resp_wait_time ? + wpa_s->dpp_resp_wait_time : 2000; + if (wait_time > max_wait_time) + wait_time = max_wait_time; + wait_time += 10; /* give the driver some extra time to complete */ + eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, + wpas_dpp_reconfig_reply_wait_timeout, + wpa_s, NULL); + wait_time -= 10; + + wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time); + + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ); + if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, + wpabuf_head(auth->reconfig_req_msg), + wpabuf_len(auth->reconfig_req_msg), + wait_time, wpas_dpp_tx_status, 0) < 0) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + } } #endif /* CONFIG_DPP2 */ @@ -2853,6 +2948,8 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, + wpa_s, NULL); dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = NULL; wpas_dpp_chirp_stop(wpa_s); From 65e94351dc4a87cdd90edba66458d9262540f185 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 9 May 2020 16:30:09 +0300 Subject: [PATCH 0476/1105] DPP2: Reconfig Authentication Request processing and Response generation Extend Enrollee functionality to process Reconfig Authentication Request message, derive the needed keys, and generate Reconfig Authentication Response message. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 9 +- src/common/dpp.h | 10 ++ src/common/dpp_crypto.c | 108 ++++++++++++++ src/common/dpp_i.h | 7 + src/common/dpp_reconfig.c | 254 ++++++++++++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.c | 50 +++++++ 6 files changed, 435 insertions(+), 3 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index c7e4421eb..37f248468 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -108,7 +108,7 @@ struct dpp_controller { }; -static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) +void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) { wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); } @@ -1002,6 +1002,7 @@ int dpp_prepare_channel_list(struct dpp_authentication *auth, return -1; auth->num_freq = 1; auth->freq[0] = neg_freq; + auth->curr_freq = neg_freq; return 0; } @@ -3255,10 +3256,12 @@ void dpp_auth_deinit(struct dpp_authentication *auth) dpp_configuration_free(auth->conf2_sta); EVP_PKEY_free(auth->own_protocol_key); EVP_PKEY_free(auth->peer_protocol_key); + EVP_PKEY_free(auth->reconfig_old_protocol_key); wpabuf_free(auth->req_msg); wpabuf_free(auth->resp_msg); wpabuf_free(auth->conf_req); wpabuf_free(auth->reconfig_req_msg); + wpabuf_free(auth->reconfig_resp_msg); for (i = 0; i < auth->num_conf_obj; i++) { struct dpp_config_obj *conf = &auth->conf_obj[i]; @@ -4477,8 +4480,8 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf, } -static EVP_PKEY * dpp_parse_jwk(struct json_token *jwk, - const struct dpp_curve_params **key_curve) +EVP_PKEY * dpp_parse_jwk(struct json_token *jwk, + const struct dpp_curve_params **key_curve) { struct json_token *token; const struct dpp_curve_params *curve; diff --git a/src/common/dpp.h b/src/common/dpp.h index 7e3952d14..a2c0f185c 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -20,6 +20,7 @@ struct crypto_ecdh; struct hostapd_ip_addr; struct dpp_global; +struct json_token; #ifdef CONFIG_TESTING_OPTIONS #define DPP_VERSION (dpp_version_override) @@ -246,9 +247,11 @@ struct dpp_authentication { u8 r_capab; EVP_PKEY *own_protocol_key; EVP_PKEY *peer_protocol_key; + EVP_PKEY *reconfig_old_protocol_key; struct wpabuf *req_msg; struct wpabuf *resp_msg; struct wpabuf *reconfig_req_msg; + struct wpabuf *reconfig_resp_msg; /* Intersection of possible frequencies for initiating DPP * Authentication exchange */ unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; @@ -641,6 +644,13 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, struct dpp_authentication * dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, struct dpp_configurator *conf, unsigned int freq); +struct dpp_authentication * +dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, + const char *own_connector, + const u8 *net_access_key, size_t net_access_key_len, + const u8 *csign_key, size_t csign_key_len, + unsigned int freq, const u8 *hdr, + const u8 *attr_start, size_t attr_len); #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 224d2871f..048f52752 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2236,6 +2236,114 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, } +int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, + const u8 *net_access_key, + size_t net_access_key_len, + struct json_token *peer_net_access_key) +{ + BN_CTX *bnctx = NULL; + EVP_PKEY *own_key = NULL, *peer_key = NULL; + BIGNUM *sum = NULL, *q = NULL, *mx = NULL; + EC_POINT *m = NULL; + const EC_KEY *cR, *pR; + const EC_GROUP *group; + const BIGNUM *cR_bn, *pR_bn; + const EC_POINT *CI_point; + const EC_KEY *CI; + u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; + u8 prk[DPP_MAX_HASH_LEN]; + const struct dpp_curve_params *curve; + int res = -1; + + own_key = dpp_set_keypair(&auth->curve, net_access_key, + net_access_key_len); + if (!own_key) { + dpp_auth_fail(auth, "Failed to parse own netAccessKey"); + goto fail; + } + + peer_key = dpp_parse_jwk(peer_net_access_key, &curve); + if (!peer_key) + goto fail; + dpp_debug_print_key("DPP: Received netAccessKey", peer_key); + + if (auth->curve != curve) { + wpa_printf(MSG_DEBUG, + "DPP: Mismatching netAccessKey curves (%s != %s)", + auth->curve->name, curve->name); + goto fail; + } + + auth->own_protocol_key = dpp_gen_keypair(curve); + if (!auth->own_protocol_key) + goto fail; + + /* M = { cR + pR } * CI */ + cR = EVP_PKEY_get0_EC_KEY(own_key); + pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); + group = EC_KEY_get0_group(pR); + bnctx = BN_CTX_new(); + sum = BN_new(); + mx = BN_new(); + q = BN_new(); + m = EC_POINT_new(group); + if (!cR || !pR || !bnctx || !sum || !mx || !q || !m) + goto fail; + cR_bn = EC_KEY_get0_private_key(cR); + pR_bn = EC_KEY_get0_private_key(pR); + if (!cR_bn || !pR_bn) + goto fail; + CI = EVP_PKEY_get0_EC_KEY(peer_key); + CI_point = EC_KEY_get0_public_key(CI); + if (EC_GROUP_get_order(group, q, bnctx) != 1 || + BN_mod_add(sum, cR_bn, pR_bn, q, bnctx) != 1 || + EC_POINT_mul(group, m, NULL, CI_point, sum, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL, + bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); + + /* ke = HKDF(I-nonce, "dpp reconfig key", M.x) */ + + /* HKDF-Extract(I-nonce, M.x) */ + if (dpp_hmac(curve->hash_len, auth->i_nonce, curve->nonce_len, + Mx, curve->prime_len, prk) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); + + /* HKDF-Expand(PRK, "dpp reconfig key", L) */ + if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, + "dpp reconfig key", auth->ke, curve->hash_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: ke = HKDF(I-nonce, \"dpp reconfig key\", M.x)", + auth->ke, curve->hash_len); + + res = 0; + EVP_PKEY_free(auth->reconfig_old_protocol_key); + auth->reconfig_old_protocol_key = own_key; + own_key = NULL; +fail: + forced_memzero(prk, sizeof(prk)); + forced_memzero(Mx, sizeof(Mx)); + EC_POINT_clear_free(m); + BN_free(q); + BN_clear_free(mx); + BN_clear_free(sum); + EVP_PKEY_free(own_key); + EVP_PKEY_free(peer_key); + BN_CTX_free(bnctx); + return res; +} + + static char * dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) { diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index 300bf5ce9..c6e9ae471 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -38,9 +38,12 @@ int dpp_connector_match_groups(struct json_token *own_root, struct json_token *peer_root, bool reconfig); int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key, const char *kid, const struct dpp_curve_params *curve); +EVP_PKEY * dpp_parse_jwk(struct json_token *jwk, + const struct dpp_curve_params **key_curve); int dpp_prepare_channel_list(struct dpp_authentication *auth, unsigned int neg_freq, struct hostapd_hw_modes *own_modes, u16 num_modes); +void dpp_auth_fail(struct dpp_authentication *auth, const char *txt); /* dpp_crypto.c */ @@ -116,6 +119,10 @@ int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, const char *code, const u8 *Kx, size_t Kx_len, u8 *z, unsigned int hash_len); +int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, + const u8 *net_access_key, + size_t net_access_key_len, + struct json_token *peer_net_access_key); char * dpp_sign_connector(struct dpp_configurator *conf, const struct wpabuf *dppcon); int dpp_test_gen_invalid_key(struct wpabuf *msg, diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 5a11b1e8b..ba3d6eace 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -7,11 +7,15 @@ */ #include "utils/includes.h" +#include +#include #include "utils/common.h" #include "utils/json.h" #include "crypto/crypto.h" #include "crypto/random.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" #include "dpp.h" #include "dpp_i.h" @@ -207,4 +211,254 @@ fail: goto out; } + +static int dpp_reconfig_build_resp(struct dpp_authentication *auth, + const char *own_connector, + struct wpabuf *conn_status) +{ + struct wpabuf *msg = NULL, *clear, *pr = NULL; + u8 *attr_start, *attr_end; + size_t clear_len, attr_len, len[2]; + const u8 *addr[2]; + u8 *wrapped; + int res = -1; + + /* Build DPP Reconfig Authentication Response frame attributes */ + clear_len = 2 * (4 + auth->curve->nonce_len) + + 4 + wpabuf_len(conn_status); + clear = wpabuf_alloc(clear_len); + if (!clear) + goto fail; + + /* I-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_I_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->i_nonce, auth->curve->nonce_len); + + /* R-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_R_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->r_nonce, auth->curve->nonce_len); + + /* Connection Status (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS); + wpabuf_put_le16(clear, wpabuf_len(conn_status)); + wpabuf_put_buf(clear, conn_status); + + pr = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pr) + goto fail; + + attr_len = 4 + 1 + 4 + 1 + + 4 + os_strlen(own_connector) + + 4 + wpabuf_len(pr) + + 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_RESP, attr_len); + if (!msg) + goto fail; + + attr_start = wpabuf_put(msg, 0); + + /* Transaction ID */ + wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, auth->transaction_id); + + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + + /* R-Connector */ + wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); + wpabuf_put_le16(msg, os_strlen(own_connector)); + wpabuf_put_str(msg, own_connector); + + /* Responder Protocol Key (Pr) */ + wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pr)); + wpabuf_put_buf(msg, pr); + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + /* Wrapped Data: {I-nonce, R-nonce, Connection Status}ke */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 2, addr, len, wrapped) < 0) + goto fail; + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Reconfig Authentication Response frame attributes", + msg); + + wpabuf_free(auth->reconfig_resp_msg); + auth->reconfig_resp_msg = msg; + + res = 0; +out: + wpabuf_free(clear); + wpabuf_free(pr); + return res; +fail: + wpabuf_free(msg); + goto out; +} + + +struct dpp_authentication * +dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, + const char *own_connector, + const u8 *net_access_key, size_t net_access_key_len, + const u8 *csign_key, size_t csign_key_len, + unsigned int freq, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + struct dpp_authentication *auth = NULL; + const u8 *trans_id, *version, *i_connector, *i_nonce; + u16 trans_id_len, version_len, i_connector_len, i_nonce_len; + struct dpp_signed_connector_info info; + enum dpp_status_error res; + struct json_token *root = NULL, *own_root = NULL, *token; + unsigned char *own_conn = NULL; + struct wpabuf *conn_status = NULL; + + os_memset(&info, 0, sizeof(info)); + + trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID, + &trans_id_len); + if (!trans_id || trans_id_len != 1) { + wpa_printf(MSG_DEBUG, + "DPP: Peer did not include Transaction ID"); + goto fail; + } + + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (!version || version_len < 1 || version[0] < 2) { + wpa_printf(MSG_DEBUG, + "DPP: Missing or invalid Protocol Version attribute"); + goto fail; + } + + i_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR, + &i_connector_len); + if (!i_connector) { + wpa_printf(MSG_DEBUG, "DPP: Missing I-Connector attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: I-Connector", + i_connector, i_connector_len); + + i_nonce = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len > DPP_MAX_NONCE_LEN) { + wpa_printf(MSG_DEBUG, + "DPP: Missing or invalid I-Nonce attribute"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-Nonce", i_nonce, i_nonce_len); + + res = dpp_check_signed_connector(&info, csign_key, csign_key_len, + i_connector, i_connector_len); + if (res != DPP_STATUS_OK) { + wpa_printf(MSG_DEBUG, "DPP: Invalid I-Connector"); + goto fail; + } + + root = json_parse((const char *) info.payload, info.payload_len); + own_root = dpp_parse_own_connector(own_connector); + if (!root || !own_root || + !dpp_connector_match_groups(own_root, root, true)) { + wpa_printf(MSG_DEBUG, + "DPP: I-Connector does not include compatible group netrole with own connector"); + goto fail; + } + + token = json_get_member(root, "expiry"); + if (token && token->type == JSON_STRING && + dpp_key_expired(token->string, NULL)) { + wpa_printf(MSG_DEBUG, + "DPP: I-Connector (netAccessKey) has expired"); + goto fail; + } + + token = json_get_member(root, "netAccessKey"); + if (!token || token->type != JSON_OBJECT) { + wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found"); + goto fail; + } + + auth = dpp_alloc_auth(dpp, msg_ctx); + if (!auth) + return NULL; + + auth->reconfig = 1; + auth->allowed_roles = DPP_CAPAB_ENROLLEE; + if (dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) + goto fail; + + auth->transaction_id = trans_id[0]; + + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + + os_memcpy(auth->i_nonce, i_nonce, i_nonce_len); + + if (dpp_reconfig_derive_ke_responder(auth, net_access_key, + net_access_key_len, token) < 0) + goto fail; + + if (i_nonce_len != auth->curve->nonce_len) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected I-nonce length %u (curve nonce len %zu)", + i_nonce_len, auth->curve->nonce_len); + goto fail; + } + + if (random_get_bytes(auth->r_nonce, auth->curve->nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce"); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: R-nonce", + auth->r_nonce, auth->curve->nonce_len); + + /* Build Connection Status object */ + /* TODO: Get appropriate result value */ + /* TODO: ssid64 and channelList */ + conn_status = dpp_build_conn_status(DPP_STATUS_NO_AP, NULL, 0, NULL); + if (!conn_status) + goto fail; + + if (dpp_reconfig_build_resp(auth, own_connector, conn_status) < 0) + goto fail; + +out: + os_free(info.payload); + os_free(own_conn); + json_free(root); + json_free(own_root); + wpabuf_free(conn_status); + return auth; +fail: + dpp_auth_deinit(auth); + auth = NULL; + goto out; +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 4a32d57c6..3f88f372c 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1915,6 +1915,53 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, } } + +static void +wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct wpa_ssid *ssid; + struct dpp_authentication *auth; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from " + MACSTR, MAC2STR(src)); + + if (!wpa_s->dpp || wpa_s->dpp_auth || + !wpa_s->dpp_reconfig_announcement || !wpa_s->dpp_reconfig_ssid) + return; + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (ssid == wpa_s->dpp_reconfig_ssid && + ssid->id == wpa_s->dpp_reconfig_ssid_id) + break; + } + if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey || + !ssid->dpp_csign) + return; + + auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector, + ssid->dpp_netaccesskey, + ssid->dpp_netaccesskey_len, + ssid->dpp_csign, ssid->dpp_csign_len, + freq, hdr, buf, len); + if (!auth) + return; + os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); + wpa_s->dpp_auth = auth; + + wpas_dpp_chirp_stop(wpa_s); + + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP); + if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, + wpabuf_head(auth->reconfig_resp_msg), + wpabuf_len(auth->reconfig_resp_msg), + 500, wpas_dpp_tx_status, 0) < 0) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + } +} + #endif /* CONFIG_DPP2 */ @@ -2480,6 +2527,9 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len, freq); break; + case DPP_PA_RECONFIG_AUTH_REQ: + wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, From 24b01c706bc32dae347f8b9f5222288e066c8bf6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 10 May 2020 12:55:43 +0300 Subject: [PATCH 0477/1105] DPP2: Reconfig Authentication Response processing and Confirm generation Extend Configurator functionality to process Reconfig Authentication Response message, derive the needed keys, and generate Reconfig Authentication Confirm message. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 50 +++++- src/common/dpp.c | 3 +- src/common/dpp.h | 10 ++ src/common/dpp_crypto.c | 91 ++++++++++ src/common/dpp_i.h | 3 + src/common/dpp_reconfig.c | 293 ++++++++++++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.c | 50 +++++- 7 files changed, 497 insertions(+), 3 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 42f992e50..f7d286747 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1300,6 +1300,50 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, } } + +static void +hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct dpp_authentication *auth = hapd->dpp_auth; + struct wpabuf *conf; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from " + MACSTR, MAC2STR(src)); + + if (!auth || !auth->reconfig || !auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - drop"); + return; + } + + if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " + MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); + return; + } + + conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); + if (!conf) + return; + + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); + + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF); + if (hostapd_drv_send_action(hapd, freq, 500, src, + wpabuf_head(conf), wpabuf_len(conf)) < 0) { + wpabuf_free(conf); + dpp_auth_deinit(hapd->dpp_auth); + hapd->dpp_auth = NULL; + return; + } + wpabuf_free(conf); +} + #endif /* CONFIG_DPP2 */ @@ -1770,6 +1814,10 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len, freq); break; + case DPP_PA_RECONFIG_AUTH_RESP: + hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len, + freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, @@ -1799,7 +1847,7 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, struct wpabuf *resp; wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa)); - if (!auth || !auth->auth_success || + if (!auth || (!auth->auth_success && !auth->reconfig_success) || os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { #ifdef CONFIG_DPP2 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data, diff --git a/src/common/dpp.c b/src/common/dpp.c index 37f248468..ff63256a4 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -3462,7 +3462,8 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth, #ifdef CONFIG_TESTING_OPTIONS skip_groups: #endif /* CONFIG_TESTING_OPTIONS */ - if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, + if (!auth->peer_protocol_key || + dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, auth->curve) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); goto fail; diff --git a/src/common/dpp.h b/src/common/dpp.h index a2c0f185c..d24e2f888 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -106,6 +106,12 @@ enum dpp_status_error { DPP_STATUS_CSR_BAD = 13, }; +/* DPP Reconfig Flags object - connectorKey values */ +enum dpp_connector_key { + DPP_CONFIG_REUSEKEY = 0, + DPP_CONFIG_REPLACEKEY = 1, +}; + #define DPP_CAPAB_ENROLLEE BIT(0) #define DPP_CAPAB_CONFIGURATOR BIT(1) #define DPP_CAPAB_ROLE_MASK (BIT(0) | BIT(1)) @@ -282,6 +288,7 @@ struct dpp_authentication { int waiting_conf_result; int waiting_conn_status_result; int auth_success; + bool reconfig_success; struct wpabuf *conf_req; const struct wpabuf *conf_resp; /* owned by GAS server */ struct dpp_configuration *conf_ap; @@ -651,6 +658,9 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, const u8 *csign_key, size_t csign_key_len, unsigned int freq, const u8 *hdr, const u8 *attr_start, size_t attr_len); +struct wpabuf * +dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 048f52752..7495746da 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2344,6 +2344,97 @@ fail: } +int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, + const u8 *r_proto, u16 r_proto_len, + struct json_token *net_access_key) +{ + BN_CTX *bnctx = NULL; + EVP_PKEY *pr = NULL, *peer_key = NULL; + EC_POINT *sum = NULL, *m = NULL; + BIGNUM *mx = NULL; + const EC_KEY *cI, *CR, *PR; + const EC_GROUP *group; + const EC_POINT *CR_point, *PR_point; + const BIGNUM *cI_bn; + u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; + u8 prk[DPP_MAX_HASH_LEN]; + int res = -1; + const struct dpp_curve_params *curve; + + pr = dpp_set_pubkey_point(auth->conf->connector_key, + r_proto, r_proto_len); + if (!pr) { + dpp_auth_fail(auth, "Invalid Responder Protocol Key"); + goto fail; + } + dpp_debug_print_key("Peer (Responder) Protocol Key", pr); + EVP_PKEY_free(auth->peer_protocol_key); + auth->peer_protocol_key = pr; + pr = NULL; + + peer_key = dpp_parse_jwk(net_access_key, &curve); + if (!peer_key) + goto fail; + dpp_debug_print_key("DPP: Received netAccessKey", peer_key); + if (auth->curve != curve) { + wpa_printf(MSG_DEBUG, + "DPP: Mismatching netAccessKey curves (%s != %s)", + auth->curve->name, curve->name); + goto fail; + } + + /* M = cI * { CR + PR } */ + cI = EVP_PKEY_get0_EC_KEY(auth->conf->connector_key); + cI_bn = EC_KEY_get0_private_key(cI); + group = EC_KEY_get0_group(cI); + bnctx = BN_CTX_new(); + sum = EC_POINT_new(group); + m = EC_POINT_new(group); + mx = BN_new(); + CR = EVP_PKEY_get0_EC_KEY(peer_key); + PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); + CR_point = EC_KEY_get0_public_key(CR); + PR_point = EC_KEY_get0_public_key(PR); + if (!bnctx || !sum || !m || !mx || + EC_POINT_add(group, sum, CR_point, PR_point, bnctx) != 1 || + EC_POINT_mul(group, m, NULL, sum, cI_bn, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL, + bnctx) != 1 || + dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); + + /* ke = HKDF(I-nonce, "dpp reconfig key", M.x) */ + + /* HKDF-Extract(I-nonce, M.x) */ + if (dpp_hmac(curve->hash_len, auth->i_nonce, curve->nonce_len, + Mx, curve->prime_len, prk) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); + + /* HKDF-Expand(PRK, "dpp reconfig key", L) */ + if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, + "dpp reconfig key", auth->ke, curve->hash_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: ke = HKDF(I-nonce, \"dpp reconfig key\", M.x)", + auth->ke, curve->hash_len); + + res = 0; +fail: + forced_memzero(prk, sizeof(prk)); + forced_memzero(Mx, sizeof(Mx)); + EVP_PKEY_free(pr); + EVP_PKEY_free(peer_key); + EC_POINT_clear_free(sum); + EC_POINT_clear_free(m); + BN_clear_free(mx); + BN_CTX_free(bnctx); + return res; +} + + static char * dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) { diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index c6e9ae471..158f8cb1d 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -123,6 +123,9 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, const u8 *net_access_key, size_t net_access_key_len, struct json_token *peer_net_access_key); +int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, + const u8 *r_proto, u16 r_proto_len, + struct json_token *net_access_key); char * dpp_sign_connector(struct dpp_configurator *conf, const struct wpabuf *dppcon); int dpp_test_gen_invalid_key(struct wpabuf *msg, diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index ba3d6eace..0db0e08b9 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -461,4 +461,297 @@ fail: goto out; } + +static struct wpabuf * +dpp_build_reconfig_flags(enum dpp_connector_key connector_key) +{ + struct wpabuf *json; + + json = wpabuf_alloc(100); + if (!json) + return NULL; + json_start_object(json, NULL); + json_add_int(json, "connectorKey", connector_key); + json_end_object(json); + wpa_hexdump_ascii(MSG_DEBUG, "DPP: Reconfig-Flags JSON", + wpabuf_head(json), wpabuf_len(json)); + + return json; +} + + +struct wpabuf * +dpp_reconfig_build_conf(struct dpp_authentication *auth) +{ + struct wpabuf *msg = NULL, *clear = NULL, *reconfig_flags; + u8 *attr_start, *attr_end; + size_t clear_len, attr_len, len[2]; + const u8 *addr[2]; + u8 *wrapped; + + reconfig_flags = dpp_build_reconfig_flags(DPP_CONFIG_REPLACEKEY); + if (!reconfig_flags) + goto fail; + + /* Build DPP Reconfig Authentication Confirm frame attributes */ + clear_len = 4 + 1 + 4 + 1 + 2 * (4 + auth->curve->nonce_len) + + 4 + wpabuf_len(reconfig_flags); + clear = wpabuf_alloc(clear_len); + if (!clear) + goto fail; + + /* Transaction ID */ + wpabuf_put_le16(clear, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(clear, 1); + wpabuf_put_u8(clear, auth->transaction_id); + + /* Protocol Version */ + wpabuf_put_le16(clear, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(clear, 1); + wpabuf_put_u8(clear, auth->peer_version); + + /* I-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_I_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->i_nonce, auth->curve->nonce_len); + + /* R-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_R_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->r_nonce, auth->curve->nonce_len); + + /* Reconfig-Flags (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_RECONFIG_FLAGS); + wpabuf_put_le16(clear, wpabuf_len(reconfig_flags)); + wpabuf_put_buf(clear, reconfig_flags); + + attr_len = 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_CONF, attr_len); + if (!msg) + goto fail; + + attr_start = wpabuf_put(msg, 0); + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + /* Wrapped Data */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 2, addr, len, wrapped) < 0) + goto fail; + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Reconfig Authentication Confirm frame attributes", + msg); + +out: + wpabuf_free(reconfig_flags); + wpabuf_free(clear); + return msg; +fail: + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +struct wpabuf * +dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + const u8 *trans_id, *version, *r_connector, *r_proto, *wrapped_data, + *i_nonce, *r_nonce, *conn_status; + u16 trans_id_len, version_len, r_connector_len, r_proto_len, + wrapped_data_len, i_nonce_len, r_nonce_len, conn_status_len; + struct wpabuf *conf = NULL; + char *signed_connector = NULL; + struct dpp_signed_connector_info info; + enum dpp_status_error res; + struct json_token *root = NULL, *token, *conn_status_json = NULL; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + + os_memset(&info, 0, sizeof(info)); + + if (!auth->reconfig || !auth->configurator) + goto fail; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", + wrapped_data, wrapped_data_len); + attr_len = wrapped_data - 4 - attr_start; + + trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID, + &trans_id_len); + if (!trans_id || trans_id_len != 1) { + dpp_auth_fail(auth, "Peer did not include Transaction ID"); + goto fail; + } + if (trans_id[0] != auth->transaction_id) { + dpp_auth_fail(auth, "Transaction ID mismatch"); + goto fail; + } + + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (!version || version_len < 1 || version[0] < 2) { + dpp_auth_fail(auth, + "Missing or invalid Protocol Version attribute"); + goto fail; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + + r_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR, + &r_connector_len); + if (!r_connector) { + dpp_auth_fail(auth, " Missing R-Connector attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: R-Connector", + r_connector, r_connector_len); + + r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, + &r_proto_len); + if (!r_proto) { + dpp_auth_fail(auth, + "Missing required Responder Protocol Key attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", + r_proto, r_proto_len); + + signed_connector = os_malloc(r_connector_len + 1); + if (!signed_connector) + goto fail; + os_memcpy(signed_connector, r_connector, r_connector_len); + signed_connector[r_connector_len] = '\0'; + + res = dpp_process_signed_connector(&info, auth->conf->csign, + signed_connector); + if (res != DPP_STATUS_OK) { + dpp_auth_fail(auth, "Invalid R-Connector"); + goto fail; + } + + root = json_parse((const char *) info.payload, info.payload_len); + if (!root) { + dpp_auth_fail(auth, "Invalid Connector payload"); + goto fail; + } + + /* Do not check netAccessKey expiration for reconfiguration to allow + * expired Connector to be updated. */ + + token = json_get_member(root, "netAccessKey"); + if (!token || token->type != JSON_OBJECT) { + dpp_auth_fail(auth, "No netAccessKey object found"); + goto fail; + } + + if (dpp_reconfig_derive_ke_initiator(auth, r_proto, r_proto_len, + token) < 0) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len || + os_memcmp(i_nonce, auth->i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid R-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); + os_memcpy(auth->r_nonce, r_nonce, r_nonce_len); + + conn_status = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_CONN_STATUS, &conn_status_len); + if (!conn_status) { + dpp_auth_fail(auth, "Missing Connection Status attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus", + conn_status, conn_status_len); + + conn_status_json = json_parse((const char *) conn_status, + conn_status_len); + if (!conn_status_json) { + dpp_auth_fail(auth, "Could not parse connStatus"); + goto fail; + } + /* TODO: use connStatus information */ + + conf = dpp_reconfig_build_conf(auth); + if (conf) + auth->reconfig_success = true; + +out: + json_free(root); + json_free(conn_status_json); + bin_clear_free(unwrapped, unwrapped_len); + os_free(info.payload); + os_free(signed_connector); + return conf; +fail: + wpabuf_free(conf); + conf = NULL; + goto out; +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 3f88f372c..8fd6ece79 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1962,6 +1962,51 @@ wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, } } + +static void +wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct dpp_authentication *auth = wpa_s->dpp_auth; + struct wpabuf *conf; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from " + MACSTR, MAC2STR(src)); + + if (!auth || !auth->reconfig || !auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - drop"); + return; + } + + if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " + MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); + return; + } + + conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); + if (!conf) + return; + + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL); + + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF); + if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, + wpabuf_head(conf), wpabuf_len(conf), + 500, wpas_dpp_tx_status, 0) < 0) { + wpabuf_free(conf); + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + return; + } + wpabuf_free(conf); + + wpas_dpp_start_gas_server(wpa_s); +} + #endif /* CONFIG_DPP2 */ @@ -2530,6 +2575,9 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, case DPP_PA_RECONFIG_AUTH_REQ: wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq); break; + case DPP_PA_RECONFIG_AUTH_RESP: + wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, @@ -2560,7 +2608,7 @@ wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query, wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa)); - if (!auth || !auth->auth_success || + if (!auth || (!auth->auth_success && !auth->reconfig_success) || os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return NULL; From 3e48c5d4b412770db89c6de0086bcf21432271cd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 10 May 2020 23:46:41 +0300 Subject: [PATCH 0478/1105] DPP2: Reconfig Authentication Confirm processing Extend Enrollee functionality to process Reconfig Authentication Confirm message and start GAS client. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 9 ++- src/common/dpp.h | 3 + src/common/dpp_reconfig.c | 124 ++++++++++++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.c | 35 ++++++++- 4 files changed, 169 insertions(+), 2 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index ff63256a4..9aa42f1c7 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -4756,8 +4756,15 @@ static void dpp_copy_netaccesskey(struct dpp_authentication *auth, unsigned char *der = NULL; int der_len; EC_KEY *eckey; + EVP_PKEY *own_key; - eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key); + own_key = auth->own_protocol_key; +#ifdef CONFIG_DPP2 + if (auth->reconfig_connector_key == DPP_CONFIG_REUSEKEY && + auth->reconfig_old_protocol_key) + own_key = auth->reconfig_old_protocol_key; +#endif /* CONFIG_DPP2 */ + eckey = EVP_PKEY_get1_EC_KEY(own_key); if (!eckey) return; diff --git a/src/common/dpp.h b/src/common/dpp.h index d24e2f888..07c5bef62 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -243,6 +243,7 @@ struct dpp_authentication { u8 waiting_pubkey_hash[SHA256_MAC_LEN]; int response_pending; int reconfig; + enum dpp_connector_key reconfig_connector_key; enum dpp_status_error auth_resp_status; enum dpp_status_error conf_resp_status; u8 peer_mac_addr[ETH_ALEN]; @@ -661,6 +662,8 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, struct wpabuf * dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len); +int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 0db0e08b9..355114cbc 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -754,4 +754,128 @@ fail: goto out; } + +int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + const u8 *trans_id, *version, *wrapped_data, *i_nonce, *r_nonce, + *reconfig_flags; + u16 trans_id_len, version_len, wrapped_data_len, i_nonce_len, + r_nonce_len, reconfig_flags_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + struct json_token *root = NULL, *token; + int res = -1; + + if (!auth->reconfig || auth->configurator) + goto fail; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", + wrapped_data, wrapped_data_len); + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = 0; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + trans_id = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_TRANSACTION_ID, &trans_id_len); + if (!trans_id || trans_id_len != 1 || + trans_id[0] != auth->transaction_id) { + dpp_auth_fail(auth, + "Peer did not include valid Transaction ID"); + goto fail; + } + + version = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_PROTOCOL_VERSION, &version_len); + if (!version || version_len < 1 || version[0] != DPP_VERSION) { + dpp_auth_fail(auth, + "Missing or invalid Protocol Version attribute"); + goto fail; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len || + os_memcmp(i_nonce, auth->i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len || + os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid R-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); + + reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_RECONFIG_FLAGS, + &reconfig_flags_len); + if (!reconfig_flags) { + dpp_auth_fail(auth, "Missing or invalid Reconfig-Flags"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: Reconfig-Flags", + reconfig_flags, reconfig_flags_len); + root = json_parse((const char *) reconfig_flags, reconfig_flags_len); + if (!root) { + dpp_auth_fail(auth, "Could not parse Reconfig-Flags"); + goto fail; + } + token = json_get_member(root, "connectorKey"); + if (!token || token->type != JSON_NUMBER) { + dpp_auth_fail(auth, "No connectorKey in Reconfig-Flags"); + goto fail; + } + if (token->number != DPP_CONFIG_REUSEKEY && + token->number != DPP_CONFIG_REPLACEKEY) { + dpp_auth_fail(auth, + "Unsupported connectorKey value in Reconfig-Flags"); + goto fail; + } + auth->reconfig_connector_key = token->number; + + auth->reconfig_success = true; + res = 0; +fail: + json_free(root); + bin_clear_free(unwrapped, unwrapped_len); + return res; +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 8fd6ece79..ae93d59fd 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1374,7 +1374,8 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, wpa_s->dpp_gas_dialog_token = -1; - if (!auth || !auth->auth_success) { + if (!auth || (!auth->auth_success && !auth->reconfig_success) || + os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return; } @@ -2007,6 +2008,35 @@ wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, wpas_dpp_start_gas_server(wpa_s); } + +static void +wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct dpp_authentication *auth = wpa_s->dpp_auth; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from " + MACSTR, MAC2STR(src)); + + if (!auth || !auth->reconfig || auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - drop"); + return; + } + + if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " + MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); + return; + } + + if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0) + return; + + wpas_dpp_start_gas_client(wpa_s); +} + #endif /* CONFIG_DPP2 */ @@ -2578,6 +2608,9 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, case DPP_PA_RECONFIG_AUTH_RESP: wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq); break; + case DPP_PA_RECONFIG_AUTH_CONF: + wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, From 182f6ae9059c7b5b8eeafb12cdcda824a6b50015 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 00:43:07 +0300 Subject: [PATCH 0479/1105] DPP2: Remove reconfigured network Do not leave behind the old network profile when reconfiguration is completed successfully. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index ae93d59fd..b8c1716ce 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1257,6 +1257,20 @@ static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s, static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s, struct dpp_authentication *auth) { +#ifdef CONFIG_DPP2 + if (auth->reconfig && wpa_s->dpp_reconfig_ssid && + wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) == + wpa_s->dpp_reconfig_ssid) { + wpa_printf(MSG_DEBUG, + "DPP: Remove reconfigured network profile"); + wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid); + wpa_config_remove_network(wpa_s->conf, + wpa_s->dpp_reconfig_ssid_id); + wpa_s->dpp_reconfig_ssid = NULL; + wpa_s->dpp_reconfig_ssid_id = -1; + } +#endif /* CONFIG_DPP2 */ + if (wpa_s->conf->dpp_config_processing < 2) return; From fdbbb74064985be3ddd4e23486000e9f77e7a19e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 01:16:12 +0300 Subject: [PATCH 0480/1105] DPP: Move authentication functionality into a separate source code file This continues splitting dpp.c into smaller pieces. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 1 + hostapd/Makefile | 1 + src/common/dpp.c | 1960 +------------------------------ src/common/dpp_auth.c | 1976 ++++++++++++++++++++++++++++++++ src/common/dpp_i.h | 2 + tests/fuzzing/dpp-uri/Makefile | 1 + wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + 8 files changed, 1985 insertions(+), 1958 deletions(-) create mode 100644 src/common/dpp_auth.c diff --git a/hostapd/Android.mk b/hostapd/Android.mk index f33163057..eaa566e60 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -537,6 +537,7 @@ endif ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c +OBJS += src/common/dpp_auth.c OBJS += src/common/dpp_crypto.c OBJS += src/common/dpp_pkex.c OBJS += src/common/dpp_reconfig.c diff --git a/hostapd/Makefile b/hostapd/Makefile index ded784f03..c6725b006 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -568,6 +568,7 @@ endif ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o +OBJS += ../src/common/dpp_auth.o OBJS += ../src/common/dpp_crypto.o OBJS += ../src/common/dpp_pkex.o OBJS += ../src/common/dpp_reconfig.o diff --git a/src/common/dpp.c b/src/common/dpp.c index 9aa42f1c7..e9f1a35cb 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -39,10 +39,6 @@ int dpp_version_override = 2; int dpp_version_override = 1; #endif enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED; -u8 dpp_protocol_key_override[600]; -size_t dpp_protocol_key_override_len = 0; -u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; -size_t dpp_nonce_override_len = 0; #endif /* CONFIG_TESTING_OPTIONS */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ @@ -489,8 +485,7 @@ void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status) } -static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, - const u8 *hash) +void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash) { if (hash) { wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash"); @@ -501,376 +496,6 @@ static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, } -static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg, - const u8 *hash) -{ - if (hash) { - wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash"); - wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH); - wpabuf_put_le16(msg, SHA256_MAC_LEN); - wpabuf_put_data(msg, hash, SHA256_MAC_LEN); - } -} - - -static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, - const struct wpabuf *pi, - size_t nonce_len, - const u8 *r_pubkey_hash, - const u8 *i_pubkey_hash, - unsigned int neg_freq) -{ - struct wpabuf *msg; - u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1]; - u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE]; - u8 *pos; - const u8 *addr[2]; - size_t len[2], siv_len, attr_len; - u8 *attr_start, *attr_end; - - /* Build DPP Authentication Request frame attributes */ - attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) + - 4 + sizeof(wrapped_data); - if (neg_freq > 0) - attr_len += 4 + 2; -#ifdef CONFIG_DPP2 - attr_len += 5; -#endif /* CONFIG_DPP2 */ -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len); - if (!msg) - return NULL; - - attr_start = wpabuf_put(msg, 0); - - /* Responder Bootstrapping Key Hash */ - dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); - - /* Initiator Bootstrapping Key Hash */ - dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); - - /* Initiator Protocol Key */ - if (pi) { - wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY); - wpabuf_put_le16(msg, wpabuf_len(pi)); - wpabuf_put_buf(msg, pi); - } - - /* Channel */ - if (neg_freq > 0) { - u8 op_class, channel; - - if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class, - &channel) == - NUM_HOSTAPD_MODES) { - wpa_printf(MSG_INFO, - "DPP: Unsupported negotiation frequency request: %d", - neg_freq); - wpabuf_free(msg); - return NULL; - } - wpabuf_put_le16(msg, DPP_ATTR_CHANNEL); - wpabuf_put_le16(msg, 2); - wpabuf_put_u8(msg, op_class); - wpabuf_put_u8(msg, channel); - } - -#ifdef CONFIG_DPP2 - /* Protocol Version */ - if (DPP_VERSION > 1) { - wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); - wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, DPP_VERSION); - } -#endif /* CONFIG_DPP2 */ - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); - goto skip_wrapped_data; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Wrapped data ({I-nonce, I-capabilities}k1) */ - pos = clear; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); - goto skip_i_nonce; - } - if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce"); - WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); - pos += 2; - WPA_PUT_LE16(pos, nonce_len - 1); - pos += 2; - os_memcpy(pos, auth->i_nonce, nonce_len - 1); - pos += nonce_len - 1; - goto skip_i_nonce; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* I-nonce */ - WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); - pos += 2; - WPA_PUT_LE16(pos, nonce_len); - pos += 2; - os_memcpy(pos, auth->i_nonce, nonce_len); - pos += nonce_len; - -#ifdef CONFIG_TESTING_OPTIONS -skip_i_nonce: - if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab"); - goto skip_i_capab; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* I-capabilities */ - WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES); - pos += 2; - WPA_PUT_LE16(pos, 1); - pos += 2; - auth->i_capab = auth->allowed_roles; - *pos++ = auth->i_capab; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_ZERO_I_CAPAB) { - wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities"); - pos[-1] = 0; - } -skip_i_capab: -#endif /* CONFIG_TESTING_OPTIONS */ - - attr_end = wpabuf_put(msg, 0); - - /* OUI, OUI type, Crypto Suite, DPP frame type */ - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = 3 + 1 + 1 + 1; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - - /* Attributes before Wrapped Data */ - addr[1] = attr_start; - len[1] = attr_end - attr_start; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - siv_len = pos - clear; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); - if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len, - 2, addr, len, wrapped_data) < 0) { - wpabuf_free(msg); - return NULL; - } - siv_len += AES_BLOCK_SIZE; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, siv_len); - - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, siv_len); - wpabuf_put_data(msg, wrapped_data, siv_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_hexdump_buf(MSG_DEBUG, - "DPP: Authentication Request frame attributes", msg); - - return msg; -} - - -static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, - enum dpp_status_error status, - const struct wpabuf *pr, - size_t nonce_len, - const u8 *r_pubkey_hash, - const u8 *i_pubkey_hash, - const u8 *r_nonce, const u8 *i_nonce, - const u8 *wrapped_r_auth, - size_t wrapped_r_auth_len, - const u8 *siv_key) -{ - struct wpabuf *msg; -#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \ - 4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE - u8 clear[DPP_AUTH_RESP_CLEAR_LEN]; - u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE]; - const u8 *addr[2]; - size_t len[2], siv_len, attr_len; - u8 *attr_start, *attr_end, *pos; - - auth->waiting_auth_conf = 1; - auth->auth_resp_tries = 0; - - /* Build DPP Authentication Response frame attributes */ - attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + - 4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data); -#ifdef CONFIG_DPP2 - attr_len += 5; -#endif /* CONFIG_DPP2 */ -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len); - if (!msg) - return NULL; - - attr_start = wpabuf_put(msg, 0); - - /* DPP Status */ - if (status != 255) - dpp_build_attr_status(msg, status); - - /* Responder Bootstrapping Key Hash */ - dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); - - /* Initiator Bootstrapping Key Hash (mutual authentication) */ - dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); - - /* Responder Protocol Key */ - if (pr) { - wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); - wpabuf_put_le16(msg, wpabuf_len(pr)); - wpabuf_put_buf(msg, pr); - } - -#ifdef CONFIG_DPP2 - /* Protocol Version */ - if (auth->peer_version >= 2) { - wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); - wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, DPP_VERSION); - } -#endif /* CONFIG_DPP2 */ - - attr_end = wpabuf_put(msg, 0); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); - goto skip_wrapped_data; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */ - pos = clear; - - if (r_nonce) { - /* R-nonce */ - WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE); - pos += 2; - WPA_PUT_LE16(pos, nonce_len); - pos += 2; - os_memcpy(pos, r_nonce, nonce_len); - pos += nonce_len; - } - - if (i_nonce) { - /* I-nonce */ - WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); - pos += 2; - WPA_PUT_LE16(pos, nonce_len); - pos += 2; - os_memcpy(pos, i_nonce, nonce_len); -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch"); - pos[nonce_len / 2] ^= 0x01; - } -#endif /* CONFIG_TESTING_OPTIONS */ - pos += nonce_len; - } - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab"); - goto skip_r_capab; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* R-capabilities */ - WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES); - pos += 2; - WPA_PUT_LE16(pos, 1); - pos += 2; - auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR : - DPP_CAPAB_ENROLLEE; - *pos++ = auth->r_capab; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_ZERO_R_CAPAB) { - wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities"); - pos[-1] = 0; - } else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - incompatible R-capabilities"); - if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) == - (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) - pos[-1] = 0; - else - pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE : - DPP_CAPAB_CONFIGURATOR; - } -skip_r_capab: -#endif /* CONFIG_TESTING_OPTIONS */ - - if (wrapped_r_auth) { - /* {R-auth}ke */ - WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA); - pos += 2; - WPA_PUT_LE16(pos, wrapped_r_auth_len); - pos += 2; - os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len); - pos += wrapped_r_auth_len; - } - - /* OUI, OUI type, Crypto Suite, DPP frame type */ - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = 3 + 1 + 1 + 1; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - - /* Attributes before Wrapped Data */ - addr[1] = attr_start; - len[1] = attr_end - attr_start; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - siv_len = pos - clear; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); - if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len, - 2, addr, len, wrapped_data) < 0) { - wpabuf_free(msg); - return NULL; - } - siv_len += AES_BLOCK_SIZE; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, siv_len); - - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, siv_len); - wpabuf_put_data(msg, wrapped_data, siv_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_hexdump_buf(MSG_DEBUG, - "DPP: Authentication Response frame attributes", msg); - return msg; -} - - static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes, u16 num_modes, unsigned int freq) { @@ -1038,7 +663,7 @@ int dpp_prepare_channel_list(struct dpp_authentication *auth, } -static int dpp_gen_uri(struct dpp_bootstrap_info *bi) +int dpp_gen_uri(struct dpp_bootstrap_info *bi) { char macstr[ETH_ALEN * 2 + 10]; size_t len; @@ -1075,33 +700,6 @@ static int dpp_gen_uri(struct dpp_bootstrap_info *bi) } -static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth) -{ - struct dpp_bootstrap_info *bi; - - if (auth->own_bi) - return 0; /* already generated */ - - bi = os_zalloc(sizeof(*bi)); - if (!bi) - return -1; - bi->type = DPP_BOOTSTRAP_QR_CODE; - if (dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0) < 0 || - dpp_gen_uri(bi) < 0) - goto fail; - wpa_printf(MSG_DEBUG, - "DPP: Auto-generated own bootstrapping key info: URI %s", - bi->uri); - - auth->tmp_own_bi = auth->own_bi = bi; - - return 0; -fail: - dpp_bootstrap_info_free(bi); - return -1; -} - - struct dpp_authentication * dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx) { @@ -1117,151 +715,6 @@ dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx) } -struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, - struct dpp_bootstrap_info *peer_bi, - struct dpp_bootstrap_info *own_bi, - u8 dpp_allowed_roles, - unsigned int neg_freq, - struct hostapd_hw_modes *own_modes, - u16 num_modes) -{ - struct dpp_authentication *auth; - size_t nonce_len; - size_t secret_len; - struct wpabuf *pi = NULL; - const u8 *r_pubkey_hash, *i_pubkey_hash; -#ifdef CONFIG_TESTING_OPTIONS - u8 test_hash[SHA256_MAC_LEN]; -#endif /* CONFIG_TESTING_OPTIONS */ - - auth = dpp_alloc_auth(dpp, msg_ctx); - if (!auth) - return NULL; - if (peer_bi->configurator_params && - dpp_set_configurator(auth, peer_bi->configurator_params) < 0) - goto fail; - auth->initiator = 1; - auth->waiting_auth_resp = 1; - auth->allowed_roles = dpp_allowed_roles; - auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR); - auth->peer_bi = peer_bi; - auth->own_bi = own_bi; - auth->curve = peer_bi->curve; - - if (dpp_autogen_bootstrap_key(auth) < 0 || - dpp_prepare_channel_list(auth, neg_freq, own_modes, num_modes) < 0) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_nonce_override_len > 0) { - wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce"); - nonce_len = dpp_nonce_override_len; - os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len); - } else { - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->i_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, - "DPP: Failed to generate I-nonce"); - goto fail; - } - } -#else /* CONFIG_TESTING_OPTIONS */ - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->i_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); - goto fail; - } -#endif /* CONFIG_TESTING_OPTIONS */ - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_protocol_key_override_len) { - const struct dpp_curve_params *tmp_curve; - - wpa_printf(MSG_INFO, - "DPP: TESTING - override protocol key"); - auth->own_protocol_key = dpp_set_keypair( - &tmp_curve, dpp_protocol_key_override, - dpp_protocol_key_override_len); - } else { - auth->own_protocol_key = dpp_gen_keypair(auth->curve); - } -#else /* CONFIG_TESTING_OPTIONS */ - auth->own_protocol_key = dpp_gen_keypair(auth->curve); -#endif /* CONFIG_TESTING_OPTIONS */ - if (!auth->own_protocol_key) - goto fail; - - pi = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (!pi) - goto fail; - - /* ECDH: M = pI * BR */ - if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey, - auth->Mx, &secret_len) < 0) - goto fail; - auth->secret_len = secret_len; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", - auth->Mx, auth->secret_len); - auth->Mx_len = auth->secret_len; - - if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, - auth->curve->hash_len) < 0) - goto fail; - - r_pubkey_hash = auth->peer_bi->pubkey_hash; - i_pubkey_hash = auth->own_bi->pubkey_hash; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); - r_pubkey_hash = NULL; - } else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid R-Bootstrap Key Hash"); - os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - r_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); - i_pubkey_hash = NULL; - } else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid I-Bootstrap Key Hash"); - os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - i_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key"); - wpabuf_free(pi); - pi = NULL; - } else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key"); - wpabuf_free(pi); - pi = wpabuf_alloc(2 * auth->curve->prime_len); - if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0) - goto fail; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (neg_freq && auth->num_freq == 1 && auth->freq[0] == neg_freq) - neg_freq = 0; - auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash, - i_pubkey_hash, neg_freq); - if (!auth->req_msg) - goto fail; - -out: - wpabuf_free(pi); - return auth; -fail: - dpp_auth_deinit(auth); - auth = NULL; - goto out; -} - - static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth, const char *json) { @@ -1476,1415 +929,6 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, } -static void dpp_auth_success(struct dpp_authentication *auth) -{ - wpa_printf(MSG_DEBUG, - "DPP: Authentication success - clear temporary keys"); - os_memset(auth->Mx, 0, sizeof(auth->Mx)); - auth->Mx_len = 0; - os_memset(auth->Nx, 0, sizeof(auth->Nx)); - auth->Nx_len = 0; - os_memset(auth->Lx, 0, sizeof(auth->Lx)); - auth->Lx_len = 0; - os_memset(auth->k1, 0, sizeof(auth->k1)); - os_memset(auth->k2, 0, sizeof(auth->k2)); - - auth->auth_success = 1; -} - - -static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) -{ - size_t nonce_len; - size_t secret_len; - struct wpabuf *msg, *pr = NULL; - u8 r_auth[4 + DPP_MAX_HASH_LEN]; - u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth; - size_t wrapped_r_auth_len; - int ret = -1; - const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce; - enum dpp_status_error status = DPP_STATUS_OK; -#ifdef CONFIG_TESTING_OPTIONS - u8 test_hash[SHA256_MAC_LEN]; -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); - if (!auth->own_bi) - return -1; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_nonce_override_len > 0) { - wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce"); - nonce_len = dpp_nonce_override_len; - os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len); - } else { - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->r_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, - "DPP: Failed to generate R-nonce"); - goto fail; - } - } -#else /* CONFIG_TESTING_OPTIONS */ - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->r_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce"); - goto fail; - } -#endif /* CONFIG_TESTING_OPTIONS */ - wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len); - - EVP_PKEY_free(auth->own_protocol_key); -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_protocol_key_override_len) { - const struct dpp_curve_params *tmp_curve; - - wpa_printf(MSG_INFO, - "DPP: TESTING - override protocol key"); - auth->own_protocol_key = dpp_set_keypair( - &tmp_curve, dpp_protocol_key_override, - dpp_protocol_key_override_len); - } else { - auth->own_protocol_key = dpp_gen_keypair(auth->curve); - } -#else /* CONFIG_TESTING_OPTIONS */ - auth->own_protocol_key = dpp_gen_keypair(auth->curve); -#endif /* CONFIG_TESTING_OPTIONS */ - if (!auth->own_protocol_key) - goto fail; - - pr = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (!pr) - goto fail; - - /* ECDH: N = pR * PI */ - if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key, - auth->Nx, &secret_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", - auth->Nx, auth->secret_len); - auth->Nx_len = auth->secret_len; - - if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, - auth->curve->hash_len) < 0) - goto fail; - - if (auth->own_bi && auth->peer_bi) { - /* Mutual authentication */ - if (dpp_auth_derive_l_responder(auth) < 0) - goto fail; - } - - if (dpp_derive_bk_ke(auth) < 0) - goto fail; - - /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ - WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG); - WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len); - if (dpp_gen_r_auth(auth, r_auth + 4) < 0) - goto fail; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch"); - r_auth[4 + auth->curve->hash_len / 2] ^= 0x01; - } -#endif /* CONFIG_TESTING_OPTIONS */ - if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, - r_auth, 4 + auth->curve->hash_len, - 0, NULL, NULL, wrapped_r_auth) < 0) - goto fail; - wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE; - wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke", - wrapped_r_auth, wrapped_r_auth_len); - w_r_auth = wrapped_r_auth; - - r_pubkey_hash = auth->own_bi->pubkey_hash; - if (auth->peer_bi) - i_pubkey_hash = auth->peer_bi->pubkey_hash; - else - i_pubkey_hash = NULL; - - i_nonce = auth->i_nonce; - r_nonce = auth->r_nonce; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); - r_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid R-Bootstrap Key Hash"); - os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - r_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); - i_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid I-Bootstrap Key Hash"); - if (i_pubkey_hash) - os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); - else - os_memset(test_hash, 0, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - i_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key"); - wpabuf_free(pr); - pr = NULL; - } else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key"); - wpabuf_free(pr); - pr = wpabuf_alloc(2 * auth->curve->prime_len); - if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0) - goto fail; - } else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth"); - w_r_auth = NULL; - wrapped_r_auth_len = 0; - } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); - status = 255; - } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); - status = 254; - } else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce"); - r_nonce = NULL; - } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); - i_nonce = NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - msg = dpp_auth_build_resp(auth, status, pr, nonce_len, - r_pubkey_hash, i_pubkey_hash, - r_nonce, i_nonce, - w_r_auth, wrapped_r_auth_len, - auth->k2); - if (!msg) - goto fail; - wpabuf_free(auth->resp_msg); - auth->resp_msg = msg; - ret = 0; -fail: - wpabuf_free(pr); - return ret; -} - - -static int dpp_auth_build_resp_status(struct dpp_authentication *auth, - enum dpp_status_error status) -{ - struct wpabuf *msg; - const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce; -#ifdef CONFIG_TESTING_OPTIONS - u8 test_hash[SHA256_MAC_LEN]; -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!auth->own_bi) - return -1; - wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); - - r_pubkey_hash = auth->own_bi->pubkey_hash; - if (auth->peer_bi) - i_pubkey_hash = auth->peer_bi->pubkey_hash; - else - i_pubkey_hash = NULL; - - i_nonce = auth->i_nonce; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); - r_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid R-Bootstrap Key Hash"); - os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - r_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); - i_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid I-Bootstrap Key Hash"); - if (i_pubkey_hash) - os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); - else - os_memset(test_hash, 0, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - i_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); - status = 255; - } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); - i_nonce = NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len, - r_pubkey_hash, i_pubkey_hash, - NULL, i_nonce, NULL, 0, auth->k1); - if (!msg) - return -1; - wpabuf_free(auth->resp_msg); - auth->resp_msg = msg; - return 0; -} - - -struct dpp_authentication * -dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles, - int qr_mutual, struct dpp_bootstrap_info *peer_bi, - struct dpp_bootstrap_info *own_bi, - unsigned int freq, const u8 *hdr, const u8 *attr_start, - size_t attr_len) -{ - EVP_PKEY *pi = NULL; - EVP_PKEY_CTX *ctx = NULL; - size_t secret_len; - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap, - *channel; - u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len, - i_bootstrap_len, channel_len; - struct dpp_authentication *auth = NULL; -#ifdef CONFIG_DPP2 - const u8 *version; - u16 version_len; -#endif /* CONFIG_DPP2 */ - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at Authentication Request"); - return NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Missing or invalid required Wrapped Data attribute"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", - wrapped_data, wrapped_data_len); - attr_len = wrapped_data - 4 - attr_start; - - auth = dpp_alloc_auth(dpp, msg_ctx); - if (!auth) - goto fail; - if (peer_bi && peer_bi->configurator_params && - dpp_set_configurator(auth, peer_bi->configurator_params) < 0) - goto fail; - auth->peer_bi = peer_bi; - auth->own_bi = own_bi; - auth->curve = own_bi->curve; - auth->curr_freq = freq; - - auth->peer_version = 1; /* default to the first version */ -#ifdef CONFIG_DPP2 - version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, - &version_len); - if (version && DPP_VERSION > 1) { - if (version_len < 1 || version[0] == 0) { - dpp_auth_fail(auth, - "Invalid Protocol Version attribute"); - goto fail; - } - auth->peer_version = version[0]; - wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", - auth->peer_version); - } -#endif /* CONFIG_DPP2 */ - - channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL, - &channel_len); - if (channel) { - int neg_freq; - - if (channel_len < 2) { - dpp_auth_fail(auth, "Too short Channel attribute"); - goto fail; - } - - neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]); - wpa_printf(MSG_DEBUG, - "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d", - channel[0], channel[1], neg_freq); - if (neg_freq < 0) { - dpp_auth_fail(auth, - "Unsupported Channel attribute value"); - goto fail; - } - - if (auth->curr_freq != (unsigned int) neg_freq) { - wpa_printf(MSG_DEBUG, - "DPP: Changing negotiation channel from %u MHz to %u MHz", - freq, neg_freq); - auth->curr_freq = neg_freq; - } - } - - i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY, - &i_proto_len); - if (!i_proto) { - dpp_auth_fail(auth, - "Missing required Initiator Protocol Key attribute"); - goto fail; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key", - i_proto, i_proto_len); - - /* M = bR * PI */ - pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len); - if (!pi) { - dpp_auth_fail(auth, "Invalid Initiator Protocol Key"); - goto fail; - } - dpp_debug_print_key("Peer (Initiator) Protocol Key", pi); - - if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0) - goto fail; - auth->secret_len = secret_len; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", - auth->Mx, auth->secret_len); - auth->Mx_len = auth->secret_len; - - if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, - auth->curve->hash_len) < 0) - goto fail; - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "Missing or invalid I-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); - os_memcpy(auth->i_nonce, i_nonce, i_nonce_len); - - i_capab = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_I_CAPABILITIES, - &i_capab_len); - if (!i_capab || i_capab_len < 1) { - dpp_auth_fail(auth, "Missing or invalid I-capabilities"); - goto fail; - } - auth->i_capab = i_capab[0]; - wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab); - - bin_clear_free(unwrapped, unwrapped_len); - unwrapped = NULL; - - switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) { - case DPP_CAPAB_ENROLLEE: - if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) { - wpa_printf(MSG_DEBUG, - "DPP: Local policy does not allow Configurator role"); - goto not_compatible; - } - wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); - auth->configurator = 1; - break; - case DPP_CAPAB_CONFIGURATOR: - if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) { - wpa_printf(MSG_DEBUG, - "DPP: Local policy does not allow Enrollee role"); - goto not_compatible; - } - wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); - auth->configurator = 0; - break; - case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE: - if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) { - wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); - auth->configurator = 0; - } else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) { - wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); - auth->configurator = 1; - } else { - wpa_printf(MSG_DEBUG, - "DPP: Local policy does not allow Configurator/Enrollee role"); - goto not_compatible; - } - break; - default: - wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities"); - wpa_msg(auth->msg_ctx, MSG_INFO, - DPP_EVENT_FAIL "Invalid role in I-capabilities 0x%02x", - auth->i_capab & DPP_CAPAB_ROLE_MASK); - goto fail; - } - - auth->peer_protocol_key = pi; - pi = NULL; - if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) { - char hex[SHA256_MAC_LEN * 2 + 1]; - - wpa_printf(MSG_DEBUG, - "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time"); - if (dpp_auth_build_resp_status(auth, - DPP_STATUS_RESPONSE_PENDING) < 0) - goto fail; - i_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_I_BOOTSTRAP_KEY_HASH, - &i_bootstrap_len); - if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) { - auth->response_pending = 1; - os_memcpy(auth->waiting_pubkey_hash, - i_bootstrap, i_bootstrap_len); - wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap, - i_bootstrap_len); - } else { - hex[0] = '\0'; - } - - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE - "%s", hex); - return auth; - } - if (dpp_auth_build_resp_ok(auth) < 0) - goto fail; - - return auth; - -not_compatible: - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE - "i-capab=0x%02x", auth->i_capab); - if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) - auth->configurator = 1; - else - auth->configurator = 0; - auth->peer_protocol_key = pi; - pi = NULL; - if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0) - goto fail; - - auth->remove_on_tx_status = 1; - return auth; -fail: - bin_clear_free(unwrapped, unwrapped_len); - EVP_PKEY_free(pi); - EVP_PKEY_CTX_free(ctx); - dpp_auth_deinit(auth); - return NULL; -} - - -int dpp_notify_new_qr_code(struct dpp_authentication *auth, - struct dpp_bootstrap_info *peer_bi) -{ - if (!auth || !auth->response_pending || - os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) - return 0; - - wpa_printf(MSG_DEBUG, - "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with " - MACSTR, MAC2STR(auth->peer_mac_addr)); - auth->peer_bi = peer_bi; - - if (dpp_auth_build_resp_ok(auth) < 0) - return -1; - - return 1; -} - - -static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth, - enum dpp_status_error status) -{ - struct wpabuf *msg; - u8 i_auth[4 + DPP_MAX_HASH_LEN]; - size_t i_auth_len; - u8 r_nonce[4 + DPP_MAX_NONCE_LEN]; - size_t r_nonce_len; - const u8 *addr[2]; - size_t len[2], attr_len; - u8 *wrapped_i_auth; - u8 *wrapped_r_nonce; - u8 *attr_start, *attr_end; - const u8 *r_pubkey_hash, *i_pubkey_hash; -#ifdef CONFIG_TESTING_OPTIONS - u8 test_hash[SHA256_MAC_LEN]; -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation"); - - i_auth_len = 4 + auth->curve->hash_len; - r_nonce_len = 4 + auth->curve->nonce_len; - /* Build DPP Authentication Confirmation frame attributes */ - attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + - 4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len); - if (!msg) - goto fail; - - attr_start = wpabuf_put(msg, 0); - - r_pubkey_hash = auth->peer_bi->pubkey_hash; - if (auth->own_bi) - i_pubkey_hash = auth->own_bi->pubkey_hash; - else - i_pubkey_hash = NULL; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); - goto skip_status; - } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); - status = 254; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* DPP Status */ - dpp_build_attr_status(msg, status); - -#ifdef CONFIG_TESTING_OPTIONS -skip_status: - if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); - r_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid R-Bootstrap Key Hash"); - os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - r_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); - i_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid I-Bootstrap Key Hash"); - if (i_pubkey_hash) - os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); - else - os_memset(test_hash, 0, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - i_pubkey_hash = test_hash; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Responder Bootstrapping Key Hash */ - dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); - - /* Initiator Bootstrapping Key Hash (mutual authentication) */ - dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF) - goto skip_wrapped_data; - if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) - i_auth_len = 0; -#endif /* CONFIG_TESTING_OPTIONS */ - - attr_end = wpabuf_put(msg, 0); - - /* OUI, OUI type, Crypto Suite, DPP frame type */ - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = 3 + 1 + 1 + 1; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - - /* Attributes before Wrapped Data */ - addr[1] = attr_start; - len[1] = attr_end - attr_start; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - if (status == DPP_STATUS_OK) { - /* I-auth wrapped with ke */ - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE); - wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) - goto skip_i_auth; -#endif /* CONFIG_TESTING_OPTIONS */ - - /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] - * 1) */ - WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG); - WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len); - if (dpp_gen_i_auth(auth, i_auth + 4) < 0) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch"); - i_auth[4 + auth->curve->hash_len / 2] ^= 0x01; - } -skip_i_auth: -#endif /* CONFIG_TESTING_OPTIONS */ - if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, - i_auth, i_auth_len, - 2, addr, len, wrapped_i_auth) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke", - wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE); - } else { - /* R-nonce wrapped with k2 */ - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE); - wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE); - - WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE); - WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len); - os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len); - - if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, - r_nonce, r_nonce_len, - 2, addr, len, wrapped_r_nonce) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2", - wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE); - } - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_hexdump_buf(MSG_DEBUG, - "DPP: Authentication Confirmation frame attributes", - msg); - if (status == DPP_STATUS_OK) - dpp_auth_success(auth); - - return msg; - -fail: - wpabuf_free(msg); - return NULL; -} - - -static void -dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr, - const u8 *attr_start, size_t attr_len, - const u8 *wrapped_data, u16 wrapped_data_len, - enum dpp_status_error status) -{ - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - const u8 *i_nonce, *r_capab; - u16 i_nonce_len, r_capab_len; - - if (status == DPP_STATUS_NOT_COMPATIBLE) { - wpa_printf(MSG_DEBUG, - "DPP: Responder reported incompatible roles"); - } else if (status == DPP_STATUS_RESPONSE_PENDING) { - wpa_printf(MSG_DEBUG, - "DPP: Responder reported more time needed"); - } else { - wpa_printf(MSG_DEBUG, - "DPP: Responder reported failure (status %d)", - status); - dpp_auth_fail(auth, "Responder reported failure"); - return; - } - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "Missing or invalid I-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); - if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { - dpp_auth_fail(auth, "I-nonce mismatch"); - goto fail; - } - - r_capab = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_R_CAPABILITIES, - &r_capab_len); - if (!r_capab || r_capab_len < 1) { - dpp_auth_fail(auth, "Missing or invalid R-capabilities"); - goto fail; - } - auth->r_capab = r_capab[0]; - wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); - if (status == DPP_STATUS_NOT_COMPATIBLE) { - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE - "r-capab=0x%02x", auth->r_capab); - } else if (status == DPP_STATUS_RESPONSE_PENDING) { - u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK; - - if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || - (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { - wpa_msg(auth->msg_ctx, MSG_INFO, - DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x", - role); - } else { - wpa_printf(MSG_DEBUG, - "DPP: Continue waiting for full DPP Authentication Response"); - wpa_msg(auth->msg_ctx, MSG_INFO, - DPP_EVENT_RESPONSE_PENDING "%s", - auth->tmp_own_bi ? auth->tmp_own_bi->uri : ""); - } - } -fail: - bin_clear_free(unwrapped, unwrapped_len); -} - - -struct wpabuf * -dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, - const u8 *attr_start, size_t attr_len) -{ - EVP_PKEY *pr; - size_t secret_len; - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL, *unwrapped2 = NULL; - size_t unwrapped_len = 0, unwrapped2_len = 0; - const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto, - *r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth; - u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, - r_proto_len, r_nonce_len, i_nonce_len, r_capab_len, - wrapped2_len, r_auth_len; - u8 r_auth2[DPP_MAX_HASH_LEN]; - u8 role; -#ifdef CONFIG_DPP2 - const u8 *version; - u16 version_len; -#endif /* CONFIG_DPP2 */ - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at Authentication Response"); - return NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!auth->initiator || !auth->peer_bi || auth->reconfig) { - dpp_auth_fail(auth, "Unexpected Authentication Response"); - return NULL; - } - - auth->waiting_auth_resp = 0; - - wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - dpp_auth_fail(auth, - "Missing or invalid required Wrapped Data attribute"); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", - wrapped_data, wrapped_data_len); - - attr_len = wrapped_data - 4 - attr_start; - - r_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_R_BOOTSTRAP_KEY_HASH, - &r_bootstrap_len); - if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { - dpp_auth_fail(auth, - "Missing or invalid required Responder Bootstrapping Key Hash attribute"); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", - r_bootstrap, r_bootstrap_len); - if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) { - dpp_auth_fail(auth, - "Unexpected Responder Bootstrapping Key Hash value"); - wpa_hexdump(MSG_DEBUG, - "DPP: Expected Responder Bootstrapping Key Hash", - auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); - return NULL; - } - - i_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_I_BOOTSTRAP_KEY_HASH, - &i_bootstrap_len); - if (i_bootstrap) { - if (i_bootstrap_len != SHA256_MAC_LEN) { - dpp_auth_fail(auth, - "Invalid Initiator Bootstrapping Key Hash attribute"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, - "DPP: Initiator Bootstrapping Key Hash", - i_bootstrap, i_bootstrap_len); - if (!auth->own_bi || - os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) { - dpp_auth_fail(auth, - "Initiator Bootstrapping Key Hash attribute did not match"); - return NULL; - } - } else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) { - /* PKEX bootstrapping mandates use of mutual authentication */ - dpp_auth_fail(auth, - "Missing Initiator Bootstrapping Key Hash attribute"); - return NULL; - } else if (auth->own_bi && - auth->own_bi->type == DPP_BOOTSTRAP_NFC_URI && - auth->own_bi->nfc_negotiated) { - /* NFC negotiated connection handover bootstrapping mandates - * use of mutual authentication */ - dpp_auth_fail(auth, - "Missing Initiator Bootstrapping Key Hash attribute"); - return NULL; - } - - auth->peer_version = 1; /* default to the first version */ -#ifdef CONFIG_DPP2 - version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, - &version_len); - if (version && DPP_VERSION > 1) { - if (version_len < 1 || version[0] == 0) { - dpp_auth_fail(auth, - "Invalid Protocol Version attribute"); - return NULL; - } - auth->peer_version = version[0]; - wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", - auth->peer_version); - } -#endif /* CONFIG_DPP2 */ - - status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, - &status_len); - if (!status || status_len < 1) { - dpp_auth_fail(auth, - "Missing or invalid required DPP Status attribute"); - return NULL; - } - wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); - auth->auth_resp_status = status[0]; - if (status[0] != DPP_STATUS_OK) { - dpp_auth_resp_rx_status(auth, hdr, attr_start, - attr_len, wrapped_data, - wrapped_data_len, status[0]); - return NULL; - } - - if (!i_bootstrap && auth->own_bi) { - wpa_printf(MSG_DEBUG, - "DPP: Responder decided not to use mutual authentication"); - auth->own_bi = NULL; - } - - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d", - auth->own_bi != NULL); - - r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, - &r_proto_len); - if (!r_proto) { - dpp_auth_fail(auth, - "Missing required Responder Protocol Key attribute"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", - r_proto, r_proto_len); - - /* N = pI * PR */ - pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len); - if (!pr) { - dpp_auth_fail(auth, "Invalid Responder Protocol Key"); - return NULL; - } - dpp_debug_print_key("Peer (Responder) Protocol Key", pr); - - if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) { - dpp_auth_fail(auth, "Failed to derive ECDH shared secret"); - goto fail; - } - EVP_PKEY_free(auth->peer_protocol_key); - auth->peer_protocol_key = pr; - pr = NULL; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", - auth->Nx, auth->secret_len); - auth->Nx_len = auth->secret_len; - - if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, - auth->curve->hash_len) < 0) - goto fail; - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, - &r_nonce_len); - if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); - os_memcpy(auth->r_nonce, r_nonce, r_nonce_len); - - i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "Missing or invalid I-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); - if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { - dpp_auth_fail(auth, "I-nonce mismatch"); - goto fail; - } - - if (auth->own_bi) { - /* Mutual authentication */ - if (dpp_auth_derive_l_initiator(auth) < 0) - goto fail; - } - - r_capab = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_R_CAPABILITIES, - &r_capab_len); - if (!r_capab || r_capab_len < 1) { - dpp_auth_fail(auth, "Missing or invalid R-capabilities"); - goto fail; - } - auth->r_capab = r_capab[0]; - wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); - role = auth->r_capab & DPP_CAPAB_ROLE_MASK; - if ((auth->allowed_roles == - (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) && - (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) { - /* Peer selected its role, so move from "either role" to the - * role that is compatible with peer's selection. */ - auth->configurator = role == DPP_CAPAB_ENROLLEE; - wpa_printf(MSG_DEBUG, "DPP: Acting as %s", - auth->configurator ? "Configurator" : "Enrollee"); - } else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || - (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { - wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection"); - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Unexpected role in R-capabilities 0x%02x", - role); - if (role != DPP_CAPAB_ENROLLEE && - role != DPP_CAPAB_CONFIGURATOR) - goto fail; - bin_clear_free(unwrapped, unwrapped_len); - auth->remove_on_tx_status = 1; - return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE); - } - - wrapped2 = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_WRAPPED_DATA, &wrapped2_len); - if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) { - dpp_auth_fail(auth, - "Missing or invalid Secondary Wrapped Data"); - goto fail; - } - - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped2, wrapped2_len); - - if (dpp_derive_bk_ke(auth) < 0) - goto fail; - - unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE; - unwrapped2 = os_malloc(unwrapped2_len); - if (!unwrapped2) - goto fail; - if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, - wrapped2, wrapped2_len, - 0, NULL, NULL, unwrapped2) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped2, unwrapped2_len); - - if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) { - dpp_auth_fail(auth, - "Invalid attribute in secondary unwrapped data"); - goto fail; - } - - r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG, - &r_auth_len); - if (!r_auth || r_auth_len != auth->curve->hash_len) { - dpp_auth_fail(auth, - "Missing or invalid Responder Authenticating Tag"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag", - r_auth, r_auth_len); - /* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ - if (dpp_gen_r_auth(auth, r_auth2) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag", - r_auth2, r_auth_len); - if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) { - dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag"); - bin_clear_free(unwrapped, unwrapped_len); - bin_clear_free(unwrapped2, unwrapped2_len); - auth->remove_on_tx_status = 1; - return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE); - } - - bin_clear_free(unwrapped, unwrapped_len); - bin_clear_free(unwrapped2, unwrapped2_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - Authentication Response in place of Confirm"); - if (dpp_auth_build_resp_ok(auth) < 0) - return NULL; - return wpabuf_dup(auth->resp_msg); - } -#endif /* CONFIG_TESTING_OPTIONS */ - - return dpp_auth_build_conf(auth, DPP_STATUS_OK); - -fail: - bin_clear_free(unwrapped, unwrapped_len); - bin_clear_free(unwrapped2, unwrapped2_len); - EVP_PKEY_free(pr); - return NULL; -} - - -static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth, - const u8 *hdr, - const u8 *attr_start, size_t attr_len, - const u8 *wrapped_data, - u16 wrapped_data_len, - enum dpp_status_error status) -{ - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - const u8 *r_nonce; - u16 r_nonce_len; - - /* Authentication Confirm failure cases are expected to include - * {R-nonce}k2 in the Wrapped Data attribute. */ - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) { - dpp_auth_fail(auth, "Authentication failed"); - goto fail; - } - if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, - &r_nonce_len); - if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); - goto fail; - } - if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) { - wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce", - r_nonce, r_nonce_len); - wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce", - auth->r_nonce, r_nonce_len); - dpp_auth_fail(auth, "R-nonce mismatch"); - goto fail; - } - - if (status == DPP_STATUS_NOT_COMPATIBLE) - dpp_auth_fail(auth, "Peer reported incompatible R-capab role"); - else if (status == DPP_STATUS_AUTH_FAILURE) - dpp_auth_fail(auth, "Peer reported authentication failure)"); - -fail: - bin_clear_free(unwrapped, unwrapped_len); - return -1; -} - - -int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, - const u8 *attr_start, size_t attr_len) -{ - const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth; - u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, - i_auth_len; - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - u8 i_auth2[DPP_MAX_HASH_LEN]; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at Authentication Confirm"); - return -1; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (auth->initiator || !auth->own_bi || !auth->waiting_auth_conf || - auth->reconfig) { - wpa_printf(MSG_DEBUG, - "DPP: initiator=%d own_bi=%d waiting_auth_conf=%d", - auth->initiator, !!auth->own_bi, - auth->waiting_auth_conf); - dpp_auth_fail(auth, "Unexpected Authentication Confirm"); - return -1; - } - - auth->waiting_auth_conf = 0; - - wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - dpp_auth_fail(auth, - "Missing or invalid required Wrapped Data attribute"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", - wrapped_data, wrapped_data_len); - - attr_len = wrapped_data - 4 - attr_start; - - r_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_R_BOOTSTRAP_KEY_HASH, - &r_bootstrap_len); - if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { - dpp_auth_fail(auth, - "Missing or invalid required Responder Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", - r_bootstrap, r_bootstrap_len); - if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, - "DPP: Expected Responder Bootstrapping Key Hash", - auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); - dpp_auth_fail(auth, - "Responder Bootstrapping Key Hash mismatch"); - return -1; - } - - i_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_I_BOOTSTRAP_KEY_HASH, - &i_bootstrap_len); - if (i_bootstrap) { - if (i_bootstrap_len != SHA256_MAC_LEN) { - dpp_auth_fail(auth, - "Invalid Initiator Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, - "DPP: Initiator Bootstrapping Key Hash", - i_bootstrap, i_bootstrap_len); - if (!auth->peer_bi || - os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) { - dpp_auth_fail(auth, - "Initiator Bootstrapping Key Hash mismatch"); - return -1; - } - } else if (auth->peer_bi) { - /* Mutual authentication and peer did not include its - * Bootstrapping Key Hash attribute. */ - dpp_auth_fail(auth, - "Missing Initiator Bootstrapping Key Hash attribute"); - return -1; - } - - status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, - &status_len); - if (!status || status_len < 1) { - dpp_auth_fail(auth, - "Missing or invalid required DPP Status attribute"); - return -1; - } - wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); - if (status[0] == DPP_STATUS_NOT_COMPATIBLE || - status[0] == DPP_STATUS_AUTH_FAILURE) - return dpp_auth_conf_rx_failure(auth, hdr, attr_start, - attr_len, wrapped_data, - wrapped_data_len, status[0]); - - if (status[0] != DPP_STATUS_OK) { - dpp_auth_fail(auth, "Authentication failed"); - return -1; - } - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - return -1; - if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, - &i_auth_len); - if (!i_auth || i_auth_len != auth->curve->hash_len) { - dpp_auth_fail(auth, - "Missing or invalid Initiator Authenticating Tag"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag", - i_auth, i_auth_len); - /* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ - if (dpp_gen_i_auth(auth, i_auth2) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag", - i_auth2, i_auth_len); - if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) { - dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag"); - goto fail; - } - - bin_clear_free(unwrapped, unwrapped_len); - dpp_auth_success(auth); - return 0; -fail: - bin_clear_free(unwrapped, unwrapped_len); - return -1; -} - - static int bin_str_eq(const char *val, size_t len, const char *cmp) { return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0; diff --git a/src/common/dpp_auth.c b/src/common/dpp_auth.c new file mode 100644 index 000000000..f79cfef4e --- /dev/null +++ b/src/common/dpp_auth.c @@ -0,0 +1,1976 @@ +/* + * DPP authentication exchange + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "crypto/random.h" +#include "dpp.h" +#include "dpp_i.h" + + +#ifdef CONFIG_TESTING_OPTIONS +u8 dpp_protocol_key_override[600]; +size_t dpp_protocol_key_override_len = 0; +u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; +size_t dpp_nonce_override_len = 0; +#endif /* CONFIG_TESTING_OPTIONS */ + + +static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg, + const u8 *hash) +{ + if (hash) { + wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash"); + wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH); + wpabuf_put_le16(msg, SHA256_MAC_LEN); + wpabuf_put_data(msg, hash, SHA256_MAC_LEN); + } +} + + +static void dpp_auth_success(struct dpp_authentication *auth) +{ + wpa_printf(MSG_DEBUG, + "DPP: Authentication success - clear temporary keys"); + os_memset(auth->Mx, 0, sizeof(auth->Mx)); + auth->Mx_len = 0; + os_memset(auth->Nx, 0, sizeof(auth->Nx)); + auth->Nx_len = 0; + os_memset(auth->Lx, 0, sizeof(auth->Lx)); + auth->Lx_len = 0; + os_memset(auth->k1, 0, sizeof(auth->k1)); + os_memset(auth->k2, 0, sizeof(auth->k2)); + + auth->auth_success = 1; +} + + +static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, + const struct wpabuf *pi, + size_t nonce_len, + const u8 *r_pubkey_hash, + const u8 *i_pubkey_hash, + unsigned int neg_freq) +{ + struct wpabuf *msg; + u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1]; + u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE]; + u8 *pos; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end; + + /* Build DPP Authentication Request frame attributes */ + attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) + + 4 + sizeof(wrapped_data); + if (neg_freq > 0) + attr_len += 4 + 2; +#ifdef CONFIG_DPP2 + attr_len += 5; +#endif /* CONFIG_DPP2 */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len); + if (!msg) + return NULL; + + attr_start = wpabuf_put(msg, 0); + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + + /* Initiator Protocol Key */ + if (pi) { + wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pi)); + wpabuf_put_buf(msg, pi); + } + + /* Channel */ + if (neg_freq > 0) { + u8 op_class, channel; + + if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class, + &channel) == + NUM_HOSTAPD_MODES) { + wpa_printf(MSG_INFO, + "DPP: Unsupported negotiation frequency request: %d", + neg_freq); + wpabuf_free(msg); + return NULL; + } + wpabuf_put_le16(msg, DPP_ATTR_CHANNEL); + wpabuf_put_le16(msg, 2); + wpabuf_put_u8(msg, op_class); + wpabuf_put_u8(msg, channel); + } + +#ifdef CONFIG_DPP2 + /* Protocol Version */ + if (DPP_VERSION > 1) { + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Wrapped data ({I-nonce, I-capabilities}k1) */ + pos = clear; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + goto skip_i_nonce; + } + if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce"); + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len - 1); + pos += 2; + os_memcpy(pos, auth->i_nonce, nonce_len - 1); + pos += nonce_len - 1; + goto skip_i_nonce; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, auth->i_nonce, nonce_len); + pos += nonce_len; + +#ifdef CONFIG_TESTING_OPTIONS +skip_i_nonce: + if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab"); + goto skip_i_capab; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-capabilities */ + WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES); + pos += 2; + WPA_PUT_LE16(pos, 1); + pos += 2; + auth->i_capab = auth->allowed_roles; + *pos++ = auth->i_capab; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_ZERO_I_CAPAB) { + wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities"); + pos[-1] = 0; + } +skip_i_capab: +#endif /* CONFIG_TESTING_OPTIONS */ + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + siv_len = pos - clear; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); + if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len, + 2, addr, len, wrapped_data) < 0) { + wpabuf_free(msg); + return NULL; + } + siv_len += AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, siv_len); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, siv_len); + wpabuf_put_data(msg, wrapped_data, siv_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Request frame attributes", msg); + + return msg; +} + + +static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, + enum dpp_status_error status, + const struct wpabuf *pr, + size_t nonce_len, + const u8 *r_pubkey_hash, + const u8 *i_pubkey_hash, + const u8 *r_nonce, const u8 *i_nonce, + const u8 *wrapped_r_auth, + size_t wrapped_r_auth_len, + const u8 *siv_key) +{ + struct wpabuf *msg; +#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \ + 4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE + u8 clear[DPP_AUTH_RESP_CLEAR_LEN]; + u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE]; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end, *pos; + + auth->waiting_auth_conf = 1; + auth->auth_resp_tries = 0; + + /* Build DPP Authentication Response frame attributes */ + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + + 4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data); +#ifdef CONFIG_DPP2 + attr_len += 5; +#endif /* CONFIG_DPP2 */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len); + if (!msg) + return NULL; + + attr_start = wpabuf_put(msg, 0); + + /* DPP Status */ + if (status != 255) + dpp_build_attr_status(msg, status); + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash (mutual authentication) */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + + /* Responder Protocol Key */ + if (pr) { + wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pr)); + wpabuf_put_buf(msg, pr); + } + +#ifdef CONFIG_DPP2 + /* Protocol Version */ + if (auth->peer_version >= 2) { + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } +#endif /* CONFIG_DPP2 */ + + attr_end = wpabuf_put(msg, 0); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */ + pos = clear; + + if (r_nonce) { + /* R-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, r_nonce, nonce_len); + pos += nonce_len; + } + + if (i_nonce) { + /* I-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, i_nonce, nonce_len); +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch"); + pos[nonce_len / 2] ^= 0x01; + } +#endif /* CONFIG_TESTING_OPTIONS */ + pos += nonce_len; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab"); + goto skip_r_capab; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* R-capabilities */ + WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES); + pos += 2; + WPA_PUT_LE16(pos, 1); + pos += 2; + auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR : + DPP_CAPAB_ENROLLEE; + *pos++ = auth->r_capab; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_ZERO_R_CAPAB) { + wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities"); + pos[-1] = 0; + } else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - incompatible R-capabilities"); + if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) == + (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) + pos[-1] = 0; + else + pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE : + DPP_CAPAB_CONFIGURATOR; + } +skip_r_capab: +#endif /* CONFIG_TESTING_OPTIONS */ + + if (wrapped_r_auth) { + /* {R-auth}ke */ + WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA); + pos += 2; + WPA_PUT_LE16(pos, wrapped_r_auth_len); + pos += 2; + os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len); + pos += wrapped_r_auth_len; + } + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + siv_len = pos - clear; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); + if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len, + 2, addr, len, wrapped_data) < 0) { + wpabuf_free(msg); + return NULL; + } + siv_len += AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, siv_len); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, siv_len); + wpabuf_put_data(msg, wrapped_data, siv_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Response frame attributes", msg); + return msg; +} + + +static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) +{ + size_t nonce_len; + size_t secret_len; + struct wpabuf *msg, *pr = NULL; + u8 r_auth[4 + DPP_MAX_HASH_LEN]; + u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth; + size_t wrapped_r_auth_len; + int ret = -1; + const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce; + enum dpp_status_error status = DPP_STATUS_OK; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); + if (!auth->own_bi) + return -1; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_nonce_override_len > 0) { + wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce"); + nonce_len = dpp_nonce_override_len; + os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len); + } else { + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->r_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate R-nonce"); + goto fail; + } + } +#else /* CONFIG_TESTING_OPTIONS */ + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->r_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce"); + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len); + + EVP_PKEY_free(auth->own_protocol_key); +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_protocol_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override protocol key"); + auth->own_protocol_key = dpp_set_keypair( + &tmp_curve, dpp_protocol_key_override, + dpp_protocol_key_override_len); + } else { + auth->own_protocol_key = dpp_gen_keypair(auth->curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + auth->own_protocol_key = dpp_gen_keypair(auth->curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!auth->own_protocol_key) + goto fail; + + pr = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pr) + goto fail; + + /* ECDH: N = pR * PI */ + if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key, + auth->Nx, &secret_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", + auth->Nx, auth->secret_len); + auth->Nx_len = auth->secret_len; + + if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, + auth->curve->hash_len) < 0) + goto fail; + + if (auth->own_bi && auth->peer_bi) { + /* Mutual authentication */ + if (dpp_auth_derive_l_responder(auth) < 0) + goto fail; + } + + if (dpp_derive_bk_ke(auth) < 0) + goto fail; + + /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG); + WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len); + if (dpp_gen_r_auth(auth, r_auth + 4) < 0) + goto fail; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch"); + r_auth[4 + auth->curve->hash_len / 2] ^= 0x01; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + r_auth, 4 + auth->curve->hash_len, + 0, NULL, NULL, wrapped_r_auth) < 0) + goto fail; + wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke", + wrapped_r_auth, wrapped_r_auth_len); + w_r_auth = wrapped_r_auth; + + r_pubkey_hash = auth->own_bi->pubkey_hash; + if (auth->peer_bi) + i_pubkey_hash = auth->peer_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + + i_nonce = auth->i_nonce; + r_nonce = auth->r_nonce; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key"); + wpabuf_free(pr); + pr = NULL; + } else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key"); + wpabuf_free(pr); + pr = wpabuf_alloc(2 * auth->curve->prime_len); + if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0) + goto fail; + } else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth"); + w_r_auth = NULL; + wrapped_r_auth_len = 0; + } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + status = 255; + } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 254; + } else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce"); + r_nonce = NULL; + } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + i_nonce = NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + msg = dpp_auth_build_resp(auth, status, pr, nonce_len, + r_pubkey_hash, i_pubkey_hash, + r_nonce, i_nonce, + w_r_auth, wrapped_r_auth_len, + auth->k2); + if (!msg) + goto fail; + wpabuf_free(auth->resp_msg); + auth->resp_msg = msg; + ret = 0; +fail: + wpabuf_free(pr); + return ret; +} + + +static int dpp_auth_build_resp_status(struct dpp_authentication *auth, + enum dpp_status_error status) +{ + struct wpabuf *msg; + const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!auth->own_bi) + return -1; + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); + + r_pubkey_hash = auth->own_bi->pubkey_hash; + if (auth->peer_bi) + i_pubkey_hash = auth->peer_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + + i_nonce = auth->i_nonce; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + status = 255; + } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + i_nonce = NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len, + r_pubkey_hash, i_pubkey_hash, + NULL, i_nonce, NULL, 0, auth->k1); + if (!msg) + return -1; + wpabuf_free(auth->resp_msg); + auth->resp_msg = msg; + return 0; +} + + +struct dpp_authentication * +dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles, + int qr_mutual, struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + unsigned int freq, const u8 *hdr, const u8 *attr_start, + size_t attr_len) +{ + EVP_PKEY *pi = NULL; + EVP_PKEY_CTX *ctx = NULL; + size_t secret_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap, + *channel; + u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len, + i_bootstrap_len, channel_len; + struct dpp_authentication *auth = NULL; +#ifdef CONFIG_DPP2 + const u8 *version; + u16 version_len; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Request"); + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Wrapped Data attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", + wrapped_data, wrapped_data_len); + attr_len = wrapped_data - 4 - attr_start; + + auth = dpp_alloc_auth(dpp, msg_ctx); + if (!auth) + goto fail; + if (peer_bi && peer_bi->configurator_params && + dpp_set_configurator(auth, peer_bi->configurator_params) < 0) + goto fail; + auth->peer_bi = peer_bi; + auth->own_bi = own_bi; + auth->curve = own_bi->curve; + auth->curr_freq = freq; + + auth->peer_version = 1; /* default to the first version */ +#ifdef CONFIG_DPP2 + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (version && DPP_VERSION > 1) { + if (version_len < 1 || version[0] == 0) { + dpp_auth_fail(auth, + "Invalid Protocol Version attribute"); + goto fail; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + } +#endif /* CONFIG_DPP2 */ + + channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL, + &channel_len); + if (channel) { + int neg_freq; + + if (channel_len < 2) { + dpp_auth_fail(auth, "Too short Channel attribute"); + goto fail; + } + + neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]); + wpa_printf(MSG_DEBUG, + "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d", + channel[0], channel[1], neg_freq); + if (neg_freq < 0) { + dpp_auth_fail(auth, + "Unsupported Channel attribute value"); + goto fail; + } + + if (auth->curr_freq != (unsigned int) neg_freq) { + wpa_printf(MSG_DEBUG, + "DPP: Changing negotiation channel from %u MHz to %u MHz", + freq, neg_freq); + auth->curr_freq = neg_freq; + } + } + + i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY, + &i_proto_len); + if (!i_proto) { + dpp_auth_fail(auth, + "Missing required Initiator Protocol Key attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key", + i_proto, i_proto_len); + + /* M = bR * PI */ + pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len); + if (!pi) { + dpp_auth_fail(auth, "Invalid Initiator Protocol Key"); + goto fail; + } + dpp_debug_print_key("Peer (Initiator) Protocol Key", pi); + + if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0) + goto fail; + auth->secret_len = secret_len; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", + auth->Mx, auth->secret_len); + auth->Mx_len = auth->secret_len; + + if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, + auth->curve->hash_len) < 0) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + os_memcpy(auth->i_nonce, i_nonce, i_nonce_len); + + i_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_I_CAPABILITIES, + &i_capab_len); + if (!i_capab || i_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid I-capabilities"); + goto fail; + } + auth->i_capab = i_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab); + + bin_clear_free(unwrapped, unwrapped_len); + unwrapped = NULL; + + switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) { + case DPP_CAPAB_ENROLLEE: + if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Configurator role"); + goto not_compatible; + } + wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); + auth->configurator = 1; + break; + case DPP_CAPAB_CONFIGURATOR: + if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Enrollee role"); + goto not_compatible; + } + wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); + auth->configurator = 0; + break; + case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE: + if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) { + wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); + auth->configurator = 0; + } else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) { + wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); + auth->configurator = 1; + } else { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Configurator/Enrollee role"); + goto not_compatible; + } + break; + default: + wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities"); + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_FAIL "Invalid role in I-capabilities 0x%02x", + auth->i_capab & DPP_CAPAB_ROLE_MASK); + goto fail; + } + + auth->peer_protocol_key = pi; + pi = NULL; + if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) { + char hex[SHA256_MAC_LEN * 2 + 1]; + + wpa_printf(MSG_DEBUG, + "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time"); + if (dpp_auth_build_resp_status(auth, + DPP_STATUS_RESPONSE_PENDING) < 0) + goto fail; + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) { + auth->response_pending = 1; + os_memcpy(auth->waiting_pubkey_hash, + i_bootstrap, i_bootstrap_len); + wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap, + i_bootstrap_len); + } else { + hex[0] = '\0'; + } + + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE + "%s", hex); + return auth; + } + if (dpp_auth_build_resp_ok(auth) < 0) + goto fail; + + return auth; + +not_compatible: + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE + "i-capab=0x%02x", auth->i_capab); + if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) + auth->configurator = 1; + else + auth->configurator = 0; + auth->peer_protocol_key = pi; + pi = NULL; + if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0) + goto fail; + + auth->remove_on_tx_status = 1; + return auth; +fail: + bin_clear_free(unwrapped, unwrapped_len); + EVP_PKEY_free(pi); + EVP_PKEY_CTX_free(ctx); + dpp_auth_deinit(auth); + return NULL; +} + + +int dpp_notify_new_qr_code(struct dpp_authentication *auth, + struct dpp_bootstrap_info *peer_bi) +{ + if (!auth || !auth->response_pending || + os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) + return 0; + + wpa_printf(MSG_DEBUG, + "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with " + MACSTR, MAC2STR(auth->peer_mac_addr)); + auth->peer_bi = peer_bi; + + if (dpp_auth_build_resp_ok(auth) < 0) + return -1; + + return 1; +} + + +static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth, + enum dpp_status_error status) +{ + struct wpabuf *msg; + u8 i_auth[4 + DPP_MAX_HASH_LEN]; + size_t i_auth_len; + u8 r_nonce[4 + DPP_MAX_NONCE_LEN]; + size_t r_nonce_len; + const u8 *addr[2]; + size_t len[2], attr_len; + u8 *wrapped_i_auth; + u8 *wrapped_r_nonce; + u8 *attr_start, *attr_end; + const u8 *r_pubkey_hash, *i_pubkey_hash; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation"); + + i_auth_len = 4 + auth->curve->hash_len; + r_nonce_len = 4 + auth->curve->nonce_len; + /* Build DPP Authentication Confirmation frame attributes */ + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + + 4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len); + if (!msg) + goto fail; + + attr_start = wpabuf_put(msg, 0); + + r_pubkey_hash = auth->peer_bi->pubkey_hash; + if (auth->own_bi) + i_pubkey_hash = auth->own_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + goto skip_status; + } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 254; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* DPP Status */ + dpp_build_attr_status(msg, status); + +#ifdef CONFIG_TESTING_OPTIONS +skip_status: + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash (mutual authentication) */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF) + goto skip_wrapped_data; + if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) + i_auth_len = 0; +#endif /* CONFIG_TESTING_OPTIONS */ + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + if (status == DPP_STATUS_OK) { + /* I-auth wrapped with ke */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE); + wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) + goto skip_i_auth; +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] + * 1) */ + WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG); + WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len); + if (dpp_gen_i_auth(auth, i_auth + 4) < 0) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch"); + i_auth[4 + auth->curve->hash_len / 2] ^= 0x01; + } +skip_i_auth: +#endif /* CONFIG_TESTING_OPTIONS */ + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + i_auth, i_auth_len, + 2, addr, len, wrapped_i_auth) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke", + wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE); + } else { + /* R-nonce wrapped with k2 */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE); + wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE); + + WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE); + WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len); + os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len); + + if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, + r_nonce, r_nonce_len, + 2, addr, len, wrapped_r_nonce) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2", + wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE); + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Confirmation frame attributes", + msg); + if (status == DPP_STATUS_OK) + dpp_auth_success(auth); + + return msg; + +fail: + wpabuf_free(msg); + return NULL; +} + + +static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth) +{ + struct dpp_bootstrap_info *bi; + + if (auth->own_bi) + return 0; /* already generated */ + + bi = os_zalloc(sizeof(*bi)); + if (!bi) + return -1; + bi->type = DPP_BOOTSTRAP_QR_CODE; + if (dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0) < 0 || + dpp_gen_uri(bi) < 0) + goto fail; + wpa_printf(MSG_DEBUG, + "DPP: Auto-generated own bootstrapping key info: URI %s", + bi->uri); + + auth->tmp_own_bi = auth->own_bi = bi; + + return 0; +fail: + dpp_bootstrap_info_free(bi); + return -1; +} + + +struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, + struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + u8 dpp_allowed_roles, + unsigned int neg_freq, + struct hostapd_hw_modes *own_modes, + u16 num_modes) +{ + struct dpp_authentication *auth; + size_t nonce_len; + size_t secret_len; + struct wpabuf *pi = NULL; + const u8 *r_pubkey_hash, *i_pubkey_hash; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + auth = dpp_alloc_auth(dpp, msg_ctx); + if (!auth) + return NULL; + if (peer_bi->configurator_params && + dpp_set_configurator(auth, peer_bi->configurator_params) < 0) + goto fail; + auth->initiator = 1; + auth->waiting_auth_resp = 1; + auth->allowed_roles = dpp_allowed_roles; + auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR); + auth->peer_bi = peer_bi; + auth->own_bi = own_bi; + auth->curve = peer_bi->curve; + + if (dpp_autogen_bootstrap_key(auth) < 0 || + dpp_prepare_channel_list(auth, neg_freq, own_modes, num_modes) < 0) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_nonce_override_len > 0) { + wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce"); + nonce_len = dpp_nonce_override_len; + os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len); + } else { + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->i_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate I-nonce"); + goto fail; + } + } +#else /* CONFIG_TESTING_OPTIONS */ + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->i_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_protocol_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override protocol key"); + auth->own_protocol_key = dpp_set_keypair( + &tmp_curve, dpp_protocol_key_override, + dpp_protocol_key_override_len); + } else { + auth->own_protocol_key = dpp_gen_keypair(auth->curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + auth->own_protocol_key = dpp_gen_keypair(auth->curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!auth->own_protocol_key) + goto fail; + + pi = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pi) + goto fail; + + /* ECDH: M = pI * BR */ + if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey, + auth->Mx, &secret_len) < 0) + goto fail; + auth->secret_len = secret_len; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", + auth->Mx, auth->secret_len); + auth->Mx_len = auth->secret_len; + + if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, + auth->curve->hash_len) < 0) + goto fail; + + r_pubkey_hash = auth->peer_bi->pubkey_hash; + i_pubkey_hash = auth->own_bi->pubkey_hash; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key"); + wpabuf_free(pi); + pi = NULL; + } else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key"); + wpabuf_free(pi); + pi = wpabuf_alloc(2 * auth->curve->prime_len); + if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0) + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (neg_freq && auth->num_freq == 1 && auth->freq[0] == neg_freq) + neg_freq = 0; + auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash, + i_pubkey_hash, neg_freq); + if (!auth->req_msg) + goto fail; + +out: + wpabuf_free(pi); + return auth; +fail: + dpp_auth_deinit(auth); + auth = NULL; + goto out; +} +static void +dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len, + const u8 *wrapped_data, u16 wrapped_data_len, + enum dpp_status_error status) +{ + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *i_nonce, *r_capab; + u16 i_nonce_len, r_capab_len; + + if (status == DPP_STATUS_NOT_COMPATIBLE) { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported incompatible roles"); + } else if (status == DPP_STATUS_RESPONSE_PENDING) { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported more time needed"); + } else { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported failure (status %d)", + status); + dpp_auth_fail(auth, "Responder reported failure"); + return; + } + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "I-nonce mismatch"); + goto fail; + } + + r_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_R_CAPABILITIES, + &r_capab_len); + if (!r_capab || r_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid R-capabilities"); + goto fail; + } + auth->r_capab = r_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); + if (status == DPP_STATUS_NOT_COMPATIBLE) { + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE + "r-capab=0x%02x", auth->r_capab); + } else if (status == DPP_STATUS_RESPONSE_PENDING) { + u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK; + + if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || + (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x", + role); + } else { + wpa_printf(MSG_DEBUG, + "DPP: Continue waiting for full DPP Authentication Response"); + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_RESPONSE_PENDING "%s", + auth->tmp_own_bi ? auth->tmp_own_bi->uri : ""); + } + } +fail: + bin_clear_free(unwrapped, unwrapped_len); +} + + +struct wpabuf * +dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + EVP_PKEY *pr; + size_t secret_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL, *unwrapped2 = NULL; + size_t unwrapped_len = 0, unwrapped2_len = 0; + const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto, + *r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth; + u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, + r_proto_len, r_nonce_len, i_nonce_len, r_capab_len, + wrapped2_len, r_auth_len; + u8 r_auth2[DPP_MAX_HASH_LEN]; + u8 role; +#ifdef CONFIG_DPP2 + const u8 *version; + u16 version_len; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Response"); + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!auth->initiator || !auth->peer_bi || auth->reconfig) { + dpp_auth_fail(auth, "Unexpected Authentication Response"); + return NULL; + } + + auth->waiting_auth_resp = 0; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + return NULL; + } + wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", + wrapped_data, wrapped_data_len); + + attr_len = wrapped_data - 4 - attr_start; + + r_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return NULL; + } + wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Unexpected Responder Bootstrapping Key Hash value"); + wpa_hexdump(MSG_DEBUG, + "DPP: Expected Responder Bootstrapping Key Hash", + auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); + return NULL; + } + + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap) { + if (i_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Invalid Initiator Bootstrapping Key Hash attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, + "DPP: Initiator Bootstrapping Key Hash", + i_bootstrap, i_bootstrap_len); + if (!auth->own_bi || + os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Initiator Bootstrapping Key Hash attribute did not match"); + return NULL; + } + } else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) { + /* PKEX bootstrapping mandates use of mutual authentication */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return NULL; + } else if (auth->own_bi && + auth->own_bi->type == DPP_BOOTSTRAP_NFC_URI && + auth->own_bi->nfc_negotiated) { + /* NFC negotiated connection handover bootstrapping mandates + * use of mutual authentication */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return NULL; + } + + auth->peer_version = 1; /* default to the first version */ +#ifdef CONFIG_DPP2 + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (version && DPP_VERSION > 1) { + if (version_len < 1 || version[0] == 0) { + dpp_auth_fail(auth, + "Invalid Protocol Version attribute"); + return NULL; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + } +#endif /* CONFIG_DPP2 */ + + status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, + &status_len); + if (!status || status_len < 1) { + dpp_auth_fail(auth, + "Missing or invalid required DPP Status attribute"); + return NULL; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); + auth->auth_resp_status = status[0]; + if (status[0] != DPP_STATUS_OK) { + dpp_auth_resp_rx_status(auth, hdr, attr_start, + attr_len, wrapped_data, + wrapped_data_len, status[0]); + return NULL; + } + + if (!i_bootstrap && auth->own_bi) { + wpa_printf(MSG_DEBUG, + "DPP: Responder decided not to use mutual authentication"); + auth->own_bi = NULL; + } + + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d", + auth->own_bi != NULL); + + r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, + &r_proto_len); + if (!r_proto) { + dpp_auth_fail(auth, + "Missing required Responder Protocol Key attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", + r_proto, r_proto_len); + + /* N = pI * PR */ + pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len); + if (!pr) { + dpp_auth_fail(auth, "Invalid Responder Protocol Key"); + return NULL; + } + dpp_debug_print_key("Peer (Responder) Protocol Key", pr); + + if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) { + dpp_auth_fail(auth, "Failed to derive ECDH shared secret"); + goto fail; + } + EVP_PKEY_free(auth->peer_protocol_key); + auth->peer_protocol_key = pr; + pr = NULL; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", + auth->Nx, auth->secret_len); + auth->Nx_len = auth->secret_len; + + if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, + auth->curve->hash_len) < 0) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); + os_memcpy(auth->r_nonce, r_nonce, r_nonce_len); + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "I-nonce mismatch"); + goto fail; + } + + if (auth->own_bi) { + /* Mutual authentication */ + if (dpp_auth_derive_l_initiator(auth) < 0) + goto fail; + } + + r_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_R_CAPABILITIES, + &r_capab_len); + if (!r_capab || r_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid R-capabilities"); + goto fail; + } + auth->r_capab = r_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); + role = auth->r_capab & DPP_CAPAB_ROLE_MASK; + if ((auth->allowed_roles == + (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) && + (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) { + /* Peer selected its role, so move from "either role" to the + * role that is compatible with peer's selection. */ + auth->configurator = role == DPP_CAPAB_ENROLLEE; + wpa_printf(MSG_DEBUG, "DPP: Acting as %s", + auth->configurator ? "Configurator" : "Enrollee"); + } else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || + (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { + wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection"); + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Unexpected role in R-capabilities 0x%02x", + role); + if (role != DPP_CAPAB_ENROLLEE && + role != DPP_CAPAB_CONFIGURATOR) + goto fail; + bin_clear_free(unwrapped, unwrapped_len); + auth->remove_on_tx_status = 1; + return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE); + } + + wrapped2 = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_WRAPPED_DATA, &wrapped2_len); + if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid Secondary Wrapped Data"); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped2, wrapped2_len); + + if (dpp_derive_bk_ke(auth) < 0) + goto fail; + + unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE; + unwrapped2 = os_malloc(unwrapped2_len); + if (!unwrapped2) + goto fail; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped2, wrapped2_len, + 0, NULL, NULL, unwrapped2) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped2, unwrapped2_len); + + if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) { + dpp_auth_fail(auth, + "Invalid attribute in secondary unwrapped data"); + goto fail; + } + + r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG, + &r_auth_len); + if (!r_auth || r_auth_len != auth->curve->hash_len) { + dpp_auth_fail(auth, + "Missing or invalid Responder Authenticating Tag"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag", + r_auth, r_auth_len); + /* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + if (dpp_gen_r_auth(auth, r_auth2) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag", + r_auth2, r_auth_len); + if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) { + dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag"); + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + auth->remove_on_tx_status = 1; + return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE); + } + + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - Authentication Response in place of Confirm"); + if (dpp_auth_build_resp_ok(auth) < 0) + return NULL; + return wpabuf_dup(auth->resp_msg); + } +#endif /* CONFIG_TESTING_OPTIONS */ + + return dpp_auth_build_conf(auth, DPP_STATUS_OK); + +fail: + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + EVP_PKEY_free(pr); + return NULL; +} + + +static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth, + const u8 *hdr, + const u8 *attr_start, size_t attr_len, + const u8 *wrapped_data, + u16 wrapped_data_len, + enum dpp_status_error status) +{ + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *r_nonce; + u16 r_nonce_len; + + /* Authentication Confirm failure cases are expected to include + * {R-nonce}k2 in the Wrapped Data attribute. */ + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) { + dpp_auth_fail(auth, "Authentication failed"); + goto fail; + } + if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); + goto fail; + } + if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) { + wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce", + r_nonce, r_nonce_len); + wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce", + auth->r_nonce, r_nonce_len); + dpp_auth_fail(auth, "R-nonce mismatch"); + goto fail; + } + + if (status == DPP_STATUS_NOT_COMPATIBLE) + dpp_auth_fail(auth, "Peer reported incompatible R-capab role"); + else if (status == DPP_STATUS_AUTH_FAILURE) + dpp_auth_fail(auth, "Peer reported authentication failure)"); + +fail: + bin_clear_free(unwrapped, unwrapped_len); + return -1; +} + + +int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth; + u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, + i_auth_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + u8 i_auth2[DPP_MAX_HASH_LEN]; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Confirm"); + return -1; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (auth->initiator || !auth->own_bi || !auth->waiting_auth_conf || + auth->reconfig) { + wpa_printf(MSG_DEBUG, + "DPP: initiator=%d own_bi=%d waiting_auth_conf=%d", + auth->initiator, !!auth->own_bi, + auth->waiting_auth_conf); + dpp_auth_fail(auth, "Unexpected Authentication Confirm"); + return -1; + } + + auth->waiting_auth_conf = 0; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", + wrapped_data, wrapped_data_len); + + attr_len = wrapped_data - 4 - attr_start; + + r_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + wpa_hexdump(MSG_DEBUG, + "DPP: Expected Responder Bootstrapping Key Hash", + auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); + dpp_auth_fail(auth, + "Responder Bootstrapping Key Hash mismatch"); + return -1; + } + + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap) { + if (i_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Invalid Initiator Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, + "DPP: Initiator Bootstrapping Key Hash", + i_bootstrap, i_bootstrap_len); + if (!auth->peer_bi || + os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Initiator Bootstrapping Key Hash mismatch"); + return -1; + } + } else if (auth->peer_bi) { + /* Mutual authentication and peer did not include its + * Bootstrapping Key Hash attribute. */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return -1; + } + + status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, + &status_len); + if (!status || status_len < 1) { + dpp_auth_fail(auth, + "Missing or invalid required DPP Status attribute"); + return -1; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); + if (status[0] == DPP_STATUS_NOT_COMPATIBLE || + status[0] == DPP_STATUS_AUTH_FAILURE) + return dpp_auth_conf_rx_failure(auth, hdr, attr_start, + attr_len, wrapped_data, + wrapped_data_len, status[0]); + + if (status[0] != DPP_STATUS_OK) { + dpp_auth_fail(auth, "Authentication failed"); + return -1; + } + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + return -1; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, + &i_auth_len); + if (!i_auth || i_auth_len != auth->curve->hash_len) { + dpp_auth_fail(auth, + "Missing or invalid Initiator Authenticating Tag"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag", + i_auth, i_auth_len); + /* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ + if (dpp_gen_i_auth(auth, i_auth2) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag", + i_auth2, i_auth_len); + if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) { + dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag"); + goto fail; + } + + bin_clear_free(unwrapped, unwrapped_len); + dpp_auth_success(auth); + return 0; +fail: + bin_clear_free(unwrapped, unwrapped_len); + return -1; +} diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index 158f8cb1d..490e5bc93 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -29,6 +29,7 @@ struct dpp_global { /* dpp.c */ void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status); +void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash); unsigned int dpp_next_id(struct dpp_global *dpp); struct wpabuf * dpp_build_conn_status(enum dpp_status_error result, const u8 *ssid, size_t ssid_len, @@ -44,6 +45,7 @@ int dpp_prepare_channel_list(struct dpp_authentication *auth, unsigned int neg_freq, struct hostapd_hw_modes *own_modes, u16 num_modes); void dpp_auth_fail(struct dpp_authentication *auth, const char *txt); +int dpp_gen_uri(struct dpp_bootstrap_info *bi); /* dpp_crypto.c */ diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index 6125e4b36..3b49fa4f5 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -21,6 +21,7 @@ OBJS += $(SRC)/crypto/sha384-kdf.o OBJS += $(SRC)/crypto/sha512-kdf.o OBJS += $(SRC)/tls/asn1.o OBJS += $(SRC)/common/dpp.o +OBJS += $(SRC)/common/dpp_auth.o OBJS += $(SRC)/common/dpp_crypto.o OBJS += $(SRC)/common/dpp_pkex.o OBJS += $(SRC)/common/dpp_reconfig.o diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 0b091d756..c85e7f957 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -247,6 +247,7 @@ endif ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c +OBJS += src/common/dpp_auth.c OBJS += src/common/dpp_crypto.c OBJS += src/common/dpp_pkex.c OBJS += src/common/dpp_reconfig.c diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index d2bdbc47c..34ac16472 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -279,6 +279,7 @@ endif ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o +OBJS += ../src/common/dpp_auth.o OBJS += ../src/common/dpp_crypto.o OBJS += ../src/common/dpp_pkex.o OBJS += ../src/common/dpp_reconfig.o From 21c612017b0c22df93eeee40863829a3fc46d336 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 01:30:13 +0300 Subject: [PATCH 0481/1105] DPP: Move configurator backup into a separate source code file This continues splitting dpp.c into smaller pieces. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 1 + hostapd/Makefile | 1 + src/common/dpp.c | 1202 +------------------------------ src/common/dpp_backup.c | 1211 ++++++++++++++++++++++++++++++++ src/common/dpp_i.h | 7 + tests/fuzzing/dpp-uri/Makefile | 1 + wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + 8 files changed, 1225 insertions(+), 1200 deletions(-) create mode 100644 src/common/dpp_backup.c diff --git a/hostapd/Android.mk b/hostapd/Android.mk index eaa566e60..5cda74885 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -538,6 +538,7 @@ ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c OBJS += src/common/dpp_auth.c +OBJS += src/common/dpp_backup.c OBJS += src/common/dpp_crypto.c OBJS += src/common/dpp_pkex.c OBJS += src/common/dpp_reconfig.c diff --git a/hostapd/Makefile b/hostapd/Makefile index c6725b006..b2d782aac 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -569,6 +569,7 @@ ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o OBJS += ../src/common/dpp_auth.o +OBJS += ../src/common/dpp_backup.o OBJS += ../src/common/dpp_crypto.o OBJS += ../src/common/dpp_pkex.o OBJS += ../src/common/dpp_reconfig.o diff --git a/src/common/dpp.c b/src/common/dpp.c index e9f1a35cb..870364a29 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -24,7 +24,6 @@ #include "crypto/random.h" #include "crypto/aes.h" #include "crypto/aes_siv.h" -#include "tls/asn1.h" #include "drivers/driver.h" #include "dpp.h" #include "dpp_i.h" @@ -1274,20 +1273,6 @@ fail: } -static void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key) -{ - while (key) { - struct dpp_asymmetric_key *next = key->next; - - EVP_PKEY_free(key->csign); - str_clear_free(key->config_template); - str_clear_free(key->connector_template); - os_free(key); - key = next; - } -} - - void dpp_auth_deinit(struct dpp_authentication *auth) { unsigned int i; @@ -1312,7 +1297,9 @@ void dpp_auth_deinit(struct dpp_authentication *auth) os_free(conf->connector); wpabuf_free(conf->c_sign_key); } +#ifdef CONFIG_DPP2 dpp_free_asymmetric_key(auth->conf_key_pkg); +#endif /* CONFIG_DPP2 */ wpabuf_free(auth->net_access_key); dpp_bootstrap_info_free(auth->tmp_own_bi); #ifdef CONFIG_TESTING_OPTIONS @@ -1655,488 +1642,6 @@ dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, } -#ifdef CONFIG_DPP2 - -static struct wpabuf * dpp_build_conf_params(void) -{ - struct wpabuf *buf; - size_t len; - /* TODO: proper template values */ - const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}"; - const char *connector_template = NULL; - - len = 100 + os_strlen(conf_template); - if (connector_template) - len += os_strlen(connector_template); - buf = wpabuf_alloc(len); - if (!buf) - return NULL; - - /* - * DPPConfigurationParameters ::= SEQUENCE { - * configurationTemplate UTF8String, - * connectorTemplate UTF8String OPTIONAL} - */ - - asn1_put_utf8string(buf, conf_template); - if (connector_template) - asn1_put_utf8string(buf, connector_template); - return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); -} - - -static struct wpabuf * dpp_build_attribute(void) -{ - struct wpabuf *conf_params, *attr; - - /* - * aa-DPPConfigurationParameters ATTRIBUTE ::= - * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } - * - * Attribute ::= SEQUENCE { - * type OBJECT IDENTIFIER, - * values SET SIZE(1..MAX) OF Type - */ - conf_params = dpp_build_conf_params(); - conf_params = asn1_encaps(conf_params, ASN1_CLASS_UNIVERSAL, - ASN1_TAG_SET); - if (!conf_params) - return NULL; - - attr = wpabuf_alloc(100 + wpabuf_len(conf_params)); - if (!attr) { - wpabuf_clear_free(conf_params); - return NULL; - } - - asn1_put_oid(attr, &asn1_dpp_config_params_oid); - wpabuf_put_buf(attr, conf_params); - wpabuf_clear_free(conf_params); - - return asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); -} - - -static struct wpabuf * dpp_build_key_alg(const struct dpp_curve_params *curve) -{ - const struct asn1_oid *oid; - struct wpabuf *params, *res; - - switch (curve->ike_group) { - case 19: - oid = &asn1_prime256v1_oid; - break; - case 20: - oid = &asn1_secp384r1_oid; - break; - case 21: - oid = &asn1_secp521r1_oid; - break; - case 28: - oid = &asn1_brainpoolP256r1_oid; - break; - case 29: - oid = &asn1_brainpoolP384r1_oid; - break; - case 30: - oid = &asn1_brainpoolP512r1_oid; - break; - default: - return NULL; - } - - params = wpabuf_alloc(20); - if (!params) - return NULL; - asn1_put_oid(params, oid); /* namedCurve */ - - res = asn1_build_alg_id(&asn1_ec_public_key_oid, params); - wpabuf_free(params); - return res; -} - - -static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth) -{ - struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL; - EC_KEY *eckey; - unsigned char *der = NULL; - int der_len; - - eckey = EVP_PKEY_get0_EC_KEY(auth->conf->csign); - if (!eckey) - return NULL; - - EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); - der_len = i2d_ECPrivateKey(eckey, &der); - if (der_len > 0) - priv_key = wpabuf_alloc_copy(der, der_len); - OPENSSL_free(der); - - alg = dpp_build_key_alg(auth->conf->curve); - - /* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */ - attr = dpp_build_attribute(); - attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET); - if (!priv_key || !attr || !alg) - goto fail; - - /* - * OneAsymmetricKey ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] Attributes OPTIONAL, - * ..., - * [[2: publicKey [1] BIT STRING OPTIONAL ]], - * ... - * } - */ - - key = wpabuf_alloc(100 + wpabuf_len(alg) + wpabuf_len(priv_key) + - wpabuf_len(attr)); - if (!key) - goto fail; - - asn1_put_integer(key, 1); /* version = v2(1) */ - - /* PrivateKeyAlgorithmIdentifier */ - wpabuf_put_buf(key, alg); - - /* PrivateKey ::= OCTET STRING */ - asn1_put_octet_string(key, priv_key); - - /* [0] Attributes OPTIONAL */ - asn1_put_hdr(key, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, wpabuf_len(attr)); - wpabuf_put_buf(key, attr); - -fail: - wpabuf_clear_free(attr); - wpabuf_clear_free(priv_key); - wpabuf_free(alg); - - /* - * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage - * - * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey - * - * OneAsymmetricKey ::= SEQUENCE - */ - return asn1_encaps(asn1_encaps(key, - ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE), - ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); -} - - -static struct wpabuf * dpp_build_pbkdf2_alg_id(const struct wpabuf *salt, - size_t hash_len) -{ - struct wpabuf *params = NULL, *buf = NULL, *prf = NULL; - const struct asn1_oid *oid; - - /* - * PBKDF2-params ::= SEQUENCE { - * salt CHOICE { - * specified OCTET STRING, - * otherSource AlgorithmIdentifier} - * iterationCount INTEGER (1..MAX), - * keyLength INTEGER (1..MAX), - * prf AlgorithmIdentifier} - * - * salt is an 64 octet value, iterationCount is 1000, keyLength is based - * on Configurator signing key length, prf is - * id-hmacWithSHA{256,384,512} based on Configurator signing key. - */ - - if (hash_len == 32) - oid = &asn1_pbkdf2_hmac_sha256_oid; - else if (hash_len == 48) - oid = &asn1_pbkdf2_hmac_sha384_oid; - else if (hash_len == 64) - oid = &asn1_pbkdf2_hmac_sha512_oid; - else - goto fail; - prf = asn1_build_alg_id(oid, NULL); - if (!prf) - goto fail; - params = wpabuf_alloc(100 + wpabuf_len(salt) + wpabuf_len(prf)); - if (!params) - goto fail; - asn1_put_octet_string(params, salt); /* salt.specified */ - asn1_put_integer(params, 1000); /* iterationCount */ - asn1_put_integer(params, hash_len); /* keyLength */ - wpabuf_put_buf(params, prf); - params = asn1_encaps(params, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); - if (!params) - goto fail; - buf = asn1_build_alg_id(&asn1_pbkdf2_oid, params); -fail: - wpabuf_free(params); - wpabuf_free(prf); - return buf; -} - - -static struct wpabuf * -dpp_build_pw_recipient_info(struct dpp_authentication *auth, size_t hash_len, - const struct wpabuf *cont_enc_key) -{ - struct wpabuf *pwri = NULL, *enc_key = NULL, *key_der_alg = NULL, - *key_enc_alg = NULL, *salt; - u8 kek[DPP_MAX_HASH_LEN]; - const u8 *key; - size_t key_len; - - salt = wpabuf_alloc(64); - if (!salt || os_get_random(wpabuf_put(salt, 64), 64) < 0) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "DPP: PBKDF2 salt", salt); - - /* TODO: For initial testing, use ke as the key. Replace this with a - * new key once that has been defined. */ - key = auth->ke; - key_len = auth->curve->hash_len; - wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); - - if (dpp_pbkdf2(hash_len, key, key_len, wpabuf_head(salt), 64, 1000, - kek, hash_len)) { - wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); - goto fail; - } - wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", - kek, hash_len); - - enc_key = wpabuf_alloc(hash_len + AES_BLOCK_SIZE); - if (!enc_key || - aes_siv_encrypt(kek, hash_len, wpabuf_head(cont_enc_key), - wpabuf_len(cont_enc_key), 0, NULL, NULL, - wpabuf_put(enc_key, hash_len + AES_BLOCK_SIZE)) < 0) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "DPP: encryptedKey", enc_key); - - /* - * PasswordRecipientInfo ::= SEQUENCE { - * version CMSVersion, - * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, - * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, - * encryptedKey EncryptedKey} - * - * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the - * parameters contains PBKDF2-params SEQUENCE. - */ - - key_der_alg = dpp_build_pbkdf2_alg_id(salt, hash_len); - key_enc_alg = asn1_build_alg_id(&asn1_aes_siv_cmac_aead_256_oid, NULL); - if (!key_der_alg || !key_enc_alg) - goto fail; - pwri = wpabuf_alloc(100 + wpabuf_len(key_der_alg) + - wpabuf_len(key_enc_alg) + wpabuf_len(enc_key)); - if (!pwri) - goto fail; - - /* version = 0 */ - asn1_put_integer(pwri, 0); - - /* [0] KeyDerivationAlgorithmIdentifier */ - asn1_put_hdr(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, - wpabuf_len(key_der_alg)); - wpabuf_put_buf(pwri, key_der_alg); - - /* KeyEncryptionAlgorithmIdentifier */ - wpabuf_put_buf(pwri, key_enc_alg); - - /* EncryptedKey ::= OCTET STRING */ - asn1_put_octet_string(pwri, enc_key); - -fail: - wpabuf_clear_free(key_der_alg); - wpabuf_free(key_enc_alg); - wpabuf_free(enc_key); - wpabuf_free(salt); - forced_memzero(kek, sizeof(kek)); - return asn1_encaps(pwri, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); -} - - -static struct wpabuf * -dpp_build_recipient_info(struct dpp_authentication *auth, size_t hash_len, - const struct wpabuf *cont_enc_key) -{ - struct wpabuf *pwri; - - /* - * RecipientInfo ::= CHOICE { - * ktri KeyTransRecipientInfo, - * kari [1] KeyAgreeRecipientInfo, - * kekri [2] KEKRecipientInfo, - * pwri [3] PasswordRecipientInfo, - * ori [4] OtherRecipientInfo} - * - * Shall always use the pwri CHOICE. - */ - - pwri = dpp_build_pw_recipient_info(auth, hash_len, cont_enc_key); - return asn1_encaps(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 3); -} - - -static struct wpabuf * -dpp_build_enc_cont_info(struct dpp_authentication *auth, size_t hash_len, - const struct wpabuf *cont_enc_key) -{ - struct wpabuf *key_pkg, *enc_cont_info = NULL, *enc_cont = NULL, - *enc_alg; - const struct asn1_oid *oid; - size_t enc_cont_len; - - /* - * EncryptedContentInfo ::= SEQUENCE { - * contentType ContentType, - * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, - * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} - */ - - if (hash_len == 32) - oid = &asn1_aes_siv_cmac_aead_256_oid; - else if (hash_len == 48) - oid = &asn1_aes_siv_cmac_aead_384_oid; - else if (hash_len == 64) - oid = &asn1_aes_siv_cmac_aead_512_oid; - else - return NULL; - - key_pkg = dpp_build_key_pkg(auth); - enc_alg = asn1_build_alg_id(oid, NULL); - if (!key_pkg || !enc_alg) - goto fail; - - wpa_hexdump_buf_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", - key_pkg); - - enc_cont_len = wpabuf_len(key_pkg) + AES_BLOCK_SIZE; - enc_cont = wpabuf_alloc(enc_cont_len); - if (!enc_cont || - aes_siv_encrypt(wpabuf_head(cont_enc_key), wpabuf_len(cont_enc_key), - wpabuf_head(key_pkg), wpabuf_len(key_pkg), - 0, NULL, NULL, - wpabuf_put(enc_cont, enc_cont_len)) < 0) - goto fail; - - enc_cont_info = wpabuf_alloc(100 + wpabuf_len(enc_alg) + - wpabuf_len(enc_cont)); - if (!enc_cont_info) - goto fail; - - /* ContentType ::= OBJECT IDENTIFIER */ - asn1_put_oid(enc_cont_info, &asn1_dpp_asymmetric_key_package_oid); - - /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ - wpabuf_put_buf(enc_cont_info, enc_alg); - - /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL - * EncryptedContent ::= OCTET STRING */ - asn1_put_hdr(enc_cont_info, ASN1_CLASS_CONTEXT_SPECIFIC, 0, 0, - wpabuf_len(enc_cont)); - wpabuf_put_buf(enc_cont_info, enc_cont); - -fail: - wpabuf_clear_free(key_pkg); - wpabuf_free(enc_cont); - wpabuf_free(enc_alg); - return enc_cont_info; -} - - -static struct wpabuf * dpp_gen_random(size_t len) -{ - struct wpabuf *key; - - key = wpabuf_alloc(len); - if (!key || os_get_random(wpabuf_put(key, len), len) < 0) { - wpabuf_free(key); - key = NULL; - } - wpa_hexdump_buf_key(MSG_DEBUG, "DPP: content-encryption key", key); - return key; -} - - -static struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth) -{ - struct wpabuf *env = NULL; - struct wpabuf *recipient_info = NULL, *enc_cont_info = NULL; - struct wpabuf *cont_enc_key = NULL; - size_t hash_len; - - if (!auth->conf) { - wpa_printf(MSG_DEBUG, - "DPP: No Configurator instance selected for the session - cannot build DPPEnvelopedData"); - return NULL; - } - - if (!auth->provision_configurator) { - wpa_printf(MSG_DEBUG, - "DPP: Configurator provisioning not allowed"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "DPP: Building DPPEnvelopedData"); - - hash_len = auth->conf->curve->hash_len; - cont_enc_key = dpp_gen_random(hash_len); - if (!cont_enc_key) - goto fail; - recipient_info = dpp_build_recipient_info(auth, hash_len, cont_enc_key); - enc_cont_info = dpp_build_enc_cont_info(auth, hash_len, cont_enc_key); - if (!recipient_info || !enc_cont_info) - goto fail; - - env = wpabuf_alloc(wpabuf_len(recipient_info) + - wpabuf_len(enc_cont_info) + - 100); - if (!env) - goto fail; - - /* - * DPPEnvelopedData ::= EnvelopedData - * - * EnvelopedData ::= SEQUENCE { - * version CMSVersion, - * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, - * recipientInfos RecipientInfos, - * encryptedContentInfo EncryptedContentInfo, - * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} - * - * For DPP, version is 3, both originatorInfo and - * unprotectedAttrs are omitted, and recipientInfos contains a single - * RecipientInfo. - */ - - /* EnvelopedData.version = 3 */ - asn1_put_integer(env, 3); - - /* RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo */ - asn1_put_set(env, recipient_info); - - /* EncryptedContentInfo ::= SEQUENCE */ - asn1_put_sequence(env, enc_cont_info); - - env = asn1_encaps(env, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: DPPEnvelopedData", env); -out: - wpabuf_clear_free(cont_enc_key); - wpabuf_clear_free(recipient_info); - wpabuf_free(enc_cont_info); - return env; -fail: - wpabuf_free(env); - env = NULL; - goto out; -} - -#endif /* CONFIG_DPP2 */ - - static struct wpabuf * dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, u16 e_nonce_len, enum dpp_netrole netrole) @@ -3123,709 +2628,6 @@ fail: } -#ifdef CONFIG_DPP2 - -struct dpp_enveloped_data { - const u8 *enc_cont; - size_t enc_cont_len; - const u8 *enc_key; - size_t enc_key_len; - const u8 *salt; - size_t pbkdf2_key_len; - size_t prf_hash_len; -}; - - -static int dpp_parse_recipient_infos(const u8 *pos, size_t len, - struct dpp_enveloped_data *data) -{ - struct asn1_hdr hdr; - const u8 *end = pos + len; - const u8 *next, *e_end; - struct asn1_oid oid; - int val; - const u8 *params; - size_t params_len; - - wpa_hexdump(MSG_MSGDUMP, "DPP: RecipientInfos", pos, len); - - /* - * RecipientInfo ::= CHOICE { - * ktri KeyTransRecipientInfo, - * kari [1] KeyAgreeRecipientInfo, - * kekri [2] KEKRecipientInfo, - * pwri [3] PasswordRecipientInfo, - * ori [4] OtherRecipientInfo} - * - * Shall always use the pwri CHOICE. - */ - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 3) { - wpa_printf(MSG_DEBUG, - "DPP: Expected CHOICE [3] (pwri) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo", - hdr.payload, hdr.length); - pos = hdr.payload; - end = pos + hdr.length; - - /* - * PasswordRecipientInfo ::= SEQUENCE { - * version CMSVersion, - * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, - * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, - * encryptedKey EncryptedKey} - * - * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the - * parameters contains PBKDF2-params SEQUENCE. - */ - - if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) - return -1; - pos = hdr.payload; - - if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) - return -1; - if (val != 0) { - wpa_printf(MSG_DEBUG, "DPP: pwri.version != 0"); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version", - pos, end - pos); - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Expected keyDerivationAlgorithm [0] - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - e_end = pos + hdr.length; - - /* KeyDerivationAlgorithmIdentifier ::= AlgorithmIdentifier */ - if (asn1_get_alg_id(pos, e_end - pos, &oid, ¶ms, ¶ms_len, - &next) < 0) - return -1; - if (!asn1_oid_equal(&oid, &asn1_pbkdf2_oid)) { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, - "DPP: Unexpected KeyDerivationAlgorithmIdentifier %s", - buf); - return -1; - } - - /* - * PBKDF2-params ::= SEQUENCE { - * salt CHOICE { - * specified OCTET STRING, - * otherSource AlgorithmIdentifier} - * iterationCount INTEGER (1..MAX), - * keyLength INTEGER (1..MAX), - * prf AlgorithmIdentifier} - * - * salt is an 64 octet value, iterationCount is 1000, keyLength is based - * on Configurator signing key length, prf is - * id-hmacWithSHA{256,384,512} based on Configurator signing key. - */ - if (!params || - asn1_get_sequence(params, params_len, &hdr, &e_end) < 0) - return -1; - pos = hdr.payload; - - if (asn1_get_next(pos, e_end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected OCTETSTRING (salt.specified) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified", - hdr.payload, hdr.length); - if (hdr.length != 64) { - wpa_printf(MSG_DEBUG, "DPP: Unexpected salt length %u", - hdr.length); - return -1; - } - data->salt = hdr.payload; - pos = hdr.payload + hdr.length; - - if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) - return -1; - if (val != 1000) { - wpa_printf(MSG_DEBUG, "DPP: Unexpected iterationCount %d", val); - return -1; - } - - if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) - return -1; - if (val != 32 && val != 48 && val != 64) { - wpa_printf(MSG_DEBUG, "DPP: Unexpected keyLength %d", val); - return -1; - } - data->pbkdf2_key_len = val; - - if (asn1_get_sequence(pos, e_end - pos, &hdr, NULL) < 0 || - asn1_get_oid(hdr.payload, hdr.length, &oid, &pos) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Could not parse prf"); - return -1; - } - if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha256_oid)) { - data->prf_hash_len = 32; - } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha384_oid)) { - data->prf_hash_len = 48; - } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha512_oid)) { - data->prf_hash_len = 64; - } else { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "DPP: Unexpected PBKDF2-params.prf %s", - buf); - return -1; - } - - pos = next; - - /* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier - * - * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * id-alg-AES-SIV-CMAC-aed-256, id-alg-AES-SIV-CMAC-aed-384, or - * id-alg-AES-SIV-CMAC-aed-512. */ - if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) - return -1; - if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && - !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && - !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, - "DPP: Unexpected KeyEncryptionAlgorithmIdentifier %s", - buf); - return -1; - } - - /* - * encryptedKey EncryptedKey - * - * EncryptedKey ::= OCTET STRING - */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected OCTETSTRING (pwri.encryptedKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey", - hdr.payload, hdr.length); - data->enc_key = hdr.payload; - data->enc_key_len = hdr.length; - - return 0; -} - - -static int dpp_parse_encrypted_content_info(const u8 *pos, const u8 *end, - struct dpp_enveloped_data *data) -{ - struct asn1_hdr hdr; - struct asn1_oid oid; - - /* - * EncryptedContentInfo ::= SEQUENCE { - * contentType ContentType, - * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, - * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} - */ - if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) - return -1; - wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContentInfo", - hdr.payload, hdr.length); - if (pos < end) { - wpa_hexdump(MSG_DEBUG, - "DPP: Unexpected extra data after EncryptedContentInfo", - pos, end - pos); - return -1; - } - - end = pos; - pos = hdr.payload; - - /* ContentType ::= OBJECT IDENTIFIER */ - if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Could not parse ContentType"); - return -1; - } - if (!asn1_oid_equal(&oid, &asn1_dpp_asymmetric_key_package_oid)) { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "DPP: Unexpected ContentType %s", buf); - return -1; - } - - /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ - if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) - return -1; - if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && - !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && - !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, - "DPP: Unexpected ContentEncryptionAlgorithmIdentifier %s", - buf); - return -1; - } - /* ignore optional parameters */ - - /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL - * EncryptedContent ::= OCTET STRING */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Expected [0] IMPLICIT (EncryptedContent) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent", - hdr.payload, hdr.length); - data->enc_cont = hdr.payload; - data->enc_cont_len = hdr.length; - return 0; -} - - -static int dpp_parse_enveloped_data(const u8 *env_data, size_t env_data_len, - struct dpp_enveloped_data *data) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - int val; - - os_memset(data, 0, sizeof(*data)); - - /* - * DPPEnvelopedData ::= EnvelopedData - * - * EnvelopedData ::= SEQUENCE { - * version CMSVersion, - * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, - * recipientInfos RecipientInfos, - * encryptedContentInfo EncryptedContentInfo, - * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} - * - * CMSVersion ::= INTEGER - * - * RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo - * - * For DPP, version is 3, both originatorInfo and - * unprotectedAttrs are omitted, and recipientInfos contains a single - * RecipientInfo. - */ - if (asn1_get_sequence(env_data, env_data_len, &hdr, &end) < 0) - return -1; - pos = hdr.payload; - if (end < env_data + env_data_len) { - wpa_hexdump(MSG_DEBUG, - "DPP: Unexpected extra data after DPPEnvelopedData", - end, env_data + env_data_len - end); - return -1; - } - - if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) - return -1; - if (val != 3) { - wpa_printf(MSG_DEBUG, "DPP: EnvelopedData.version != 3"); - return -1; - } - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { - wpa_printf(MSG_DEBUG, - "DPP: Expected SET (RecipientInfos) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - if (dpp_parse_recipient_infos(hdr.payload, hdr.length, data) < 0) - return -1; - return dpp_parse_encrypted_content_info(hdr.payload + hdr.length, end, - data); -} - - -static struct dpp_asymmetric_key * -dpp_parse_one_asymmetric_key(const u8 *buf, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos = buf, *end = buf + len, *next; - int val; - const u8 *params; - size_t params_len; - struct asn1_oid oid; - char txt[80]; - struct dpp_asymmetric_key *key; - EC_KEY *eckey; - - wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len); - - key = os_zalloc(sizeof(*key)); - if (!key) - return NULL; - - /* - * OneAsymmetricKey ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] Attributes OPTIONAL, - * ..., - * [[2: publicKey [1] BIT STRING OPTIONAL ]], - * ... - * } - */ - if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) - goto fail; - pos = hdr.payload; - - /* Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) */ - if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) - goto fail; - if (val != 1) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported DPPAsymmetricKeyPackage version %d", - val); - goto fail; - } - - /* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier */ - if (asn1_get_alg_id(pos, end - pos, &oid, ¶ms, ¶ms_len, - &pos) < 0) - goto fail; - if (!asn1_oid_equal(&oid, &asn1_ec_public_key_oid)) { - asn1_oid_to_str(&oid, txt, sizeof(txt)); - wpa_printf(MSG_DEBUG, - "DPP: Unsupported PrivateKeyAlgorithmIdentifier %s", - txt); - goto fail; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: PrivateKeyAlgorithmIdentifier params", - params, params_len); - /* - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * -- implicitCurve NULL - * -- specifiedCurve SpecifiedECDomain} - */ - if (!params || asn1_get_oid(params, params_len, &oid, &next) < 0) { - wpa_printf(MSG_DEBUG, - "DPP: Could not parse ECParameters.namedCurve"); - goto fail; - } - asn1_oid_to_str(&oid, txt, sizeof(txt)); - wpa_printf(MSG_MSGDUMP, "DPP: namedCurve %s", txt); - /* Assume the curve is identified within ECPrivateKey, so that this - * separate indication is not really needed. */ - - /* - * PrivateKey ::= OCTET STRING - * (Contains DER encoding of ECPrivateKey) - */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey", - hdr.payload, hdr.length); - pos = hdr.payload + hdr.length; - eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length); - if (!eckey) { - wpa_printf(MSG_INFO, - "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - key->csign = EVP_PKEY_new(); - if (!key->csign || EVP_PKEY_assign_EC_KEY(key->csign, eckey) != 1) { - EC_KEY_free(eckey); - goto fail; - } - if (wpa_debug_show_keys) - dpp_debug_print_key("DPP: Received c-sign-key", key->csign); - - /* - * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } - * - * Exactly one instance of type Attribute in OneAsymmetricKey. - */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Expected [0] Attributes - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes", - hdr.payload, hdr.length); - if (hdr.payload + hdr.length < end) { - wpa_hexdump_key(MSG_MSGDUMP, - "DPP: Ignore additional data at the end of OneAsymmetricKey", - hdr.payload + hdr.length, - end - (hdr.payload + hdr.length)); - } - pos = hdr.payload; - end = hdr.payload + hdr.length; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { - wpa_printf(MSG_DEBUG, - "DPP: Expected SET (Attributes) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - if (hdr.payload + hdr.length < end) { - wpa_hexdump_key(MSG_MSGDUMP, - "DPP: Ignore additional data at the end of OneAsymmetricKey (after SET)", - hdr.payload + hdr.length, - end - (hdr.payload + hdr.length)); - } - pos = hdr.payload; - end = hdr.payload + hdr.length; - - /* - * OneAsymmetricKeyAttributes ATTRIBUTE ::= { - * aa-DPPConfigurationParameters, - * ... -- For local profiles - * } - * - * aa-DPPConfigurationParameters ATTRIBUTE ::= - * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } - * - * Attribute ::= SEQUENCE { - * type OBJECT IDENTIFIER, - * values SET SIZE(1..MAX) OF Type - * - * Exactly one instance of ATTRIBUTE in attrValues. - */ - if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) - goto fail; - if (pos < end) { - wpa_hexdump_key(MSG_MSGDUMP, - "DPP: Ignore additional data at the end of ATTRIBUTE", - pos, end - pos); - } - end = pos; - pos = hdr.payload; - - if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) - goto fail; - if (!asn1_oid_equal(&oid, &asn1_dpp_config_params_oid)) { - asn1_oid_to_str(&oid, txt, sizeof(txt)); - wpa_printf(MSG_DEBUG, - "DPP: Unexpected Attribute identifier %s", txt); - goto fail; - } - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { - wpa_printf(MSG_DEBUG, - "DPP: Expected SET (Attribute) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - pos = hdr.payload; - end = hdr.payload + hdr.length; - - /* - * DPPConfigurationParameters ::= SEQUENCE { - * configurationTemplate UTF8String, - * connectorTemplate UTF8String OPTIONAL} - */ - - wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPConfigurationParameters", - pos, end - pos); - if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) - goto fail; - if (pos < end) { - wpa_hexdump_key(MSG_MSGDUMP, - "DPP: Ignore additional data after DPPConfigurationParameters", - pos, end - pos); - } - end = pos; - pos = hdr.payload; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_UTF8STRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected UTF8STRING (configurationTemplate) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate", - hdr.payload, hdr.length); - key->config_template = os_zalloc(hdr.length + 1); - if (!key->config_template) - goto fail; - os_memcpy(key->config_template, hdr.payload, hdr.length); - - pos = hdr.payload + hdr.length; - - if (pos < end) { - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_UTF8STRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected UTF8STRING (connectorTemplate) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate", - hdr.payload, hdr.length); - key->connector_template = os_zalloc(hdr.length + 1); - if (!key->connector_template) - goto fail; - os_memcpy(key->connector_template, hdr.payload, hdr.length); - } - - return key; -fail: - wpa_printf(MSG_DEBUG, "DPP: Failed to parse OneAsymmetricKey"); - dpp_free_asymmetric_key(key); - return NULL; -} - - -static struct dpp_asymmetric_key * -dpp_parse_dpp_asymmetric_key_package(const u8 *key_pkg, size_t key_pkg_len) -{ - struct asn1_hdr hdr; - const u8 *pos = key_pkg, *end = key_pkg + key_pkg_len; - struct dpp_asymmetric_key *first = NULL, *last = NULL, *key; - - wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", - key_pkg, key_pkg_len); - - /* - * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage - * - * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey - */ - while (pos < end) { - if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0 || - !(key = dpp_parse_one_asymmetric_key(hdr.payload, - hdr.length))) { - dpp_free_asymmetric_key(first); - return NULL; - } - if (!last) { - first = last = key; - } else { - last->next = key; - last = key; - } - } - - return first; -} - - -static int dpp_conf_resp_env_data(struct dpp_authentication *auth, - const u8 *env_data, size_t env_data_len) -{ - const u8 *key; - size_t key_len; - u8 kek[DPP_MAX_HASH_LEN]; - u8 cont_encr_key[DPP_MAX_HASH_LEN]; - size_t cont_encr_key_len; - int res; - u8 *key_pkg; - size_t key_pkg_len; - struct dpp_enveloped_data data; - struct dpp_asymmetric_key *keys; - - wpa_hexdump(MSG_DEBUG, "DPP: DPPEnvelopedData", env_data, env_data_len); - - if (dpp_parse_enveloped_data(env_data, env_data_len, &data) < 0) - return -1; - - /* TODO: For initial testing, use ke as the key. Replace this with a - * new key once that has been defined. */ - key = auth->ke; - key_len = auth->curve->hash_len; - wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); - - if (dpp_pbkdf2(data.prf_hash_len, key, key_len, data.salt, 64, 1000, - kek, data.pbkdf2_key_len)) { - wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", - kek, data.pbkdf2_key_len); - - if (data.enc_key_len < AES_BLOCK_SIZE || - data.enc_key_len > sizeof(cont_encr_key) + AES_BLOCK_SIZE) { - wpa_printf(MSG_DEBUG, "DPP: Invalid encryptedKey length"); - return -1; - } - res = aes_siv_decrypt(kek, data.pbkdf2_key_len, - data.enc_key, data.enc_key_len, - 0, NULL, NULL, cont_encr_key); - forced_memzero(kek, data.pbkdf2_key_len); - if (res < 0) { - wpa_printf(MSG_DEBUG, - "DPP: AES-SIV decryption of encryptedKey failed"); - return -1; - } - cont_encr_key_len = data.enc_key_len - AES_BLOCK_SIZE; - wpa_hexdump_key(MSG_DEBUG, "DPP: content-encryption key", - cont_encr_key, cont_encr_key_len); - - if (data.enc_cont_len < AES_BLOCK_SIZE) - return -1; - key_pkg_len = data.enc_cont_len - AES_BLOCK_SIZE; - key_pkg = os_malloc(key_pkg_len); - if (!key_pkg) - return -1; - res = aes_siv_decrypt(cont_encr_key, cont_encr_key_len, - data.enc_cont, data.enc_cont_len, - 0, NULL, NULL, key_pkg); - forced_memzero(cont_encr_key, cont_encr_key_len); - if (res < 0) { - bin_clear_free(key_pkg, key_pkg_len); - wpa_printf(MSG_DEBUG, - "DPP: AES-SIV decryption of encryptedContent failed"); - return -1; - } - - keys = dpp_parse_dpp_asymmetric_key_package(key_pkg, key_pkg_len); - bin_clear_free(key_pkg, key_pkg_len); - dpp_free_asymmetric_key(auth->conf_key_pkg); - auth->conf_key_pkg = keys; - - return keys != NULL;; -} - -#endif /* CONFIG_DPP2 */ - - int dpp_conf_resp_rx(struct dpp_authentication *auth, const struct wpabuf *resp) { diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c new file mode 100644 index 000000000..4bd5ba616 --- /dev/null +++ b/src/common/dpp_backup.c @@ -0,0 +1,1211 @@ +/* + * DPP configurator backup + * Copyright (c) 2019-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include + +#include "utils/common.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "tls/asn1.h" +#include "dpp.h" +#include "dpp_i.h" + +#ifdef CONFIG_DPP2 + +void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key) +{ + while (key) { + struct dpp_asymmetric_key *next = key->next; + + EVP_PKEY_free(key->csign); + str_clear_free(key->config_template); + str_clear_free(key->connector_template); + os_free(key); + key = next; + } +} + + +static struct wpabuf * dpp_build_conf_params(void) +{ + struct wpabuf *buf; + size_t len; + /* TODO: proper template values */ + const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}"; + const char *connector_template = NULL; + + len = 100 + os_strlen(conf_template); + if (connector_template) + len += os_strlen(connector_template); + buf = wpabuf_alloc(len); + if (!buf) + return NULL; + + /* + * DPPConfigurationParameters ::= SEQUENCE { + * configurationTemplate UTF8String, + * connectorTemplate UTF8String OPTIONAL} + */ + + asn1_put_utf8string(buf, conf_template); + if (connector_template) + asn1_put_utf8string(buf, connector_template); + return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +} + + +static struct wpabuf * dpp_build_attribute(void) +{ + struct wpabuf *conf_params, *attr; + + /* + * aa-DPPConfigurationParameters ATTRIBUTE ::= + * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } + * + * Attribute ::= SEQUENCE { + * type OBJECT IDENTIFIER, + * values SET SIZE(1..MAX) OF Type + */ + conf_params = dpp_build_conf_params(); + conf_params = asn1_encaps(conf_params, ASN1_CLASS_UNIVERSAL, + ASN1_TAG_SET); + if (!conf_params) + return NULL; + + attr = wpabuf_alloc(100 + wpabuf_len(conf_params)); + if (!attr) { + wpabuf_clear_free(conf_params); + return NULL; + } + + asn1_put_oid(attr, &asn1_dpp_config_params_oid); + wpabuf_put_buf(attr, conf_params); + wpabuf_clear_free(conf_params); + + return asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +} + + +static struct wpabuf * dpp_build_key_alg(const struct dpp_curve_params *curve) +{ + const struct asn1_oid *oid; + struct wpabuf *params, *res; + + switch (curve->ike_group) { + case 19: + oid = &asn1_prime256v1_oid; + break; + case 20: + oid = &asn1_secp384r1_oid; + break; + case 21: + oid = &asn1_secp521r1_oid; + break; + case 28: + oid = &asn1_brainpoolP256r1_oid; + break; + case 29: + oid = &asn1_brainpoolP384r1_oid; + break; + case 30: + oid = &asn1_brainpoolP512r1_oid; + break; + default: + return NULL; + } + + params = wpabuf_alloc(20); + if (!params) + return NULL; + asn1_put_oid(params, oid); /* namedCurve */ + + res = asn1_build_alg_id(&asn1_ec_public_key_oid, params); + wpabuf_free(params); + return res; +} + + +static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth) +{ + struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL; + EC_KEY *eckey; + unsigned char *der = NULL; + int der_len; + + eckey = EVP_PKEY_get0_EC_KEY(auth->conf->csign); + if (!eckey) + return NULL; + + EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len > 0) + priv_key = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + + alg = dpp_build_key_alg(auth->conf->curve); + + /* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */ + attr = dpp_build_attribute(); + attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET); + if (!priv_key || !attr || !alg) + goto fail; + + /* + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] BIT STRING OPTIONAL ]], + * ... + * } + */ + + key = wpabuf_alloc(100 + wpabuf_len(alg) + wpabuf_len(priv_key) + + wpabuf_len(attr)); + if (!key) + goto fail; + + asn1_put_integer(key, 1); /* version = v2(1) */ + + /* PrivateKeyAlgorithmIdentifier */ + wpabuf_put_buf(key, alg); + + /* PrivateKey ::= OCTET STRING */ + asn1_put_octet_string(key, priv_key); + + /* [0] Attributes OPTIONAL */ + asn1_put_hdr(key, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, wpabuf_len(attr)); + wpabuf_put_buf(key, attr); + +fail: + wpabuf_clear_free(attr); + wpabuf_clear_free(priv_key); + wpabuf_free(alg); + + /* + * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage + * + * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey + * + * OneAsymmetricKey ::= SEQUENCE + */ + return asn1_encaps(asn1_encaps(key, + ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE), + ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +} + + +static struct wpabuf * dpp_build_pbkdf2_alg_id(const struct wpabuf *salt, + size_t hash_len) +{ + struct wpabuf *params = NULL, *buf = NULL, *prf = NULL; + const struct asn1_oid *oid; + + /* + * PBKDF2-params ::= SEQUENCE { + * salt CHOICE { + * specified OCTET STRING, + * otherSource AlgorithmIdentifier} + * iterationCount INTEGER (1..MAX), + * keyLength INTEGER (1..MAX), + * prf AlgorithmIdentifier} + * + * salt is an 64 octet value, iterationCount is 1000, keyLength is based + * on Configurator signing key length, prf is + * id-hmacWithSHA{256,384,512} based on Configurator signing key. + */ + + if (hash_len == 32) + oid = &asn1_pbkdf2_hmac_sha256_oid; + else if (hash_len == 48) + oid = &asn1_pbkdf2_hmac_sha384_oid; + else if (hash_len == 64) + oid = &asn1_pbkdf2_hmac_sha512_oid; + else + goto fail; + prf = asn1_build_alg_id(oid, NULL); + if (!prf) + goto fail; + params = wpabuf_alloc(100 + wpabuf_len(salt) + wpabuf_len(prf)); + if (!params) + goto fail; + asn1_put_octet_string(params, salt); /* salt.specified */ + asn1_put_integer(params, 1000); /* iterationCount */ + asn1_put_integer(params, hash_len); /* keyLength */ + wpabuf_put_buf(params, prf); + params = asn1_encaps(params, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); + if (!params) + goto fail; + buf = asn1_build_alg_id(&asn1_pbkdf2_oid, params); +fail: + wpabuf_free(params); + wpabuf_free(prf); + return buf; +} + + +static struct wpabuf * +dpp_build_pw_recipient_info(struct dpp_authentication *auth, size_t hash_len, + const struct wpabuf *cont_enc_key) +{ + struct wpabuf *pwri = NULL, *enc_key = NULL, *key_der_alg = NULL, + *key_enc_alg = NULL, *salt; + u8 kek[DPP_MAX_HASH_LEN]; + const u8 *key; + size_t key_len; + + salt = wpabuf_alloc(64); + if (!salt || os_get_random(wpabuf_put(salt, 64), 64) < 0) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "DPP: PBKDF2 salt", salt); + + /* TODO: For initial testing, use ke as the key. Replace this with a + * new key once that has been defined. */ + key = auth->ke; + key_len = auth->curve->hash_len; + wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); + + if (dpp_pbkdf2(hash_len, key, key_len, wpabuf_head(salt), 64, 1000, + kek, hash_len)) { + wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", + kek, hash_len); + + enc_key = wpabuf_alloc(hash_len + AES_BLOCK_SIZE); + if (!enc_key || + aes_siv_encrypt(kek, hash_len, wpabuf_head(cont_enc_key), + wpabuf_len(cont_enc_key), 0, NULL, NULL, + wpabuf_put(enc_key, hash_len + AES_BLOCK_SIZE)) < 0) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "DPP: encryptedKey", enc_key); + + /* + * PasswordRecipientInfo ::= SEQUENCE { + * version CMSVersion, + * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * encryptedKey EncryptedKey} + * + * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the + * parameters contains PBKDF2-params SEQUENCE. + */ + + key_der_alg = dpp_build_pbkdf2_alg_id(salt, hash_len); + key_enc_alg = asn1_build_alg_id(&asn1_aes_siv_cmac_aead_256_oid, NULL); + if (!key_der_alg || !key_enc_alg) + goto fail; + pwri = wpabuf_alloc(100 + wpabuf_len(key_der_alg) + + wpabuf_len(key_enc_alg) + wpabuf_len(enc_key)); + if (!pwri) + goto fail; + + /* version = 0 */ + asn1_put_integer(pwri, 0); + + /* [0] KeyDerivationAlgorithmIdentifier */ + asn1_put_hdr(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, + wpabuf_len(key_der_alg)); + wpabuf_put_buf(pwri, key_der_alg); + + /* KeyEncryptionAlgorithmIdentifier */ + wpabuf_put_buf(pwri, key_enc_alg); + + /* EncryptedKey ::= OCTET STRING */ + asn1_put_octet_string(pwri, enc_key); + +fail: + wpabuf_clear_free(key_der_alg); + wpabuf_free(key_enc_alg); + wpabuf_free(enc_key); + wpabuf_free(salt); + forced_memzero(kek, sizeof(kek)); + return asn1_encaps(pwri, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +} + + +static struct wpabuf * +dpp_build_recipient_info(struct dpp_authentication *auth, size_t hash_len, + const struct wpabuf *cont_enc_key) +{ + struct wpabuf *pwri; + + /* + * RecipientInfo ::= CHOICE { + * ktri KeyTransRecipientInfo, + * kari [1] KeyAgreeRecipientInfo, + * kekri [2] KEKRecipientInfo, + * pwri [3] PasswordRecipientInfo, + * ori [4] OtherRecipientInfo} + * + * Shall always use the pwri CHOICE. + */ + + pwri = dpp_build_pw_recipient_info(auth, hash_len, cont_enc_key); + return asn1_encaps(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 3); +} + + +static struct wpabuf * +dpp_build_enc_cont_info(struct dpp_authentication *auth, size_t hash_len, + const struct wpabuf *cont_enc_key) +{ + struct wpabuf *key_pkg, *enc_cont_info = NULL, *enc_cont = NULL, + *enc_alg; + const struct asn1_oid *oid; + size_t enc_cont_len; + + /* + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} + */ + + if (hash_len == 32) + oid = &asn1_aes_siv_cmac_aead_256_oid; + else if (hash_len == 48) + oid = &asn1_aes_siv_cmac_aead_384_oid; + else if (hash_len == 64) + oid = &asn1_aes_siv_cmac_aead_512_oid; + else + return NULL; + + key_pkg = dpp_build_key_pkg(auth); + enc_alg = asn1_build_alg_id(oid, NULL); + if (!key_pkg || !enc_alg) + goto fail; + + wpa_hexdump_buf_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", + key_pkg); + + enc_cont_len = wpabuf_len(key_pkg) + AES_BLOCK_SIZE; + enc_cont = wpabuf_alloc(enc_cont_len); + if (!enc_cont || + aes_siv_encrypt(wpabuf_head(cont_enc_key), wpabuf_len(cont_enc_key), + wpabuf_head(key_pkg), wpabuf_len(key_pkg), + 0, NULL, NULL, + wpabuf_put(enc_cont, enc_cont_len)) < 0) + goto fail; + + enc_cont_info = wpabuf_alloc(100 + wpabuf_len(enc_alg) + + wpabuf_len(enc_cont)); + if (!enc_cont_info) + goto fail; + + /* ContentType ::= OBJECT IDENTIFIER */ + asn1_put_oid(enc_cont_info, &asn1_dpp_asymmetric_key_package_oid); + + /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ + wpabuf_put_buf(enc_cont_info, enc_alg); + + /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL + * EncryptedContent ::= OCTET STRING */ + asn1_put_hdr(enc_cont_info, ASN1_CLASS_CONTEXT_SPECIFIC, 0, 0, + wpabuf_len(enc_cont)); + wpabuf_put_buf(enc_cont_info, enc_cont); + +fail: + wpabuf_clear_free(key_pkg); + wpabuf_free(enc_cont); + wpabuf_free(enc_alg); + return enc_cont_info; +} + + +static struct wpabuf * dpp_gen_random(size_t len) +{ + struct wpabuf *key; + + key = wpabuf_alloc(len); + if (!key || os_get_random(wpabuf_put(key, len), len) < 0) { + wpabuf_free(key); + key = NULL; + } + wpa_hexdump_buf_key(MSG_DEBUG, "DPP: content-encryption key", key); + return key; +} + + +struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth) +{ + struct wpabuf *env = NULL; + struct wpabuf *recipient_info = NULL, *enc_cont_info = NULL; + struct wpabuf *cont_enc_key = NULL; + size_t hash_len; + + if (!auth->conf) { + wpa_printf(MSG_DEBUG, + "DPP: No Configurator instance selected for the session - cannot build DPPEnvelopedData"); + return NULL; + } + + if (!auth->provision_configurator) { + wpa_printf(MSG_DEBUG, + "DPP: Configurator provisioning not allowed"); + return NULL; + } + + wpa_printf(MSG_DEBUG, "DPP: Building DPPEnvelopedData"); + + hash_len = auth->conf->curve->hash_len; + cont_enc_key = dpp_gen_random(hash_len); + if (!cont_enc_key) + goto fail; + recipient_info = dpp_build_recipient_info(auth, hash_len, cont_enc_key); + enc_cont_info = dpp_build_enc_cont_info(auth, hash_len, cont_enc_key); + if (!recipient_info || !enc_cont_info) + goto fail; + + env = wpabuf_alloc(wpabuf_len(recipient_info) + + wpabuf_len(enc_cont_info) + + 100); + if (!env) + goto fail; + + /* + * DPPEnvelopedData ::= EnvelopedData + * + * EnvelopedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * encryptedContentInfo EncryptedContentInfo, + * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} + * + * For DPP, version is 3, both originatorInfo and + * unprotectedAttrs are omitted, and recipientInfos contains a single + * RecipientInfo. + */ + + /* EnvelopedData.version = 3 */ + asn1_put_integer(env, 3); + + /* RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo */ + asn1_put_set(env, recipient_info); + + /* EncryptedContentInfo ::= SEQUENCE */ + asn1_put_sequence(env, enc_cont_info); + + env = asn1_encaps(env, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: DPPEnvelopedData", env); +out: + wpabuf_clear_free(cont_enc_key); + wpabuf_clear_free(recipient_info); + wpabuf_free(enc_cont_info); + return env; +fail: + wpabuf_free(env); + env = NULL; + goto out; +} + + +struct dpp_enveloped_data { + const u8 *enc_cont; + size_t enc_cont_len; + const u8 *enc_key; + size_t enc_key_len; + const u8 *salt; + size_t pbkdf2_key_len; + size_t prf_hash_len; +}; + + +static int dpp_parse_recipient_infos(const u8 *pos, size_t len, + struct dpp_enveloped_data *data) +{ + struct asn1_hdr hdr; + const u8 *end = pos + len; + const u8 *next, *e_end; + struct asn1_oid oid; + int val; + const u8 *params; + size_t params_len; + + wpa_hexdump(MSG_MSGDUMP, "DPP: RecipientInfos", pos, len); + + /* + * RecipientInfo ::= CHOICE { + * ktri KeyTransRecipientInfo, + * kari [1] KeyAgreeRecipientInfo, + * kekri [2] KEKRecipientInfo, + * pwri [3] PasswordRecipientInfo, + * ori [4] OtherRecipientInfo} + * + * Shall always use the pwri CHOICE. + */ + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 3) { + wpa_printf(MSG_DEBUG, + "DPP: Expected CHOICE [3] (pwri) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo", + hdr.payload, hdr.length); + pos = hdr.payload; + end = pos + hdr.length; + + /* + * PasswordRecipientInfo ::= SEQUENCE { + * version CMSVersion, + * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * encryptedKey EncryptedKey} + * + * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the + * parameters contains PBKDF2-params SEQUENCE. + */ + + if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) + return -1; + pos = hdr.payload; + + if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) + return -1; + if (val != 0) { + wpa_printf(MSG_DEBUG, "DPP: pwri.version != 0"); + return -1; + } + + wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version", + pos, end - pos); + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Expected keyDerivationAlgorithm [0] - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + e_end = pos + hdr.length; + + /* KeyDerivationAlgorithmIdentifier ::= AlgorithmIdentifier */ + if (asn1_get_alg_id(pos, e_end - pos, &oid, ¶ms, ¶ms_len, + &next) < 0) + return -1; + if (!asn1_oid_equal(&oid, &asn1_pbkdf2_oid)) { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, + "DPP: Unexpected KeyDerivationAlgorithmIdentifier %s", + buf); + return -1; + } + + /* + * PBKDF2-params ::= SEQUENCE { + * salt CHOICE { + * specified OCTET STRING, + * otherSource AlgorithmIdentifier} + * iterationCount INTEGER (1..MAX), + * keyLength INTEGER (1..MAX), + * prf AlgorithmIdentifier} + * + * salt is an 64 octet value, iterationCount is 1000, keyLength is based + * on Configurator signing key length, prf is + * id-hmacWithSHA{256,384,512} based on Configurator signing key. + */ + if (!params || + asn1_get_sequence(params, params_len, &hdr, &e_end) < 0) + return -1; + pos = hdr.payload; + + if (asn1_get_next(pos, e_end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected OCTETSTRING (salt.specified) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified", + hdr.payload, hdr.length); + if (hdr.length != 64) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected salt length %u", + hdr.length); + return -1; + } + data->salt = hdr.payload; + pos = hdr.payload + hdr.length; + + if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) + return -1; + if (val != 1000) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected iterationCount %d", val); + return -1; + } + + if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) + return -1; + if (val != 32 && val != 48 && val != 64) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected keyLength %d", val); + return -1; + } + data->pbkdf2_key_len = val; + + if (asn1_get_sequence(pos, e_end - pos, &hdr, NULL) < 0 || + asn1_get_oid(hdr.payload, hdr.length, &oid, &pos) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Could not parse prf"); + return -1; + } + if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha256_oid)) { + data->prf_hash_len = 32; + } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha384_oid)) { + data->prf_hash_len = 48; + } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha512_oid)) { + data->prf_hash_len = 64; + } else { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, "DPP: Unexpected PBKDF2-params.prf %s", + buf); + return -1; + } + + pos = next; + + /* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier + * + * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * id-alg-AES-SIV-CMAC-aed-256, id-alg-AES-SIV-CMAC-aed-384, or + * id-alg-AES-SIV-CMAC-aed-512. */ + if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) + return -1; + if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && + !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && + !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, + "DPP: Unexpected KeyEncryptionAlgorithmIdentifier %s", + buf); + return -1; + } + + /* + * encryptedKey EncryptedKey + * + * EncryptedKey ::= OCTET STRING + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected OCTETSTRING (pwri.encryptedKey) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey", + hdr.payload, hdr.length); + data->enc_key = hdr.payload; + data->enc_key_len = hdr.length; + + return 0; +} + + +static int dpp_parse_encrypted_content_info(const u8 *pos, const u8 *end, + struct dpp_enveloped_data *data) +{ + struct asn1_hdr hdr; + struct asn1_oid oid; + + /* + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} + */ + if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) + return -1; + wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContentInfo", + hdr.payload, hdr.length); + if (pos < end) { + wpa_hexdump(MSG_DEBUG, + "DPP: Unexpected extra data after EncryptedContentInfo", + pos, end - pos); + return -1; + } + + end = pos; + pos = hdr.payload; + + /* ContentType ::= OBJECT IDENTIFIER */ + if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Could not parse ContentType"); + return -1; + } + if (!asn1_oid_equal(&oid, &asn1_dpp_asymmetric_key_package_oid)) { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, "DPP: Unexpected ContentType %s", buf); + return -1; + } + + /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ + if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) + return -1; + if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && + !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && + !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, + "DPP: Unexpected ContentEncryptionAlgorithmIdentifier %s", + buf); + return -1; + } + /* ignore optional parameters */ + + /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL + * EncryptedContent ::= OCTET STRING */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Expected [0] IMPLICIT (EncryptedContent) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent", + hdr.payload, hdr.length); + data->enc_cont = hdr.payload; + data->enc_cont_len = hdr.length; + return 0; +} + + +static int dpp_parse_enveloped_data(const u8 *env_data, size_t env_data_len, + struct dpp_enveloped_data *data) +{ + struct asn1_hdr hdr; + const u8 *pos, *end; + int val; + + os_memset(data, 0, sizeof(*data)); + + /* + * DPPEnvelopedData ::= EnvelopedData + * + * EnvelopedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * encryptedContentInfo EncryptedContentInfo, + * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} + * + * CMSVersion ::= INTEGER + * + * RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo + * + * For DPP, version is 3, both originatorInfo and + * unprotectedAttrs are omitted, and recipientInfos contains a single + * RecipientInfo. + */ + if (asn1_get_sequence(env_data, env_data_len, &hdr, &end) < 0) + return -1; + pos = hdr.payload; + if (end < env_data + env_data_len) { + wpa_hexdump(MSG_DEBUG, + "DPP: Unexpected extra data after DPPEnvelopedData", + end, env_data + env_data_len - end); + return -1; + } + + if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) + return -1; + if (val != 3) { + wpa_printf(MSG_DEBUG, "DPP: EnvelopedData.version != 3"); + return -1; + } + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { + wpa_printf(MSG_DEBUG, + "DPP: Expected SET (RecipientInfos) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + + if (dpp_parse_recipient_infos(hdr.payload, hdr.length, data) < 0) + return -1; + return dpp_parse_encrypted_content_info(hdr.payload + hdr.length, end, + data); +} + + +static struct dpp_asymmetric_key * +dpp_parse_one_asymmetric_key(const u8 *buf, size_t len) +{ + struct asn1_hdr hdr; + const u8 *pos = buf, *end = buf + len, *next; + int val; + const u8 *params; + size_t params_len; + struct asn1_oid oid; + char txt[80]; + struct dpp_asymmetric_key *key; + EC_KEY *eckey; + + wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len); + + key = os_zalloc(sizeof(*key)); + if (!key) + return NULL; + + /* + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] BIT STRING OPTIONAL ]], + * ... + * } + */ + if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) + goto fail; + pos = hdr.payload; + + /* Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) */ + if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) + goto fail; + if (val != 1) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported DPPAsymmetricKeyPackage version %d", + val); + goto fail; + } + + /* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier */ + if (asn1_get_alg_id(pos, end - pos, &oid, ¶ms, ¶ms_len, + &pos) < 0) + goto fail; + if (!asn1_oid_equal(&oid, &asn1_ec_public_key_oid)) { + asn1_oid_to_str(&oid, txt, sizeof(txt)); + wpa_printf(MSG_DEBUG, + "DPP: Unsupported PrivateKeyAlgorithmIdentifier %s", + txt); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: PrivateKeyAlgorithmIdentifier params", + params, params_len); + /* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * -- implicitCurve NULL + * -- specifiedCurve SpecifiedECDomain} + */ + if (!params || asn1_get_oid(params, params_len, &oid, &next) < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Could not parse ECParameters.namedCurve"); + goto fail; + } + asn1_oid_to_str(&oid, txt, sizeof(txt)); + wpa_printf(MSG_MSGDUMP, "DPP: namedCurve %s", txt); + /* Assume the curve is identified within ECPrivateKey, so that this + * separate indication is not really needed. */ + + /* + * PrivateKey ::= OCTET STRING + * (Contains DER encoding of ECPrivateKey) + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey", + hdr.payload, hdr.length); + pos = hdr.payload + hdr.length; + eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length); + if (!eckey) { + wpa_printf(MSG_INFO, + "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + key->csign = EVP_PKEY_new(); + if (!key->csign || EVP_PKEY_assign_EC_KEY(key->csign, eckey) != 1) { + EC_KEY_free(eckey); + goto fail; + } + if (wpa_debug_show_keys) + dpp_debug_print_key("DPP: Received c-sign-key", key->csign); + + /* + * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } + * + * Exactly one instance of type Attribute in OneAsymmetricKey. + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Expected [0] Attributes - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes", + hdr.payload, hdr.length); + if (hdr.payload + hdr.length < end) { + wpa_hexdump_key(MSG_MSGDUMP, + "DPP: Ignore additional data at the end of OneAsymmetricKey", + hdr.payload + hdr.length, + end - (hdr.payload + hdr.length)); + } + pos = hdr.payload; + end = hdr.payload + hdr.length; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { + wpa_printf(MSG_DEBUG, + "DPP: Expected SET (Attributes) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + if (hdr.payload + hdr.length < end) { + wpa_hexdump_key(MSG_MSGDUMP, + "DPP: Ignore additional data at the end of OneAsymmetricKey (after SET)", + hdr.payload + hdr.length, + end - (hdr.payload + hdr.length)); + } + pos = hdr.payload; + end = hdr.payload + hdr.length; + + /* + * OneAsymmetricKeyAttributes ATTRIBUTE ::= { + * aa-DPPConfigurationParameters, + * ... -- For local profiles + * } + * + * aa-DPPConfigurationParameters ATTRIBUTE ::= + * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } + * + * Attribute ::= SEQUENCE { + * type OBJECT IDENTIFIER, + * values SET SIZE(1..MAX) OF Type + * + * Exactly one instance of ATTRIBUTE in attrValues. + */ + if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) + goto fail; + if (pos < end) { + wpa_hexdump_key(MSG_MSGDUMP, + "DPP: Ignore additional data at the end of ATTRIBUTE", + pos, end - pos); + } + end = pos; + pos = hdr.payload; + + if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) + goto fail; + if (!asn1_oid_equal(&oid, &asn1_dpp_config_params_oid)) { + asn1_oid_to_str(&oid, txt, sizeof(txt)); + wpa_printf(MSG_DEBUG, + "DPP: Unexpected Attribute identifier %s", txt); + goto fail; + } + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { + wpa_printf(MSG_DEBUG, + "DPP: Expected SET (Attribute) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + pos = hdr.payload; + end = hdr.payload + hdr.length; + + /* + * DPPConfigurationParameters ::= SEQUENCE { + * configurationTemplate UTF8String, + * connectorTemplate UTF8String OPTIONAL} + */ + + wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPConfigurationParameters", + pos, end - pos); + if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) + goto fail; + if (pos < end) { + wpa_hexdump_key(MSG_MSGDUMP, + "DPP: Ignore additional data after DPPConfigurationParameters", + pos, end - pos); + } + end = pos; + pos = hdr.payload; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_UTF8STRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected UTF8STRING (configurationTemplate) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate", + hdr.payload, hdr.length); + key->config_template = os_zalloc(hdr.length + 1); + if (!key->config_template) + goto fail; + os_memcpy(key->config_template, hdr.payload, hdr.length); + + pos = hdr.payload + hdr.length; + + if (pos < end) { + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_UTF8STRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected UTF8STRING (connectorTemplate) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate", + hdr.payload, hdr.length); + key->connector_template = os_zalloc(hdr.length + 1); + if (!key->connector_template) + goto fail; + os_memcpy(key->connector_template, hdr.payload, hdr.length); + } + + return key; +fail: + wpa_printf(MSG_DEBUG, "DPP: Failed to parse OneAsymmetricKey"); + dpp_free_asymmetric_key(key); + return NULL; +} + + +static struct dpp_asymmetric_key * +dpp_parse_dpp_asymmetric_key_package(const u8 *key_pkg, size_t key_pkg_len) +{ + struct asn1_hdr hdr; + const u8 *pos = key_pkg, *end = key_pkg + key_pkg_len; + struct dpp_asymmetric_key *first = NULL, *last = NULL, *key; + + wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", + key_pkg, key_pkg_len); + + /* + * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage + * + * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey + */ + while (pos < end) { + if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0 || + !(key = dpp_parse_one_asymmetric_key(hdr.payload, + hdr.length))) { + dpp_free_asymmetric_key(first); + return NULL; + } + if (!last) { + first = last = key; + } else { + last->next = key; + last = key; + } + } + + return first; +} + + +int dpp_conf_resp_env_data(struct dpp_authentication *auth, + const u8 *env_data, size_t env_data_len) +{ + const u8 *key; + size_t key_len; + u8 kek[DPP_MAX_HASH_LEN]; + u8 cont_encr_key[DPP_MAX_HASH_LEN]; + size_t cont_encr_key_len; + int res; + u8 *key_pkg; + size_t key_pkg_len; + struct dpp_enveloped_data data; + struct dpp_asymmetric_key *keys; + + wpa_hexdump(MSG_DEBUG, "DPP: DPPEnvelopedData", env_data, env_data_len); + + if (dpp_parse_enveloped_data(env_data, env_data_len, &data) < 0) + return -1; + + /* TODO: For initial testing, use ke as the key. Replace this with a + * new key once that has been defined. */ + key = auth->ke; + key_len = auth->curve->hash_len; + wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); + + if (dpp_pbkdf2(data.prf_hash_len, key, key_len, data.salt, 64, 1000, + kek, data.pbkdf2_key_len)) { + wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", + kek, data.pbkdf2_key_len); + + if (data.enc_key_len < AES_BLOCK_SIZE || + data.enc_key_len > sizeof(cont_encr_key) + AES_BLOCK_SIZE) { + wpa_printf(MSG_DEBUG, "DPP: Invalid encryptedKey length"); + return -1; + } + res = aes_siv_decrypt(kek, data.pbkdf2_key_len, + data.enc_key, data.enc_key_len, + 0, NULL, NULL, cont_encr_key); + forced_memzero(kek, data.pbkdf2_key_len); + if (res < 0) { + wpa_printf(MSG_DEBUG, + "DPP: AES-SIV decryption of encryptedKey failed"); + return -1; + } + cont_encr_key_len = data.enc_key_len - AES_BLOCK_SIZE; + wpa_hexdump_key(MSG_DEBUG, "DPP: content-encryption key", + cont_encr_key, cont_encr_key_len); + + if (data.enc_cont_len < AES_BLOCK_SIZE) + return -1; + key_pkg_len = data.enc_cont_len - AES_BLOCK_SIZE; + key_pkg = os_malloc(key_pkg_len); + if (!key_pkg) + return -1; + res = aes_siv_decrypt(cont_encr_key, cont_encr_key_len, + data.enc_cont, data.enc_cont_len, + 0, NULL, NULL, key_pkg); + forced_memzero(cont_encr_key, cont_encr_key_len); + if (res < 0) { + bin_clear_free(key_pkg, key_pkg_len); + wpa_printf(MSG_DEBUG, + "DPP: AES-SIV decryption of encryptedContent failed"); + return -1; + } + + keys = dpp_parse_dpp_asymmetric_key_package(key_pkg, key_pkg_len); + bin_clear_free(key_pkg, key_pkg_len); + dpp_free_asymmetric_key(auth->conf_key_pkg); + auth->conf_key_pkg = keys; + + return keys != NULL; +} + +#endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index 490e5bc93..c81411a9b 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -47,6 +47,13 @@ int dpp_prepare_channel_list(struct dpp_authentication *auth, void dpp_auth_fail(struct dpp_authentication *auth, const char *txt); int dpp_gen_uri(struct dpp_bootstrap_info *bi); +/* dpp_backup.c */ + +void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key); +struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth); +int dpp_conf_resp_env_data(struct dpp_authentication *auth, + const u8 *env_data, size_t env_data_len); + /* dpp_crypto.c */ struct dpp_signed_connector_info { diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index 3b49fa4f5..a5c45fd90 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -22,6 +22,7 @@ OBJS += $(SRC)/crypto/sha512-kdf.o OBJS += $(SRC)/tls/asn1.o OBJS += $(SRC)/common/dpp.o OBJS += $(SRC)/common/dpp_auth.o +OBJS += $(SRC)/common/dpp_backup.o OBJS += $(SRC)/common/dpp_crypto.o OBJS += $(SRC)/common/dpp_pkex.o OBJS += $(SRC)/common/dpp_reconfig.o diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index c85e7f957..eea5875e0 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -248,6 +248,7 @@ ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c OBJS += src/common/dpp_auth.c +OBJS += src/common/dpp_backup.c OBJS += src/common/dpp_crypto.c OBJS += src/common/dpp_pkex.c OBJS += src/common/dpp_reconfig.c diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 34ac16472..66ed8352a 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -280,6 +280,7 @@ ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o OBJS += ../src/common/dpp_auth.o +OBJS += ../src/common/dpp_backup.o OBJS += ../src/common/dpp_crypto.o OBJS += ../src/common/dpp_pkex.o OBJS += ../src/common/dpp_reconfig.o From 3aaf269f67f38cd2ae9a06878363b004616e2586 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 11:59:46 +0300 Subject: [PATCH 0482/1105] DPP: Move TCP encapsulation into a separate source code file This continues splitting dpp.c into smaller pieces. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 1 + hostapd/Makefile | 1 + src/common/dpp.c | 1455 +------------------------------ src/common/dpp_i.h | 9 + src/common/dpp_tcp.c | 1462 ++++++++++++++++++++++++++++++++ tests/fuzzing/dpp-uri/Makefile | 1 + wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + 8 files changed, 1478 insertions(+), 1453 deletions(-) create mode 100644 src/common/dpp_tcp.c diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 5cda74885..c389cb75d 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -542,6 +542,7 @@ OBJS += src/common/dpp_backup.c OBJS += src/common/dpp_crypto.c OBJS += src/common/dpp_pkex.c OBJS += src/common/dpp_reconfig.c +OBJS += src/common/dpp_tcp.c OBJS += src/ap/dpp_hostapd.c OBJS += src/ap/gas_query_ap.c NEED_AES_SIV=y diff --git a/hostapd/Makefile b/hostapd/Makefile index b2d782aac..5b0d3b8e3 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -573,6 +573,7 @@ OBJS += ../src/common/dpp_backup.o OBJS += ../src/common/dpp_crypto.o OBJS += ../src/common/dpp_pkex.o OBJS += ../src/common/dpp_reconfig.o +OBJS += ../src/common/dpp_tcp.o OBJS += ../src/ap/dpp_hostapd.o OBJS += ../src/ap/gas_query_ap.o NEED_AES_SIV=y diff --git a/src/common/dpp.c b/src/common/dpp.c index 870364a29..ca3b8b50c 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -8,15 +8,12 @@ */ #include "utils/includes.h" -#include #include #include #include "utils/common.h" #include "utils/base64.h" #include "utils/json.h" -#include "utils/ip_addr.h" -#include "utils/eloop.h" #include "common/ieee802_11_common.h" #include "common/wpa_ctrl.h" #include "common/gas.h" @@ -57,52 +54,6 @@ static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) #endif -struct dpp_connection { - struct dl_list list; - struct dpp_controller *ctrl; - struct dpp_relay_controller *relay; - struct dpp_global *global; - struct dpp_authentication *auth; - int sock; - u8 mac_addr[ETH_ALEN]; - unsigned int freq; - u8 msg_len[4]; - size_t msg_len_octets; - struct wpabuf *msg; - struct wpabuf *msg_out; - size_t msg_out_pos; - unsigned int read_eloop:1; - unsigned int write_eloop:1; - unsigned int on_tcp_tx_complete_gas_done:1; - unsigned int on_tcp_tx_complete_remove:1; - unsigned int on_tcp_tx_complete_auth_ok:1; -}; - -/* Remote Controller */ -struct dpp_relay_controller { - struct dl_list list; - struct dpp_global *global; - u8 pkhash[SHA256_MAC_LEN]; - struct hostapd_ip_addr ipaddr; - void *cb_ctx; - void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg, - size_t len); - void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token, - int prot, struct wpabuf *buf); - struct dl_list conn; /* struct dpp_connection */ -}; - -/* Local Controller */ -struct dpp_controller { - struct dpp_global *global; - u8 allowed_roles; - int qr_mutual; - int sock; - struct dl_list conn; /* struct dpp_connection */ - char *configurator_params; -}; - - void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) { wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); @@ -819,7 +770,7 @@ fail: } -static void dpp_write_adv_proto(struct wpabuf *buf) +void dpp_write_adv_proto(struct wpabuf *buf) { /* Advertisement Protocol IE */ wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); @@ -833,7 +784,7 @@ static void dpp_write_adv_proto(struct wpabuf *buf) } -static void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query) +void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query) { /* GAS Query */ wpabuf_put_le16(buf, wpabuf_len(query)); @@ -4043,71 +3994,6 @@ struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp, return NULL; } - -static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, - void *timeout_ctx); - - -static void dpp_connection_free(struct dpp_connection *conn) -{ - if (conn->sock >= 0) { - wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d", - conn->sock); - eloop_unregister_sock(conn->sock, EVENT_TYPE_READ); - eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); - close(conn->sock); - } - eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout, - conn, NULL); - wpabuf_free(conn->msg); - wpabuf_free(conn->msg_out); - dpp_auth_deinit(conn->auth); - os_free(conn); -} - - -static void dpp_connection_remove(struct dpp_connection *conn) -{ - dl_list_del(&conn->list); - dpp_connection_free(conn); -} - - -static void dpp_tcp_init_flush(struct dpp_global *dpp) -{ - struct dpp_connection *conn, *tmp; - - dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection, - list) - dpp_connection_remove(conn); -} - - -static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl) -{ - struct dpp_connection *conn, *tmp; - - dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection, - list) - dpp_connection_remove(conn); - os_free(ctrl); -} - - -static void dpp_relay_flush_controllers(struct dpp_global *dpp) -{ - struct dpp_relay_controller *ctrl, *tmp; - - if (!dpp) - return; - - dl_list_for_each_safe(ctrl, tmp, &dpp->controllers, - struct dpp_relay_controller, list) { - dl_list_del(&ctrl->list); - dpp_relay_controller_free(ctrl); - } -} - #endif /* CONFIG_DPP2 */ @@ -4159,1342 +4045,6 @@ void dpp_global_deinit(struct dpp_global *dpp) #ifdef CONFIG_DPP2 - -static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx); -static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx); -static void dpp_controller_auth_success(struct dpp_connection *conn, - int initiator); - - -int dpp_relay_add_controller(struct dpp_global *dpp, - struct dpp_relay_config *config) -{ - struct dpp_relay_controller *ctrl; - - if (!dpp) - return -1; - - ctrl = os_zalloc(sizeof(*ctrl)); - if (!ctrl) - return -1; - dl_list_init(&ctrl->conn); - ctrl->global = dpp; - os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr)); - os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN); - ctrl->cb_ctx = config->cb_ctx; - ctrl->tx = config->tx; - ctrl->gas_resp_tx = config->gas_resp_tx; - dl_list_add(&dpp->controllers, &ctrl->list); - return 0; -} - - -static struct dpp_relay_controller * -dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash) -{ - struct dpp_relay_controller *ctrl; - - if (!dpp) - return NULL; - - dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller, - list) { - if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0) - return ctrl; - } - - return NULL; -} - - -static void dpp_controller_gas_done(struct dpp_connection *conn) -{ - struct dpp_authentication *auth = conn->auth; - - if (auth->peer_version >= 2 && - auth->conf_resp_status == DPP_STATUS_OK) { - wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); - auth->waiting_conf_result = 1; - return; - } - - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); - dpp_connection_remove(conn); -} - - -static int dpp_tcp_send(struct dpp_connection *conn) -{ - int res; - - if (!conn->msg_out) { - eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); - conn->write_eloop = 0; - return -1; - } - res = send(conn->sock, - wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos, - wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s", - strerror(errno)); - dpp_connection_remove(conn); - return -1; - } - - conn->msg_out_pos += res; - if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) { - wpa_printf(MSG_DEBUG, - "DPP: %u/%u bytes of message sent to Controller", - (unsigned int) conn->msg_out_pos, - (unsigned int) wpabuf_len(conn->msg_out)); - if (!conn->write_eloop && - eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, conn, NULL) == 0) - conn->write_eloop = 1; - return 1; - } - - wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP"); - wpabuf_free(conn->msg_out); - conn->msg_out = NULL; - conn->msg_out_pos = 0; - eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); - conn->write_eloop = 0; - if (!conn->read_eloop && - eloop_register_sock(conn->sock, EVENT_TYPE_READ, - dpp_controller_rx, conn, NULL) == 0) - conn->read_eloop = 1; - if (conn->on_tcp_tx_complete_remove) { - dpp_connection_remove(conn); - } else if (conn->ctrl && conn->on_tcp_tx_complete_gas_done && - conn->auth) { - dpp_controller_gas_done(conn); - } else if (conn->on_tcp_tx_complete_auth_ok) { - conn->on_tcp_tx_complete_auth_ok = 0; - dpp_controller_auth_success(conn, 1); - } - - return 0; -} - - -static int dpp_tcp_send_msg(struct dpp_connection *conn, - const struct wpabuf *msg) -{ - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1); - if (!conn->msg_out) - return -1; - wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1); - wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1, - wpabuf_len(msg) - 1); - - if (dpp_tcp_send(conn) == 1) { - if (!conn->write_eloop) { - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, - conn, NULL) < 0) - return -1; - conn->write_eloop = 1; - } - } - - return 0; -} - - -static void dpp_controller_start_gas_client(struct dpp_connection *conn) -{ - struct dpp_authentication *auth = conn->auth; - struct wpabuf *buf; - int netrole_ap = 0; /* TODO: make this configurable */ - - buf = dpp_build_conf_req_helper(auth, "Test", netrole_ap, NULL, NULL); - if (!buf) { - wpa_printf(MSG_DEBUG, - "DPP: No configuration request data available"); - return; - } - - dpp_tcp_send_msg(conn, buf); - wpabuf_free(buf); -} - - -static void dpp_controller_auth_success(struct dpp_connection *conn, - int initiator) -{ - struct dpp_authentication *auth = conn->auth; - - if (!auth) - return; - - wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded"); - wpa_msg(conn->global->msg_ctx, MSG_INFO, - DPP_EVENT_AUTH_SUCCESS "init=%d", initiator); -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at Authentication Confirm"); - if (auth->configurator) { - /* Prevent GAS response */ - auth->auth_success = 0; - } - return; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!auth->configurator) - dpp_controller_start_gas_client(conn); -} - - -static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct dpp_connection *conn = eloop_ctx; - - wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock); - dpp_tcp_send(conn); -} - - -static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen, - const struct hostapd_ip_addr *ipaddr, - int port) -{ - struct sockaddr_in *dst; -#ifdef CONFIG_IPV6 - struct sockaddr_in6 *dst6; -#endif /* CONFIG_IPV6 */ - - switch (ipaddr->af) { - case AF_INET: - dst = (struct sockaddr_in *) addr; - os_memset(dst, 0, sizeof(*dst)); - dst->sin_family = AF_INET; - dst->sin_addr.s_addr = ipaddr->u.v4.s_addr; - dst->sin_port = htons(port); - *addrlen = sizeof(*dst); - break; -#ifdef CONFIG_IPV6 - case AF_INET6: - dst6 = (struct sockaddr_in6 *) addr; - os_memset(dst6, 0, sizeof(*dst6)); - dst6->sin6_family = AF_INET6; - os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6, - sizeof(struct in6_addr)); - dst6->sin6_port = htons(port); - *addrlen = sizeof(*dst6); - break; -#endif /* CONFIG_IPV6 */ - default: - return -1; - } - - return 0; -} - - -static struct dpp_connection * -dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src, - unsigned int freq) -{ - struct dpp_connection *conn; - struct sockaddr_storage addr; - socklen_t addrlen; - char txt[100]; - - if (dl_list_len(&ctrl->conn) >= 15) { - wpa_printf(MSG_DEBUG, - "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one"); - return NULL; - } - - if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen, - &ctrl->ipaddr, DPP_TCP_PORT) < 0) - return NULL; - - conn = os_zalloc(sizeof(*conn)); - if (!conn) - return NULL; - - conn->global = ctrl->global; - conn->relay = ctrl; - os_memcpy(conn->mac_addr, src, ETH_ALEN); - conn->freq = freq; - - conn->sock = socket(AF_INET, SOCK_STREAM, 0); - if (conn->sock < 0) - goto fail; - wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s", - conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt))); - - if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { - wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - goto fail; - } - - if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) { - if (errno != EINPROGRESS) { - wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", - strerror(errno)); - goto fail; - } - - /* - * Continue connecting in the background; eloop will call us - * once the connection is ready (or failed). - */ - } - - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, conn, NULL) < 0) - goto fail; - conn->write_eloop = 1; - - /* TODO: eloop timeout to clear a connection if it does not complete - * properly */ - - dl_list_add(&ctrl->conn, &conn->list); - return conn; -fail: - dpp_connection_free(conn); - return NULL; -} - - -static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len) -{ - struct wpabuf *msg; - - msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len); - if (!msg) - return NULL; - wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len); - wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC); - wpabuf_put_data(msg, hdr, DPP_HDR_LEN); - wpabuf_put_data(msg, buf, len); - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); - return msg; -} - - -static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr, - const u8 *buf, size_t len) -{ - u8 type = hdr[DPP_HDR_LEN - 1]; - - wpa_printf(MSG_DEBUG, - "DPP: Continue already established Relay/Controller connection for this session"); - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = dpp_tcp_encaps(hdr, buf, len); - if (!conn->msg_out) { - dpp_connection_remove(conn); - return -1; - } - - /* TODO: for proto ver 1, need to do remove connection based on GAS Resp - * TX status */ - if (type == DPP_PA_CONFIGURATION_RESULT) - conn->on_tcp_tx_complete_remove = 1; - dpp_tcp_send(conn); - return 0; -} - - -int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, - const u8 *buf, size_t len, unsigned int freq, - const u8 *i_bootstrap, const u8 *r_bootstrap) -{ - struct dpp_relay_controller *ctrl; - struct dpp_connection *conn; - u8 type = hdr[DPP_HDR_LEN - 1]; - - /* Check if there is an already started session for this peer and if so, - * continue that session (send this over TCP) and return 0. - */ - if (type != DPP_PA_PEER_DISCOVERY_REQ && - type != DPP_PA_PEER_DISCOVERY_RESP && - type != DPP_PA_PRESENCE_ANNOUNCEMENT) { - dl_list_for_each(ctrl, &dpp->controllers, - struct dpp_relay_controller, list) { - dl_list_for_each(conn, &ctrl->conn, - struct dpp_connection, list) { - if (os_memcmp(src, conn->mac_addr, - ETH_ALEN) == 0) - return dpp_relay_tx(conn, hdr, buf, len); - } - } - } - - if (!r_bootstrap) - return -1; - - if (type == DPP_PA_PRESENCE_ANNOUNCEMENT) { - /* TODO: Could send this to all configured Controllers. For now, - * only the first Controller is supported. */ - ctrl = dl_list_first(&dpp->controllers, - struct dpp_relay_controller, list); - } else { - ctrl = dpp_relay_controller_get(dpp, r_bootstrap); - } - if (!ctrl) - return -1; - - wpa_printf(MSG_DEBUG, - "DPP: Authentication Request for a configured Controller"); - conn = dpp_relay_new_conn(ctrl, src, freq); - if (!conn) - return -1; - - conn->msg_out = dpp_tcp_encaps(hdr, buf, len); - if (!conn->msg_out) { - dpp_connection_remove(conn); - return -1; - } - /* Message will be sent in dpp_conn_tx_ready() */ - - return 0; -} - - -int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data, - size_t data_len) -{ - struct dpp_relay_controller *ctrl; - struct dpp_connection *conn, *found = NULL; - struct wpabuf *msg; - - /* Check if there is a successfully completed authentication for this - * and if so, continue that session (send this over TCP) and return 0. - */ - dl_list_for_each(ctrl, &dpp->controllers, - struct dpp_relay_controller, list) { - if (found) - break; - dl_list_for_each(conn, &ctrl->conn, - struct dpp_connection, list) { - if (os_memcmp(src, conn->mac_addr, - ETH_ALEN) == 0) { - found = conn; - break; - } - } - } - - if (!found) - return -1; - - msg = wpabuf_alloc(4 + 1 + data_len); - if (!msg) - return -1; - wpabuf_put_be32(msg, 1 + data_len); - wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ); - wpabuf_put_data(msg, data, data_len); - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); - - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = msg; - dpp_tcp_send(conn); - return 0; -} - - -static void dpp_controller_free(struct dpp_controller *ctrl) -{ - struct dpp_connection *conn, *tmp; - - if (!ctrl) - return; - - dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection, - list) - dpp_connection_remove(conn); - - if (ctrl->sock >= 0) { - close(ctrl->sock); - eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ); - } - os_free(ctrl->configurator_params); - os_free(ctrl); -} - - -static int dpp_controller_rx_auth_req(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, size_t len) -{ - const u8 *r_bootstrap, *i_bootstrap; - u16 r_bootstrap_len, i_bootstrap_len; - struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL; - - if (!conn->ctrl) - return 0; - - wpa_printf(MSG_DEBUG, "DPP: Authentication Request"); - - r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, - &r_bootstrap_len); - if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { - wpa_printf(MSG_INFO, - "Missing or invalid required Responder Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", - r_bootstrap, r_bootstrap_len); - - i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH, - &i_bootstrap_len); - if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) { - wpa_printf(MSG_INFO, - "Missing or invalid required Initiator Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", - i_bootstrap, i_bootstrap_len); - - /* Try to find own and peer bootstrapping key matches based on the - * received hash values */ - dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap, - &own_bi, &peer_bi); - if (!own_bi) { - wpa_printf(MSG_INFO, - "No matching own bootstrapping key found - ignore message"); - return -1; - } - - if (conn->auth) { - wpa_printf(MSG_INFO, - "Already in DPP authentication exchange - ignore new one"); - return 0; - } - - conn->auth = dpp_auth_req_rx(conn->ctrl->global, - conn->ctrl->global->msg_ctx, - conn->ctrl->allowed_roles, - conn->ctrl->qr_mutual, - peer_bi, own_bi, -1, hdr, buf, len); - if (!conn->auth) { - wpa_printf(MSG_DEBUG, "DPP: No response generated"); - return -1; - } - - if (dpp_set_configurator(conn->auth, - conn->ctrl->configurator_params) < 0) { - dpp_connection_remove(conn); - return -1; - } - - return dpp_tcp_send_msg(conn, conn->auth->resp_msg); -} - - -static int dpp_controller_rx_auth_resp(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, size_t len) -{ - struct dpp_authentication *auth = conn->auth; - struct wpabuf *msg; - int res; - - if (!auth) - return -1; - - wpa_printf(MSG_DEBUG, "DPP: Authentication Response"); - - msg = dpp_auth_resp_rx(auth, hdr, buf, len); - if (!msg) { - if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { - wpa_printf(MSG_DEBUG, - "DPP: Start wait for full response"); - return -1; - } - wpa_printf(MSG_DEBUG, "DPP: No confirm generated"); - dpp_connection_remove(conn); - return -1; - } - - conn->on_tcp_tx_complete_auth_ok = 1; - res = dpp_tcp_send_msg(conn, msg); - wpabuf_free(msg); - return res; -} - - -static int dpp_controller_rx_auth_conf(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, size_t len) -{ - struct dpp_authentication *auth = conn->auth; - - wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation"); - - if (!auth) { - wpa_printf(MSG_DEBUG, - "DPP: No DPP Authentication in progress - drop"); - return -1; - } - - if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); - return -1; - } - - dpp_controller_auth_success(conn, 0); - return 0; -} - - -static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, - void *timeout_ctx) -{ - struct dpp_connection *conn = eloop_ctx; - - if (!conn->auth->waiting_conf_result) - return; - - wpa_printf(MSG_DEBUG, - "DPP: Timeout while waiting for Connection Status Result"); - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONN_STATUS_RESULT "timeout"); - dpp_connection_remove(conn); -} - - -static int dpp_controller_rx_conf_result(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, - size_t len) -{ - struct dpp_authentication *auth = conn->auth; - enum dpp_status_error status; - - if (!conn->ctrl) - return 0; - - wpa_printf(MSG_DEBUG, "DPP: Configuration Result"); - - if (!auth || !auth->waiting_conf_result) { - wpa_printf(MSG_DEBUG, - "DPP: No DPP Configuration waiting for result - drop"); - return -1; - } - - status = dpp_conf_result_rx(auth, hdr, buf, len); - if (status == DPP_STATUS_OK && auth->send_conn_status) { - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONF_SENT "wait_conn_status=1"); - wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); - eloop_cancel_timeout( - dpp_controller_conn_status_result_wait_timeout, - conn, NULL); - eloop_register_timeout( - 16, 0, dpp_controller_conn_status_result_wait_timeout, - conn, NULL); - return 0; - } - if (status == DPP_STATUS_OK) - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONF_SENT); - else - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONF_FAILED); - return -1; /* to remove the completed connection */ -} - - -static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, - size_t len) -{ - struct dpp_authentication *auth = conn->auth; - enum dpp_status_error status; - u8 ssid[SSID_MAX_LEN]; - size_t ssid_len = 0; - char *channel_list = NULL; - - if (!conn->ctrl) - return 0; - - wpa_printf(MSG_DEBUG, "DPP: Connection Status Result"); - - if (!auth || !auth->waiting_conn_status_result) { - wpa_printf(MSG_DEBUG, - "DPP: No DPP Configuration waiting for connection status result - drop"); - return -1; - } - - status = dpp_conn_status_result_rx(auth, hdr, buf, len, - ssid, &ssid_len, &channel_list); - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONN_STATUS_RESULT - "result=%d ssid=%s channel_list=%s", - status, wpa_ssid_txt(ssid, ssid_len), - channel_list ? channel_list : "N/A"); - os_free(channel_list); - return -1; /* to remove the completed connection */ -} - - -static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, - size_t len) -{ - const u8 *r_bootstrap; - u16 r_bootstrap_len; - struct dpp_bootstrap_info *peer_bi; - struct dpp_authentication *auth; - struct dpp_global *dpp = conn->ctrl->global; - - if (conn->auth) { - wpa_printf(MSG_DEBUG, - "DPP: Ignore Presence Announcement during ongoing Authentication"); - return -1; - } - - wpa_printf(MSG_DEBUG, "DPP: Presence Announcement"); - - r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, - &r_bootstrap_len); - if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { - wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Missing or invalid required Responder Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", - r_bootstrap, r_bootstrap_len); - peer_bi = dpp_bootstrap_find_chirp(dpp, r_bootstrap); - if (!peer_bi) { - wpa_printf(MSG_DEBUG, - "DPP: No matching bootstrapping information found"); - return -1; - } - - auth = dpp_auth_init(dpp, dpp->msg_ctx, peer_bi, NULL, - DPP_CAPAB_CONFIGURATOR, -1, NULL, 0); - if (!auth) - return -1; - if (dpp_set_configurator(conn->auth, - conn->ctrl->configurator_params) < 0) { - dpp_auth_deinit(auth); - dpp_connection_remove(conn); - return -1; - } - - conn->auth = auth; - return dpp_tcp_send_msg(conn, conn->auth->req_msg); -} - - -static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, - size_t len) -{ - const u8 *csign_hash; - u16 csign_hash_len; - struct dpp_configurator *conf; - struct dpp_global *dpp = conn->ctrl->global; - - if (conn->auth) { - wpa_printf(MSG_DEBUG, - "DPP: Ignore Reconfig Announcement during ongoing Authentication"); - return -1; - } - - wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement"); - - csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, - &csign_hash_len); - if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { - wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Missing or invalid required Configurator C-sign key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", - csign_hash, csign_hash_len); - conf = dpp_configurator_find_kid(dpp, csign_hash); - if (!conf) { - wpa_printf(MSG_DEBUG, - "DPP: No matching Configurator information found"); - return -1; - } - - /* TODO: Initiate Reconfig Authentication */ - return -1; -} - - -static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, - size_t len) -{ - const u8 *pos, *end; - u8 type; - - wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP"); - pos = msg; - end = msg + len; - - if (end - pos < DPP_HDR_LEN || - WPA_GET_BE24(pos) != OUI_WFA || - pos[3] != DPP_OUI_TYPE) { - wpa_printf(MSG_DEBUG, "DPP: Unrecognized header"); - return -1; - } - - if (pos[4] != 1) { - wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u", - pos[4]); - return -1; - } - type = pos[5]; - wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type); - pos += DPP_HDR_LEN; - - wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", - pos, end - pos); - if (dpp_check_attrs(pos, end - pos) < 0) - return -1; - - if (conn->relay) { - wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN"); - conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr, - conn->freq, msg, len); - return 0; - } - - switch (type) { - case DPP_PA_AUTHENTICATION_REQ: - return dpp_controller_rx_auth_req(conn, msg, pos, end - pos); - case DPP_PA_AUTHENTICATION_RESP: - return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos); - case DPP_PA_AUTHENTICATION_CONF: - return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos); - case DPP_PA_CONFIGURATION_RESULT: - return dpp_controller_rx_conf_result(conn, msg, pos, end - pos); - case DPP_PA_CONNECTION_STATUS_RESULT: - return dpp_controller_rx_conn_status_result(conn, msg, pos, - end - pos); - case DPP_PA_PRESENCE_ANNOUNCEMENT: - return dpp_controller_rx_presence_announcement(conn, msg, pos, - end - pos); - case DPP_PA_RECONFIG_ANNOUNCEMENT: - return dpp_controller_rx_reconfig_announcement(conn, msg, pos, - end - pos); - default: - /* TODO: missing messages types */ - wpa_printf(MSG_DEBUG, - "DPP: Unsupported frame subtype %d", type); - return -1; - } -} - - -static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, - size_t len) -{ - const u8 *pos, *end, *next; - u8 dialog_token; - const u8 *adv_proto; - u16 slen; - struct wpabuf *resp, *buf; - struct dpp_authentication *auth = conn->auth; - - if (len < 1 + 2) - return -1; - - wpa_printf(MSG_DEBUG, - "DPP: Received DPP Configuration Request over TCP"); - - if (!conn->ctrl || !auth || !auth->auth_success) { - wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); - return -1; - } - - pos = msg; - end = msg + len; - - dialog_token = *pos++; - adv_proto = pos++; - slen = *pos++; - if (*adv_proto != WLAN_EID_ADV_PROTO || - slen > end - pos || slen < 2) - return -1; - - next = pos + slen; - pos++; /* skip QueryRespLenLimit and PAME-BI */ - - if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC || - pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA || - pos[5] != DPP_OUI_TYPE || pos[6] != 0x01) - return -1; - - pos = next; - /* Query Request */ - if (end - pos < 2) - return -1; - slen = WPA_GET_LE16(pos); - pos += 2; - if (slen > end - pos) - return -1; - - resp = dpp_conf_req_rx(auth, pos, slen); - if (!resp) - return -1; - - buf = wpabuf_alloc(4 + 18 + wpabuf_len(resp)); - if (!buf) { - wpabuf_free(resp); - return -1; - } - - wpabuf_put_be32(buf, 18 + wpabuf_len(resp)); - - wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP); - wpabuf_put_u8(buf, dialog_token); - wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); - wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */ - - dpp_write_adv_proto(buf); - dpp_write_gas_query(buf, resp); - wpabuf_free(resp); - - /* Send Config Response over TCP; GAS fragmentation is taken care of by - * the Relay */ - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = buf; - conn->on_tcp_tx_complete_gas_done = 1; - dpp_tcp_send(conn); - return 0; -} - - -static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) -{ - struct dpp_authentication *auth = conn->auth; - int res; - struct wpabuf *msg; - enum dpp_status_error status; - - wpa_printf(MSG_DEBUG, - "DPP: Configuration Response for local stack from TCP"); - - res = dpp_conf_resp_rx(auth, resp); - wpabuf_free(resp); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); - return -1; - } - - if (conn->global->process_conf_obj) - res = conn->global->process_conf_obj(conn->global->cb_ctx, - auth); - else - res = 0; - - if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK) - return -1; - - wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result"); - status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK; - msg = dpp_build_conf_result(auth, status); - if (!msg) - return -1; - - conn->on_tcp_tx_complete_remove = 1; - res = dpp_tcp_send_msg(conn, msg); - wpabuf_free(msg); - - /* This exchange will be terminated in the TX status handler */ - - return res; -} - - -static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, - size_t len) -{ - struct wpabuf *buf; - u8 dialog_token; - const u8 *pos, *end, *next, *adv_proto; - u16 status, slen; - - if (len < 5 + 2) - return -1; - - wpa_printf(MSG_DEBUG, - "DPP: Received DPP Configuration Response over TCP"); - - pos = msg; - end = msg + len; - - dialog_token = *pos++; - status = WPA_GET_LE16(pos); - if (status != WLAN_STATUS_SUCCESS) { - wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status); - return -1; - } - pos += 2; - pos += 2; /* ignore GAS Comeback Delay */ - - adv_proto = pos++; - slen = *pos++; - if (*adv_proto != WLAN_EID_ADV_PROTO || - slen > end - pos || slen < 2) - return -1; - - next = pos + slen; - pos++; /* skip QueryRespLenLimit and PAME-BI */ - - if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC || - pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA || - pos[5] != DPP_OUI_TYPE || pos[6] != 0x01) - return -1; - - pos = next; - /* Query Response */ - if (end - pos < 2) - return -1; - slen = WPA_GET_LE16(pos); - pos += 2; - if (slen > end - pos) - return -1; - - buf = wpabuf_alloc(slen); - if (!buf) - return -1; - wpabuf_put_data(buf, pos, slen); - - if (!conn->relay && !conn->ctrl) - return dpp_tcp_rx_gas_resp(conn, buf); - - if (!conn->relay) { - wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); - wpabuf_free(buf); - return -1; - } - wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN"); - conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr, - dialog_token, 0, buf); - - return 0; -} - - -static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx) -{ - struct dpp_connection *conn = eloop_ctx; - int res; - const u8 *pos; - - wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)", - sd); - - if (conn->msg_len_octets < 4) { - u32 msglen; - - res = recv(sd, &conn->msg_len[conn->msg_len_octets], - 4 - conn->msg_len_octets, 0); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", - strerror(errno)); - dpp_connection_remove(conn); - return; - } - if (res == 0) { - wpa_printf(MSG_DEBUG, - "DPP: No more data available over TCP"); - dpp_connection_remove(conn); - return; - } - wpa_printf(MSG_DEBUG, - "DPP: Received %d/%d octet(s) of message length field", - res, (int) (4 - conn->msg_len_octets)); - conn->msg_len_octets += res; - - if (conn->msg_len_octets < 4) { - wpa_printf(MSG_DEBUG, - "DPP: Need %d more octets of message length field", - (int) (4 - conn->msg_len_octets)); - return; - } - - msglen = WPA_GET_BE32(conn->msg_len); - wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen); - if (msglen > 65535) { - wpa_printf(MSG_INFO, "DPP: Unexpectedly long message"); - dpp_connection_remove(conn); - return; - } - - wpabuf_free(conn->msg); - conn->msg = wpabuf_alloc(msglen); - } - - if (!conn->msg) { - wpa_printf(MSG_DEBUG, - "DPP: No buffer available for receiving the message"); - dpp_connection_remove(conn); - return; - } - - wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload", - (unsigned int) wpabuf_tailroom(conn->msg)); - - res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno)); - dpp_connection_remove(conn); - return; - } - if (res == 0) { - wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP"); - dpp_connection_remove(conn); - return; - } - wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res); - wpabuf_put(conn->msg, res); - - if (wpabuf_tailroom(conn->msg) > 0) { - wpa_printf(MSG_DEBUG, - "DPP: Need %u more octets of message payload", - (unsigned int) wpabuf_tailroom(conn->msg)); - return; - } - - conn->msg_len_octets = 0; - wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg); - if (wpabuf_len(conn->msg) < 1) { - dpp_connection_remove(conn); - return; - } - - pos = wpabuf_head(conn->msg); - switch (*pos) { - case WLAN_PA_VENDOR_SPECIFIC: - if (dpp_controller_rx_action(conn, pos + 1, - wpabuf_len(conn->msg) - 1) < 0) - dpp_connection_remove(conn); - break; - case WLAN_PA_GAS_INITIAL_REQ: - if (dpp_controller_rx_gas_req(conn, pos + 1, - wpabuf_len(conn->msg) - 1) < 0) - dpp_connection_remove(conn); - break; - case WLAN_PA_GAS_INITIAL_RESP: - if (dpp_rx_gas_resp(conn, pos + 1, - wpabuf_len(conn->msg) - 1) < 0) - dpp_connection_remove(conn); - break; - default: - wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u", - *pos); - break; - } -} - - -static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) -{ - struct dpp_controller *ctrl = eloop_ctx; - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); - int fd; - struct dpp_connection *conn; - - wpa_printf(MSG_DEBUG, "DPP: New TCP connection"); - - fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len); - if (fd < 0) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to accept new connection: %s", - strerror(errno)); - return; - } - wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d", - inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - - conn = os_zalloc(sizeof(*conn)); - if (!conn) - goto fail; - - conn->global = ctrl->global; - conn->ctrl = ctrl; - conn->sock = fd; - - if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { - wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - goto fail; - } - - if (eloop_register_sock(conn->sock, EVENT_TYPE_READ, - dpp_controller_rx, conn, NULL) < 0) - goto fail; - conn->read_eloop = 1; - - /* TODO: eloop timeout to expire connections that do not complete in - * reasonable time */ - dl_list_add(&ctrl->conn, &conn->list); - return; - -fail: - close(fd); - os_free(conn); -} - - -int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, - const struct hostapd_ip_addr *addr, int port) -{ - struct dpp_connection *conn; - struct sockaddr_storage saddr; - socklen_t addrlen; - const u8 *hdr, *pos, *end; - char txt[100]; - - wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d", - hostapd_ip_txt(addr, txt, sizeof(txt)), port); - if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen, - addr, port) < 0) { - dpp_auth_deinit(auth); - return -1; - } - - conn = os_zalloc(sizeof(*conn)); - if (!conn) { - dpp_auth_deinit(auth); - return -1; - } - - conn->global = dpp; - conn->auth = auth; - conn->sock = socket(AF_INET, SOCK_STREAM, 0); - if (conn->sock < 0) - goto fail; - - if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { - wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - goto fail; - } - - if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) { - if (errno != EINPROGRESS) { - wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", - strerror(errno)); - goto fail; - } - - /* - * Continue connecting in the background; eloop will call us - * once the connection is ready (or failed). - */ - } - - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, conn, NULL) < 0) - goto fail; - conn->write_eloop = 1; - - hdr = wpabuf_head(auth->req_msg); - end = hdr + wpabuf_len(auth->req_msg); - hdr += 2; /* skip Category and Actiom */ - pos = hdr + DPP_HDR_LEN; - conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos); - if (!conn->msg_out) - goto fail; - /* Message will be sent in dpp_conn_tx_ready() */ - - /* TODO: eloop timeout to clear a connection if it does not complete - * properly */ - dl_list_add(&dpp->tcp_init, &conn->list); - return 0; -fail: - dpp_connection_free(conn); - return -1; -} - - -int dpp_controller_start(struct dpp_global *dpp, - struct dpp_controller_config *config) -{ - struct dpp_controller *ctrl; - int on = 1; - struct sockaddr_in sin; - int port; - - if (!dpp || dpp->controller) - return -1; - - ctrl = os_zalloc(sizeof(*ctrl)); - if (!ctrl) - return -1; - ctrl->global = dpp; - if (config->configurator_params) - ctrl->configurator_params = - os_strdup(config->configurator_params); - dl_list_init(&ctrl->conn); - /* TODO: configure these somehow */ - ctrl->allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; - ctrl->qr_mutual = 0; - - ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); - if (ctrl->sock < 0) - goto fail; - - if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)) < 0) { - wpa_printf(MSG_DEBUG, - "DPP: setsockopt(SO_REUSEADDR) failed: %s", - strerror(errno)); - /* try to continue anyway */ - } - - if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) { - wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - goto fail; - } - - /* TODO: IPv6 */ - os_memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT; - sin.sin_port = htons(port); - if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { - wpa_printf(MSG_INFO, - "DPP: Failed to bind Controller TCP port: %s", - strerror(errno)); - goto fail; - } - if (listen(ctrl->sock, 10 /* max backlog */) < 0 || - fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 || - eloop_register_sock(ctrl->sock, EVENT_TYPE_READ, - dpp_controller_tcp_cb, ctrl, NULL)) - goto fail; - - dpp->controller = ctrl; - wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port); - return 0; -fail: - dpp_controller_free(ctrl); - return -1; -} - - -void dpp_controller_stop(struct dpp_global *dpp) -{ - if (dpp) { - dpp_controller_free(dpp->controller); - dpp->controller = NULL; - } -} - - struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi) { struct wpabuf *msg; @@ -5511,5 +4061,4 @@ struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi) "DPP: Presence Announcement frame attributes", msg); return msg; } - #endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index c81411a9b..f18b8be08 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -46,6 +46,8 @@ int dpp_prepare_channel_list(struct dpp_authentication *auth, struct hostapd_hw_modes *own_modes, u16 num_modes); void dpp_auth_fail(struct dpp_authentication *auth, const char *txt); int dpp_gen_uri(struct dpp_bootstrap_info *bi); +void dpp_write_adv_proto(struct wpabuf *buf); +void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query); /* dpp_backup.c */ @@ -140,5 +142,12 @@ char * dpp_sign_connector(struct dpp_configurator *conf, int dpp_test_gen_invalid_key(struct wpabuf *msg, const struct dpp_curve_params *curve); +/* dpp_tcp.c */ + +void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, + void *timeout_ctx); +void dpp_tcp_init_flush(struct dpp_global *dpp); +void dpp_relay_flush_controllers(struct dpp_global *dpp); + #endif /* CONFIG_DPP */ #endif /* DPP_I_H */ diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c new file mode 100644 index 000000000..3165a03f9 --- /dev/null +++ b/src/common/dpp_tcp.c @@ -0,0 +1,1462 @@ +/* + * DPP over TCP + * Copyright (c) 2019-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include + +#include "utils/common.h" +#include "utils/ip_addr.h" +#include "utils/eloop.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "dpp.h" +#include "dpp_i.h" + +#ifdef CONFIG_DPP2 + +struct dpp_connection { + struct dl_list list; + struct dpp_controller *ctrl; + struct dpp_relay_controller *relay; + struct dpp_global *global; + struct dpp_authentication *auth; + int sock; + u8 mac_addr[ETH_ALEN]; + unsigned int freq; + u8 msg_len[4]; + size_t msg_len_octets; + struct wpabuf *msg; + struct wpabuf *msg_out; + size_t msg_out_pos; + unsigned int read_eloop:1; + unsigned int write_eloop:1; + unsigned int on_tcp_tx_complete_gas_done:1; + unsigned int on_tcp_tx_complete_remove:1; + unsigned int on_tcp_tx_complete_auth_ok:1; +}; + +/* Remote Controller */ +struct dpp_relay_controller { + struct dl_list list; + struct dpp_global *global; + u8 pkhash[SHA256_MAC_LEN]; + struct hostapd_ip_addr ipaddr; + void *cb_ctx; + void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg, + size_t len); + void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token, + int prot, struct wpabuf *buf); + struct dl_list conn; /* struct dpp_connection */ +}; + +/* Local Controller */ +struct dpp_controller { + struct dpp_global *global; + u8 allowed_roles; + int qr_mutual; + int sock; + struct dl_list conn; /* struct dpp_connection */ + char *configurator_params; +}; + +static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx); +static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx); +static void dpp_controller_auth_success(struct dpp_connection *conn, + int initiator); + + +static void dpp_connection_free(struct dpp_connection *conn) +{ + if (conn->sock >= 0) { + wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d", + conn->sock); + eloop_unregister_sock(conn->sock, EVENT_TYPE_READ); + eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); + close(conn->sock); + } + eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout, + conn, NULL); + wpabuf_free(conn->msg); + wpabuf_free(conn->msg_out); + dpp_auth_deinit(conn->auth); + os_free(conn); +} + + +static void dpp_connection_remove(struct dpp_connection *conn) +{ + dl_list_del(&conn->list); + dpp_connection_free(conn); +} + + +int dpp_relay_add_controller(struct dpp_global *dpp, + struct dpp_relay_config *config) +{ + struct dpp_relay_controller *ctrl; + + if (!dpp) + return -1; + + ctrl = os_zalloc(sizeof(*ctrl)); + if (!ctrl) + return -1; + dl_list_init(&ctrl->conn); + ctrl->global = dpp; + os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr)); + os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN); + ctrl->cb_ctx = config->cb_ctx; + ctrl->tx = config->tx; + ctrl->gas_resp_tx = config->gas_resp_tx; + dl_list_add(&dpp->controllers, &ctrl->list); + return 0; +} + + +static struct dpp_relay_controller * +dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash) +{ + struct dpp_relay_controller *ctrl; + + if (!dpp) + return NULL; + + dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller, + list) { + if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0) + return ctrl; + } + + return NULL; +} + + +static void dpp_controller_gas_done(struct dpp_connection *conn) +{ + struct dpp_authentication *auth = conn->auth; + + if (auth->peer_version >= 2 && + auth->conf_resp_status == DPP_STATUS_OK) { + wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); + auth->waiting_conf_result = 1; + return; + } + + wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); + dpp_connection_remove(conn); +} + + +static int dpp_tcp_send(struct dpp_connection *conn) +{ + int res; + + if (!conn->msg_out) { + eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); + conn->write_eloop = 0; + return -1; + } + res = send(conn->sock, + wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos, + wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s", + strerror(errno)); + dpp_connection_remove(conn); + return -1; + } + + conn->msg_out_pos += res; + if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) { + wpa_printf(MSG_DEBUG, + "DPP: %u/%u bytes of message sent to Controller", + (unsigned int) conn->msg_out_pos, + (unsigned int) wpabuf_len(conn->msg_out)); + if (!conn->write_eloop && + eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, conn, NULL) == 0) + conn->write_eloop = 1; + return 1; + } + + wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP"); + wpabuf_free(conn->msg_out); + conn->msg_out = NULL; + conn->msg_out_pos = 0; + eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); + conn->write_eloop = 0; + if (!conn->read_eloop && + eloop_register_sock(conn->sock, EVENT_TYPE_READ, + dpp_controller_rx, conn, NULL) == 0) + conn->read_eloop = 1; + if (conn->on_tcp_tx_complete_remove) { + dpp_connection_remove(conn); + } else if (conn->ctrl && conn->on_tcp_tx_complete_gas_done && + conn->auth) { + dpp_controller_gas_done(conn); + } else if (conn->on_tcp_tx_complete_auth_ok) { + conn->on_tcp_tx_complete_auth_ok = 0; + dpp_controller_auth_success(conn, 1); + } + + return 0; +} + + +static int dpp_tcp_send_msg(struct dpp_connection *conn, + const struct wpabuf *msg) +{ + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1); + if (!conn->msg_out) + return -1; + wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1); + wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1, + wpabuf_len(msg) - 1); + + if (dpp_tcp_send(conn) == 1) { + if (!conn->write_eloop) { + if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, + conn, NULL) < 0) + return -1; + conn->write_eloop = 1; + } + } + + return 0; +} + + +static void dpp_controller_start_gas_client(struct dpp_connection *conn) +{ + struct dpp_authentication *auth = conn->auth; + struct wpabuf *buf; + int netrole_ap = 0; /* TODO: make this configurable */ + + buf = dpp_build_conf_req_helper(auth, "Test", netrole_ap, NULL, NULL); + if (!buf) { + wpa_printf(MSG_DEBUG, + "DPP: No configuration request data available"); + return; + } + + dpp_tcp_send_msg(conn, buf); + wpabuf_free(buf); +} + + +static void dpp_controller_auth_success(struct dpp_connection *conn, + int initiator) +{ + struct dpp_authentication *auth = conn->auth; + + if (!auth) + return; + + wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded"); + wpa_msg(conn->global->msg_ctx, MSG_INFO, + DPP_EVENT_AUTH_SUCCESS "init=%d", initiator); +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Confirm"); + if (auth->configurator) { + /* Prevent GAS response */ + auth->auth_success = 0; + } + return; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!auth->configurator) + dpp_controller_start_gas_client(conn); +} + + +static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + + wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock); + dpp_tcp_send(conn); +} + + +static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen, + const struct hostapd_ip_addr *ipaddr, + int port) +{ + struct sockaddr_in *dst; +#ifdef CONFIG_IPV6 + struct sockaddr_in6 *dst6; +#endif /* CONFIG_IPV6 */ + + switch (ipaddr->af) { + case AF_INET: + dst = (struct sockaddr_in *) addr; + os_memset(dst, 0, sizeof(*dst)); + dst->sin_family = AF_INET; + dst->sin_addr.s_addr = ipaddr->u.v4.s_addr; + dst->sin_port = htons(port); + *addrlen = sizeof(*dst); + break; +#ifdef CONFIG_IPV6 + case AF_INET6: + dst6 = (struct sockaddr_in6 *) addr; + os_memset(dst6, 0, sizeof(*dst6)); + dst6->sin6_family = AF_INET6; + os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6, + sizeof(struct in6_addr)); + dst6->sin6_port = htons(port); + *addrlen = sizeof(*dst6); + break; +#endif /* CONFIG_IPV6 */ + default: + return -1; + } + + return 0; +} + + +static struct dpp_connection * +dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src, + unsigned int freq) +{ + struct dpp_connection *conn; + struct sockaddr_storage addr; + socklen_t addrlen; + char txt[100]; + + if (dl_list_len(&ctrl->conn) >= 15) { + wpa_printf(MSG_DEBUG, + "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one"); + return NULL; + } + + if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen, + &ctrl->ipaddr, DPP_TCP_PORT) < 0) + return NULL; + + conn = os_zalloc(sizeof(*conn)); + if (!conn) + return NULL; + + conn->global = ctrl->global; + conn->relay = ctrl; + os_memcpy(conn->mac_addr, src, ETH_ALEN); + conn->freq = freq; + + conn->sock = socket(AF_INET, SOCK_STREAM, 0); + if (conn->sock < 0) + goto fail; + wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s", + conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt))); + + if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { + wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", + strerror(errno)); + goto fail; + } + + if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) { + if (errno != EINPROGRESS) { + wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", + strerror(errno)); + goto fail; + } + + /* + * Continue connecting in the background; eloop will call us + * once the connection is ready (or failed). + */ + } + + if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, conn, NULL) < 0) + goto fail; + conn->write_eloop = 1; + + /* TODO: eloop timeout to clear a connection if it does not complete + * properly */ + + dl_list_add(&ctrl->conn, &conn->list); + return conn; +fail: + dpp_connection_free(conn); + return NULL; +} + + +static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len) +{ + struct wpabuf *msg; + + msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len); + if (!msg) + return NULL; + wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len); + wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC); + wpabuf_put_data(msg, hdr, DPP_HDR_LEN); + wpabuf_put_data(msg, buf, len); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); + return msg; +} + + +static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr, + const u8 *buf, size_t len) +{ + u8 type = hdr[DPP_HDR_LEN - 1]; + + wpa_printf(MSG_DEBUG, + "DPP: Continue already established Relay/Controller connection for this session"); + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = dpp_tcp_encaps(hdr, buf, len); + if (!conn->msg_out) { + dpp_connection_remove(conn); + return -1; + } + + /* TODO: for proto ver 1, need to do remove connection based on GAS Resp + * TX status */ + if (type == DPP_PA_CONFIGURATION_RESULT) + conn->on_tcp_tx_complete_remove = 1; + dpp_tcp_send(conn); + return 0; +} + + +int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, + const u8 *buf, size_t len, unsigned int freq, + const u8 *i_bootstrap, const u8 *r_bootstrap) +{ + struct dpp_relay_controller *ctrl; + struct dpp_connection *conn; + u8 type = hdr[DPP_HDR_LEN - 1]; + + /* Check if there is an already started session for this peer and if so, + * continue that session (send this over TCP) and return 0. + */ + if (type != DPP_PA_PEER_DISCOVERY_REQ && + type != DPP_PA_PEER_DISCOVERY_RESP && + type != DPP_PA_PRESENCE_ANNOUNCEMENT) { + dl_list_for_each(ctrl, &dpp->controllers, + struct dpp_relay_controller, list) { + dl_list_for_each(conn, &ctrl->conn, + struct dpp_connection, list) { + if (os_memcmp(src, conn->mac_addr, + ETH_ALEN) == 0) + return dpp_relay_tx(conn, hdr, buf, len); + } + } + } + + if (!r_bootstrap) + return -1; + + if (type == DPP_PA_PRESENCE_ANNOUNCEMENT) { + /* TODO: Could send this to all configured Controllers. For now, + * only the first Controller is supported. */ + ctrl = dl_list_first(&dpp->controllers, + struct dpp_relay_controller, list); + } else { + ctrl = dpp_relay_controller_get(dpp, r_bootstrap); + } + if (!ctrl) + return -1; + + wpa_printf(MSG_DEBUG, + "DPP: Authentication Request for a configured Controller"); + conn = dpp_relay_new_conn(ctrl, src, freq); + if (!conn) + return -1; + + conn->msg_out = dpp_tcp_encaps(hdr, buf, len); + if (!conn->msg_out) { + dpp_connection_remove(conn); + return -1; + } + /* Message will be sent in dpp_conn_tx_ready() */ + + return 0; +} + + +int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data, + size_t data_len) +{ + struct dpp_relay_controller *ctrl; + struct dpp_connection *conn, *found = NULL; + struct wpabuf *msg; + + /* Check if there is a successfully completed authentication for this + * and if so, continue that session (send this over TCP) and return 0. + */ + dl_list_for_each(ctrl, &dpp->controllers, + struct dpp_relay_controller, list) { + if (found) + break; + dl_list_for_each(conn, &ctrl->conn, + struct dpp_connection, list) { + if (os_memcmp(src, conn->mac_addr, + ETH_ALEN) == 0) { + found = conn; + break; + } + } + } + + if (!found) + return -1; + + msg = wpabuf_alloc(4 + 1 + data_len); + if (!msg) + return -1; + wpabuf_put_be32(msg, 1 + data_len); + wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ); + wpabuf_put_data(msg, data, data_len); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); + + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = msg; + dpp_tcp_send(conn); + return 0; +} + + +static void dpp_controller_free(struct dpp_controller *ctrl) +{ + struct dpp_connection *conn, *tmp; + + if (!ctrl) + return; + + dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection, + list) + dpp_connection_remove(conn); + + if (ctrl->sock >= 0) { + close(ctrl->sock); + eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ); + } + os_free(ctrl->configurator_params); + os_free(ctrl); +} + + +static int dpp_controller_rx_auth_req(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, size_t len) +{ + const u8 *r_bootstrap, *i_bootstrap; + u16 r_bootstrap_len, i_bootstrap_len; + struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL; + + if (!conn->ctrl) + return 0; + + wpa_printf(MSG_DEBUG, "DPP: Authentication Request"); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_printf(MSG_INFO, + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + + i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) { + wpa_printf(MSG_INFO, + "Missing or invalid required Initiator Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", + i_bootstrap, i_bootstrap_len); + + /* Try to find own and peer bootstrapping key matches based on the + * received hash values */ + dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap, + &own_bi, &peer_bi); + if (!own_bi) { + wpa_printf(MSG_INFO, + "No matching own bootstrapping key found - ignore message"); + return -1; + } + + if (conn->auth) { + wpa_printf(MSG_INFO, + "Already in DPP authentication exchange - ignore new one"); + return 0; + } + + conn->auth = dpp_auth_req_rx(conn->ctrl->global, + conn->ctrl->global->msg_ctx, + conn->ctrl->allowed_roles, + conn->ctrl->qr_mutual, + peer_bi, own_bi, -1, hdr, buf, len); + if (!conn->auth) { + wpa_printf(MSG_DEBUG, "DPP: No response generated"); + return -1; + } + + if (dpp_set_configurator(conn->auth, + conn->ctrl->configurator_params) < 0) { + dpp_connection_remove(conn); + return -1; + } + + return dpp_tcp_send_msg(conn, conn->auth->resp_msg); +} + + +static int dpp_controller_rx_auth_resp(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, size_t len) +{ + struct dpp_authentication *auth = conn->auth; + struct wpabuf *msg; + int res; + + if (!auth) + return -1; + + wpa_printf(MSG_DEBUG, "DPP: Authentication Response"); + + msg = dpp_auth_resp_rx(auth, hdr, buf, len); + if (!msg) { + if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { + wpa_printf(MSG_DEBUG, + "DPP: Start wait for full response"); + return -1; + } + wpa_printf(MSG_DEBUG, "DPP: No confirm generated"); + dpp_connection_remove(conn); + return -1; + } + + conn->on_tcp_tx_complete_auth_ok = 1; + res = dpp_tcp_send_msg(conn, msg); + wpabuf_free(msg); + return res; +} + + +static int dpp_controller_rx_auth_conf(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, size_t len) +{ + struct dpp_authentication *auth = conn->auth; + + wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation"); + + if (!auth) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Authentication in progress - drop"); + return -1; + } + + if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); + return -1; + } + + dpp_controller_auth_success(conn, 0); + return 0; +} + + +void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, + void *timeout_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + + if (!conn->auth->waiting_conf_result) + return; + + wpa_printf(MSG_DEBUG, + "DPP: Timeout while waiting for Connection Status Result"); + wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, + DPP_EVENT_CONN_STATUS_RESULT "timeout"); + dpp_connection_remove(conn); +} + + +static int dpp_controller_rx_conf_result(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + struct dpp_authentication *auth = conn->auth; + enum dpp_status_error status; + + if (!conn->ctrl) + return 0; + + wpa_printf(MSG_DEBUG, "DPP: Configuration Result"); + + if (!auth || !auth->waiting_conf_result) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Configuration waiting for result - drop"); + return -1; + } + + status = dpp_conf_result_rx(auth, hdr, buf, len); + if (status == DPP_STATUS_OK && auth->send_conn_status) { + wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, + DPP_EVENT_CONF_SENT "wait_conn_status=1"); + wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); + eloop_cancel_timeout( + dpp_controller_conn_status_result_wait_timeout, + conn, NULL); + eloop_register_timeout( + 16, 0, dpp_controller_conn_status_result_wait_timeout, + conn, NULL); + return 0; + } + if (status == DPP_STATUS_OK) + wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, + DPP_EVENT_CONF_SENT); + else + wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, + DPP_EVENT_CONF_FAILED); + return -1; /* to remove the completed connection */ +} + + +static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + struct dpp_authentication *auth = conn->auth; + enum dpp_status_error status; + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len = 0; + char *channel_list = NULL; + + if (!conn->ctrl) + return 0; + + wpa_printf(MSG_DEBUG, "DPP: Connection Status Result"); + + if (!auth || !auth->waiting_conn_status_result) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Configuration waiting for connection status result - drop"); + return -1; + } + + status = dpp_conn_status_result_rx(auth, hdr, buf, len, + ssid, &ssid_len, &channel_list); + wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, + DPP_EVENT_CONN_STATUS_RESULT + "result=%d ssid=%s channel_list=%s", + status, wpa_ssid_txt(ssid, ssid_len), + channel_list ? channel_list : "N/A"); + os_free(channel_list); + return -1; /* to remove the completed connection */ +} + + +static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + const u8 *r_bootstrap; + u16 r_bootstrap_len; + struct dpp_bootstrap_info *peer_bi; + struct dpp_authentication *auth; + struct dpp_global *dpp = conn->ctrl->global; + + if (conn->auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Presence Announcement during ongoing Authentication"); + return -1; + } + + wpa_printf(MSG_DEBUG, "DPP: Presence Announcement"); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + peer_bi = dpp_bootstrap_find_chirp(dpp, r_bootstrap); + if (!peer_bi) { + wpa_printf(MSG_DEBUG, + "DPP: No matching bootstrapping information found"); + return -1; + } + + auth = dpp_auth_init(dpp, dpp->msg_ctx, peer_bi, NULL, + DPP_CAPAB_CONFIGURATOR, -1, NULL, 0); + if (!auth) + return -1; + if (dpp_set_configurator(conn->auth, + conn->ctrl->configurator_params) < 0) { + dpp_auth_deinit(auth); + dpp_connection_remove(conn); + return -1; + } + + conn->auth = auth; + return dpp_tcp_send_msg(conn, conn->auth->req_msg); +} + + +static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + const u8 *csign_hash; + u16 csign_hash_len; + struct dpp_configurator *conf; + struct dpp_global *dpp = conn->ctrl->global; + + if (conn->auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Reconfig Announcement during ongoing Authentication"); + return -1; + } + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement"); + + csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, + &csign_hash_len); + if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { + wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Configurator C-sign key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", + csign_hash, csign_hash_len); + conf = dpp_configurator_find_kid(dpp, csign_hash); + if (!conf) { + wpa_printf(MSG_DEBUG, + "DPP: No matching Configurator information found"); + return -1; + } + + /* TODO: Initiate Reconfig Authentication */ + return -1; +} + + +static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, + size_t len) +{ + const u8 *pos, *end; + u8 type; + + wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP"); + pos = msg; + end = msg + len; + + if (end - pos < DPP_HDR_LEN || + WPA_GET_BE24(pos) != OUI_WFA || + pos[3] != DPP_OUI_TYPE) { + wpa_printf(MSG_DEBUG, "DPP: Unrecognized header"); + return -1; + } + + if (pos[4] != 1) { + wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u", + pos[4]); + return -1; + } + type = pos[5]; + wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type); + pos += DPP_HDR_LEN; + + wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", + pos, end - pos); + if (dpp_check_attrs(pos, end - pos) < 0) + return -1; + + if (conn->relay) { + wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN"); + conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr, + conn->freq, msg, len); + return 0; + } + + switch (type) { + case DPP_PA_AUTHENTICATION_REQ: + return dpp_controller_rx_auth_req(conn, msg, pos, end - pos); + case DPP_PA_AUTHENTICATION_RESP: + return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos); + case DPP_PA_AUTHENTICATION_CONF: + return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos); + case DPP_PA_CONFIGURATION_RESULT: + return dpp_controller_rx_conf_result(conn, msg, pos, end - pos); + case DPP_PA_CONNECTION_STATUS_RESULT: + return dpp_controller_rx_conn_status_result(conn, msg, pos, + end - pos); + case DPP_PA_PRESENCE_ANNOUNCEMENT: + return dpp_controller_rx_presence_announcement(conn, msg, pos, + end - pos); + case DPP_PA_RECONFIG_ANNOUNCEMENT: + return dpp_controller_rx_reconfig_announcement(conn, msg, pos, + end - pos); + default: + /* TODO: missing messages types */ + wpa_printf(MSG_DEBUG, + "DPP: Unsupported frame subtype %d", type); + return -1; + } +} + + +static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, + size_t len) +{ + const u8 *pos, *end, *next; + u8 dialog_token; + const u8 *adv_proto; + u16 slen; + struct wpabuf *resp, *buf; + struct dpp_authentication *auth = conn->auth; + + if (len < 1 + 2) + return -1; + + wpa_printf(MSG_DEBUG, + "DPP: Received DPP Configuration Request over TCP"); + + if (!conn->ctrl || !auth || !auth->auth_success) { + wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); + return -1; + } + + pos = msg; + end = msg + len; + + dialog_token = *pos++; + adv_proto = pos++; + slen = *pos++; + if (*adv_proto != WLAN_EID_ADV_PROTO || + slen > end - pos || slen < 2) + return -1; + + next = pos + slen; + pos++; /* skip QueryRespLenLimit and PAME-BI */ + + if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC || + pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA || + pos[5] != DPP_OUI_TYPE || pos[6] != 0x01) + return -1; + + pos = next; + /* Query Request */ + if (end - pos < 2) + return -1; + slen = WPA_GET_LE16(pos); + pos += 2; + if (slen > end - pos) + return -1; + + resp = dpp_conf_req_rx(auth, pos, slen); + if (!resp) + return -1; + + buf = wpabuf_alloc(4 + 18 + wpabuf_len(resp)); + if (!buf) { + wpabuf_free(resp); + return -1; + } + + wpabuf_put_be32(buf, 18 + wpabuf_len(resp)); + + wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP); + wpabuf_put_u8(buf, dialog_token); + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */ + + dpp_write_adv_proto(buf); + dpp_write_gas_query(buf, resp); + wpabuf_free(resp); + + /* Send Config Response over TCP; GAS fragmentation is taken care of by + * the Relay */ + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = buf; + conn->on_tcp_tx_complete_gas_done = 1; + dpp_tcp_send(conn); + return 0; +} + + +static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) +{ + struct dpp_authentication *auth = conn->auth; + int res; + struct wpabuf *msg; + enum dpp_status_error status; + + wpa_printf(MSG_DEBUG, + "DPP: Configuration Response for local stack from TCP"); + + res = dpp_conf_resp_rx(auth, resp); + wpabuf_free(resp); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); + return -1; + } + + if (conn->global->process_conf_obj) + res = conn->global->process_conf_obj(conn->global->cb_ctx, + auth); + else + res = 0; + + if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK) + return -1; + + wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result"); + status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK; + msg = dpp_build_conf_result(auth, status); + if (!msg) + return -1; + + conn->on_tcp_tx_complete_remove = 1; + res = dpp_tcp_send_msg(conn, msg); + wpabuf_free(msg); + + /* This exchange will be terminated in the TX status handler */ + + return res; +} + + +static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, + size_t len) +{ + struct wpabuf *buf; + u8 dialog_token; + const u8 *pos, *end, *next, *adv_proto; + u16 status, slen; + + if (len < 5 + 2) + return -1; + + wpa_printf(MSG_DEBUG, + "DPP: Received DPP Configuration Response over TCP"); + + pos = msg; + end = msg + len; + + dialog_token = *pos++; + status = WPA_GET_LE16(pos); + if (status != WLAN_STATUS_SUCCESS) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status); + return -1; + } + pos += 2; + pos += 2; /* ignore GAS Comeback Delay */ + + adv_proto = pos++; + slen = *pos++; + if (*adv_proto != WLAN_EID_ADV_PROTO || + slen > end - pos || slen < 2) + return -1; + + next = pos + slen; + pos++; /* skip QueryRespLenLimit and PAME-BI */ + + if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC || + pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA || + pos[5] != DPP_OUI_TYPE || pos[6] != 0x01) + return -1; + + pos = next; + /* Query Response */ + if (end - pos < 2) + return -1; + slen = WPA_GET_LE16(pos); + pos += 2; + if (slen > end - pos) + return -1; + + buf = wpabuf_alloc(slen); + if (!buf) + return -1; + wpabuf_put_data(buf, pos, slen); + + if (!conn->relay && !conn->ctrl) + return dpp_tcp_rx_gas_resp(conn, buf); + + if (!conn->relay) { + wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); + wpabuf_free(buf); + return -1; + } + wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN"); + conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr, + dialog_token, 0, buf); + + return 0; +} + + +static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + int res; + const u8 *pos; + + wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)", + sd); + + if (conn->msg_len_octets < 4) { + u32 msglen; + + res = recv(sd, &conn->msg_len[conn->msg_len_octets], + 4 - conn->msg_len_octets, 0); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", + strerror(errno)); + dpp_connection_remove(conn); + return; + } + if (res == 0) { + wpa_printf(MSG_DEBUG, + "DPP: No more data available over TCP"); + dpp_connection_remove(conn); + return; + } + wpa_printf(MSG_DEBUG, + "DPP: Received %d/%d octet(s) of message length field", + res, (int) (4 - conn->msg_len_octets)); + conn->msg_len_octets += res; + + if (conn->msg_len_octets < 4) { + wpa_printf(MSG_DEBUG, + "DPP: Need %d more octets of message length field", + (int) (4 - conn->msg_len_octets)); + return; + } + + msglen = WPA_GET_BE32(conn->msg_len); + wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen); + if (msglen > 65535) { + wpa_printf(MSG_INFO, "DPP: Unexpectedly long message"); + dpp_connection_remove(conn); + return; + } + + wpabuf_free(conn->msg); + conn->msg = wpabuf_alloc(msglen); + } + + if (!conn->msg) { + wpa_printf(MSG_DEBUG, + "DPP: No buffer available for receiving the message"); + dpp_connection_remove(conn); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload", + (unsigned int) wpabuf_tailroom(conn->msg)); + + res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno)); + dpp_connection_remove(conn); + return; + } + if (res == 0) { + wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP"); + dpp_connection_remove(conn); + return; + } + wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res); + wpabuf_put(conn->msg, res); + + if (wpabuf_tailroom(conn->msg) > 0) { + wpa_printf(MSG_DEBUG, + "DPP: Need %u more octets of message payload", + (unsigned int) wpabuf_tailroom(conn->msg)); + return; + } + + conn->msg_len_octets = 0; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg); + if (wpabuf_len(conn->msg) < 1) { + dpp_connection_remove(conn); + return; + } + + pos = wpabuf_head(conn->msg); + switch (*pos) { + case WLAN_PA_VENDOR_SPECIFIC: + if (dpp_controller_rx_action(conn, pos + 1, + wpabuf_len(conn->msg) - 1) < 0) + dpp_connection_remove(conn); + break; + case WLAN_PA_GAS_INITIAL_REQ: + if (dpp_controller_rx_gas_req(conn, pos + 1, + wpabuf_len(conn->msg) - 1) < 0) + dpp_connection_remove(conn); + break; + case WLAN_PA_GAS_INITIAL_RESP: + if (dpp_rx_gas_resp(conn, pos + 1, + wpabuf_len(conn->msg) - 1) < 0) + dpp_connection_remove(conn); + break; + default: + wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u", + *pos); + break; + } +} + + +static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) +{ + struct dpp_controller *ctrl = eloop_ctx; + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + int fd; + struct dpp_connection *conn; + + wpa_printf(MSG_DEBUG, "DPP: New TCP connection"); + + fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len); + if (fd < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to accept new connection: %s", + strerror(errno)); + return; + } + wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d", + inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + conn = os_zalloc(sizeof(*conn)); + if (!conn) + goto fail; + + conn->global = ctrl->global; + conn->ctrl = ctrl; + conn->sock = fd; + + if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { + wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", + strerror(errno)); + goto fail; + } + + if (eloop_register_sock(conn->sock, EVENT_TYPE_READ, + dpp_controller_rx, conn, NULL) < 0) + goto fail; + conn->read_eloop = 1; + + /* TODO: eloop timeout to expire connections that do not complete in + * reasonable time */ + dl_list_add(&ctrl->conn, &conn->list); + return; + +fail: + close(fd); + os_free(conn); +} + + +int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, + const struct hostapd_ip_addr *addr, int port) +{ + struct dpp_connection *conn; + struct sockaddr_storage saddr; + socklen_t addrlen; + const u8 *hdr, *pos, *end; + char txt[100]; + + wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d", + hostapd_ip_txt(addr, txt, sizeof(txt)), port); + if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen, + addr, port) < 0) { + dpp_auth_deinit(auth); + return -1; + } + + conn = os_zalloc(sizeof(*conn)); + if (!conn) { + dpp_auth_deinit(auth); + return -1; + } + + conn->global = dpp; + conn->auth = auth; + conn->sock = socket(AF_INET, SOCK_STREAM, 0); + if (conn->sock < 0) + goto fail; + + if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { + wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", + strerror(errno)); + goto fail; + } + + if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) { + if (errno != EINPROGRESS) { + wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", + strerror(errno)); + goto fail; + } + + /* + * Continue connecting in the background; eloop will call us + * once the connection is ready (or failed). + */ + } + + if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, conn, NULL) < 0) + goto fail; + conn->write_eloop = 1; + + hdr = wpabuf_head(auth->req_msg); + end = hdr + wpabuf_len(auth->req_msg); + hdr += 2; /* skip Category and Actiom */ + pos = hdr + DPP_HDR_LEN; + conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos); + if (!conn->msg_out) + goto fail; + /* Message will be sent in dpp_conn_tx_ready() */ + + /* TODO: eloop timeout to clear a connection if it does not complete + * properly */ + dl_list_add(&dpp->tcp_init, &conn->list); + return 0; +fail: + dpp_connection_free(conn); + return -1; +} + + +int dpp_controller_start(struct dpp_global *dpp, + struct dpp_controller_config *config) +{ + struct dpp_controller *ctrl; + int on = 1; + struct sockaddr_in sin; + int port; + + if (!dpp || dpp->controller) + return -1; + + ctrl = os_zalloc(sizeof(*ctrl)); + if (!ctrl) + return -1; + ctrl->global = dpp; + if (config->configurator_params) + ctrl->configurator_params = + os_strdup(config->configurator_params); + dl_list_init(&ctrl->conn); + /* TODO: configure these somehow */ + ctrl->allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; + ctrl->qr_mutual = 0; + + ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); + if (ctrl->sock < 0) + goto fail; + + if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)) < 0) { + wpa_printf(MSG_DEBUG, + "DPP: setsockopt(SO_REUSEADDR) failed: %s", + strerror(errno)); + /* try to continue anyway */ + } + + if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) { + wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s", + strerror(errno)); + goto fail; + } + + /* TODO: IPv6 */ + os_memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT; + sin.sin_port = htons(port); + if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + wpa_printf(MSG_INFO, + "DPP: Failed to bind Controller TCP port: %s", + strerror(errno)); + goto fail; + } + if (listen(ctrl->sock, 10 /* max backlog */) < 0 || + fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 || + eloop_register_sock(ctrl->sock, EVENT_TYPE_READ, + dpp_controller_tcp_cb, ctrl, NULL)) + goto fail; + + dpp->controller = ctrl; + wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port); + return 0; +fail: + dpp_controller_free(ctrl); + return -1; +} + + +void dpp_controller_stop(struct dpp_global *dpp) +{ + if (dpp) { + dpp_controller_free(dpp->controller); + dpp->controller = NULL; + } +} + + +void dpp_tcp_init_flush(struct dpp_global *dpp) +{ + struct dpp_connection *conn, *tmp; + + dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection, + list) + dpp_connection_remove(conn); +} + + +static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl) +{ + struct dpp_connection *conn, *tmp; + + dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection, + list) + dpp_connection_remove(conn); + os_free(ctrl); +} + + +void dpp_relay_flush_controllers(struct dpp_global *dpp) +{ + struct dpp_relay_controller *ctrl, *tmp; + + if (!dpp) + return; + + dl_list_for_each_safe(ctrl, tmp, &dpp->controllers, + struct dpp_relay_controller, list) { + dl_list_del(&ctrl->list); + dpp_relay_controller_free(ctrl); + } +} + +#endif /* CONFIG_DPP2 */ diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index a5c45fd90..07bfac06c 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -26,6 +26,7 @@ OBJS += $(SRC)/common/dpp_backup.o OBJS += $(SRC)/common/dpp_crypto.o OBJS += $(SRC)/common/dpp_pkex.o OBJS += $(SRC)/common/dpp_reconfig.o +OBJS += $(SRC)/common/dpp_tcp.o dpp-uri: dpp-uri.o $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index eea5875e0..a0c9e23c8 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -252,6 +252,7 @@ OBJS += src/common/dpp_backup.c OBJS += src/common/dpp_crypto.c OBJS += src/common/dpp_pkex.c OBJS += src/common/dpp_reconfig.c +OBJS += src/common/dpp_tcp.c OBJS += dpp_supplicant.c NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 66ed8352a..e15694821 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -284,6 +284,7 @@ OBJS += ../src/common/dpp_backup.o OBJS += ../src/common/dpp_crypto.o OBJS += ../src/common/dpp_pkex.o OBJS += ../src/common/dpp_reconfig.o +OBJS += ../src/common/dpp_tcp.o OBJS += dpp_supplicant.o NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y From 5e2d877cc4137e7bea7d0cdd4bc643e69c957922 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 12:16:20 +0300 Subject: [PATCH 0483/1105] DPP: Mark internal-to-file functions static These functions are not used outside dpp_crypto.c anymore. Signed-off-by: Jouni Malinen --- src/common/dpp_crypto.c | 12 +++++++----- src/common/dpp_i.h | 5 ----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 7495746da..8bf2a74a6 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -99,7 +99,8 @@ const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name) } -const struct dpp_curve_params * dpp_get_curve_oid(const ASN1_OBJECT *poid) +static const struct dpp_curve_params * +dpp_get_curve_oid(const ASN1_OBJECT *poid) { ASN1_OBJECT *oid; int i; @@ -215,8 +216,9 @@ void dpp_debug_print_key(const char *title, EVP_PKEY *key) } -int dpp_hash_vector(const struct dpp_curve_params *curve, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) +static int dpp_hash_vector(const struct dpp_curve_params *curve, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) { if (curve->hash_len == 32) return sha256_vector(num_elem, addr, len, mac); @@ -264,8 +266,8 @@ int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, } -int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, u8 *mac) +static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, + const u8 *data, size_t data_len, u8 *mac) { if (hash_len == 32) return hmac_sha256(key, key_len, data, data_len, mac); diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index f18b8be08..e66eb6cfd 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -72,7 +72,6 @@ dpp_check_signed_connector(struct dpp_signed_connector_info *info, const u8 *peer_connector, size_t peer_connector_len); const struct dpp_curve_params * dpp_get_curve_name(const char *name); const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name); -const struct dpp_curve_params * dpp_get_curve_oid(const ASN1_OBJECT *poid); const struct dpp_curve_params * dpp_get_curve_nid(int nid); int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len); @@ -82,12 +81,8 @@ EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, size_t len); EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len); int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len); -int dpp_hash_vector(const struct dpp_curve_params *curve, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, const char *label, u8 *out, size_t outlen); -int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, u8 *mac); int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); From 3b4f7dfaa178bc9e774701a32f64228cccf0f9c6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 15:59:12 +0300 Subject: [PATCH 0484/1105] DPP2: Fix Presence Announcement processing in Controller Use the new struct dpp_authentication instance when setting Configurator parameters for authentication exchange triggered by Presence Announcement. conn->auth is NULL here and would cause dereferencing of a NULL pointer if dpp_configurator_params is set. Fixes: fa5143feb3cb ("DPP2: Presence Announcement processing in Controller") Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 3165a03f9..5a824943d 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -804,8 +804,7 @@ static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, DPP_CAPAB_CONFIGURATOR, -1, NULL, 0); if (!auth) return -1; - if (dpp_set_configurator(conn->auth, - conn->ctrl->configurator_params) < 0) { + if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) { dpp_auth_deinit(auth); dpp_connection_remove(conn); return -1; From 6dcb8aaf13f0b15334c31554ce8034fb58d81c04 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 16:02:51 +0300 Subject: [PATCH 0485/1105] DPP2: Reconfig Announcement relaying from AP to Controller Recognize the Reconfig Announcement message type and handle it similarly to the Presence Announcement in the Relay, i.e., send it to the first Controller if the local Configurator does not have matching C-sign-key. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 4 ++++ src/common/dpp_tcp.c | 11 ++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index f7d286747..548e8856e 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1258,6 +1258,10 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp, csign_hash); if (!conf) { + if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, + src, hdr, buf, len, freq, NULL, + NULL) == 0) + return; wpa_printf(MSG_DEBUG, "DPP: No matching Configurator information found"); return; diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 5a824943d..bfac377bb 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -448,7 +448,8 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, */ if (type != DPP_PA_PEER_DISCOVERY_REQ && type != DPP_PA_PEER_DISCOVERY_RESP && - type != DPP_PA_PRESENCE_ANNOUNCEMENT) { + type != DPP_PA_PRESENCE_ANNOUNCEMENT && + type != DPP_PA_RECONFIG_ANNOUNCEMENT) { dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller, list) { dl_list_for_each(conn, &ctrl->conn, @@ -460,15 +461,15 @@ int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, } } - if (!r_bootstrap) - return -1; - - if (type == DPP_PA_PRESENCE_ANNOUNCEMENT) { + if (type == DPP_PA_PRESENCE_ANNOUNCEMENT || + type == DPP_PA_RECONFIG_ANNOUNCEMENT) { /* TODO: Could send this to all configured Controllers. For now, * only the first Controller is supported. */ ctrl = dl_list_first(&dpp->controllers, struct dpp_relay_controller, list); } else { + if (!r_bootstrap) + return -1; ctrl = dpp_relay_controller_get(dpp, r_bootstrap); } if (!ctrl) From 7f20a3ebda5e319904f6bfb12b2b697318192604 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 16:04:46 +0300 Subject: [PATCH 0486/1105] DPP2: Reconfiguration support in Controller Add handling of Reconfiguration messages in Controller. Signed-off-by: Jouni Malinen --- src/common/dpp_reconfig.c | 2 +- src/common/dpp_tcp.c | 45 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 355114cbc..0bb00cc1d 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -188,7 +188,7 @@ dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, auth->configurator = 1; auth->curve = conf->curve; auth->transaction_id = 1; - if (dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) + if (freq && dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) goto fail; if (dpp_configurator_build_own_connector(conf) < 0) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index bfac377bb..f58093f0d 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -824,6 +824,7 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, u16 csign_hash_len; struct dpp_configurator *conf; struct dpp_global *dpp = conn->ctrl->global; + struct dpp_authentication *auth; if (conn->auth) { wpa_printf(MSG_DEBUG, @@ -849,8 +850,42 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, return -1; } - /* TODO: Initiate Reconfig Authentication */ - return -1; + auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0); + if (!auth) + return -1; + if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) { + dpp_auth_deinit(auth); + return -1; + } + + conn->auth = auth; + return dpp_tcp_send_msg(conn, auth->reconfig_req_msg); +} + + +static int dpp_controller_rx_reconfig_auth_resp(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + struct dpp_authentication *auth = conn->auth; + struct wpabuf *conf; + int res; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response"); + + if (!auth || !auth->reconfig || !auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - drop"); + return -1; + } + + conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); + if (!conf) + return -1; + + res = dpp_tcp_send_msg(conn, conf); + wpabuf_free(conf); + return res; } @@ -910,6 +945,9 @@ static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, case DPP_PA_RECONFIG_ANNOUNCEMENT: return dpp_controller_rx_reconfig_announcement(conn, msg, pos, end - pos); + case DPP_PA_RECONFIG_AUTH_RESP: + return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos, + end - pos); default: /* TODO: missing messages types */ wpa_printf(MSG_DEBUG, @@ -935,7 +973,8 @@ static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, wpa_printf(MSG_DEBUG, "DPP: Received DPP Configuration Request over TCP"); - if (!conn->ctrl || !auth || !auth->auth_success) { + if (!conn->ctrl || !auth || + (!auth->auth_success && !auth->reconfig_success)) { wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return -1; } From 217656d098329fd865679d325cd09a1174961b45 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 2 May 2020 00:01:47 +0300 Subject: [PATCH 0487/1105] tests: DPP reconfiguration exchange Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 170 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 164 insertions(+), 6 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index ff3faaa0f..a2c1d53a0 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -4642,8 +4642,8 @@ def test_dpp_controller_relay_chirp(dev, apdev, params): dev[1].request("DPP_CONTROLLER_STOP") def run_dpp_controller_relay(dev, apdev, params, chirp=False): - check_dpp_capab(dev[0]) - check_dpp_capab(dev[1]) + check_dpp_capab(dev[0], min_ver=2) + check_dpp_capab(dev[1], min_ver=2) prefix = "dpp_controller_relay" if chirp: prefix += "_chirp" @@ -4653,9 +4653,8 @@ def run_dpp_controller_relay(dev, apdev, params, chirp=False): # Controller conf_id = dev[1].dpp_configurator_add() - if not chirp: - dev[1].set("dpp_configurator_params", - " conf=sta-dpp configurator=%d" % conf_id) + dev[1].set("dpp_configurator_params", + "conf=sta-dpp configurator=%d" % conf_id) id_c = dev[1].dpp_bootstrap_gen() uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) res = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_c) @@ -4711,6 +4710,24 @@ def run_dpp_controller_relay(dev, apdev, params, chirp=False): wait_auth_success(dev[1], dev[0], configurator=dev[1], enrollee=dev[0], allow_enrollee_failure=True, allow_configurator_failure=True) + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1) + if ev is None: + raise Exception("DPP network id not reported") + network = int(ev.split(' ')[1]) + dev[0].wait_connected() + dev[0].dump_monitor() + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + if "OK" not in dev[0].request("DPP_RECONFIG %s" % network): + raise Exception("Failed to start reconfiguration") + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=15) + if ev is None: + raise Exception("DPP network id not reported for reconfiguration") + network2 = int(ev.split(' ')[1]) + if network == network2: + raise Exception("Network ID did not change") dev[0].wait_connected() time.sleep(0.5) @@ -5335,6 +5352,7 @@ def run_dpp_reconfig_connector(dev, apdev): ssid = "reconfig" passphrase = "secret passphrase" + passphrase2 = "another secret passphrase" params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) hapd = hostapd.add_ap(apdev[0], params) @@ -5345,9 +5363,16 @@ def run_dpp_reconfig_connector(dev, apdev): configurator = dev[1].dpp_configurator_add() conf = 'sta-psk' dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid=ssid, - passphrase=passphrase, configurator=configurator) + passphrase=passphrase, configurator=configurator, + conn_status=True) res = wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0]) + if 'wait_conn_status' not in res: + raise Exception("Configurator did not request connection status") + ev = dev[1].wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20) + if ev is None: + raise Exception("No connection status reported") + dev[1].dump_monitor() ev = dev[0].wait_event(["DPP-CONFOBJ-SSID"], timeout=1) if ev is None: @@ -5395,6 +5420,139 @@ def run_dpp_reconfig_connector(dev, apdev): raise Exception("net_access_key mismatch: %s %s" % (n_net_access_key, net_access_key)) + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + + hapd.disable() + hapd.set("wpa_passphrase", passphrase2) + hapd.enable() + + time.sleep(0.1) + dev[0].dump_monitor() + dev[1].dump_monitor() + + dev[1].set("dpp_configurator_params", + "conf=sta-psk ssid=%s pass=%s conn_status=1" % (binascii.hexlify(ssid.encode()).decode(), binascii.hexlify(passphrase2.encode()).decode())) + dev[1].dpp_listen(2437) + + if "OK" not in dev[0].request("DPP_RECONFIG %s" % id): + raise Exception("Failed to start reconfiguration") + ev = dev[0].wait_event(["DPP-TX "], timeout=10) + if ev is None or "type=14" not in ev: + raise Exception("Reconfig Announcement not sent") + + ev = dev[1].wait_event(["DPP-RX"], timeout=5) + if ev is None: + raise Exception("DPP Reconfig Announcement not received") + if "freq=2437 type=14" not in ev: + raise Exception("Unexpected RX data for Reconfig Announcement: " + ev) + + ev = dev[0].wait_event(["DPP-RX"], timeout=5) + if ev is None or "freq=2437 type=15" not in ev: + raise Exception("DPP Reconfig Authentication Request not received") + + ev = dev[1].wait_event(["DPP-RX"], timeout=5) + if ev is None or "freq=2437 type=16" not in ev: + raise Exception("DPP Reconfig Authentication Response not received") + + ev = dev[0].wait_event(["DPP-RX"], timeout=5) + if ev is None or "freq=2437 type=17" not in ev: + raise Exception("DPP Reconfig Authentication Confirm not received") + + ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) + if ev is None or "freq=2437" not in ev: + raise Exception("DPP Config Request (GAS) not transmitted") + + ev = dev[1].wait_event(["DPP-CONF-REQ-RX"], timeout=5) + if ev is None: + raise Exception("DPP Config Request (GAS) not received") + + ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) + if ev is None or "freq=2437" not in ev: + raise Exception("DPP Config Response (GAS) not received") + + ev = dev[1].wait_event(["DPP-RX"], timeout=5) + if ev is None or "freq=2437 type=11" not in ev: + raise Exception("DPP Config Result not received") + + ev = dev[1].wait_event(["DPP-CONF-SENT"], timeout=5) + if ev is None: + raise Exception("DPP Config Response (GAS) not transmitted") + + ev = dev[0].wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"], timeout=5) + if ev is None: + raise Exception("DPP config response reception result not indicated") + if "DPP-CONF-RECEIVED" not in ev: + raise Exception("Reconfiguration failed") + + dev[0].wait_connected() + + ev = dev[1].wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20) + if ev is None: + raise Exception("No connection status reported") + +def test_dpp_reconfig_hostapd_configurator(dev, apdev): + """DPP reconfiguration with hostapd as configurator""" + try: + run_dpp_reconfig_hostapd_configurator(dev, apdev) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_reconfig_hostapd_configurator(dev, apdev): + ssid = "reconfig-ap" + check_dpp_capab(dev[0], min_ver=2) + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"}) + check_dpp_capab(hapd, min_ver=2) + conf_id = hapd.dpp_configurator_add() + + cmd = "DPP_CONFIGURATOR_SIGN conf=ap-dpp configurator=%d ssid=%s" % (conf_id, binascii.hexlify(ssid.encode()).decode()) + res = hapd.request(cmd) + if "FAIL" in res: + raise Exception("Failed to generate own configuration") + hapd.set("dpp_configurator_connectivity", "1") + update_hapd_config(hapd) + + id = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id) + dev[0].set("dpp_config_processing", "2") + dev[0].dpp_listen(2412) + hapd.dpp_auth_init(uri=uri, conf="sta-dpp", configurator=conf_id, + extra="expiry=%d" % (time.time() + 10), ssid=ssid) + wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0]) + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1) + if ev is None: + raise Exception("DPP network id not reported") + network = int(ev.split(' ')[1]) + dev[0].wait_connected() + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].dump_monitor() + time.sleep(10) + if "FAIL" in dev[0].request("PMKSA_FLUSH"): + raise Exception("PMKSA_FLUSH failed") + dev[0].request("RECONNECT") + ev = dev[0].wait_event(["DPP-MISSING-CONNECTOR", "CTRL-EVENT-CONNECTED"], + timeout=15) + if ev is None or "DPP-MISSING-CONNECTOR" not in ev: + raise Exception("Missing Connector not reported") + if "netAccessKey expired" not in ev: + raise Exception("netAccessKey expiry not indicated") + dev[0].request("DISCONNECT") + dev[0].dump_monitor() + + hapd.set("dpp_configurator_params", + "conf=sta-dpp configurator=%d ssid=%s" % (conf_id, binascii.hexlify(ssid.encode()).decode())) + + if "OK" not in dev[0].request("DPP_RECONFIG %s" % network): + raise Exception("Failed to start reconfiguration") + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=15) + if ev is None: + raise Exception("DPP network id not reported for reconfiguration") + network2 = int(ev.split(' ')[1]) + if network == network2: + raise Exception("Network ID did not change") + dev[0].wait_connected() + def test_dpp_qr_code_auth_rand_mac_addr(dev, apdev): """DPP QR Code and authentication exchange (rand_mac_addr=1)""" flags = int(dev[0].get_driver_status_field('capa.flags'), 16) From 670e1533775703e14450d3a0650fb75811377f08 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 17:28:09 +0300 Subject: [PATCH 0488/1105] DPP2: Fix DPP_CHIRP listen parameter value validation Check the correct variable. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index b8c1716ce..d3de39558 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3362,7 +3362,7 @@ int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd) pos = os_strstr(cmd, " listen="); if (pos) { listen_freq = atoi(pos + 8); - if (iter <= 0) + if (listen_freq <= 0) return -1; } From 890ae336c0a4ec3daa6a4a2ba1a344d318072261 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 11 May 2020 17:30:26 +0300 Subject: [PATCH 0489/1105] DPP2: Clean up CONFIG_DPP2 use with configurator connectivity IE Avoid duplicated return statement in CONFIG_DPP2=y builds. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11_shared.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 113b4ef04..74a837f8b 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -886,9 +886,9 @@ size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd) u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len) { -#ifdef CONFIG_DPP2 u8 *pos = eid; +#ifdef CONFIG_DPP2 if (!hapd->conf->dpp_configurator_connectivity || len < 6) return pos; @@ -897,10 +897,9 @@ u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len) WPA_PUT_BE24(pos, OUI_WFA); pos += 3; *pos++ = DPP_CC_OUI_TYPE; +#endif /* CONFIG_DPP2 */ return pos; -#endif /* CONFIG_DPP2 */ - return eid; } From 0086c145285f0c9372c0f1908127270ceef67567 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 12 May 2020 00:57:44 +0300 Subject: [PATCH 0490/1105] DPP: Extend NFC bootstrapping script for more control by caller Add more parameters to dpp-nfc.py to allow it to be used with more detailed control by the caller. This allows Enrollee/Configurator roles to be selected and Configurator parameters to be specified on the command line. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 48 +++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index f49da34f4..173416794 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -255,18 +255,28 @@ def dpp_handover_client(llc): success_report("DPP handover reported successfully (initiator)") print("peer_id=" + res) peer_id = int(res) - # TODO: Single Configurator instance wpas = wpas_connect() if wpas is None: break - res = wpas.request("DPP_CONFIGURATOR_ADD") - if "FAIL" in res: - print("Failed to initiate Configurator") - break - conf_id = int(res) + + global enrollee_only + global config_params + if enrollee_only: + extra = " role=enrollee" + elif config_params: + extra = " role=configurator " + config_params + else: + # TODO: Single Configurator instance + res = wpas.request("DPP_CONFIGURATOR_ADD") + if "FAIL" in res: + print("Failed to initiate Configurator") + break + conf_id = int(res) + extra = " conf=sta-dpp configurator=%d" % conf_id global own_id print("Initiate DPP authentication") - cmd = "DPP_AUTH_INIT peer=%d own=%d conf=sta-dpp configurator=%d" % (peer_id, own_id, conf_id) + cmd = "DPP_AUTH_INIT peer=%d own=%d" % (peer_id, own_id) + cmd += extra res = wpas.request(cmd) if "FAIL" in res: print("Failed to initiate DPP authentication") @@ -356,7 +366,14 @@ class HandoverServer(nfc.handover.HandoverServer): if freq is None: print("No channel negotiated over NFC - use channel 1") freq = 2412 - res = wpas.request("DPP_LISTEN %d" % freq) + cmd = "DPP_LISTEN %d" % freq + global enrollee_only + global configurator_only + if enrollee_only: + cmd += " role=enrollee" + elif configurator_only: + cmd += " role=configurator" + res = wpas.request(cmd) if "OK" not in res: print("Failed to start DPP listen") break @@ -592,6 +609,12 @@ def main(): help='tag read only (do not allow connection handover)') parser.add_argument('--handover-only', action='store_true', help='connection handover only (do not allow tag read)') + parser.add_argument('--enrollee', action='store_true', + help='run as Enrollee-only') + parser.add_argument('--configurator', action='store_true', + help='run as Configurator-only') + parser.add_argument('--config-params', default='', + help='configurator parameters') parser.add_argument('--summary', help='summary file for writing status updates') parser.add_argument('--success', @@ -618,6 +641,15 @@ def main(): global init_on_touch init_on_touch = args.init_on_touch + global enrollee_only + enrollee_only = args.enrollee + + global configurator_only + configurator_only = args.configurator + + global config_params + config_params = args.config_params + if args.ifname: global ifname ifname = args.ifname From db59827a3c899d7f985c2217397ac15c92c3d4cb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 12 May 2020 14:25:15 +0300 Subject: [PATCH 0491/1105] DPP2: Extend TCP encapsulation case to support Configurator as Initiator This allows DPP_AUTH_INIT to be used with tcp_addr= argument and Configurator parameters to perform Configurator initiated DPP provisioning over TCP. Similarly, DPP_CONTROLLER_START can now be used to specify Configurator/Enrollee roles and extend Controller to work in Enrollee role. Signed-off-by: Jouni Malinen --- src/common/dpp.h | 1 + src/common/dpp_tcp.c | 39 +++++++++++++++++++++------------ wpa_supplicant/dpp_supplicant.c | 15 +++++++++++++ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/common/dpp.h b/src/common/dpp.h index 07c5bef62..c0927d9b8 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -358,6 +358,7 @@ struct dpp_relay_config { struct dpp_controller_config { const char *configurator_params; int tcp_port; + u8 allowed_roles; }; #ifdef CONFIG_TESTING_OPTIONS diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index f58093f0d..fc53b8a0b 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -139,6 +139,7 @@ dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash) static void dpp_controller_gas_done(struct dpp_connection *conn) { struct dpp_authentication *auth = conn->auth; + void *msg_ctx; if (auth->peer_version >= 2 && auth->conf_resp_status == DPP_STATUS_OK) { @@ -147,7 +148,11 @@ static void dpp_controller_gas_done(struct dpp_connection *conn) return; } - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); + if (conn->ctrl) + msg_ctx = conn->ctrl->global->msg_ctx; + else + msg_ctx = auth->msg_ctx; + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); dpp_connection_remove(conn); } @@ -196,8 +201,8 @@ static int dpp_tcp_send(struct dpp_connection *conn) conn->read_eloop = 1; if (conn->on_tcp_tx_complete_remove) { dpp_connection_remove(conn); - } else if (conn->ctrl && conn->on_tcp_tx_complete_gas_done && - conn->auth) { + } else if (conn->auth && (conn->ctrl || conn->auth->configurator) && + conn->on_tcp_tx_complete_gas_done) { dpp_controller_gas_done(conn); } else if (conn->on_tcp_tx_complete_auth_ok) { conn->on_tcp_tx_complete_auth_ok = 0; @@ -699,8 +704,9 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn, { struct dpp_authentication *auth = conn->auth; enum dpp_status_error status; + void *msg_ctx; - if (!conn->ctrl) + if (!conn->ctrl && (!auth || !auth->configurator)) return 0; wpa_printf(MSG_DEBUG, "DPP: Configuration Result"); @@ -710,10 +716,14 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn, "DPP: No DPP Configuration waiting for result - drop"); return -1; } + if (conn->ctrl) + msg_ctx = conn->ctrl->global->msg_ctx; + else + msg_ctx = auth->msg_ctx; status = dpp_conf_result_rx(auth, hdr, buf, len); if (status == DPP_STATUS_OK && auth->send_conn_status) { - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT "wait_conn_status=1"); wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); eloop_cancel_timeout( @@ -725,11 +735,9 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn, return 0; } if (status == DPP_STATUS_OK) - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONF_SENT); + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); else - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONF_FAILED); + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED); return -1; /* to remove the completed connection */ } @@ -973,7 +981,7 @@ static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, wpa_printf(MSG_DEBUG, "DPP: Received DPP Configuration Request over TCP"); - if (!conn->ctrl || !auth || + if (!auth || (!conn->ctrl && !auth->configurator) || (!auth->auth_success && !auth->reconfig_success)) { wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return -1; @@ -1049,7 +1057,10 @@ static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) wpa_printf(MSG_DEBUG, "DPP: Configuration Response for local stack from TCP"); - res = dpp_conf_resp_rx(auth, resp); + if (auth) + res = dpp_conf_resp_rx(auth, resp); + else + res = -1; wpabuf_free(resp); if (res < 0) { wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); @@ -1135,7 +1146,8 @@ static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, return -1; wpabuf_put_data(buf, pos, slen); - if (!conn->relay && !conn->ctrl) + if (!conn->relay && + (!conn->ctrl || (conn->ctrl->allowed_roles & DPP_CAPAB_ENROLLEE))) return dpp_tcp_rx_gas_resp(conn, buf); if (!conn->relay) { @@ -1405,8 +1417,7 @@ int dpp_controller_start(struct dpp_global *dpp, ctrl->configurator_params = os_strdup(config->configurator_params); dl_list_init(&ctrl->conn); - /* TODO: configure these somehow */ - ctrl->allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; + ctrl->allowed_roles = config->allowed_roles; ctrl->qr_mutual = 0; ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index d3de39558..b9b882bf2 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3117,12 +3117,27 @@ int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) const char *pos; os_memset(&config, 0, sizeof(config)); + config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; if (cmd) { pos = os_strstr(cmd, " tcp_port="); if (pos) { pos += 10; config.tcp_port = atoi(pos); } + + pos = os_strstr(cmd, " role="); + if (pos) { + pos += 6; + if (os_strncmp(pos, "configurator", 12) == 0) + config.allowed_roles = DPP_CAPAB_CONFIGURATOR; + else if (os_strncmp(pos, "enrollee", 8) == 0) + config.allowed_roles = DPP_CAPAB_ENROLLEE; + else if (os_strncmp(pos, "either", 6) == 0) + config.allowed_roles = DPP_CAPAB_CONFIGURATOR | + DPP_CAPAB_ENROLLEE; + else + return -1; + } } config.configurator_params = wpa_s->dpp_configurator_params; return dpp_controller_start(wpa_s->dpp, &config); From b37a1ec24f8efab49e341a4366302bad9f51e9b8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 12 May 2020 14:38:56 +0300 Subject: [PATCH 0492/1105] tests: DPP over TCP (Configurator initiates) Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index a2c1d53a0..c228d5673 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -4788,6 +4788,40 @@ def run_dpp_tcp(dev, apdev, cap_lo, port=None): time.sleep(0.5) wt.close() +def test_dpp_tcp_conf_init(dev, apdev, params): + """DPP over TCP (Configurator initiates)""" + cap_lo = os.path.join(params['prefix'], ".lo.pcap") + try: + run_dpp_tcp_conf_init(dev, apdev, cap_lo) + finally: + dev[1].request("DPP_CONTROLLER_STOP") + +def run_dpp_tcp_conf_init(dev, apdev, cap_lo, port=None): + check_dpp_capab(dev[0], min_ver=2) + check_dpp_capab(dev[1], min_ver=2) + + wt = WlantestCapture('lo', cap_lo) + time.sleep(1) + + id_c = dev[1].dpp_bootstrap_gen() + uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + res = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_c) + req = "DPP_CONTROLLER_START role=enrollee" + if port: + req += " tcp_port=" + port + if "OK" not in dev[1].request(req): + raise Exception("Failed to start Controller") + + conf_id = dev[0].dpp_configurator_add() + dev[0].dpp_auth_init(uri=uri_c, role="configurator", conf="sta-dpp", + configurator=conf_id, + tcp_addr="127.0.0.1", tcp_port=port) + wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1], + allow_enrollee_failure=True, + allow_configurator_failure=True) + time.sleep(0.5) + wt.close() + def test_dpp_tcp_controller_start_failure(dev, apdev, params): """DPP Controller startup failure""" check_dpp_capab(dev[0]) From 644638819ab014cc69d4ede2f32eb438e1e25711 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 12 May 2020 14:32:00 +0300 Subject: [PATCH 0493/1105] tests: Additional sigma_dut DPP over TCP coverage Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 114 ++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index dd3f35fb9..b7f832c9e 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -2968,6 +2968,56 @@ def run_sigma_dut_dpp_tcp_conf_resp(dev, status_query=False): finally: stop_sigma_dut(sigma) +def dpp_init_tcp_configurator(dev, id1, conf_id): + logger.info("Starting DPP initiator/configurator (TCP) in a thread") + time.sleep(1) + cmd = "DPP_AUTH_INIT peer=%d role=configurator conf=sta-dpp configurator=%d tcp_addr=127.0.0.1" % (id1, conf_id) + if "OK" not in dev.request(cmd): + raise Exception("Failed to initiate DPP Authentication") + ev = dev.wait_event(["DPP-CONF-SENT"], timeout=5) + if ev is None: + raise Exception("DPP configuration not completed (Configurator)") + logger.info("DPP initiator/configurator done") + +def test_sigma_dut_dpp_tcp_enrollee_resp(dev, apdev): + """sigma_dut DPP TCP Enrollee (Controller) as responder""" + run_sigma_dut_dpp_tcp_enrollee_resp(dev) + +def run_sigma_dut_dpp_tcp_enrollee_resp(dev, status_query=False): + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + sigma = start_sigma_dut(dev[0].ifname) + try: + cmd = "dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPCryptoIdentifier,P-256,DPPBS,QR" + res = sigma_dut_cmd(cmd) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + hex = res.split(',')[3] + uri = from_hex(hex) + logger.info("URI from sigma_dut: " + uri) + + cmd = "DPP_CONFIGURATOR_ADD" + res = dev[1].request(cmd) + if "FAIL" in res: + raise Exception("Failed to add configurator") + conf_id = int(res) + + id1 = dev[1].dpp_qr_code(uri) + + t = threading.Thread(target=dpp_init_tcp_configurator, args=(dev[1], id1, conf_id)) + t.start() + cmd = "dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Responder,DPPAuthDirection,Single,DPPProvisioningRole,Enrollee,DPPSigningKeyECC,P-256,DPPBS,QR,DPPOverTCP,yes,DPPTimeout,6" + if status_query: + cmd += ",DPPStatusQuery,Yes" + res = sigma_dut_cmd(cmd, timeout=10) + t.join() + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: + raise Exception("Unexpected result: " + res) + if status_query and "StatusResult,0" not in res: + raise Exception("Status query did not succeed: " + res) + finally: + stop_sigma_dut(sigma) + def test_sigma_dut_dpp_tcp_enrollee_init(dev, apdev): """sigma_dut DPP TCP Enrollee as initiator""" check_dpp_capab(dev[0]) @@ -2995,6 +3045,70 @@ def test_sigma_dut_dpp_tcp_enrollee_init(dev, apdev): stop_sigma_dut(sigma) dev[1].request("DPP_CONTROLLER_STOP") +def test_sigma_dut_dpp_tcp_enrollee_init_mutual(dev, apdev): + """sigma_dut DPP TCP Enrollee as initiator with mutual authentication""" + check_dpp_capab(dev[0], min_ver=2) + check_dpp_capab(dev[1], min_ver=2) + sigma = start_sigma_dut(dev[0].ifname) + try: + # Controller + conf_id = dev[1].dpp_configurator_add() + dev[1].set("dpp_configurator_params", + "conf=sta-dpp configurator=%d" % conf_id) + id_c = dev[1].dpp_bootstrap_gen() + uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + if "OK" not in dev[1].request("DPP_CONTROLLER_START"): + raise Exception("Failed to start Controller") + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,QR" % to_hex(uri_c)) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + + cmd = "dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPCryptoIdentifier,P-256,DPPBS,QR" + res = sigma_dut_cmd_check(cmd) + hex = res.split(',')[3] + uri = from_hex(hex) + logger.info("URI from sigma_dut: " + uri) + id1 = dev[1].dpp_qr_code(uri) + + cmd = "dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPAuthDirection,Mutual,DPPProvisioningRole,Enrollee,DPPBS,QR,DPPOverTCP,127.0.0.1,DPPTimeout,6" + res = sigma_dut_cmd(cmd, timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: + raise Exception("Unexpected result: " + res) + finally: + stop_sigma_dut(sigma) + dev[1].request("DPP_CONTROLLER_STOP") + +def test_sigma_dut_dpp_tcp_configurator_init_mutual(dev, apdev): + """sigma_dut DPP TCP Configurator as initiator with mutual authentication""" + check_dpp_capab(dev[0], min_ver=2) + check_dpp_capab(dev[1], min_ver=2) + sigma = start_sigma_dut(dev[0].ifname) + try: + id_c = dev[1].dpp_bootstrap_gen() + uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + if "OK" not in dev[1].request("DPP_CONTROLLER_START role=enrollee"): + raise Exception("Failed to start Controller") + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,QR" % to_hex(uri_c)) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + + cmd = "dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPCryptoIdentifier,P-256,DPPBS,QR" + res = sigma_dut_cmd_check(cmd) + hex = res.split(',')[3] + uri = from_hex(hex) + logger.info("URI from sigma_dut: " + uri) + id1 = dev[1].dpp_qr_code(uri) + + cmd = "dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPAuthDirection,Mutual,DPPProvisioningRole,Configurator,DPPConfIndex,1,DPPConfEnrolleeRole,STA,DPPBS,QR,DPPOverTCP,127.0.0.1,DPPTimeout,6" + res = sigma_dut_cmd(cmd, timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: + raise Exception("Unexpected result: " + res) + finally: + stop_sigma_dut(sigma) + dev[1].request("DPP_CONTROLLER_STOP") + def test_sigma_dut_dpp_nfc_handover_requestor_enrollee(dev, apdev): """sigma_dut DPP/NFC handover requestor as Enrollee""" check_dpp_capab(dev[0]) From 6fffb320fc278bd0af091e3ee53417cdead6ac6a Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 24 Apr 2020 19:20:36 +0530 Subject: [PATCH 0494/1105] nl80211: Remove QCA vendor specific AKM capability handling Since this functionality was not used for anything in practice, it is easier to simply remove this functionality completely to avoid potential conflicts in using the kernel tree upstream commit ab4dfa20534e ("cfg80211: Allow drivers to advertise supported AKM suites"). This is practically reverting the commit 8ec7c99ee4c6 ("nl80211: Fetch supported AKM list from the driver"). Signed-off-by: Veerendranath Jakkam --- src/drivers/driver_nl80211.h | 1 - src/drivers/driver_nl80211_capa.c | 129 ------------------------------ 2 files changed, 130 deletions(-) diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index dc80a17b8..c3ad88a39 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -169,7 +169,6 @@ struct wpa_driver_nl80211_data { unsigned int set_wifi_conf_vendor_cmd_avail:1; unsigned int fetch_bss_trans_status:1; unsigned int roam_vendor_cmd_avail:1; - unsigned int get_supported_akm_suites_avail:1; unsigned int add_sta_node_vendor_cmd_avail:1; unsigned int control_port_ap:1; unsigned int multicast_registrations:1; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index f997577db..34ad0c694 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -809,9 +809,6 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) case QCA_NL80211_VENDOR_SUBCMD_ROAM: drv->roam_vendor_cmd_avail = 1; break; - case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS: - drv->get_supported_akm_suites_avail = 1; - break; case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: drv->add_sta_node_vendor_cmd_avail = 1; break; @@ -990,126 +987,6 @@ static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data *drv) } -static unsigned int get_akm_suites_info(struct nlattr *tb) -{ - int i, num; - unsigned int key_mgmt = 0; - u32 *akms; - - if (!tb) - return 0; - - num = nla_len(tb) / sizeof(u32); - akms = nla_data(tb); - for (i = 0; i < num; i++) { - u32 a = akms[i]; - - wpa_printf(MSG_DEBUG, - "nl80211: Supported AKM %02x-%02x-%02x:%u", - a >> 24, (a >> 16) & 0xff, - (a >> 8) & 0xff, a & 0xff); - switch (a) { - case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2; - break; - case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - break; - case RSN_AUTH_KEY_MGMT_FT_802_1X: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT; - break; - case RSN_AUTH_KEY_MGMT_FT_PSK: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; - break; - case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B; - break; - case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192; - break; - case RSN_AUTH_KEY_MGMT_OWE: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OWE; - break; - case RSN_AUTH_KEY_MGMT_DPP: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_DPP; - break; - case RSN_AUTH_KEY_MGMT_FILS_SHA256: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256; - break; - case RSN_AUTH_KEY_MGMT_FILS_SHA384: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; - break; - case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256; - break; - case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384; - break; - case RSN_AUTH_KEY_MGMT_SAE: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SAE; - break; - } - } - - return key_mgmt; -} - - -static int get_akm_suites_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - unsigned int *key_mgmt = arg; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (tb[NL80211_ATTR_VENDOR_DATA]) { - struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA]; - struct nlattr *tb_data[NL80211_ATTR_MAX + 1]; - - nla_parse(tb_data, NL80211_ATTR_MAX, - nla_data(nl_vend), nla_len(nl_vend), NULL); - - *key_mgmt = - get_akm_suites_info(tb_data[NL80211_ATTR_AKM_SUITES]); - } - - return NL_SKIP; -} - - -static int qca_nl80211_get_akm_suites(struct wpa_driver_nl80211_data *drv) -{ - struct nl_msg *msg; - unsigned int key_mgmt = 0; - int ret; - - if (!drv->get_supported_akm_suites_avail) - return -1; - - if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || - nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || - nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, - QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS)) { - nlmsg_free(msg); - return -1; - } - - ret = send_and_recv_msgs(drv, msg, get_akm_suites_handler, &key_mgmt); - if (!ret) { - wpa_printf(MSG_DEBUG, - "nl80211: Replace capa.key_mgmt based on driver advertised capabilities: 0x%x", - key_mgmt); - drv->capa.key_mgmt = key_mgmt; - } - - return ret; -} - - struct features_info { u8 *flags; size_t flags_len; @@ -1250,12 +1127,6 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; -#ifdef CONFIG_DRIVER_NL80211_QCA - /* Override drv->capa.key_mgmt based on driver advertised capability - * constraints, if available. */ - qca_nl80211_get_akm_suites(drv); -#endif /* CONFIG_DRIVER_NL80211_QCA */ - drv->capa.auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | WPA_DRIVER_AUTH_LEAP; From b67bedf2e3572411b1a65933a425dfef299ee185 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 24 Apr 2020 22:49:25 +0530 Subject: [PATCH 0495/1105] nl80211: Fetch information on supported AKMs from the driver The driver can advertise supported AKMs per wiphy and/or per interface. Populate per interface supported AKMs based on the driver advertisement in the following order of preference: 1. AKM suites advertised by NL80211_ATTR_IFTYPE_AKM_SUITES 2. AKM suites advertised by NL80211_ATTR_AKM_SUITES If neither of these is available: 3. AKMs support is assumed as per legacy behavior. In addition, extend other driver interface wrappers to set the per-interface values based on the global capability indication. Signed-off-by: Veerendranath Jakkam --- src/drivers/driver.h | 127 ++++++++-------- src/drivers/driver_bsd.c | 5 + src/drivers/driver_ndis.c | 6 + src/drivers/driver_nl80211.c | 15 +- src/drivers/driver_nl80211.h | 1 + src/drivers/driver_nl80211_capa.c | 231 +++++++++++++++++++++++++++--- src/drivers/driver_wext.c | 5 + 7 files changed, 311 insertions(+), 79 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index e3b13bc25..b0713249f 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1658,6 +1658,73 @@ struct wpa_driver_set_key_params { enum key_flag key_flag; }; +enum wpa_driver_if_type { + /** + * WPA_IF_STATION - Station mode interface + */ + WPA_IF_STATION, + + /** + * WPA_IF_AP_VLAN - AP mode VLAN interface + * + * This interface shares its address and Beacon frame with the main + * BSS. + */ + WPA_IF_AP_VLAN, + + /** + * WPA_IF_AP_BSS - AP mode BSS interface + * + * This interface has its own address and Beacon frame. + */ + WPA_IF_AP_BSS, + + /** + * WPA_IF_P2P_GO - P2P Group Owner + */ + WPA_IF_P2P_GO, + + /** + * WPA_IF_P2P_CLIENT - P2P Client + */ + WPA_IF_P2P_CLIENT, + + /** + * WPA_IF_P2P_GROUP - P2P Group interface (will become either + * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known) + */ + WPA_IF_P2P_GROUP, + + /** + * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the + * abstracted P2P Device function in the driver + */ + WPA_IF_P2P_DEVICE, + + /* + * WPA_IF_MESH - Mesh interface + */ + WPA_IF_MESH, + + /* + * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only) + */ + WPA_IF_TDLS, + + /* + * WPA_IF_IBSS - IBSS interface (used for pref freq only) + */ + WPA_IF_IBSS, + + /* + * WPA_IF_NAN - NAN Device + */ + WPA_IF_NAN, + + /* keep last */ + WPA_IF_MAX +}; + /** * struct wpa_driver_capa - Driver capability information */ @@ -1681,6 +1748,7 @@ struct wpa_driver_capa { #define WPA_DRIVER_CAPA_KEY_MGMT_SAE 0x00010000 /** Bitfield of supported key management suites */ unsigned int key_mgmt; + unsigned int key_mgmt_iftype[WPA_IF_MAX]; #define WPA_DRIVER_CAPA_ENC_WEP40 0x00000001 #define WPA_DRIVER_CAPA_ENC_WEP104 0x00000002 @@ -2045,65 +2113,6 @@ struct hostapd_acl_params { struct mac_address mac_acl[0]; }; -enum wpa_driver_if_type { - /** - * WPA_IF_STATION - Station mode interface - */ - WPA_IF_STATION, - - /** - * WPA_IF_AP_VLAN - AP mode VLAN interface - * - * This interface shares its address and Beacon frame with the main - * BSS. - */ - WPA_IF_AP_VLAN, - - /** - * WPA_IF_AP_BSS - AP mode BSS interface - * - * This interface has its own address and Beacon frame. - */ - WPA_IF_AP_BSS, - - /** - * WPA_IF_P2P_GO - P2P Group Owner - */ - WPA_IF_P2P_GO, - - /** - * WPA_IF_P2P_CLIENT - P2P Client - */ - WPA_IF_P2P_CLIENT, - - /** - * WPA_IF_P2P_GROUP - P2P Group interface (will become either - * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known) - */ - WPA_IF_P2P_GROUP, - - /** - * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the - * abstracted P2P Device function in the driver - */ - WPA_IF_P2P_DEVICE, - - /* - * WPA_IF_MESH - Mesh interface - */ - WPA_IF_MESH, - - /* - * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only) - */ - WPA_IF_TDLS, - - /* - * WPA_IF_IBSS - IBSS interface (used for pref freq only) - */ - WPA_IF_IBSS, -}; - struct wpa_init_params { void *global_priv; const u8 *bssid; diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c index b4400d7bf..5adee13a2 100644 --- a/src/drivers/driver_bsd.c +++ b/src/drivers/driver_bsd.c @@ -1451,6 +1451,7 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) #define GETPARAM(drv, param, v) \ (((v) = get80211param(drv, param)) != -1) struct bsd_driver_data *drv; + int i; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) @@ -1486,6 +1487,10 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) if (wpa_driver_bsd_capa(drv)) goto fail; + /* Update per interface supported AKMs */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + /* Down interface during setup. */ if (bsd_get_iface_flags(drv) < 0) goto fail; diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c index 529fc3bc6..b5fff483e 100644 --- a/src/drivers/driver_ndis.c +++ b/src/drivers/driver_ndis.c @@ -2809,6 +2809,7 @@ static void * wpa_driver_ndis_init(void *ctx, const char *ifname) { struct wpa_driver_ndis_data *drv; u32 mode; + int i; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) @@ -2855,6 +2856,11 @@ static void * wpa_driver_ndis_init(void *ctx, const char *ifname) } wpa_driver_ndis_get_capability(drv); + /* Update per interface supported AKMs */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + + /* Make sure that the driver does not have any obsolete PMKID entries. */ wpa_driver_ndis_flush_pmkid(drv); diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index d48f8cb76..9c72341f9 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2328,10 +2328,19 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) /* FT Action frames */ if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0) ret = -1; - else + else if (!drv->has_driver_key_mgmt) { + int i; + + /* Update supported AKMs only if the driver doesn't advertize + * any AKM capabilities. */ drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT | WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; + /* Update per interface supported AKMs */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + } + /* WNM - BSS Transition Management Request */ if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0) ret = -1; @@ -5056,6 +5065,10 @@ const char * nl80211_iftype_str(enum nl80211_iftype mode) return "P2P_GO"; case NL80211_IFTYPE_P2P_DEVICE: return "P2P_DEVICE"; + case NL80211_IFTYPE_OCB: + return "OCB"; + case NL80211_IFTYPE_NAN: + return "NAN"; default: return "unknown"; } diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index c3ad88a39..660f49879 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -111,6 +111,7 @@ struct wpa_driver_nl80211_data { unsigned int num_iface_ext_capa; int has_capability; + int has_driver_key_mgmt; int operstate; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 34ad0c694..a3341a088 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -79,6 +79,8 @@ struct wiphy_info_data { unsigned int mac_addr_rand_scan_supported:1; unsigned int mac_addr_rand_sched_scan_supported:1; unsigned int update_ft_ies_supported:1; + unsigned int has_key_mgmt:1; + unsigned int has_key_mgmt_iftype:1; }; @@ -252,6 +254,158 @@ static void wiphy_info_supp_cmds(struct wiphy_info_data *info, } +static unsigned int get_akm_suites_info(struct nlattr *tb) +{ + int i, num; + unsigned int key_mgmt = 0; + u32 *akms; + + if (!tb) + return 0; + + num = nla_len(tb) / sizeof(u32); + akms = nla_data(tb); + for (i = 0; i < num; i++) { + switch (akms[i]) { + case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2; + break; + case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; + break; + case RSN_AUTH_KEY_MGMT_FT_802_1X: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT; + break; + case RSN_AUTH_KEY_MGMT_FT_PSK: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; + break; + case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B; + break; + case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192; + break; + case RSN_AUTH_KEY_MGMT_OWE: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OWE; + break; + case RSN_AUTH_KEY_MGMT_DPP: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_DPP; + break; + case RSN_AUTH_KEY_MGMT_FILS_SHA256: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256; + break; + case RSN_AUTH_KEY_MGMT_FILS_SHA384: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; + break; + case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256; + break; + case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384; + break; + case RSN_AUTH_KEY_MGMT_SAE: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SAE; + break; + } + } + + return key_mgmt; +} + + +static void get_iface_akm_suites_info(struct wiphy_info_data *info, + struct nlattr *nl_akms) +{ + struct nlattr *tb[NL80211_IFTYPE_AKM_ATTR_MAX + 1]; + struct nlattr *nl_iftype; + unsigned int key_mgmt; + int i; + + if (!nl_akms) + return; + + nla_parse(tb, NL80211_IFTYPE_AKM_ATTR_MAX, + nla_data(nl_akms), nla_len(nl_akms), NULL); + + if (!tb[NL80211_IFTYPE_AKM_ATTR_IFTYPES] || + !tb[NL80211_IFTYPE_AKM_ATTR_SUITES]) + return; + + info->has_key_mgmt_iftype = 1; + key_mgmt = get_akm_suites_info(tb[NL80211_IFTYPE_AKM_ATTR_SUITES]); + + nla_for_each_nested(nl_iftype, tb[NL80211_IFTYPE_AKM_ATTR_IFTYPES], i) { + switch (nla_type(nl_iftype)) { + case NL80211_IFTYPE_ADHOC: + info->drv->capa.key_mgmt_iftype[WPA_IF_IBSS] = key_mgmt; + break; + case NL80211_IFTYPE_STATION: + info->drv->capa.key_mgmt_iftype[WPA_IF_STATION] = + key_mgmt; + break; + case NL80211_IFTYPE_AP: + info->drv->capa.key_mgmt_iftype[WPA_IF_AP_BSS] = + key_mgmt; + break; + case NL80211_IFTYPE_AP_VLAN: + info->drv->capa.key_mgmt_iftype[WPA_IF_AP_VLAN] = + key_mgmt; + break; + case NL80211_IFTYPE_MESH_POINT: + info->drv->capa.key_mgmt_iftype[WPA_IF_MESH] = key_mgmt; + break; + case NL80211_IFTYPE_P2P_CLIENT: + info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_CLIENT] = + key_mgmt; + break; + case NL80211_IFTYPE_P2P_GO: + info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_GO] = + key_mgmt; + break; + case NL80211_IFTYPE_P2P_DEVICE: + info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_DEVICE] = + key_mgmt; + break; + case NL80211_IFTYPE_NAN: + info->drv->capa.key_mgmt_iftype[WPA_IF_NAN] = key_mgmt; + break; + } + wpa_printf(MSG_DEBUG, "nl80211: %s supported key_mgmt 0x%x", + nl80211_iftype_str(nla_type(nl_iftype)), + key_mgmt); + } +} + + +static void wiphy_info_iftype_akm_suites(struct wiphy_info_data *info, + struct nlattr *tb) +{ + struct nlattr *nl_if; + int rem_if; + + if (!tb) + return; + + nla_for_each_nested(nl_if, tb, rem_if) + get_iface_akm_suites_info(info, nl_if); +} + + +static void wiphy_info_akm_suites(struct wiphy_info_data *info, + struct nlattr *tb) +{ + if (!tb) + return; + + info->has_key_mgmt = 1; + info->capa->key_mgmt = get_akm_suites_info(tb); + wpa_printf(MSG_DEBUG, "nl80211: wiphy supported key_mgmt 0x%x", + info->capa->key_mgmt); +} + + static void wiphy_info_cipher_suites(struct wiphy_info_data *info, struct nlattr *tb) { @@ -696,6 +850,8 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]); wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]); wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]); + wiphy_info_akm_suites(info, tb[NL80211_ATTR_AKM_SUITES]); + wiphy_info_iftype_akm_suites(info, tb[NL80211_ATTR_IFTYPE_AKM_SUITES]); if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) { wpa_printf(MSG_DEBUG, "nl80211: Using driver-based " @@ -1098,6 +1254,8 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv) int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) { struct wiphy_info_data info; + int i; + if (wpa_driver_nl80211_get_info(drv, &info)) return -1; @@ -1105,27 +1263,62 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) return -1; drv->has_capability = 1; - drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B | - WPA_DRIVER_CAPA_KEY_MGMT_OWE | - WPA_DRIVER_CAPA_KEY_MGMT_DPP; + drv->has_driver_key_mgmt = info.has_key_mgmt | info.has_key_mgmt_iftype; - if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 | - WPA_DRIVER_CAPA_ENC_GCMP_256)) - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192; + /* Fallback to hardcoded defaults if the driver does nott advertize any + * AKM capabilities. */ + if (!drv->has_driver_key_mgmt) { + drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B | + WPA_DRIVER_CAPA_KEY_MGMT_OWE | + WPA_DRIVER_CAPA_KEY_MGMT_DPP; - if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | - WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 | - WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 | - WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 | - WPA_DRIVER_CAPA_KEY_MGMT_SAE; - else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | - WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; + if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 | + WPA_DRIVER_CAPA_ENC_GCMP_256)) + drv->capa.key_mgmt |= + WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192; + + if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) + drv->capa.key_mgmt |= + WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | + WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 | + WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 | + WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 | + WPA_DRIVER_CAPA_KEY_MGMT_SAE; + else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) + drv->capa.key_mgmt |= + WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | + WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; + } + + if (!info.has_key_mgmt_iftype) { + /* If the driver does not advertize per interface AKM + * capabilities, consider all interfaces to support default AKMs + * in key_mgmt. */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + } else if (info.has_key_mgmt_iftype && !info.has_key_mgmt) { + /* If the driver advertizes only per interface supported AKMs + * but does not advertize per wiphy AKM capabilities, consider + * the default key_mgmt as a mask of per interface supported + * AKMs. */ + drv->capa.key_mgmt = 0; + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt |= drv->capa.key_mgmt_iftype[i]; + } else if (info.has_key_mgmt_iftype && info.has_key_mgmt) { + /* If the driver advertizes AKM capabilities both per wiphy and + * per interface, consider the interfaces for which per + * interface AKM capabilities were not received to support the + * default key_mgmt capabilities. + */ + for (i = 0; i < WPA_IF_MAX; i++) + if (!drv->capa.key_mgmt_iftype[i]) + drv->capa.key_mgmt_iftype[i] = + drv->capa.key_mgmt; + } drv->capa.auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index 978e1cf43..8a3adee05 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -968,6 +968,7 @@ static void wext_check_hostap(struct wpa_driver_wext_data *drv) static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) { int send_rfkill_event = 0; + int i; if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) { if (rfkill_is_blocked(drv->rfkill)) { @@ -996,6 +997,10 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) wpa_driver_wext_get_range(drv); + /* Update per interface supported AKMs */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + /* * Unlock the driver's BSSID and force to a random SSID to clear any * previous association the driver might have when the supplicant From 8d7502809c93ef7161e6e91707977a3d63bafc8a Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 22 Apr 2020 12:54:35 +0530 Subject: [PATCH 0496/1105] Allow per interface type AKM capabilities to be fetched Add support to query per interface type AKM capabilities through the control interface. For example, "GET_CAPABILITY key_mgmt iftype=STATION". Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/ctrl_iface.c | 109 ++++++++++++++++++++++++++++-------- wpa_supplicant/wpa_cli.c | 43 ++++++++++++-- 2 files changed, 122 insertions(+), 30 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 5c99735c8..4860e3480 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4098,11 +4098,49 @@ static int ctrl_iface_get_capability_group_mgmt(int res, char *strict, } +static int iftype_str_to_index(const char *iftype_str) +{ + if (!iftype_str) + return WPA_IF_MAX; + + if (os_strcmp(iftype_str, "STATION") == 0) + return WPA_IF_STATION; + + if (os_strcmp(iftype_str, "AP_VLAN") == 0) + return WPA_IF_AP_VLAN; + + if (os_strcmp(iftype_str, "AP") == 0) + return WPA_IF_AP_BSS; + + if (os_strcmp(iftype_str, "P2P_GO") == 0) + return WPA_IF_P2P_GO; + + if (os_strcmp(iftype_str, "P2P_CLIENT") == 0) + return WPA_IF_P2P_CLIENT; + + if (os_strcmp(iftype_str, "P2P_DEVICE") == 0) + return WPA_IF_P2P_DEVICE; + + if (os_strcmp(iftype_str, "MESH") == 0) + return WPA_IF_MESH; + + if (os_strcmp(iftype_str, "IBSS") == 0) + return WPA_IF_IBSS; + + if (os_strcmp(iftype_str, "NAN") == 0) + return WPA_IF_NAN; + + return WPA_IF_MAX; +} + + static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, struct wpa_driver_capa *capa, + const char *iftype_str, char *buf, size_t buflen) { int ret; + unsigned int key_mgmt; char *pos, *end; size_t len; @@ -4119,28 +4157,39 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, return len; } + if (iftype_str) { + enum wpa_driver_if_type iftype; + + iftype = iftype_str_to_index(iftype_str); + if (iftype == WPA_IF_MAX) + return -1; + key_mgmt = capa->key_mgmt_iftype[iftype]; + } else { + key_mgmt = capa->key_mgmt; + } + ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; - if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { + if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { ret = os_snprintf(pos, end - pos, " WPA-EAP"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { + if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { ret = os_snprintf(pos, end - pos, " WPA-PSK"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { ret = os_snprintf(pos, end - pos, " WPA-NONE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4148,7 +4197,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #ifdef CONFIG_SUITEB - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4156,7 +4205,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_SUITEB */ #ifdef CONFIG_SUITEB192 - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4164,7 +4213,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_SUITEB192 */ #ifdef CONFIG_OWE - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { ret = os_snprintf(pos, end - pos, " OWE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4172,7 +4221,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { ret = os_snprintf(pos, end - pos, " DPP"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4180,26 +4229,26 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_DPP */ #ifdef CONFIG_FILS - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { ret = os_snprintf(pos, end - pos, " FILS-SHA256"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { ret = os_snprintf(pos, end - pos, " FILS-SHA384"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } #ifdef CONFIG_IEEE80211R - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4208,7 +4257,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, #endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_FILS */ #ifdef CONFIG_IEEE80211R - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { ret = os_snprintf(pos, end - pos, " FT-PSK"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4216,7 +4265,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_SAE - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { ret = os_snprintf(pos, end - pos, " SAE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4512,23 +4561,35 @@ static int wpa_supplicant_ctrl_iface_get_capability( { struct wpa_driver_capa capa; int res; - char *strict; - char field[30]; + char *next_param, *curr_param, *iftype = NULL, *strict = NULL; + char field[50]; size_t len; /* Determine whether or not strict checking was requested */ len = os_strlcpy(field, _field, sizeof(field)); if (len >= sizeof(field)) return -1; - strict = os_strchr(field, ' '); - if (strict != NULL) { - *strict++ = '\0'; - if (os_strcmp(strict, "strict") != 0) + + next_param = os_strchr(field, ' '); + while (next_param) { + *next_param++ = '\0'; + curr_param = next_param; + next_param = os_strchr(next_param, ' '); + + if (next_param) + *next_param = '\0'; + + if (os_strcmp(curr_param, "strict") == 0) + strict = curr_param; + else if (os_strncmp(curr_param, "iftype=", 7) == 0) + iftype = curr_param + 7; + else return -1; } - wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", - field, strict ? strict : ""); + wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s", + field, iftype ? " iftype=" : "", iftype ? iftype : "", + strict ? " strict" : ""); if (os_strcmp(field, "eap") == 0) { return eap_get_names(buf, buflen); @@ -4550,7 +4611,7 @@ static int wpa_supplicant_ctrl_iface_get_capability( if (os_strcmp(field, "key_mgmt") == 0) return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, - buf, buflen); + iftype, buf, buflen); if (os_strcmp(field, "proto") == 0) return ctrl_iface_get_capability_proto(res, strict, &capa, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 07d5f315c..6a2d2c3d6 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1706,15 +1706,25 @@ static char ** wpa_cli_complete_bss(const char *str, int pos) static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, char *argv[]) { - if (argc < 1 || argc > 2) { - printf("Invalid GET_CAPABILITY command: need either one or " - "two arguments\n"); + if (argc < 1 || argc > 3) { + printf("Invalid GET_CAPABILITY command: need at least one argument and max three arguments\n"); return -1; } - if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { - printf("Invalid GET_CAPABILITY command: second argument, " - "if any, must be 'strict'\n"); + if (argc > 1 && os_strcmp(argv[0], "key_mgmt") != 0 && + os_strncmp(argv[1], "iftype=", 7) == 0) { + printf("Invalid GET_CAPABILITY command: 'iftype=' param is allowed only for 'key_mgmt'\n"); + return -1; + } + + if (argc == 2 && os_strcmp(argv[1], "strict") != 0 && + os_strncmp(argv[1], "iftype=", 7) != 0) { + printf("Invalid GET_CAPABILITY command: the second argument, if any, must be 'strict' OR 'iftype='\n"); + return -1; + } + + if (argc == 3 && os_strcmp(argv[2], "strict") != 0) { + printf("Invalid GET_CAPABILITY command: the third argument, if any, must be 'strict'\n"); return -1; } @@ -1741,7 +1751,13 @@ static char ** wpa_cli_complete_get_capability(const char *str, int pos) "acs", #endif /* CONFIG_ACS */ }; + const char *iftypes[] = { + "iftype=STATION", "iftype=AP", "iftype=P2P_CLIENT", + "iftype=P2P_GO", "iftype=AP_VLAN", "iftype=IBSS", "iftype=NAN", + "iftype=P2P_DEVICE", "iftype=MESH", + }; int i, num_fields = ARRAY_SIZE(fields); + int num_iftypes = ARRAY_SIZE(iftypes); char **res = NULL; if (arg == 1) { @@ -1755,6 +1771,21 @@ static char ** wpa_cli_complete_get_capability(const char *str, int pos) } } if (arg == 2) { + /* the second argument can be "iftype=" OR + * "strict" */ + res = os_calloc(num_iftypes + 2, sizeof(char *)); + if (!res) + return NULL; + res[0] = os_strdup("strict"); + if (!res[0]) + return res; + for (i = 0; i < num_iftypes; i++) { + res[i + 1] = os_strdup(iftypes[i]); + if (!res[i + 1]) + return res; + } + } + if (arg == 3) { res = os_calloc(1 + 1, sizeof(char *)); if (res == NULL) return NULL; From 3790f3a6eeba0ec828d32ab7ce8eb8f85cc72f19 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 22 Apr 2020 12:54:35 +0530 Subject: [PATCH 0497/1105] Use per-interface type driver key_mgmt capabilities when possible Use key_mgmt_iftype instead of key_mgmt when the specific interface type is known by the context of the operation. Use per interface type AKM capabilities in capa.key_mgmt_iftype array based on the wpa_supplicant context instead of using capa.key_mgmt to determine the driver AKM capability. Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/dpp_supplicant.c | 3 ++- wpa_supplicant/interworking.c | 3 ++- wpa_supplicant/wps_supplicant.c | 6 +++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index b9b882bf2..a41b3f5c0 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1136,7 +1136,8 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, res = wpa_drv_get_capa(wpa_s, &capa); if (res == 0 && - !(capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) && + !(capa.key_mgmt_iftype[WPA_IF_STATION] & + WPA_DRIVER_CAPA_KEY_MGMT_SAE) && !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) { wpa_printf(MSG_DEBUG, "DPP: SAE not supported by the driver"); diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index c48525cec..a380123b3 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -946,7 +946,8 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, struct wpa_driver_capa capa; res = wpa_drv_get_capa(wpa_s, &capa); - if (res == 0 && capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { + if (res == 0 && capa.key_mgmt_iftype[WPA_IF_STATION] & + WPA_DRIVER_CAPA_KEY_MGMT_FT) { key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? "WPA-EAP WPA-EAP-SHA256 FT-EAP" : "WPA-EAP FT-EAP"; diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index b160fd0d4..b7680f088 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -188,6 +188,7 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s, const u8 *ie; struct wpa_ie_data adv; int wpa2 = 0, ccmp = 0; + enum wpa_driver_if_type iftype; /* * Many existing WPS APs do not know how to negotiate WPA2 or CCMP in @@ -239,9 +240,12 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s, return; } + iftype = ssid->p2p_group ? WPA_IF_P2P_CLIENT : WPA_IF_STATION; + if (ccmp && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && (ssid->pairwise_cipher & WPA_CIPHER_TKIP) && - (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { + (capa.key_mgmt_iftype[iftype] & + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { wpa_printf(MSG_DEBUG, "WPS: Add CCMP into the credential " "based on scan results"); if (wpa_s->conf->ap_scan == 1) From 44f786678470755c00ba95fd2842ca3f26a70e2d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 12 May 2020 17:21:08 +0300 Subject: [PATCH 0498/1105] Clean up GET_CAPABILITY handling of 'strict' argument There is no need to maintain a pointer to the substring "strict"; use a bool instead. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 4860e3480..1507c48d2 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -3981,7 +3981,7 @@ static const struct cipher_info ciphers_group_mgmt[] = { }; -static int ctrl_iface_get_capability_pairwise(int res, char *strict, +static int ctrl_iface_get_capability_pairwise(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4021,7 +4021,7 @@ static int ctrl_iface_get_capability_pairwise(int res, char *strict, } -static int ctrl_iface_get_capability_group(int res, char *strict, +static int ctrl_iface_get_capability_group(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4069,7 +4069,7 @@ static int ctrl_iface_get_capability_group(int res, char *strict, } -static int ctrl_iface_get_capability_group_mgmt(int res, char *strict, +static int ctrl_iface_get_capability_group_mgmt(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4134,7 +4134,7 @@ static int iftype_str_to_index(const char *iftype_str) } -static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, +static int ctrl_iface_get_capability_key_mgmt(int res, bool strict, struct wpa_driver_capa *capa, const char *iftype_str, char *buf, size_t buflen) @@ -4277,7 +4277,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } -static int ctrl_iface_get_capability_proto(int res, char *strict, +static int ctrl_iface_get_capability_proto(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4320,7 +4320,7 @@ static int ctrl_iface_get_capability_proto(int res, char *strict, static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, - int res, char *strict, + int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4398,7 +4398,7 @@ static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, } -static int ctrl_iface_get_capability_modes(int res, char *strict, +static int ctrl_iface_get_capability_modes(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4561,7 +4561,8 @@ static int wpa_supplicant_ctrl_iface_get_capability( { struct wpa_driver_capa capa; int res; - char *next_param, *curr_param, *iftype = NULL, *strict = NULL; + char *next_param, *curr_param, *iftype = NULL; + bool strict = false; char field[50]; size_t len; @@ -4580,7 +4581,7 @@ static int wpa_supplicant_ctrl_iface_get_capability( *next_param = '\0'; if (os_strcmp(curr_param, "strict") == 0) - strict = curr_param; + strict = true; else if (os_strncmp(curr_param, "iftype=", 7) == 0) iftype = curr_param + 7; else From dff67270b54b046a080e2d74f3b359b365ac35bc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 12 May 2020 17:33:26 +0300 Subject: [PATCH 0499/1105] tests: iftype parameter with GET_CAPABILITY key_mgmt Signed-off-by: Jouni Malinen --- tests/hwsim/test_wpas_ctrl.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py index cc3d5e98b..04418f093 100644 --- a/tests/hwsim/test_wpas_ctrl.py +++ b/tests/hwsim/test_wpas_ctrl.py @@ -987,6 +987,16 @@ def test_wpas_ctrl_get_capability(dev): if "WPA-PSK" not in res or "WPA-EAP" not in res: raise Exception("Unexpected GET_CAPABILITY key_mgmt response: " + str(res)) + res = dev[0].get_capability("key_mgmt iftype=STATION") + if "WPA-PSK" not in res or "WPA-EAP" not in res: + raise Exception("Unexpected GET_CAPABILITY key_mgmt iftype=STATION response: " + str(res)) + + iftypes = [ "STATION", "AP_VLAN", "AP", "P2P_GO", "P2P_CLIENT", + "P2P_DEVICE", "MESH", "IBSS", "NAN", "UNKNOWN" ] + for i in iftypes: + res = dev[0].get_capability("key_mgmt iftype=" + i) + logger.info("GET_CAPABILITY key_mgmt iftype=%s: %s" % (i, res)) + res = dev[0].get_capability("proto") if "WPA" not in res or "RSN" not in res: raise Exception("Unexpected GET_CAPABILITY proto response: " + str(res)) From 0f58c88fc395cfad67a0ff9c29dc99b6f9931622 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 12 May 2020 21:02:39 +0300 Subject: [PATCH 0500/1105] DPP2: Fix CONFIG_DPP2=y build with OpenSSL 1.0.2 This file needs the EVP_PKEY_get0_EC_KEY() compatibility wrapper just like other DPP source code files using this function. Fixes: 21c612017b0c ("DPP: Move configurator backup into a separate source code file") Signed-off-by: Jouni Malinen --- src/common/dpp_backup.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c index 4bd5ba616..c675c427b 100644 --- a/src/common/dpp_backup.c +++ b/src/common/dpp_backup.c @@ -7,6 +7,7 @@ */ #include "utils/includes.h" +#include #include #include "utils/common.h" @@ -18,6 +19,21 @@ #ifdef CONFIG_DPP2 +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +/* Compatibility wrappers for older versions. */ + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + +#endif + + void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key) { while (key) { From 99809c7a44e86918d08aa23d1666c99ccd22693a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 13 May 2020 17:09:52 +0300 Subject: [PATCH 0501/1105] nl80211: Disable offchannel-ok in AP mode only if beaconing When hostapd is started without beaconing (start_disabled=1), Public Action frame transmission command through nl80211 needs to allow offchannel operations regardless of the operating channel configuration. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 9c72341f9..0bedf0630 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -7755,7 +7755,8 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, struct ieee80211_hdr *hdr; int offchanok = 1; - if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq) + if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq && + bss->beacon_set) offchanok = 0; wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, " From 95471fc3e88fccdaaabc96227742a619d320c621 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 13 May 2020 17:36:40 +0300 Subject: [PATCH 0502/1105] Handle hostapd_for_each_interface() at the process termination Clean struct hapd_interfaces pointers and interface count during deinitialization at the end of theh ostapd process termination so that a call to hostapd_for_each_interface() after this does not end up dereferencing freed memory. Such cases do not exist before this commit, but can be added after this, e.g., for DPP needs. Signed-off-by: Jouni Malinen --- hostapd/main.c | 3 +++ src/ap/hostapd.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/hostapd/main.c b/hostapd/main.c index 6a69412d0..09261d6be 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -903,8 +903,11 @@ int main(int argc, char *argv[]) !!(interfaces.iface[i]->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); hostapd_interface_deinit_free(interfaces.iface[i]); + interfaces.iface[i] = NULL; } os_free(interfaces.iface); + interfaces.iface = NULL; + interfaces.count = 0; #ifdef CONFIG_DPP dpp_global_deinit(interfaces.dpp); diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 5515ab34d..79ad38c40 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -76,6 +76,8 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces, int ret; for (i = 0; i < interfaces->count; i++) { + if (!interfaces->iface[i]) + continue; ret = cb(interfaces->iface[i], ctx); if (ret) return ret; From 98e4b38403c8ae957359eaf98f065f463f50a683 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 13 May 2020 17:11:40 +0300 Subject: [PATCH 0503/1105] DPP2: Chirping in hostapd Enrollee Add a new hostapd control interface command "DPP_CHIRP own= iter=" to request chirping, i.e., sending of Presence Announcement frames, to be started. This follows the model of similar wpa_supplicant functionality from commit 562f77144cd2 ("DPP2: Chirping in wpa_supplicant Enrollee"). The hostapd case requires the AP to be started without beaconing, i.e., with start_disabled=1 in hostapd configuration, to allow iteration of channels needed for chirping. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 7 + hostapd/main.c | 4 + src/ap/dpp_hostapd.c | 322 +++++++++++++++++++++++++++++++++++++++++++ src/ap/dpp_hostapd.h | 6 + src/ap/hostapd.h | 10 ++ 5 files changed, 349 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 87f2cb17e..ed5100fbf 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -3708,6 +3708,13 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0) reply_len = -1; +#ifdef CONFIG_DPP2 + } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) { + if (hostapd_dpp_chirp(hapd, buf + 9) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { + hostapd_dpp_chirp_stop(hapd); +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #ifdef RADIUS_SERVER } else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) { diff --git a/hostapd/main.c b/hostapd/main.c index 09261d6be..353b20a80 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -674,7 +674,11 @@ int main(int argc, char *argv[]) #endif /* CONFIG_ETH_P_OUI */ #ifdef CONFIG_DPP os_memset(&dpp_conf, 0, sizeof(dpp_conf)); + dpp_conf.cb_ctx = &interfaces; /* TODO: dpp_conf.msg_ctx? */ +#ifdef CONFIG_DPP2 + dpp_conf.remove_bi = hostapd_dpp_remove_bi; +#endif /* CONFIG_DPP2 */ interfaces.dpp = dpp_global_init(&dpp_conf); if (!interfaces.dpp) return -1; diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 548e8856e..178fd126e 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -630,6 +630,10 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR, MAC2STR(src)); +#ifdef CONFIG_DPP2 + hostapd_dpp_chirp_stop(hapd); +#endif /* CONFIG_DPP2 */ + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, &r_bootstrap_len); if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { @@ -2139,6 +2143,7 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd) NULL); eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd, NULL); + hostapd_dpp_chirp_stop(hapd); #endif /* CONFIG_DPP2 */ dpp_auth_deinit(hapd->dpp_auth); hapd->dpp_auth = NULL; @@ -2147,3 +2152,320 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd) os_free(hapd->dpp_configurator_params); hapd->dpp_configurator_params = NULL; } + + +#ifdef CONFIG_DPP2 + +static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx); + +static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + + wpa_printf(MSG_DEBUG, "DPP: No chirp response received"); + hostapd_drv_send_action_cancel_wait(hapd); + hostapd_dpp_chirp_next(hapd, NULL); +} + + +static void hostapd_dpp_chirp_start(struct hostapd_data *hapd) +{ + struct wpabuf *msg; + int type; + + msg = hapd->dpp_presence_announcement; + type = DPP_PA_PRESENCE_ANNOUNCEMENT; + wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq); + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " freq=%u type=%d", + MAC2STR(broadcast), hapd->dpp_chirp_freq, type); + if (hostapd_drv_send_action( + hapd, hapd->dpp_chirp_freq, 2000, broadcast, + wpabuf_head(msg), wpabuf_len(msg)) < 0 || + eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout, + hapd, NULL) < 0) + hostapd_dpp_chirp_stop(hapd); +} + + +static struct hostapd_hw_modes * +dpp_get_mode(struct hostapd_data *hapd, + enum hostapd_hw_mode mode) +{ + struct hostapd_hw_modes *modes = hapd->iface->hw_features; + u16 num_modes = hapd->iface->num_hw_features; + u16 i; + + for (i = 0; i < num_modes; i++) { + if (modes[i].mode != mode || + !modes[i].num_channels || !modes[i].channels) + continue; + return &modes[i]; + } + + return NULL; +} + + +static void +hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + struct wpa_scan_results *scan_res; + struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi; + unsigned int i; + struct hostapd_hw_modes *mode; + int c; + + if (!bi) + return; + + hapd->dpp_chirp_scan_done = 1; + + scan_res = hostapd_driver_get_scan_results(hapd); + + os_free(hapd->dpp_chirp_freqs); + hapd->dpp_chirp_freqs = NULL; + + /* Channels from own bootstrapping info */ + if (bi) { + for (i = 0; i < bi->num_freq; i++) + int_array_add_unique(&hapd->dpp_chirp_freqs, + bi->freq[i]); + } + + /* Preferred chirping channels */ + int_array_add_unique(&hapd->dpp_chirp_freqs, 2437); + + mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A); + if (mode) { + int chan44 = 0, chan149 = 0; + + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if (chan->flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) + continue; + if (chan->freq == 5220) + chan44 = 1; + if (chan->freq == 5745) + chan149 = 1; + } + if (chan149) + int_array_add_unique(&hapd->dpp_chirp_freqs, 5745); + else if (chan44) + int_array_add_unique(&hapd->dpp_chirp_freqs, 5220); + } + + mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD); + if (mode) { + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if ((chan->flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) || + chan->freq != 60480) + continue; + int_array_add_unique(&hapd->dpp_chirp_freqs, 60480); + break; + } + } + + /* Add channels from scan results for APs that advertise Configurator + * Connectivity element */ + for (i = 0; scan_res && i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + size_t ie_len = bss->ie_len; + + if (!ie_len) + ie_len = bss->beacon_ie_len; + if (get_vendor_ie((const u8 *) (bss + 1), ie_len, + DPP_CC_IE_VENDOR_TYPE)) + int_array_add_unique(&hapd->dpp_chirp_freqs, + bss->freq); + } + + if (!hapd->dpp_chirp_freqs || + eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, + hapd, NULL) < 0) + hostapd_dpp_chirp_stop(hapd); + + wpa_scan_results_free(scan_res); +} + + +static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + int i; + + if (hapd->dpp_chirp_listen) + hostapd_dpp_listen_stop(hapd); + + if (hapd->dpp_chirp_freq == 0) { + if (hapd->dpp_chirp_round % 4 == 0 && + !hapd->dpp_chirp_scan_done) { + struct wpa_driver_scan_params params; + int ret; + + wpa_printf(MSG_DEBUG, + "DPP: Update channel list for chirping"); + os_memset(¶ms, 0, sizeof(params)); + ret = hostapd_driver_scan(hapd, ¶ms); + if (ret < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to request a scan ret=%d (%s)", + ret, strerror(-ret)); + hostapd_dpp_chirp_scan_res_handler(hapd->iface); + } else { + hapd->iface->scan_cb = + hostapd_dpp_chirp_scan_res_handler; + } + return; + } + hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0]; + hapd->dpp_chirp_round++; + wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d", + hapd->dpp_chirp_round); + } else { + for (i = 0; hapd->dpp_chirp_freqs[i]; i++) + if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq) + break; + if (!hapd->dpp_chirp_freqs[i]) { + wpa_printf(MSG_DEBUG, + "DPP: Previous chirp freq %d not found", + hapd->dpp_chirp_freq); + return; + } + i++; + if (hapd->dpp_chirp_freqs[i]) { + hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i]; + } else { + hapd->dpp_chirp_iter--; + if (hapd->dpp_chirp_iter <= 0) { + wpa_printf(MSG_DEBUG, + "DPP: Chirping iterations completed"); + hostapd_dpp_chirp_stop(hapd); + return; + } + hapd->dpp_chirp_freq = 0; + hapd->dpp_chirp_scan_done = 0; + if (eloop_register_timeout(30, 0, + hostapd_dpp_chirp_next, + hapd, NULL) < 0) { + hostapd_dpp_chirp_stop(hapd); + return; + } + if (hapd->dpp_chirp_listen) { + wpa_printf(MSG_DEBUG, + "DPP: Listen on %d MHz during chirp 30 second wait", + hapd->dpp_chirp_listen); + /* TODO: start listen on the channel */ + } else { + wpa_printf(MSG_DEBUG, + "DPP: Wait 30 seconds before starting the next chirping round"); + } + return; + } + } + + hostapd_dpp_chirp_start(hapd); +} + + +int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd) +{ + const char *pos; + int iter = 1, listen_freq = 0; + struct dpp_bootstrap_info *bi; + + pos = os_strstr(cmd, " own="); + if (!pos) + return -1; + pos += 5; + bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos)); + if (!bi) { + wpa_printf(MSG_DEBUG, + "DPP: Identified bootstrap info not found"); + return -1; + } + + pos = os_strstr(cmd, " iter="); + if (pos) { + iter = atoi(pos + 6); + if (iter <= 0) + return -1; + } + + pos = os_strstr(cmd, " listen="); + if (pos) { + listen_freq = atoi(pos + 8); + if (listen_freq <= 0) + return -1; + } + + hostapd_dpp_chirp_stop(hapd); + hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; + hapd->dpp_qr_mutual = 0; + hapd->dpp_chirp_bi = bi; + hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi); + if (!hapd->dpp_presence_announcement) + return -1; + hapd->dpp_chirp_iter = iter; + hapd->dpp_chirp_round = 0; + hapd->dpp_chirp_scan_done = 0; + hapd->dpp_chirp_listen = listen_freq; + + return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL); +} + + +void hostapd_dpp_chirp_stop(struct hostapd_data *hapd) +{ + if (hapd->dpp_presence_announcement) { + hostapd_drv_send_action_cancel_wait(hapd); + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED); + } + hapd->dpp_chirp_bi = NULL; + wpabuf_free(hapd->dpp_presence_announcement); + hapd->dpp_presence_announcement = NULL; + if (hapd->dpp_chirp_listen) + hostapd_dpp_listen_stop(hapd); + hapd->dpp_chirp_listen = 0; + hapd->dpp_chirp_freq = 0; + os_free(hapd->dpp_chirp_freqs); + hapd->dpp_chirp_freqs = NULL; + eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL); + eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL); + if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) { + /* TODO: abort ongoing scan */ + hapd->iface->scan_cb = NULL; + } +} + + +static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx) +{ + struct dpp_bootstrap_info *bi = ctx; + size_t i; + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *hapd = iface->bss[i]; + + if (bi == hapd->dpp_chirp_bi) + hostapd_dpp_chirp_stop(hapd); + } + + return 0; +} + + +void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi) +{ + struct hapd_interfaces *interfaces = ctx; + + hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi); +} + +#endif /* CONFIG_DPP2 */ diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h index b1fa99ed0..7e74185ca 100644 --- a/src/ap/dpp_hostapd.h +++ b/src/ap/dpp_hostapd.h @@ -10,6 +10,8 @@ #ifndef DPP_HOSTAPD_H #define DPP_HOSTAPD_H +struct dpp_bootstrap_info; + int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd); @@ -39,4 +41,8 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd); void hostapd_dpp_init_global(struct hapd_interfaces *ifaces); void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces); +int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd); +void hostapd_dpp_chirp_stop(struct hostapd_data *hapd); +void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi); + #endif /* DPP_HOSTAPD_H */ diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index fff15f118..597bbb432 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -386,6 +386,16 @@ struct hostapd_data { unsigned int dpp_resp_wait_time; unsigned int dpp_resp_max_tries; unsigned int dpp_resp_retry_time; +#ifdef CONFIG_DPP2 + struct wpabuf *dpp_presence_announcement; + struct dpp_bootstrap_info *dpp_chirp_bi; + int dpp_chirp_freq; + int *dpp_chirp_freqs; + int dpp_chirp_iter; + int dpp_chirp_round; + int dpp_chirp_scan_done; + int dpp_chirp_listen; +#endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS char *dpp_config_obj_override; char *dpp_discovery_override; From d5b596996e66ca06fb51e5b6f866465ebab81e18 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 13 May 2020 17:11:15 +0300 Subject: [PATCH 0504/1105] tests: DPP chirp by an AP Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index c228d5673..a15a8a689 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5290,6 +5290,27 @@ def test_dpp_chirp_configurator_inits(dev, apdev): dev[1].dpp_auth_init(uri=uri, conf="sta-dpp", configurator=conf_id) wait_auth_success(dev[0], dev[1], dev[1], dev[0]) +def test_dpp_chirp_ap(dev, apdev): + """DPP chirp by an AP""" + check_dpp_capab(dev[0], min_ver=2) + + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured", + "start_disabled": "1"}) + check_dpp_capab(hapd, min_ver=2) + + id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True) + uri = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h) + + conf_id = dev[0].dpp_configurator_add() + idc = dev[0].dpp_qr_code(uri) + dev[0].dpp_bootstrap_set(idc, conf="ap-dpp", configurator=conf_id) + dev[0].dpp_listen(2437) + if "OK" not in hapd.request("DPP_CHIRP own=%d iter=5" % id_h): + raise Exception("DPP_CHIRP failed") + wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd, + timeout=20) + update_hapd_config(hapd) + def start_dpp_pfs_ap(apdev, pfs): params = {"ssid": "dpp", "wpa": "2", From 47323a6f508bfe07eed30540a40c248ea92653a7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 13 May 2020 17:38:40 +0300 Subject: [PATCH 0505/1105] tests: sigma_dut DPP/QR AP as chirping Enrollee Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index b7f832c9e..10313c215 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -2208,6 +2208,46 @@ def test_sigma_dut_dpp_qr_configurator_chirp(dev, apdev): dev[0].set("dpp_config_processing", "0") stop_sigma_dut(sigma) +def test_sigma_dut_ap_dpp_qr_enrollee_chirp(dev, apdev, params): + """sigma_dut DPP/QR AP as chirping Enrollee""" + check_dpp_capab(dev[0], min_ver=2) + check_dpp_capab(dev[1]) + logdir = params['prefix'] + ".sigma-hostapd" + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default,program,DPP") + cmd = "dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPCryptoIdentifier,P-256,DPPBS,QR" + res = sigma_dut_cmd_check(cmd) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + hex = res.split(',')[3] + uri = from_hex(hex) + logger.info("URI from sigma_dut: " + uri) + + conf_id = dev[0].dpp_configurator_add(key=csign) + idc = dev[0].dpp_qr_code(uri) + dev[0].dpp_bootstrap_set(idc, conf="ap-dpp", configurator=conf_id, + ssid="DPPNET01") + dev[0].dpp_listen(2437) + + res = sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Responder,DPPAuthDirection,Single,DPPProvisioningRole,Enrollee,DPPBS,QR,DPPTimeout,16,DPPChirp,Enable", timeout=20) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: + raise Exception("Unexpected result: " + res) + + dev[1].set("dpp_config_processing", "2") + id = dev[1].dpp_bootstrap_gen(chan="81/6", mac=True) + uri = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id) + dev[1].dpp_listen(2437) + dev[0].dpp_auth_init(uri=uri, conf="sta-dpp", ssid="DPPNET01", + configurator=conf_id) + dev[1].wait_connected() + + sigma_dut_cmd_check("ap_reset_default,program,DPP") + finally: + dev[1].set("dpp_config_processing", "0", allow_fail=True) + stop_sigma_dut(sigma) + def test_sigma_dut_dpp_pkex_init_configurator(dev, apdev): """sigma_dut DPP/PKEX initiator as Configurator""" check_dpp_capab(dev[0]) From f85fb349fd7452b2a15feefd66b466d7714e6661 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 14 May 2020 21:29:25 +0300 Subject: [PATCH 0506/1105] dpp-nfc: More robust determination of the script directory Make it more robust to import wpaspy regardless of how dpp-nfc.py is being executed. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 173416794..e448315ba 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -18,7 +18,7 @@ import ndef import logging -scriptsdir = os.path.dirname(os.path.realpath("dpp-nfc.py")) +scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__)) sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy')) import wpaspy From 69dfbe6a9373c1b495d29eb015084a73eed0ded2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 14 May 2020 21:46:50 +0300 Subject: [PATCH 0507/1105] dpp-nfc: Use Configurator/Enrollee parameters with tag reading This was previously done only for the negotiated connection handover case, but the same parameters are useful for the tag reading cases (URI record and static handover). Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index e448315ba..86524ab17 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -80,8 +80,16 @@ def dpp_nfc_uri_process(uri): print("Could not parse DPP URI from NFC URI record") return False peer_id = int(peer_id) - print("peer_id=%d" % peer_id) + print("peer_id=%d for URI from NFC Tag: %s" % (peer_id, uri)) cmd = "DPP_AUTH_INIT peer=%d" % peer_id + global enrollee_only, configurator_only, config_params + if enrollee_only: + cmd += " role=enrollee" + elif configurator_only: + cmd += " role=configurator" + if config_params: + cmd += " " + config_params + print("Initiate DPP authentication: " + cmd) res = wpas.request(cmd) if "OK" not in res: print("Failed to initiate DPP Authentication") From 0b04d3c578dab207b6e284a98e2bdbe3ac5dce6b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 14 May 2020 21:52:09 +0300 Subject: [PATCH 0508/1105] dpp-nfc: Allow wpa_supplicant control interface directory to be set Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 86524ab17..cc32e4904 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -623,6 +623,8 @@ def main(): help='run as Configurator-only') parser.add_argument('--config-params', default='', help='configurator parameters') + parser.add_argument('--ctrl', default='/var/run/wpa_supplicant', + help='wpa_supplicant/hostapd control interface') parser.add_argument('--summary', help='summary file for writing status updates') parser.add_argument('--success', @@ -663,6 +665,10 @@ def main(): ifname = args.ifname print("Selected ifname " + ifname) + if args.ctrl: + global wpas_ctrl + wpas_ctrl = args.ctrl + if args.summary: global summary_file summary_file = args.summary From 8f96f2c3b122bf543188f82fd3ba54f35a3d71d2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 00:31:32 +0300 Subject: [PATCH 0509/1105] dpp-nfc: Be more graceful when wpa_supplicant is not available Do not try to proceed with negotiated connection handover if wpa_supplicant control interface is not available. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index cc32e4904..2f220f964 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -154,7 +154,10 @@ def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, if mac: if mac is True: mac = own_addr(wpas) - cmd += " mac=" + mac.replace(':', '') + if mac is None: + print("Could not determine local MAC address for bootstrap info") + else: + cmd += " mac=" + mac.replace(':', '') if info: cmd += " info=" + info if curve: @@ -197,6 +200,9 @@ def wpas_report_handover_sel(uri): def dpp_handover_client(llc): uri = wpas_get_nfc_uri(start_listen=False) + if uri is None: + print("Cannot start handover client - no bootstrap URI available") + return uri = ndef.UriRecord(uri) print("NFC URI record for DPP: " + str(uri)) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) From 24efcdf74dc8c7d46b1022350320bb40ead922e2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 00:44:27 +0300 Subject: [PATCH 0510/1105] dpp-nfc: Own MAC address fetching from hostapd Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 2f220f964..4f64bc250 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -144,7 +144,10 @@ def get_status_field(wpas, field, extra=None): return None def own_addr(wpas): - return get_status_field(wpas, "address") + addr = get_status_field(wpas, "address") + if addr is None: + addr = get_status_field(wpas, "bssid[0]") + return addr def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, curve=None, key=None): From 9ad3fe93431c184fc031d7b799ba155ef751aa1d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 01:21:01 +0300 Subject: [PATCH 0511/1105] dpp-nfc: Start handover server regardless of init-on-touch setting The previous version was trying to force the handover roles based on the --init-on-touch parameter on both sides. That is fine for some test scenarios, but not appropriate for more normal use cases. Change this design to enable handover server in all cases and only control starting of the handover client based on --init-on-touch. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 4f64bc250..86d4479b0 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -587,10 +587,8 @@ def llcp_connected(llc): print("P2P LLCP connected") global wait_connection wait_connection = False - global init_on_touch - if not init_on_touch: - global srv - srv.start() + global srv + srv.start() if init_on_touch or not no_input: threading.Thread(target=llcp_worker, args=(llc,)).start() return True From 1e0bc897ab4e79c3cdfadcfc3705ab1da4a97533 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 02:26:01 +0300 Subject: [PATCH 0512/1105] dpp-nfc: Collision detection for handover request Address possible handover request collisions for cases where both devices try to initiate handover simultaneously. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 50 +++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 86d4479b0..a002e08df 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -8,6 +8,7 @@ # See README for more details. import os +import struct import sys import time import threading @@ -33,6 +34,8 @@ continue_loop = True terminate_now = False summary_file = None success_file = None +my_crn = None +peer_crn = None def summary(txt): print(txt) @@ -209,11 +212,16 @@ def dpp_handover_client(llc): uri = ndef.UriRecord(uri) print("NFC URI record for DPP: " + str(uri)) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) - hr = ndef.HandoverRequestRecord(version="1.4", crn=os.urandom(2)) + crn = os.urandom(2) + hr = ndef.HandoverRequestRecord(version="1.4", crn=crn) hr.add_alternative_carrier('active', carrier.name) message = [hr, carrier] print("NFC Handover Request message for DPP: " + str(message)) + global peer_crn + if peer_crn is not None: + print("NFC handover request from peer was already received - do not send own") + return client = nfc.handover.HandoverClient(llc) try: summary("Trying to initiate NFC connection handover") @@ -228,6 +236,11 @@ def dpp_handover_client(llc): client.close() return + if peer_crn is not None: + print("NFC handover request from peer was already received - do not send own") + client.close() + return + summary("Sending handover request") if not client.send_records(message): @@ -235,6 +248,9 @@ def dpp_handover_client(llc): client.close() return + global my_crn + my_crn, = struct.unpack('>H', crn) + summary("Receiving handover response") message = client.recv_records(timeout=3.0) if message is None: @@ -335,7 +351,32 @@ class HandoverServer(nfc.handover.HandoverServer): clear_raw_mode() print("\nHandoverServer - request received: " + str(records)) - carrier = None + global my_crn, peer_crn + + for carrier in records: + if not isinstance(carrier, ndef.HandoverRequestRecord): + continue + if carrier.collision_resolution_number: + peer_crn = carrier.collision_resolution_number + print("peer_crn:", peer_crn) + + if my_crn is not None: + print("my_crn:", my_crn) + + if my_crn is not None and peer_crn is not None: + if my_crn == peer_crn: + print("Same crn used - automatic collision resolution failed") + # TODO: Should generate a new Handover Request message + return '' + if ((my_crn & 1) == (peer_crn & 1) and my_crn > peer_crn) or \ + ((my_crn & 1) != (peer_crn & 1) and my_crn < peer_crn): + print("I'm the Handover Selector Device") + pass + else: + print("Peer is the Handover Selector device") + print("Ignore the received request.") + return '' + hs = ndef.HandoverSelectRecord('1.4') sel = [hs] @@ -362,7 +403,6 @@ class HandoverServer(nfc.handover.HandoverServer): continue found = True - self.received_carrier = carrier wpas = wpas_connect() if wpas is None: @@ -585,8 +625,10 @@ def llcp_startup(llc): def llcp_connected(llc): print("P2P LLCP connected") - global wait_connection + global wait_connection, my_crn, peer_crn wait_connection = False + my_crn = None + peer_crn = None global srv srv.start() if init_on_touch or not no_input: From 8791e7461c71752d56e9eed9c312ec1497ced0e4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 12:03:53 +0300 Subject: [PATCH 0513/1105] dpp-nfc: Write debug info to summary log Convert most print() calls to use the summary() helper so that the printed information gets written into a log file as well. In addition, start using a mutex lock to synchronize debug prints between threads to avoid merging of messages from different contexts. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 206 +++++++++++++++-------------- 1 file changed, 110 insertions(+), 96 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index a002e08df..b82713832 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -36,12 +36,14 @@ summary_file = None success_file = None my_crn = None peer_crn = None +mutex = threading.Lock() def summary(txt): - print(txt) - if summary_file: - with open(summary_file, 'a') as f: - f.write(txt + "\n") + with mutex: + print(txt) + if summary_file: + with open(summary_file, 'a') as f: + f.write(txt + "\n") def success_report(txt): summary(txt) @@ -55,11 +57,11 @@ def wpas_connect(): try: ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)] except OSError as error: - print("Could not find wpa_supplicant: ", error) + summary("Could not find wpa_supplicant: %s", str(error)) return None if len(ifaces) < 1: - print("No wpa_supplicant control interface found") + summary("No wpa_supplicant control interface found") return None for ctrl in ifaces: @@ -67,7 +69,7 @@ def wpas_connect(): if ifname not in ctrl: continue try: - print("Trying to use control interface " + ctrl) + summary("Trying to use control interface " + ctrl) wpas = wpaspy.Ctrl(ctrl) return wpas except Exception as e: @@ -80,10 +82,10 @@ def dpp_nfc_uri_process(uri): return False peer_id = wpas.request("DPP_NFC_URI " + uri) if "FAIL" in peer_id: - print("Could not parse DPP URI from NFC URI record") + summary("Could not parse DPP URI from NFC URI record") return False peer_id = int(peer_id) - print("peer_id=%d for URI from NFC Tag: %s" % (peer_id, uri)) + summary("peer_id=%d for URI from NFC Tag: %s" % (peer_id, uri)) cmd = "DPP_AUTH_INIT peer=%d" % peer_id global enrollee_only, configurator_only, config_params if enrollee_only: @@ -92,34 +94,34 @@ def dpp_nfc_uri_process(uri): cmd += " role=configurator" if config_params: cmd += " " + config_params - print("Initiate DPP authentication: " + cmd) + summary("Initiate DPP authentication: " + cmd) res = wpas.request(cmd) if "OK" not in res: - print("Failed to initiate DPP Authentication") + summary("Failed to initiate DPP Authentication") return False - print("DPP Authentication initiated") + summary("DPP Authentication initiated") return True def dpp_hs_tag_read(record): wpas = wpas_connect() if wpas is None: return False - print(record) + summary(record) if len(record.data) < 5: - print("Too short DPP HS") + summary("Too short DPP HS") return False if record.data[0] != 0: - print("Unexpected URI Identifier Code") + summary("Unexpected URI Identifier Code") return False uribuf = record.data[1:] try: uri = uribuf.decode() except: - print("Invalid URI payload") + summary("Invalid URI payload") return False - print("URI: " + uri) + summary("URI: " + uri) if not uri.startswith("DPP:"): - print("Not a DPP URI") + summary("Not a DPP URI") return False return dpp_nfc_uri_process(uri) @@ -161,7 +163,7 @@ def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, if mac is True: mac = own_addr(wpas) if mac is None: - print("Could not determine local MAC address for bootstrap info") + summary("Could not determine local MAC address for bootstrap info") else: cmd += " mac=" + mac.replace(':', '') if info: @@ -207,20 +209,20 @@ def wpas_report_handover_sel(uri): def dpp_handover_client(llc): uri = wpas_get_nfc_uri(start_listen=False) if uri is None: - print("Cannot start handover client - no bootstrap URI available") + summary("Cannot start handover client - no bootstrap URI available") return uri = ndef.UriRecord(uri) - print("NFC URI record for DPP: " + str(uri)) + summary("NFC URI record for DPP: " + str(uri)) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) crn = os.urandom(2) hr = ndef.HandoverRequestRecord(version="1.4", crn=crn) hr.add_alternative_carrier('active', carrier.name) message = [hr, carrier] - print("NFC Handover Request message for DPP: " + str(message)) + summary("NFC Handover Request message for DPP: " + str(message)) global peer_crn if peer_crn is not None: - print("NFC handover request from peer was already received - do not send own") + summary("NFC handover request from peer was already received - do not send own") return client = nfc.handover.HandoverClient(llc) try: @@ -237,7 +239,7 @@ def dpp_handover_client(llc): return if peer_crn is not None: - print("NFC handover request from peer was already received - do not send own") + summary("NFC handover request from peer was already received - do not send own") client.close() return @@ -257,36 +259,36 @@ def dpp_handover_client(llc): summary("No response received") client.close() return - print("Received message: " + str(message)) + summary("Received message: " + str(message)) if len(message) < 1 or \ not isinstance(message[0], ndef.HandoverSelectRecord): summary("Response was not Hs - received: " + message.type) client.close() return - print("Received message") - print("alternative carriers: " + str(message[0].alternative_carriers)) + summary("Received handover select message") + summary("alternative carriers: " + str(message[0].alternative_carriers)) dpp_found = False for carrier in message: if isinstance(carrier, ndef.HandoverSelectRecord): continue - print("Remote carrier type: " + carrier.type) + summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": if len(carrier.data) == 0 or carrier.data[0] != 0: - print("URI Identifier Code 'None' not seen") + summary("URI Identifier Code 'None' not seen") continue - print("DPP carrier type match - send to wpa_supplicant") + summary("DPP carrier type match - send to wpa_supplicant") dpp_found = True uri = carrier.data[1:].decode("utf-8") - print("DPP URI: " + uri) + summary("DPP URI: " + uri) res = wpas_report_handover_sel(uri) if res is None or "FAIL" in res: summary("DPP handover report rejected") break success_report("DPP handover reported successfully (initiator)") - print("peer_id=" + res) + summary("peer_id=" + res) peer_id = int(res) wpas = wpas_connect() if wpas is None: @@ -302,28 +304,28 @@ def dpp_handover_client(llc): # TODO: Single Configurator instance res = wpas.request("DPP_CONFIGURATOR_ADD") if "FAIL" in res: - print("Failed to initiate Configurator") + summary("Failed to initiate Configurator") break conf_id = int(res) extra = " conf=sta-dpp configurator=%d" % conf_id global own_id - print("Initiate DPP authentication") + summary("Initiate DPP authentication") cmd = "DPP_AUTH_INIT peer=%d own=%d" % (peer_id, own_id) cmd += extra res = wpas.request(cmd) if "FAIL" in res: - print("Failed to initiate DPP authentication") + summary("Failed to initiate DPP authentication") break if not dpp_found: - print("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") + summary("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") client.close() - print("Returning from dpp_handover_client") + summary("Returning from dpp_handover_client") return - print("Remove peer") + summary("Remove peer") client.close() - print("Done with handover") + summary("Done with handover") global only_one if only_one: print("only_one -> stop loop") @@ -336,7 +338,7 @@ def dpp_handover_client(llc): global terminate_now terminate_now = True - print("Returning from dpp_handover_client") + summary("Returning from dpp_handover_client") class HandoverServer(nfc.handover.HandoverServer): def __init__(self, llc): @@ -348,8 +350,12 @@ class HandoverServer(nfc.handover.HandoverServer): def process_handover_request_message(self, records): self.ho_server_processing = True + global in_raw_mode + was_in_raw_mode = in_raw_mode clear_raw_mode() - print("\nHandoverServer - request received: " + str(records)) + if was_in_raw_mode: + print("\n") + summary("HandoverServer - request received: " + str(records)) global my_crn, peer_crn @@ -358,23 +364,23 @@ class HandoverServer(nfc.handover.HandoverServer): continue if carrier.collision_resolution_number: peer_crn = carrier.collision_resolution_number - print("peer_crn:", peer_crn) + summary("peer_crn: %d" % peer_crn) if my_crn is not None: - print("my_crn:", my_crn) + summary("my_crn: %d" % my_crn) if my_crn is not None and peer_crn is not None: if my_crn == peer_crn: - print("Same crn used - automatic collision resolution failed") + summary("Same crn used - automatic collision resolution failed") # TODO: Should generate a new Handover Request message return '' if ((my_crn & 1) == (peer_crn & 1) and my_crn > peer_crn) or \ ((my_crn & 1) != (peer_crn & 1) and my_crn < peer_crn): - print("I'm the Handover Selector Device") + summary("I'm the Handover Selector Device") pass else: - print("Peer is the Handover Selector device") - print("Ignore the received request.") + summary("Peer is the Handover Selector device") + summary("Ignore the received request.") return '' hs = ndef.HandoverSelectRecord('1.4') @@ -385,21 +391,21 @@ class HandoverServer(nfc.handover.HandoverServer): for carrier in records: if isinstance(carrier, ndef.HandoverRequestRecord): continue - print("Remote carrier type: " + carrier.type) + summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": - print("DPP carrier type match - add DPP carrier record") + summary("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: - print("URI Identifier Code 'None' not seen") + summary("URI Identifier Code 'None' not seen") continue uri = carrier.data[1:].decode("utf-8") - print("Received DPP URI: " + uri) + summary("Received DPP URI: " + uri) data = wpas_get_nfc_uri(start_listen=False) - print("Own URI (pre-processing): %s" % data) + summary("Own URI (pre-processing): %s" % data) res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: - print("DPP handover request processing failed") + summary("DPP handover request processing failed") continue found = True @@ -411,9 +417,9 @@ class HandoverServer(nfc.handover.HandoverServer): data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in data: continue - print("Own URI (post-processing): %s" % data) + summary("Own URI (post-processing): %s" % data) uri = ndef.UriRecord(data) - print("Own bootstrapping NFC URI record: " + str(uri)) + summary("Own bootstrapping NFC URI record: " + str(uri)) info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) freq = None @@ -421,7 +427,7 @@ class HandoverServer(nfc.handover.HandoverServer): if line.startswith("use_freq="): freq = int(line.split('=')[1]) if freq is None: - print("No channel negotiated over NFC - use channel 1") + summary("No channel negotiated over NFC - use channel 1") freq = 2412 cmd = "DPP_LISTEN %d" % freq global enrollee_only @@ -432,11 +438,11 @@ class HandoverServer(nfc.handover.HandoverServer): cmd += " role=configurator" res = wpas.request(cmd) if "OK" not in res: - print("Failed to start DPP listen") + summary("Failed to start DPP listen") break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) - print("Own DPP carrier record: " + str(carrier)) + summary("Own DPP carrier record: " + str(carrier)) hs.add_alternative_carrier('active', carrier.name) sel = [hs, carrier] break @@ -477,22 +483,22 @@ def getch(): def dpp_tag_read(tag): success = False for record in tag.ndef.records: - print(record) - print("record type " + record.type) + summary(record) + summary("record type " + record.type) if record.type == "application/vnd.wfa.dpp": summary("DPP HS tag - send to wpa_supplicant") success = dpp_hs_tag_read(record) break if isinstance(record, ndef.UriRecord): - print("URI record: uri=" + record.uri) - print("URI record: iri=" + record.iri) + summary("URI record: uri=" + record.uri) + summary("URI record: iri=" + record.iri) if record.iri.startswith("DPP:"): - print("DPP URI") + summary("DPP URI") if not dpp_nfc_uri_process(record.iri): break success = True else: - print("Ignore unknown URI") + summary("Ignore unknown URI") break if success: @@ -503,15 +509,15 @@ def dpp_tag_read(tag): def rdwr_connected_write_tag(tag): summary("Tag found - writing - " + str(tag)) if not tag.ndef.is_writeable: - print("Not a writable tag") + summary("Not a writable tag") return global dpp_tag_data if tag.ndef.capacity < len(dpp_tag_data): - print("Not enough room for the message") + summary("Not enough room for the message") return tag.ndef.records = dpp_tag_data success_report("Tag write succeeded") - print("Done - remove tag") + summary("Done - remove tag") global only_one if only_one: global continue_loop @@ -520,7 +526,7 @@ def rdwr_connected_write_tag(tag): return dpp_sel_wait_remove def write_nfc_uri(clf, wait_remove=True): - print("Write NFC URI record") + summary("Write NFC URI record") data = wpas_get_nfc_uri() if data is None: summary("Could not get NFC URI from wpa_supplicant") @@ -528,17 +534,17 @@ def write_nfc_uri(clf, wait_remove=True): global dpp_sel_wait_remove dpp_sel_wait_remove = wait_remove - print("URI: %s" % data) + summary("URI: %s" % data) uri = ndef.UriRecord(data) - print(uri) + summary(uri) - print("Touch an NFC tag") + summary("Touch an NFC tag") global dpp_tag_data dpp_tag_data = [uri] clf.connect(rdwr={'on-connect': rdwr_connected_write_tag}) def write_nfc_hs(clf, wait_remove=True): - print("Write NFC Handover Select record on a tag") + summary("Write NFC Handover Select record on a tag") data = wpas_get_nfc_uri() if data is None: summary("Could not get NFC URI from wpa_supplicant") @@ -546,19 +552,19 @@ def write_nfc_hs(clf, wait_remove=True): global dpp_sel_wait_remove dpp_sel_wait_remove = wait_remove - print("URI: %s" % data) + summary("URI: %s" % data) uri = ndef.UriRecord(data) - print(uri) + summary(uri) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) hs = ndef.HandoverSelectRecord('1.4') hs.add_alternative_carrier('active', carrier.name) - print(hs) - print(carrier) + summary(hs) + summary(carrier) - print("Touch an NFC tag") + summary("Touch an NFC tag") global dpp_tag_data dpp_tag_data = [hs, carrier] - print(dpp_tag_data) + summary(dpp_tag_data) clf.connect(rdwr={'on-connect': rdwr_connected_write_tag}) def rdwr_connected(tag): @@ -566,8 +572,8 @@ def rdwr_connected(tag): summary("Tag connected: " + str(tag)) if tag.ndef: - print("NDEF tag: " + tag.type) - print(tag.ndef.records) + summary("NDEF tag: " + tag.type) + summary(tag.ndef.records) success = dpp_tag_read(tag) if only_one and success: global continue_loop @@ -581,14 +587,14 @@ def rdwr_connected(tag): def llcp_worker(llc): global init_on_touch if init_on_touch: - print("Starting handover client") + summary("Starting handover client") dpp_handover_client(llc) - print("Exiting llcp_worker thread (init_in_touch)") + summary("Exiting llcp_worker thread (init_in_touch)") return global no_input if no_input: - print("Wait for handover to complete") + summary("Wait for handover to complete") else: print("Wait for handover to complete - press 'i' to initiate") global srv @@ -596,9 +602,9 @@ def llcp_worker(llc): while not wait_connection and srv.sent_carrier is None: if srv.try_own: srv.try_own = False - print("Try to initiate another handover with own parameters") + summary("Try to initiate another handover with own parameters") dpp_handover_client(llc) - print("Exiting llcp_worker thread (retry with own parameters)") + summary("Exiting llcp_worker thread (retry with own parameters)") return if srv.ho_server_processing: time.sleep(0.025) @@ -609,22 +615,26 @@ def llcp_worker(llc): if res != 'i': continue clear_raw_mode() - print("Starting handover client") + summary("Starting handover client") dpp_handover_client(llc) - print("Exiting llcp_worker thread (manual init)") + summary("Exiting llcp_worker thread (manual init)") return + global in_raw_mode + was_in_raw_mode = in_raw_mode clear_raw_mode() - print("\rExiting llcp_worker thread") + if was_in_raw_mode: + print("\r") + summary("Exiting llcp_worker thread") def llcp_startup(llc): - print("Start LLCP server") + summary("Start LLCP server") global srv srv = HandoverServer(llc) return llc def llcp_connected(llc): - print("P2P LLCP connected") + summary("P2P LLCP connected") global wait_connection, my_crn, peer_crn wait_connection = False my_crn = None @@ -636,7 +646,7 @@ def llcp_connected(llc): return True def llcp_release(llc): - print("LLCP release") + summary("LLCP release") return True def terminate_loop(): @@ -684,7 +694,7 @@ def main(): 'write-nfc-hs'], nargs='?') args = parser.parse_args() - print(args) + summary(args) global only_one only_one = args.only_one @@ -712,7 +722,7 @@ def main(): if args.ifname: global ifname ifname = args.ifname - print("Selected ifname " + ifname) + summary("Selected ifname " + ifname) if args.ctrl: global wpas_ctrl @@ -735,7 +745,7 @@ def main(): try: if not clf.open(args.device): - print("Could not open connection with an NFC device") + summary("Could not open connection with an NFC device") raise SystemExit if args.command == "write-nfc-uri": @@ -748,8 +758,12 @@ def main(): global continue_loop while continue_loop: + global in_raw_mode + was_in_raw_mode = in_raw_mode clear_raw_mode() - print("\rWaiting for a tag or peer to be touched") + if was_in_raw_mode: + print("\r") + summary("Waiting for a tag or peer to be touched") wait_connection = True try: if args.tag_read_only: @@ -769,7 +783,7 @@ def main(): terminate=terminate_loop): break except Exception as e: - print("clf.connect failed: " + str(e)) + summary("clf.connect failed: " + str(e)) break global srv From d0e2d8091f5c254e0c5d44d9c25f6491cd98434d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 12:10:59 +0300 Subject: [PATCH 0514/1105] dpp-nfc: Make handover request collision detection more robust Wait up to 100 ms for own handover request transmission to succeed if peer handover request is received, but own crn is not yet available. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index b82713832..d9ae7475a 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -34,6 +34,7 @@ continue_loop = True terminate_now = False summary_file = None success_file = None +my_crn_ready = False my_crn = None peer_crn = None mutex = threading.Lock() @@ -245,12 +246,15 @@ def dpp_handover_client(llc): summary("Sending handover request") + global my_crn, my_crn_ready + my_crn_ready = True + if not client.send_records(message): + my_crn_ready = False summary("Failed to send handover request") client.close() return - global my_crn my_crn, = struct.unpack('>H', crn) summary("Receiving handover response") @@ -357,7 +361,7 @@ class HandoverServer(nfc.handover.HandoverServer): print("\n") summary("HandoverServer - request received: " + str(records)) - global my_crn, peer_crn + global my_crn, peer_crn, my_crn_ready for carrier in records: if not isinstance(carrier, ndef.HandoverRequestRecord): @@ -366,6 +370,12 @@ class HandoverServer(nfc.handover.HandoverServer): peer_crn = carrier.collision_resolution_number summary("peer_crn: %d" % peer_crn) + if my_crn is None and my_crn_ready: + summary("Still trying to send own handover request - wait a moment to see if that succeeds before checking crn values") + for i in range(10): + if my_crn is not None: + break + time.sleep(0.01) if my_crn is not None: summary("my_crn: %d" % my_crn) @@ -635,8 +645,9 @@ def llcp_startup(llc): def llcp_connected(llc): summary("P2P LLCP connected") - global wait_connection, my_crn, peer_crn + global wait_connection, my_crn, peer_crn, my_crn_ready wait_connection = False + my_crn_ready = False my_crn = None peer_crn = None global srv From 5d49c1bf7c4e8fee574e11b70e21b15f06b956b5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 14:17:40 +0300 Subject: [PATCH 0515/1105] dpp-nfc: Do not indicate a single channel 1 by default Allow any channel to be used by not including a specific single channel in the handover request without a need (for AP mode, use the current operating channel). When sending out the handover select, pick a single channel if no specific channel has been negotiated. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index d9ae7475a..1dbf47ad7 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -178,12 +178,23 @@ def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, raise Exception("Failed to generate bootstrapping info") return int(res) -def wpas_get_nfc_uri(start_listen=True): +def wpas_get_nfc_uri(start_listen=True, pick_channel=False): wpas = wpas_connect() if wpas is None: return None global own_id, chanlist - own_id = dpp_bootstrap_gen(wpas, type="nfc-uri", chan=chanlist, mac=True) + chan = chanlist + if chan is None and get_status_field(wpas, "bssid[0]"): + freq = get_status_field(wpas, "freq") + if freq: + freq = int(freq) + if freq >= 2412 and freq <= 2462: + chan = "81/%d" % ((freq - 2407) / 5) + summary("Use current AP operating channel (%d MHz) as the URI channel list (%s)" % (freq, chan)) + if chan is None and pick_channel: + chan = "81/6" + summary("Use channel 2437 MHz since no other preference provided") + own_id = dpp_bootstrap_gen(wpas, type="nfc-uri", chan=chan, mac=True) res = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in res: return None @@ -410,7 +421,7 @@ class HandoverServer(nfc.handover.HandoverServer): uri = carrier.data[1:].decode("utf-8") summary("Received DPP URI: " + uri) - data = wpas_get_nfc_uri(start_listen=False) + data = wpas_get_nfc_uri(start_listen=False, pick_channel=True) summary("Own URI (pre-processing): %s" % data) res = wpas_report_handover_req(uri) @@ -436,9 +447,13 @@ class HandoverServer(nfc.handover.HandoverServer): for line in info.splitlines(): if line.startswith("use_freq="): freq = int(line.split('=')[1]) - if freq is None: - summary("No channel negotiated over NFC - use channel 1") - freq = 2412 + if freq is None or freq == 0: + summary("No channel negotiated over NFC - use channel 6") + freq = 2437 + else: + summary("Negotiated channel: %d MHz" % freq) + if get_status_field(wpas, "bssid[0]"): + summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) cmd = "DPP_LISTEN %d" % freq global enrollee_only global configurator_only @@ -700,7 +715,7 @@ def main(): parser.add_argument('--success', help='success file for writing success update') parser.add_argument('--device', default='usb', help='NFC device to open') - parser.add_argument('--chan', default='81/1', help='channel list') + parser.add_argument('--chan', default=None, help='channel list') parser.add_argument('command', choices=['write-nfc-uri', 'write-nfc-hs'], nargs='?') From 134ad50b0e4c2db4e2880c6e76810fb66bfc7a08 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 14:20:26 +0300 Subject: [PATCH 0516/1105] dpp-nfc: Clean up debug prints when handover select is received If the local device becomes the handover selector, make the debug log entries about client functionality not receiving the response clearer since that is not really an error case. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 1dbf47ad7..abda8216c 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -37,6 +37,7 @@ success_file = None my_crn_ready = False my_crn = None peer_crn = None +hs_sent = False mutex = threading.Lock() def summary(txt): @@ -257,7 +258,7 @@ def dpp_handover_client(llc): summary("Sending handover request") - global my_crn, my_crn_ready + global my_crn, my_crn_ready, hs_sent my_crn_ready = True if not client.send_records(message): @@ -269,9 +270,20 @@ def dpp_handover_client(llc): my_crn, = struct.unpack('>H', crn) summary("Receiving handover response") - message = client.recv_records(timeout=3.0) + try: + message = client.recv_records(timeout=3.0) + except Exception as e: + # This is fine if we are the handover selector + if hs_sent: + summary("Client receive failed as expected since I'm the handover server: %s" % str(e)) + else: + summary("Client receive failed: %s" % str(e)) + message = None if message is None: - summary("No response received") + if hs_sent: + summary("No response received as expected since I'm the handover server") + else: + summary("No response received") client.close() return summary("Received message: " + str(message)) @@ -461,6 +473,7 @@ class HandoverServer(nfc.handover.HandoverServer): cmd += " role=enrollee" elif configurator_only: cmd += " role=configurator" + summary(cmd) res = wpas.request(cmd) if "OK" not in res: summary("Failed to start DPP listen") @@ -477,6 +490,8 @@ class HandoverServer(nfc.handover.HandoverServer): self.success = True else: self.try_own = True + global hs_sent + hs_sent = True return sel def clear_raw_mode(): @@ -660,11 +675,12 @@ def llcp_startup(llc): def llcp_connected(llc): summary("P2P LLCP connected") - global wait_connection, my_crn, peer_crn, my_crn_ready + global wait_connection, my_crn, peer_crn, my_crn_ready, hs_sent wait_connection = False my_crn_ready = False my_crn = None peer_crn = None + hs_sent = False global srv srv.start() if init_on_touch or not no_input: From 7adea21d2ff876d37b459705a8a1b55109123e80 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 14:46:41 +0300 Subject: [PATCH 0517/1105] dpp-nfc: Enable hostapd beaconing for listen state This is needed to be able to receive Public Action frames when hostapd was initially started with start_disabled=1. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index abda8216c..188354553 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -139,7 +139,7 @@ def get_status(wpas, extra=None): try: [name, value] = l.split('=', 1) except ValueError: - logger.info("Ignore unexpected status line: " + l) + summary("Ignore unexpected status line: %s" % l) continue vals[name] = value return vals @@ -466,6 +466,11 @@ class HandoverServer(nfc.handover.HandoverServer): summary("Negotiated channel: %d MHz" % freq) if get_status_field(wpas, "bssid[0]"): summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) + if get_status_field(wpas, "beacon_set", extra="DRIVER") is None: + summary("Enable beaconing to have radio ready for RX") + wpas.request("DISABLE") + wpas.request("SET start_disabled 0") + wpas.request("ENABLE") cmd = "DPP_LISTEN %d" % freq global enrollee_only global configurator_only From 04030e8c0dcef6c2423eee1419e13e0ba738c4bb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 15 May 2020 21:23:50 +0300 Subject: [PATCH 0518/1105] nl80211: Remove AP mode interface from bridge for STA-mode-scan Linux bridging code does not allow a station mode WLAN interface in a bridge and this prevents the AP mode scan workaround from working if the AP interface is in a bridge and scanning can be only done by moving to STA mode. Extend this workaround to remove the interface from the bridge temporarily for the duration of the scan, i.e., for the same duration as the interface needs to be moved into the station. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 37 ++++++++++++++++++++++++++++++ src/drivers/driver_nl80211.h | 2 ++ src/drivers/driver_nl80211_event.c | 7 ++---- src/drivers/driver_nl80211_scan.c | 7 ++---- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 0bedf0630..bb0768c1c 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -6274,6 +6274,20 @@ static int wpa_driver_nl80211_set_mode_impl( } } + if (i == 0 && was_ap && !is_ap_interface(nlmode) && + bss->brname[0] && + (bss->added_if_into_bridge || bss->already_in_bridge)) { + wpa_printf(MSG_DEBUG, + "nl80211: Remove AP interface %s temporarily from the bridge %s to allow its mode to be set to STATION", + bss->ifname, bss->brname); + if (linux_br_del_if(drv->global->ioctl_sock, + bss->brname, bss->ifname) < 0) + wpa_printf(MSG_INFO, + "nl80211: Failed to remove interface %s from bridge %s: %s", + bss->ifname, bss->brname, + strerror(errno)); + } + /* Try to set the mode again while the interface is down */ mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode); if (mode_switch_res == -EBUSY) { @@ -6346,6 +6360,29 @@ done: } +void nl80211_restore_ap_mode(struct i802_bss *bss) +{ + struct wpa_driver_nl80211_data *drv = bss->drv; + int was_ap = is_ap_interface(drv->nlmode); + + wpa_driver_nl80211_set_mode(bss, drv->ap_scan_as_station); + if (!was_ap && is_ap_interface(drv->ap_scan_as_station) && + bss->brname[0] && + (bss->added_if_into_bridge || bss->already_in_bridge)) { + wpa_printf(MSG_DEBUG, + "nl80211: Add AP interface %s back into the bridge %s", + bss->ifname, bss->brname); + if (linux_br_add_if(drv->global->ioctl_sock, bss->brname, + bss->ifname) < 0) { + wpa_printf(MSG_WARNING, + "nl80211: Failed to add interface %s into bridge %s: %s", + bss->ifname, bss->brname, strerror(errno)); + } + } + drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; +} + + int wpa_driver_nl80211_set_mode(struct i802_bss *bss, enum nl80211_iftype nlmode) { diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 660f49879..895f9d72e 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -275,6 +275,8 @@ int process_bss_event(struct nl_msg *msg, void *arg); const char * nl80211_iftype_str(enum nl80211_iftype mode); +void nl80211_restore_ap_mode(struct i802_bss *bss); + #ifdef ANDROID int android_nl_socket_set_nonblocking(struct nl_sock *handle); int android_pno_start(struct i802_bss *bss, diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 1152312a8..6a2de1f3c 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -2581,11 +2581,8 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED && (cmd == NL80211_CMD_NEW_SCAN_RESULTS || - cmd == NL80211_CMD_SCAN_ABORTED)) { - wpa_driver_nl80211_set_mode(drv->first_bss, - drv->ap_scan_as_station); - drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; - } + cmd == NL80211_CMD_SCAN_ABORTED)) + nl80211_restore_ap_mode(bss); switch (cmd) { case NL80211_CMD_TRIGGER_SCAN: diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index 17e8b2c2e..dc91a2901 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -166,11 +166,8 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan"); - if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) { - wpa_driver_nl80211_set_mode(drv->first_bss, - drv->ap_scan_as_station); - drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; - } + if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) + nl80211_restore_ap_mode(drv->first_bss); wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results"); wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); From 094c8a6218d0fe8b178a5ad24c1a0e7b46fdbf43 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 11:28:03 +0300 Subject: [PATCH 0519/1105] Remove unnecessary key clearing at AP start with nl80211 cfg80211 takes care of key removal when link/association is lost, so there is no need to explicitly clear old keys when starting AP. Signed-off-by: Jouni Malinen --- src/ap/ap_drv_ops.c | 6 ++++++ src/ap/ap_drv_ops.h | 1 + src/ap/hostapd.c | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 1f284f0f3..904236bae 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -650,6 +650,12 @@ int hostapd_drv_none(struct hostapd_data *hapd) } +bool hostapd_drv_nl80211(struct hostapd_data *hapd) +{ + return hapd->driver && os_strcmp(hapd->driver->name, "nl80211") == 0; +} + + int hostapd_driver_scan(struct hostapd_data *hapd, struct wpa_driver_scan_params *params) { diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 56d1ad862..811d26a2c 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -80,6 +80,7 @@ hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, u16 *flags, u8 *dfs_domain); int hostapd_driver_commit(struct hostapd_data *hapd); int hostapd_drv_none(struct hostapd_data *hapd); +bool hostapd_drv_nl80211(struct hostapd_data *hapd); int hostapd_driver_scan(struct hostapd_data *hapd, struct wpa_driver_scan_params *params); struct wpa_scan_results * hostapd_driver_get_scan_results( diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 79ad38c40..0f5a37f09 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1182,7 +1182,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) hostapd_set_privacy(hapd, 0); #ifdef CONFIG_WEP - hostapd_broadcast_wep_clear(hapd); + if (!hostapd_drv_nl80211(hapd)) + hostapd_broadcast_wep_clear(hapd); if (hostapd_setup_encryption(conf->iface, hapd)) return -1; #endif /* CONFIG_WEP */ From c82535edd6bea8a34b711d1f1015ea750b5db9da Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 11:38:09 +0300 Subject: [PATCH 0520/1105] Move deauthentication at AP start to be after beacon configuration This allows nl80211-based drivers to get the frame out. The old earlier location resulted in the driver operation getting rejected before the kernel was not ready to transmit the frame in the BSS context of the AP interface that has not yet been started. While getting this broadcast Deauthentication frame transmitted at the BSS start is not critical, it is one more chance of getting any previously associated station notified of their previous association not being valid anymore had they missed previous notifications in cases where the AP is stopped and restarted. Signed-off-by: Jouni Malinen --- src/ap/hostapd.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 0f5a37f09..f9af038be 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1177,8 +1177,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) #endif /* CONFIG_MESH */ if (flush_old_stations) - hostapd_flush_old_stations(hapd, - WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_flush(hapd); hostapd_set_privacy(hapd, 0); #ifdef CONFIG_WEP @@ -1372,6 +1371,21 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) return -1; + if (flush_old_stations && !conf->start_disabled && + conf->broadcast_deauth) { + u8 addr[ETH_ALEN]; + + /* Should any previously associated STA not have noticed that + * the AP had stopped and restarted, send one more + * deauthentication notification now that the AP is ready to + * operate. */ + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, + "Deauthenticate all stations at BSS start"); + os_memset(addr, 0xff, ETH_ALEN); + hostapd_drv_sta_deauth(hapd, addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } + if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0) return -1; From 5a04a76aa20d32417484e40b878596e5933c645e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 12:16:34 +0300 Subject: [PATCH 0521/1105] Ignore Management frames while AP interface is not fully enabled It is possible for drivers to report received Management frames while AP is going through initial setup (e.g., during ACS or DFS CAC). hostapd and the driver is not yet ready for actually sending out responses to such frames at this point and as such, it is better to explicitly ignore such received frames rather than try to process them and have the response (e.g., a Probe Response frame) getting dropped by the driver as an invalid or getting out with some incorrect information. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 15e44b912..3e1896cf1 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4858,6 +4858,11 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, return 0; } + if (hapd->iface->state != HAPD_IFACE_ENABLED) { + wpa_printf(MSG_DEBUG, "MGMT: Ignore management frame while interface is not enabled (SA=" MACSTR " DA=" MACSTR " subtype=%u)", + MAC2STR(mgmt->sa), MAC2STR(mgmt->da), stype); + return 1; + } if (stype == WLAN_FC_STYPE_PROBE_REQ) { handle_probe_req(hapd, mgmt, len, ssi_signal); From 72e10af9caf12b46a19a410231fa2d55eaa18ada Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 12:18:42 +0300 Subject: [PATCH 0522/1105] tests: Automatic channel selection and RX during ACS Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_acs.py | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index 450a38fa1..2bd979de4 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -573,3 +573,45 @@ def test_ap_acs_with_fallback_to_20(dev, apdev): logger.info("SIGNAL_POLL: " + str(sig)) if "WIDTH=20 MHz" not in sig: raise Exception("Station did not report 20 MHz bandwidth") + +def test_ap_acs_rx_during(dev, apdev): + """Automatic channel selection and RX during ACS""" + force_prev_ap_on_24g(apdev[0]) + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['channel'] = '0' + params['chanlist'] = '1 6 11' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + + time.sleep(0.1) + hapd.set("ext_mgmt_frame_handling", "1") + bssid = hapd.own_addr().replace(':', '') + addr = "020304050607" + broadcast = 6*"ff" + + probereq = "40000000" + broadcast + addr + broadcast + "1000" + probereq += "0000" + "010802040b160c121824" + "32043048606c" + "030100" + if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % probereq): + raise Exception("MGMT_RX_PROCESS failed") + + probereq = "40000000" + broadcast + addr + broadcast + "1000" + probereq += "0000" + "010102" + if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2437 datarate=0 ssi_signal=-30 frame=%s" % probereq): + raise Exception("MGMT_RX_PROCESS failed") + + auth = "b0003a01" + bssid + addr + bssid + '1000000001000000' + if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % auth): + raise Exception("MGMT_RX_PROCESS failed") + hapd.set("ext_mgmt_frame_handling", "0") + + time.sleep(0.2) + try: + for i in range(3): + dev[i].request("SCAN_INTERVAL 1") + dev[i].connect("test-acs", psk="12345678", + scan_freq="2412 2437 2462", wait_connect=False) + wait_acs(hapd) + for i in range(3): + dev[i].wait_connected() + finally: + for i in range(3): + dev[i].request("SCAN_INTERVAL 5") From 3e1a1301074a652c65ece8ef32761e5b9d0481a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Mon, 11 May 2020 10:16:51 +0200 Subject: [PATCH 0523/1105] nl80211: Change AKM suite limit from warning to debug print MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit dd74ddd0dff6 ("nl80211: Handle AKM suite selectors for AP configuration") added warning log message "nl80211: Not enough room for all AKM suites (num_suites=X > NL80211_MAX_NR_AKM_SUITES)" which in some cases fills logs every 3 seconds, so fix this by increasing the log message level to debug. Reported-by: Stefan Lippers-Hollmann Ref: https://patchwork.ozlabs.org/project/openwrt/patch/20200504130757.12736-1-ynezz@true.cz/#2429246 Fixes: dd74ddd0dff6 ("nl80211: Handle AKM suite selectors for AP configuration") Signed-off-by: Petr Å tetiar Tested-by: Stefan Lippers-Hollmann --- src/drivers/driver_nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index bb0768c1c..2790346f4 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4332,7 +4332,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, num_suites = wpa_key_mgmt_to_suites(params->key_mgmt_suites, suites, ARRAY_SIZE(suites)); if (num_suites > NL80211_MAX_NR_AKM_SUITES) - wpa_printf(MSG_WARNING, + wpa_printf(MSG_DEBUG, "nl80211: Not enough room for all AKM suites (num_suites=%d > NL80211_MAX_NR_AKM_SUITES)", num_suites); else if (num_suites && From 0388992905a5c2be5cba9497504eaea346474754 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Thu, 7 May 2020 00:29:53 +0200 Subject: [PATCH 0524/1105] wpa_gui: Fix build with Inkscape 1.0 Inkscape 1.0 revamped their CLI flags, breaking the icon build. https://wiki.inkscape.org/wiki/index.php?title=Using_the_Command_Line#Background Signed-off-by: Jan Tojnar --- wpa_supplicant/wpa_gui-qt4/icons/Makefile | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/wpa_gui-qt4/icons/Makefile b/wpa_supplicant/wpa_gui-qt4/icons/Makefile index 709514c12..88efc3c5b 100644 --- a/wpa_supplicant/wpa_gui-qt4/icons/Makefile +++ b/wpa_supplicant/wpa_gui-qt4/icons/Makefile @@ -5,14 +5,28 @@ SIZES := 16x16 22x22 32x32 48x48 64x64 128x128 ICONS := $(addsuffix .png, $(foreach name, $(NAMES), $(foreach size, $(SIZES), $(size)/$(name)))) ICONS += $(addsuffix .xpm, $(NAMES)) +ifeq (1, $(shell which inkscape; echo $$?)) +$(error "No inkscape in PATH, it is required for exporting icons.") +else +ifeq (0, $(shell inkscape --without-gui 2>&1 > /dev/null; echo $$?)) +# Inkscape < 1.0 +INKSCAPE_GUI_FLAG := --without-gui +INKSCAPE_OUTPUT_FLAG := --export-png +else +# Inkscape >= 1.0 +INKSCAPE_GUI_FLAG := +INKSCAPE_OUTPUT_FLAG := --export-filename +endif +endif + all: $(ICONS) %.png: mkdir -p hicolor/$(word 1, $(subst /, ,$(@)))/apps/ - inkscape $(subst .png,.svg, $(word 2, $(subst /, , $(@)))) --without-gui \ + inkscape $(subst .png,.svg, $(word 2, $(subst /, , $(@)))) $(INKSCAPE_GUI_FLAG) \ --export-width=$(word 1, $(subst x, , $(@))) \ --export-height=$(word 2, $(subst x, , $(subst /, , $(@)))) \ - --export-png=hicolor/$(word 1, $(subst /, ,$(@)))/apps/$(word 2, $(subst /, , $@)) + $(INKSCAPE_OUTPUT_FLAG)=hicolor/$(word 1, $(subst /, ,$(@)))/apps/$(word 2, $(subst /, , $@)) %.xpm: mkdir -p pixmaps/ From 0218bf05d6d281be6a686be27075882dcb67eb09 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 1 May 2020 14:02:07 -0700 Subject: [PATCH 0525/1105] tests: sigma_dut: set regulatory inside try/except If sigma_dut is not installed, start_sigma_dut() will throw an exception. Call start_sigma_dut() inside the try/except to correctly reset the regulatory domain. This fixes several seemingly random failures due to regulatory domain not being reset. Signed-off-by: Thomas Pedersen --- tests/hwsim/test_sigma_dut.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 10313c215..dc2986b51 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4401,9 +4401,9 @@ def run_sigma_dut_ap_channel(dev, apdev, params, channel, mode, scan_freq, extra=None, check_signal=None, program=None): logdir = params['prefix'] + ".sigma-hostapd" with HWSimRadio() as (radio, iface): - subprocess.call(['iw', 'reg', 'set', 'US']) sigma = start_sigma_dut(iface, hostapd_logdir=logdir) try: + subprocess.call(['iw', 'reg', 'set', 'US']) cmd = "ap_reset_default" if program: cmd += ",program," + program From 692bbd25b4ea66a7fa994a599e5b425c900ade7c Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 1 May 2020 14:02:11 -0700 Subject: [PATCH 0526/1105] tests: Flush scan results before checking alloc failure When run after other tests, It was likely that the target bss was already present in scan_fail, so the scan_for_bss() wouldn't trip the allocation failure in wpa_bss_add(). Flush the scan results before the scan to ensure wpa_bss_add() is called and consistently pass scan_fail. Signed-off-by: Thomas Pedersen --- tests/hwsim/test_scan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index 9bf7a0fd4..aac07eea6 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -1166,6 +1166,7 @@ def test_scan_fail(dev, apdev): hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) with alloc_fail(dev[0], 1, "wpa_bss_add"): + dev[0].flush_scan_cache() dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") def test_scan_fail_type_only(dev, apdev): From f2dbaa8ace307de275f7580fa2788b3943fb6fc9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 21:01:32 +0300 Subject: [PATCH 0527/1105] SAE: Fix a typo in a comment Signed-off-by: Jouni Malinen --- src/common/sae.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/sae.c b/src/common/sae.c index 543640de3..1b4ec6d81 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -169,7 +169,7 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, * being smaller than prime. */ in_range = const_time_fill_msb((unsigned int) cmp_prime); /* The algorithm description would skip the next steps if - * cmp_prime >= 0 (reutnr 0 here), but go through them regardless to + * cmp_prime >= 0 (return 0 here), but go through them regardless to * minimize externally observable differences in behavior. */ x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); From 6a28c4dbc102de3fed9db44637f47a10e7adfb78 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 21:01:51 +0300 Subject: [PATCH 0528/1105] wolfssl: Fix compiler warnings on size_t printf format use Signed-off-by: Jouni Malinen --- src/crypto/tls_wolfssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c index d222d1427..11e658220 100644 --- a/src/crypto/tls_wolfssl.c +++ b/src/crypto/tls_wolfssl.c @@ -1741,7 +1741,7 @@ struct wpabuf * tls_connection_encrypt(void *tls_ctx, if (!conn) return NULL; - wpa_printf(MSG_DEBUG, "SSL: encrypt: %ld bytes", wpabuf_len(in_data)); + wpa_printf(MSG_DEBUG, "SSL: encrypt: %zu bytes", wpabuf_len(in_data)); wolfssl_reset_out_data(&conn->output); @@ -1792,7 +1792,7 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx, } wpabuf_put(buf, res); - wpa_printf(MSG_DEBUG, "SSL: decrypt: %ld bytes", wpabuf_len(buf)); + wpa_printf(MSG_DEBUG, "SSL: decrypt: %zu bytes", wpabuf_len(buf)); return buf; } From eb595b3e3ab531645a5bde71cf6385335b7a4b95 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 21:02:17 +0300 Subject: [PATCH 0529/1105] wolfssl: Fix crypto_bignum_rand() implementation The previous implementation used mp_rand_prime() to generate a random value in range 0..m. That is insanely slow way of generating a random value since mp_rand_prime() is for generating a random _prime_ which is not what is needed here. Replace that implementation with generationg of a random value in the requested range without doing any kind of prime number checks or loops to reject values that are not primes. This speeds up SAE and EAP-pwd routines by couple of orders of magnitude.. Signed-off-by: Jouni Malinen --- src/crypto/crypto_wolfssl.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c index dc68bd651..2e4bf8962 100644 --- a/src/crypto/crypto_wolfssl.c +++ b/src/crypto/crypto_wolfssl.c @@ -1104,19 +1104,21 @@ int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) { int ret = 0; WC_RNG rng; + size_t len; + u8 *buf; if (TEST_FAIL()) return -1; if (wc_InitRng(&rng) != 0) return -1; - if (mp_rand_prime((mp_int *) r, - (mp_count_bits((mp_int *) m) + 7) / 8 * 2, - &rng, NULL) != 0) - ret = -1; - if (ret == 0 && + len = (mp_count_bits((mp_int *) m) + 7) / 8; + buf = os_malloc(len); + if (!buf || wc_RNG_GenerateBlock(&rng, buf, len) != 0 || + mp_read_unsigned_bin((mp_int *) r, buf, len) != MP_OKAY || mp_mod((mp_int *) r, (mp_int *) m, (mp_int *) r) != 0) ret = -1; wc_FreeRng(&rng); + bin_clear_free(buf, len); return ret; } From 79488da576aeeb9400e1742fab7f463eed0fa7a1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 21:07:45 +0300 Subject: [PATCH 0530/1105] wolfssl: Do not hardcode include directory in wpa_supplicant build This is not really appropriate for any kind of cross compilations and is not really needed in general since system specific values can be set in .config. Signed-off-by: Jouni Malinen --- wpa_supplicant/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index e15694821..f4878807d 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1077,7 +1077,7 @@ endif ifeq ($(CONFIG_TLS), wolfssl) ifdef TLS_FUNCS -CFLAGS += -DWOLFSSL_DER_LOAD -I/usr/local/include/wolfssl +CFLAGS += -DWOLFSSL_DER_LOAD OBJS += ../src/crypto/tls_wolfssl.o endif OBJS += ../src/crypto/crypto_wolfssl.o From 4294d221d31d6ee162326757861200126d929ffc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 21:46:24 +0300 Subject: [PATCH 0531/1105] D-Bus: Increase introspection buffer size It was apparently possible to hit the 20000 octet limit in some cases, so increase the limit to avoid process termination due to insufficient room for preparing a response to Introspect calls. Signed-off-by: Jouni Malinen --- wpa_supplicant/dbus/dbus_new_introspect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/dbus/dbus_new_introspect.c b/wpa_supplicant/dbus/dbus_new_introspect.c index aee105b4b..6c721bf55 100644 --- a/wpa_supplicant/dbus/dbus_new_introspect.c +++ b/wpa_supplicant/dbus/dbus_new_introspect.c @@ -257,7 +257,7 @@ DBusMessage * wpa_dbus_introspect(DBusMessage *message, DBusMessage *reply; struct wpabuf *xml; - xml = wpabuf_alloc(20000); + xml = wpabuf_alloc(30000); if (xml == NULL) return NULL; From f636bc3abcce6acc953b5296d8d6fe7fd0a9fae9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 21:58:10 +0300 Subject: [PATCH 0532/1105] tests: Skip TOD-TOFU/STRICT tests if build does not support this This functionality is currently available only with OpenSSL and internal TLS implementation. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_eap.py | 2 ++ tests/hwsim/test_sigma_dut.py | 4 +++- tests/hwsim/utils.py | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index f41c6ffb3..0eed03500 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -7250,6 +7250,7 @@ def run_openssl_systemwide_policy(iface, apdev, test_params): def test_ap_wpa2_eap_tls_tod(dev, apdev): """EAP-TLS server certificate validation and TOD-STRICT""" + check_tls_tod(dev[0]) params = int_eap_server_params() params["server_cert"] = "auth_serv/server-certpol.pem" params["private_key"] = "auth_serv/server-certpol.key" @@ -7279,6 +7280,7 @@ def test_ap_wpa2_eap_tls_tod(dev, apdev): def test_ap_wpa2_eap_tls_tod_tofu(dev, apdev): """EAP-TLS server certificate validation and TOD-TOFU""" + check_tls_tod(dev[0]) params = int_eap_server_params() params["server_cert"] = "auth_serv/server-certpol2.pem" params["private_key"] = "auth_serv/server-certpol2.key" diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index dc2986b51..f1e8dfc39 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -19,7 +19,7 @@ import threading import time import hostapd -from utils import HwsimSkip +from utils import * from hwsim import HWSimRadio import hwsim_utils from wlantest import Wlantest @@ -3817,6 +3817,7 @@ def test_sigma_dut_eap_ttls_uosc_tod_tofu(dev, apdev, params): run_sigma_dut_eap_ttls_uosc_tod(dev, apdev, params, True) def run_sigma_dut_eap_ttls_uosc_tod(dev, apdev, params, tofu): + check_tls_tod(dev[0]) logdir = params['logdir'] name = "sigma_dut_eap_ttls_uosc_tod" @@ -3895,6 +3896,7 @@ def test_sigma_dut_eap_ttls_uosc_initial_tod_tofu(dev, apdev, params): run_sigma_dut_eap_ttls_uosc_initial_tod(dev, apdev, params, True) def run_sigma_dut_eap_ttls_uosc_initial_tod(dev, apdev, params, tofu): + check_tls_tod(dev[0]) logdir = params['logdir'] name = "sigma_dut_eap_ttls_uosc_initial_tod" diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index c259a766c..a6f260b62 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -113,6 +113,11 @@ def check_sae_capab(dev): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") +def check_tls_tod(dev): + tls = dev.request("GET tls_library") + if not tls.startswith("OpenSSL") and not tls.startswith("internal"): + raise HwsimSkip("TLS TOD-TOFU/STRICT not supported with this TLS library: " + tls) + def vht_supported(): cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) reg = cmd.stdout.read() From df49c53f4a464651a0920cc7c1c617f6a8cc0b59 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 16 May 2020 22:12:46 +0300 Subject: [PATCH 0533/1105] Fix a typo in a comment Signed-off-by: Jouni Malinen --- src/crypto/crypto.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 7c7515f6b..de2b07732 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -485,7 +485,7 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len); /** - * crypto_get_random - Generate cryptographically strong pseudy-random bytes + * crypto_get_random - Generate cryptographically strong pseudo-random bytes * @buf: Buffer for data * @len: Number of bytes to generate * Returns: 0 on success, -1 on failure From 4a0b27c62f3fc2b67c136bb09e95de658d8d6e7c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 May 2020 10:26:47 +0200 Subject: [PATCH 0534/1105] tests: Replace gtk boolean by keytype in cipher suite tests Replace the gtk boolean by a keytype value indicating GTK or PTK, to be able to extend to other types later. Signed-off-by: Johannes Berg --- tests/hwsim/test_ap_ciphers.py | 50 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index fb0d9b614..3d10cb0dc 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -17,6 +17,8 @@ from utils import * from wlantest import Wlantest from wpasupplicant import WpaSupplicant +KT_PTK, KT_GTK = range(2) + def check_cipher(dev, ap, cipher, group_cipher=None): if cipher not in dev.get_capability("pairwise"): raise HwsimSkip("Cipher %s not supported" % cipher) @@ -483,15 +485,15 @@ def test_ap_cipher_bip_req_mismatch(dev, apdev): dev[0].select_network(id) dev[0].wait_connected() -def get_rx_spec(phy, gtk=False): +def get_rx_spec(phy, keytype=KT_PTK): keys = "/sys/kernel/debug/ieee80211/%s/keys" % (phy) try: for key in os.listdir(keys): keydir = keys + "/" + key files = os.listdir(keydir) - if not gtk and "station" not in files: + if keytype == KT_PTK and "station" not in files: continue - if gtk and "station" in files: + if keytype != KT_PTK and "station" in files: continue with open(keydir + "/rx_spec") as f: return f.read() @@ -499,15 +501,15 @@ def get_rx_spec(phy, gtk=False): raise HwsimSkip("debugfs not supported in mac80211") return None -def get_tk_replay_counter(phy, gtk=False): +def get_tk_replay_counter(phy, keytype=KT_PTK): keys = "/sys/kernel/debug/ieee80211/%s/keys" % (phy) try: for key in os.listdir(keys): keydir = keys + "/" + key files = os.listdir(keydir) - if not gtk and "station" not in files: + if keytype == KT_PTK and "station" not in files: continue - if gtk and "station" in files: + if keytype != KT_PTK and "station" in files: continue with open(keydir + "/replays") as f: return int(f.read()) @@ -589,20 +591,20 @@ def test_ap_cipher_replay_protection_sta_gcmp(dev, apdev): def test_ap_cipher_replay_protection_sta_gtk_ccmp(dev, apdev): """CCMP replay protection on STA (GTK)""" - run_ap_cipher_replay_protection_sta(dev, apdev, "CCMP", gtk=True) + run_ap_cipher_replay_protection_sta(dev, apdev, "CCMP", keytype=KT_GTK) def test_ap_cipher_replay_protection_sta_gtk_tkip(dev, apdev): """TKIP replay protection on STA (GTK)""" skip_without_tkip(dev[0]) - run_ap_cipher_replay_protection_sta(dev, apdev, "TKIP", gtk=True) + run_ap_cipher_replay_protection_sta(dev, apdev, "TKIP", keytype=KT_GTK) def test_ap_cipher_replay_protection_sta_gtk_gcmp(dev, apdev): """GCMP replay protection on STA (GTK)""" if "GCMP" not in dev[0].get_capability("pairwise"): raise HwsimSkip("GCMP not supported") - run_ap_cipher_replay_protection_sta(dev, apdev, "GCMP", gtk=True) + run_ap_cipher_replay_protection_sta(dev, apdev, "GCMP", keytype=KT_GTK) -def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, gtk=False): +def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, keytype=KT_PTK): params = {"ssid": "test-wpa2-psk", "wpa_passphrase": "12345678", "wpa": "2", @@ -621,7 +623,7 @@ def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, gtk=False): hapd.wait_sta() if cipher != "TKIP": - replays = get_tk_replay_counter(phy, gtk) + replays = get_tk_replay_counter(phy, keytype) if replays != 0: raise Exception("Unexpected replay reported (1)") @@ -629,11 +631,11 @@ def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, gtk=False): hwsim_utils.test_connectivity(dev[0], hapd) if cipher != "TKIP": - replays = get_tk_replay_counter(phy, gtk) + replays = get_tk_replay_counter(phy, keytype) if replays != 0: raise Exception("Unexpected replay reported (2)") - addr = "ff:ff:ff:ff:ff:ff" if gtk else dev[0].own_addr() + addr = "ff:ff:ff:ff:ff:ff" if keytype != KT_PTK else dev[0].own_addr() if "OK" not in hapd.request("RESET_PN " + addr): raise Exception("RESET_PN failed") time.sleep(0.1) @@ -641,7 +643,7 @@ def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, gtk=False): success_expected=False) if cipher != "TKIP": - replays = get_tk_replay_counter(phy, gtk) + replays = get_tk_replay_counter(phy, keytype) if replays < 1: raise Exception("Replays not reported") @@ -679,14 +681,14 @@ def run_ap_wpa2_delayed_m3_retransmission(dev, apdev): hwsim_utils.test_connectivity(dev[0], hapd) time.sleep(0.1) - before_tk = get_rx_spec(phy, gtk=False).splitlines() - before_gtk = get_rx_spec(phy, gtk=True).splitlines() + before_tk = get_rx_spec(phy, keytype=KT_PTK).splitlines() + before_gtk = get_rx_spec(phy, keytype=KT_GTK).splitlines() addr = dev[0].own_addr() if "OK" not in hapd.request("RESEND_M3 " + addr): raise Exception("RESEND_M3 failed") time.sleep(0.1) - after_tk = get_rx_spec(phy, gtk=False).splitlines() - after_gtk = get_rx_spec(phy, gtk=True).splitlines() + after_tk = get_rx_spec(phy, keytype=KT_PTK).splitlines() + after_gtk = get_rx_spec(phy, keytype=KT_GTK).splitlines() if "OK" not in hapd.request("RESET_PN " + addr): raise Exception("RESET_PN failed") @@ -760,8 +762,8 @@ def run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, hwsim_utils.test_connectivity(dev[0], hapd) time.sleep(0.1) - before_tk = get_rx_spec(phy, gtk=False).splitlines() - before_gtk = get_rx_spec(phy, gtk=True).splitlines() + before_tk = get_rx_spec(phy, keytype=KT_PTK).splitlines() + before_gtk = get_rx_spec(phy, keytype=KT_GTK).splitlines() addr = dev[0].own_addr() if change_m1_anonce: if "OK" not in hapd.request("RESEND_M1 " + addr + " change-anonce"): @@ -771,8 +773,8 @@ def run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, if "OK" not in hapd.request("RESEND_M3 " + addr): raise Exception("RESEND_M3 failed") time.sleep(0.1) - after_tk = get_rx_spec(phy, gtk=False).splitlines() - after_gtk = get_rx_spec(phy, gtk=True).splitlines() + after_tk = get_rx_spec(phy, keytype=KT_PTK).splitlines() + after_gtk = get_rx_spec(phy, keytype=KT_GTK).splitlines() if "OK" not in hapd.request("RESET_PN " + addr): raise Exception("RESET_PN failed") @@ -828,12 +830,12 @@ def run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): hwsim_utils.test_connectivity(dev[0], hapd) time.sleep(0.1) - before = get_rx_spec(phy, gtk=True).splitlines() + before = get_rx_spec(phy, keytype=KT_GTK).splitlines() addr = dev[0].own_addr() if "OK" not in hapd.request("RESEND_GROUP_M1 " + addr): raise Exception("RESEND_GROUP_M1 failed") time.sleep(0.1) - after = get_rx_spec(phy, gtk=True).splitlines() + after = get_rx_spec(phy, keytype=KT_GTK).splitlines() if "OK" not in hapd.request("RESET_PN " + addr): raise Exception("RESET_PN failed") From bd1aebbd088394592dd4af12d43903efc34ae644 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 May 2020 10:26:48 +0200 Subject: [PATCH 0535/1105] hostapd: Extend RESET_PN for BIGTK Extend the RESET_PN command to allow resetting the BIGTK PN for testing. Signed-off-by: Johannes Berg --- hostapd/ctrl_iface.c | 26 ++++++++++++++++++++++++++ src/ap/hostapd.h | 5 +++++ src/ap/wpa_auth_glue.c | 18 +++++++++++++----- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index ed5100fbf..edc69f470 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2165,6 +2165,32 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd) if (hwaddr_aton(cmd, addr)) return -1; + if (is_broadcast_ether_addr(addr) && os_strstr(cmd, " BIGTK")) { + if (hapd->last_bigtk_alg == WPA_ALG_NONE) + return -1; + + wpa_printf(MSG_INFO, "TESTING: Reset BIPN for BIGTK"); + + /* First, use a zero key to avoid any possible duplicate key + * avoidance in the driver. */ + if (hostapd_drv_set_key(hapd->conf->iface, hapd, + hapd->last_bigtk_alg, + broadcast_ether_addr, + hapd->last_bigtk_key_idx, 0, 1, NULL, 0, + zero, hapd->last_bigtk_len, + KEY_FLAG_GROUP_TX_DEFAULT) < 0) + return -1; + + /* Set the previously configured key to reset its TSC */ + return hostapd_drv_set_key(hapd->conf->iface, hapd, + hapd->last_bigtk_alg, + broadcast_ether_addr, + hapd->last_bigtk_key_idx, 0, 1, NULL, + 0, hapd->last_bigtk, + hapd->last_bigtk_len, + KEY_FLAG_GROUP_TX_DEFAULT); + } + if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) { if (hapd->last_igtk_alg == WPA_ALG_NONE) return -1; diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 597bbb432..609c84b22 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -349,6 +349,11 @@ struct hostapd_data { int last_igtk_key_idx; u8 last_igtk[WPA_IGTK_MAX_LEN]; size_t last_igtk_len; + + enum wpa_alg last_bigtk_alg; + int last_bigtk_key_idx; + u8 last_bigtk[WPA_BIGTK_MAX_LEN]; + size_t last_bigtk_len; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_MBO diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 44ab83095..169be37ab 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -457,11 +457,19 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, alg == WPA_ALG_BIP_GMAC_128 || alg == WPA_ALG_BIP_GMAC_256 || alg == WPA_ALG_BIP_CMAC_256) { - hapd->last_igtk_alg = alg; - hapd->last_igtk_key_idx = idx; - if (key) - os_memcpy(hapd->last_igtk, key, key_len); - hapd->last_igtk_len = key_len; + if (idx == 4 || idx == 5) { + hapd->last_igtk_alg = alg; + hapd->last_igtk_key_idx = idx; + if (key) + os_memcpy(hapd->last_igtk, key, key_len); + hapd->last_igtk_len = key_len; + } else if (idx == 6 || idx == 7) { + hapd->last_bigtk_alg = alg; + hapd->last_bigtk_key_idx = idx; + if (key) + os_memcpy(hapd->last_bigtk, key, key_len); + hapd->last_bigtk_len = key_len; + } } else { hapd->last_gtk_alg = alg; hapd->last_gtk_key_idx = idx; From d3cab56c040d560b5a7e61f24ca870eba182ae98 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 May 2020 00:11:59 +0300 Subject: [PATCH 0536/1105] Rename WPA_ALG_IGTK to use the correct cipher name for BIP IGTK is the key that is used a BIP cipher. WPA_ALG_IGTK was the historical name used for this enum value when only the AES-128-CMAC based BIP algorithm was supported. Rename this to match the style used with the other BIP options. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth_glue.c | 2 +- src/common/defs.h | 2 +- src/common/wpa_common.c | 2 +- src/drivers/driver.h | 5 +++-- src/drivers/driver_atheros.c | 2 +- src/drivers/driver_nl80211.c | 6 +++--- src/drivers/driver_wext.c | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 169be37ab..05d87ac50 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -453,7 +453,7 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, os_memcpy(sta->last_tk, key, key_len); sta->last_tk_len = key_len; } - } else if (alg == WPA_ALG_IGTK || + } else if (alg == WPA_ALG_BIP_CMAC_128 || alg == WPA_ALG_BIP_GMAC_128 || alg == WPA_ALG_BIP_GMAC_256 || alg == WPA_ALG_BIP_CMAC_256) { diff --git a/src/common/defs.h b/src/common/defs.h index bcf6f543b..27c55de05 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -190,7 +190,7 @@ enum wpa_alg { WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP, - WPA_ALG_IGTK, + WPA_ALG_BIP_CMAC_128, WPA_ALG_GCMP, WPA_ALG_SMS4, WPA_ALG_KRK, diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index bddc696cf..1e7498a9e 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -2305,7 +2305,7 @@ enum wpa_alg wpa_cipher_to_alg(int cipher) case WPA_CIPHER_TKIP: return WPA_ALG_TKIP; case WPA_CIPHER_AES_128_CMAC: - return WPA_ALG_IGTK; + return WPA_ALG_BIP_CMAC_128; case WPA_CIPHER_BIP_GMAC_128: return WPA_ALG_BIP_GMAC_128; case WPA_CIPHER_BIP_GMAC_256: diff --git a/src/drivers/driver.h b/src/drivers/driver.h index b0713249f..782725efb 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1553,8 +1553,9 @@ struct wpa_driver_set_key_params { * alg - Encryption algorithm * * (%WPA_ALG_NONE, %WPA_ALG_WEP, %WPA_ALG_TKIP, %WPA_ALG_CCMP, - * %WPA_ALG_IGTK, %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, %WPA_ALG_CCMP_256, - * %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256, %WPA_ALG_BIP_CMAC_256); + * %WPA_ALG_BIP_AES_CMAC_128, %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, + * %WPA_ALG_CCMP_256, %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256, + * %WPA_ALG_BIP_CMAC_256); * %WPA_ALG_NONE clears the key. */ enum wpa_alg alg; diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c index d630c3dc4..9b4166d22 100644 --- a/src/drivers/driver_atheros.c +++ b/src/drivers/driver_atheros.c @@ -532,7 +532,7 @@ atheros_set_key(void *priv, struct wpa_driver_set_key_params *params) cipher = IEEE80211_CIPHER_AES_GCM_256; break; #endif /* ATH_GCM_SUPPORT */ - case WPA_ALG_IGTK: + case WPA_ALG_BIP_CMAC_128: cipher = IEEE80211_CIPHER_AES_CMAC; break; #ifdef ATH_GCM_SUPPORT diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 2790346f4..017cc30d5 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2927,7 +2927,7 @@ static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len) return RSN_CIPHER_SUITE_CCMP_256; case WPA_ALG_GCMP_256: return RSN_CIPHER_SUITE_GCMP_256; - case WPA_ALG_IGTK: + case WPA_ALG_BIP_CMAC_128: return RSN_CIPHER_SUITE_AES_128_CMAC; case WPA_ALG_BIP_GMAC_128: return RSN_CIPHER_SUITE_BIP_GMAC_128; @@ -3284,7 +3284,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, goto fail2; if (!key_msg || nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) || - nla_put_flag(key_msg, (alg == WPA_ALG_IGTK || + nla_put_flag(key_msg, (alg == WPA_ALG_BIP_CMAC_128 || alg == WPA_ALG_BIP_GMAC_128 || alg == WPA_ALG_BIP_GMAC_256 || alg == WPA_ALG_BIP_CMAC_256) ? @@ -3356,7 +3356,7 @@ static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg, if (!suite) return -1; - if (defkey && alg == WPA_ALG_IGTK) { + if (defkey && alg == WPA_ALG_BIP_CMAC_128) { if (nla_put_flag(msg, NL80211_KEY_DEFAULT_MGMT)) return -1; } else if (defkey) { diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index 8a3adee05..0f0ad1f53 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -1773,7 +1773,7 @@ static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, case WPA_ALG_CCMP: ext->alg = IW_ENCODE_ALG_CCMP; break; - case WPA_ALG_IGTK: + case WPA_ALG_BIP_CMAC_128: ext->alg = IW_ENCODE_ALG_AES_CMAC; break; default: From 4ae3f3972077cb7873fe47d1fd08a5f77b1d3430 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 May 2020 00:17:55 +0300 Subject: [PATCH 0537/1105] Add a helper function for recognizing BIP enum wpa_alg values Use a shared wpa_alg_bip() function for this and fix the case in nl_add_key() to cover all BIP algorithms. That fix does not change any behavior since the function is not currently used with any BIP algorithm, but it is better to avoid surprises should it ever be needed with IGTK. Signed-off-by: Jouni Malinen --- src/common/defs.h | 8 ++++++++ src/drivers/driver_nl80211.c | 7 ++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/common/defs.h b/src/common/defs.h index 27c55de05..bbe3120de 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -201,6 +201,14 @@ enum wpa_alg { WPA_ALG_BIP_CMAC_256 }; +static inline int wpa_alg_bip(enum wpa_alg alg) +{ + return alg == WPA_ALG_BIP_CMAC_128 || + alg == WPA_ALG_BIP_GMAC_128 || + alg == WPA_ALG_BIP_GMAC_256 || + alg == WPA_ALG_BIP_CMAC_256; +} + /** * enum wpa_states - wpa_supplicant state * diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 017cc30d5..8be593a52 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -3284,10 +3284,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, goto fail2; if (!key_msg || nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) || - nla_put_flag(key_msg, (alg == WPA_ALG_BIP_CMAC_128 || - alg == WPA_ALG_BIP_GMAC_128 || - alg == WPA_ALG_BIP_GMAC_256 || - alg == WPA_ALG_BIP_CMAC_256) ? + nla_put_flag(key_msg, wpa_alg_bip(alg) ? (key_idx == 6 || key_idx == 7 ? NL80211_KEY_DEFAULT_BEACON : NL80211_KEY_DEFAULT_MGMT) : @@ -3356,7 +3353,7 @@ static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg, if (!suite) return -1; - if (defkey && alg == WPA_ALG_BIP_CMAC_128) { + if (defkey && wpa_alg_bip(alg)) { if (nla_put_flag(msg, NL80211_KEY_DEFAULT_MGMT)) return -1; } else if (defkey) { From 889218c14a23ff663aad74705c17252dc6e7a069 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 May 2020 10:26:49 +0200 Subject: [PATCH 0538/1105] tests: Extend debugfs key state reading for IGTK/BIGTK Extend the debugfs read helpers to work with IGTK and BIGTK. Signed-off-by: Johannes Berg --- tests/hwsim/test_ap_ciphers.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index 3d10cb0dc..482fba18f 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -17,7 +17,7 @@ from utils import * from wlantest import Wlantest from wpasupplicant import WpaSupplicant -KT_PTK, KT_GTK = range(2) +KT_PTK, KT_GTK, KT_IGTK, KT_BIGTK = range(4) def check_cipher(dev, ap, cipher, group_cipher=None): if cipher not in dev.get_capability("pairwise"): @@ -490,6 +490,14 @@ def get_rx_spec(phy, keytype=KT_PTK): try: for key in os.listdir(keys): keydir = keys + "/" + key + with open(keydir + '/keyidx') as f: + keyid = int(f.read()) + if keytype in (KT_PTK, KT_GTK) and keyid not in (0, 1, 2, 3): + continue + if keytype == KT_IGTK and keyid not in (4, 5): + continue + if keytype == KT_BIGTK and keyid not in (6, 7): + continue files = os.listdir(keydir) if keytype == KT_PTK and "station" not in files: continue @@ -506,6 +514,14 @@ def get_tk_replay_counter(phy, keytype=KT_PTK): try: for key in os.listdir(keys): keydir = keys + "/" + key + with open(keydir + '/keyidx') as f: + keyid = int(f.read()) + if keytype in (KT_PTK, KT_GTK) and keyid not in (0, 1, 2, 3): + continue + if keytype == KT_IGTK and keyid not in (4, 5): + continue + if keytype == KT_BIGTK and keyid not in (6, 7): + continue files = os.listdir(keydir) if keytype == KT_PTK and "station" not in files: continue From 7f508ff96858e61bf216e749e09bb0dbdcbaf66e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 May 2020 10:26:50 +0200 Subject: [PATCH 0539/1105] tests: Reset the correct key's PN for group key handshake testing While adding support for IGTK and BIGTK here, I tested this without protections (i.e., with protections removed from both wpa_supplicant and the driver), and while I got some bad resets on the debugfs values, it should have failed with "unexpected connectivity". Fix this to be correct - we need to reset the GTK PN, not the PTK PN in this test. Signed-off-by: Johannes Berg --- tests/hwsim/test_ap_ciphers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index 482fba18f..352830a04 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -853,7 +853,7 @@ def run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): time.sleep(0.1) after = get_rx_spec(phy, keytype=KT_GTK).splitlines() - if "OK" not in hapd.request("RESET_PN " + addr): + if "OK" not in hapd.request("RESET_PN ff:ff:ff:ff:ff:ff"): raise Exception("RESET_PN failed") time.sleep(0.1) hwsim_utils.test_connectivity(dev[0], hapd, timeout=1, From 34ac7d871aeacc2c537e53bc0689951bc2fb4a68 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 May 2020 10:26:51 +0200 Subject: [PATCH 0540/1105] tests: Delayed group rekey retransmit test for IGTK Add a test for delayed group rekey retransmission that checks that the IGTK is protected against it by not resetting the IPN replay counter when reinstalling such a key. Signed-off-by: Johannes Berg --- tests/hwsim/test_ap_ciphers.py | 63 ++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index 352830a04..c709b886d 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -867,6 +867,69 @@ def run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): if a < b: raise Exception("RX counter decreased: idx=%d before=%d after=%d" % (i, b, a)) +def test_ap_wpa2_delayed_group_m1_retransmission_igtk(dev, apdev): + """Delayed group M1 retransmission (check IGTK protection)""" + require_under_vm() + try: + subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], + stdout=open('/dev/null', 'w')) + subprocess.call(['sysctl', '-w', + 'net.ipv6.conf.default.disable_ipv6=1'], + stdout=open('/dev/null', 'w')) + run_ap_wpa2_delayed_group_m1_retransmission_igtk(dev, apdev) + finally: + subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], + stdout=open('/dev/null', 'w')) + subprocess.call(['sysctl', '-w', + 'net.ipv6.conf.default.disable_ipv6=0'], + stdout=open('/dev/null', 'w')) + +def run_ap_wpa2_delayed_group_m1_retransmission_igtk(dev, apdev): + params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678", + ieee80211w="2") + hapd = hostapd.add_ap(apdev[0], params) + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + phy = dev[0].get_driver_status_field("phyname") + dev[0].connect("test-wpa2-psk", psk="12345678", scan_freq="2412", + ieee80211w="1") + hapd.wait_sta() + + hwsim_utils.test_connectivity(dev[0], hapd, timeout=1) + + # deauth once to see that works OK + addr = dev[0].own_addr() + hapd.request("DEAUTHENTICATE ff:ff:ff:ff:ff:ff") + dev[0].wait_disconnected(timeout=10) + + # now to check the protection + dev[0].request("RECONNECT") + dev[0].wait_connected() + hapd.wait_sta() + + hwsim_utils.test_connectivity(dev[0], hapd, timeout=1) + + if "OK" not in hapd.request("RESEND_GROUP_M1 " + addr): + raise Exception("RESEND_GROUP_M1 failed") + if "OK" not in hapd.request("RESET_PN ff:ff:ff:ff:ff:ff IGTK"): + raise Exception("RESET_PN failed") + + time.sleep(0.1) + hapd.request("DEAUTHENTICATE ff:ff:ff:ff:ff:ff test=1") + + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.1) + if ev is not None: + raise Exception("Unexpected disconnection") + + hwsim_utils.test_connectivity(dev[0], hapd, timeout=1) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + def test_ap_wpa2_delayed_m1_m3_zero_tk(dev, apdev): """Delayed M1+M3 retransmission and zero TK""" params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") From 025ab330b4b28f59cf81476c6ae69a0e298be1da Mon Sep 17 00:00:00 2001 From: neo_jou Date: Mon, 11 May 2020 15:42:49 +0800 Subject: [PATCH 0541/1105] ACS: Channel selection based freqlist When doing ACS, check freqlist also if it is specified. Signed-off-by: neojou --- src/ap/acs.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/ap/acs.c b/src/ap/acs.c index 5c0161070..aa2ceb0d1 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -512,6 +512,17 @@ static int is_in_chanlist(struct hostapd_iface *iface, } +static int is_in_freqlist(struct hostapd_iface *iface, + struct hostapd_channel_data *chan) +{ + if (!iface->conf->acs_freq_list.num) + return 1; + + return freq_range_list_includes(&iface->conf->acs_freq_list, + chan->freq); +} + + static void acs_survey_mode_interference_factor( struct hostapd_iface *iface, struct hostapd_hw_modes *mode) { @@ -527,6 +538,9 @@ static void acs_survey_mode_interference_factor( if (!is_in_chanlist(iface, chan)) continue; + if (!is_in_freqlist(iface, chan)) + continue; + wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)", chan->chan, chan->freq); @@ -651,6 +665,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface, if (!is_in_chanlist(iface, chan)) continue; + if (!is_in_freqlist(iface, chan)) + continue; + if (!chan_bw_allowed(chan, bw, 1, 1)) { wpa_printf(MSG_DEBUG, "ACS: Channel %d: BW %u is not supported", @@ -1013,6 +1030,9 @@ static int * acs_request_scan_add_freqs(struct hostapd_iface *iface, if (!is_in_chanlist(iface, chan)) continue; + if (!is_in_freqlist(iface, chan)) + continue; + *freq++ = chan->freq; } From 87c8e86da98ff4ee4df76cee36f80bbac638c564 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 May 2020 00:59:00 +0300 Subject: [PATCH 0542/1105] tests: Fix ACS freqlist testing The freqlist parameter uses comma, not space, separated values. Add another test case for checking freqlist values that do not use the preferred channel numbers to make sure the frequency list is actually used as a constraint for selecting the channel. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_acs.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index 2bd979de4..0f547cc13 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -90,16 +90,23 @@ def test_ap_acs_chanlist(dev, apdev): def test_ap_acs_freqlist(dev, apdev): """Automatic channel selection with freqlist set""" + run_ap_acs_freqlist(dev, apdev, [2412, 2437, 2462]) + +def test_ap_acs_freqlist2(dev, apdev): + """Automatic channel selection with freqlist set""" + run_ap_acs_freqlist(dev, apdev, [2417, 2432, 2457]) + +def run_ap_acs_freqlist(dev, apdev, freqlist): force_prev_ap_on_24g(apdev[0]) params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") params['channel'] = '0' - params['freqlist'] = '2412 2437 2462' + params['freqlist'] = ','.join([str(x) for x in freqlist]) hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) wait_acs(hapd) freq = int(hapd.get_status_field("freq")) - if freq not in [2412, 2437, 2462]: - raise Exception("Unexpected frequency: " + freq) + if freq not in freqlist: + raise Exception("Unexpected frequency: %d" % freq) dev[0].connect("test-acs", psk="12345678", scan_freq=str(freq)) From 570ae3ef54e4269bdf7849d4b491f98e1de48022 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 May 2020 12:47:52 +0200 Subject: [PATCH 0543/1105] tests: Unify IPv6 disabling Add a decorator that disables IPv6 and requires running under a VM, rather than open-coding that many times. Signed-off-by: Johannes Berg --- tests/hwsim/test_ap_ciphers.py | 83 +++------------------------------- tests/hwsim/utils.py | 24 ++++++++++ 2 files changed, 31 insertions(+), 76 deletions(-) diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index c709b886d..d9f827aaf 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -663,24 +663,9 @@ def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, keytype=KT_PTK): if replays < 1: raise Exception("Replays not reported") +@disable_ipv6 def test_ap_wpa2_delayed_m3_retransmission(dev, apdev): """Delayed M3 retransmission""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_m3_retransmission(dev, apdev) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - -def run_ap_wpa2_delayed_m3_retransmission(dev, apdev): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") hapd = hostapd.add_ap(apdev[0], params) @@ -726,39 +711,15 @@ def run_ap_wpa2_delayed_m3_retransmission(dev, apdev): if a < b: raise Exception("GTK RX counter decreased: idx=%d before=%d after=%d" % (i, b, a)) +@disable_ipv6 def test_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev): """Delayed M1+M3 retransmission""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) + run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, False) +@disable_ipv6 def test_ap_wpa2_delayed_m1_m3_retransmission2(dev, apdev): """Delayed M1+M3 retransmission (change M1 ANonce)""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, True) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) + run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, True) def run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, change_m1_anonce=False): @@ -812,24 +773,9 @@ def run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, if a < b: raise Exception("GTK RX counter decreased: idx=%d before=%d after=%d" % (i, b, a)) +@disable_ipv6 def test_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): """Delayed group M1 retransmission""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - -def run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") hapd = hostapd.add_ap(apdev[0], params) @@ -867,24 +813,9 @@ def run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): if a < b: raise Exception("RX counter decreased: idx=%d before=%d after=%d" % (i, b, a)) +@disable_ipv6 def test_ap_wpa2_delayed_group_m1_retransmission_igtk(dev, apdev): """Delayed group M1 retransmission (check IGTK protection)""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_group_m1_retransmission_igtk(dev, apdev) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - -def run_ap_wpa2_delayed_group_m1_retransmission_igtk(dev, apdev): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678", ieee80211w="2") hapd = hostapd.add_ap(apdev[0], params) diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index a6f260b62..098726b08 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -254,3 +254,27 @@ def set_world_reg(apdev0=None, apdev1=None, dev0=None): if dev0: dev0.cmd_execute(['iw', 'reg', 'set', '00']) time.sleep(0.1) + +def sysctl_write(val): + subprocess.call(['sysctl', '-w', val], stdout=open('/dev/null', 'w')) + +def disable_ipv6(fn): + def wrapper(dev, apdev, params): + require_under_vm() + try: + sysctl_write('net.ipv6.conf.all.disable_ipv6=1') + sysctl_write('net.ipv6.conf.default.disable_ipv6=1') + if fn.__code__.co_argcount > 2: + return fn(dev, apdev, params) + elif fn.__code__.co_argcount > 1: + return fn(dev, apdev) + return fn(dev) + finally: + sysctl_write('net.ipv6.conf.all.disable_ipv6=0') + sysctl_write('net.ipv6.conf.default.disable_ipv6=0') + # we need the name set right for selecting / printing etc. + wrapper.__name__ = fn.__name__ + wrapper.__doc__ = fn.__doc__ + # reparent to the right module for module filtering + wrapper.__module__ = fn.__module__ + return wrapper From 49d1f9c98efcb7b0edd3e4a674110061d84b849f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 May 2020 01:25:11 +0300 Subject: [PATCH 0544/1105] tests: Unify ignore_old_scan_res resetting Add a decorator that clears ignore_old_scan_res parameter value instead of doing this with try/finally in large number of test cases. Signed-off-by: Jouni Malinen --- tests/hwsim/test_scan.py | 6 +-- tests/hwsim/test_sigma_dut.py | 85 +++++++++-------------------------- tests/hwsim/utils.py | 42 +++++++++++------ 3 files changed, 49 insertions(+), 84 deletions(-) diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index aac07eea6..2e64ceec7 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -1273,13 +1273,9 @@ def test_scan_chan_switch(dev, apdev): run_scan(dev[0], bssid, 2412) dev[0].dump_monitor() +@reset_ignore_old_scan_res def test_scan_new_only(dev, apdev): """Scan and only_new=1 multiple times""" - try: - _test_scan_new_only(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") -def _test_scan_new_only(dev, apdev): dev[0].flush_scan_cache() hapd = hostapd.add_ap(apdev[0], {"ssid": "test-scan"}) dev[0].set("ignore_old_scan_res", "1") diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index f1e8dfc39..e446bcc90 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -183,14 +183,9 @@ def test_sigma_dut_basic(dev, apdev): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_open(dev, apdev): """sigma_dut controlled open network association""" - try: - run_sigma_dut_open(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") - -def run_sigma_dut_open(dev, apdev): ifname = dev[0].ifname sigma = start_sigma_dut(ifname) @@ -208,14 +203,9 @@ def run_sigma_dut_open(dev, apdev): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_psk_pmf(dev, apdev): """sigma_dut controlled PSK+PMF association""" - try: - run_sigma_dut_psk_pmf(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") - -def run_sigma_dut_psk_pmf(dev, apdev): ifname = dev[0].ifname sigma = start_sigma_dut(ifname) @@ -238,41 +228,31 @@ def run_sigma_dut_psk_pmf(dev, apdev): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_psk_pmf_bip_cmac_128(dev, apdev): """sigma_dut controlled PSK+PMF association with BIP-CMAC-128""" - try: - run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-CMAC-128", "AES-128-CMAC") - finally: - dev[0].set("ignore_old_scan_res", "0") + run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-CMAC-128", "AES-128-CMAC") +@reset_ignore_old_scan_res def test_sigma_dut_psk_pmf_bip_cmac_256(dev, apdev): """sigma_dut controlled PSK+PMF association with BIP-CMAC-256""" - try: - run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-CMAC-256", "BIP-CMAC-256") - finally: - dev[0].set("ignore_old_scan_res", "0") + run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-CMAC-256", "BIP-CMAC-256") +@reset_ignore_old_scan_res def test_sigma_dut_psk_pmf_bip_gmac_128(dev, apdev): """sigma_dut controlled PSK+PMF association with BIP-GMAC-128""" - try: - run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-GMAC-128", "BIP-GMAC-128") - finally: - dev[0].set("ignore_old_scan_res", "0") + run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-GMAC-128", "BIP-GMAC-128") +@reset_ignore_old_scan_res def test_sigma_dut_psk_pmf_bip_gmac_256(dev, apdev): """sigma_dut controlled PSK+PMF association with BIP-GMAC-256""" - try: - run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-GMAC-256", "BIP-GMAC-256") - finally: - dev[0].set("ignore_old_scan_res", "0") + run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-GMAC-256", "BIP-GMAC-256") +@reset_ignore_old_scan_res def test_sigma_dut_psk_pmf_bip_gmac_256_mismatch(dev, apdev): """sigma_dut controlled PSK+PMF association with BIP-GMAC-256 mismatch""" - try: - run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-GMAC-256", "AES-128-CMAC", - failure=True) - finally: - dev[0].set("ignore_old_scan_res", "0") + run_sigma_dut_psk_pmf_cipher(dev, apdev, "BIP-GMAC-256", "AES-128-CMAC", + failure=True) def run_sigma_dut_psk_pmf_cipher(dev, apdev, sigma_cipher, hostapd_cipher, failure=False): @@ -562,14 +542,9 @@ def run_sigma_dut_sae_pw_id_ft(dev, apdev, over_ds=False): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_sta_override_rsne(dev, apdev): """sigma_dut and RSNE override on STA""" - try: - run_sigma_dut_sta_override_rsne(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") - -def run_sigma_dut_sta_override_rsne(dev, apdev): ifname = dev[0].ifname sigma = start_sigma_dut(ifname) @@ -1261,14 +1236,9 @@ def test_sigma_dut_ap_psk_sae_ft(dev, apdev, params): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_owe(dev, apdev): """sigma_dut controlled OWE station""" - try: - run_sigma_dut_owe(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") - -def run_sigma_dut_owe(dev, apdev): if "OWE" not in dev[0].get_capability("key_mgmt"): raise HwsimSkip("OWE not supported") @@ -1332,6 +1302,7 @@ def run_sigma_dut_owe(dev, apdev): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_owe_ptk_workaround(dev, apdev): """sigma_dut controlled OWE station with PTK workaround""" if "OWE" not in dev[0].get_capability("key_mgmt"): @@ -1359,7 +1330,6 @@ def test_sigma_dut_owe_ptk_workaround(dev, apdev): sigma_dut_cmd_check("sta_reset_default,interface," + ifname) finally: stop_sigma_dut(sigma) - dev[0].set("ignore_old_scan_res", "0") def test_sigma_dut_ap_owe(dev, apdev, params): """sigma_dut controlled AP with OWE""" @@ -3305,14 +3275,9 @@ def test_sigma_dut_dpp_nfc_static_write_enrollee(dev, apdev): dev[0].set("dpp_config_processing", "0") stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_preconfigured_profile(dev, apdev): """sigma_dut controlled connection using preconfigured profile""" - try: - run_sigma_dut_preconfigured_profile(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") - -def run_sigma_dut_preconfigured_profile(dev, apdev): ifname = dev[0].ifname sigma = start_sigma_dut(ifname) @@ -3332,14 +3297,9 @@ def run_sigma_dut_preconfigured_profile(dev, apdev): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_wps_pbc(dev, apdev): """sigma_dut and WPS PBC Enrollee""" - try: - run_sigma_dut_wps_pbc(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") - -def run_sigma_dut_wps_pbc(dev, apdev): ssid = "test-wps-conf" hapd = hostapd.add_ap(apdev[0], {"ssid": "wps", "eap_server": "1", "wps_state": "2", @@ -3612,14 +3572,9 @@ def test_sigma_dut_ap_ent_ft_eap(dev, apdev, params): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_venue_url(dev, apdev): """sigma_dut controlled Venue URL fetch""" - try: - run_sigma_dut_venue_url(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") - -def run_sigma_dut_venue_url(dev, apdev): ifname = dev[0].ifname sigma = start_sigma_dut(ifname) @@ -4436,6 +4391,7 @@ def run_sigma_dut_ap_channel(dev, apdev, params, channel, mode, scan_freq, subprocess.call(['iw', 'reg', 'set', '00']) dev[0].flush_scan_cache() +@reset_ignore_old_scan_res def test_sigma_dut_beacon_prot(dev, apdev): """sigma_dut controlled STA and beacon protection""" ssid = "test-pmf-required" @@ -4467,7 +4423,6 @@ def test_sigma_dut_beacon_prot(dev, apdev): sigma_dut_cmd_check("sta_reset_default,interface," + ifname) finally: stop_sigma_dut(sigma) - dev[0].set("ignore_old_scan_res", "0") def test_sigma_dut_ap_beacon_prot(dev, apdev, params): """sigma_dut controlled AP and beacon protection""" diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index 098726b08..714f7644f 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -258,23 +258,37 @@ def set_world_reg(apdev0=None, apdev1=None, dev0=None): def sysctl_write(val): subprocess.call(['sysctl', '-w', val], stdout=open('/dev/null', 'w')) -def disable_ipv6(fn): - def wrapper(dev, apdev, params): - require_under_vm() - try: - sysctl_write('net.ipv6.conf.all.disable_ipv6=1') - sysctl_write('net.ipv6.conf.default.disable_ipv6=1') - if fn.__code__.co_argcount > 2: - return fn(dev, apdev, params) - elif fn.__code__.co_argcount > 1: - return fn(dev, apdev) - return fn(dev) - finally: - sysctl_write('net.ipv6.conf.all.disable_ipv6=0') - sysctl_write('net.ipv6.conf.default.disable_ipv6=0') +def var_arg_call(fn, dev, apdev, params): + if fn.__code__.co_argcount > 2: + return fn(dev, apdev, params) + elif fn.__code__.co_argcount > 1: + return fn(dev, apdev) + return fn(dev) + +def cloned_wrapper(wrapper, fn): # we need the name set right for selecting / printing etc. wrapper.__name__ = fn.__name__ wrapper.__doc__ = fn.__doc__ # reparent to the right module for module filtering wrapper.__module__ = fn.__module__ return wrapper + +def disable_ipv6(fn): + def wrapper(dev, apdev, params): + require_under_vm() + try: + sysctl_write('net.ipv6.conf.all.disable_ipv6=1') + sysctl_write('net.ipv6.conf.default.disable_ipv6=1') + var_arg_call(fn, dev, apdev, params) + finally: + sysctl_write('net.ipv6.conf.all.disable_ipv6=0') + sysctl_write('net.ipv6.conf.default.disable_ipv6=0') + return cloned_wrapper(wrapper, fn) + +def reset_ignore_old_scan_res(fn): + def wrapper(dev, apdev, params): + try: + var_arg_call(fn, dev, apdev, params) + finally: + dev[0].set("ignore_old_scan_res", "0") + return cloned_wrapper(wrapper, fn) From 7134b2a54841c7318f55800514f9028228bd98a4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 May 2020 01:29:40 +0300 Subject: [PATCH 0545/1105] tests: Add description for test cases that were missing it All test_*() functions are expected to use __doc__ to provide a short description of the test case. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_ft.py | 1 + tests/hwsim/test_ap_psk.py | 1 + tests/hwsim/test_hs20_filter.py | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 1162f98af..f2ca6f1ea 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -1530,6 +1530,7 @@ def test_ap_ft_eap_pull(dev, apdev): generic_ap_ft_eap_pull(dev, apdev) def test_ap_ft_eap_pull_vlan(dev, apdev): + """WPA2-EAP-FT AP (pull PMK) - with VLAN""" generic_ap_ft_eap_pull(dev, apdev, vlan=True) def test_ap_ft_eap_pull_wildcard(dev, apdev): diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index f52e38843..116733a1b 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -2935,6 +2935,7 @@ def test_rsn_ie_proto_psk_sta(dev, apdev): @remote_compatible def test_ap_cli_order(dev, apdev): + """hostapd configuration parameter SET ordering""" ssid = "test-rsn-setup" passphrase = 'zzzzzzzz' diff --git a/tests/hwsim/test_hs20_filter.py b/tests/hwsim/test_hs20_filter.py index 5194339c7..11cf34756 100644 --- a/tests/hwsim/test_hs20_filter.py +++ b/tests/hwsim/test_hs20_filter.py @@ -104,9 +104,11 @@ def _test_ip4_gtk_drop(devs, apdevs, params, dst): pass def test_ip4_gtk_drop_bcast(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv4 GTK drop broadcast""" _test_ip4_gtk_drop(devs, apdevs, params, dst='ffffffffffff') def test_ip4_gtk_drop_mcast(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv4 GTK drop multicast""" _test_ip4_gtk_drop(devs, apdevs, params, dst='ff0000000000') def _test_ip6_gtk_drop(devs, apdevs, params, dst): @@ -140,12 +142,15 @@ def _test_ip6_gtk_drop(devs, apdevs, params, dst): pass def test_ip6_gtk_drop_bcast(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv6 GTK drop broadcast""" _test_ip6_gtk_drop(devs, apdevs, params, dst='ffffffffffff') def test_ip6_gtk_drop_mcast(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv6 GTK drop multicast""" _test_ip6_gtk_drop(devs, apdevs, params, dst='ff0000000000') def test_ip4_drop_gratuitous_arp(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv4 drop gratuitous ARP""" require_under_vm() procfile = '/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp' % devs[0].ifname if not os.path.exists(procfile): @@ -173,6 +178,7 @@ def test_ip4_drop_gratuitous_arp(devs, apdevs, params): subprocess.call(['ip', 'neigh', 'del', '10.0.0.1', 'dev', dev.ifname]) def test_ip6_drop_unsolicited_na(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv6 drop unsolicited NA""" require_under_vm() procfile = '/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na' % devs[0].ifname if not os.path.exists(procfile): From f382af2c1e5ec3a5d09dceb3cc183b99f78a764a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 May 2020 12:59:53 +0300 Subject: [PATCH 0546/1105] tests: Avoid hapd reference before assignment on error cases Couple of VHT test cases missed explicit setting of hapd to None before trying to start hostapd. Add those to avoid unexpected exceptions in case hostapd start fails. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_vht.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index dce0dfff9..358e192de 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -330,6 +330,7 @@ def test_ap_vht_40(devs, apdevs): def test_ap_vht_capab_not_supported(dev, apdev): """VHT configuration with driver not supporting all vht_capab entries""" try: + hapd = None params = {"ssid": "vht", "country_code": "FI", "hw_mode": "a", @@ -1004,6 +1005,7 @@ def test_ap_vht_on_24ghz_2(dev, apdev): def test_prefer_vht40(dev, apdev): """Preference on VHT40 over HT40""" try: + hapd = None hapd2 = None params = {"ssid": "test", From 78c823de4e63b5e1172908f5caef2c20ea4b97c3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 May 2020 13:04:26 +0300 Subject: [PATCH 0547/1105] tests: Handle unexpected get_driver_status_field() error If the current country code cannot be fetched, do not try to report the current value in the log since that will result in TypeError exception. Signed-off-by: Jouni Malinen --- tests/hwsim/run-tests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/run-tests.py b/tests/hwsim/run-tests.py index 7ed632b66..019533f54 100755 --- a/tests/hwsim/run-tests.py +++ b/tests/hwsim/run-tests.py @@ -537,7 +537,9 @@ def main(): if check_country_00: for d in dev: country = d.get_driver_status_field("country") - if country != "00": + if country is None: + logger.info(d.ifname + ": Could not fetch country code after the test case run") + elif country != "00": d.dump_monitor() logger.info(d.ifname + ": Country code not reset back to 00: is " + country) print(d.ifname + ": Country code not reset back to 00: is " + country) From 0132a72922c4eed102a44b08c8e7e00070a0cf59 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 17 May 2020 16:03:29 +0300 Subject: [PATCH 0548/1105] tests: Use test-name.* style files more consistently Use params['prefix'] to build the file names for dynamically generated files. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_config.py | 17 +++++++---------- tests/hwsim/test_ap_dynamic.py | 4 ++-- tests/hwsim/test_ap_hs20.py | 35 +++++++++++----------------------- tests/hwsim/test_sigma_dut.py | 11 ++++------- 4 files changed, 24 insertions(+), 43 deletions(-) diff --git a/tests/hwsim/test_ap_config.py b/tests/hwsim/test_ap_config.py index e93c91477..b1d9d2133 100644 --- a/tests/hwsim/test_ap_config.py +++ b/tests/hwsim/test_ap_config.py @@ -161,10 +161,9 @@ def run_ap_config_reload_on_sighup(dev, apdev, params, ht=True): name = "ap_config_reload_on_sighup" if not ht: name += "_no_ht" - pidfile = os.path.join(params['logdir'], name + "-hostapd.pid") - logfile = os.path.join(params['logdir'], name + "-hostapd-log") - conffile = os.path.join(os.getcwd(), params['logdir'], - name + "-hostapd.conf") + pidfile = params['prefix'] + ".hostapd.pid" + logfile = params['prefix'] + ".hostapd.log" + conffile = params['prefix'] + ".hostapd.conf" prg = os.path.join(params['logdir'], 'alt-hostapd/hostapd/hostapd') if not os.path.exists(prg): prg = '../../hostapd/hostapd' @@ -208,11 +207,9 @@ def run_ap_config_reload_on_sighup(dev, apdev, params, ht=True): def test_ap_config_reload_on_sighup_bss_changes(dev, apdev, params): """hostapd configuration reload modification from file on SIGHUP with bss remove/add""" - name = "ap_config_reload_on_sighup_bss_changes" - pidfile = os.path.join(params['logdir'], name + "-hostapd.pid") - logfile = os.path.join(params['logdir'], name + "-hostapd-log") - conffile = os.path.join(os.getcwd(), params['logdir'], - name + "-hostapd.conf") + pidfile = params['prefix'] + ".hostapd.pid" + logfile = params['prefix'] + ".hostapd-log" + conffile = params['prefix'] + ".hostapd.conf" prg = os.path.join(params['logdir'], 'alt-hostapd/hostapd/hostapd') if not os.path.exists(prg): prg = '../../hostapd/hostapd' @@ -364,7 +361,7 @@ def test_ap_config_invalid_value(dev, apdev, params): def test_ap_config_eap_user_file_parsing(dev, apdev, params): """hostapd eap_user_file parsing""" - tmp = os.path.join(params['logdir'], 'ap_config_eap_user_file_parsing.tmp') + tmp = params['prefix'] + '.tmp' hapd = hostapd.add_ap(apdev[0], {"ssid": "foobar"}) for i in range(2): diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index 07afee313..96d35b9a2 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -502,8 +502,8 @@ def test_ap_duplicate_bssid(dev, apdev): def test_ap_bss_config_file(dev, apdev, params): """hostapd BSS config file""" - pidfile = os.path.join(params['logdir'], "ap_bss_config_file-hostapd.pid") - logfile = os.path.join(params['logdir'], "ap_bss_config_file-hostapd-log") + pidfile = params['prefix'] + ".hostapd.pid" + logfile = params['prefix'] + ".hostapd-log" prg = os.path.join(params['logdir'], 'alt-hostapd/hostapd/hostapd') if not os.path.exists(prg): prg = '../../hostapd/hostapd' diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index 863567eb1..9ff95b7d9 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -3850,7 +3850,7 @@ def test_ap_hs20_remediation_sql(dev, apdev, params): import sqlite3 except ImportError: raise HwsimSkip("No sqlite3 module available") - dbfile = os.path.join(params['logdir'], "eap-user.db") + dbfile = params['prefix'] + ".eap-user.db" try: os.remove(dbfile) except: @@ -3914,7 +3914,7 @@ def test_ap_hs20_sim_provisioning(dev, apdev, params): import sqlite3 except ImportError: raise HwsimSkip("No sqlite3 module available") - dbfile = os.path.join(params['logdir'], "ap_hs20_sim_provisioning-eap-user.db") + dbfile = params['prefix'] + ".eap-user.db" try: os.remove(dbfile) except: @@ -4632,16 +4632,10 @@ def tshark_get_na(cap): return frames def _test_proxyarp_open(dev, apdev, params, ebtables=False): - prefix = "proxyarp_open" - if ebtables: - prefix += "_ebtables" - cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap") - cap_dev0 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[0].ifname) - cap_dev1 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[1].ifname) - cap_dev2 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[2].ifname) + cap_br = params['prefix'] + ".ap-br0.pcap" + cap_dev0 = params['prefix'] + ".%s.pcap" % dev[0].ifname + cap_dev1 = params['prefix'] + ".%s.pcap" % dev[1].ifname + cap_dev2 = params['prefix'] + ".%s.pcap" % dev[2].ifname bssid = apdev[0]['bssid'] params = {'ssid': 'open'} @@ -4960,17 +4954,10 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): # raise Exception("br did not get ARP response for 192.168.1.123") def _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=False): - prefix = "proxyarp_open" - if ebtables: - prefix += "_ebtables" - prefix += "_ipv6" - cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap") - cap_dev0 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[0].ifname) - cap_dev1 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[1].ifname) - cap_dev2 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[2].ifname) + cap_br = params['prefix'] + ".ap-br0.pcap" + cap_dev0 = params['prefix'] + ".%s.pcap" % dev[0].ifname + cap_dev1 = params['prefix'] + ".%s.pcap" % dev[1].ifname + cap_dev2 = params['prefix'] + ".%s.pcap" % dev[2].ifname bssid = apdev[0]['bssid'] params = {'ssid': 'open'} @@ -6182,7 +6169,7 @@ def run_ap_hs20_terms_and_conditions_sql(dev, apdev, params, url_template, import sqlite3 except ImportError: raise HwsimSkip("No sqlite3 module available") - dbfile = os.path.join(params['logdir'], "eap-user.db") + dbfile = params['prefix'] + ".eap-user.db" try: os.remove(dbfile) except: diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index e446bcc90..070a2a549 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3853,20 +3853,17 @@ def test_sigma_dut_eap_ttls_uosc_initial_tod_tofu(dev, apdev, params): def run_sigma_dut_eap_ttls_uosc_initial_tod(dev, apdev, params, tofu): check_tls_tod(dev[0]) logdir = params['logdir'] - - name = "sigma_dut_eap_ttls_uosc_initial_tod" - if tofu: - name += "_tofu" + name = params['name'] with open("auth_serv/rsa3072-ca.pem", "r") as f: - with open(os.path.join(logdir, name + ".ca.pem"), "w") as f2: + with open(params['prefix'] + ".ca.pem", "w") as f2: f2.write(f.read()) if tofu: src = "auth_serv/server-certpol2.pem" else: src = "auth_serv/server-certpol.pem" - dst = os.path.join(logdir, name + ".server.der") - hashdst = os.path.join(logdir, name + ".server.pem.sha256") + dst = params['prefix'] + ".server.der" + hashdst = params['prefix'] + ".server.pem.sha256" subprocess.check_call(["openssl", "x509", "-in", src, "-out", dst, "-outform", "DER"], stderr=open('/dev/null', 'w')) From 39f29f250a217160215577143bb950469f7bc140 Mon Sep 17 00:00:00 2001 From: Davide Caratti Date: Fri, 24 Apr 2020 14:43:06 +0200 Subject: [PATCH 0549/1105] defconfig: Enable TDLS Some distros (e.g., Debian and Arch) already build wpa_supplicant with support for TDLS, and Fedora is about to enable this feature as well. Set CONFIG_TDLS=y in wpa_supplicant default build configuration. Signed-off-by: Davide Caratti --- wpa_supplicant/defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index cbe49c8ec..a0fe94e67 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -506,7 +506,7 @@ CONFIG_AP=y CONFIG_P2P=y # Enable TDLS support -#CONFIG_TDLS=y +CONFIG_TDLS=y # Wi-Fi Display # This can be used to enable Wi-Fi Display extensions for P2P using an external From e297a5bfdadf37dbcea50c44d550fccca3225d45 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 24 Apr 2020 15:45:34 -0700 Subject: [PATCH 0550/1105] HE: Define 6 GHz band capability elements Defines IEEE P802.11ax/D6.0, 9.4.2.261 HE 6 GHz Band Capabilities element and 6 GHz Operation Information field of HE Operation element (IEEE P802.11ax/D6.0, Figure 9-787k). Signed-off-by: Rajkumar Manoharan --- src/common/ieee802_11_defs.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 7f31e09a1..49266ada9 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -473,6 +473,7 @@ #define WLAN_EID_EXT_SPATIAL_REUSE 39 #define WLAN_EID_EXT_OCV_OCI 54 #define WLAN_EID_EXT_SHORT_SSID_LIST 58 +#define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 #define WLAN_EID_EXT_EDMG_CAPABILITIES 61 #define WLAN_EID_EXT_EDMG_OPERATION 62 #define WLAN_EID_EXT_REJECTED_GROUPS 92 @@ -2151,6 +2152,41 @@ struct ieee80211_he_operation { /* Followed by conditional MaxBSSID Indicator subfield (u8) */ } STRUCT_PACKED; +/* IEEE P802.11ax/D6.0, Figure 9-787k - 6 GHz Operation Information field */ +struct ieee80211_he_6ghz_oper_info { + u8 primary_chan; + u8 control; + u8 chan_center_freq_seg0; + u8 chan_center_freq_seg1; + u8 min_rate; +} STRUCT_PACKED; + +#define HE_6GHZ_OPER_INFO_CTRL_CHAN_WIDTH_MASK (BIT(0) | BIT(1)) +#define HE_6GHZ_OPER_INFO_CTRL_DUP_BEACON BIT(2) + +/* IEEE P802.11ax/D6.0, 9.4.2.261 HE 6 GHz Band Capabilities element */ +struct ieee80211_he_6ghz_band_cap { + /* Minimum MPDU Start Spacing B0..B2 + * Maximum A-MPDU Length Exponent B3..B5 + * Maximum MPDU Length B6..B7 */ + u8 a_mpdu_params; /* B0..B7 */ + u8 info; /* B8..B15 */ +} STRUCT_PACKED; + +#define HE_6GHZ_BAND_CAP_MIN_MPDU_START_SPACE_MASK 0x7 +#define HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK 0x7 +#define HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 3 +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_MASK 0x3 +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_SHIFT 6 + +#define HE_6GHZ_BAND_CAP_SMPS_MASK (BIT(1) | BIT(2)) +#define HE_6GHZ_BAND_CAP_SMPS_STATIC 0 +#define HE_6GHZ_BAND_CAP_SMPS_DYNAMIC BIT(1) +#define HE_6GHZ_BAND_CAP_SMPS_DISABLED (BIT(1) | BIT(2)) +#define HE_6GHZ_BAND_CAP_RD_RESPONDER BIT(3) +#define HE_6GHZ_BAND_CAP_RX_ANTENNA_PATTERN BIT(4) +#define HE_6GHZ_BAND_CAP_TX_ANTENNA_PATTERN BIT(5) + /* * IEEE P802.11ax/D4.0, 9.4.2.246 Spatial Reuse Parameter Set element */ From b2c0b83c66044131c8a5053c780688f14ff3586f Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 24 Apr 2020 15:45:35 -0700 Subject: [PATCH 0551/1105] HE: Remove VHT Operation Information from HE Operation element The VHT Operation Information subfield is conditonally present, so do not hardcoded it in struct ieee80211_he_operation. These members of the struct are not currently used, so these can be removed without impact to functionality. Signed-off-by: Rajkumar Manoharan --- src/common/ieee802_11_defs.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 49266ada9..0dd386f9e 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2146,10 +2146,9 @@ struct ieee80211_he_operation { le32 he_oper_params; /* HE Operation Parameters[3] and * BSS Color Information[1] */ le16 he_mcs_nss_set; - u8 vht_op_info_chwidth; - u8 vht_op_info_chan_center_freq_seg0_idx; - u8 vht_op_info_chan_center_freq_seg1_idx; - /* Followed by conditional MaxBSSID Indicator subfield (u8) */ + /* Followed by conditional VHT Operation Information (3 octets), + * Max Co-Hosted BSSID Indicator subfield (1 octet), and/or 6 GHz + * Operation Information subfield (5 octets). */ } STRUCT_PACKED; /* IEEE P802.11ax/D6.0, Figure 9-787k - 6 GHz Operation Information field */ From 88911a0aa437182c3ac0c31c25a4adae7351d859 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 24 Apr 2020 15:45:36 -0700 Subject: [PATCH 0552/1105] HE: Add HE 6 GHz Band Capabilities into ieee802_11_parse_elems() Handle 6 GHz band capability element parsing for association. Signed-off-by: Rajkumar Manoharan --- src/common/ieee802_11_common.c | 5 +++++ src/common/ieee802_11_common.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index e7ee24e2a..46f4f4d6f 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -294,6 +294,11 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, elems->short_ssid_list = pos; elems->short_ssid_list_len = elen; break; + case WLAN_EID_EXT_HE_6GHZ_BAND_CAP: + if (elen < sizeof(struct ieee80211_he_6ghz_band_cap)) + break; + elems->he_6ghz_band_cap = pos; + break; default: if (show_errors) { wpa_printf(MSG_MSGDUMP, diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 7994cd7d6..cf4865014 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -113,6 +113,7 @@ struct ieee802_11_elems { const u8 *he_capabilities; const u8 *he_operation; const u8 *short_ssid_list; + const u8 *he_6ghz_band_cap; u8 ssid_len; u8 supp_rates_len; From db603634a936ce773178f3599f4da15274c8c934 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 24 Apr 2020 15:45:37 -0700 Subject: [PATCH 0553/1105] HE: Add 6 GHz Band Capabilities element in Beacon and response frames Construct HE 6 GHz Band Capabilities element (IEEE 802.11ax/D6.0, 9.4.2.261) from HT and VHT capabilities and add it to Beacon, Probe Response, and (Re)Association Response frames when operating on the 6 GHz band. Signed-off-by: Rajkumar Manoharan --- src/ap/beacon.c | 8 +++++++ src/ap/ieee802_11.c | 1 + src/ap/ieee802_11.h | 1 + src/ap/ieee802_11_he.c | 48 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 47ced9a16..22e672c8d 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -463,6 +463,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, 3 + sizeof(struct ieee80211_he_operation) + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + 3 + sizeof(struct ieee80211_spatial_reuse); + if (is_6ghz_op_class(hapd->iconf->op_class)) + buflen += sizeof(struct ieee80211_he_6ghz_oper_info) + + 3 + sizeof(struct ieee80211_he_6ghz_band_cap); } #endif /* CONFIG_IEEE80211AX */ @@ -570,6 +573,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_he_operation(hapd, pos); pos = hostapd_eid_spatial_reuse(hapd, pos); pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); + pos = hostapd_eid_he_6ghz_band_cap(hapd, pos); } #endif /* CONFIG_IEEE80211AX */ @@ -1161,6 +1165,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, 3 + sizeof(struct ieee80211_he_operation) + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + 3 + sizeof(struct ieee80211_spatial_reuse); + if (is_6ghz_op_class(hapd->iconf->op_class)) + tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) + + 3 + sizeof(struct ieee80211_he_6ghz_band_cap); } #endif /* CONFIG_IEEE80211AX */ @@ -1288,6 +1295,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_he_operation(hapd, tailpos); tailpos = hostapd_eid_spatial_reuse(hapd, tailpos); tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); + tailpos = hostapd_eid_he_6ghz_band_cap(hapd, tailpos); } #endif /* CONFIG_IEEE80211AX */ diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 3e1896cf1..3a7c9a2b9 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3786,6 +3786,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, p = hostapd_eid_he_operation(hapd, p); p = hostapd_eid_spatial_reuse(hapd, p); p = hostapd_eid_he_mu_edca_parameter_set(hapd, p); + p = hostapd_eid_he_6ghz_band_cap(hapd, p); } #endif /* CONFIG_IEEE80211AX */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index c7bdb4b2b..ba5056289 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -63,6 +63,7 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid, u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid); int hostapd_ht_operation_update(struct hostapd_iface *iface); void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 57c6b18f4..3267a9d67 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -311,6 +311,54 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid) } +u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid) +{ + struct hostapd_hw_modes *mode = hapd->iface->current_mode; + struct ieee80211_he_6ghz_band_cap *cap; + u32 vht_cap; + u8 ht_info; + u8 params; + u8 *pos; + + if (!mode || !is_6ghz_op_class(hapd->iconf->op_class)) + return eid; + + vht_cap = hapd->iface->conf->vht_capab; + ht_info = mode->a_mpdu_params; + + pos = eid; + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 1 + sizeof(*cap); + *pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP; + + /* Minimum MPDU Start Spacing B0..B2 */ + params = (ht_info >> 2) & HE_6GHZ_BAND_CAP_MIN_MPDU_START_SPACE_MASK; + + /* Maximum A-MPDU Length Exponent B3..B5 */ + params |= ((((vht_cap & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >> + VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT) & + HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) << + HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); + + /* Maximum MPDU Length B6..B7 */ + params |= ((((vht_cap & VHT_CAP_MAX_MPDU_LENGTH_MASK) >> + VHT_CAP_MAX_MPDU_LENGTH_MASK_SHIFT) & + HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_MASK) << + HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_SHIFT); + + cap = (struct ieee80211_he_6ghz_band_cap *) pos; + cap->a_mpdu_params = params; + cap->info = HE_6GHZ_BAND_CAP_SMPS_DISABLED; + if (vht_cap & VHT_CAP_RX_ANTENNA_PATTERN) + cap->info |= HE_6GHZ_BAND_CAP_RX_ANTENNA_PATTERN; + if (vht_cap & VHT_CAP_TX_ANTENNA_PATTERN) + cap->info |= HE_6GHZ_BAND_CAP_TX_ANTENNA_PATTERN; + pos += sizeof(*cap); + + return pos; +} + + void hostapd_get_he_capab(struct hostapd_data *hapd, const struct ieee80211_he_capabilities *he_cap, struct ieee80211_he_capabilities *neg_he_cap, From dd2daf0848ed8854065cc5cfca07a0538cd380af Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Fri, 24 Apr 2020 15:45:41 -0700 Subject: [PATCH 0554/1105] HE: Process HE 6 GHz band capab from associating HE STA Process HE 6 GHz band capabilities in (Re)Association Request frames and pass the information to the driver. Signed-off-by: Rajkumar Manoharan --- src/ap/ap_drv_ops.c | 2 ++ src/ap/ap_drv_ops.h | 1 + src/ap/ieee802_11.c | 7 +++++++ src/ap/ieee802_11.h | 2 ++ src/ap/ieee802_11_he.c | 26 ++++++++++++++++++++++++++ src/ap/sta_info.c | 7 +++++-- src/ap/sta_info.h | 2 ++ src/drivers/driver.h | 1 + 8 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 904236bae..f15765945 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -418,6 +418,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, const struct ieee80211_vht_capabilities *vht_capab, const struct ieee80211_he_capabilities *he_capab, size_t he_capab_len, + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, int set) { @@ -439,6 +440,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, params.vht_capabilities = vht_capab; params.he_capab = he_capab; params.he_capab_len = he_capab_len; + params.he_6ghz_capab = he_6ghz_capab; params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); params.vht_opmode = vht_opmode; params.flags = hostapd_sta_flags_to_drv(flags); diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 811d26a2c..5738c1c97 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -43,6 +43,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, const struct ieee80211_vht_capabilities *vht_capab, const struct ieee80211_he_capabilities *he_capab, size_t he_capab_len, + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, int set); int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 3a7c9a2b9..f1f37027b 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3181,6 +3181,12 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, elems.he_capabilities_len); if (resp != WLAN_STATUS_SUCCESS) return resp; + if (is_6ghz_op_class(hapd->iconf->op_class)) { + resp = copy_sta_he_6ghz_capab(hapd, sta, + elems.he_6ghz_band_cap); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } } #endif /* CONFIG_IEEE80211AX */ @@ -3627,6 +3633,7 @@ static int add_associated_sta(struct hostapd_data *hapd, sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, sta->flags & WLAN_STA_HE ? &he_cap : NULL, sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0, + sta->he_6ghz_capab, sta->flags | WLAN_STA_ASSOC, sta->qosinfo, sta->vht_opmode, sta->p2p_ie ? 1 : 0, set)) { diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index ba5056289..ea8c60846 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -96,6 +96,8 @@ u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, enum ieee80211_op_mode opmode, const u8 *he_capab, size_t he_capab_len); +u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *he_6ghz_capab); int hostapd_get_he_twt_responder(struct hostapd_data *hapd, enum ieee80211_op_mode mode); void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 3267a9d67..f1f2442fc 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -463,6 +463,32 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, } +u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *he_6ghz_capab) +{ + if (!he_6ghz_capab || !hapd->iconf->ieee80211ax || + !is_6ghz_op_class(hapd->iconf->op_class)) { + sta->flags &= ~WLAN_STA_6GHZ; + os_free(sta->he_6ghz_capab); + sta->he_6ghz_capab = NULL; + return WLAN_STATUS_SUCCESS; + } + + if (!sta->he_6ghz_capab) { + sta->he_6ghz_capab = + os_zalloc(sizeof(struct ieee80211_he_6ghz_band_cap)); + if (!sta->he_6ghz_capab) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_6GHZ; + os_memcpy(sta->he_6ghz_capab, he_6ghz_capab, + sizeof(struct ieee80211_he_6ghz_band_cap)); + + return WLAN_STATUS_SUCCESS; +} + + int hostapd_get_he_twt_responder(struct hostapd_data *hapd, enum ieee80211_op_mode mode) { diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 93f1f0c20..67b5e9885 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -326,6 +326,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) os_free(sta->vht_capabilities); os_free(sta->vht_operation); os_free(sta->he_capab); + os_free(sta->he_6ghz_capab); hostapd_free_psk_list(sta->psk); os_free(sta->identity); os_free(sta->radius_cui); @@ -1424,7 +1425,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) int res; buf[0] = '\0'; - res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + res = os_snprintf(buf, buflen, + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (flags & WLAN_STA_AUTH ? "[AUTH]" : ""), (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""), @@ -1444,6 +1446,7 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) (flags & WLAN_STA_HT ? "[HT]" : ""), (flags & WLAN_STA_VHT ? "[VHT]" : ""), (flags & WLAN_STA_HE ? "[HE]" : ""), + (flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""), (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""), (flags & WLAN_STA_WNM_SLEEP_MODE ? "[WNM_SLEEP_MODE]" : "")); @@ -1515,7 +1518,7 @@ int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta) if (hostapd_sta_add(hapd, sta->addr, 0, 0, sta->supported_rates, sta->supported_rates_len, - 0, NULL, NULL, NULL, 0, + 0, NULL, NULL, NULL, 0, NULL, sta->flags, 0, 0, 0, 0)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 308aa29d9..940d31590 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -38,6 +38,7 @@ #define WLAN_STA_PENDING_FILS_ERP BIT(22) #define WLAN_STA_MULTI_AP BIT(23) #define WLAN_STA_HE BIT(24) +#define WLAN_STA_6GHZ BIT(25) #define WLAN_STA_PENDING_DISASSOC_CB BIT(29) #define WLAN_STA_PENDING_DEAUTH_CB BIT(30) #define WLAN_STA_NONERP BIT(31) @@ -170,6 +171,7 @@ struct sta_info { u8 vht_opmode; struct ieee80211_he_capabilities *he_capab; size_t he_capab_len; + struct ieee80211_he_6ghz_band_cap *he_6ghz_capab; int sa_query_count; /* number of pending SA Query requests; * 0 = no SA Query in progress */ diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 782725efb..1e2e332a6 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2087,6 +2087,7 @@ struct hostapd_sta_add_params { u8 vht_opmode; const struct ieee80211_he_capabilities *he_capab; size_t he_capab_len; + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab; u32 flags; /* bitmask of WPA_STA_* flags */ u32 flags_mask; /* unset bits in flags */ #ifdef CONFIG_MESH From db0d0b84af89dcf7bb09a666931d97d93f80e749 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Mon, 27 Apr 2020 14:36:16 +0530 Subject: [PATCH 0555/1105] nl80211: Control the registration for RRM frame with driver_param wpa_supplicant registered to process the Radio Measurement Request frames unconditionally. This would prevent other location based applications from handling these frames. Enable such a use case by allowing wpa_supplicant to be configured not to register to process these frames. This can now be done by adding "no_rrm=1" to the driver_param configuration parameter. In addition, wpa_driver_nl80211_init() does not have the provision to take driver_params. Hence, resubscribe again with cfg80211 when this driver parameter "no_rrm=1" is set after the initial setup steps. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 15 ++++++++++++++- src/drivers/driver_nl80211.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 8be593a52..72189da24 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2372,7 +2372,8 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) ret = -1; /* Radio Measurement - Radio Measurement Request */ - if (nl80211_register_action_frame(bss, (u8 *) "\x05\x00", 2) < 0) + if (!drv->no_rrm && + nl80211_register_action_frame(bss, (u8 *) "\x05\x00", 2) < 0) ret = -1; /* Radio Measurement - Link Measurement Request */ @@ -8239,6 +8240,18 @@ static int nl80211_set_param(void *priv, const char *param) if (os_strstr(param, "full_ap_client_state=0")) drv->capa.flags &= ~WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE; + if (os_strstr(param, "no_rrm=1")) { + drv->no_rrm = 1; + + if (!bss->in_deinit && !is_ap_interface(drv->nlmode) && + !is_mesh_interface(drv->nlmode)) { + nl80211_mgmt_unsubscribe(bss, "no_rrm=1"); + if (nl80211_mgmt_subscribe_non_ap(bss) < 0) + wpa_printf(MSG_DEBUG, + "nl80211: Failed to re-register Action frame processing - ignore for now"); + } + } + return 0; } diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 895f9d72e..1dd5aee8b 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -173,6 +173,7 @@ struct wpa_driver_nl80211_data { unsigned int add_sta_node_vendor_cmd_avail:1; unsigned int control_port_ap:1; unsigned int multicast_registrations:1; + unsigned int no_rrm:1; u64 vendor_scan_cookie; u64 remain_on_chan_cookie; From e5e275745597e0c82f5267f1242753c5c917a7f0 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Fri, 17 Apr 2020 17:00:34 +0530 Subject: [PATCH 0556/1105] Add QCA vendor interface support to configure PHY modes Add an attribute that can be used with QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION vendor command to configure different PHY modes to the driver/firmware. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 74 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index e599b8d7e..a6fbfa660 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2120,6 +2120,14 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON = 61, + /* 32-bit unsigned value to configure different PHY modes to the + * driver/firmware. The possible values are defined in + * enum qca_wlan_vendor_phy_mode. The configuration will be reset to + * default value, i.e., QCA_WLAN_VENDOR_PHY_MODE_AUTO upon restarting + * the driver. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE = 62, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = @@ -6847,6 +6855,72 @@ enum qca_wlan_vendor_attr_he_omi_tx { QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST - 1, }; + /** + * enum qca_wlan_vendor_phy_mode - Different PHY modes + * These values are used with %QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE. + * + * @QCA_WLAN_VENDOR_PHY_MODE_AUTO: autoselect + * @QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO: 2.4 GHz 802.11b/g/n/ax autoselect + * @QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO: 5 GHz 802.11a/n/ac/ax autoselect + * @QCA_WLAN_VENDOR_PHY_MODE_11A: 5 GHz, OFDM + * @QCA_WLAN_VENDOR_PHY_MODE_11B: 2.4 GHz, CCK + * @QCA_WLAN_VENDOR_PHY_MODE_11G: 2.4 GHz, OFDM + * @QCA_WLAN_VENDOR_PHY_MODE_11AGN: Support 802.11n in both 2.4 GHz and 5 GHz + * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20: 2.4 GHz, HT20 + * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS: 2.4 GHz, HT40 (ext ch +1) + * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS: 2.4 GHz, HT40 (ext ch -1) + * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40: 2.4 GHz, Auto HT40 + * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20: 5 GHz, HT20 + * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS: 5 GHz, HT40 (ext ch +1) + * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS: 5 GHz, HT40 (ext ch -1) + * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40: 5 GHz, Auto HT40 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20: 5 GHz, VHT20 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS: 5 GHz, VHT40 (Ext ch +1) + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS: 5 GHz VHT40 (Ext ch -1) + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40: 5 GHz, VHT40 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80: 5 GHz, VHT80 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80: 5 GHz, VHT80+80 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160: 5 GHz, VHT160 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20: HE20 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40: HE40 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS: HE40 (ext ch +1) + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS: HE40 (ext ch -1) + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80: HE80 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80: HE 80P80 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160: HE160 + */ +enum qca_wlan_vendor_phy_mode { + QCA_WLAN_VENDOR_PHY_MODE_AUTO = 0, + QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO = 1, + QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO = 2, + QCA_WLAN_VENDOR_PHY_MODE_11A = 3, + QCA_WLAN_VENDOR_PHY_MODE_11B = 4, + QCA_WLAN_VENDOR_PHY_MODE_11G = 5, + QCA_WLAN_VENDOR_PHY_MODE_11AGN = 6, + QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20 = 7, + QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS = 8, + QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS = 9, + QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40 = 10, + QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20 = 11, + QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS = 12, + QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS = 13, + QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40 = 14, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20 = 15, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS = 16, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS = 17, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40 = 18, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80 = 19, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80 = 20, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160 = 21, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20 = 22, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40 = 23, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS = 24, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS = 25, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80 = 26, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80 = 27, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160 = 28, +}; + /* Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION */ From 82867456e94b843e94d918a5ed43814514e40998 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Fri, 24 Apr 2020 13:15:34 -0700 Subject: [PATCH 0557/1105] Vendor attributes to configure PMF protection and disassoc Tx for testing Add new QCA vendor attributes to configure misbehavior for PMF protection for Management frames and to inject Disassociation frames. These attributes are used for testing purposes. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index a6fbfa660..312fcf70a 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7204,6 +7204,18 @@ enum qca_wlan_vendor_attr_wifi_test_config { */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT = 37, + /* 8-bit unsigned value to configure protection for Management + * frames when PMF is enabled for the association. + * This attribute is used to configure the testbed device. + * 0-use the correct key, 1-use an incorrect key, 2-disable protection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION = 38, + + /* Flag attribute to inject Disassociation frame to the connected AP. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX = 39, + /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX = From f7a904a283861425e3be16368b75c8a6731e4c5a Mon Sep 17 00:00:00 2001 From: Min Liu Date: Mon, 13 Apr 2020 21:36:48 +0800 Subject: [PATCH 0558/1105] QCA vendor command for adding and deleting TSPEC Add a QCA vendor subcommand QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC to add and delete TSPEC in STA mode. The attributes defined in enum qca_wlan_vendor_attr_config_tspec are used to encapsulate required information. Signed-off-by: Min Liu --- src/common/qca-vendor.h | 175 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 312fcf70a..50b6938d9 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -646,6 +646,12 @@ enum qca_radiotap_vendor_ids { * code immediately prior to triggering cfg80211_disconnected(). The * attributes used with this event are defined in enum * qca_wlan_vendor_attr_driver_disconnect_reason. + * + * @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC: This vendor subcommand is used to + * add/delete TSPEC for each AC. One command is for one specific AC only. + * This command can only be used in STA mode and the STA must be + * associated with an AP when the command is issued. Uses attributes + * defined in enum qca_wlan_vendor_attr_config_tspec. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -825,6 +831,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT = 187, QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO = 188, QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON = 189, + QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC = 190, }; enum qca_wlan_vendor_attr { @@ -8927,4 +8934,172 @@ enum qca_wlan_vendor_attr_driver_disconnect_reason { QCA_WLAN_VENDOR_ATTR_DRIVER_DISCONNECT_REASON_AFTER_LAST - 1, }; +/** + * enum qca_wlan_tspec_operation - Operation of the config TSPEC request + * + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION. + */ +enum qca_wlan_tspec_operation { + QCA_WLAN_TSPEC_ADD = 0, + QCA_WLAN_TSPEC_DEL = 1, + QCA_WLAN_TSPEC_GET = 2, +}; + +/** + * enum qca_wlan_tspec_direction - Direction in TSPEC + * As what is defined in IEEE Std 802.11-2016, Table 9-139. + * + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION. + */ +enum qca_wlan_tspec_direction { + QCA_WLAN_TSPEC_DIRECTION_UPLINK = 0, + QCA_WLAN_TSPEC_DIRECTION_DOWNLINK = 1, + QCA_WLAN_TSPEC_DIRECTION_DIRECT = 2, + QCA_WLAN_TSPEC_DIRECTION_BOTH = 3, +}; + +/** + * enum qca_wlan_tspec_ack_policy - MAC acknowledgement policy in TSPEC + * As what is defined in IEEE Std 802.11-201, Table 9-141. + * + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY. + */ +enum qca_wlan_tspec_ack_policy { + QCA_WLAN_TSPEC_NORMAL_ACK = 0, + QCA_WLAN_TSPEC_NO_ACK = 1, + /* Reserved */ + QCA_WLAN_TSPEC_BLOCK_ACK = 3, +}; + +/** + * enum qca_wlan_vendor_attr_config_tspec - Defines attributes + * used by %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC vendor command. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION: + * u8 attribute. Specify the TSPEC operation of this request. Possible values + * are defined in enum qca_wlan_tspec_operation. + * Mandatory attribute for all kinds of config TSPEC requests. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_TSID: + * u8 attribute. TS ID. Possible values are 0-7. + * Applicable for operation: QCA_WLAN_TSPEC_ADD, QCA_WLAN_TSPEC_DEL, + * QCA_WLAN_TSPEC_GET. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION: + * u8 attribute. Direction of data carried by the TS. Possible values are + * defined in enum qca_wlan_tspec_direction. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_APSD: + * Flag attribute. Indicate whether APSD is enabled for the traffic associated + * with the TS. set - enabled, not set - disabled. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_USER_PRIORITY: + * u8 attribute. User priority to be used for the transport of MSDUs/A-MSDUs + * belonging to this TS. Possible values are 0-7. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY: + * u8 attribute. Indicate whether MAC acknowledgements are required for + * MPDUs/A-MSDUs belonging to this TS and the form of those acknowledgements. + * Possible values are defined in enum qca_wlan_tspec_ack_policy. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_NOMINAL_MSDU_SIZE: + * u16 attribute. Specify the nominal size in bytes of MSDUs/A-MSDUs + * belonging to this TS. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAXIMUM_MSDU_SIZE: + * u16 attribute. Specify the maximum size in bytes of MSDUs/A-MSDUs + * belonging to this TS. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MIN_SERVICE_INTERVAL: + * u32 attribute. Specify the minimum interval in microseconds between the + * start of two successive SPs. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX_SERVICE_INTERVAL: + * u32 attribute. Specify the maximum interval in microseconds between the + * start of two successive SPs. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INACTIVITY_INTERVAL: + * u32 attribute. Specify the minimum interval in microseconds that can elapse + * without arrival or transfer of an MPDU belonging to the TS before this TS + * is deleted by the MAC entity at the HC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SUSPENSION_INTERVAL: + * u32 attribute. Specify the minimum interval in microseconds that can elapse + * without arrival or transfer of an MSDU belonging to the TS before the + * generation of successive QoS(+)CF-Poll is stopped for this TS. A value of + * 0xFFFFFFFF disables the suspension interval. The value of the suspension + * interval is always less than or equal to the inactivity interval. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_DATA_RATE: + * u32 attribute. Indicate the lowest data rate in bps specified at the MAC + * SAP for transport of MSDUs or A-MSDUs belonging to this TS within the + * bounds of this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MEAN_DATA_RATE: + * u32 attribute. Indicate the average data rate in bps specified at the MAC + * SAP for transport of MSDUs or A-MSDUs belonging to this TS within the + * bounds of this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_PEAK_DATA_RATE: + * u32 attribute. Indicate the maximum allowable data rate in bps specified at + * the MAC SAP for transport of MSDUs or A-MSDUs belonging to this TS within + * the bounds of this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_BURST_SIZE: + * u32 attribute. Specify the maximum burst size in bytes of the MSDUs/A-MSDUs + * belonging to this TS that arrive at the MAC SAP at the peak data rate. A + * value of 0 indicates that there are no bursts. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_PHY_RATE: + * u32 attribute. Indicate the minimum PHY rate in bps for transport of + * MSDUs/A-MSDUs belonging to this TS within the bounds of this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SURPLUS_BANDWIDTH_ALLOWANCE: + * u16 attribute. Specify the excess allocation of time (and bandwidth) over + * and above the stated application rates required to transport an MSDU/A-MSDU + * belonging to the TS in this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + */ +enum qca_wlan_vendor_attr_config_tspec { + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION = 1, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_TSID = 2, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION = 3, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_APSD = 4, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_USER_PRIORITY = 5, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY = 6, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_NOMINAL_MSDU_SIZE = 7, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAXIMUM_MSDU_SIZE = 8, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MIN_SERVICE_INTERVAL = 9, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX_SERVICE_INTERVAL = 10, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INACTIVITY_INTERVAL = 11, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SUSPENSION_INTERVAL = 12, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_DATA_RATE = 13, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MEAN_DATA_RATE = 14, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_PEAK_DATA_RATE = 15, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_BURST_SIZE = 16, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_PHY_RATE = 17, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SURPLUS_BANDWIDTH_ALLOWANCE = 18, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX = + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_AFTER_LAST - 1, +}; + #endif /* QCA_VENDOR_H */ From 5ab8ad4cfec2937df332d29416b9bd0ff162623b Mon Sep 17 00:00:00 2001 From: Min Liu Date: Thu, 7 May 2020 16:20:10 +0800 Subject: [PATCH 0559/1105] Vendor attributes for ssetting TX A-MSDU and RX A-MSDU parameters Define QCA vendor attributes for SET(GET)_WIFI_CONFIGURATION to dynamically configure capabilities for TX A-MSDU and RX A-MSDU. Signed-off-by: Min Liu --- src/common/qca-vendor.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 50b6938d9..bb133e1c4 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2135,6 +2135,18 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE = 62, + /* 8-bit unsigned value to configure the maximum number of subframes of + * TX MSDU for aggregation. Possible values are 0-31. When set to 0, + * it is decided by the hardware. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION = 65, + + /* 8-bit unsigned value to configure the maximum number of subframes of + * RX MSDU for aggregation. Possible values are 0-31. When set to 0, + * it is decided by the hardware. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION = 66, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = From 7cd17a4b5ebda3e36999d8e1b4e6fc7a539415fe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 23 May 2020 21:11:33 +0300 Subject: [PATCH 0560/1105] wlantest: Handle FT over-the-DS association state update cleanly It is expected for the STA entry on the target AP to move directly from State 1 to State 3 when performing FT over-the-DS (i.e., FT Action Request/Response frame exchange through the old AP followed by Reassociation Request/Response frame exchange with the target AP). Signed-off-by: Jouni Malinen --- wlantest/rx_mgmt.c | 5 +++-- wlantest/wlantest.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index ad388e122..62ed237b7 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -1,6 +1,6 @@ /* * Received Management frame processing - * Copyright (c) 2010-2015, Jouni Malinen + * Copyright (c) 2010-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -965,7 +965,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, } sta->aid = aid & 0xc000; - if (sta->state < STATE2) { + if (sta->state < STATE2 && !sta->ft_over_ds) { add_note(wt, MSG_DEBUG, "STA " MACSTR " was not in State 2 when " "getting associated", MAC2STR(sta->addr)); @@ -1110,6 +1110,7 @@ static void rx_mgmt_action_ft_request(struct wlantest *wt, if (!sta) return; + sta->ft_over_ds = true; sta->key_mgmt = parse.key_mgmt; sta->pairwise_cipher = parse.pairwise_cipher; } diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index e2395d033..2c2712de8 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -1,6 +1,6 @@ /* * wlantest - IEEE 802.11 protocol monitoring and testing tool - * Copyright (c) 2010-2019, Jouni Malinen + * Copyright (c) 2010-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -61,6 +61,7 @@ struct wlantest_sta { STATE3 /* associated */ } state; u16 auth_alg; + bool ft_over_ds; u16 aid; u8 rsnie[257]; /* WPA/RSN IE */ u8 osenie[257]; /* OSEN IE */ From bfc4569f89183c86b2ac3b0a16245a5e13387852 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 23 May 2020 21:24:01 +0300 Subject: [PATCH 0561/1105] wlantest: Store PMK-R0 length explicitly PMK-R0 is not of fixed length, so store its length explicitly. Signed-off-by: Jouni Malinen --- wlantest/rx_eapol.c | 14 +++++++++----- wlantest/rx_mgmt.c | 10 ++++++---- wlantest/wlantest.h | 3 ++- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 1cfdf8e9e..c80837ba7 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -1,6 +1,6 @@ /* * Received Data frame processing for EAPOL messages - * Copyright (c) 2010-2015, Jouni Malinen + * Copyright (c) 2010-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -103,17 +103,21 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss, u8 pmk_r1[PMK_LEN]; u8 pmk_r1_name[WPA_PMK_NAME_LEN]; u8 ptk_name[WPA_PMK_NAME_LEN]; + int use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); - if (wpa_derive_pmk_r0(pmk->pmk, PMK_LEN, + if (wpa_derive_pmk_r0(pmk->pmk, pmk->pmk_len, bss->ssid, bss->ssid_len, bss->mdid, bss->r0kh_id, bss->r0kh_id_len, sta->addr, sta->pmk_r0, sta->pmk_r0_name, - 0) < 0) + use_sha384) < 0) return -1; - wpa_hexdump(MSG_DEBUG, "FT: PMK-R0", sta->pmk_r0, PMK_LEN); + sta->pmk_r0_len = use_sha384 ? PMK_LEN_SUITE_B_192 : PMK_LEN; + wpa_hexdump(MSG_DEBUG, "FT: PMK-R0", sta->pmk_r0, + sta->pmk_r0_len); wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", sta->pmk_r0_name, WPA_PMK_NAME_LEN); - if (wpa_derive_pmk_r1(sta->pmk_r0, PMK_LEN, sta->pmk_r0_name, + if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, + sta->pmk_r0_name, bss->r1kh_id, sta->addr, pmk_r1, pmk_r1_name) < 0) return -1; diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 62ed237b7..a2183a12f 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -274,14 +274,15 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, if (!old_sta) return; - os_memcpy(sta->pmk_r0, old_sta->pmk_r0, sizeof(sta->pmk_r0)); + os_memcpy(sta->pmk_r0, old_sta->pmk_r0, old_sta->pmk_r0_len); + sta->pmk_r0_len = old_sta->pmk_r0_len; os_memcpy(sta->pmk_r0_name, old_sta->pmk_r0_name, sizeof(sta->pmk_r0_name)); if (parse.r1kh_id) os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); - if (wpa_derive_pmk_r1(sta->pmk_r0, PMK_LEN, sta->pmk_r0_name, + if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, bss->r1kh_id, sta->addr, pmk_r1, pmk_r1_name) < 0) return; wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); @@ -1161,7 +1162,7 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, if (parse.r1kh_id) os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); - if (wpa_derive_pmk_r1(sta->pmk_r0, PMK_LEN, sta->pmk_r0_name, + if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, bss->r1kh_id, sta->addr, pmk_r1, pmk_r1_name) < 0) return; wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); @@ -1169,7 +1170,8 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, new_sta = sta_get(bss, sta->addr); if (!new_sta) return; - os_memcpy(new_sta->pmk_r0, sta->pmk_r0, sizeof(sta->pmk_r0)); + os_memcpy(new_sta->pmk_r0, sta->pmk_r0, sta->pmk_r0_len); + new_sta->pmk_r0_len = sta->pmk_r0_len; os_memcpy(new_sta->pmk_r0_name, sta->pmk_r0_name, sizeof(sta->pmk_r0_name)); if (!parse.fte_anonce || !parse.fte_snonce || diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 2c2712de8..4de2fe56b 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -72,7 +72,8 @@ struct wlantest_sta { int rsn_capab; u8 anonce[32]; /* ANonce from the previous EAPOL-Key msg 1/4 or 3/4 */ u8 snonce[32]; /* SNonce from the previous EAPOL-Key msg 2/4 */ - u8 pmk_r0[PMK_LEN]; + u8 pmk_r0[PMK_LEN_MAX]; + size_t pmk_r0_len; u8 pmk_r0_name[WPA_PMK_NAME_LEN]; struct wpa_ptk ptk; /* Derived PTK */ int ptk_set; From d9532eb70fc25cb8025c4772ad944b644369eade Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 23 May 2020 21:42:45 +0300 Subject: [PATCH 0562/1105] Debug print PMK-R0/R1 and PMKR0/R1Name in the helper functions There is no need to have all callers debug print these separately. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 5 ----- src/ap/wpa_auth_ft.c | 14 +------------- src/common/wpa_common.c | 6 ++++-- src/rsn_supp/wpa.c | 6 ------ src/rsn_supp/wpa_ft.c | 9 --------- 5 files changed, 5 insertions(+), 35 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 019e5357e..8e21ee2c4 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2322,7 +2322,6 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_auth_config *conf = &wpa_auth->conf; u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN]; int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); - size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; if (wpa_derive_pmk_r0(fils_ft, fils_ft_len, conf->ssid, conf->ssid_len, @@ -2333,10 +2332,6 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, use_sha384) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", - pmk_r0, pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", - pmk_r0_name, WPA_PMK_NAME_LEN); wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name); forced_memzero(fils_ft, sizeof(fils_ft)); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 5af65aad8..d9a92e15f 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2128,8 +2128,6 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk) pmk_r0, pmk_r0_name, wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len, pmk_r0_name, @@ -2140,9 +2138,6 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk) if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr, pmk_r1, sm->pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, - WPA_PMK_NAME_LEN); if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len, sm->pmk_r1_name, sm->pairwise, &vlan, @@ -2961,8 +2956,6 @@ static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth, conf->r1_key_holder, sm->addr, out_pmk_r1, pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", out_pmk_r1, r0->pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); os_get_reltime(&now); if (r0->expiration) @@ -3091,8 +3084,6 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, sm->wpa_auth->conf.r1_key_holder, sm->addr, pmk_r1_name, use_sha384) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; - wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name", - pmk_r1_name, WPA_PMK_NAME_LEN); if (conf->ft_psk_generate_local && wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { @@ -3699,14 +3690,11 @@ static int wpa_ft_rrb_build_r0(const u8 *key, const size_t key_len, { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL }, }; + wpa_printf(MSG_DEBUG, "FT: Derive PMK-R1 for peer AP"); if (wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_len, pmk_r0->pmk_r0_name, r1kh_id, s1kh_id, pmk_r1, pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 (for peer AP)", - pmk_r1, pmk_r1_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name (for peer AP)", - pmk_r1_name, WPA_PMK_NAME_LEN); WPA_PUT_LE16(f_pairwise, pmk_r0->pairwise); os_get_reltime(&now); diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 1e7498a9e..82a5a174f 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -1633,7 +1633,8 @@ int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, if (!use_sha384 && sha256_vector(2, addr, len, hash) < 0) return -1; os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); - os_memset(r0_key_data, 0, sizeof(r0_key_data)); + wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); + forced_memzero(r0_key_data, sizeof(r0_key_data)); return 0; } @@ -1670,6 +1671,7 @@ int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, if (!use_sha384 && sha256_vector(4, addr, len, hash) < 0) return -1; os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); return 0; } @@ -1839,7 +1841,7 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len, wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len); wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - os_memset(tmp, 0, sizeof(tmp)); + forced_memzero(tmp, sizeof(tmp)); return 0; } diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index a9e2e2474..28d417608 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -4430,10 +4430,6 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) return -1; } sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; - wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", - sm->pmk_r0, sm->pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", - sm->pmk_r0_name, WPA_PMK_NAME_LEN); wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR, MAC2STR(sm->r1kh_id)); pos = wpabuf_put(buf, WPA_PMK_NAME_LEN); @@ -4442,8 +4438,6 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMKR1Name"); return -1; } - wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name, - WPA_PMK_NAME_LEN); os_memcpy(pos, sm->pmk_r1_name, WPA_PMK_NAME_LEN); if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 3e51cf2a1..63a4175ab 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -50,17 +50,11 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, sm->pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", - sm->pmk_r0_name, WPA_PMK_NAME_LEN); sm->pmk_r1_len = sm->pmk_r0_len; if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name, sm->r1kh_id, sm->own_addr, sm->pmk_r1, sm->pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, sm->pmk_r1_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, - WPA_PMK_NAME_LEN); return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, anonce, sm->own_addr, sm->bssid, sm->pmk_r1_name, ptk, ptk_name, sm->key_mgmt, sm->pairwise_cipher); @@ -641,9 +635,6 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, sm->pmk_r1_name) < 0) return -1; sm->pmk_r1_len = sm->pmk_r0_len; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, sm->pmk_r1_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", - sm->pmk_r1_name, WPA_PMK_NAME_LEN); bssid = target_ap; if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, From 59d9994ac733ce441fe0c133183c46ba2ab1e3d3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 23 May 2020 21:43:36 +0300 Subject: [PATCH 0563/1105] wlantest: Store PMK-R1 in STA entry Signed-off-by: Jouni Malinen --- wlantest/rx_eapol.c | 20 ++++++-------------- wlantest/rx_mgmt.c | 28 +++++++++++++++------------- wlantest/wlantest.h | 3 +++ 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index c80837ba7..4dff7f8dd 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -100,8 +100,6 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss, struct wpa_ptk ptk; if (wpa_key_mgmt_ft(sta->key_mgmt)) { - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; u8 ptk_name[WPA_PMK_NAME_LEN]; int use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); @@ -112,22 +110,16 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss, use_sha384) < 0) return -1; sta->pmk_r0_len = use_sha384 ? PMK_LEN_SUITE_B_192 : PMK_LEN; - wpa_hexdump(MSG_DEBUG, "FT: PMK-R0", sta->pmk_r0, - sta->pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", sta->pmk_r0_name, - WPA_PMK_NAME_LEN); if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, bss->r1kh_id, sta->addr, - pmk_r1, pmk_r1_name) < 0) + sta->pmk_r1, sta->pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, - WPA_PMK_NAME_LEN); - if (wpa_pmk_r1_to_ptk(pmk_r1, PMK_LEN, sta->snonce, sta->anonce, - sta->addr, - bss->bssid, pmk_r1_name, &ptk, ptk_name, - sta->key_mgmt, + sta->pmk_r1_len = sta->pmk_r0_len; + if (wpa_pmk_r1_to_ptk(sta->pmk_r1, sta->pmk_r1_len, + sta->snonce, sta->anonce, sta->addr, + bss->bssid, sta->pmk_r1_name, + &ptk, ptk_name, sta->key_mgmt, sta->pairwise_cipher) < 0 || check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data, len) < 0) diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index a2183a12f..5eb32f1da 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -232,8 +232,6 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, { u16 trans; struct wpa_ft_ies parse; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; struct wpa_ptk ptk; u8 ptk_name[WPA_PMK_NAME_LEN]; struct wlantest_bss *old_bss; @@ -283,14 +281,15 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, - bss->r1kh_id, sta->addr, pmk_r1, pmk_r1_name) < 0) + bss->r1kh_id, sta->addr, sta->pmk_r1, + sta->pmk_r1_name) < 0) return; - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); + sta->pmk_r1_len = sta->pmk_r0_len; if (!parse.fte_anonce || !parse.fte_snonce || - wpa_pmk_r1_to_ptk(pmk_r1, PMK_LEN, parse.fte_snonce, + wpa_pmk_r1_to_ptk(sta->pmk_r1, sta->pmk_r1_len, parse.fte_snonce, parse.fte_anonce, sta->addr, bss->bssid, - pmk_r1_name, &ptk, ptk_name, sta->key_mgmt, + sta->pmk_r1_name, &ptk, ptk_name, sta->key_mgmt, sta->pairwise_cipher) < 0) return; @@ -1127,8 +1126,6 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, const u8 *ies; size_t ies_len; struct wpa_ft_ies parse; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; struct wpa_ptk ptk; u8 ptk_name[WPA_PMK_NAME_LEN]; @@ -1163,9 +1160,10 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, - bss->r1kh_id, sta->addr, pmk_r1, pmk_r1_name) < 0) + bss->r1kh_id, sta->addr, sta->pmk_r1, + sta->pmk_r1_name) < 0) return; - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); + sta->pmk_r1_len = sta->pmk_r0_len; new_sta = sta_get(bss, sta->addr); if (!new_sta) @@ -1174,11 +1172,15 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, new_sta->pmk_r0_len = sta->pmk_r0_len; os_memcpy(new_sta->pmk_r0_name, sta->pmk_r0_name, sizeof(sta->pmk_r0_name)); + os_memcpy(new_sta->pmk_r1, sta->pmk_r1, sta->pmk_r1_len); + new_sta->pmk_r1_len = sta->pmk_r1_len; + os_memcpy(new_sta->pmk_r1_name, sta->pmk_r1_name, + sizeof(sta->pmk_r1_name)); if (!parse.fte_anonce || !parse.fte_snonce || - wpa_pmk_r1_to_ptk(pmk_r1, PMK_LEN, parse.fte_snonce, + wpa_pmk_r1_to_ptk(sta->pmk_r1, sta->pmk_r1_len, parse.fte_snonce, parse.fte_anonce, new_sta->addr, bss->bssid, - pmk_r1_name, &ptk, ptk_name, new_sta->key_mgmt, - new_sta->pairwise_cipher) < 0) + sta->pmk_r1_name, &ptk, ptk_name, + new_sta->key_mgmt, new_sta->pairwise_cipher) < 0) return; add_note(wt, MSG_DEBUG, "Derived new PTK"); diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 4de2fe56b..f7fcd8440 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -75,6 +75,9 @@ struct wlantest_sta { u8 pmk_r0[PMK_LEN_MAX]; size_t pmk_r0_len; u8 pmk_r0_name[WPA_PMK_NAME_LEN]; + u8 pmk_r1[PMK_LEN_MAX]; + size_t pmk_r1_len; + u8 pmk_r1_name[WPA_PMK_NAME_LEN]; struct wpa_ptk ptk; /* Derived PTK */ int ptk_set; struct wpa_ptk tptk; /* Derived PTK during rekeying */ From e10144c910cadbb298de797e9062b3f886d0e0c1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 23 May 2020 21:44:16 +0300 Subject: [PATCH 0564/1105] wlantest: Validate FT elements in Reassociation Request frame Verify that RSNE, MDE, and FTE have valid information in FT Reassociation Request frames. Signed-off-by: Jouni Malinen --- wlantest/rx_mgmt.c | 176 +++++++++++++++++++++++++++++++++++++++++++- wlantest/wlantest.h | 8 +- 2 files changed, 180 insertions(+), 4 deletions(-) diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 5eb32f1da..b9632474f 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -879,7 +879,179 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, sta->assocreq_seen = 1; sta_update_assoc(sta, &elems); - /* TODO: FT protocol: verify FTE MIC and update GTK/IGTK for the BSS */ + if (elems.ftie) { + struct wpa_ft_ies parse; + int use_sha384; + struct rsn_mdie *mde; + const u8 *anonce, *snonce, *fte_mic; + u8 fte_elem_count; + unsigned int count; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; + const u8 *kck; + size_t kck_len; + + use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); + + if (wpa_ft_parse_ies(ie, ie_len, &parse, use_sha384) < 0) { + add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs"); + return; + } + + if (!parse.rsn) { + add_note(wt, MSG_INFO, "FT: No RSNE in Reassoc Req"); + return; + } + + if (!parse.rsn_pmkid) { + add_note(wt, MSG_INFO, "FT: No PMKID in RSNE"); + return; + } + + if (os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + add_note(wt, MSG_INFO, + "FT: PMKID in Reassoc Req did not match PMKR1Name"); + wpa_hexdump(MSG_DEBUG, + "FT: Received RSNE[PMKR1Name]", + parse.rsn_pmkid, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, + "FT: Previously derived PMKR1Name", + sta->pmk_r1_name, WPA_PMK_NAME_LEN); + return; + } + + mde = (struct rsn_mdie *) parse.mdie; + if (!mde || parse.mdie_len < sizeof(*mde) || + os_memcmp(mde->mobility_domain, bss->mdid, + MOBILITY_DOMAIN_ID_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: Invalid MDE"); + } + + if (use_sha384) { + struct rsn_ftie_sha384 *fte; + + fte = (struct rsn_ftie_sha384 *) parse.ftie; + if (!fte || parse.ftie_len < sizeof(*fte)) { + add_note(wt, MSG_INFO, "FT: Invalid FTE"); + return; + } + + anonce = fte->anonce; + snonce = fte->snonce; + fte_elem_count = fte->mic_control[1]; + fte_mic = fte->mic; + } else { + struct rsn_ftie *fte; + + fte = (struct rsn_ftie *) parse.ftie; + if (!fte || parse.ftie_len < sizeof(*fte)) { + add_note(wt, MSG_INFO, "FT: Invalid FTIE"); + return; + } + + anonce = fte->anonce; + snonce = fte->snonce; + fte_elem_count = fte->mic_control[1]; + fte_mic = fte->mic; + } + + if (os_memcmp(snonce, sta->snonce, WPA_NONCE_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: SNonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", + snonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", + sta->snonce, WPA_NONCE_LEN); + return; + } + + if (os_memcmp(anonce, sta->anonce, WPA_NONCE_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: ANonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", + anonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", + sta->anonce, WPA_NONCE_LEN); + return; + } + + if (!parse.r0kh_id) { + add_note(wt, MSG_INFO, "FT: No R0KH-ID subelem in FTE"); + return; + } + os_memcpy(bss->r0kh_id, parse.r0kh_id, parse.r0kh_id_len); + bss->r0kh_id_len = parse.r0kh_id_len; + + if (!parse.r1kh_id) { + add_note(wt, MSG_INFO, "FT: No R1KH-ID subelem in FTE"); + return; + } + + os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); + + if (!parse.rsn_pmkid || + os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name, + WPA_PMK_NAME_LEN)) { + add_note(wt, MSG_INFO, + "FT: No matching PMKR1Name (PMKID) in RSNE (pmkid=%d)", + !!parse.rsn_pmkid); + return; + } + + count = 3; + if (parse.ric) + count += ieee802_11_ie_count(parse.ric, parse.ric_len); + if (parse.rsnxe) + count++; + if (fte_elem_count != count) { + add_note(wt, MSG_INFO, + "FT: Unexpected IE count in MIC Control: received %u expected %u", + fte_elem_count, count); + return; + } + + if (wpa_key_mgmt_fils(sta->key_mgmt)) { + kck = sta->ptk.kck2; + kck_len = sta->ptk.kck2_len; + } else { + kck = sta->ptk.kck; + kck_len = sta->ptk.kck_len; + } + if (wpa_ft_mic(kck, kck_len, sta->addr, bss->bssid, 5, + parse.mdie - 2, parse.mdie_len + 2, + parse.ftie - 2, parse.ftie_len + 2, + parse.rsn - 2, parse.rsn_len + 2, + parse.ric, parse.ric_len, + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0, + mic) < 0) { + add_note(wt, MSG_INFO, "FT: Failed to calculate MIC"); + return; + } + + if (os_memcmp_const(mic, fte_mic, mic_len) != 0) { + add_note(wt, MSG_INFO, "FT: Invalid MIC in FTE"); + wpa_printf(MSG_DEBUG, + "FT: addr=" MACSTR " auth_addr=" MACSTR, + MAC2STR(sta->addr), + MAC2STR(bss->bssid)); + wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", + fte_mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", + mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: MDE", + parse.mdie - 2, parse.mdie_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: FTE", + parse.ftie - 2, parse.ftie_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: RSN", + parse.rsn - 2, parse.rsn_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE", + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0); + return; + } + + add_note(wt, MSG_INFO, "FT: Valid FTE MIC"); + } } @@ -1188,6 +1360,8 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, new_sta->ptk_set = 1; os_memset(new_sta->rsc_tods, 0, sizeof(new_sta->rsc_tods)); os_memset(new_sta->rsc_fromds, 0, sizeof(new_sta->rsc_fromds)); + os_memcpy(new_sta->snonce, parse.fte_snonce, WPA_NONCE_LEN); + os_memcpy(new_sta->anonce, parse.fte_anonce, WPA_NONCE_LEN); } diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index f7fcd8440..0c266f4e9 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -70,8 +70,10 @@ struct wlantest_sta { int group_cipher; int key_mgmt; int rsn_capab; - u8 anonce[32]; /* ANonce from the previous EAPOL-Key msg 1/4 or 3/4 */ - u8 snonce[32]; /* SNonce from the previous EAPOL-Key msg 2/4 */ + /* ANonce from the previous EAPOL-Key msg 1/4 or 3/4 */ + u8 anonce[WPA_NONCE_LEN]; + /* SNonce from the previous EAPOL-Key msg 2/4 */ + u8 snonce[WPA_NONCE_LEN]; u8 pmk_r0[PMK_LEN_MAX]; size_t pmk_r0_len; u8 pmk_r0_name[WPA_PMK_NAME_LEN]; @@ -164,7 +166,7 @@ struct wlantest_bss { int bigtk_idx; u32 counters[NUM_WLANTEST_BSS_COUNTER]; struct dl_list tdls; /* struct wlantest_tdls */ - u8 mdid[2]; + u8 mdid[MOBILITY_DOMAIN_ID_LEN]; u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; size_t r0kh_id_len; u8 r1kh_id[FT_R1KH_ID_LEN]; From b6a3bcffd76b598ae44299f0a5860b9b82f2d99f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 24 May 2020 00:35:13 +0300 Subject: [PATCH 0565/1105] wlantest: Validate FT elements in Reassociation Response frame Verify that RSNE, MDE, and FTE have valid information in FT Reassociation Response frames. In addition, decrypt GTK, IGTK, and BIGTK from the frame. Signed-off-by: Jouni Malinen --- wlantest/rx_mgmt.c | 447 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 437 insertions(+), 10 deletions(-) diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index b9632474f..0bc7eb2b2 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -1055,6 +1055,228 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, } +static void process_gtk_subelem(struct wlantest *wt, struct wlantest_bss *bss, + struct wlantest_sta *sta, + const u8 *kek, size_t kek_len, + const u8 *gtk_elem, + size_t gtk_elem_len) +{ + u8 gtk[32]; + int keyidx; + enum wpa_alg alg; + size_t gtk_len, keylen; + const u8 *rsc; + + if (!gtk_elem) { + add_note(wt, MSG_INFO, "FT: No GTK included in FTE"); + return; + } + + wpa_hexdump(MSG_DEBUG, "FT: Received GTK in Reassoc Resp", + gtk_elem, gtk_elem_len); + + if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 || + gtk_elem_len - 19 > sizeof(gtk)) { + add_note(wt, MSG_INFO, "FT: Invalid GTK sub-elem length %zu", + gtk_elem_len); + return; + } + gtk_len = gtk_elem_len - 19; + if (aes_unwrap(kek, kek_len, gtk_len / 8, gtk_elem + 11, gtk)) { + add_note(wt, MSG_INFO, + "FT: AES unwrap failed - could not decrypt GTK"); + return; + } + + keylen = wpa_cipher_key_len(bss->group_cipher); + alg = wpa_cipher_to_alg(bss->group_cipher); + if (alg == WPA_ALG_NONE) { + add_note(wt, MSG_INFO, "FT: Unsupported Group Cipher %d", + bss->group_cipher); + return; + } + + if (gtk_len < keylen) { + add_note(wt, MSG_INFO, "FT: Too short GTK in FTE"); + return; + } + + /* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */ + + keyidx = WPA_GET_LE16(gtk_elem) & 0x03; + + if (gtk_elem[2] != keylen) { + add_note(wt, MSG_INFO, + "FT: GTK length mismatch: received %u negotiated %zu", + gtk_elem[2], keylen); + return; + } + + add_note(wt, MSG_DEBUG, "GTK KeyID=%u", keyidx); + wpa_hexdump(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen); + if (bss->group_cipher == WPA_CIPHER_TKIP) { + /* Swap Tx/Rx keys for Michael MIC */ + u8 tmp[8]; + + os_memcpy(tmp, gtk + 16, 8); + os_memcpy(gtk + 16, gtk + 24, 8); + os_memcpy(gtk + 24, tmp, 8); + } + + bss->gtk_len[keyidx] = gtk_len; + sta->gtk_len = gtk_len; + os_memcpy(bss->gtk[keyidx], gtk, gtk_len); + os_memcpy(sta->gtk, gtk, gtk_len); + rsc = gtk_elem + 2; + bss->rsc[keyidx][0] = rsc[5]; + bss->rsc[keyidx][1] = rsc[4]; + bss->rsc[keyidx][2] = rsc[3]; + bss->rsc[keyidx][3] = rsc[2]; + bss->rsc[keyidx][4] = rsc[1]; + bss->rsc[keyidx][5] = rsc[0]; + bss->gtk_idx = keyidx; + sta->gtk_idx = keyidx; + wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[keyidx], 6); +} + + +static void process_igtk_subelem(struct wlantest *wt, struct wlantest_bss *bss, + struct wlantest_sta *sta, + const u8 *kek, size_t kek_len, + const u8 *igtk_elem, size_t igtk_elem_len) +{ + u8 igtk[WPA_IGTK_MAX_LEN]; + size_t igtk_len; + u16 keyidx; + const u8 *ipn; + + if (bss->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256) + return; + + if (!igtk_elem) { + add_note(wt, MSG_INFO, "FT: No IGTK included in FTE"); + return; + } + + wpa_hexdump(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp", + igtk_elem, igtk_elem_len); + + igtk_len = wpa_cipher_key_len(bss->mgmt_group_cipher); + if (igtk_elem_len != 2 + 6 + 1 + igtk_len + 8) { + add_note(wt, MSG_INFO, "FT: Invalid IGTK sub-elem length %zu", + igtk_elem_len); + return; + } + if (igtk_elem[8] != igtk_len) { + add_note(wt, MSG_INFO, + "FT: Invalid IGTK sub-elem Key Length %d", + igtk_elem[8]); + return; + } + + if (aes_unwrap(kek, kek_len, igtk_len / 8, igtk_elem + 9, igtk)) { + add_note(wt, MSG_INFO, + "FT: AES unwrap failed - could not decrypt IGTK"); + return; + } + + /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ + + keyidx = WPA_GET_LE16(igtk_elem); + + wpa_hexdump(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk, igtk_len); + + if (keyidx < 4 || keyidx > 5) { + add_note(wt, MSG_INFO, "Unexpected IGTK KeyID %u", keyidx); + return; + } + + add_note(wt, MSG_DEBUG, "IGTK KeyID %u", keyidx); + wpa_hexdump(MSG_DEBUG, "IPN", igtk_elem + 2, 6); + wpa_hexdump(MSG_DEBUG, "IGTK", igtk, igtk_len); + os_memcpy(bss->igtk[keyidx], igtk, igtk_len); + bss->igtk_len[keyidx] = igtk_len; + ipn = igtk_elem + 2; + bss->ipn[keyidx][0] = ipn[5]; + bss->ipn[keyidx][1] = ipn[4]; + bss->ipn[keyidx][2] = ipn[3]; + bss->ipn[keyidx][3] = ipn[2]; + bss->ipn[keyidx][4] = ipn[1]; + bss->ipn[keyidx][5] = ipn[0]; + bss->igtk_idx = keyidx; +} + + +static void process_bigtk_subelem(struct wlantest *wt, struct wlantest_bss *bss, + struct wlantest_sta *sta, + const u8 *kek, size_t kek_len, + const u8 *bigtk_elem, size_t bigtk_elem_len) +{ + u8 bigtk[WPA_BIGTK_MAX_LEN]; + size_t bigtk_len; + u16 keyidx; + const u8 *ipn; + + if (!bigtk_elem || + (bss->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256)) + return; + + wpa_hexdump_key(MSG_DEBUG, "FT: Received BIGTK in Reassoc Resp", + bigtk_elem, bigtk_elem_len); + + bigtk_len = wpa_cipher_key_len(bss->mgmt_group_cipher); + if (bigtk_elem_len != 2 + 6 + 1 + bigtk_len + 8) { + add_note(wt, MSG_INFO, + "FT: Invalid BIGTK sub-elem length %zu", + bigtk_elem_len); + return; + } + if (bigtk_elem[8] != bigtk_len) { + add_note(wt, MSG_INFO, + "FT: Invalid BIGTK sub-elem Key Length %d", + bigtk_elem[8]); + return; + } + + if (aes_unwrap(kek, kek_len, bigtk_len / 8, bigtk_elem + 9, bigtk)) { + add_note(wt, MSG_INFO, + "FT: AES unwrap failed - could not decrypt BIGTK"); + return; + } + + /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ + + keyidx = WPA_GET_LE16(bigtk_elem); + + wpa_hexdump(MSG_DEBUG, "FT: BIGTK from Reassoc Resp", bigtk, bigtk_len); + + if (keyidx < 6 || keyidx > 7) { + add_note(wt, MSG_INFO, "Unexpected BIGTK KeyID %u", keyidx); + return; + } + + add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", keyidx); + wpa_hexdump(MSG_DEBUG, "BIPN", bigtk_elem + 2, 6); + wpa_hexdump(MSG_DEBUG, "BIGTK", bigtk, bigtk_len); + os_memcpy(bss->igtk[keyidx], bigtk, bigtk_len); + bss->igtk_len[keyidx] = bigtk_len; + ipn = bigtk_elem + 2; + bss->ipn[keyidx][0] = ipn[5]; + bss->ipn[keyidx][1] = ipn[4]; + bss->ipn[keyidx][2] = ipn[3]; + bss->ipn[keyidx][3] = ipn[2]; + bss->ipn[keyidx][4] = ipn[1]; + bss->ipn[keyidx][5] = ipn[0]; + bss->bigtk_idx = keyidx; +} + + static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, size_t len) { @@ -1064,6 +1286,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, u16 capab, status, aid; const u8 *ies; size_t ies_len; + struct ieee802_11_elems elems; mgmt = (const struct ieee80211_mgmt *) data; bss = bss_get(wt, mgmt->bssid); @@ -1106,17 +1329,15 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, } } - if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) { - struct ieee802_11_elems elems; + if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed) { + add_note(wt, MSG_INFO, + "Failed to parse IEs in ReassocResp from " MACSTR, + MAC2STR(mgmt->sa)); + } - if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == - ParseFailed) { - add_note(wt, MSG_INFO, "Failed to parse IEs in " - "ReassocResp from " MACSTR, - MAC2STR(mgmt->sa)); - } else if (elems.timeout_int == NULL || - elems.timeout_int[0] != - WLAN_TIMEOUT_ASSOC_COMEBACK) { + if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) { + if (!elems.timeout_int || + elems.timeout_int[0] != WLAN_TIMEOUT_ASSOC_COMEBACK) { add_note(wt, MSG_INFO, "No valid Timeout Interval IE " "with Assoc Comeback time in ReassocResp " "(status=30) from " MACSTR, @@ -1149,6 +1370,212 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, MAC2STR(sta->addr), MAC2STR(bss->bssid)); sta->state = STATE3; } + + if (elems.ftie) { + struct wpa_ft_ies parse; + int use_sha384; + struct rsn_mdie *mde; + const u8 *anonce, *snonce, *fte_mic; + u8 fte_elem_count; + unsigned int count; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; + const u8 *kck, *kek; + size_t kck_len, kek_len; + + use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); + + if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) { + add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs"); + return; + } + + if (!parse.rsn) { + add_note(wt, MSG_INFO, "FT: No RSNE in Reassoc Resp"); + return; + } + + if (!parse.rsn_pmkid) { + add_note(wt, MSG_INFO, "FT: No PMKID in RSNE"); + return; + } + + if (os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + add_note(wt, MSG_INFO, + "FT: PMKID in Reassoc Resp did not match PMKR1Name"); + wpa_hexdump(MSG_DEBUG, + "FT: Received RSNE[PMKR1Name]", + parse.rsn_pmkid, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, + "FT: Previously derived PMKR1Name", + sta->pmk_r1_name, WPA_PMK_NAME_LEN); + return; + } + + mde = (struct rsn_mdie *) parse.mdie; + if (!mde || parse.mdie_len < sizeof(*mde) || + os_memcmp(mde->mobility_domain, bss->mdid, + MOBILITY_DOMAIN_ID_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: Invalid MDE"); + } + + if (use_sha384) { + struct rsn_ftie_sha384 *fte; + + fte = (struct rsn_ftie_sha384 *) parse.ftie; + if (!fte || parse.ftie_len < sizeof(*fte)) { + add_note(wt, MSG_INFO, "FT: Invalid FTE"); + return; + } + + anonce = fte->anonce; + snonce = fte->snonce; + fte_elem_count = fte->mic_control[1]; + fte_mic = fte->mic; + } else { + struct rsn_ftie *fte; + + fte = (struct rsn_ftie *) parse.ftie; + if (!fte || parse.ftie_len < sizeof(*fte)) { + add_note(wt, MSG_INFO, "FT: Invalid FTIE"); + return; + } + + anonce = fte->anonce; + snonce = fte->snonce; + fte_elem_count = fte->mic_control[1]; + fte_mic = fte->mic; + } + + if (os_memcmp(snonce, sta->snonce, WPA_NONCE_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: SNonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", + snonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", + sta->snonce, WPA_NONCE_LEN); + return; + } + + if (os_memcmp(anonce, sta->anonce, WPA_NONCE_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: ANonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", + anonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", + sta->anonce, WPA_NONCE_LEN); + return; + } + + if (!parse.r0kh_id) { + add_note(wt, MSG_INFO, "FT: No R0KH-ID subelem in FTE"); + return; + } + + if (parse.r0kh_id_len != bss->r0kh_id_len || + os_memcmp_const(parse.r0kh_id, bss->r0kh_id, + parse.r0kh_id_len) != 0) { + add_note(wt, MSG_INFO, + "FT: R0KH-ID in FTE did not match the current R0KH-ID"); + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", + parse.r0kh_id, parse.r0kh_id_len); + wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", + bss->r0kh_id, bss->r0kh_id_len); + os_memcpy(bss->r0kh_id, parse.r0kh_id, + parse.r0kh_id_len); + bss->r0kh_id_len = parse.r0kh_id_len; + } + + if (!parse.r1kh_id) { + add_note(wt, MSG_INFO, "FT: No R1KH-ID subelem in FTE"); + return; + } + + if (os_memcmp_const(parse.r1kh_id, bss->r1kh_id, + FT_R1KH_ID_LEN) != 0) { + add_note(wt, MSG_INFO, + "FT: Unknown R1KH-ID used in ReassocResp"); + os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); + } + + count = 3; + if (parse.ric) + count += ieee802_11_ie_count(parse.ric, parse.ric_len); + if (parse.rsnxe) + count++; + if (fte_elem_count != count) { + add_note(wt, MSG_INFO, + "FT: Unexpected IE count in MIC Control: received %u expected %u", + fte_elem_count, count); + return; + } + + if (wpa_key_mgmt_fils(sta->key_mgmt)) { + kck = sta->ptk.kck2; + kck_len = sta->ptk.kck2_len; + kek = sta->ptk.kek2; + kek_len = sta->ptk.kek2_len; + } else { + kck = sta->ptk.kck; + kck_len = sta->ptk.kck_len; + kek = sta->ptk.kek; + kek_len = sta->ptk.kek_len; + } + if (wpa_ft_mic(kck, kck_len, sta->addr, bss->bssid, 6, + parse.mdie - 2, parse.mdie_len + 2, + parse.ftie - 2, parse.ftie_len + 2, + parse.rsn - 2, parse.rsn_len + 2, + parse.ric, parse.ric_len, + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0, + mic) < 0) { + add_note(wt, MSG_INFO, "FT: Failed to calculate MIC"); + return; + } + + if (os_memcmp_const(mic, fte_mic, mic_len) != 0) { + add_note(wt, MSG_INFO, "FT: Invalid MIC in FTE"); + wpa_printf(MSG_DEBUG, + "FT: addr=" MACSTR " auth_addr=" MACSTR, + MAC2STR(sta->addr), + MAC2STR(bss->bssid)); + wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", + fte_mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", + mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: MDE", + parse.mdie - 2, parse.mdie_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: FTE", + parse.ftie - 2, parse.ftie_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: RSN", + parse.rsn - 2, parse.rsn_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE", + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0); + return; + } + + add_note(wt, MSG_INFO, "FT: Valid FTE MIC"); + + if (wpa_compare_rsn_ie(wpa_key_mgmt_ft(sta->key_mgmt), + bss->rsnie, 2 + bss->rsnie[1], + parse.rsn - 2, parse.rsn_len + 2)) { + add_note(wt, MSG_INFO, + "FT: RSNE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame"); + wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp", + &bss->rsnie[2], bss->rsnie[1]); + wpa_hexdump(MSG_INFO, + "RSNE in FT protocol Reassociation Response frame", + parse.rsn ? parse.rsn - 2 : NULL, + parse.rsn ? parse.rsn_len + 2 : 0); + } + + process_gtk_subelem(wt, bss, sta, kek, kek_len, + parse.gtk, parse.gtk_len); + process_igtk_subelem(wt, bss, sta, kek, kek_len, + parse.igtk, parse.igtk_len); + process_bigtk_subelem(wt, bss, sta, kek, kek_len, + parse.bigtk, parse.bigtk_len); + } } From 6e47dd04ff28665a8c466bc4ac99036a0b96ddae Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 13:42:08 +0300 Subject: [PATCH 0566/1105] wlantest: Fix RSNE check in FT 4-way handshake msg 3/4 Signed-off-by: Jouni Malinen --- wlantest/rx_eapol.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 4dff7f8dd..d75ed92ba 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -628,6 +628,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, const u8 *decrypted; size_t decrypted_len = 0; struct wpa_eapol_ie_parse ie; + struct wpa_ie_data rsn; wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); @@ -781,7 +782,9 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, } if ((ie.rsn_ie && - os_memcmp(ie.rsn_ie, bss->rsnie, ie.rsn_ie_len) != 0) || + wpa_compare_rsn_ie(wpa_key_mgmt_ft(sta->key_mgmt), + ie.rsn_ie, ie.rsn_ie_len, + bss->rsnie, 2 + bss->rsnie[1])) || (ie.rsn_ie == NULL && bss->rsnie[0])) { add_note(wt, MSG_INFO, "Mismatch in RSN IE between EAPOL-Key " "3/4 and Beacon/Probe Response from " MACSTR, @@ -793,6 +796,16 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, bss->rsnie[0] ? 2 + bss->rsnie[1] : 0); } + if (wpa_key_mgmt_ft(sta->key_mgmt) && + (wpa_parse_wpa_ie_rsn(ie.rsn_ie, ie.rsn_ie_len, &rsn) < 0 || + rsn.num_pmkid != 1 || !rsn.pmkid || + os_memcmp_const(rsn.pmkid, sta->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0)) + add_note(wt, MSG_INFO, + "FT: No matching PMKR1Name in FT 4-way handshake message 3/4"); + + /* TODO: validate MDE and FTE match */ + learn_kde_keys(wt, bss, sta, decrypted, decrypted_len, hdr->key_rsc); os_free(decrypted_buf); } From bf47f0542f7dee6d3a476cf971b6c51b84a43957 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 16:20:33 +0300 Subject: [PATCH 0567/1105] tests: Suite B using PMKSA caching and roaming Signed-off-by: Jouni Malinen --- tests/hwsim/test_suite_b.py | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tests/hwsim/test_suite_b.py b/tests/hwsim/test_suite_b.py index f61947251..7065b18bd 100644 --- a/tests/hwsim/test_suite_b.py +++ b/tests/hwsim/test_suite_b.py @@ -672,3 +672,68 @@ def test_openssl_ecdh_curves(dev, apdev): raise Exception("EAP failure not reported") dev[0].request("REMOVE_NETWORK all") dev[0].wait_disconnected() + +def test_suite_b_192_pmksa_caching_roam(dev, apdev): + """WPA2/GCMP-256 connection at Suite B 192-bit level using PMKSA caching and roaming""" + check_suite_b_192_capa(dev) + dev[0].flush_scan_cache() + params = suite_b_192_ap_params() + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192", + ieee80211w="2", + openssl_ciphers="SUITEB192", + eap="TLS", identity="tls user", + ca_cert="auth_serv/ec2-ca.pem", + client_cert="auth_serv/ec2-user.pem", + private_key="auth_serv/ec2-user.key", + pairwise="GCMP-256", group="GCMP-256", scan_freq="2412") + ev = dev[0].wait_event(["PMKSA-CACHE-ADDED"], timeout=5) + if ev is None: + raise Exception("PMKSA cache entry not added for AP1") + hapd.wait_sta() + dev[0].dump_monitor() + + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + dev[0].scan_for_bss(bssid2, freq=2412) + dev[0].request("ROAM " + bssid2) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-CONNECTED"], timeout=20) + if ev is None: + raise Exception("Roaming with the AP timed out") + if "CTRL-EVENT-EAP-STARTED" not in ev: + raise Exception("EAP exchange not seen") + ev = dev[0].wait_connected() + if bssid2 not in ev: + raise Exception("Roam to AP2 connected back to AP1") + ev = dev[0].wait_event(["PMKSA-CACHE-ADDED"], timeout=5) + if ev is None: + raise Exception("PMKSA cache entry not added for AP2") + hapd2.wait_sta() + dev[0].dump_monitor() + + dev[0].request("ROAM " + bssid) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-CONNECTED"], timeout=20) + if ev is None: + raise Exception("Roaming with the AP timed out") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Unexpected EAP exchange") + if bssid not in ev: + raise Exception("Roam to AP1 connected back to AP2") + hapd.wait_sta() + dev[0].dump_monitor() + + dev[0].request("ROAM " + bssid2) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-CONNECTED"], timeout=20) + if ev is None: + raise Exception("Roaming with the AP timed out") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Unexpected EAP exchange") + if bssid2 not in ev: + raise Exception("Second roam to AP2 connected back to AP1") + hapd2.wait_sta() + dev[0].dump_monitor() From c2080e8657f812f504ff44011115ab5816b2ce3f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 16:25:50 +0300 Subject: [PATCH 0568/1105] Clear current PMKSA cache selection on association/roam It was possible for the RSN state machine to maintain old PMKSA cache selection (sm->cur_pmksa) when roaming to another BSS based on driver-based roaming indication. This could result in mismatching state and unexpected behavior, e.g., with not generating a Suite B PMKSA cache entry. Signed-off-by: Jouni Malinen --- src/rsn_supp/pmksa_cache.c | 3 +++ wpa_supplicant/events.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index bd32cef08..4a175f166 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -485,6 +485,9 @@ void pmksa_cache_clear_current(struct wpa_sm *sm) { if (sm == NULL) return; + if (sm->cur_pmksa) + wpa_printf(MSG_DEBUG, + "RSN: Clear current PMKSA entry selection"); sm->cur_pmksa = NULL; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 46341e936..f0f91892f 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -356,6 +356,9 @@ static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s) int pmksa_set = -1; size_t i; + /* Start with assumption of no PMKSA cache entry match */ + pmksa_cache_clear_current(wpa_s->wpa); + if (wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0 || ie.pmkid == NULL) return; From 2d118f557a71b865064bc7419534cf2859d2584d Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Fri, 8 May 2020 23:29:04 +0530 Subject: [PATCH 0569/1105] OCV: Add support to override channel info OCI element (STA) To support the STA testbed role, the STA has to use specified channel information in OCI element sent to the AP in EAPOL-Key msg 2/4, SA Query Request, and SA Query Response frames. Add override parameters to use the specified channel while populating OCI element in all these frames. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 11 +++++++++++ src/rsn_supp/wpa.h | 1 + src/rsn_supp/wpa_i.h | 1 + wpa_supplicant/ctrl_iface.c | 9 +++++++++ wpa_supplicant/sme.c | 20 ++++++++++++++++++++ wpa_supplicant/wpa_supplicant.c | 2 ++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ 7 files changed, 47 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 28d417608..0e6e2212c 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -756,6 +756,14 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, "Failed to get channel info for OCI element in EAPOL-Key 2/4"); goto failed; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->oci_freq_override_eapol) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, sm->oci_freq_override_eapol); + ci.frequency = sm->oci_freq_override_eapol; + } +#endif /* CONFIG_TESTING_OPTIONS */ if (ocv_insert_oci_kde(&ci, &pos) < 0) goto failed; @@ -3291,6 +3299,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_FT_RSNXE_USED: sm->ft_rsnxe_used = value; break; + case WPA_PARAM_OCI_FREQ_EAPOL: + sm->oci_freq_override_eapol = value; + break; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_DPP2 case WPA_PARAM_DPP_PFS: diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index dfc156b55..f3901e01b 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -108,6 +108,7 @@ enum wpa_sm_conf_params { WPA_PARAM_USE_EXT_KEY_ID, WPA_PARAM_FT_RSNXE_USED, WPA_PARAM_DPP_PFS, + WPA_PARAM_OCI_FREQ_EAPOL, }; struct rsn_supp_config { diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index f7d9f6255..4db925619 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -154,6 +154,7 @@ struct wpa_sm { #ifdef CONFIG_TESTING_OPTIONS struct wpabuf *test_assoc_ie; int ft_rsnxe_used; + unsigned int oci_freq_override_eapol; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_FILS diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 1507c48d2..ff2f69ea4 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -751,6 +751,12 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, } } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) { wpa_s->ft_rsnxe_used = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) { + wpa_s->oci_freq_override_eapol = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) { + wpa_s->oci_freq_override_saquery_req = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) { + wpa_s->oci_freq_override_saquery_resp = atoi(value); } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) { wpabuf_free(wpa_s->rsne_override_eapol); if (os_strcmp(value, "NULL") == 0) @@ -8315,6 +8321,9 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpabuf_free(wpa_s->rsnxe_override_eapol); wpa_s->rsnxe_override_eapol = NULL; wpas_clear_driver_signal_override(wpa_s); + wpa_s->oci_freq_override_eapol = 0; + wpa_s->oci_freq_override_saquery_req = 0; + wpa_s->oci_freq_override_saquery_resp = 0; #ifdef CONFIG_DPP os_free(wpa_s->dpp_config_obj_override); wpa_s->dpp_config_obj_override = NULL; diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index d06f6e298..28167cf27 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -2573,6 +2573,16 @@ static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s, return; } +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->oci_freq_override_saquery_req) { + wpa_printf(MSG_INFO, + "TEST: Override SA Query Request OCI frequency %d -> %d MHz", + ci.frequency, + wpa_s->oci_freq_override_saquery_req); + ci.frequency = wpa_s->oci_freq_override_saquery_req; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (ocv_insert_extended_oci(&ci, req + req_len) < 0) return; @@ -2727,6 +2737,16 @@ static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s, return; } +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->oci_freq_override_saquery_resp) { + wpa_printf(MSG_INFO, + "TEST: Override SA Query Response OCI frequency %d -> %d MHz", + ci.frequency, + wpa_s->oci_freq_override_saquery_resp); + ci.frequency = wpa_s->oci_freq_override_saquery_resp; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0) return; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index af4e7eb3a..acd0091bc 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1642,6 +1642,8 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, #ifdef CONFIG_TESTING_OPTIONS wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED, wpa_s->ft_rsnxe_used); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL, + wpa_s->oci_freq_override_eapol); #endif /* CONFIG_TESTING_OPTIONS */ /* Extended Key ID is only supported in infrastructure BSS so far */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 734ba0797..28867f04e 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1149,6 +1149,9 @@ struct wpa_supplicant { struct wpabuf *rsnxe_override_assoc; struct wpabuf *rsnxe_override_eapol; struct dl_list drv_signal_override; + unsigned int oci_freq_override_eapol; + unsigned int oci_freq_override_saquery_req; + unsigned int oci_freq_override_saquery_resp; #endif /* CONFIG_TESTING_OPTIONS */ struct wmm_ac_assoc_data *wmm_ac_assoc_info; From 52579be860d389dc298db8b52e05ff7cdfc090e6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 18:33:00 +0300 Subject: [PATCH 0570/1105] OCV: Move "OCV failed" prefix to callers Make reporting of OCV validation failure reasons more flexible by removing the fixed prefix from ocv_verify_tx_params() output in ocv_errorstr so that the caller can use whatever prefix or encapsulation that is most appropriate for each case. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 3 ++- src/ap/ieee802_11_shared.c | 2 +- src/ap/wnm_ap.c | 3 ++- src/ap/wpa_auth.c | 8 ++++---- src/ap/wpa_auth_ft.c | 2 +- src/common/ocv.c | 14 +++++++------- src/rsn_supp/wpa.c | 7 ++++--- src/rsn_supp/wpa_ft.c | 2 +- wpa_supplicant/mesh_mpm.c | 2 +- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wnm_sta.c | 3 ++- 11 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index f1f37027b..b54580efe 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3509,7 +3509,8 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr); + wpa_printf(MSG_WARNING, "FILS: OCV failed: %s", + ocv_errorstr); return WLAN_STATUS_UNSPECIFIED_FAILURE; } } diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 74a837f8b..9f2ec772e 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -255,7 +255,7 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); return; } } diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 67281b38d..4a7da9513 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -318,7 +318,8 @@ static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd, if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_msg(hapd, MSG_WARNING, "WNM: %s", ocv_errorstr); + wpa_msg(hapd, MSG_WARNING, "WNM: OCV failed: %s", + ocv_errorstr); return; } } diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 8e21ee2c4..d5aaf9cb8 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3042,8 +3042,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != 0) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - ocv_errorstr); + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "OCV failed: %s", ocv_errorstr); return; } } @@ -3880,8 +3880,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != 0) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - ocv_errorstr); + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "OCV failed: %s", ocv_errorstr); return; } } diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index d9a92e15f..f52a872c3 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -3466,7 +3466,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); return WLAN_STATUS_UNSPECIFIED_FAILURE; } } diff --git a/src/common/ocv.c b/src/common/ocv.c index 06badfbfb..6c35117a7 100644 --- a/src/common/ocv.c +++ b/src/common/ocv.c @@ -103,13 +103,13 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, if (!oci_ie) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: did not receive mandatory OCI"); + "did not receive mandatory OCI"); return -1; } if (oci_ie_len != 3) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: received OCI of unexpected length (%d)", + "received OCI of unexpected length (%d)", (int) oci_ie_len); return -1; } @@ -120,14 +120,14 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, oci.seg1_idx = oci_ie[2]; if (ocv_derive_all_parameters(&oci) != 0) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: unable to interpret received OCI"); + "unable to interpret received OCI"); return -1; } /* Primary frequency used to send frames to STA must match the STA's */ if ((int) ci->frequency != oci.freq) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: primary channel mismatch in received OCI (we use %d but receiver is using %d)", + "primary channel mismatch in received OCI (we use %d but receiver is using %d)", ci->frequency, oci.freq); return -1; } @@ -136,7 +136,7 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, */ if (tx_chanwidth > oci.chanwidth) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: channel bandwidth mismatch in received OCI (we use %d but receiver only supports %d)", + "channel bandwidth mismatch in received OCI (we use %d but receiver only supports %d)", tx_chanwidth, oci.chanwidth); return -1; } @@ -150,7 +150,7 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, if (tx_chanwidth == 40 && ci->frequency < 2500 && ci->sec_channel != oci.sec_channel) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: secondary channel mismatch in received OCI (we use %d but receiver is using %d)", + "secondary channel mismatch in received OCI (we use %d but receiver is using %d)", ci->sec_channel, oci.sec_channel); return -1; } @@ -163,7 +163,7 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, ci->chanwidth == CHAN_WIDTH_80P80) && tx_seg1_idx != oci.seg1_idx) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: frequency segment 1 mismatch in received OCI (we use %d but receiver is using %d)", + "frequency segment 1 mismatch in received OCI (we use %d but receiver is using %d)", tx_seg1_idx, oci.seg1_idx); return -1; } diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 0e6e2212c..482cc0623 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1717,7 +1717,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s", + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "OCV failed: %s", ocv_errorstr); return; } @@ -1864,7 +1864,7 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s", + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "OCV failed: %s", ocv_errorstr); return -1; } @@ -4764,7 +4764,8 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr); + wpa_printf(MSG_WARNING, "FILS: OCV failed: %s", + ocv_errorstr); goto fail; } } diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 63a4175ab..0cb327d7e 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -1159,7 +1159,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); return -1; } } diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 12aafcb97..ea62abf5b 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -1291,7 +1291,7 @@ void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "MPM: %s", + wpa_printf(MSG_WARNING, "MPM: OCV failed: %s", ocv_errorstr); return; } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 28167cf27..7e8de4eb7 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -2827,7 +2827,7 @@ void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); return; } } diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 06cb70fe5..411ce886d 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -375,7 +375,8 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s, if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_msg(wpa_s, MSG_WARNING, "WNM: %s", ocv_errorstr); + wpa_msg(wpa_s, MSG_WARNING, "WNM: OCV failed: %s", + ocv_errorstr); return; } } From d52067a5b6c3af1439a5edf7c8b09b4f1f45213c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 18:41:04 +0300 Subject: [PATCH 0571/1105] OCV: Report validation errors for SA Query Request/Response in AP mode Add a new OCV-FAILURE control interface event to notify upper layers of OCV validation issues. This commit adds this for SA Query processing in AP mode. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11_shared.c | 7 ++++++- src/common/wpa_ctrl.h | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 9f2ec772e..ba8f2cf98 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -11,6 +11,7 @@ #include "utils/common.h" #include "common/ieee802_11_defs.h" #include "common/ocv.h" +#include "common/wpa_ctrl.h" #include "hostapd.h" #include "sta_info.h" #include "ap_config.h" @@ -255,7 +256,11 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); + wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" + MACSTR " frame=saquery%s error=%s", + MAC2STR(sa), + action_type == WLAN_SA_QUERY_REQUEST ? + "req" : "resp", ocv_errorstr); return; } } diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 354de2854..488e4addc 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -388,6 +388,10 @@ extern "C" { /* Transition mode disabled indication - followed by bitmap */ #define TRANSITION_DISABLE "TRANSITION-DISABLE " +/* OCV validation failure; parameters: addr= + * frame= error= */ +#define OCV_FAILURE "OCV-FAILURE " + #ifndef BIT #define BIT(x) (1U << (x)) #endif From a3556d5813106308a7954402026d0948b00575da Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 19:08:16 +0300 Subject: [PATCH 0572/1105] OCV: Report validation errors for EAPOL-Key messages in AP mode Add the OCV-FAILURE control interface event to notify upper layers of OCV validation issues in EAPOL-Key msg 2/4 and group 2/2. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 13 ++++++++++++- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index d5aaf9cb8..203aecea7 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -15,6 +15,7 @@ #include "common/ieee802_11_defs.h" #include "common/ocv.h" #include "common/dpp.h" +#include "common/wpa_ctrl.h" #include "crypto/aes.h" #include "crypto/aes_wrap.h" #include "crypto/aes_siv.h" @@ -3044,6 +3045,11 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) tx_chanwidth, tx_seg1_idx) != 0) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, "OCV failed: %s", ocv_errorstr); + if (wpa_auth->conf.msg_ctx) + wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO, + OCV_FAILURE "addr=" MACSTR + " frame=eapol-key-m2 error=%s", + MAC2STR(sm->addr), ocv_errorstr); return; } } @@ -3868,7 +3874,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) if (wpa_channel_info(wpa_auth, &ci) != 0) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "Failed to get channel info to validate received OCI in EAPOL-Key group 1/2"); + "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2"); return; } @@ -3882,6 +3888,11 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) tx_chanwidth, tx_seg1_idx) != 0) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, "OCV failed: %s", ocv_errorstr); + if (wpa_auth->conf.msg_ctx) + wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO, + OCV_FAILURE "addr=" MACSTR + " frame=eapol-key-g2 error=%s", + MAC2STR(sm->addr), ocv_errorstr); return; } } diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 1ea067bcf..90b188599 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -168,6 +168,7 @@ struct ft_remote_r1kh { struct wpa_auth_config { + void *msg_ctx; int wpa; int extended_key_id; int wpa_key_mgmt; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 05d87ac50..e1da56da9 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1451,6 +1451,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) size_t wpa_ie_len; hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf); + _conf.msg_ctx = hapd->msg_ctx; if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) _conf.tx_status = 1; if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) From 5071248bd4cb8bcac2cc063ae0d2fbbaebc73206 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 18:32:32 +0300 Subject: [PATCH 0573/1105] tests: OCV with OCI override on STA Signed-off-by: Jouni Malinen --- tests/hwsim/test_ocv.py | 89 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py index 5456f3ba0..80bdd7a5c 100644 --- a/tests/hwsim/test_ocv.py +++ b/tests/hwsim/test_ocv.py @@ -903,3 +903,92 @@ def test_wpa2_ocv_auto_enable_pmf(dev, apdev): ieee80211w="2") dev[0].request("REMOVE_NETWORK all") dev[0].wait_disconnected() + +def test_wpa2_ocv_sta_override_eapol(dev, apdev): + """OCV on 2.4 GHz and STA override EAPOL-Key msg 2/4""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + dev[0].set("oci_freq_override_eapol", "2462") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=15) + dev[0].request("DISCONNECT") + if ev is None: + raise Exception("No connection result reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + if "reason=15" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + + ev = hapd.wait_event(["OCV-FAILURE"], timeout=1) + if ev is None: + raise Exception("OCV failure for EAPOL-Key msg 2/4 not reported") + if "addr=" + dev[0].own_addr() not in ev: + raise Exception("Unexpected OCV failure addr: " + ev) + if "frame=eapol-key-m2" not in ev: + raise Exception("Unexpected OCV failure frame: " + ev) + if "error=primary channel mismatch" not in ev: + raise Exception("Unexpected OCV failure error: " + ev) + +def test_wpa2_ocv_sta_override_sa_query_req(dev, apdev): + """OCV on 2.4 GHz and STA override SA Query Request""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + hapd.wait_sta() + dev[0].set("oci_freq_override_saquery_req", "2462") + if "OK" not in dev[0].request("UNPROT_DEAUTH"): + raise Exception("Triggering SA Query from the STA failed") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3) + if ev is None: + raise Exception("Disconnection after failed SA Query not reported") + dev[0].set("oci_freq_override_saquery_req", "0") + dev[0].wait_connected() + if "OK" not in dev[0].request("UNPROT_DEAUTH"): + raise Exception("Triggering SA Query from the STA failed") + ev = hapd.wait_event(["OCV-FAILURE"], timeout=3) + if ev is None: + raise Exception("OCV failure for SA Query Request not reported") + if "addr=" + dev[0].own_addr() not in ev: + raise Exception("Unexpected OCV failure addr: " + ev) + if "frame=saqueryreq" not in ev: + raise Exception("Unexpected OCV failure frame: " + ev) + if "error=primary channel mismatch" not in ev: + raise Exception("Unexpected OCV failure error: " + ev) + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3) + if ev is not None: + raise Exception("SA Query from the STA failed") + +def test_wpa2_ocv_sta_override_sa_query_resp(dev, apdev): + """OCV on 2.4 GHz and STA override SA Query Response""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + dev[0].set("oci_freq_override_saquery_resp", "2462") + hapd.wait_sta() + if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()): + raise Exception("SA_QUERY failed") + ev = hapd.wait_event(["OCV-FAILURE"], timeout=3) + if ev is None: + raise Exception("OCV failure for SA Query Response not reported") + if "addr=" + dev[0].own_addr() not in ev: + raise Exception("Unexpected OCV failure addr: " + ev) + if "frame=saqueryresp" not in ev: + raise Exception("Unexpected OCV failure frame: " + ev) + if "error=primary channel mismatch" not in ev: + if "error=did not receive mandatory OCI" in ev: + # This is not correct, but do not report this as test failure for + # now since the issue seems to be in mac80211 not allowing + # wpa_supplicant to process the SA Query Request frame. + logger.info("Unexpected OCV failure error: " + ev) + else: + raise Exception("Unexpected OCV failure error: " + ev) From 01ceb88c77f2b6f25ac22b426eadecfed432d2bd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 20:46:32 +0300 Subject: [PATCH 0574/1105] OCV: Report validation errors for (Re)Association Request frames Add the OCV-FAILURE control interface event to notify upper layers of OCV validation issues in FT and FILS (Re)Association Request frames. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 4 ++++ src/ap/wpa_auth_ft.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index b54580efe..c4bf434f2 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -24,6 +24,7 @@ #include "common/dpp.h" #include "common/ocv.h" #include "common/wpa_common.h" +#include "common/wpa_ctrl.h" #include "radius/radius.h" #include "radius/radius_client.h" #include "p2p/p2p.h" @@ -3511,6 +3512,9 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, tx_chanwidth, tx_seg1_idx) != 0) { wpa_printf(MSG_WARNING, "FILS: OCV failed: %s", ocv_errorstr); + wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" + MACSTR " frame=fils-reassoc-req error=%s", + MAC2STR(sta->addr), ocv_errorstr); return WLAN_STATUS_UNSPECIFIED_FAILURE; } } diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index f52a872c3..1a1fa2420 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -14,6 +14,7 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/ocv.h" +#include "common/wpa_ctrl.h" #include "drivers/driver.h" #include "crypto/aes.h" #include "crypto/aes_siv.h" @@ -3467,6 +3468,11 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != 0) { wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); + if (sm->wpa_auth->conf.msg_ctx) + wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, + OCV_FAILURE "addr=" MACSTR + " frame=ft-reassoc-req error=%s", + MAC2STR(sm->addr), ocv_errorstr); return WLAN_STATUS_UNSPECIFIED_FAILURE; } } From 8ee0bc622a715366344e6669bc19c9bd40891aeb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 21:55:49 +0300 Subject: [PATCH 0575/1105] OCV: Disconnect STAs that do not use SA Query after CSA Verify that all associated STAs that claim support for OCV initiate an SA Query after CSA. If no SA Query is seen within 15 seconds, deauthenticate the STA. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 25 +++++++++++++++++++++++-- src/ap/hostapd.c | 27 +++++++++++++++++++++++++++ src/ap/hostapd.h | 1 + src/ap/ieee802_11_shared.c | 2 ++ src/ap/sta_info.h | 1 + 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 524a15132..173549e7b 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -844,8 +844,6 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, int offset, int width, int cf1, int cf2, int finished) { - /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */ - #ifdef NEED_AP_MLME int channel, chwidth, is_dfs; u8 seg0_idx = 0, seg1_idx = 0; @@ -958,6 +956,29 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, for (i = 0; i < hapd->iface->num_bss; i++) hostapd_neighbor_set_own_report(hapd->iface->bss[i]); + +#ifdef CONFIG_OCV + if (hapd->conf->ocv) { + struct sta_info *sta; + bool check_sa_query = false; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (wpa_auth_uses_ocv(sta->wpa_sm) && + !(sta->flags & WLAN_STA_WNM_SLEEP_MODE)) { + sta->post_csa_sa_query = 1; + check_sa_query = true; + } + } + + if (check_sa_query) { + wpa_printf(MSG_DEBUG, + "OCV: Check post-CSA SA Query initiation in 15 seconds"); + eloop_register_timeout(15, 0, + hostapd_ocv_check_csa_sa_query, + hapd, NULL); + } + } +#endif /* CONFIG_OCV */ #endif /* NEED_AP_MLME */ } diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index f9af038be..f0af4b87c 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -439,6 +439,10 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd) hostapd_clean_rrm(hapd); fils_hlp_deinit(hapd); +#ifdef CONFIG_OCV + eloop_cancel_timeout(hostapd_ocv_check_csa_sa_query, hapd, NULL); +#endif /* CONFIG_OCV */ + #ifdef CONFIG_SAE { struct hostapd_sae_commit_queue *q; @@ -3151,6 +3155,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, hostapd_prune_associations(hapd, sta->addr); ap_sta_clear_disconnect_timeouts(hapd, sta); + sta->post_csa_sa_query = 0; #ifdef CONFIG_P2P if (sta->p2p_ie == NULL && !sta->no_p2p_set) { @@ -3662,3 +3667,25 @@ void hostapd_periodic_iface(struct hostapd_iface *iface) #endif /* CONFIG_NO_RADIUS */ } } + + +#ifdef CONFIG_OCV +void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta; + + wpa_printf(MSG_DEBUG, "OCV: Post-CSA SA Query initiation check"); + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (!sta->post_csa_sa_query) + continue; + + wpa_printf(MSG_DEBUG, "OCV: OCVC STA " MACSTR + " did not start SA Query after CSA - disconnect", + MAC2STR(sta->addr)); + ap_sta_disconnect(hapd, sta, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } +} +#endif /* CONFIG_OCV */ diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 609c84b22..b70d13fba 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -632,6 +632,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface, void hostapd_cleanup_cs_params(struct hostapd_data *hapd); void hostapd_periodic_iface(struct hostapd_iface *iface); int hostapd_owe_trans_get_info(struct hostapd_data *hapd); +void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); /* utils.c */ int hostapd_register_probereq_cb(struct hostapd_data *hapd, diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index ba8f2cf98..45a07085f 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -267,6 +267,8 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, #endif /* CONFIG_OCV */ if (action_type == WLAN_SA_QUERY_REQUEST) { + if (sta) + sta->post_csa_sa_query = 0; ieee802_11_send_sa_query_resp(hapd, sa, trans_id); return; } diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 940d31590..ef485618a 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -122,6 +122,7 @@ struct sta_info { unsigned int hs20_t_c_filtering:1; unsigned int ft_over_ds:1; unsigned int external_dh_updated:1; + unsigned int post_csa_sa_query:1; u16 auth_alg; From 38163b193eff2444f1422d631afe9f76ef3ea922 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 21:54:49 +0300 Subject: [PATCH 0576/1105] tests: OCV and post-CSA SA Query error cases Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_pmf.py | 68 +++++++++++++++++++++++++++----------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index 594c0c884..54f04f387 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -59,24 +59,30 @@ def test_ap_pmf_required(dev, apdev): dev[1].p2p_interface_addr()) < 1: raise Exception("STA did not reply to SA Query") -@remote_compatible -def test_ocv_sa_query(dev, apdev): - """Test SA Query with OCV""" +def start_ocv_ap(apdev): ssid = "test-pmf-required" params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") params["wpa_key_mgmt"] = "WPA-PSK-SHA256" params["ieee80211w"] = "2" params["ocv"] = "1" try: - hapd = hostapd.add_ap(apdev[0], params) + hapd = hostapd.add_ap(apdev, params) except Exception as e: if "Failed to set hostapd parameter ocv" in str(e): raise HwsimSkip("OCV not supported") raise + Wlantest.setup(hapd) wt = Wlantest() wt.flush() wt.add_passphrase("12345678") + + return hapd, ssid, wt + +@remote_compatible +def test_ocv_sa_query(dev, apdev): + """Test SA Query with OCV""" + hapd, ssid, wt = start_ocv_ap(apdev[0]) dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1", key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") @@ -99,21 +105,7 @@ def test_ocv_sa_query(dev, apdev): @remote_compatible def test_ocv_sa_query_csa(dev, apdev): """Test SA Query with OCV after channel switch""" - ssid = "test-pmf-required" - params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") - params["wpa_key_mgmt"] = "WPA-PSK-SHA256" - params["ieee80211w"] = "2" - params["ocv"] = "1" - try: - hapd = hostapd.add_ap(apdev[0], params) - except Exception as e: - if "Failed to set hostapd parameter ocv" in str(e): - raise HwsimSkip("OCV not supported") - raise - Wlantest.setup(hapd) - wt = Wlantest() - wt.flush() - wt.add_passphrase("12345678") + hapd, ssid, wt = start_ocv_ap(apdev[0]) dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1", key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") @@ -124,6 +116,44 @@ def test_ocv_sa_query_csa(dev, apdev): dev[0].own_addr()) < 1: raise Exception("STA did not start SA Query after channel switch") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=16) + if ev is not None: + raise Exception("Unexpected disconnection") + +def test_ocv_sa_query_csa_no_resp(dev, apdev): + """Test SA Query with OCV after channel switch getting no response""" + hapd, ssid, wt = start_ocv_ap(apdev[0]) + dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412") + + hapd.set("ext_mgmt_frame_handling", "1") + hapd.request("CHAN_SWITCH 5 2437") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5) + if ev is None: + raise Exception("Disconnection after CSA not reported") + if "locally_generated=1" not in ev: + raise Exception("Unexpectedly disconnected by AP: " + ev) + +def test_ocv_sa_query_csa_missing(dev, apdev): + """Test SA Query with OCV missing after channel switch""" + hapd, ssid, wt = start_ocv_ap(apdev[0]) + dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412") + + hapd.set("ext_mgmt_frame_handling", "1") + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + ev = hapd.wait_event(['MGMT-RX'], timeout=5) + if ev is None: + raise Exception("Deauthentication frame RX not reported") + hapd.set("ext_mgmt_frame_handling", "0") + hapd.request("CHAN_SWITCH 5 2437") + ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=20) + if ev is None: + raise Exception("No disconnection event received from hostapd") + @remote_compatible def test_ap_pmf_optional(dev, apdev): """WPA2-PSK AP with PMF optional""" From b96a3bd5dfe21656a9fe2d4fce0f428da483d7fe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 25 May 2020 23:24:55 +0300 Subject: [PATCH 0577/1105] tests: sigma_dut controlled STA using OCV Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 070a2a549..b87f44bb8 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4587,3 +4587,48 @@ def test_sigma_dut_ap_ft_rsnxe_used_mismatch(dev, apdev, params): sigma_dut_cmd_check("ap_reset_default") finally: stop_sigma_dut(sigma) + +def test_sigma_dut_ocv(dev, apdev): + """sigma_dut controlled STA using OCV""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params['sae_groups'] = '19' + params['ocv'] = '1' + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ocvc,1" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + sigma_dut_wait_connected(ifname) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ocvc,1" % ifname) + sigma_dut_cmd_check("sta_set_rfeature,interface,%s,prog,WPA3,OCIFrameType,eapolM2,OCIChannel,11" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae")) + ev = hapd.wait_event(["OCV-FAILURE"], timeout=1) + if ev is None: + raise Exception("OCV failure for EAPOL-Key msg 2/4 not reported") + if "addr=" + dev[0].own_addr() not in ev: + raise Exception("Unexpected OCV failure addr: " + ev) + if "frame=eapol-key-m2" not in ev: + raise Exception("Unexpected OCV failure frame: " + ev) + if "error=primary channel mismatch" not in ev: + raise Exception("Unexpected OCV failure error: " + ev) + + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) From 3f9a89ca1cd5397165200bd38b8ffdf258df007e Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Thu, 7 May 2020 01:16:35 +0530 Subject: [PATCH 0578/1105] Vendor attributes for configuring LDPC, TX STBC, RX STBC Defines the attributes in SET(GET)_WIFI_CONFIGURATION to dynamically configure capabilities: LDPC, TX STBC, RX STBC. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index bb133e1c4..9e938c18e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2147,6 +2147,42 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION = 66, + /* 8-bit unsigned value. This attribute is used to dynamically + * enable/disable the LDPC capability of the device. When configured in + * the disconnected state, the updated configuration will be considered + * for the immediately following connection attempt. If this + * configuration is modified while the device is in the connected state, + * the LDPC TX will be updated with this configuration immediately, + * while the LDPC RX configuration update will take place starting from + * the subsequent association attempt. + * 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC = 67, + + /* 8-bit unsigned value. This attribute is used to dynamically + * enable/disable the TX STBC capability of the device. When configured + * in the disconnected state, the updated configuration will be + * considered for the immediately following connection attempt. If the + * connection is formed with TX STBC enabled and if this configuration + * is disabled during that association, the TX will be impacted + * immediately. Further connection attempts will disable TX STBC. + * However, enabling the TX STBC for a connected session with disabled + * capability is not allowed and will fail. + * 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC = 68, + + /* 8-bit unsigned value. This attribute is used to dynamically + * enable/disable the RX STBC capability of the device. When configured + * in the disconnected state, the updated configuration will be + * considered for the immediately following connection attempt. If the + * configuration is modified in the connected state, there will be no + * impact for the current association, but further connection attempts + * will use the updated configuration. + * 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC = 69, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = From 88436baaac4172fda2abbe41449ff0bf8994ee9d Mon Sep 17 00:00:00 2001 From: Sachin Ahuja Date: Mon, 18 May 2020 20:00:18 +0530 Subject: [PATCH 0579/1105] Add a vendor attribute to get OEM data Add an attribute QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED to get the response for the queried data. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 9e938c18e..ea68beceb 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -8462,10 +8462,14 @@ enum qca_vendor_oem_device_type { * enum qca_wlan_vendor_attr_oem_data_params - Used by the vendor command/event * QCA_NL80211_VENDOR_SUBCMD_OEM_DATA. * - * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA: The binary blob for the vendor - * command/event QCA_NL80211_VENDOR_SUBCMD_OEM_DATA are carried through this - * attribute. - * NLA_BINARY attribute, the max size is 1024 bytes. + * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA: This NLA_BINARY attribute is + * used to set/query the data to/from the firmware. On query, the same + * attribute is used to carry the respective data in the reply sent by the + * driver to userspace. The request to set/query the data and the format of the + * respective data from the firmware are embedded in the attribute. The + * maximum size of the attribute payload is 1024 bytes. + * Userspace has to set the QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED + * attribute when the data is queried from the firmware. * * @QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO: The binary blob will be routed * based on this field. This optional attribute is included to specify whether @@ -8474,11 +8478,16 @@ enum qca_vendor_oem_device_type { * command/event. * This u8 attribute is used to carry information for the device type using * values defined by enum qca_vendor_oem_device_type. + * + * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED: This NLA_FLAG attribute + * is set when the userspace queries data from the firmware. This attribute + * should not be set when userspace sets the OEM data to the firmware. */ enum qca_wlan_vendor_attr_oem_data_params { QCA_WLAN_VENDOR_ATTR_OEM_DATA_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA = 1, QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO = 2, + QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_AFTER_LAST, From 9818fbe9bc00d97657c7e039f51c682c5f256673 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 26 May 2020 12:31:16 +0300 Subject: [PATCH 0580/1105] tests: Enforce proper OCV behavior for SA Query Response from STA Now that there is a pending mac80211 patch ("mac80211: allow SA-QUERY processing in userspace") to allow wpa_supplicant to take care of SA Query Request processing, start enforcing correct behavior for this in ocv_sa_query and wpa2_ocv_sta_override_sa_query_resp. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_pmf.py | 4 +++- tests/hwsim/test_ocv.py | 8 +------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index 54f04f387..2bb4a3602 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -90,7 +90,9 @@ def test_ocv_sa_query(dev, apdev): # Test that client can handle SA Query with OCI element if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()): raise Exception("SA_QUERY failed") - time.sleep(0.1) + ev = hapd.wait_event(["OCV-FAILURE"], timeout=0.1) + if ev: + raise Exception("Unexpected OCV failure reported") if wt.get_sta_counter("valid_saqueryresp_tx", apdev[0]['bssid'], dev[0].own_addr()) < 1: raise Exception("STA did not reply to SA Query") diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py index 80bdd7a5c..1f185d7e9 100644 --- a/tests/hwsim/test_ocv.py +++ b/tests/hwsim/test_ocv.py @@ -985,10 +985,4 @@ def test_wpa2_ocv_sta_override_sa_query_resp(dev, apdev): if "frame=saqueryresp" not in ev: raise Exception("Unexpected OCV failure frame: " + ev) if "error=primary channel mismatch" not in ev: - if "error=did not receive mandatory OCI" in ev: - # This is not correct, but do not report this as test failure for - # now since the issue seems to be in mac80211 not allowing - # wpa_supplicant to process the SA Query Request frame. - logger.info("Unexpected OCV failure error: " + ev) - else: - raise Exception("Unexpected OCV failure error: " + ev) + raise Exception("Unexpected OCV failure error: " + ev) From d578e890eb4fe344824ee9f43124091fc0f848b1 Mon Sep 17 00:00:00 2001 From: Hu Wang Date: Fri, 15 May 2020 14:20:32 +0800 Subject: [PATCH 0581/1105] OWE: Skip beacon update of transition BSS if it is not yet enabled When a single hostapd process manages both the OWE and open BSS for transition mode, owe_transition_ifname can be used to clone the transition mode information (i.e., BSSID/SSID) automatically. When both BSSs use ACS, the completion of ACS on the 1st BSS sets state to HAPD_IFACE_ENABLED and the OWE transition mode information is updated for all the other BSSs. However, the 2nd BSS is still in the ACS phase and the beacon update messes up the state for AP startup and prevents proper ACS competion. If 2nd BSS is not yet enabled (e.g., in ACS), skip beacon update and defer OWE transition information cloning until the BSS is enabled. Signed-off-by: Jouni Malinen --- src/ap/hostapd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index f0af4b87c..b37f49f9a 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1915,6 +1915,13 @@ static int hostapd_owe_iface_iter2(struct hostapd_iface *iface, void *ctx) if (!bss->conf->owe_transition_ifname[0]) continue; + if (bss->iface->state != HAPD_IFACE_ENABLED) { + wpa_printf(MSG_DEBUG, + "OWE: Interface %s state %s - defer beacon update", + bss->conf->iface, + hostapd_state_text(bss->iface->state)); + continue; + } res = hostapd_owe_trans_get_info(bss); if (res == 0) continue; From eff431ff3868d5414f6017fa0bccdde03bb0b922 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 26 May 2020 16:15:45 +0300 Subject: [PATCH 0582/1105] tests: OWE transition mode with owe_transition_ifname Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_acs.py | 4 +- tests/hwsim/test_owe.py | 83 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index 0f547cc13..eb245e7c3 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -37,7 +37,7 @@ def wait_acs(hapd, return_after_acs=False): state = hapd.get_status_field("state") if state != "ACS": - raise Exception("Unexpected interface state") + raise Exception("Unexpected interface state %s (expected ACS)" % state) ev = hapd.wait_event(["ACS-COMPLETED", "ACS-FAILED", "AP-ENABLED", "AP-DISABLED"], timeout=20) @@ -57,7 +57,7 @@ def wait_acs(hapd, return_after_acs=False): state = hapd.get_status_field("state") if state != "ENABLED": - raise Exception("Unexpected interface state") + raise Exception("Unexpected interface state %s (expected ENABLED)" % state) def test_ap_acs(dev, apdev): """Automatic channel selection""" diff --git a/tests/hwsim/test_owe.py b/tests/hwsim/test_owe.py index 51cd7bf74..e0d356858 100644 --- a/tests/hwsim/test_owe.py +++ b/tests/hwsim/test_owe.py @@ -16,6 +16,7 @@ from wpasupplicant import WpaSupplicant import hwsim_utils from tshark import run_tshark from utils import HwsimSkip, fail_test, alloc_fail, wait_fail_trigger +from test_ap_acs import wait_acs def test_owe(dev, apdev): """Opportunistic Wireless Encryption""" @@ -208,6 +209,88 @@ def run_owe_transition_mode(dev, apdev): dev[0].wait_connected() hwsim_utils.test_connectivity(dev[0], hapd) +def test_owe_transition_mode_ifname(dev, apdev): + """Opportunistic Wireless Encryption transition mode (ifname)""" + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + dev[0].flush_scan_cache() + params = {"ssid": "owe-random", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "rsn_pairwise": "CCMP", + "ieee80211w": "2", + "owe_transition_ifname": apdev[1]['ifname'], + "ignore_broadcast_ssid": "1"} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + params = {"ssid": "owe-test", + "owe_transition_ifname": apdev[0]['ifname']} + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid, freq="2412") + dev[0].scan_for_bss(bssid2, freq="2412") + + id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2", + scan_freq="2412") + val = dev[0].get_status_field("key_mgmt") + if val != "OWE": + raise Exception("Unexpected key_mgmt: " + val) + +def test_owe_transition_mode_ifname_acs(dev, apdev): + """Opportunistic Wireless Encryption transition mode (ifname, ACS)""" + run_owe_transition_mode_ifname_acs(dev, apdev, wait_first=False) + +def test_owe_transition_mode_ifname_acs2(dev, apdev): + """Opportunistic Wireless Encryption transition mode (ifname, ACS)""" + run_owe_transition_mode_ifname_acs(dev, apdev, wait_first=True) + +def run_owe_transition_mode_ifname_acs(dev, apdev, wait_first): + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + dev[0].flush_scan_cache() + params = {"ssid": "owe-random", + "channel": "0", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "rsn_pairwise": "CCMP", + "ieee80211w": "2", + "owe_transition_ifname": apdev[1]['ifname'], + "ignore_broadcast_ssid": "1"} + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + bssid = hapd.own_addr() + + if wait_first: + wait_acs(hapd) + + params = {"ssid": "owe-test", + "channel": "0", + "owe_transition_ifname": apdev[0]['ifname']} + hapd2 = hostapd.add_ap(apdev[1], params, wait_enabled=False) + bssid2 = hapd2.own_addr() + + wait_acs(hapd2) + if not wait_first: + state = hapd.get_status_field("state") + if state == "ACS-STARTED": + time.sleep(5) + state = hapd.get_status_field("state") + if state != "ENABLED": + raise Exception("AP1 startup did not succeed") + + freq = hapd.get_status_field("freq") + freq2 = hapd2.get_status_field("freq") + + dev[0].scan_for_bss(bssid, freq=freq) + dev[0].scan_for_bss(bssid2, freq=freq2) + + id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2", + scan_freq="%s %s" % (freq, freq2)) + val = dev[0].get_status_field("key_mgmt") + if val != "OWE": + raise Exception("Unexpected key_mgmt: " + val) + def test_owe_transition_mode_open_only_ap(dev, apdev): """Opportunistic Wireless Encryption transition mode connect to open-only AP""" if "OWE" not in dev[0].get_capability("key_mgmt"): From b50b8f04297316bd57305abadb68f04aff582ce1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 29 May 2020 20:55:18 +0300 Subject: [PATCH 0583/1105] tests: HS 2.0 deauthentication request PMF misbehavior (+HTC) Verify driver/mac80211 behavior with HT Control field in Public Action frames. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_hs20.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index 9ff95b7d9..d9f2e08c6 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -2547,6 +2547,41 @@ def test_ap_hs20_deauth_req_without_pmf(dev, apdev): if "FAIL" not in hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/"): raise Exception("HS20_DEAUTH_REQ accepted during OOM") +def test_ap_hs20_deauth_req_pmf_htc(dev, apdev): + """Hotspot 2.0 connection and deauthentication request PMF misbehavior (+HTC)""" + try: + run_ap_hs20_deauth_req_pmf_htc(dev, apdev) + finally: + stop_monitor(apdev[1]["ifname"]) + +def run_ap_hs20_deauth_req_pmf_htc(dev, apdev): + check_eap_capa(dev[0], "MSCHAPV2") + dev[0].request("SET pmf 0") + hapd = eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user", release=1) + dev[0].dump_monitor() + addr = dev[0].own_addr() + hapd.wait_sta() + + sock = start_monitor(apdev[1]["ifname"]) + radiotap = radiotap_build() + bssid = hapd.own_addr().replace(':', '') + addr = dev[0].own_addr().replace(':', '') + payload = "0a1a0101dd1b506f9a0101780013687474703a2f2f6578616d706c652e636f6d2f" + # Claim there is a HT Control field, but then start the frame body from + # there and do not encrypt the Robust Action frame. + frame = binascii.unhexlify("d0803a01" + addr + 2 * bssid + "0000" + payload) + # Claim there is a HT Control field and start the frame body in the correct + # location, but do not encrypt the Robust Action frame. Make the first octet + # of HT Control field use a non-robust Action Category value. + frame2 = binascii.unhexlify("d0803a01" + addr + 2 * bssid + "0000" + "04000000" + payload) + + sock.send(radiotap + frame) + sock.send(radiotap + frame2) + + ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=1) + if ev is not None: + raise Exception("Deauth imminent notice without PMF accepted") + def test_ap_hs20_remediation_required(dev, apdev): """Hotspot 2.0 connection and remediation required from RADIUS""" check_eap_capa(dev[0], "MSCHAPV2") From a998337895714a71381d554d70b9c8dbb36bce27 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 29 May 2020 21:04:40 +0300 Subject: [PATCH 0584/1105] WNM: Do not expose GTK/IGTK in WNM Sleep Mode Response frame in OSEN Do not include the actual GTK/IGTK value in WNM Sleep Mode Response frame if WNM Sleep Mode is used in OSEN or in a network where use of GTK is disabled. This was already the case for the EAPOL-Key cases of providing GTK/IGTK, but the WNM Sleep Mode exit case was missed. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 203aecea7..6b8fa52fc 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -4078,6 +4078,7 @@ void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) { + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; u8 *start = pos; @@ -4096,6 +4097,14 @@ int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) return 0; pos += 8; os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(pos, gsm->GTK_len) < 0) + return 0; + } pos += gsm->GTK_len; wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", @@ -4109,6 +4118,7 @@ int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) { + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; u8 *start = pos; size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); @@ -4126,6 +4136,14 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) pos += 6; os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len); + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random IGTK to each STA to prevent use + * of IGTK in the BSS. + */ + if (random_get_bytes(pos, len) < 0) + return 0; + } pos += len; wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", From 2d6cc0e67066ce76a01d776cbf9f1281adf2ac9f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 29 May 2020 21:23:09 +0300 Subject: [PATCH 0585/1105] FT: Do not expose GTK/IGTK in FT Reassociation Response frame in OSEN Do not include the actual GTK/IGTK value in FT protocol cases in OSEN or with DGAF disabled (Hotspot 2.0). This was already the case for the EAPOL-Key cases of providing GTK/IGTK, but the FT protocol case was missed. OSEN cannot really use FT, so that part is not impacted, but it would be possible to enable FT in a Hotspot 2.0 network that has DGAF disabled. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth_ft.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 1a1fa2420..79cf10866 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2163,11 +2163,12 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) { u8 *subelem; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; size_t subelem_len, pad_len; const u8 *key; size_t key_len; - u8 keybuf[32]; + u8 keybuf[WPA_GTK_MAX_LEN]; const u8 *kek; size_t kek_len; @@ -2194,12 +2195,30 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) pad_len += 8; if (pad_len && key_len < sizeof(keybuf)) { os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len); + if (conf->disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(keybuf, key_len) < 0) + return NULL; + } os_memset(keybuf + key_len, 0, pad_len); keybuf[key_len] = 0xdd; key_len += pad_len; key = keybuf; - } else + } else if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use of GTK + * in the BSS. + */ + if (random_get_bytes(keybuf, key_len) < 0) + return NULL; + key = keybuf; + } else { key = gsm->GTK[gsm->GN - 1]; + } /* * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | @@ -2233,11 +2252,13 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) { u8 *subelem, *pos; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; size_t subelem_len; - const u8 *kek; + const u8 *kek, *igtk; size_t kek_len; size_t igtk_len; + u8 dummy_igtk[WPA_IGTK_MAX_LEN]; if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { kek = sm->PTK.kek2; @@ -2264,8 +2285,19 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos); pos += 6; *pos++ = igtk_len; - if (aes_wrap(kek, kek_len, igtk_len / 8, - gsm->IGTK[gsm->GN_igtk - 4], pos)) { + igtk = gsm->IGTK[gsm->GN_igtk - 4]; + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random IGTK to each STA to prevent use of + * IGTK in the BSS. + */ + if (random_get_bytes(dummy_igtk, igtk_len / 8) < 0) { + os_free(subelem); + return NULL; + } + igtk = dummy_igtk; + } + if (aes_wrap(kek, kek_len, igtk_len / 8, igtk, pos)) { wpa_printf(MSG_DEBUG, "FT: IGTK subelem encryption failed: kek_len=%d", (int) kek_len); From 5a7bcb7725da53f1fe58badae4ab3e4404784f84 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 29 May 2020 21:07:45 +0300 Subject: [PATCH 0586/1105] OSEN: Do not send the actual BIGTK to OSEN STAs OSEN STAs are not authenticated, so do not send the actual BIGTK for them so that they cannot generate forged protected Beacon frames. This means that OSEN STAs cannot enable beacon protection. Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 16 ++++++++++++++++ src/ap/wpa_auth_ft.c | 18 +++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 6b8fa52fc..50b42646e 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3212,6 +3212,14 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) else os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn)); os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len); + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random BIGTK to each OSEN STA to prevent use + * of BIGTK in the BSS. + */ + if (random_get_bytes(bigtk.bigtk, len) < 0) + return pos; + } pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK, (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len, NULL, 0); @@ -4174,6 +4182,14 @@ int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos) pos += 6; os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len); + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random BIGTK to each STA to prevent use + * of BIGTK in the BSS. + */ + if (random_get_bytes(pos, len) < 0) + return 0; + } pos += len; wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit", diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 79cf10866..570e2ee4a 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2315,9 +2315,10 @@ static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len) u8 *subelem, *pos; struct wpa_group *gsm = sm->group; size_t subelem_len; - const u8 *kek; + const u8 *kek, *bigtk; size_t kek_len; size_t bigtk_len; + u8 dummy_bigtk[WPA_IGTK_MAX_LEN]; if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { kek = sm->PTK.kek2; @@ -2344,8 +2345,19 @@ static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len) wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos); pos += 6; *pos++ = bigtk_len; - if (aes_wrap(kek, kek_len, bigtk_len / 8, - gsm->IGTK[gsm->GN_bigtk - 6], pos)) { + bigtk = gsm->IGTK[gsm->GN_bigtk - 6]; + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random BIGTK to each OSEN STA to prevent use + * of BIGTK in the BSS. + */ + if (random_get_bytes(dummy_bigtk, bigtk_len / 8) < 0) { + os_free(subelem); + return NULL; + } + bigtk = dummy_bigtk; + } + if (aes_wrap(kek, kek_len, bigtk_len / 8, bigtk, pos)) { wpa_printf(MSG_DEBUG, "FT: BIGTK subelem encryption failed: kek_len=%d", (int) kek_len); From 32d3360f33cf1d74c6a506ec73f772264c6d349e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 29 May 2020 21:35:26 +0300 Subject: [PATCH 0587/1105] DPP: Fix a typo in a comment Signed-off-by: Jouni Malinen --- src/common/dpp_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 8bf2a74a6..8f884fd61 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -855,7 +855,7 @@ int dpp_derive_bk_ke(struct dpp_authentication *auth) "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])", auth->bk, hash_len); - /* ke = HKDF-Expand(bkK, "DPP Key", length) */ + /* ke = HKDF-Expand(bk, "DPP Key", length) */ res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke, hash_len); if (res < 0) From d10a57f6e97eb851e631ab7f9701fb3a2274593f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 29 May 2020 21:42:33 +0300 Subject: [PATCH 0588/1105] DPP2: Derive a separate key for enveloped data Derive a new key from bk to be used as the password for PBKDF2 instead of using ke for this. Signed-off-by: Jouni Malinen --- src/common/dpp_backup.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c index c675c427b..e12bc6d7c 100644 --- a/src/common/dpp_backup.c +++ b/src/common/dpp_backup.c @@ -275,18 +275,21 @@ dpp_build_pw_recipient_info(struct dpp_authentication *auth, size_t hash_len, struct wpabuf *pwri = NULL, *enc_key = NULL, *key_der_alg = NULL, *key_enc_alg = NULL, *salt; u8 kek[DPP_MAX_HASH_LEN]; - const u8 *key; + u8 key[DPP_MAX_HASH_LEN]; size_t key_len; + int res; salt = wpabuf_alloc(64); if (!salt || os_get_random(wpabuf_put(salt, 64), 64) < 0) goto fail; wpa_hexdump_buf(MSG_DEBUG, "DPP: PBKDF2 salt", salt); - /* TODO: For initial testing, use ke as the key. Replace this with a - * new key once that has been defined. */ - key = auth->ke; key_len = auth->curve->hash_len; + /* password = HKDF-Expand(bk, "Enveloped Data Password", length) */ + res = dpp_hkdf_expand(key_len, auth->bk, key_len, + "Enveloped Data Password", key, key_len); + if (res < 0) + goto fail; wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); if (dpp_pbkdf2(hash_len, key, key_len, wpabuf_head(salt), 64, 1000, @@ -1151,7 +1154,7 @@ dpp_parse_dpp_asymmetric_key_package(const u8 *key_pkg, size_t key_pkg_len) int dpp_conf_resp_env_data(struct dpp_authentication *auth, const u8 *env_data, size_t env_data_len) { - const u8 *key; + u8 key[DPP_MAX_HASH_LEN]; size_t key_len; u8 kek[DPP_MAX_HASH_LEN]; u8 cont_encr_key[DPP_MAX_HASH_LEN]; @@ -1167,10 +1170,12 @@ int dpp_conf_resp_env_data(struct dpp_authentication *auth, if (dpp_parse_enveloped_data(env_data, env_data_len, &data) < 0) return -1; - /* TODO: For initial testing, use ke as the key. Replace this with a - * new key once that has been defined. */ - key = auth->ke; key_len = auth->curve->hash_len; + /* password = HKDF-Expand(bk, "Enveloped Data Password", length) */ + res = dpp_hkdf_expand(key_len, auth->bk, key_len, + "Enveloped Data Password", key, key_len); + if (res < 0) + return -1; wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); if (dpp_pbkdf2(data.prf_hash_len, key, key_len, data.salt, 64, 1000, From 661e661186af8891df801b53af24b25f21bd7319 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 00:04:53 +0300 Subject: [PATCH 0589/1105] OCV: Allow OCI channel to be overridden for testing (AP) Add hostapd configuration parameters oci_freq_override_* to allow the OCI channel information to be overridden for various frames for testing purposes. This can be set in the configuration and also updated during the runtime of a BSS. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 14 +++++++++ hostapd/ctrl_iface.c | 16 +++++++++++ src/ap/ap_config.h | 7 +++++ src/ap/ieee802_11_shared.c | 20 +++++++++++++ src/ap/wnm_ap.c | 9 ++++++ src/ap/wpa_auth.c | 58 +++++++++++++++++++++++++++++++++----- src/ap/wpa_auth.h | 14 +++++++++ src/ap/wpa_auth_ft.c | 9 ++++++ src/ap/wpa_auth_glue.c | 5 ++++ 9 files changed, 145 insertions(+), 7 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index cc1855dcd..bc650e949 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4217,6 +4217,20 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->skip_prune_assoc = atoi(pos); } else if (os_strcmp(buf, "ft_rsnxe_used") == 0) { bss->ft_rsnxe_used = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) { + bss->oci_freq_override_eapol_m3 = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) { + bss->oci_freq_override_eapol_g1 = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) { + bss->oci_freq_override_saquery_req = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) { + bss->oci_freq_override_saquery_resp = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) { + bss->oci_freq_override_ft_assoc = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) { + bss->oci_freq_override_fils_assoc = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) { + bss->oci_freq_override_wnm_sleep = atoi(pos); #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_SAE } else if (os_strcmp(buf, "sae_password") == 0) { diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index edc69f470..8a79ef783 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1484,6 +1484,22 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) if (os_strcmp(cmd, "ft_rsnxe_used") == 0) wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth, hapd->conf->ft_rsnxe_used); + else if (os_strcmp(cmd, "oci_freq_override_eapol_m3") == 0) + wpa_auth_set_ocv_override_freq( + hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_M3, + atoi(value)); + else if (os_strcmp(cmd, "oci_freq_override_eapol_g1") == 0) + wpa_auth_set_ocv_override_freq( + hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_G1, + atoi(value)); + else if (os_strcmp(cmd, "oci_freq_override_ft_assoc") == 0) + wpa_auth_set_ocv_override_freq( + hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_FT_ASSOC, + atoi(value)); + else if (os_strcmp(cmd, "oci_freq_override_fils_assoc") == 0) + wpa_auth_set_ocv_override_freq( + hapd->wpa_auth, + WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value)); #endif /* CONFIG_TESTING_OPTIONS */ } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index cffa636cc..c1b4b1bbb 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -687,6 +687,13 @@ struct hostapd_bss_config { int no_beacon_rsnxe; int skip_prune_assoc; int ft_rsnxe_used; + unsigned int oci_freq_override_eapol_m3; + unsigned int oci_freq_override_eapol_g1; + unsigned int oci_freq_override_saquery_req; + unsigned int oci_freq_override_saquery_resp; + unsigned int oci_freq_override_ft_assoc; + unsigned int oci_freq_override_fils_assoc; + unsigned int oci_freq_override_wnm_sleep; #endif /* CONFIG_TESTING_OPTIONS */ #define MESH_ENABLED BIT(0) diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 45a07085f..45683d76e 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -73,6 +73,16 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, "Failed to get channel info for OCI element in SA Query Request"); return; } +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->oci_freq_override_saquery_req) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + hapd->conf->oci_freq_override_saquery_req); + ci.frequency = + hapd->conf->oci_freq_override_saquery_req; + } +#endif /* CONFIG_TESTING_OPTIONS */ oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie = os_zalloc(oci_ie_len); @@ -152,6 +162,16 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, "Failed to get channel info for OCI element in SA Query Response"); return; } +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->oci_freq_override_saquery_resp) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + hapd->conf->oci_freq_override_saquery_resp); + ci.frequency = + hapd->conf->oci_freq_override_saquery_resp; + } +#endif /* CONFIG_TESTING_OPTIONS */ oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie = os_zalloc(oci_ie_len); diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 4a7da9513..248f5a1cf 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -103,6 +103,15 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, os_free(wnmtfs_ie); return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->oci_freq_override_wnm_sleep) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + hapd->conf->oci_freq_override_wnm_sleep); + ci.frequency = hapd->conf->oci_freq_override_wnm_sleep; + } +#endif /* CONFIG_TESTING_OPTIONS */ oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie = os_zalloc(oci_ie_len); diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 50b42646e..0efa28797 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2772,6 +2772,15 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, wpabuf_clear_free(plain); return NULL; } +#ifdef CONFIG_TESTING_OPTIONS + if (conf->oci_freq_override_fils_assoc) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + conf->oci_freq_override_fils_assoc); + ci.frequency = conf->oci_freq_override_fils_assoc; + } +#endif /* CONFIG_TESTING_OPTIONS */ pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN); if (ocv_insert_extended_oci(&ci, pos) < 0) { @@ -3237,7 +3246,9 @@ static int ocv_oci_len(struct wpa_state_machine *sm) return 0; } -static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) + +static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos, + unsigned int freq) { #ifdef CONFIG_OCV struct wpa_channel_info ci; @@ -3250,6 +3261,14 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) "Failed to get channel info for OCI element"); return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if (freq) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %u MHz", + ci.frequency, freq); + ci.frequency = freq; + } +#endif /* CONFIG_TESTING_OPTIONS */ return ocv_insert_oci_kde(&ci, argpos); #else /* CONFIG_OCV */ @@ -3466,7 +3485,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) gtk, gtk_len); } pos = ieee80211w_kde_add(sm, pos); - if (ocv_oci_add(sm, &pos) < 0) + if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) goto done; #ifdef CONFIG_IEEE80211R_AP @@ -3816,7 +3835,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gsm->GTK_len); pos = ieee80211w_kde_add(sm, pos); - if (ocv_oci_add(sm, &pos) < 0) { + if (ocv_oci_add(sm, &pos, + conf->oci_freq_override_eapol_g1) < 0) { os_free(kde_buf); return; } @@ -5299,6 +5319,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos; u8 *opos; size_t gtk_len, kde_len; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; u8 *wpa_ie; int wpa_ie_len, secure, gtkidx, encr = 0; @@ -5409,7 +5430,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, opos += 2 + RSN_SELECTOR_LEN + 2; os_memset(opos, 0, 6); /* clear PN */ } - if (ocv_oci_add(sm, &pos) < 0) { + if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) { os_free(kde); return -1; } @@ -5417,9 +5438,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { int res; - struct wpa_auth_config *conf; - conf = &sm->wpa_auth->conf; if (sm->assoc_resp_ftie && kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { os_memcpy(pos, sm->assoc_resp_ftie, @@ -5476,6 +5495,7 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, void *ctx1, void *ctx2) { u8 rsc[WPA_KEY_RSC_LEN]; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; const u8 *kde; u8 *kde_buf = NULL, *pos, hdr[2]; @@ -5510,7 +5530,8 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, opos += 2 + RSN_SELECTOR_LEN + 2; os_memset(opos, 0, 6); /* clear PN */ } - if (ocv_oci_add(sm, &pos) < 0) { + if (ocv_oci_add(sm, &pos, + conf->oci_freq_override_eapol_g1) < 0) { os_free(kde_buf); return -1; } @@ -5552,4 +5573,27 @@ void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val) wpa_auth->conf.ft_rsnxe_used = val; } + +void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth, + enum wpa_auth_ocv_override_frame frame, + unsigned int freq) +{ + if (!wpa_auth) + return; + switch (frame) { + case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3: + wpa_auth->conf.oci_freq_override_eapol_m3 = freq; + break; + case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1: + wpa_auth->conf.oci_freq_override_eapol_g1 = freq; + break; + case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC: + wpa_auth->conf.oci_freq_override_ft_assoc = freq; + break; + case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC: + wpa_auth->conf.oci_freq_override_fils_assoc = freq; + break; + } +} + #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 90b188599..e059f3db3 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -241,6 +241,10 @@ struct wpa_auth_config { unsigned int igtk_rsc_override_set:1; int ft_rsnxe_used; #endif /* CONFIG_TESTING_OPTIONS */ + unsigned int oci_freq_override_eapol_m3; + unsigned int oci_freq_override_eapol_g1; + unsigned int oci_freq_override_ft_assoc; + unsigned int oci_freq_override_fils_assoc; #ifdef CONFIG_P2P u8 ip_addr_go[4]; u8 ip_addr_mask[4]; @@ -526,4 +530,14 @@ int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth); void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm); void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val); +enum wpa_auth_ocv_override_frame { + WPA_AUTH_OCV_OVERRIDE_EAPOL_M3, + WPA_AUTH_OCV_OVERRIDE_EAPOL_G1, + WPA_AUTH_OCV_OVERRIDE_FT_ASSOC, + WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, +}; +void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth, + enum wpa_auth_ocv_override_frame frame, + unsigned int freq); + #endif /* WPA_AUTH_H */ diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 570e2ee4a..db272d41e 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2661,6 +2661,15 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, os_free(subelem); return NULL; } +#ifdef CONFIG_TESTING_OPTIONS + if (conf->oci_freq_override_ft_assoc) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + conf->oci_freq_override_ft_assoc); + ci.frequency = conf->oci_freq_override_ft_assoc; + } +#endif /* CONFIG_TESTING_OPTIONS */ subelem_len += 2 + OCV_OCI_LEN; nbuf = os_realloc(subelem, subelem_len); diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index e1da56da9..b90c9ef61 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -175,6 +175,11 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wconf->igtk_rsc_override_set = 1; } wconf->ft_rsnxe_used = conf->ft_rsnxe_used; + wconf->oci_freq_override_eapol_m3 = conf->oci_freq_override_eapol_m3; + wconf->oci_freq_override_eapol_g1 = conf->oci_freq_override_eapol_g1; + wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc; + wconf->oci_freq_override_fils_assoc = + conf->oci_freq_override_fils_assoc; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_P2P os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); From 8c1f61e820d6590e712fa30f2a6bb31057f81030 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 00:24:15 +0300 Subject: [PATCH 0590/1105] OCV: Report OCI validation failures with OCV-FAILURE messages (STA) Convert the previously used text log entries to use the more formal OCV-FAILURE prefix and always send these as control interface events to allow upper layers to get information about unexpected operating channel mismatches. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 16 ++++++++++------ src/rsn_supp/wpa_ft.c | 5 ++++- wpa_supplicant/sme.c | 5 ++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 482cc0623..0ae73e8f3 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -22,6 +22,7 @@ #include "common/ieee802_11_common.h" #include "common/ocv.h" #include "common/dpp.h" +#include "common/wpa_ctrl.h" #include "eap_common/eap_defs.h" #include "eapol_supp/eapol_supp_sm.h" #include "drivers/driver.h" @@ -1717,8 +1718,9 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "OCV failed: %s", - ocv_errorstr); + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE + "addr=" MACSTR " frame=eapol-key-m3 error=%s", + MAC2STR(sm->bssid), ocv_errorstr); return; } } @@ -1864,8 +1866,9 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "OCV failed: %s", - ocv_errorstr); + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE + "addr=" MACSTR " frame=eapol-key-g1 error=%s", + MAC2STR(sm->bssid), ocv_errorstr); return -1; } } @@ -4764,8 +4767,9 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "FILS: OCV failed: %s", - ocv_errorstr); + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE + "addr=" MACSTR " frame=fils-assoc error=%s", + MAC2STR(sm->bssid), ocv_errorstr); goto fail; } } diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 0cb327d7e..00151df59 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -15,6 +15,7 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/ocv.h" +#include "common/wpa_ctrl.h" #include "drivers/driver.h" #include "wpa.h" #include "wpa_i.h" @@ -1159,7 +1160,9 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE + "addr=" MACSTR " frame=ft-assoc error=%s", + MAC2STR(sm->bssid), ocv_errorstr); return -1; } } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 7e8de4eb7..753e40965 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -2827,7 +2827,10 @@ void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, channel_width_to_int(ci.chanwidth), ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); + wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR + " frame=saquery%s error=%s", + MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ? + "req" : "resp", ocv_errorstr); return; } } From 8019033fc5dff3aae1824950aefeba650c33489c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 00:29:56 +0300 Subject: [PATCH 0591/1105] tests: OCV channel mismatch validation by STA Signed-off-by: Jouni Malinen --- tests/hwsim/test_ocv.py | 96 +++++++++++++++++++++++++++++++---------- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py index 1f185d7e9..bfefcf6b5 100644 --- a/tests/hwsim/test_ocv.py +++ b/tests/hwsim/test_ocv.py @@ -923,15 +923,8 @@ def test_wpa2_ocv_sta_override_eapol(dev, apdev): if "reason=15" not in ev: raise Exception("Unexpected disconnection reason: " + ev) - ev = hapd.wait_event(["OCV-FAILURE"], timeout=1) - if ev is None: - raise Exception("OCV failure for EAPOL-Key msg 2/4 not reported") - if "addr=" + dev[0].own_addr() not in ev: - raise Exception("Unexpected OCV failure addr: " + ev) - if "frame=eapol-key-m2" not in ev: - raise Exception("Unexpected OCV failure frame: " + ev) - if "error=primary channel mismatch" not in ev: - raise Exception("Unexpected OCV failure error: " + ev) + check_ocv_failure(hapd, "EAPOL-Key msg 2/4", "eapol-key-m2", + dev[0].own_addr()) def test_wpa2_ocv_sta_override_sa_query_req(dev, apdev): """OCV on 2.4 GHz and STA override SA Query Request""" @@ -952,15 +945,8 @@ def test_wpa2_ocv_sta_override_sa_query_req(dev, apdev): dev[0].wait_connected() if "OK" not in dev[0].request("UNPROT_DEAUTH"): raise Exception("Triggering SA Query from the STA failed") - ev = hapd.wait_event(["OCV-FAILURE"], timeout=3) - if ev is None: - raise Exception("OCV failure for SA Query Request not reported") - if "addr=" + dev[0].own_addr() not in ev: - raise Exception("Unexpected OCV failure addr: " + ev) - if "frame=saqueryreq" not in ev: - raise Exception("Unexpected OCV failure frame: " + ev) - if "error=primary channel mismatch" not in ev: - raise Exception("Unexpected OCV failure error: " + ev) + check_ocv_failure(hapd, "SA Query Request", "saqueryreq", + dev[0].own_addr()) ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3) if ev is not None: raise Exception("SA Query from the STA failed") @@ -977,12 +963,78 @@ def test_wpa2_ocv_sta_override_sa_query_resp(dev, apdev): hapd.wait_sta() if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()): raise Exception("SA_QUERY failed") - ev = hapd.wait_event(["OCV-FAILURE"], timeout=3) + check_ocv_failure(hapd, "SA Query Response", "saqueryresp", + dev[0].own_addr()) + +def check_ocv_failure(dev, frame_txt, frame, addr): + ev = dev.wait_event(["OCV-FAILURE"], timeout=3) if ev is None: - raise Exception("OCV failure for SA Query Response not reported") - if "addr=" + dev[0].own_addr() not in ev: + raise Exception("OCV failure for %s not reported" % frame_txt) + if "addr=" + addr not in ev: raise Exception("Unexpected OCV failure addr: " + ev) - if "frame=saqueryresp" not in ev: + if "frame=" + frame not in ev: raise Exception("Unexpected OCV failure frame: " + ev) if "error=primary channel mismatch" not in ev: raise Exception("Unexpected OCV failure error: " + ev) + +def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev): + """OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1", + "oci_freq_override_eapol_m3": "2462"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2", wait_connect=False) + + check_ocv_failure(dev[0], "EAPOL-Key msg 3/4", "eapol-key-m3", bssid) + + ev = dev[0].wait_disconnected() + if "reason=15" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + +def test_wpa2_ocv_ap_override_eapol_g1(dev, apdev): + """OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1", + "oci_freq_override_eapol_g1": "2462"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + + if "OK" not in hapd.request("REKEY_GTK"): + raise Exception("REKEY_GTK failed") + check_ocv_failure(dev[0], "EAPOL-Key group msg 1/2", "eapol-key-g1", bssid) + +def test_wpa2_ocv_ap_override_saquery_req(dev, apdev): + """OCV on 2.4 GHz and AP override SA Query Request""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1", + "oci_freq_override_saquery_req": "2462"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + + if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()): + raise Exception("SA_QUERY failed") + check_ocv_failure(dev[0], "SA Query Request", "saqueryreq", bssid) + +def test_wpa2_ocv_ap_override_saquery_resp(dev, apdev): + """OCV on 2.4 GHz and AP override SA Query Response""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1", + "oci_freq_override_saquery_resp": "2462"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + + if "OK" not in dev[0].request("UNPROT_DEAUTH"): + raise Exception("Triggering SA Query from the STA failed") + check_ocv_failure(dev[0], "SA Query Response", "saqueryresp", bssid) From 30885edb7e89a97cd30593a0043eab303683e341 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 1 Jun 2020 22:24:00 +0300 Subject: [PATCH 0592/1105] wpaspy: Be a bit more careful on detaching the control interface Check that the client socket is still open before trying to detach the control interface to avoid undesired exceptions on cleanup paths on unexpected errors due to the socket getting closed. Signed-off-by: Jouni Malinen --- wpaspy/wpaspy.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wpaspy/wpaspy.py b/wpaspy/wpaspy.py index 89e973b98..c50cd531e 100644 --- a/wpaspy/wpaspy.py +++ b/wpaspy/wpaspy.py @@ -113,6 +113,9 @@ class Ctrl: def detach(self): if not self.attached: return None + if self.s.fileno() == -1: + self.attached = False + return None while self.pending(): ev = self.recv() res = self.request("DETACH") From aed01b82d31509119b584df6948264af8d82aa52 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0593/1105] OpenSSL: Additional EC functionality for SAE-PK These will be needed for implementing SAE-PK ECDSA signing and signature verification operations. Signed-off-by: Jouni Malinen --- src/crypto/crypto.h | 12 +++ src/crypto/crypto_openssl.c | 164 ++++++++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+) diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index de2b07732..7d2ebd61c 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -918,4 +918,16 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, void crypto_ecdh_deinit(struct crypto_ecdh *ecdh); size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh); +struct crypto_ec_key; + +struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len); +struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len); +void crypto_ec_key_deinit(struct crypto_ec_key *key); +struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key); +struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, + size_t len); +int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, + size_t len, const u8 *sig, size_t sig_len); +int crypto_ec_key_group(struct crypto_ec_key *key); + #endif /* CRYPTO_H */ diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index 47b6ebbd6..54bfcd25f 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -21,6 +21,7 @@ #endif /* CONFIG_OPENSSL_CMAC */ #ifdef CONFIG_ECC #include +#include #endif /* CONFIG_ECC */ #include "common.h" @@ -79,6 +80,14 @@ static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) bin_clear_free(ctx, sizeof(*ctx)); } + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + #endif /* OpenSSL version < 1.1.0 */ static BIGNUM * get_group5_prime(void) @@ -2174,4 +2183,159 @@ size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) return crypto_ec_prime_len(ecdh->ec); } + +struct crypto_ec_key { + EVP_PKEY *pkey; + EC_KEY *eckey; + BIGNUM *kinv; + BIGNUM *rp; +}; + + +struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len) +{ + struct crypto_ec_key *key; + + key = os_zalloc(sizeof(*key)); + if (!key) + return NULL; + + key->eckey = d2i_ECPrivateKey(NULL, &der, der_len); + if (!key->eckey) { + wpa_printf(MSG_INFO, "OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + EC_KEY_set_conv_form(key->eckey, POINT_CONVERSION_COMPRESSED); + + key->pkey = EVP_PKEY_new(); + if (!key->pkey || EVP_PKEY_assign_EC_KEY(key->pkey, key->eckey) != 1) { + EC_KEY_free(key->eckey); + key->eckey = NULL; + goto fail; + } + + if (ECDSA_sign_setup(key->eckey, NULL, &key->kinv, &key->rp) != 1) + goto fail; + return key; +fail: + crypto_ec_key_deinit(key); + return NULL; +} + + +struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len) +{ + struct crypto_ec_key *key; + + key = os_zalloc(sizeof(*key)); + if (!key) + return NULL; + + key->pkey = d2i_PUBKEY(NULL, &der, der_len); + if (!key->pkey) { + wpa_printf(MSG_INFO, "OpenSSL: d2i_PUBKEY() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + key->eckey = EVP_PKEY_get0_EC_KEY(key->pkey); + if (!key->eckey) + goto fail; + return key; +fail: + crypto_ec_key_deinit(key); + return NULL; +} + + +void crypto_ec_key_deinit(struct crypto_ec_key *key) +{ + if (key) { + EVP_PKEY_free(key->pkey); + BN_clear_free(key->kinv); + BN_clear_free(key->rp); + os_free(key); + } +} + + +struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) +{ + unsigned char *der = NULL; + int der_len; + struct wpabuf *buf; + + der_len = i2d_PUBKEY(key->pkey, &der); + if (der_len <= 0) { + wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return NULL; + } + + buf = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + return buf; +} + + +struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, + size_t len) +{ + struct wpabuf *sig_der; + int res; + unsigned int sig_len; + + sig_len = ECDSA_size(key->eckey); + sig_der = wpabuf_alloc(sig_len); + if (!sig_der) + return NULL; + res = ECDSA_sign_ex(0, data, len, wpabuf_put(sig_der, 0), &sig_len, + key->kinv, key->rp, key->eckey); + if (res != 1) { + wpabuf_free(sig_der); + return NULL; + } + wpabuf_put(sig_der, sig_len); + + return sig_der; +} + + +int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, + size_t len, const u8 *sig, size_t sig_len) +{ + int ret; + + ret = ECDSA_verify(0, data, len, sig, sig_len, key->eckey); + if (ret == 1) + return 1; /* signature ok */ + if (ret == 0) + return 0; /* incorrect signature */ + wpa_printf(MSG_INFO, "OpenSSL: ECDSA_verify() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; +} + + +int crypto_ec_key_group(struct crypto_ec_key *key) +{ + const EC_GROUP *group; + int nid; + + group = EC_KEY_get0_group(key->eckey); + if (!group) + return -1; + nid = EC_GROUP_get_curve_name(group); + switch (nid) { + case NID_X9_62_prime256v1: + return 19; + case NID_secp384r1: + return 20; + case NID_secp521r1: + return 21; + } + return -1; +} + #endif /* CONFIG_ECC */ From b6dcbd01a604088f1152c62ae8a7965df859eaf4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0594/1105] SAE-PK: Identifier definitions Add the assigned identifiers for SAE-PK elements and fields. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_common.c | 1 + src/common/ieee802_11_defs.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 46f4f4d6f..981652e47 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1667,6 +1667,7 @@ const char * status2str(u16 status) S2S(UNKNOWN_AUTHENTICATION_SERVER) S2S(UNKNOWN_PASSWORD_IDENTIFIER) S2S(SAE_HASH_TO_ELEMENT) + S2S(SAE_PK) } return "UNKNOWN"; #undef S2S diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 0dd386f9e..3fc4200a0 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -205,6 +205,7 @@ #define WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER 113 #define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123 #define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126 +#define WLAN_STATUS_SAE_PK 127 /* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */ #define WLAN_REASON_UNSPECIFIED 1 @@ -560,11 +561,13 @@ #define WLAN_EXT_CAPAB_SAE_PW_ID 81 #define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82 #define WLAN_EXT_CAPAB_BEACON_PROTECTION 84 +#define WLAN_EXT_CAPAB_SAE_PK_EXCLUSIVELY 88 /* Extended RSN Capabilities */ /* bits 0-3: Field length (n-1) */ #define WLAN_RSNX_CAPAB_PROTECTED_TWT 4 #define WLAN_RSNX_CAPAB_SAE_H2E 5 +#define WLAN_RSNX_CAPAB_SAE_PK 6 /* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */ #define WLAN_ACTION_SPECTRUM_MGMT 0 @@ -1319,6 +1322,7 @@ struct ieee80211_ampe_ie { #define MULTI_AP_OUI_TYPE 0x1B #define DPP_CC_IE_VENDOR_TYPE 0x506f9a1e #define DPP_CC_OUI_TYPE 0x1e +#define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f #define MULTI_AP_SUB_ELEM_TYPE 0x06 #define MULTI_AP_TEAR_DOWN BIT(4) From 6b9e99e571ee6a075117ccea873b6578ad9ceb04 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0595/1105] SAE-PK: Extend SAE functionality for AP validation This adds core SAE functionality for a new mode of using SAE with a specially constructed password that contains a fingerprint for an AP public key and that public key being used to validate an additional signature in SAE confirm from the AP. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 4 + hostapd/Makefile | 4 + src/ap/ieee802_11.c | 2 +- src/common/sae.c | 91 +++++- src/common/sae.h | 56 +++- src/common/sae_pk.c | 653 ++++++++++++++++++++++++++++++++++++++ wpa_supplicant/Android.mk | 4 + wpa_supplicant/Makefile | 4 + wpa_supplicant/sme.c | 2 +- 9 files changed, 801 insertions(+), 19 deletions(-) create mode 100644 src/common/sae_pk.c diff --git a/hostapd/Android.mk b/hostapd/Android.mk index c389cb75d..6cfbe5c22 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -250,6 +250,10 @@ endif ifdef CONFIG_SAE L_CFLAGS += -DCONFIG_SAE OBJS += src/common/sae.c +ifdef CONFIG_SAE_PK +L_CFLAGS += -DCONFIG_SAE_PK +OBJS += src/common/sae_pk.c +endif NEED_ECC=y NEED_DH_GROUPS=y NEED_HMAC_SHA256_KDF=y diff --git a/hostapd/Makefile b/hostapd/Makefile index 5b0d3b8e3..3cc64c965 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -294,6 +294,10 @@ endif ifdef CONFIG_SAE CFLAGS += -DCONFIG_SAE OBJS += ../src/common/sae.o +ifdef CONFIG_SAE_PK +CFLAGS += -DCONFIG_SAE_PK +OBJS += ../src/common/sae_pk.o +endif NEED_ECC=y NEED_DH_GROUPS=y NEED_HMAC_SHA256_KDF=y diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index c4bf434f2..a10bbdcfb 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -515,7 +515,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, if (update && use_pt && sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr, - NULL) < 0) + NULL, NULL) < 0) return NULL; if (update && !use_pt && diff --git a/src/common/sae.c b/src/common/sae.c index 1b4ec6d81..a298212ca 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -112,6 +112,9 @@ void sae_clear_temp_data(struct sae_data *sae) wpabuf_free(tmp->own_rejected_groups); wpabuf_free(tmp->peer_rejected_groups); os_free(tmp->pw_id); +#ifdef CONFIG_SAE_PK + bin_clear_free(tmp->pw, tmp->pw_len); +#endif /* CONFIG_SAE_PK */ bin_clear_free(tmp, sizeof(*tmp)); sae->tmp = NULL; } @@ -1052,10 +1055,17 @@ sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len, wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group); + if (ssid_len > 32) + return NULL; + pt = os_zalloc(sizeof(*pt)); if (!pt) return NULL; +#ifdef CONFIG_SAE_PK + os_memcpy(pt->ssid, ssid, ssid_len); + pt->ssid_len = ssid_len; +#endif /* CONFIG_SAE_PK */ pt->group = group; pt->ec = crypto_ec_init(group); if (pt->ec) { @@ -1355,13 +1365,14 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2, return -1; sae->tmp->h2e = 0; + sae->tmp->pk = 0; return sae_derive_commit(sae); } int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, const u8 *addr1, const u8 *addr2, - int *rejected_groups) + int *rejected_groups, const struct sae_pk *pk) { if (!sae->tmp) return -1; @@ -1377,6 +1388,20 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, return -1; } +#ifdef CONFIG_SAE_PK + os_memcpy(sae->tmp->ssid, pt->ssid, pt->ssid_len); + sae->tmp->ssid_len = pt->ssid_len; + sae->tmp->ap_pk = pk; + /* TODO: Could support alternative groups as long as the combination + * meets the requirements. */ + if (pk && pk->group != sae->group) { + wpa_printf(MSG_DEBUG, + "SAE-PK: Reject attempt to use group %d since K_AP use group %d", + sae->group, pk->group); + sae->tmp->reject_group = true; + return -1; + } +#endif /* CONFIG_SAE_PK */ sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0; wpabuf_free(sae->tmp->own_rejected_groups); sae->tmp->own_rejected_groups = NULL; @@ -1515,7 +1540,7 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) const u8 *salt; struct wpabuf *rejected_groups = NULL; u8 keyseed[SAE_MAX_HASH_LEN]; - u8 keys[SAE_MAX_HASH_LEN + SAE_PMK_LEN]; + u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN]; struct crypto_bignum *tmp; int ret = -1; size_t hash_len, salt_len, prime_len = sae->tmp->prime_len; @@ -1530,6 +1555,9 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) * KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK", * (commit-scalar + peer-commit-scalar) modulo r) * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128) + * + * When SAE-PK is used, + * KCK || PMK || KEK = KDF-Hash-Length(keyseed, "SAE-PK keys", context) */ if (!sae->tmp->h2e) hash_len = SHA256_MAC_LEN; @@ -1589,15 +1617,32 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) * octets). */ crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len); wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); - if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", + if (!sae->tmp->pk && + sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", val, sae->tmp->order_len, keys, hash_len + SAE_PMK_LEN) < 0) goto fail; +#ifdef CONFIG_SAE_PK + if (sae->tmp->pk && + sae_kdf_hash(hash_len, keyseed, "SAE-PK keys", + val, sae->tmp->order_len, + keys, 2 * hash_len + SAE_PMK_LEN) < 0) + goto fail; +#endif /* CONFIG_SAE_PK */ forced_memzero(keyseed, sizeof(keyseed)); os_memcpy(sae->tmp->kck, keys, hash_len); sae->tmp->kck_len = hash_len; os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN); os_memcpy(sae->pmkid, val, SAE_PMKID_LEN); +#ifdef CONFIG_SAE_PK + if (sae->tmp->pk) { + os_memcpy(sae->tmp->kek, keys + hash_len + SAE_PMK_LEN, + hash_len); + sae->tmp->kek_len = hash_len; + wpa_hexdump_key(MSG_DEBUG, "SAE: KEK for SAE-PK", + sae->tmp->kek, sae->tmp->kek_len); + } +#endif /* CONFIG_SAE_PK */ forced_memzero(keys, sizeof(keys)); wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, sae->tmp->kck_len); @@ -2189,13 +2234,14 @@ static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc, } -void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) +int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) { const u8 *sc; size_t hash_len; + int res; if (sae->tmp == NULL) - return; + return -1; hash_len = sae->tmp->kck_len; @@ -2206,17 +2252,26 @@ void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) sae->send_confirm++; if (sae->tmp->ec) - sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, - sae->tmp->own_commit_element_ecc, - sae->peer_commit_scalar, - sae->tmp->peer_commit_element_ecc, - wpabuf_put(buf, hash_len)); + res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, + sae->tmp->own_commit_element_ecc, + sae->peer_commit_scalar, + sae->tmp->peer_commit_element_ecc, + wpabuf_put(buf, hash_len)); else - sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, - sae->tmp->own_commit_element_ffc, - sae->peer_commit_scalar, - sae->tmp->peer_commit_element_ffc, - wpabuf_put(buf, hash_len)); + res = sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, + sae->tmp->own_commit_element_ffc, + sae->peer_commit_scalar, + sae->tmp->peer_commit_element_ffc, + wpabuf_put(buf, hash_len)); + if (res) + return res; + +#ifdef CONFIG_SAE_PK + if (sae_write_confirm_pk(sae, buf) < 0) + return -1; +#endif /* CONFIG_SAE_PK */ + + return 0; } @@ -2270,6 +2325,12 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) return -1; } +#ifdef CONFIG_SAE_PK + if (sae_check_confirm_pk(sae, data + 2 + hash_len, + len - 2 - hash_len) < 0) + return -1; +#endif /* CONFIG_SAE_PK */ + return 0; } diff --git a/src/common/sae.h b/src/common/sae.h index 7966d70e4..61b228819 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -16,11 +16,24 @@ #define SAE_MAX_ECC_PRIME_LEN 66 #define SAE_MAX_HASH_LEN 64 #define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN + 255) +#ifdef CONFIG_SAE_PK +#define SAE_CONFIRM_MAX_LEN ((2 + SAE_MAX_HASH_LEN) + 1500) +#else /* CONFIG_SAE_PK */ #define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_HASH_LEN) +#endif /* CONFIG_SAE_PK */ +#define SAE_PK_M_LEN 16 /* Special value returned by sae_parse_commit() */ #define SAE_SILENTLY_DISCARD 65535 +struct sae_pk { + struct wpabuf *m; + struct crypto_ec_key *key; + int group; + struct wpabuf *pubkey; /* DER encoded subjectPublicKey */ +}; + + struct sae_temporary_data { u8 kck[SAE_MAX_HASH_LEN]; size_t kck_len; @@ -47,7 +60,22 @@ struct sae_temporary_data { struct wpabuf *own_rejected_groups; struct wpabuf *peer_rejected_groups; unsigned int h2e:1; + unsigned int pk:1; unsigned int own_addr_higher:1; + +#ifdef CONFIG_SAE_PK + u8 kek[SAE_MAX_HASH_LEN]; + size_t kek_len; + const struct sae_pk *ap_pk; + u8 own_addr[ETH_ALEN]; + u8 peer_addr[ETH_ALEN]; + u8 *pw; + size_t pw_len; + size_t lambda; + u8 ssid[32]; + size_t ssid_len; + bool reject_group; +#endif /* CONFIG_SAE_PK */ }; struct sae_pt { @@ -58,6 +86,10 @@ struct sae_pt { const struct dh_group *dh; struct crypto_bignum *ffc_pt; +#ifdef CONFIG_SAE_PK + u8 ssid[32]; + size_t ssid_len; +#endif /* CONFIG_SAE_PK */ }; enum sae_state { @@ -86,17 +118,19 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2, const char *identifier, struct sae_data *sae); int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, const u8 *addr1, const u8 *addr2, - int *rejected_groups); + int *rejected_groups, const struct sae_pk *pk); int sae_process_commit(struct sae_data *sae); int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, const struct wpabuf *token, const char *identifier); u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, const u8 **token, size_t *token_len, int *allowed_groups, int h2e); -void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf); +int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf); int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len); u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group); const char * sae_state_txt(enum sae_state state); +size_t sae_ecc_prime_len_2_hash_len(size_t prime_len); +size_t sae_ffc_prime_len_2_hash_len(size_t prime_len); struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len, const u8 *password, size_t password_len, const char *identifier); @@ -108,4 +142,22 @@ sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt, const u8 *addr1, const u8 *addr2); void sae_deinit_pt(struct sae_pt *pt); +/* sae_pk.c */ +#ifdef CONFIG_SAE_PK +bool sae_pk_valid_password(const char *pw); +#else /* CONFIG_SAE_PK */ +static inline bool sae_pk_valid_password(const char *pw) +{ + return false; +} +#endif /* CONFIG_SAE_PK */ +char * sae_pk_base32_encode(const u8 *src, size_t len_bits); +u8 * sae_pk_base32_decode(const char *src, size_t len, size_t *out_len); +int sae_pk_set_password(struct sae_data *sae, const char *password); +void sae_deinit_pk(struct sae_pk *pk); +struct sae_pk * sae_parse_pk(const char *val); +int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf); +int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len); +int sae_hash(size_t hash_len, const u8 *data, size_t len, u8 *hash); + #endif /* SAE_H */ diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c new file mode 100644 index 000000000..df0f7db9d --- /dev/null +++ b/src/common/sae_pk.c @@ -0,0 +1,653 @@ +/* + * SAE-PK + * Copyright (c) 2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include + +#include "utils/common.h" +#include "utils/base64.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "crypto/crypto.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "sae.h" + + +/* RFC 4648 base 32 alphabet with lowercase characters */ +static const char *sae_pk_base32_table = "abcdefghijklmnopqrstuvwxyz234567"; + + +bool sae_pk_valid_password(const char *pw) +{ + int pos; + + /* Minimum password length for SAE-PK is not defined, but the automatic + * password style determination is more reliable if at least one hyphen + * is forced to be present in the password. */ + if (os_strlen(pw) < 6) + return false; + + for (pos = 0; pw[pos]; pos++) { + if (pos && pos % 5 == 4) { + if (pw[pos] != '-') + return false; + continue; + } + if (!os_strchr(sae_pk_base32_table, pw[pos])) + return false; + } + if (pos == 0) + return false; + return pw[pos - 1] != '-'; +} + + +static char * add_char(const char *start, char *pos, u8 idx, size_t *bits) +{ + if (*bits == 0) + return pos; + if (*bits > 5) + *bits -= 5; + else + *bits = 0; + + if ((pos - start) % 5 == 4) + *pos++ = '-'; + *pos++ = sae_pk_base32_table[idx]; + return pos; +} + + +char * sae_pk_base32_encode(const u8 *src, size_t len_bits) +{ + char *out, *pos; + size_t olen, extra_pad, i; + u64 block = 0; + u8 val; + size_t len = (len_bits + 7) / 8; + size_t left = len_bits; + int j; + + if (len == 0 || len >= SIZE_MAX / 8) + return NULL; + olen = len * 8 / 5 + 1; + olen += olen / 4; /* hyphen separators */ + pos = out = os_zalloc(olen + 1); + if (!out) + return NULL; + + extra_pad = (5 - len % 5) % 5; + for (i = 0; i < len + extra_pad; i++) { + val = i < len ? src[i] : 0; + block <<= 8; + block |= val; + if (i % 5 == 4) { + for (j = 7; j >= 0; j--) + pos = add_char(out, pos, + (block >> j * 5) & 0x1f, &left); + block = 0; + } + } + + return out; +} + + +u8 * sae_pk_base32_decode(const char *src, size_t len, size_t *out_len) +{ + u8 dtable[256], *out, *pos, tmp; + u64 block = 0; + size_t i, count, olen; + int pad = 0; + size_t extra_pad; + + os_memset(dtable, 0x80, 256); + for (i = 0; sae_pk_base32_table[i]; i++) + dtable[(u8) sae_pk_base32_table[i]] = i; + dtable['='] = 0; + + count = 0; + for (i = 0; i < len; i++) { + if (dtable[(u8) src[i]] != 0x80) + count++; + } + + if (count == 0) + return NULL; + extra_pad = (8 - count % 8) % 8; + + olen = (count + extra_pad) / 8 * 5; + pos = out = os_malloc(olen); + if (!out) + return NULL; + + count = 0; + for (i = 0; i < len + extra_pad; i++) { + u8 val; + + if (i >= len) + val = '='; + else + val = src[i]; + tmp = dtable[val]; + if (tmp == 0x80) + continue; + + if (val == '=') + pad++; + block <<= 5; + block |= tmp; + count++; + if (count == 8) { + *pos++ = (block >> 32) & 0xff; + *pos++ = (block >> 24) & 0xff; + *pos++ = (block >> 16) & 0xff; + *pos++ = (block >> 8) & 0xff; + *pos++ = block & 0xff; + count = 0; + block = 0; + if (pad) { + /* Leave in all the available bits with zero + * padding to full octets from right. */ + pos -= pad * 5 / 8; + break; + } + } + } + + *out_len = pos - out; + return out; +} + + +int sae_pk_set_password(struct sae_data *sae, const char *password) +{ + struct sae_temporary_data *tmp = sae->tmp; + size_t len; + + len = os_strlen(password); + if (!tmp || len < 1) + return -1; + + bin_clear_free(tmp->pw, tmp->pw_len); + tmp->pw = sae_pk_base32_decode(password, len, &tmp->pw_len); + tmp->lambda = len - len / 5; + return tmp->pw ? 0 : -1; +} + + +void sae_deinit_pk(struct sae_pk *pk) +{ + if (pk) { + wpabuf_free(pk->m); + crypto_ec_key_deinit(pk->key); + wpabuf_free(pk->pubkey); + os_free(pk); + } +} + + +struct sae_pk * sae_parse_pk(const char *val) +{ + struct sae_pk *pk; + const char *pos; + size_t len; + unsigned char *der; + size_t der_len; + + /* : */ + + pos = os_strchr(val, ':'); + if (!pos || (pos - val) & 0x01) + return NULL; + len = (pos - val) / 2; + if (len != SAE_PK_M_LEN) { + wpa_printf(MSG_INFO, "SAE: Unexpected Modifier M length %zu", + len); + return NULL; + } + + pk = os_zalloc(sizeof(*pk)); + if (!pk) + return NULL; + pk->m = wpabuf_alloc(len); + if (!pk->m || hexstr2bin(val, wpabuf_put(pk->m, len), len)) { + wpa_printf(MSG_INFO, "SAE: Failed to parse m"); + goto fail; + } + + pos++; + der = base64_decode(pos, os_strlen(pos), &der_len); + if (!der) { + wpa_printf(MSG_INFO, "SAE: Failed to base64 decode PK key"); + goto fail; + } + + pk->key = crypto_ec_key_parse_priv(der, der_len); + bin_clear_free(der, der_len); + if (!pk->key) + goto fail; + pk->group = crypto_ec_key_group(pk->key); + pk->pubkey = crypto_ec_key_get_subject_public_key(pk->key); + if (!pk->pubkey) + goto fail; + + return pk; +fail: + sae_deinit_pk(pk); + return NULL; +} + + +int sae_hash(size_t hash_len, const u8 *data, size_t len, u8 *hash) +{ + if (hash_len == 32) + return sha256_vector(1, &data, &len, hash); +#ifdef CONFIG_SHA384 + if (hash_len == 48) + return sha384_vector(1, &data, &len, hash); +#endif /* CONFIG_SHA384 */ +#ifdef CONFIG_SHA512 + if (hash_len == 64) + return sha512_vector(1, &data, &len, hash); +#endif /* CONFIG_SHA512 */ + return -1; +} + + +static int sae_pk_hash_sig_data(struct sae_data *sae, size_t hash_len, + bool ap, const u8 *m, size_t m_len, + const u8 *pubkey, size_t pubkey_len, u8 *hash) +{ + struct sae_temporary_data *tmp = sae->tmp; + struct wpabuf *sig_data; + u8 *pos; + int ret = -1; + + /* Signed data for KeyAuth: eleAP || eleSTA || scaAP || scaSTA || + * M || K_AP || AP-BSSID || STA-MAC */ + sig_data = wpabuf_alloc(tmp->prime_len * 6 + m_len + pubkey_len + + 2 * ETH_ALEN); + if (!sig_data) + goto fail; + pos = wpabuf_put(sig_data, 2 * tmp->prime_len); + if (crypto_ec_point_to_bin(tmp->ec, ap ? tmp->own_commit_element_ecc : + tmp->peer_commit_element_ecc, + pos, pos + tmp->prime_len) < 0) + goto fail; + pos = wpabuf_put(sig_data, 2 * tmp->prime_len); + if (crypto_ec_point_to_bin(tmp->ec, ap ? tmp->peer_commit_element_ecc : + tmp->own_commit_element_ecc, + pos, pos + tmp->prime_len) < 0) + goto fail; + if (crypto_bignum_to_bin(ap ? tmp->own_commit_scalar : + sae->peer_commit_scalar, + wpabuf_put(sig_data, tmp->prime_len), + tmp->prime_len, tmp->prime_len) < 0 || + crypto_bignum_to_bin(ap ? sae->peer_commit_scalar : + tmp->own_commit_scalar, + wpabuf_put(sig_data, tmp->prime_len), + tmp->prime_len, tmp->prime_len) < 0) + goto fail; + wpabuf_put_data(sig_data, m, m_len); + wpabuf_put_data(sig_data, pubkey, pubkey_len); + wpabuf_put_data(sig_data, ap ? tmp->own_addr : tmp->peer_addr, + ETH_ALEN); + wpabuf_put_data(sig_data, ap ? tmp->peer_addr : tmp->own_addr, + ETH_ALEN); + wpa_hexdump_buf_key(MSG_DEBUG, "SAE-PK: Data to be signed for KeyAuth", + sig_data); + if (sae_hash(hash_len, wpabuf_head(sig_data), wpabuf_len(sig_data), + hash) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "SAE-PK: hash(data to be signed)", + hash, hash_len); + ret = 0; +fail: + wpabuf_free(sig_data); + return ret; +} + + +int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) +{ + struct sae_temporary_data *tmp = sae->tmp; + struct wpabuf *elem = NULL, *sig = NULL; + size_t extra; + int ret = -1; + u8 *encr_mod; + size_t encr_mod_len; + const struct sae_pk *pk; + u8 hash[SAE_MAX_HASH_LEN]; + size_t hash_len; + + if (!tmp) + return -1; + + pk = tmp->ap_pk; + if (!pk) + return 0; + + if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { + wpa_printf(MSG_INFO, "SAE-PK: No KEK available for confirm"); + return -1; + } + + if (!tmp->ec) { + /* Only ECC groups are supported for SAE-PK in the current + * implementation. */ + wpa_printf(MSG_INFO, + "SAE-PK: SAE commit did not use an ECC group"); + return -1; + } + + hash_len = sae_ecc_prime_len_2_hash_len(tmp->prime_len); + if (sae_pk_hash_sig_data(sae, hash_len, true, wpabuf_head(pk->m), + wpabuf_len(pk->m), wpabuf_head(pk->pubkey), + wpabuf_len(pk->pubkey), hash) < 0) + goto fail; + sig = crypto_ec_key_sign(pk->key, hash, hash_len); + if (!sig) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "SAE-PK: KeyAuth = Sig_AP()", sig); + + elem = wpabuf_alloc(1500 + wpabuf_len(sig)); + if (!elem) + goto fail; + + /* EncryptedModifier = AES-SIV-Q(M); no AAD */ + encr_mod_len = wpabuf_len(pk->m) + AES_BLOCK_SIZE; + wpabuf_put_u8(elem, encr_mod_len); + encr_mod = wpabuf_put(elem, encr_mod_len); + if (aes_siv_encrypt(tmp->kek, tmp->kek_len, + wpabuf_head(pk->m), wpabuf_len(pk->m), + 0, NULL, NULL, encr_mod) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier", + encr_mod, encr_mod_len); + + /* FILS Public Key element */ + wpabuf_put_u8(elem, WLAN_EID_EXTENSION); + wpabuf_put_u8(elem, 2 + wpabuf_len(pk->pubkey)); + wpabuf_put_u8(elem, WLAN_EID_EXT_FILS_PUBLIC_KEY); + wpabuf_put_u8(elem, 3); /* Key Type: ECDSA public key */ + wpabuf_put_buf(elem, pk->pubkey); + + /* FILS Key Confirmation element (KeyAuth) */ + wpabuf_put_u8(elem, WLAN_EID_EXTENSION); + wpabuf_put_u8(elem, 1 + wpabuf_len(sig)); + wpabuf_put_u8(elem, WLAN_EID_EXT_FILS_KEY_CONFIRM); + /* KeyAuth = Sig_AP(eleAP || eleSTA || scaAP || scaSTA || M || K_AP || + * AP-BSSID || STA-MAC) */ + wpabuf_put_buf(elem, sig); + + /* TODO: fragmentation */ + extra = 6; /* Vendor specific element header */ + + if (wpabuf_tailroom(elem) < extra + wpabuf_len(buf)) { + wpa_printf(MSG_INFO, + "SAE-PK: No room in message buffer for SAE-PK element (%zu < %zu)", + wpabuf_tailroom(buf), extra + wpabuf_len(buf)); + goto fail; + } + + /* SAE-PK element */ + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(buf, 4 + wpabuf_len(elem)); + wpabuf_put_be32(buf, SAE_PK_IE_VENDOR_TYPE); + wpabuf_put_buf(buf, elem); + + ret = 0; +fail: + wpabuf_free(elem); + wpabuf_free(sig); + return ret; + +} + + +static bool sae_pk_valid_fingerprint(struct sae_data *sae, + const u8 *m, size_t m_len, + const u8 *k_ap, size_t k_ap_len) +{ + struct sae_temporary_data *tmp = sae->tmp; + size_t sec, i; + u8 *fingerprint_exp, *hash_data, *pos; + size_t hash_len, hash_data_len, fingerprint_bits, fingerprint_bytes; + u8 hash[SAE_MAX_HASH_LEN]; + int res; + + if (!tmp->pw || tmp->pw_len < 1) { + wpa_printf(MSG_DEBUG, + "SAE-PK: No PW available for K_AP fingerprint check"); + return false; + } + + /* Fingerprint = L(Hash(SSID || M || K_AP), 0, 8*Sec + 5*Lambda - 2) */ + + hash_len = sae_ecc_prime_len_2_hash_len(tmp->prime_len); + hash_data_len = tmp->ssid_len + m_len + k_ap_len; + hash_data = os_malloc(hash_data_len); + if (!hash_data) + return false; + pos = hash_data; + os_memcpy(pos, tmp->ssid, tmp->ssid_len); + pos += tmp->ssid_len; + os_memcpy(pos, m, m_len); + pos += m_len; + os_memcpy(pos, k_ap, k_ap_len); + + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: SSID || M || K_AP", + hash_data, hash_data_len); + res = sae_hash(hash_len, hash_data, hash_data_len, hash); + bin_clear_free(hash_data, hash_data_len); + if (res < 0) + return false; + wpa_hexdump(MSG_DEBUG, "SAE-PK: Hash(SSID || M || K_AP)", + hash, hash_len); + + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: PW", tmp->pw, tmp->pw_len); + sec = (tmp->pw[0] >> 6) + 2; + fingerprint_bits = 8 * sec + 5 * tmp->lambda - 2; + wpa_printf(MSG_DEBUG, "SAE-PK: Sec=%zu Lambda=%zu fingerprint_bits=%zu", + sec, tmp->lambda, fingerprint_bits); + if (fingerprint_bits > hash_len * 8) { + wpa_printf(MSG_INFO, + "SAE-PK: Not enough hash output bits for the fingerprint"); + return false; + } + fingerprint_bytes = (fingerprint_bits + 7) / 8; + if (fingerprint_bits % 8) { + size_t extra; + + /* Zero out the extra bits in the last octet */ + extra = 8 - fingerprint_bits % 8; + pos = &hash[fingerprint_bits / 8]; + *pos = (*pos >> extra) << extra; + } + wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint", hash, fingerprint_bytes); + + fingerprint_exp = os_zalloc(sec + tmp->pw_len); + if (!fingerprint_exp) + return false; + pos = fingerprint_exp + sec; + for (i = 0; i < tmp->pw_len; i++) { + u8 next = i + 1 < tmp->pw_len ? tmp->pw[i + 1] : 0; + + *pos++ = tmp->pw[i] << 2 | next >> 6; + } + + wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint_Expected", + fingerprint_exp, fingerprint_bytes); + res = os_memcmp_const(hash, fingerprint_exp, fingerprint_bytes); + bin_clear_free(fingerprint_exp, tmp->pw_len); + + if (res) { + wpa_printf(MSG_DEBUG, "SAE-PK: K_AP fingerprint mismatch"); + return false; + } + + wpa_printf(MSG_DEBUG, "SAE-PK: Valid K_AP fingerprint"); + return true; +} + + +int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) +{ + struct sae_temporary_data *tmp = sae->tmp; + const u8 *sae_pk, *pos, *end, *encr_mod, *k_ap, *key_auth; + u8 m[SAE_PK_M_LEN]; + size_t k_ap_len, key_auth_len; + struct crypto_ec_key *key; + int res; + u8 hash[SAE_MAX_HASH_LEN]; + size_t hash_len; + int group; + + if (!tmp) + return -1; + if (!tmp->pk || tmp->ap_pk) + return 0; + + if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { + wpa_printf(MSG_INFO, "SAE-PK: No KEK available for confirm"); + return -1; + } + + if (!tmp->ec) { + /* Only ECC groups are supported for SAE-PK in the current + * implementation. */ + wpa_printf(MSG_INFO, + "SAE-PK: SAE commit did not use an ECC group"); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "SAE-PK: Received confirm IEs", ies, ies_len); + sae_pk = get_vendor_ie(ies, ies_len, SAE_PK_IE_VENDOR_TYPE); + if (!sae_pk) { + wpa_printf(MSG_INFO, "SAE-PK: No SAE-PK element included"); + return -1; + } + /* TODO: Fragment reassembly */ + pos = sae_pk + 2; + end = pos + sae_pk[1]; + + if (end - pos < 4 + 1 + SAE_PK_M_LEN + AES_BLOCK_SIZE) { + wpa_printf(MSG_INFO, + "SAE-PK: No room for EncryptedModifier in SAE-PK element"); + return -1; + } + pos += 4; + if (*pos != SAE_PK_M_LEN + AES_BLOCK_SIZE) { + wpa_printf(MSG_INFO, + "SAE-PK: Unexpected EncryptedModifier length %u", + *pos); + return -1; + } + pos++; + encr_mod = pos; + pos += SAE_PK_M_LEN + AES_BLOCK_SIZE; + + if (end - pos < 4 || pos[0] != WLAN_EID_EXTENSION || pos[1] < 2 || + pos[1] > end - pos - 2 || + pos[2] != WLAN_EID_EXT_FILS_PUBLIC_KEY) { + wpa_printf(MSG_INFO, + "SAE-PK: No FILS Public Key element in SAE-PK element"); + return -1; + } + if (pos[3] != 3) { + wpa_printf(MSG_INFO, "SAE-PK: Unsupported public key type %u", + pos[3]); + return -1; + } + k_ap_len = pos[1] - 2; + pos += 4; + k_ap = pos; + pos += k_ap_len; + + if (end - pos < 4 || pos[0] != WLAN_EID_EXTENSION || pos[1] < 1 || + pos[1] > end - pos - 2 || + pos[2] != WLAN_EID_EXT_FILS_KEY_CONFIRM) { + wpa_printf(MSG_INFO, + "SAE-PK: No FILS Key Confirm element in SAE-PK element"); + return -1; + } + key_auth_len = pos[1] - 1; + pos += 3; + key_auth = pos; + pos += key_auth_len; + + if (pos < end) { + wpa_hexdump(MSG_DEBUG, + "SAE-PK: Extra data at the end of SAE-PK element", + pos, end - pos); + } + + wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier", + encr_mod, SAE_PK_M_LEN + AES_BLOCK_SIZE); + + if (aes_siv_decrypt(tmp->kek, tmp->kek_len, + encr_mod, SAE_PK_M_LEN + AES_BLOCK_SIZE, + 0, NULL, NULL, m) < 0) { + wpa_printf(MSG_INFO, + "SAE-PK: Failed to decrypt EncryptedModifier"); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Modifier M", m, SAE_PK_M_LEN); + + wpa_hexdump(MSG_DEBUG, "SAE-PK: Received K_AP", k_ap, k_ap_len); + /* TODO: Check against the public key, if one is stored in the network + * profile */ + + if (!sae_pk_valid_fingerprint(sae, m, SAE_PK_M_LEN, k_ap, k_ap_len)) + return -1; + + key = crypto_ec_key_parse_pub(k_ap, k_ap_len); + if (!key) { + wpa_printf(MSG_INFO, "SAE-PK: Failed to parse K_AP"); + return -1; + } + + group = crypto_ec_key_group(key); + /* TODO: Could support alternative groups as long as the combination + * meets the requirements. */ + if (group != sae->group) { + wpa_printf(MSG_INFO, + "SAE-PK: K_AP group %d does not match SAE group %d", + group, sae->group); + crypto_ec_key_deinit(key); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "SAE-PK: Received KeyAuth", + key_auth, key_auth_len); + + hash_len = sae_ecc_prime_len_2_hash_len(tmp->prime_len); + if (sae_pk_hash_sig_data(sae, hash_len, false, m, SAE_PK_M_LEN, + k_ap, k_ap_len, hash) < 0) { + crypto_ec_key_deinit(key); + return -1; + } + + res = crypto_ec_key_verify_signature(key, hash, hash_len, + key_auth, key_auth_len); + crypto_ec_key_deinit(key); + + if (res != 1) { + wpa_printf(MSG_INFO, + "SAE-PK: Invalid or incorrect signature in KeyAuth"); + return -1; + } + + wpa_printf(MSG_DEBUG, "SAE-PK: Valid KeyAuth signature received"); + + /* TODO: Store validated public key into network profile */ + + return 0; +} diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index a0c9e23c8..0f24d7b71 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -235,6 +235,10 @@ endif ifdef CONFIG_SAE L_CFLAGS += -DCONFIG_SAE OBJS += src/common/sae.c +ifdef CONFIG_SAE_PK +L_CFLAGS += -DCONFIG_SAE_PK +OBJS += src/common/sae_pk.c +endif NEED_ECC=y NEED_DH_GROUPS=y NEED_HMAC_SHA256_KDF=y diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index f4878807d..09ac7a493 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -267,6 +267,10 @@ endif ifdef CONFIG_SAE CFLAGS += -DCONFIG_SAE OBJS += ../src/common/sae.o +ifdef CONFIG_SAE_PK +CFLAGS += -DCONFIG_SAE_PK +OBJS += ../src/common/sae_pk.o +endif NEED_ECC=y NEED_DH_GROUPS=y NEED_HMAC_SHA256_KDF=y diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 753e40965..d03b0ce8a 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -157,7 +157,7 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, if (use_pt && sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt, wpa_s->own_addr, bssid, - wpa_s->sme.sae_rejected_groups) < 0) + wpa_s->sme.sae_rejected_groups, NULL) < 0) return NULL; if (!use_pt && sae_prepare_commit(wpa_s->own_addr, bssid, From 00e4fbdcc5fdb37f4a08e6495c78787cf19601d4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0596/1105] tests: Module test for SAE-PK Signed-off-by: Jouni Malinen --- src/common/common_module_tests.c | 107 +++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c index a58bf666a..77d6001c8 100644 --- a/src/common/common_module_tests.c +++ b/src/common/common_module_tests.c @@ -548,6 +548,112 @@ fail: } +static int sae_pk_tests(void) +{ +#ifdef CONFIG_SAE_PK + const char *invalid[] = { "a2bc-de3f-ghi4-", "a2bcde3fghi4", "", NULL }; + struct { + const char *pw; + const u8 *val; + } valid[] = { + { "a2bc-de3f-ghi4", (u8 *) "\x06\x82\x21\x93\x65\x31\xd1\xc0" }, + { "ci2f-m6e2", (u8 *) "\x12\x34\x56\x78\x9a" }, + { "aaaa-aaaa-aaaa-a", + (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, + { "aaaa-aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00" }, + { "aaaa-aaaa-aa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00" }, + { "aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00" }, + { "aaaa-aaa", (u8 *) "\x00\x00\x00\x00\x00" }, + { "aaaa-a", (u8 *) "\x00\x00\x00\x00" }, + { "aeaa-a", (u8 *) "\x01\x00\x00\x00" }, + { "7777-7", (u8 *) "\xff\xff\xff\x80" }, + { "7777-77", (u8 *) "\xff\xff\xff\xfc" }, + { "7777-777", (u8 *) "\xff\xff\xff\xff\xe0" }, + { "7777-7777", (u8 *) "\xff\xff\xff\xff\xff" }, + { "7777-7777-7", (u8 *) "\xff\xff\xff\xff\xff\xf8" }, + { "7777-7777-77", (u8 *) "\xff\xff\xff\xff\xff\xff\xc0" }, + { "7777-7777-777", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe" }, + { "7777-7777-7777", (u8 *) "\xff\xff\xff\xff\xff\xff\xff\xf0" }, + { "7777-7777-7777-7", + (u8 *) "\xff\xff\xff\xff\xff\xff\xff\xff\x80" }, + { NULL, NULL } + }; + int i; + bool failed; + + for (i = 0; invalid[i]; i++) { + if (sae_pk_valid_password(invalid[i])) { + wpa_printf(MSG_ERROR, + "SAE-PK: Invalid password '%s' not recognized", + invalid[i]); + return -1; + } + } + + failed = false; + for (i = 0; valid[i].pw; i++) { + u8 *res; + size_t res_len; + char *b32; + const char *pw = valid[i].pw; + const u8 *val = valid[i].val; + size_t pw_len = os_strlen(pw); + size_t bits = (pw_len - pw_len / 5) * 5; + size_t bytes = (bits + 7) / 8; + + if (!sae_pk_valid_password(pw)) { + wpa_printf(MSG_ERROR, + "SAE-PK: Valid password '%s' not recognized", + pw); + failed = true; + continue; + } + + res = sae_pk_base32_decode(pw, pw_len, &res_len); + if (!res) { + wpa_printf(MSG_ERROR, + "SAE-PK: Failed to decode password '%s'", + valid[i].pw); + failed = true; + continue; + } + if (res_len != bytes || os_memcmp(val, res, res_len) != 0) { + wpa_printf(MSG_ERROR, + "SAE-PK: Mismatch for decoded password '%s'", + valid[i].pw); + wpa_hexdump(MSG_INFO, "SAE-PK: Decoded value", + res, res_len); + wpa_hexdump(MSG_INFO, "SAE-PK: Expected value", + val, bytes); + failed = true; + } + os_free(res); + + b32 = sae_pk_base32_encode(val, bits); + if (!b32) { + wpa_printf(MSG_ERROR, + "SAE-PK: Failed to encode password '%s'", + pw); + failed = true; + continue; + } + if (os_strcmp(b32, pw) != 0) { + wpa_printf(MSG_ERROR, + "SAE-PK: Mismatch for password '%s'", pw); + wpa_printf(MSG_INFO, "SAE-PK: Encoded value: '%s'", + b32); + failed = true; + } + os_free(b32); + } + + return failed ? -1 : 0; +#else /* CONFIG_SAE_PK */ + return 0; +#endif /* CONFIG_SAE_PK */ +} + + int common_module_tests(void) { int ret = 0; @@ -557,6 +663,7 @@ int common_module_tests(void) if (ieee802_11_parse_tests() < 0 || gas_tests() < 0 || sae_tests() < 0 || + sae_pk_tests() < 0 || rsn_ie_parse_tests() < 0) ret = -1; From 20ccf97b3dc1733a70818435298e2ec432458e4b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0597/1105] SAE-PK: AP functionality This adds AP side functionality for SAE-PK. The new sae_password configuration parameters can now be used to enable SAE-PK mode whenever SAE is enabled. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 41 ++++++++++++++++ hostapd/hostapd.conf | 3 +- src/ap/ap_config.c | 69 ++++++++++++++++++++++++++- src/ap/ap_config.h | 3 ++ src/ap/ieee802_11.c | 96 ++++++++++++++++++++++++++++++-------- src/ap/ieee802_11_shared.c | 28 ++++++++++- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 3 ++ src/ap/wpa_auth_ie.c | 9 +++- 9 files changed, 228 insertions(+), 25 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index bc650e949..49894c5ba 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -14,6 +14,7 @@ #include "utils/common.h" #include "utils/uuid.h" #include "common/ieee802_11_defs.h" +#include "common/sae.h" #include "crypto/sha256.h" #include "crypto/tls.h" #include "drivers/driver.h" @@ -2290,6 +2291,35 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val) pw->vlan_id = atoi(pos2); } +#ifdef CONFIG_SAE_PK + pos2 = os_strstr(pos, "|pk="); + if (pos2) { + const char *epos; + char *tmp; + + if (!end) + end = pos2; + pos2 += 4; + epos = os_strchr(pos2, '|'); + if (epos) { + tmp = os_malloc(epos - pos2 + 1); + if (!tmp) + goto fail; + os_memcpy(tmp, pos2, epos - pos2); + tmp[epos - pos2] = '\0'; + } else { + tmp = os_strdup(pos2); + if (!tmp) + goto fail; + } + + pw->pk = sae_parse_pk(tmp); + str_clear_free(tmp); + if (!pw->pk) + goto fail; + } +#endif /* CONFIG_SAE_PK */ + pos2 = os_strstr(pos, "|id="); if (pos2) { if (!end) @@ -2312,6 +2342,14 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val) pw->password[end - val] = '\0'; } +#ifdef CONFIG_SAE_PK + if (pw->pk && !sae_pk_valid_password(pw->password)) { + wpa_printf(MSG_INFO, + "Invalid SAE password for a SAE-PK sae_password entry"); + goto fail; + } +#endif /* CONFIG_SAE_PK */ + pw->next = bss->sae_passwords; bss->sae_passwords = pw; @@ -2319,6 +2357,9 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val) fail: str_clear_free(pw->password); os_free(pw->identifier); +#ifdef CONFIG_SAE_PK + sae_deinit_pk(pw->pk); +#endif /* CONFIG_SAE_PK */ os_free(pw); return -1; } diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 812c09a9f..2b0f762e5 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1776,7 +1776,8 @@ own_ip_addr=127.0.0.1 # special meaning of removing all previously added entries. # # sae_password uses the following encoding: -#[|mac=][|vlanid=][|id=] +#[|mac=][|vlanid=] +#[|pk=][|id=] # Examples: #sae_password=secret #sae_password=really secret|mac=ff:ff:ff:ff:ff:ff diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 35a32a130..a4e1bbb3d 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -461,7 +461,8 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf) struct hostapd_ssid *ssid = &conf->ssid; struct sae_password_entry *pw; - if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf)) || + if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf) && + !hostapd_sae_pk_in_use(conf)) || conf->sae_pwe == 3 || !wpa_key_mgmt_sae(conf->wpa_key_mgmt)) return 0; /* PT not needed */ @@ -711,6 +712,9 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf) #ifdef CONFIG_SAE sae_deinit_pt(tmp->pt); #endif /* CONFIG_SAE */ +#ifdef CONFIG_SAE_PK + sae_deinit_pk(tmp->pk); +#endif /* CONFIG_SAE_PK */ os_free(tmp); } } @@ -1111,6 +1115,25 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, } +#ifdef CONFIG_SAE_PK +static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss) +{ + struct sae_password_entry *pw; + + if (bss->ssid.wpa_passphrase && + sae_pk_valid_password(bss->ssid.wpa_passphrase)) + return true; + + for (pw = bss->sae_passwords; pw; pw = pw->next) { + if (!pw->pk && sae_pk_valid_password(pw->password)) + return true; + } + + return false; +} +#endif /* CONFIG_SAE_PK */ + + static int hostapd_config_check_bss(struct hostapd_bss_config *bss, struct hostapd_config *conf, int full_config) @@ -1294,6 +1317,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } #endif /* CONFIG_OCV */ +#ifdef CONFIG_SAE_PK + if (full_config && hostapd_sae_pk_in_use(bss) && + hostapd_sae_pk_password_without_pk(bss)) { + wpa_printf(MSG_ERROR, + "SAE-PK: SAE password uses SAE-PK style, but does not have PK configured"); + return -1; + } +#endif /* CONFIG_SAE_PK */ + return 0; } @@ -1473,3 +1505,38 @@ int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf) return 2; return with_id; } + + +bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf) +{ +#ifdef CONFIG_SAE_PK + struct sae_password_entry *pw; + + for (pw = conf->sae_passwords; pw; pw = pw->next) { + if (pw->pk) + return true; + } +#endif /* CONFIG_SAE_PK */ + + return false; +} + + +#ifdef CONFIG_SAE_PK +bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf) +{ + bool with_pk = false; + struct sae_password_entry *pw; + + if (conf->ssid.wpa_passphrase) + return false; + + for (pw = conf->sae_passwords; pw; pw = pw->next) { + if (!pw->pk) + return false; + with_pk = true; + } + + return with_pk; +} +#endif /* CONFIG_SAE_PK */ diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index c1b4b1bbb..cafc44edd 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -261,6 +261,7 @@ struct sae_password_entry { u8 peer_addr[ETH_ALEN]; int vlan_id; struct sae_pt *pt; + struct sae_pk *pk; }; struct dpp_controller_conf { @@ -1147,6 +1148,8 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config); void hostapd_set_security_params(struct hostapd_bss_config *bss, int full_config); int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf); +bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf); +bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf); int hostapd_setup_sae_pt(struct hostapd_bss_config *conf); #endif /* HOSTAPD_CONFIG_H */ diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index a10bbdcfb..0822dfd34 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -386,7 +386,8 @@ static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta, auth_alg == WLAN_AUTH_SAE) { if (auth_transaction == 1 && sta && (resp == WLAN_STATUS_SUCCESS || - resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT)) { + resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + resp == WLAN_STATUS_SAE_PK)) { wpa_printf(MSG_DEBUG, "TESTING: Postpone SAE Commit transmission until Confirm is ready"); os_free(sta->sae_postponed_commit); @@ -478,17 +479,23 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, const char *rx_id = NULL; int use_pt = 0; struct sae_pt *pt = NULL; + const struct sae_pk *pk = NULL; if (sta->sae->tmp) { rx_id = sta->sae->tmp->pw_id; use_pt = sta->sae->tmp->h2e; +#ifdef CONFIG_SAE_PK + os_memcpy(sta->sae->tmp->own_addr, hapd->own_addr, ETH_ALEN); + os_memcpy(sta->sae->tmp->peer_addr, sta->addr, ETH_ALEN); +#endif /* CONFIG_SAE_PK */ } if (rx_id && hapd->conf->sae_pwe != 3) use_pt = 1; else if (status_code == WLAN_STATUS_SUCCESS) use_pt = 0; - else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) + else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK) use_pt = 1; for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) { @@ -502,6 +509,8 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, continue; password = pw->password; pt = pw->pt; + if (!(hapd->conf->mesh & MESH_ENABLED)) + pk = pw->pk; break; } if (!password) { @@ -515,7 +524,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, if (update && use_pt && sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr, - NULL, NULL) < 0) + NULL, pk) < 0) return NULL; if (update && !use_pt && @@ -558,7 +567,10 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd, if (buf == NULL) return NULL; - sae_write_confirm(sta->sae, buf); + if (sae_write_confirm(sta->sae, buf) < 0) { + wpabuf_free(buf); + return NULL; + } return buf; } @@ -575,11 +587,19 @@ static int auth_sae_send_commit(struct hostapd_data *hapd, data = auth_build_sae_commit(hapd, sta, update, status_code); if (!data && sta->sae->tmp && sta->sae->tmp->pw_id) return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; +#ifdef CONFIG_SAE_PK + if (!data && sta->sae->tmp && sta->sae->tmp->reject_group) + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; +#endif /* CONFIG_SAE_PK */ if (data == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; - status = (sta->sae->tmp && sta->sae->tmp->h2e) ? - WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS; + if (sta->sae->tmp && sta->sae->tmp->pk) + status = WLAN_STATUS_SAE_PK; + else if (sta->sae->tmp && sta->sae->tmp->h2e) + status = WLAN_STATUS_SAE_HASH_TO_ELEMENT; + else + status = WLAN_STATUS_SUCCESS; reply_res = send_auth_reply(hapd, sta, sta->addr, bssid, WLAN_AUTH_SAE, 1, status, wpabuf_head(data), @@ -900,9 +920,14 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta, switch (sta->sae->state) { case SAE_NOTHING: if (auth_transaction == 1) { - if (sta->sae->tmp) - sta->sae->tmp->h2e = status_code == - WLAN_STATUS_SAE_HASH_TO_ELEMENT; + if (sta->sae->tmp) { + sta->sae->tmp->h2e = + (status_code == + WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK); + sta->sae->tmp->pk = + status_code == WLAN_STATUS_SAE_PK; + } ret = auth_sae_send_commit(hapd, sta, bssid, !allow_reuse, status_code); if (ret) @@ -1118,14 +1143,20 @@ static int sae_status_success(struct hostapd_data *hapd, u16 status_code) sae_pwe = 1; else if (id_in_use == 1 && sae_pwe == 0) sae_pwe = 2; +#ifdef CONFIG_SAE_PK + if (sae_pwe == 0 && hostapd_sae_pk_in_use(hapd->conf)) + sae_pwe = 2; +#endif /* CONFIG_SAE_PK */ return ((sae_pwe == 0 || sae_pwe == 3) && status_code == WLAN_STATUS_SUCCESS) || (sae_pwe == 1 && - status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) || + (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK)) || (sae_pwe == 2 && (status_code == WLAN_STATUS_SUCCESS || - status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)); + status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK)); } @@ -1148,11 +1179,15 @@ static int sae_is_group_enabled(struct hostapd_data *hapd, int group) static int check_sae_rejected_groups(struct hostapd_data *hapd, - const struct wpabuf *groups) + struct sae_data *sae, bool pk) { + const struct wpabuf *groups; size_t i, count; const u8 *pos; + if (!sae->tmp) + return 0; + groups = sae->tmp->peer_rejected_groups; if (!groups) return 0; @@ -1165,8 +1200,29 @@ static int check_sae_rejected_groups(struct hostapd_data *hapd, group = WPA_GET_LE16(pos); pos += 2; enabled = sae_is_group_enabled(hapd, group); - wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s", - group, enabled ? "enabled" : "disabled"); + +#ifdef CONFIG_SAE_PK + /* TODO: Could check more explicitly against the matching + * sae_password entry only for the somewhat theoretical case of + * different passwords using different groups for SAE-PK K_AP + * values. */ + if (pk) { + struct sae_password_entry *pw; + + enabled = false; + for (pw = hapd->conf->sae_passwords; pw; + pw = pw->next) { + if (pw->pk && pw->pk->group == group) { + enabled = true; + break; + } + } + } +#endif /* CONFIG_SAE_PK */ + + wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s%s", + group, enabled ? "enabled" : "disabled", + pk ? " (PK)" : ""); if (enabled) return 1; } @@ -1339,7 +1395,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, ((const u8 *) mgmt) + len - mgmt->u.auth.variable, &token, &token_len, groups, status_code == - WLAN_STATUS_SAE_HASH_TO_ELEMENT); + WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK); if (resp == SAE_SILENTLY_DISCARD) { wpa_printf(MSG_DEBUG, "SAE: Drop commit message from " MACSTR " due to reflection attack", @@ -1369,9 +1426,9 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, if (resp != WLAN_STATUS_SUCCESS) goto reply; - if (sta->sae->tmp && - check_sae_rejected_groups( - hapd, sta->sae->tmp->peer_rejected_groups)) { + if (check_sae_rejected_groups(hapd, sta->sae, + status_code == + WLAN_STATUS_SAE_PK)) { resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto reply; } @@ -1384,7 +1441,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, MACSTR, MAC2STR(sta->addr)); if (sta->sae->tmp) h2e = sta->sae->tmp->h2e; - if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) + if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK) h2e = 1; data = auth_build_token_req(hapd, sta->sae->group, sta->addr, h2e); diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 45683d76e..79ed450e2 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -427,6 +427,14 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) if (hapd->conf->beacon_prot) *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */ break; + case 11: /* Bits 88-95 */ +#ifdef CONFIG_SAE_PK + if (hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + hostapd_sae_pk_exclusively(hapd->conf)) + *pos |= 0x01; /* Bit 88 - SAE PK Exclusively */ +#endif /* CONFIG_SAE_PK */ + break; } } @@ -487,6 +495,12 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) #endif /* CONFIG_SAE */ if (len < 11 && hapd->conf->beacon_prot) len = 11; +#ifdef CONFIG_SAE_PK + if (len < 12 && hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + hostapd_sae_pk_exclusively(hapd->conf)) + len = 12; +#endif /* CONFIG_SAE_PK */ if (len < hapd->iface->extended_capa_len) len = hapd->iface->extended_capa_len; if (len == 0) @@ -1081,11 +1095,16 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len) { u8 *pos = eid; + bool sae_pk = false; + +#ifdef CONFIG_SAE_PK + sae_pk = hostapd_sae_pk_in_use(hapd->conf); +#endif /* CONFIG_SAE_PK */ if (!(hapd->conf->wpa & WPA_PROTO_RSN) || !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) || (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 && - !hostapd_sae_pw_id_in_use(hapd->conf)) || + !hostapd_sae_pw_id_in_use(hapd->conf) && !sae_pk) || hapd->conf->sae_pwe == 3 || len < 3) return pos; @@ -1094,7 +1113,12 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len) *pos++ = 1; /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is * used for now */ - *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E); + *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E); +#ifdef CONFIG_SAE_PK + if (sae_pk) + *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK); +#endif /* CONFIG_SAE_PK */ + pos++; return pos; } diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index e059f3db3..59794a7f9 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -256,6 +256,7 @@ struct wpa_auth_config { u8 fils_cache_id[FILS_CACHE_ID_LEN]; #endif /* CONFIG_FILS */ int sae_pwe; + bool sae_pk; int owe_ptk_workaround; u8 transition_disable; #ifdef CONFIG_DPP2 diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index b90c9ef61..c01654f38 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -198,6 +198,9 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wconf->sae_pwe = 1; else if (sae_pw_id == 1 && wconf->sae_pwe == 0) wconf->sae_pwe = 2; +#ifdef CONFIG_SAE_PK + wconf->sae_pk = hostapd_sae_pk_in_use(conf); +#endif /* CONFIG_SAE_PK */ #ifdef CONFIG_OWE wconf->owe_ptk_workaround = conf->owe_ptk_workaround; #endif /* CONFIG_OWE */ diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 8dfd65700..a7e6354a5 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -378,7 +378,7 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len) { u8 *pos = buf; - if (conf->sae_pwe != 1 && conf->sae_pwe != 2) + if (conf->sae_pwe != 1 && conf->sae_pwe != 2 && !conf->sae_pk) return 0; /* no supported extended RSN capabilities */ if (len < 3) @@ -388,7 +388,12 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len) *pos++ = 1; /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is * used for now */ - *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E); + *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E); +#ifdef CONFIG_SAE_PK + if (conf->sae_pk) + *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK); +#endif /* CONFIG_SAE_PK */ + pos++; return pos - buf; } From e7aeb6d8ac416ddd96d736e9cd3127430339ec0a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0598/1105] SAE-PK: STA functionality This adds STA side functionality for SAE-PK. This version enables SAE-PK automatically based on the configured SAE password value if the selected AP advertises support for SAE-PK. Signed-off-by: Jouni Malinen --- wpa_supplicant/sme.c | 88 +++++++++++++++++++++++++-------- wpa_supplicant/wpa_supplicant.c | 4 +- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index d03b0ce8a..3ad006528 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -85,16 +85,21 @@ static int sme_set_sae_group(struct wpa_supplicant *wpa_s) static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, const u8 *bssid, int external, - int reuse, int *ret_use_pt) + int reuse, int *ret_use_pt, + bool *ret_use_pk) { struct wpabuf *buf; size_t len; const char *password; struct wpa_bss *bss; int use_pt = 0; + bool use_pk = false; + u8 rsnxe_capa = 0; if (ret_use_pt) *ret_use_pt = 0; + if (ret_use_pk) + *ret_use_pk = false; #ifdef CONFIG_TESTING_OPTIONS if (wpa_s->sae_commit_override) { @@ -124,6 +129,7 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "SAE: Reuse previously generated PWE on a retry with the same AP"); use_pt = wpa_s->sme.sae.tmp->h2e; + use_pk = wpa_s->sme.sae.tmp->pk; goto reuse_data; } if (sme_set_sae_group(wpa_s) < 0) { @@ -131,19 +137,27 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, return NULL; } + bss = wpa_bss_get_bssid_latest(wpa_s, bssid); + if (bss) { + const u8 *rsnxe; + + rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (rsnxe && rsnxe[1] >= 1) + rsnxe_capa = rsnxe[2]; + } + if (ssid->sae_password_id && wpa_s->conf->sae_pwe != 3) use_pt = 1; +#ifdef CONFIG_SAE_PK + if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) && + ssid->sae_password && sae_pk_valid_password(ssid->sae_password)) { + use_pt = 1; + use_pk = true; + } +#endif /* CONFIG_SAE_PK */ if (use_pt || wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) { - bss = wpa_bss_get_bssid_latest(wpa_s, bssid); - if (bss) { - const u8 *rsnxe; - - rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); - if (rsnxe && rsnxe[1] >= 1) - use_pt = !!(rsnxe[2] & - BIT(WLAN_RSNX_CAPAB_SAE_H2E)); - } + use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E)); if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && wpa_s->conf->sae_pwe != 3 && @@ -167,8 +181,17 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE"); return NULL; } - if (wpa_s->sme.sae.tmp) + if (wpa_s->sme.sae.tmp) { os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN); + if (use_pt && use_pk) + wpa_s->sme.sae.tmp->pk = 1; +#ifdef CONFIG_SAE_PK + os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr, + ETH_ALEN); + os_memcpy(wpa_s->sme.sae.tmp->peer_addr, bssid, ETH_ALEN); + sae_pk_set_password(&wpa_s->sme.sae, password); +#endif /* CONFIG_SAE_PK */ + } reuse_data: len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0; @@ -179,8 +202,12 @@ reuse_data: return NULL; if (!external) { wpabuf_put_le16(buf, 1); /* Transaction seq# */ - wpabuf_put_le16(buf, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT : - WLAN_STATUS_SUCCESS); + if (use_pk) + wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK); + else if (use_pt) + wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT); + else + wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS); } if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token, ssid->sae_password_id) < 0) { @@ -189,6 +216,8 @@ reuse_data: } if (ret_use_pt) *ret_use_pt = use_pt; + if (ret_use_pk) + *ret_use_pk = use_pk; return buf; } @@ -716,7 +745,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, bss->bssid, 0, - start == 2, NULL); + start == 2, NULL, + NULL); else resp = sme_auth_build_sae_confirm(wpa_s, 0); if (resp == NULL) { @@ -1008,8 +1038,11 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s, { struct wpabuf *resp, *buf; int use_pt; + bool use_pk; + u16 status; - resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt); + resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt, + &use_pk); if (!resp) { wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit"); return -1; @@ -1023,10 +1056,14 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s, } wpa_s->sme.seq_num++; + if (use_pk) + status = WLAN_STATUS_SAE_PK; + else if (use_pt) + status = WLAN_STATUS_SAE_HASH_TO_ELEMENT; + else + status = WLAN_STATUS_SUCCESS; sme_external_auth_build_buf(buf, resp, wpa_s->own_addr, - bssid, 1, wpa_s->sme.seq_num, - use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT : - WLAN_STATUS_SUCCESS); + bssid, 1, wpa_s->sme.seq_num, status); wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0); wpabuf_free(resp); wpabuf_free(buf); @@ -1287,7 +1324,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, } if (status_code != WLAN_STATUS_SUCCESS && - status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT) + status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT && + status_code != WLAN_STATUS_SAE_PK) return -1; if (auth_transaction == 1) { @@ -1310,18 +1348,26 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected"); return -1; } - if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->h2e && + if (wpa_s->sme.sae.tmp && + (!wpa_s->sme.sae.tmp->h2e || wpa_s->sme.sae.tmp->pk) && status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) { wpa_printf(MSG_DEBUG, "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected"); return -1; } + if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->pk && + status_code == WLAN_STATUS_SAE_PK) { + wpa_printf(MSG_DEBUG, + "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected"); + return -1; + } if (groups && groups[0] <= 0) groups = NULL; res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL, groups, status_code == - WLAN_STATUS_SAE_HASH_TO_ELEMENT); + WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK); if (res == SAE_SILENTLY_DISCARD) { wpa_printf(MSG_DEBUG, "SAE: Drop commit message due to reflection attack"); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index acd0091bc..f5a4c360b 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2061,7 +2061,9 @@ static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid) if (!password) password = ssid->passphrase; - if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password || + if (!password || + (conf->sae_pwe == 0 && !ssid->sae_password_id && + !sae_pk_valid_password(password)) || conf->sae_pwe == 3) { /* PT derivation not needed */ sae_deinit_pt(ssid->pt); From 9bf576870e1a2ce9a3f098619b896b5a429aa148 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0599/1105] Show SAE flags in scan results Indicate AP support for SAE H2E and SAE-PK in scan results. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index ff2f69ea4..7569beddc 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2940,7 +2940,7 @@ static int wpa_supplicant_ctrl_iface_scan_result( { char *pos, *end; int ret; - const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe; + const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe; mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); @@ -2967,6 +2967,21 @@ static int wpa_supplicant_ctrl_iface_scan_result( pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2", ie2, 2 + ie2[1]); } + rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (rsnxe && rsnxe[1] >= 1) { + if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) { + ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) { + ret = os_snprintf(pos, end - pos, "[SAE-PK]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); if (osen_ie) pos = wpa_supplicant_ie_txt(pos, end, "OSEN", @@ -4831,7 +4846,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, size_t i; int ret; char *pos, *end; - const u8 *ie, *ie2, *osen_ie, *mesh, *owe; + const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe; pos = buf; end = buf + buflen; @@ -4951,6 +4966,21 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2", ie2, 2 + ie2[1]); + rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (rsnxe && rsnxe[1] >= 1) { + if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) { + ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) { + ret = os_snprintf(pos, end - pos, "[SAE-PK]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); if (osen_ie) pos = wpa_supplicant_ie_txt(pos, end, "OSEN", From b6bcd74e53beb7d6ca424c57cfb4fda3b56f4a30 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0600/1105] Show SAE capabilities in control interface Indicate local support for SAE H2E and SAE-PK. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 7569beddc..e727dc5bb 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4726,6 +4726,20 @@ static int wpa_supplicant_ctrl_iface_get_capability( } #endif /* CONFIG_DPP */ +#ifdef CONFIG_SAE + if (os_strcmp(field, "sae") == 0 && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) { +#ifdef CONFIG_SAE_PK + res = os_snprintf(buf, buflen, "H2E PK"); +#else /* CONFIG_SAE_PK */ + res = os_snprintf(buf, buflen, "H2E"); +#endif /* CONFIG_SAE_PK */ + if (os_snprintf_error(buflen, res)) + return -1; + return res; + } +#endif /* CONFIG_SAE */ + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", field); From fb09ec87f206f25be82349dde334ab0dc61b7630 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 2 Jun 2020 22:44:42 +0300 Subject: [PATCH 0601/1105] SAE-PK: A tool for generating SAE-PK Modifier and password sae_pk_gen can be used to generate Modifier (M) and password for SAE-PK based on a previously generated EC private key, Sec value (2..5), and SSID. For example, these commands can be used to generate the private key and the needed hostapd configuration parameter options: make sae_pk_gen openssl ecparam -genkey -outform DER -out saepk.der -name prime256v1 ./sae_pk_gen saepk.der 3 "SAE-PK test" Signed-off-by: Jouni Malinen --- hostapd/Makefile | 34 +++++++++ hostapd/sae_pk_gen.c | 160 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 hostapd/sae_pk_gen.c diff --git a/hostapd/Makefile b/hostapd/Makefile index 3cc64c965..1400002a9 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -19,6 +19,9 @@ endif ifndef LIBS_n LIBS_n := $(LIBS) endif +ifndef LIBS_s +LIBS_s := $(LIBS) +endif endif CFLAGS += $(EXTRA_CFLAGS) @@ -122,6 +125,7 @@ LIBS += -lbfd -ldl -liberty -lz LIBS_c += -lbfd -ldl -liberty -lz LIBS_h += -lbfd -ldl -liberty -lz LIBS_n += -lbfd -ldl -liberty -lz +LIBS_s += -lbfd -ldl -liberty -lz endif endif @@ -704,6 +708,7 @@ LIBS += -lssl endif OBJS += ../src/crypto/crypto_openssl.o HOBJS += ../src/crypto/crypto_openssl.o +SOBJS += ../src/crypto/crypto_openssl.o ifdef NEED_FIPS186_2_PRF OBJS += ../src/crypto/fips_prf_openssl.o endif @@ -711,9 +716,11 @@ NEED_TLS_PRF_SHA256=y LIBS += -lcrypto LIBS_h += -lcrypto LIBS_n += -lcrypto +LIBS_s += -lcrypto ifdef CONFIG_TLS_ADD_DL LIBS += -ldl LIBS_h += -ldl +LIBS_s += -ldl endif ifndef CONFIG_TLS_DEFAULT_CIPHERS CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW" @@ -1345,6 +1352,28 @@ ifeq ($(CONFIG_TLS), linux) HOBJS += ../src/crypto/crypto_linux.o endif +SOBJS += sae_pk_gen.o +SOBJS += ../src/utils/common.o +SOBJS += ../src/utils/os_$(CONFIG_OS).o +SOBJS += ../src/utils/base64.o +SOBJS += ../src/utils/wpa_debug.o +SOBJS += ../src/utils/wpabuf.o +ifdef CONFIG_WPA_TRACE +SOBJS += ../src/utils/trace.o +endif +SOBJS += ../src/common/ieee802_11_common.o +SOBJS += ../src/common/sae.o +SOBJS += ../src/common/sae_pk.o +SOBJS += ../src/common/dragonfly.o +SOBJS += $(AESOBJS) +SOBJS += ../src/crypto/sha256-prf.o +SOBJS += ../src/crypto/sha384-prf.o +SOBJS += ../src/crypto/sha512-prf.o +SOBJS += ../src/crypto/dh_groups.o +SOBJS += ../src/crypto/sha256-kdf.o +SOBJS += ../src/crypto/sha384-kdf.o +SOBJS += ../src/crypto/sha512-kdf.o + nt_password_hash: $(NOBJS) $(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n) @$(E) " LD " $@ @@ -1353,6 +1382,10 @@ hlr_auc_gw: $(HOBJS) $(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h) @$(E) " LD " $@ +sae_pk_gen: $(SOBJS) + $(Q)$(CC) $(LDFLAGS) -o sae_pk_gen $(SOBJS) $(LIBS_s) + @$(E) " LD " $@ + lcov-html: lcov -c -d .. > lcov.info genhtml lcov.info --output-directory lcov-html @@ -1360,6 +1393,7 @@ lcov-html: clean: $(MAKE) -C ../src clean rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw + rm -f sae_pk_gen rm -f *.d *.gcno *.gcda *.gcov rm -f lcov.info rm -rf lcov-html diff --git a/hostapd/sae_pk_gen.c b/hostapd/sae_pk_gen.c new file mode 100644 index 000000000..6570e9ed9 --- /dev/null +++ b/hostapd/sae_pk_gen.c @@ -0,0 +1,160 @@ +/* + * SAE-PK password/modifier generator + * Copyright (c) 2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/base64.h" +#include "crypto/crypto.h" +#include "common/sae.h" + + +int main(int argc, char *argv[]) +{ + char *der = NULL; + size_t der_len; + struct crypto_ec_key *key = NULL; + struct wpabuf *pub = NULL; + u8 *data = NULL, *m; + size_t data_len; + char *b64 = NULL, *pw = NULL, *pos, *src; + int sec, j; + int ret = -1; + u8 hash[SAE_MAX_HASH_LEN], fingerprint[SAE_MAX_HASH_LEN]; + int group; + size_t hash_len; + unsigned long long i, expected; + char m_hex[2 * SAE_PK_M_LEN + 1]; + + wpa_debug_level = MSG_INFO; + if (os_program_init() < 0) + goto fail; + + if (argc != 4) { + fprintf(stderr, + "usage: sae_pk_gen \n"); + goto fail; + } + + sec = atoi(argv[2]); + if (sec < 2 || sec > 5) { + fprintf(stderr, "Invalid Sec value (allowed range: 2..5)\n"); + goto fail; + } + expected = 1; + for (j = 0; j < sec; j++) + expected *= 256; + + der = os_readfile(argv[1], &der_len); + if (!der) { + fprintf(stderr, "Could not read %s: %s\n", + argv[1], strerror(errno)); + goto fail; + } + + key = crypto_ec_key_parse_priv((u8 *) der, der_len); + if (!key) { + fprintf(stderr, "Could not parse ECPrivateKey\n"); + goto fail; + } + + pub = crypto_ec_key_get_subject_public_key(key); + if (!pub) { + fprintf(stderr, "Failed to build SubjectPublicKey\n"); + goto fail; + } + + group = crypto_ec_key_group(key); + switch (group) { + case 19: + hash_len = 32; + break; + case 20: + hash_len = 48; + break; + case 21: + hash_len = 64; + break; + default: + fprintf(stderr, "Unsupported private key group\n"); + goto fail; + } + + data_len = os_strlen(argv[3]) + SAE_PK_M_LEN + wpabuf_len(pub); + data = os_malloc(data_len); + if (!data) { + fprintf(stderr, "No memory for data buffer\n"); + goto fail; + } + os_memcpy(data, argv[3], os_strlen(argv[3])); + m = data + os_strlen(argv[3]); + if (os_get_random(m, SAE_PK_M_LEN) < 0) { + fprintf(stderr, "Could not generate random Modifier M\n"); + goto fail; + } + os_memcpy(m + SAE_PK_M_LEN, wpabuf_head(pub), wpabuf_len(pub)); + + fprintf(stderr, "Searching for a suitable Modifier M value\n"); + for (i = 0;; i++) { + if (sae_hash(hash_len, data, data_len, hash) < 0) { + fprintf(stderr, "Hash failed\n"); + goto fail; + } + if (hash[0] == 0 && hash[1] == 0) { + if (sec == 2 || (hash[2] & 0xf0) == 0) + fprintf(stderr, "\r%3.2f%%", + 100.0 * (double) i / (double) expected); + for (j = 2; j < sec; j++) { + if (hash[j]) + break; + } + if (j == sec) + break; + } + inc_byte_array(m, SAE_PK_M_LEN); + } + + fprintf(stderr, "\nFound a valid hash in %llu iterations\n", i); + wpa_hexdump(MSG_DEBUG, "Valid hash", hash, hash_len); + fingerprint[0] = (sec - 2) << 6 | hash[sec] >> 2; + for (i = 1; i < hash_len - sec; i++) + fingerprint[i] = hash[sec + i - 1] << 6 | hash[sec + i] >> 2; + wpa_hexdump(MSG_DEBUG, "Fingerprint part for password", + fingerprint, hash_len - sec); + + b64 = base64_encode(der, der_len, NULL); + pw = sae_pk_base32_encode(fingerprint, (hash_len - sec) * 8 - 2); + if (!b64 || !pw || + wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0) + goto fail; + src = pos = b64; + while (*src) { + if (*src != '\n') + *pos++ = *src; + src++; + } + *pos = '\0'; + + printf("# SAE-PK password/M/private key for Sec=%d.\n", sec); + printf("# The password can be truncated from right to improve\n"); + printf("# usability at the cost of security.\n"); + printf("sae_password=%s|pk=%s:%s\n", pw, m_hex, b64); + + ret = 0; +fail: + os_free(der); + wpabuf_free(pub); + crypto_ec_key_deinit(key); + os_free(data); + os_free(b64); + os_free(pw); + + os_program_deinit(); + + return ret; +} From fca9ef3feeba080b37c8896ca88b15aa4ab450b7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 May 2020 23:30:42 +0300 Subject: [PATCH 0602/1105] tests: SAE-PK Signed-off-by: Jouni Malinen --- tests/hwsim/example-hostapd.config | 1 + tests/hwsim/example-wpa_supplicant.config | 1 + tests/hwsim/test_sae_pk.py | 121 ++++++++++++++++++++++ tests/hwsim/utils.py | 4 + 4 files changed, 127 insertions(+) create mode 100644 tests/hwsim/test_sae_pk.py diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config index f1a9adf7b..972d35c75 100644 --- a/tests/hwsim/example-hostapd.config +++ b/tests/hwsim/example-hostapd.config @@ -71,6 +71,7 @@ CONFIG_INTERWORKING=y CONFIG_HS20=y CONFIG_SQLITE=y CONFIG_SAE=y +CONFIG_SAE_PK=y CFLAGS += -DALL_DH_GROUPS CONFIG_FST=y diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config index 253f329bb..9e3cc67e4 100644 --- a/tests/hwsim/example-wpa_supplicant.config +++ b/tests/hwsim/example-wpa_supplicant.config @@ -116,6 +116,7 @@ CONFIG_EXT_PASSWORD_TEST=y CONFIG_EAP_UNAUTH_TLS=y CONFIG_SAE=y +CONFIG_SAE_PK=y CFLAGS += -DALL_DH_GROUPS CONFIG_WNM=y diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py new file mode 100644 index 000000000..dfecbc5e9 --- /dev/null +++ b/tests/hwsim/test_sae_pk.py @@ -0,0 +1,121 @@ +# Test cases for SAE-PK +# Copyright (c) 2020, The Linux Foundation +# +# This software may be distributed under the terms of the BSD license. +# See README for more details. + +import hostapd +from utils import * + +def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None): + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + if ap_groups: + params['sae_groups'] = ap_groups + hapd = hostapd.add_ap(apdev, params) + bssid = hapd.own_addr() + + dev.connect(ssid, sae_password=pw, key_mgmt="SAE", scan_freq="2412") + bss = dev.get_bss(bssid) + if 'flags' not in bss: + raise Exception("Could not get BSS flags from BSS table") + if "[SAE-H2E]" not in bss['flags'] or "[SAE-PK]" not in bss['flags']: + raise Exception("Unexpected BSS flags: " + bss['flags']) + dev.request("REMOVE_NETWORK *") + dev.wait_disconnected() + hapd.disable() + +def test_sae_pk(dev, apdev): + """SAE-PK""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-qleg" + m = "431ff8322f93b9dc50ded9f3d14ace22" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + for i in range(6, len(pw) + 1): + p = pw[:i] + if p.endswith('-'): + continue + run_sae_pk(apdev[0], dev[0], ssid, p, m, pk) + +def test_sae_pk_group_negotiation(dev, apdev): + """SAE-PK""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "20 19") + + ssid = "SAE-PK test" + pw = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-qleg" + m = "431ff8322f93b9dc50ded9f3d14ace22" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + try: + run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk, ap_groups="19 20") + finally: + dev[0].set("sae_groups", "") + +def test_sae_pk_sec_2(dev, apdev): + """SAE-PK with Sec 2""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "dwxm-zv66-p5ue" + m = "431ff8322f93b9dc50ded9f3d14ace22" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk) + +def test_sae_pk_sec_3(dev, apdev): + """SAE-PK with Sec 3""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "iian-qey6-pu5t" + m = "128e51ddb5e2e24388f9ed14b687e2eb" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk) + +def test_sae_pk_sec_4(dev, apdev): + """SAE-PK with Sec 4""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "ssko-2lmu-7hzs-bqct" + m = "a5e38c7251ea310cc348fbcdadfa8bcb" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk) + +def test_sae_pk_sec_5(dev, apdev): + """SAE-PK with Sec 5""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "3qqu-f4xq-dz37-fes3-fbgc" + m = "d2e5fa27d1be8897f987f2d480d2af6b" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk) + +def test_sae_pk_group_20(dev, apdev): + """SAE-PK with group 20""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "20") + + ssid = "SAE-PK test" + pw = "f3bh-5un3-wz7o-al3p" + m = "50bf37ba0033ed110a74e3a7aa52f4e9" + pk = "MIGkAgEBBDA4wpA6w/fK0g3a2V6QmcoxNoFCVuQPyzWvKYimJkgXsVsXt2ERXQ7dGOVXeycM5DqgBwYFK4EEACKhZANiAARTdszGBNe2PGCnc8Wvs+IDvdVEf4PPBrty0meRZf6UTbGouquTHpy6KKTq5sxrulYzsQFimg4op0UJBGxAzqo0EtTgMlLiBvY0I3Nl3N69MhWo8nvnmguvGGN32AAPXpQ=" + + try: + run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk, ap_groups="20") + finally: + dev[0].set("sae_groups", "") diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index 714f7644f..3aa7c4497 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -113,6 +113,10 @@ def check_sae_capab(dev): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") +def check_sae_pk_capab(dev): + if "PK" not in dev.get_capability("sae"): + raise HwsimSkip("SAE-PK not supported") + def check_tls_tod(dev): tls = dev.request("GET tls_library") if not tls.startswith("OpenSSL") and not tls.startswith("internal"): From c3f894ad005e7978ae5c30f03670bece7b7c4f22 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 2 Jun 2020 23:35:17 +0300 Subject: [PATCH 0603/1105] tests: Fix eapol-supp fuzzing tool build Boolean handling was changed to use "true" instead of "TRUE", but this location was missed. Signed-off-by: Jouni Malinen --- tests/fuzzing/eapol-supp/eapol-supp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fuzzing/eapol-supp/eapol-supp.c b/tests/fuzzing/eapol-supp/eapol-supp.c index 6f0b8cba8..94e0147ad 100644 --- a/tests/fuzzing/eapol-supp/eapol-supp.c +++ b/tests/fuzzing/eapol-supp/eapol-supp.c @@ -33,7 +33,7 @@ static void test_send_eapol(void *eloop_data, void *user_ctx) wpa_hexdump(MSG_MSGDUMP, "fuzzer - EAPOL", ctx->data, ctx->data_len); - eapol_sm_notify_portEnabled(ctx->eapol, TRUE); + eapol_sm_notify_portEnabled(ctx->eapol, true); wpa_sm_set_param(ctx->wpa, WPA_PARAM_PROTO, WPA_PROTO_RSN); wpa_sm_set_param(ctx->wpa, WPA_PARAM_RSN_ENABLED, 1); From d777156e1f07380004eb77432bb0ec39ead151c8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 3 Jun 2020 17:30:36 +0300 Subject: [PATCH 0604/1105] SAE-PK: Determine hash algorithm from K_AP group instead of SAE group While the current implementation forces these groups to be same, that is not strictly speaking necessary and the correct group to use here is K_AP, not the SAE authentication group. Signed-off-by: Jouni Malinen --- src/common/sae_pk.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index df0f7db9d..624557a4e 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -182,6 +182,21 @@ int sae_pk_set_password(struct sae_data *sae, const char *password) } +static size_t sae_group_2_hash_len(int group) +{ + switch (group) { + case 19: + return 32; + case 20: + return 48; + case 21: + return 64; + } + + return 0; +} + + void sae_deinit_pk(struct sae_pk *pk) { if (pk) { @@ -347,7 +362,7 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) return -1; } - hash_len = sae_ecc_prime_len_2_hash_len(tmp->prime_len); + hash_len = sae_group_2_hash_len(pk->group); if (sae_pk_hash_sig_data(sae, hash_len, true, wpabuf_head(pk->m), wpabuf_len(pk->m), wpabuf_head(pk->pubkey), wpabuf_len(pk->pubkey), hash) < 0) @@ -414,7 +429,7 @@ fail: static bool sae_pk_valid_fingerprint(struct sae_data *sae, const u8 *m, size_t m_len, - const u8 *k_ap, size_t k_ap_len) + const u8 *k_ap, size_t k_ap_len, int group) { struct sae_temporary_data *tmp = sae->tmp; size_t sec, i; @@ -431,7 +446,7 @@ static bool sae_pk_valid_fingerprint(struct sae_data *sae, /* Fingerprint = L(Hash(SSID || M || K_AP), 0, 8*Sec + 5*Lambda - 2) */ - hash_len = sae_ecc_prime_len_2_hash_len(tmp->prime_len); + hash_len = sae_group_2_hash_len(group); hash_data_len = tmp->ssid_len + m_len + k_ap_len; hash_data = os_malloc(hash_data_len); if (!hash_data) @@ -605,9 +620,6 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) /* TODO: Check against the public key, if one is stored in the network * profile */ - if (!sae_pk_valid_fingerprint(sae, m, SAE_PK_M_LEN, k_ap, k_ap_len)) - return -1; - key = crypto_ec_key_parse_pub(k_ap, k_ap_len); if (!key) { wpa_printf(MSG_INFO, "SAE-PK: Failed to parse K_AP"); @@ -615,6 +627,12 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) } group = crypto_ec_key_group(key); + if (!sae_pk_valid_fingerprint(sae, m, SAE_PK_M_LEN, k_ap, k_ap_len, + group)) { + crypto_ec_key_deinit(key); + return -1; + } + /* TODO: Could support alternative groups as long as the combination * meets the requirements. */ if (group != sae->group) { @@ -628,7 +646,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) wpa_hexdump(MSG_DEBUG, "SAE-PK: Received KeyAuth", key_auth, key_auth_len); - hash_len = sae_ecc_prime_len_2_hash_len(tmp->prime_len); + hash_len = sae_group_2_hash_len(group); if (sae_pk_hash_sig_data(sae, hash_len, false, m, SAE_PK_M_LEN, k_ap, k_ap_len, hash) < 0) { crypto_ec_key_deinit(key); From 2c7b5a2c5fccd1e475151f58a50450272211e6a0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 4 Jun 2020 01:41:50 +0300 Subject: [PATCH 0605/1105] tests: Skip too short SAE-PK passwords in positive testing Lambda >= 12 is needed with Sec = 2, so drop the shorter password lengths in the sae_pk and module_wpa_supplicant test cases. Signed-off-by: Jouni Malinen --- src/common/common_module_tests.c | 6 ------ tests/hwsim/test_sae_pk.py | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c index 77d6001c8..8a7d9fe25 100644 --- a/src/common/common_module_tests.c +++ b/src/common/common_module_tests.c @@ -563,12 +563,6 @@ static int sae_pk_tests(void) { "aaaa-aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00" }, { "aaaa-aaaa-aa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00" }, { "aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00" }, - { "aaaa-aaa", (u8 *) "\x00\x00\x00\x00\x00" }, - { "aaaa-a", (u8 *) "\x00\x00\x00\x00" }, - { "aeaa-a", (u8 *) "\x01\x00\x00\x00" }, - { "7777-7", (u8 *) "\xff\xff\xff\x80" }, - { "7777-77", (u8 *) "\xff\xff\xff\xfc" }, - { "7777-777", (u8 *) "\xff\xff\xff\xff\xe0" }, { "7777-7777", (u8 *) "\xff\xff\xff\xff\xff" }, { "7777-7777-7", (u8 *) "\xff\xff\xff\xff\xff\xf8" }, { "7777-7777-77", (u8 *) "\xff\xff\xff\xff\xff\xff\xc0" }, diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index dfecbc5e9..4cd95cdc6 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -36,7 +36,7 @@ def test_sae_pk(dev, apdev): m = "431ff8322f93b9dc50ded9f3d14ace22" pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - for i in range(6, len(pw) + 1): + for i in range(14, len(pw) + 1): p = pw[:i] if p.endswith('-'): continue From c85b39ec503e331c1de9c9e26331da96615ed066 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 4 Jun 2020 01:36:50 +0300 Subject: [PATCH 0606/1105] SAE-PK: Increment the minimum password length to 9 While this is not explicitly defined as the limit, lambda=8 (i.e., 9 characters with the added hyphen) is needed with Sec=5 to reach the minimum required resistance to preimage attacks, so use this as an implicit definition of the password length constraint. Signed-off-by: Jouni Malinen --- src/common/sae_pk.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index 624557a4e..2469534b9 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -27,11 +27,12 @@ bool sae_pk_valid_password(const char *pw) { int pos; - /* Minimum password length for SAE-PK is not defined, but the automatic - * password style determination is more reliable if at least one hyphen - * is forced to be present in the password. */ - if (os_strlen(pw) < 6) + if (os_strlen(pw) < 9) { + /* Not long enough to meet the minimum required resistance to + * preimage attacks, so do not consider this valid for SAE-PK. + */ return false; + } for (pos = 0; pw[pos]; pos++) { if (pos && pos % 5 == 4) { From 40240735bd6731fc00dd1b3ad0a7d1722bf706bc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 4 Jun 2020 21:04:59 +0300 Subject: [PATCH 0607/1105] WPS UPnP: Do not update Beacon frames unnecessarily on subscription removal There is no need to update the WPS IE in Beacon frames when a subscription is removed if that subscription is not for an actual selected registrar. For example, this gets rids of unnecessary driver operations when a subscription request gets rejected when parsing the callback URLs. Signed-off-by: Jouni Malinen --- src/wps/wps_upnp_ap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wps/wps_upnp_ap.c b/src/wps/wps_upnp_ap.c index cca390530..b6c9478ff 100644 --- a/src/wps/wps_upnp_ap.c +++ b/src/wps/wps_upnp_ap.c @@ -76,8 +76,10 @@ int upnp_er_set_selected_registrar(struct wps_registrar *reg, void upnp_er_remove_notification(struct wps_registrar *reg, struct subscription *s) { + bool was_sel_reg = s->selected_registrar; + s->selected_registrar = 0; eloop_cancel_timeout(upnp_er_set_selected_timeout, s, reg); - if (reg) + if (reg && was_sel_reg) wps_registrar_selected_registrar_changed(reg, 0); } From cb43c9bfd0d8b980cb154702abb00e65ee6c6f5d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 5 Jun 2020 13:39:41 +0300 Subject: [PATCH 0608/1105] tests: sigma_dut controlled AP using OCV Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index b87f44bb8..58384c70a 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -28,6 +28,7 @@ from test_suite_b import check_suite_b_192_capa, suite_b_as_params, suite_b_192_ from test_ap_eap import check_eap_capa, int_eap_server_params, check_domain_match, check_domain_suffix_match from test_ap_hs20 import hs20_ap_params from test_ap_pmf import check_mac80211_bigtk +from test_ocv import check_ocv_failure def check_sigma_dut(): if not os.path.exists("./sigma_dut"): @@ -4632,3 +4633,45 @@ def test_sigma_dut_ocv(dev, apdev): sigma_dut_cmd_check("sta_reset_default,interface," + ifname) finally: stop_sigma_dut(sigma) + +def test_sigma_dut_ap_ocv(dev, apdev, params): + """sigma_dut controlled AP using OCV""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,ocvc,1") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + bssid = bssid.split(',')[3] + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "wb") as f2: + f2.write(f.read()) + + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", ocv="1", scan_freq="2412") + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + sigma_dut_cmd_check("ap_set_rfeature,NAME,AP,type,WPA3,OCIFrameType,eapolM3,OCIChannel,3") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", ocv="1", scan_freq="2412", + wait_connect=False) + check_ocv_failure(dev[0], "EAPOL-Key msg 3/4", "eapol-key-m3", + bssid) + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) From 37a5b50de3bea447ba815341fab00f51507dcda5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 5 Jun 2020 13:41:59 +0300 Subject: [PATCH 0609/1105] tests: Fix sigma_dut ap_get_mac_address result parsing Get only the actual BSSID part from the response string. Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 58384c70a..78aca683a 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4439,6 +4439,7 @@ def test_sigma_dut_ap_beacon_prot(dev, apdev, params): sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-PSK,PSK,12345678,PMF,Required,BeaconProtection,1") sigma_dut_cmd_check("ap_config_commit,NAME,AP") bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + bssid = bssid.split(',')[3] dev[0].connect("test-psk", key_mgmt="WPA-PSK-SHA256", psk="12345678", scan_freq="2412", @@ -4467,7 +4468,6 @@ def test_sigma_dut_ap_transition_disable(dev, apdev, params): sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678,PMF,Required,Transition_Disable,1,Transition_Disable_Index,0") sigma_dut_cmd_check("ap_config_commit,NAME,AP") - bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") dev[0].set("sae_groups", "") dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", From c55a52a85d004b3fb3db13cd7962807a9154f02a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 5 Jun 2020 15:35:44 +0300 Subject: [PATCH 0610/1105] tests: sigma_dut controlled GTK rekeying Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 78aca683a..f3a4cc60e 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4675,3 +4675,65 @@ def test_sigma_dut_ap_ocv(dev, apdev, params): sigma_dut_cmd_check("ap_reset_default") finally: stop_sigma_dut(sigma) + +def test_sigma_dut_gtk_rekey(dev, apdev): + """sigma_dut controlled STA requesting GTK rekeying""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params['sae_groups'] = '19' + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ocvc,1" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + sigma_dut_wait_connected(ifname) + + dev[0].dump_monitor() + sigma_dut_cmd_check("dev_exec_action,interface,%s,program,WPA3,KeyRotation,1" % ifname) + ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=5) + if ev is None: + raise Exception("GTK rekeying not seen") + + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ap_gtk_rekey(dev, apdev, params): + """sigma_dut controlled AP and requested GTK rekeying""" + logdir = params['prefix'] + ".sigma-hostapd" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", scan_freq="2412") + dev[0].dump_monitor() + + sigma_dut_cmd_check("dev_exec_action,name,AP,interface,%s,program,WPA3,KeyRotation,1" % iface) + + ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=5) + if ev is None: + raise Exception("GTK rekeying not seen") + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) From db23b8f95b1c93c5392211b37ce9a6c5d0b9eeac Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 5 Jun 2020 16:58:25 +0300 Subject: [PATCH 0611/1105] tests: sigma_dut and SAE-PK Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 111 ++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index f3a4cc60e..c9e7c34c8 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4737,3 +4737,114 @@ def test_sigma_dut_ap_gtk_rekey(dev, apdev, params): sigma_dut_cmd_check("ap_reset_default") finally: stop_sigma_dut(sigma) + +def test_sigma_dut_sae_pk(dev, apdev): + """sigma_dut controlled STA using SAE-PK""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + ssid = "SAE-PK test" + pw = "dwxm-zv66-p5ue" + m = "431ff8322f93b9dc50ded9f3d14ace22" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + try: + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params['sae_groups'] = '19' + params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2,sae_pk,1" % (ifname, ssid, pw)) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, ssid), + timeout=10) + sigma_dut_wait_connected(ifname) + dev[0].dump_monitor() + + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + +def run_sigma_dut_ap_sae_pk(conffile, dev, ssid, pw, keypair, m, failure): + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,%s,MODE,11ng" % ssid) + sigma_dut_cmd_check("ap_set_security,NAME,AP,AKMSuiteType,8,PairwiseCipher,AES-CCMP-128,GroupCipher,AES-CCMP-128,GroupMgntCipher,BIP-CMAC-128,PMF,Required,PSK,%s,sae_pk,1,Transition_Disable,1,Transition_Disable_Index,0,SAE_PK_KeyPair,%s,SAE_PK_Modifier,%s" % (pw, keypair, m)) + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + bssid = bssid.split(',')[3] + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "ab") as f2: + f2.write(f.read()) + f2.write('\n'.encode()) + + dev.set("sae_groups", "") + dev.connect(ssid, key_mgmt="SAE", sae_password=pw, ieee80211w="2", + scan_freq="2412", wait_connect=False) + + ev = dev.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=15) + if ev is None: + raise Exception("No connection result reported") + + bss = dev.get_bss(bssid) + if 'flags' not in bss: + raise Exception("Could not get BSS flags from BSS table") + if "[SAE-H2E]" not in bss['flags'] or "[SAE-PK]" not in bss['flags']: + raise Exception("Unexpected BSS flags: " + bss['flags']) + + if failure: + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + dev.request("REMOVE_NETWORK all") + else: + if "CTRL-EVENT-CONNECTED" not in ev: + raise Exception("Connection failed") + dev.request("REMOVE_NETWORK all") + dev.wait_disconnected() + dev.dump_monitor() + + sigma_dut_cmd_check("ap_reset_default") + +def test_sigma_dut_ap_sae_pk(dev, apdev, params): + """sigma_dut controlled AP using SAE-PK""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + tests = [("SAEPK-4.7.1", "fb4c-zpqh-bhdc", "saepk.pem", + "2ec1f37b47b402252e9dc5001e81fd1c", False), + ("SAEPK-5.7.1.1", "amro-yjrs-zzda", "saepk1.pem", + "f42baa90420032486b3229ab0890878a", False), + ("SAEPK-5.7.1.2", "eh56-tjce-cnzg-ymhq", "saepk2.pem", + "efb8b7a87e0638a93b056cb4aadf4a71", False), + ("SAEPK-5.7.1.3", "knny-r45l-ww3w", "saepk3.pem", + "6502721b2c2dfea3c9aefc5324eee9c9", False), + ("SAEPK-5.7.2.1", "fvys-4brw-d67c", "saepk4.pem", + "b63662c6f0bdd12bf5a2075ccfd7e132", False), + ("SAEPK-5.7.2.2", "cnj6-khsf-dgzh", "saepk5.pem", + "126d37fae167a53d4ebb08a235cef1da", False), + ("SAEPK-5.7.2.3", "hr7j-3cdr-wtq6", "saepk6.pem", + "61a84a86ffb1b9e23f576a0275ddcc78", True), + ("SAEPK-5.7.2.4", "geoh-2rvn-ivwu", "saepk7.pem", + "61a84a86ffb1b9e23f576a0275ddcc78", False), + ("SAEPK-5.7.2.4", "geoh-2rvn-ivwu", "saepk8_sig.pem", + "61a84a86ffb1b9e23f576a0275ddcc78", True), + ("SAEPK-5.7.3", "hbhh-r4um-jzjs", "saepk9.pem", + "af9b55bce52040892634bb3e41d557ee", False)] + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + for ssid, pw, keypair, m, failure in tests: + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + failure) + finally: + stop_sigma_dut(sigma) From b96a4fa99650eac63497b707fb823a1a3065399b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 11:25:40 +0300 Subject: [PATCH 0612/1105] tests: Report unknown WpaSupplicant::connect() arguments Signed-off-by: Jouni Malinen --- tests/hwsim/wpasupplicant.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 0ed043802..7c089c049 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1110,6 +1110,15 @@ class WpaSupplicant: if field in kwargs and kwargs[field]: self.set_network(id, field, kwargs[field]) + known_args = {"raw_psk", "password_hex", "peerkey", "okc", "ocsp", + "only_add_network", "wait_connect"} + unknown = set(kwargs.keys()) + unknown -= set(quoted) + unknown -= set(not_quoted) + unknown -= known_args + if unknown: + raise Exception("Unknown WpaSupplicant::connect() arguments: " + str(unknown)) + if "raw_psk" in kwargs and kwargs['raw_psk']: self.set_network(id, "psk", kwargs['raw_psk']) if "password_hex" in kwargs and kwargs['password_hex']: From 1c846d647e13923cfd1170068e5c944606041656 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 11:42:59 +0300 Subject: [PATCH 0613/1105] SAE-PK: Allow SAE authentication without PK to be disabled The new wpa_supplicant network profile parameter sae_pk_only=1 can now be used to disable use of SAE authentication without SAE-PK. Signed-off-by: Jouni Malinen --- wpa_supplicant/config.c | 1 + wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 9 +++++++++ wpa_supplicant/events.c | 23 ++++++++++++++++++++--- wpa_supplicant/sme.c | 6 ++++++ wpa_supplicant/wpa_supplicant.conf | 5 +++++ 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 49b25f124..86373ad05 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2582,6 +2582,7 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(ft_eap_pmksa_caching, 0, 1) }, { INT_RANGE(beacon_prot, 0, 1) }, { INT_RANGE(transition_disable, 0, 255) }, + { INT_RANGE(sae_pk_only, 0, 1) }, }; #undef OFFSET diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index a69c4cc6d..9a1c39cc7 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -937,6 +937,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(ft_eap_pmksa_caching); INT(beacon_prot); INT(transition_disable); + INT(sae_pk_only); #ifdef CONFIG_HT_OVERRIDES INT_DEF(disable_ht, DEFAULT_DISABLE_HT); INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 1e2c32268..730282f3b 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -1121,6 +1121,15 @@ struct wpa_ssid { * OWE) */ u8 transition_disable; + + /** + * sae_pk_only - SAE-PK only mode (disable transition mode) + * + * 0 = enable transition mode (allow SAE authentication without SAE-PK) + * 1 = disable transition mode (allow SAE authentication only with + * SAE-PK) + */ + int sae_pk_only; }; #endif /* CONFIG_SSID_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index f0f91892f..dd83ddce2 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1094,6 +1094,9 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, const u8 *ie; struct wpa_ssid *ssid; int osen, rsn_osen = 0; +#ifdef CONFIG_SAE + u8 rsnxe_capa = 0; +#endif /* CONFIG_SAE */ #ifdef CONFIG_MBO const u8 *assoc_disallow; #endif /* CONFIG_MBO */ @@ -1113,6 +1116,12 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); osen = ie != NULL; +#ifdef CONFIG_SAE + ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (ie && ie[1] >= 1) + rsnxe_capa = ie[2]; +#endif /* CONFIG_SAE */ + if (debug_print) { wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s", @@ -1349,9 +1358,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && wpa_s->conf->sae_pwe != 3 && wpa_key_mgmt_sae(ssid->key_mgmt) && - (!(ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX)) || - ie[1] < 1 || - !(ie[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)))) { + !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { if (debug_print) wpa_dbg(wpa_s, MSG_DEBUG, " skip - SAE H2E required, but not supported by the AP"); @@ -1359,6 +1366,16 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_SAE */ +#ifdef CONFIG_SAE_PK + if (ssid->sae_pk_only && + !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK))) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - SAE-PK required, but not supported by the AP"); + continue; + } +#endif /* CONFIG_SAE_PK */ + #ifndef CONFIG_IBSS_RSN if (ssid->mode == WPAS_MODE_IBSS && !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 3ad006528..1d347839a 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -154,6 +154,12 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, use_pt = 1; use_pk = true; } + + if (ssid->sae_pk_only && !use_pk) { + wpa_printf(MSG_DEBUG, + "SAE: Cannot use PK with the selected AP"); + return NULL; + } #endif /* CONFIG_SAE_PK */ if (use_pt || wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) { diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 3b9056770..45a811f64 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1472,6 +1472,11 @@ fast_reauth=1 # 2: do not allow PFS to be used #dpp_pfs=0 +# SAE-PK only mode (disable transition mode) +# 0: enable transition mode (allow SAE authentication without SAE-PK) +# 1: disable transition mode (allow SAE authentication only with SAE-PK) +#sae_pk_only=0 + # MAC address policy # 0 = use permanent MAC address # 1 = use random MAC address for each ESS connection From 4ea4df529ddac75a97470a7096e92e7d4b2781e7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 11:17:03 +0300 Subject: [PATCH 0614/1105] tests: SAE-PK only Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 53 ++++++++++++++++++++++++++++++++++++ tests/hwsim/wpasupplicant.py | 1 + 2 files changed, 54 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 4cd95cdc6..c024312fd 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -119,3 +119,56 @@ def test_sae_pk_group_20(dev, apdev): run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk, ap_groups="20") finally: dev[0].set("sae_groups", "") + +def test_sae_pk_password_without_pk(dev, apdev): + """SAE-PK password but not SAE-PK on the AP""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "dwxm-zv66-p5ue" + + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = pw + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", scan_freq="2412") + +def test_sae_pk_only(dev, apdev): + """SAE-PK only""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "dwxm-zv66-p5ue" + m = "431ff8322f93b9dc50ded9f3d14ace22" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = pw + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", sae_pk_only="1", + scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) + if ev is None: + raise Exception("No result for the connection attempt") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection without SAE-PK") + dev[0].request("DISCONNECT") + dev[0].dump_monitor() + + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid2, freq=2412, force_scan=True) + dev[0].request("RECONNECT") + ev = dev[0].wait_connected() + if bssid2 not in ev: + raise Exception("Unexpected connection BSSID") diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 7c089c049..2c94162fa 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1102,6 +1102,7 @@ class WpaSupplicant: "dpp_netaccesskey", "dpp_netaccesskey_expiry", "dpp_pfs", "group_mgmt", "owe_group", "owe_only", "owe_ptk_workaround", + "transition_disable", "sae_pk_only", "roaming_consortium_selection", "ocv", "multi_ap_backhaul_sta", "rx_stbc", "tx_stbc", "ft_eap_pmksa_caching", "beacon_prot", From bc908daacec237d6450f38e1077daed9e0cbbf2e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 11:47:12 +0300 Subject: [PATCH 0615/1105] Document more network profile parameters Some of the recently added wpa_supplicant network profile parameters were not documented in wpa_supplicant.conf. Add these there based on the documentation in config_ssid.h. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.conf | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 45a811f64..bf8a6dd5a 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1472,6 +1472,50 @@ fast_reauth=1 # 2: do not allow PFS to be used #dpp_pfs=0 +# Whether Beacon protection is enabled +# This depends on management frame protection (ieee80211w) being enabled. +#beacon_prot=0 + +# OWE DH Group +# 0: use default (19) first and then try all supported groups one by one if AP +# rejects the selected group +# 1-65535: DH Group to use for OWE +# Groups 19 (NIST P-256), 20 (NIST P-384), and 21 (NIST P-521) are +# currently supported. +#owe_group=0 + +# OWE-only mode (disable transition mode) +# 0: enable transition mode (allow connection to either OWE or open BSS) +# 1 = disable transition mode (allow connection only with OWE) +#owe_only=0 + +# OWE PTK derivation workaround +# Initial OWE implementation used SHA256 when deriving the PTK for all +# OWE groups. This was supposed to change to SHA384 for group 20 and +# SHA512 for group 21. This parameter can be used to enable older +# behavior mainly for testing purposes. There is no impact to group 19 +# behavior, but if enabled, this will make group 20 and 21 cases use +# SHA256-based PTK derivation which will not work with the updated +# OWE implementation on the AP side. +#owe_ptk_workaround=0 + +# Transition Disable indication +# The AP can notify authenticated stations to disable transition mode +# in their network profiles when the network has completed transition +# steps, i.e., once sufficiently large number of APs in the ESS have +# been updated to support the more secure alternative. When this +# indication is used, the stations are expected to automatically +# disable transition mode and less secure security options. This +# includes use of WEP, TKIP (including use of TKIP as the group +# cipher), and connections without PMF. +# Bitmap bits: +# bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK +# and only allow SAE to be used) +# bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK) +# bit 2 (0x04): WPA3-Enterprise (move to requiring PMF) +# bit 3 (0x08): Enhanced Open (disable use of open network; require +# OWE) + # SAE-PK only mode (disable transition mode) # 0: enable transition mode (allow SAE authentication without SAE-PK) # 1: disable transition mode (allow SAE authentication only with SAE-PK) From cc22fb1b869ccd8c0c6f52134cb29e25a6b45c16 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 12:08:37 +0300 Subject: [PATCH 0616/1105] SAE: Move H2E and PK flags to main sae_data This maintains knowledge of whether H2E or PK was used as part of the SAE authentication beyond the removal of temporary state needed during that authentication. This makes it easier to use information about which kind of SAE authentication was used at higher layer functionality. Signed-off-by: Jouni Malinen --- src/ap/drv_callbacks.c | 2 +- src/ap/ieee802_11.c | 14 +++++++------- src/common/sae.c | 24 ++++++++++++------------ src/common/sae.h | 4 ++-- src/common/sae_pk.c | 2 +- wpa_supplicant/sme.c | 17 +++++++---------- 6 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 173549e7b..36678e7a3 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -439,7 +439,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, #ifdef CONFIG_SAE if (hapd->conf->sae_pwe == 2 && sta->auth_alg == WLAN_AUTH_SAE && - sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e && + sta->sae && !sta->sae->h2e && elems.rsnxe && elems.rsnxe_len >= 1 && (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { wpa_printf(MSG_INFO, "SAE: " MACSTR diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 0822dfd34..eca8b19ad 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -483,7 +483,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, if (sta->sae->tmp) { rx_id = sta->sae->tmp->pw_id; - use_pt = sta->sae->tmp->h2e; + use_pt = sta->sae->h2e; #ifdef CONFIG_SAE_PK os_memcpy(sta->sae->tmp->own_addr, hapd->own_addr, ETH_ALEN); os_memcpy(sta->sae->tmp->peer_addr, sta->addr, ETH_ALEN); @@ -594,9 +594,9 @@ static int auth_sae_send_commit(struct hostapd_data *hapd, if (data == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; - if (sta->sae->tmp && sta->sae->tmp->pk) + if (sta->sae->tmp && sta->sae->pk) status = WLAN_STATUS_SAE_PK; - else if (sta->sae->tmp && sta->sae->tmp->h2e) + else if (sta->sae->tmp && sta->sae->h2e) status = WLAN_STATUS_SAE_HASH_TO_ELEMENT; else status = WLAN_STATUS_SUCCESS; @@ -921,11 +921,11 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta, case SAE_NOTHING: if (auth_transaction == 1) { if (sta->sae->tmp) { - sta->sae->tmp->h2e = + sta->sae->h2e = (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || status_code == WLAN_STATUS_SAE_PK); - sta->sae->tmp->pk = + sta->sae->pk = status_code == WLAN_STATUS_SAE_PK; } ret = auth_sae_send_commit(hapd, sta, bssid, @@ -1440,7 +1440,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, "SAE: Request anti-clogging token from " MACSTR, MAC2STR(sta->addr)); if (sta->sae->tmp) - h2e = sta->sae->tmp->h2e; + h2e = sta->sae->h2e; if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || status_code == WLAN_STATUS_SAE_PK) h2e = 1; @@ -3405,7 +3405,7 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->conf->sae_pwe == 2 && sta->auth_alg == WLAN_AUTH_SAE && - sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e && + sta->sae && !sta->sae->h2e && elems.rsnxe && elems.rsnxe_len >= 1 && (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { wpa_printf(MSG_INFO, "SAE: " MACSTR diff --git a/src/common/sae.c b/src/common/sae.c index a298212ca..c8e77aaec 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -1364,8 +1364,8 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2, identifier) < 0)) return -1; - sae->tmp->h2e = 0; - sae->tmp->pk = 0; + sae->h2e = 0; + sae->pk = 0; return sae_derive_commit(sae); } @@ -1434,7 +1434,7 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, return -1; } - sae->tmp->h2e = 1; + sae->h2e = 1; return sae_derive_commit(sae); } @@ -1559,14 +1559,14 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) * When SAE-PK is used, * KCK || PMK || KEK = KDF-Hash-Length(keyseed, "SAE-PK keys", context) */ - if (!sae->tmp->h2e) + if (!sae->h2e) hash_len = SHA256_MAC_LEN; else if (sae->tmp->dh) hash_len = sae_ffc_prime_len_2_hash_len(prime_len); else hash_len = sae_ecc_prime_len_2_hash_len(prime_len); - if (sae->tmp->h2e && (sae->tmp->own_rejected_groups || - sae->tmp->peer_rejected_groups)) { + if (sae->h2e && (sae->tmp->own_rejected_groups || + sae->tmp->peer_rejected_groups)) { struct wpabuf *own, *peer; own = sae->tmp->own_rejected_groups; @@ -1617,13 +1617,13 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) * octets). */ crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len); wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); - if (!sae->tmp->pk && + if (!sae->pk && sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", val, sae->tmp->order_len, keys, hash_len + SAE_PMK_LEN) < 0) goto fail; #ifdef CONFIG_SAE_PK - if (sae->tmp->pk && + if (sae->pk && sae_kdf_hash(hash_len, keyseed, "SAE-PK keys", val, sae->tmp->order_len, keys, 2 * hash_len + SAE_PMK_LEN) < 0) @@ -1635,7 +1635,7 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN); os_memcpy(sae->pmkid, val, SAE_PMKID_LEN); #ifdef CONFIG_SAE_PK - if (sae->tmp->pk) { + if (sae->pk) { os_memcpy(sae->tmp->kek, keys + hash_len + SAE_PMK_LEN, hash_len); sae->tmp->kek_len = hash_len; @@ -1677,7 +1677,7 @@ int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, return -1; wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ - if (!sae->tmp->h2e && token) { + if (!sae->h2e && token) { wpabuf_put_buf(buf, token); wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token", wpabuf_head(token), wpabuf_len(token)); @@ -1718,7 +1718,7 @@ int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, identifier); } - if (sae->tmp->h2e && sae->tmp->own_rejected_groups) { + if (sae->h2e && sae->tmp->own_rejected_groups) { wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups", sae->tmp->own_rejected_groups); wpabuf_put_u8(buf, WLAN_EID_EXTENSION); @@ -1728,7 +1728,7 @@ int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, wpabuf_put_buf(buf, sae->tmp->own_rejected_groups); } - if (sae->tmp->h2e && token) { + if (sae->h2e && token) { wpabuf_put_u8(buf, WLAN_EID_EXTENSION); wpabuf_put_u8(buf, 1 + wpabuf_len(token)); wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN); diff --git a/src/common/sae.h b/src/common/sae.h index 61b228819..887cd4e9a 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -59,8 +59,6 @@ struct sae_temporary_data { u8 bssid[ETH_ALEN]; struct wpabuf *own_rejected_groups; struct wpabuf *peer_rejected_groups; - unsigned int h2e:1; - unsigned int pk:1; unsigned int own_addr_higher:1; #ifdef CONFIG_SAE_PK @@ -106,6 +104,8 @@ struct sae_data { int group; unsigned int sync; /* protocol instance variable: Sync */ u16 rc; /* protocol instance variable: Rc (received send-confirm) */ + unsigned int h2e:1; + unsigned int pk:1; struct sae_temporary_data *tmp; }; diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index 2469534b9..806498c38 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -528,7 +528,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) if (!tmp) return -1; - if (!tmp->pk || tmp->ap_pk) + if (!sae->pk || tmp->ap_pk) return 0; if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 1d347839a..fa18f9893 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -128,8 +128,8 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, os_memcmp(bssid, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) { wpa_printf(MSG_DEBUG, "SAE: Reuse previously generated PWE on a retry with the same AP"); - use_pt = wpa_s->sme.sae.tmp->h2e; - use_pk = wpa_s->sme.sae.tmp->pk; + use_pt = wpa_s->sme.sae.h2e; + use_pk = wpa_s->sme.sae.pk; goto reuse_data; } if (sme_set_sae_group(wpa_s) < 0) { @@ -190,7 +190,7 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, if (wpa_s->sme.sae.tmp) { os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN); if (use_pt && use_pk) - wpa_s->sme.sae.tmp->pk = 1; + wpa_s->sme.sae.pk = 1; #ifdef CONFIG_SAE_PK os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr, ETH_ALEN); @@ -1266,8 +1266,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, wpabuf_free(wpa_s->sme.sae_token); token_pos = data + sizeof(le16); token_len = len - sizeof(le16); - if (wpa_s->sme.sae.tmp) - h2e = wpa_s->sme.sae.tmp->h2e; + h2e = wpa_s->sme.sae.h2e; if (h2e) { if (token_len < 3) { wpa_dbg(wpa_s, MSG_DEBUG, @@ -1348,20 +1347,18 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, "SAE: Ignore commit message while waiting for confirm"); return 0; } - if (wpa_s->sme.sae.tmp && wpa_s->sme.sae.tmp->h2e && - status_code == WLAN_STATUS_SUCCESS) { + if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) { wpa_printf(MSG_DEBUG, "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected"); return -1; } - if (wpa_s->sme.sae.tmp && - (!wpa_s->sme.sae.tmp->h2e || wpa_s->sme.sae.tmp->pk) && + if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) && status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) { wpa_printf(MSG_DEBUG, "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected"); return -1; } - if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->pk && + if (!wpa_s->sme.sae.pk && status_code == WLAN_STATUS_SAE_PK) { wpa_printf(MSG_DEBUG, "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected"); From a7526952907caa1150e15478e5a43bb1ba896af7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 12:09:47 +0300 Subject: [PATCH 0617/1105] SAE: Add sae_h2e and sae_pk to wpa_supplicant STATUS command This provides additional information on which options were used during SAE authentication. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index e727dc5bb..79b5e8054 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -2283,8 +2283,12 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, !wpa_s->ap_iface && #endif /* CONFIG_AP */ wpa_s->sme.sae.state == SAE_ACCEPTED) { - ret = os_snprintf(pos, end - pos, "sae_group=%d\n", - wpa_s->sme.sae.group); + ret = os_snprintf(pos, end - pos, "sae_group=%d\n" + "sae_h2e=%d\n" + "sae_pk=%d\n", + wpa_s->sme.sae.group, + wpa_s->sme.sae.h2e, + wpa_s->sme.sae.pk); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; From 7937160d241e8e988c21cac84f655f81cf077501 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 12:10:41 +0300 Subject: [PATCH 0618/1105] tests: Verify SAE-PK use more explicitly Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index c024312fd..e6b707ed7 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -22,6 +22,10 @@ def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None): raise Exception("Could not get BSS flags from BSS table") if "[SAE-H2E]" not in bss['flags'] or "[SAE-PK]" not in bss['flags']: raise Exception("Unexpected BSS flags: " + bss['flags']) + status = dev.get_status() + if "sae_h2e" not in status or "sae_pk" not in status or \ + status["sae_h2e"] != "1" or status["sae_pk"] != "1": + raise Exception("SAE-PK or H2E not indicated in STATUS") dev.request("REMOVE_NETWORK *") dev.wait_disconnected() hapd.disable() @@ -134,6 +138,8 @@ def test_sae_pk_password_without_pk(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", scan_freq="2412") + if dev[0].get_status_field("sae_pk") != "0": + raise Exception("Unexpected sae_pk STATUS value") def test_sae_pk_only(dev, apdev): """SAE-PK only""" @@ -172,3 +178,5 @@ def test_sae_pk_only(dev, apdev): ev = dev[0].wait_connected() if bssid2 not in ev: raise Exception("Unexpected connection BSSID") + if dev[0].get_status_field("sae_pk") != "1": + raise Exception("SAE-PK was not used") From 8d1cbaaff729b041182651bfcec5c9731a787655 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 12:06:59 +0300 Subject: [PATCH 0619/1105] SAE-PK: Transition mode disabled indication processing Allow AP to disable transition mode for SAE-PK (i.e., prevent SAE authentication without SAE-PK). Signed-off-by: Jouni Malinen --- wpa_supplicant/wpas_glue.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 6bd271e12..ec6d7858d 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1268,6 +1268,7 @@ static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap) if (!ssid) return; +#ifdef CONFIG_SAE if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) && wpa_key_mgmt_sae(wpa_s->key_mgmt) && (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && @@ -1279,6 +1280,24 @@ static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap) changed = 1; } + if ((bitmap & TRANSITION_DISABLE_SAE_PK) && + wpa_key_mgmt_sae(wpa_s->key_mgmt) && +#ifdef CONFIG_SME + wpa_s->sme.sae.state == SAE_ACCEPTED && + wpa_s->sme.sae.pk && +#endif /* CONFIG_SME */ + (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && + (!ssid->sae_pk_only || + ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + wpa_printf(MSG_DEBUG, + "SAE-PK: SAE authentication without PK disabled based on AP notification"); + disable_wpa_wpa2(ssid); + ssid->sae_pk_only = 1; + changed = 1; + } +#endif /* CONFIG_SAE */ + if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) && wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | From 747c69fa904c9a85032f4d393fad3cf2bca1461e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 12:18:55 +0300 Subject: [PATCH 0620/1105] tests: SAE-PK transition disable indication Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index e6b707ed7..94a8a743e 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -180,3 +180,30 @@ def test_sae_pk_only(dev, apdev): raise Exception("Unexpected connection BSSID") if dev[0].get_status_field("sae_pk") != "1": raise Exception("SAE-PK was not used") + +def test_sae_pk_transition_disable(dev, apdev): + """SAE-PK transition disable indication""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "dwxm-zv66-p5ue" + m = "431ff8322f93b9dc50ded9f3d14ace22" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + params['transition_disable'] = '0x02' + hapd = hostapd.add_ap(apdev[0], params) + + id = dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "02": + raise Exception("Unexpected transition disable bitmap: " + ev) + + val = dev[0].get_network(id, "sae_pk_only") + if val != "1": + raise Exception("Unexpected sae_pk_only value: " + str(val)) From 960e8e53346e2e6163de436835ef440d615a879f Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Wed, 27 May 2020 16:55:49 +0530 Subject: [PATCH 0621/1105] QCA vendor attribute to configure NSS Defines the attribute in SET(GET)_WIFI_CONFIGURATION to dynamically configure NSS. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index ea68beceb..bf29f12ba 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2183,6 +2183,18 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC = 69, + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of spatial streams. When configured in the disconnected + * state, the updated configuration will be considered for the + * immediately following connection attempt. If the NSS is updated after + * the connection, the updated NSS value is notified to the peer using + * the Operating Mode Notification/Spatial Multiplexing Power Save + * frame. The updated NSS value after the connection shall not be + * greater than the one negotiated during the connection. Any such + * higher value configuration shall be returned with a failure. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_NSS = 70, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = From e53756a64eb6c7aebd72642b54e02575991348e5 Mon Sep 17 00:00:00 2001 From: Min Liu Date: Fri, 5 Jun 2020 11:11:51 +0800 Subject: [PATCH 0622/1105] Fix a typo vendor attribute documentation Fix a typo in comment of enum qca_wlan_tspec_ack_policy. Signed-off-by: Min Liu --- src/common/qca-vendor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index bf29f12ba..84268d98b 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -9029,7 +9029,7 @@ enum qca_wlan_tspec_direction { /** * enum qca_wlan_tspec_ack_policy - MAC acknowledgement policy in TSPEC - * As what is defined in IEEE Std 802.11-201, Table 9-141. + * As what is defined in IEEE Std 802.11-2016, Table 9-141. * * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY. */ From 18f3f99ac46701deeafd47bfc18bb97ace54cff5 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 22 May 2020 14:47:34 +0530 Subject: [PATCH 0623/1105] Add vendor attributes to configure testing functionality for FT/OCV/SAE Add new QCA vendor attributes to configure RSNXE Used (FTE), ignore CSA, and OCI frequency override with QCA vendor command QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION for STA testbed role. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 71 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 84268d98b..b81bbbe2a 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7283,6 +7283,37 @@ enum qca_wlan_vendor_attr_wifi_test_config { */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX = 39, + /* 8-bit unsigned value to configure an override for the RSNXE Used + * subfield in the MIC control field of the FTE in FT Reassociation + * Request frame. + * 0 - Default behavior, 1 - override with 1, 2 - override with 0. + * This attribute is used to configure the testbed device. + * This attribute can be configured when STA is in disconnected or + * associated state and the configuration is valid until the next + * disconnection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED = 40, + + /* 8-bit unsigned value to configure the driver to ignore CSA (Channel + * Switch Announcement) when STA is in connected state. + * 0 - Default behavior, 1 - Ignore CSA. + * This attribute is used to configure the testbed device. + * This attribute can be configured when STA is in disconnected or + * associated state and the configuration is valid until the next + * disconnection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA = 41, + + /* Nested attribute values required to configure OCI (Operating Channel + * Information). Attributes defined in enum + * qca_wlan_vendor_attr_oci_override are nested within this attribute. + * This attribute is used to configure the testbed device. + * This attribute can be configured when STA is in disconnected or + * associated state and the configuration is valid until the next + * disconnection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE = 42, + /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX = @@ -9171,4 +9202,44 @@ enum qca_wlan_vendor_attr_config_tspec { QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_AFTER_LAST - 1, }; +/** + * enum qca_wlan_vendor_oci_override_frame_type - OCI override frame type + * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ: SA Query Request frame + * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP: SA Query Response frame + * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ: FT Reassociation Request + * frame + * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ: FILS Reassociation + * Request frame. + */ +enum qca_wlan_vendor_oci_override_frame_type { + QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ = 1, + QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP = 2, + QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ = 3, + QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ = 4, +}; + +/** + * enum qca_wlan_vendor_attr_oci_override: Represents attributes for + * OCI override request. These attributes are used inside nested attribute + * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE in QCA vendor command + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * + * @QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE: Required attribute, u8. + * Values from enum qca_wlan_vendor_oci_override_frame_type used in this + * attribute to specify the frame type in which the OCI is to be overridden. + * + * @QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY: Required (u32) + * OCI frequency (in MHz) to override in the specified frame type. + */ +enum qca_wlan_vendor_attr_oci_override { + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE = 1, + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX = + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_AFTER_LAST - 1, +}; + #endif /* QCA_VENDOR_H */ From 63653307df2dc4bd6b3429cbc63278da1f4def44 Mon Sep 17 00:00:00 2001 From: Tanmay Garg Date: Mon, 18 May 2020 15:52:44 +0530 Subject: [PATCH 0624/1105] Add support for indicating missing driver AKM capability flags Add support for missing driver AKM capability flags from the list of RSN_AUTH_KEY_MGMT_* flags and make these available through the 'GET_CAPABILITY key_mgmt' control interface command. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 7 ++++ src/drivers/driver_nl80211_capa.c | 21 ++++++++++ wpa_supplicant/ctrl_iface.c | 66 +++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 1e2e332a6..350c1cb57 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1747,6 +1747,13 @@ struct wpa_driver_capa { #define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 0x00004000 #define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 0x00008000 #define WPA_DRIVER_CAPA_KEY_MGMT_SAE 0x00010000 +#define WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256 0x00020000 +#define WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256 0x00040000 +#define WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE 0x00080000 +#define WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE 0x00100000 +#define WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384 0x00200000 +#define WPA_DRIVER_CAPA_KEY_MGMT_CCKM 0x00400000 +#define WPA_DRIVER_CAPA_KEY_MGMT_OSEN 0x00800000 /** Bitfield of supported key management suites */ unsigned int key_mgmt; unsigned int key_mgmt_iftype[WPA_IF_MAX]; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index a3341a088..3e8dcef2a 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -281,6 +281,27 @@ static unsigned int get_akm_suites_info(struct nlattr *tb) case RSN_AUTH_KEY_MGMT_FT_PSK: key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; break; + case RSN_AUTH_KEY_MGMT_802_1X_SHA256: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256; + break; + case RSN_AUTH_KEY_MGMT_PSK_SHA256: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256; + break; + case RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE; + break; + case RSN_AUTH_KEY_MGMT_FT_SAE: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE; + break; + case RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384; + break; + case RSN_AUTH_KEY_MGMT_CCKM: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_CCKM; + break; + case RSN_AUTH_KEY_MGMT_OSEN: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OSEN; + break; case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B: key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B; break; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 79b5e8054..298f3c442 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -4221,6 +4221,27 @@ static int ctrl_iface_get_capability_key_mgmt(int res, bool strict, pos += ret; } + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) { + ret = os_snprintf(pos, end - pos, " WAPI-PSK"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) { + ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) { + ret = os_snprintf(pos, end - pos, " CCKM"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + #ifdef CONFIG_SUITEB if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B"); @@ -4288,6 +4309,28 @@ static int ctrl_iface_get_capability_key_mgmt(int res, bool strict, return pos - buf; pos += ret; } + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { + ret = os_snprintf(pos, end - pos, " FT-EAP"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#ifdef CONFIG_SAE + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) { + ret = os_snprintf(pos, end - pos, " FT-SAE"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SAE */ +#ifdef CONFIG_SHA384 + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) { + ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_SAE if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { @@ -4297,6 +4340,29 @@ static int ctrl_iface_get_capability_key_mgmt(int res, bool strict, pos += ret; } #endif /* CONFIG_SAE */ +#ifdef CONFIG_SHA256 + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) { + ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) { + ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SHA256 */ +#ifdef CONFIG_HS20 + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) { + ret = os_snprintf(pos, end - pos, " OSEN"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_HS20 */ return pos - buf; } From 1a28589b28626641c8ffa43f4816bf1c3cf81def Mon Sep 17 00:00:00 2001 From: Min Liu Date: Fri, 5 Jun 2020 11:55:26 +0800 Subject: [PATCH 0625/1105] QCA vendor attributes for setting channel width Define QCA vendor attribute in SET(GET)_WIFI_CONFIGURATION to dynamically configure capabilities for channel width. Signed-off-by: Min Liu --- src/common/qca-vendor.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index b81bbbe2a..a781f337e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2135,6 +2135,20 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE = 62, + /* 8-bit unsigned value to configure the maximum supported channel width + * for STA mode. If this value is configured when STA is in connected + * state, it should not exceed the negotiated channel width. If it is + * configured when STA is in disconnected state, the configured value + * will take effect for the next immediate connection. + * Possible values are: + * NL80211_CHAN_WIDTH_20 + * NL80211_CHAN_WIDTH_40 + * NL80211_CHAN_WIDTH_80 + * NL80211_CHAN_WIDTH_80P80 + * NL80211_CHAN_WIDTH_160 + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH = 63, + /* 8-bit unsigned value to configure the maximum number of subframes of * TX MSDU for aggregation. Possible values are 0-31. When set to 0, * it is decided by the hardware. From 5cf91afeeb53502bbcafe3d8eb12cd4cde250002 Mon Sep 17 00:00:00 2001 From: Min Liu Date: Fri, 5 Jun 2020 12:15:24 +0800 Subject: [PATCH 0626/1105] QCA vendor attribute for dynamic bandwidth adjustment Define QCA vendor attribute in SET(GET)_WIFI_CONFIGURATION to dynamically configure capabilities for dynamic bandwidth adjustment. Signed-off-by: Min Liu --- src/common/qca-vendor.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index a781f337e..c6a19b7bf 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2149,6 +2149,14 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH = 63, + /* 8-bit unsigned value to enable/disable dynamic bandwidth adjustment. + * This attribute is only applicable for STA mode. When dynamic + * bandwidth adjustment is disabled, STA will use static channel width + * the value of which is negotiated during connection. + * 1-enable (default), 0-disable + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW = 64, + /* 8-bit unsigned value to configure the maximum number of subframes of * TX MSDU for aggregation. Possible values are 0-31. When set to 0, * it is decided by the hardware. From 215b4d8a725c73fed4378f1e31b58760a190084a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 16:46:32 +0300 Subject: [PATCH 0627/1105] FT: Do not add PMKID to the driver for FT-EAP if caching is disabled wpa_supplicant disables PMKSA caching with FT-EAP by default due to known interoperability issues with APs. This is allowed only if the network profile is explicitly enabling caching with ft_eap_pmksa_caching=1. However, the PMKID for such PMKSA cache entries was still being configured to the driver and it was possible for the driver to build an RSNE with the PMKID for SME-in-driver cases. This could result in hitting the interop issue with some APs. Fix this by skipping PMKID configuration to the driver fot FT-EAP AKM if ft_eap_pmksa_caching=1 is not used in the network profile so that the driver and wpa_supplicant behavior are in sync for this. Signed-off-by: Jouni Malinen --- src/rsn_supp/pmksa_cache.c | 3 ++- src/rsn_supp/preauth.c | 3 ++- src/rsn_supp/wpa.h | 2 +- src/rsn_supp/wpa_i.h | 4 ++-- wpa_supplicant/preauth_test.c | 3 ++- wpa_supplicant/wpas_glue.c | 18 ++++++++++++++++-- 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index 4a175f166..e481dd5d6 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -269,7 +269,8 @@ pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, entry->fils_cache_id_set ? entry->fils_cache_id : NULL, entry->pmk, entry->pmk_len, pmksa->sm->dot11RSNAConfigPMKLifetime, - pmksa->sm->dot11RSNAConfigPMKReauthThreshold); + pmksa->sm->dot11RSNAConfigPMKReauthThreshold, + entry->akmp); return entry; } diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index d4d1307a9..1a38bf6bc 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -349,7 +349,8 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) * PMKIDs again, so report the existing data now. */ if (p) { wpa_sm_add_pmkid(sm, NULL, candidate->bssid, p->pmkid, - NULL, p->pmk, p->pmk_len, 0, 0); + NULL, p->pmk, p->pmk_len, 0, 0, + p->akmp); } dl_list_del(&candidate->list); diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index f3901e01b..a4512eadc 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -43,7 +43,7 @@ struct wpa_sm_ctx { int (*add_pmkid)(void *ctx, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, const u8 *pmk, size_t pmk_len, u32 pmk_lifetime, - u8 pmk_reauth_threshold); + u8 pmk_reauth_threshold, int akmp); int (*remove_pmkid)(void *ctx, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id); void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 4db925619..b2b43f4f0 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -268,12 +268,12 @@ static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *cache_id, const u8 *pmk, size_t pmk_len, u32 pmk_lifetime, - u8 pmk_reauth_threshold) + u8 pmk_reauth_threshold, int akmp) { WPA_ASSERT(sm->ctx->add_pmkid); return sm->ctx->add_pmkid(sm->ctx->ctx, network_ctx, bssid, pmkid, cache_id, pmk, pmk_len, pmk_lifetime, - pmk_reauth_threshold); + pmk_reauth_threshold, akmp); } static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, void *network_ctx, diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c index 4a8f4ff8f..de49948f7 100644 --- a/wpa_supplicant/preauth_test.c +++ b/wpa_supplicant/preauth_test.c @@ -154,7 +154,8 @@ static int wpa_supplicant_add_pmkid(void *wpa_s, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, const u8 *pmk, size_t pmk_len, - u32 pmk_lifetime, u8 pmk_reauth_threshold) + u32 pmk_lifetime, u8 pmk_reauth_threshold, + int akmp) { printf("%s - not implemented\n", __func__); return -1; diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index ec6d7858d..bafcb00e0 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -575,7 +575,8 @@ static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, const u8 *pmk, size_t pmk_len, - u32 pmk_lifetime, u8 pmk_reauth_threshold) + u32 pmk_lifetime, u8 pmk_reauth_threshold, + int akmp) { struct wpa_supplicant *wpa_s = _wpa_s; struct wpa_ssid *ssid; @@ -583,9 +584,22 @@ static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, os_memset(¶ms, 0, sizeof(params)); ssid = wpas_get_network_ctx(wpa_s, network_ctx); - if (ssid) + if (ssid) { wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d", MAC2STR(bssid), ssid->id); + if ((akmp == WPA_KEY_MGMT_FT_IEEE8021X || + akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) && + !ssid->ft_eap_pmksa_caching) { + /* Since we will not be using PMKSA caching for FT-EAP + * within wpa_supplicant to avoid known interop issues + * with APs, do not add this PMKID to the driver either + * so that we won't be hitting those interop issues + * with driver-based RSNE generation. */ + wpa_printf(MSG_DEBUG, + "FT: Do not add PMKID entry to the driver since FT-EAP PMKSA caching is not enabled in configuration"); + return 0; + } + } if (ssid && fils_cache_id) { params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; From f38146e5599d6f9914efd009cc39f4d868a7f75f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 6 Jun 2020 16:46:03 +0300 Subject: [PATCH 0628/1105] tests: PMKSA cache control interface for external management (FT) Signed-off-by: Jouni Malinen --- tests/hwsim/test_pmksa_cache.py | 60 +++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/hwsim/test_pmksa_cache.py b/tests/hwsim/test_pmksa_cache.py index 22db7e8d4..526f7f455 100644 --- a/tests/hwsim/test_pmksa_cache.py +++ b/tests/hwsim/test_pmksa_cache.py @@ -1098,6 +1098,66 @@ def test_pmksa_cache_ctrl_ext(dev, apdev): if "CTRL-EVENT-EAP-STARTED" in ev: raise Exception("Unexpected EAP exchange after external PMKSA cache restore") +def test_pmksa_cache_ctrl_ext_ft(dev, apdev): + """PMKSA cache control interface for external management (FT)""" + params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache") + params['wpa_key_mgmt'] = "FT-EAP" + params['nas_identifier'] = "nas.w1.fi" + params['r1_key_holder'] = "000102030406" + params["mobility_domain"] = "a1b2" + hapd = hostapd.add_ap(apdev[0], params) + bssid = apdev[0]['bssid'] + + id = dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="FT-EAP", + eap="GPSK", identity="gpsk user", + password="abcdefghijklmnop0123456789abcdef", + scan_freq="2412") + + res1 = dev[0].request("PMKSA_GET %d" % id) + logger.info("PMKSA_GET: " + res1) + if "UNKNOWN COMMAND" in res1: + raise HwsimSkip("PMKSA_GET not supported in the build") + if bssid not in res1: + raise Exception("PMKSA cache entry missing") + + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + dev[0].request("PMKSA_FLUSH") + + id = dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="FT-EAP", + eap="GPSK", identity="gpsk user", + password="abcdefghijklmnop0123456789abcdef", + ft_eap_pmksa_caching="1", + scan_freq="2412", only_add_network=True) + res3 = dev[0].request("PMKSA_GET %d" % id) + if res3 != '': + raise Exception("Unexpected PMKSA cache entry remains: " + res3) + + for entry in res1.splitlines(): + if "OK" not in dev[0].request("PMKSA_ADD %d %s" % (id, entry)): + raise Exception("Failed to add PMKSA entry") + + dev[0].select_network(id) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-CONNECTED"], timeout=15) + if ev is None: + raise Exception("Connection with the AP timed out") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Unexpected EAP exchange after external PMKSA cache restore") + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].dump_monitor() + dev[0].request("PMKSA_FLUSH") + # Add a PMKSA cache entry for FT-EAP with PMKSA caching disabled to confirm + # that the PMKID is not configured to the driver (this part requires manual + # check of the debug log currently). + dev[0].set_network(id, "ft_eap_pmksa_caching", "0") + for entry in res1.splitlines(): + if "OK" not in dev[0].request("PMKSA_ADD %d %s" % (id, entry)): + raise Exception("Failed to add PMKSA entry") + def test_rsn_preauth_processing(dev, apdev): """RSN pre-authentication processing on AP""" params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") From 85ca13ebcf155046bf9bf486c2f4f7e0e247fc2a Mon Sep 17 00:00:00 2001 From: Purushottam Kushwaha Date: Thu, 28 May 2020 12:07:37 +0530 Subject: [PATCH 0629/1105] wpa_cli: Add all_bss command to print all scan results (BSS entries) The wpa_supplicant control interface returns maximum of 4 kB of response data and, thus, limits maximum number of scan entries as part of SCAN_RESULTS to approximately 60. Add a new all_bss command to use a more robust iteration of the BSS table entries with the BSS command to to get all scan entries and print them in the same format as the scan_results command. Signed-off-by: Purushottam Kushwaha --- wpa_supplicant/wpa_cli.c | 74 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 6a2d2c3d6..f5b02f662 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -3059,6 +3059,78 @@ static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, #endif /* CONFIG_DPP */ +static int wpa_ctrl_command_bss(struct wpa_ctrl *ctrl, const char *cmd) +{ + char buf[512], *pos, *bssid, *freq, *level, *flags, *ssid; + size_t len; + int ret, id = -1; + + if (!ctrl_conn) + return -1; + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, + wpa_cli_msg_cb); + if (ret == -2) { + printf("'%s' command timed out.\n", cmd); + return -2; + } else if (ret < 0) { + printf("'%s' command failed.\n", cmd); + return -1; + } + + buf[len] = '\0'; + if (os_memcmp(buf, "FAIL", 4) == 0) + return -1; + + pos = buf; + while (*pos != '\0') { + if (str_starts(pos, "id=")) + id = atoi(pos + 3); + if (str_starts(pos, "bssid=")) + bssid = pos + 6; + if (str_starts(pos, "freq=")) + freq = pos + 5; + if (str_starts(pos, "level=")) + level = pos + 6; + if (str_starts(pos, "flags=")) + flags = pos + 6; + if (str_starts(pos, "ssid=")) + ssid = pos + 5; + + while (*pos != '\0' && *pos != '\n') + pos++; + *pos++ = '\0'; + } + if (id != -1) + printf("%s\t%s\t%s\t%s\t%s\n", bssid, freq, level, flags, ssid); + return id; +} + + +static int wpa_cli_cmd_all_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[64]; + int id = -1; + unsigned int mask; + + printf("bssid / frequency / signal level / flags / ssid\n"); + + mask = WPA_BSS_MASK_ID | WPA_BSS_MASK_BSSID | WPA_BSS_MASK_FREQ | + WPA_BSS_MASK_LEVEL | WPA_BSS_MASK_FLAGS | WPA_BSS_MASK_SSID; + do { + if (id < 0) + os_snprintf(cmd, sizeof(cmd), "BSS FIRST MASK=0x%x", + mask); + else + os_snprintf(cmd, sizeof(cmd), "BSS NEXT-%d MASK=0x%x", + id, mask); + id = wpa_ctrl_command_bss(ctrl, cmd); + } while (id >= 0); + + return 0; +} + + enum wpa_cli_cmd_flags { cli_cmd_flag_none = 0x00, cli_cmd_flag_sensitive = 0x01 @@ -3718,6 +3790,8 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { cli_cmd_flag_none, "*| = remove DPP pkex information" }, #endif /* CONFIG_DPP */ + { "all_bss", wpa_cli_cmd_all_bss, NULL, cli_cmd_flag_none, + "= list all BSS entries (scan results)" }, { NULL, NULL, NULL, cli_cmd_flag_none, NULL } }; From 9ad010c2908fab6ce6b8ffed449f3cec24172cce Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 11:53:26 +0300 Subject: [PATCH 0630/1105] SAE-PK: Allow automatic SAE-PK to be disabled This replaces the previously used sae_pk_only configuration parameter with a more generic sae_pk that can be used to specify how SAE-PK is negotiated. The default behavior (sae_pk=0) is to automatically negotiate SAE-PK whenever the AP supports it and the password is in appropriate format. sae_pk=1 allows only SAE-PK to be used and sae_pk=2 disables SAE-PK completely. Signed-off-by: Jouni Malinen --- wpa_supplicant/config.c | 2 +- wpa_supplicant/config_file.c | 2 +- wpa_supplicant/config_ssid.h | 19 +++++++++++++------ wpa_supplicant/events.c | 2 +- wpa_supplicant/sme.c | 3 ++- wpa_supplicant/wpa_supplicant.conf | 11 +++++++---- wpa_supplicant/wpas_glue.c | 4 ++-- 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 86373ad05..a9726e2d6 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2582,7 +2582,7 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(ft_eap_pmksa_caching, 0, 1) }, { INT_RANGE(beacon_prot, 0, 1) }, { INT_RANGE(transition_disable, 0, 255) }, - { INT_RANGE(sae_pk_only, 0, 1) }, + { INT_RANGE(sae_pk, 0, 2) }, }; #undef OFFSET diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 9a1c39cc7..1ca254813 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -937,7 +937,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(ft_eap_pmksa_caching); INT(beacon_prot); INT(transition_disable); - INT(sae_pk_only); + INT(sae_pk); #ifdef CONFIG_HT_OVERRIDES INT_DEF(disable_ht, DEFAULT_DISABLE_HT); INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 730282f3b..2c08c0218 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -62,6 +62,12 @@ enum wpas_mode { WPAS_MODE_MESH = 5, }; +enum sae_pk_mode { + SAE_PK_MODE_AUTOMATIC = 0, + SAE_PK_MODE_ONLY = 1, + SAE_PK_MODE_DISABLED = 2, +}; + /** * struct wpa_ssid - Network configuration data * @@ -1123,13 +1129,14 @@ struct wpa_ssid { u8 transition_disable; /** - * sae_pk_only - SAE-PK only mode (disable transition mode) - * - * 0 = enable transition mode (allow SAE authentication without SAE-PK) - * 1 = disable transition mode (allow SAE authentication only with - * SAE-PK) + * sae_pk - SAE-PK mode + * 0 = automatic SAE/SAE-PK selection based on password; enable + * transition mode (allow SAE authentication without SAE-PK) + * 1 = SAE-PK only (disable transition mode; allow SAE authentication + * only with SAE-PK) + * 2 = disable SAE-PK (allow SAE authentication only without SAE-PK) */ - int sae_pk_only; + enum sae_pk_mode sae_pk; }; #endif /* CONFIG_SSID_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index dd83ddce2..99940d95c 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1367,7 +1367,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, #endif /* CONFIG_SAE */ #ifdef CONFIG_SAE_PK - if (ssid->sae_pk_only && + if (ssid->sae_pk == SAE_PK_MODE_ONLY && !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK))) { if (debug_print) wpa_dbg(wpa_s, MSG_DEBUG, diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index fa18f9893..f45bab27a 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -150,12 +150,13 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, use_pt = 1; #ifdef CONFIG_SAE_PK if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) && + ssid->sae_pk != SAE_PK_MODE_DISABLED && ssid->sae_password && sae_pk_valid_password(ssid->sae_password)) { use_pt = 1; use_pk = true; } - if (ssid->sae_pk_only && !use_pk) { + if (ssid->sae_pk == SAE_PK_MODE_ONLY && !use_pk) { wpa_printf(MSG_DEBUG, "SAE: Cannot use PK with the selected AP"); return NULL; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index bf8a6dd5a..125083414 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1516,10 +1516,13 @@ fast_reauth=1 # bit 3 (0x08): Enhanced Open (disable use of open network; require # OWE) -# SAE-PK only mode (disable transition mode) -# 0: enable transition mode (allow SAE authentication without SAE-PK) -# 1: disable transition mode (allow SAE authentication only with SAE-PK) -#sae_pk_only=0 +# SAE-PK mode +# 0: automatic SAE/SAE-PK selection based on password; enable +# transition mode (allow SAE authentication without SAE-PK) +# 1: SAE-PK only (disable transition mode; allow SAE authentication +# only with SAE-PK) +# 2: disable SAE-PK (allow SAE authentication only without SAE-PK) +#sae_pk=0 # MAC address policy # 0 = use permanent MAC address diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index bafcb00e0..a9a66baad 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1301,13 +1301,13 @@ static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap) wpa_s->sme.sae.pk && #endif /* CONFIG_SME */ (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && - (!ssid->sae_pk_only || + (ssid->sae_pk != SAE_PK_MODE_ONLY || ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || (ssid->group_cipher & WPA_CIPHER_TKIP))) { wpa_printf(MSG_DEBUG, "SAE-PK: SAE authentication without PK disabled based on AP notification"); disable_wpa_wpa2(ssid); - ssid->sae_pk_only = 1; + ssid->sae_pk = SAE_PK_MODE_ONLY; changed = 1; } #endif /* CONFIG_SAE */ From 5ee94a997e582409f6d6c0a8694c855f5d63090f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 11:53:00 +0300 Subject: [PATCH 0631/1105] tests: Replace sae_pk_only with sae_pk to match implementation Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 33 ++++++++++++++++++++++++++++++--- tests/hwsim/wpasupplicant.py | 2 +- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 94a8a743e..3f7f0f461 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -156,7 +156,7 @@ def test_sae_pk_only(dev, apdev): params['sae_password'] = pw hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", sae_pk_only="1", + dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", sae_pk="1", scan_freq="2412", wait_connect=False) ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) @@ -181,6 +181,33 @@ def test_sae_pk_only(dev, apdev): if dev[0].get_status_field("sae_pk") != "1": raise Exception("SAE-PK was not used") +def test_sae_pk_modes(dev, apdev): + """SAE-PK modes""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + ssid = "SAE-PK test" + pw = "dwxm-zv66-p5ue" + m = "431ff8322f93b9dc50ded9f3d14ace22" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + hapd = hostapd.add_ap(apdev[0], params) + + tests = [(2, 0), (1, 1), (0, 1)] + for sae_pk, expected in tests: + dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", + sae_pk=str(sae_pk), ieee80211w="2", scan_freq="2412") + val = dev[0].get_status_field("sae_pk") + if val != str(expected): + raise Exception("Unexpected sae_pk=%d result %s" % (sae_pk, val)) + dev[0].request("REMOVE_NETWORK *") + dev[0].wait_disconnected() + dev[0].dump_monitor() + def test_sae_pk_transition_disable(dev, apdev): """SAE-PK transition disable indication""" check_sae_pk_capab(dev[0]) @@ -204,6 +231,6 @@ def test_sae_pk_transition_disable(dev, apdev): if ev.split(' ')[1] != "02": raise Exception("Unexpected transition disable bitmap: " + ev) - val = dev[0].get_network(id, "sae_pk_only") + val = dev[0].get_network(id, "sae_pk") if val != "1": - raise Exception("Unexpected sae_pk_only value: " + str(val)) + raise Exception("Unexpected sae_pk value: " + str(val)) diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 2c94162fa..88e64340a 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1102,7 +1102,7 @@ class WpaSupplicant: "dpp_netaccesskey", "dpp_netaccesskey_expiry", "dpp_pfs", "group_mgmt", "owe_group", "owe_only", "owe_ptk_workaround", - "transition_disable", "sae_pk_only", + "transition_disable", "sae_pk", "roaming_consortium_selection", "ocv", "multi_ap_backhaul_sta", "rx_stbc", "tx_stbc", "ft_eap_pmksa_caching", "beacon_prot", From f179475bf759506fe2bf8befec66228c94da43c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 12:01:52 +0300 Subject: [PATCH 0632/1105] tests: Share a single definition of SAE-PK Sec=2 values Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 89 +++++++++++++++----------------------- 1 file changed, 36 insertions(+), 53 deletions(-) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 3f7f0f461..ecf179842 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -7,6 +7,12 @@ import hostapd from utils import * +SAE_PK_SEC2_SSID = "SAE-PK test" +SAE_PK_SEC2_PW = "dwxm-zv66-p5ue" +SAE_PK_SEC2_PW_FULL = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-qleg" +SAE_PK_SEC2_M = "431ff8322f93b9dc50ded9f3d14ace22" +SAE_PK_SEC2_PK = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None): params = hostapd.wpa2_params(ssid=ssid) params['wpa_key_mgmt'] = 'SAE' @@ -35,29 +41,21 @@ def test_sae_pk(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - ssid = "SAE-PK test" - pw = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-qleg" - m = "431ff8322f93b9dc50ded9f3d14ace22" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - - for i in range(14, len(pw) + 1): - p = pw[:i] + for i in range(14, len(SAE_PK_SEC2_PW_FULL) + 1): + p = SAE_PK_SEC2_PW_FULL[:i] if p.endswith('-'): continue - run_sae_pk(apdev[0], dev[0], ssid, p, m, pk) + run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, p, SAE_PK_SEC2_M, + SAE_PK_SEC2_PK) def test_sae_pk_group_negotiation(dev, apdev): """SAE-PK""" check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "20 19") - ssid = "SAE-PK test" - pw = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-qleg" - m = "431ff8322f93b9dc50ded9f3d14ace22" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - try: - run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk, ap_groups="19 20") + run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_SEC2_PW, + SAE_PK_SEC2_M, SAE_PK_SEC2_PK, ap_groups="19 20") finally: dev[0].set("sae_groups", "") @@ -66,12 +64,8 @@ def test_sae_pk_sec_2(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - ssid = "SAE-PK test" - pw = "dwxm-zv66-p5ue" - m = "431ff8322f93b9dc50ded9f3d14ace22" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - - run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk) + run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_SEC2_PW, + SAE_PK_SEC2_M, SAE_PK_SEC2_PK) def test_sae_pk_sec_3(dev, apdev): """SAE-PK with Sec 3""" @@ -129,15 +123,13 @@ def test_sae_pk_password_without_pk(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - ssid = "SAE-PK test" - pw = "dwxm-zv66-p5ue" - - params = hostapd.wpa2_params(ssid=ssid) + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = pw + params['sae_password'] = SAE_PK_SEC2_PW hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", scan_freq="2412") + dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + key_mgmt="SAE", scan_freq="2412") if dev[0].get_status_field("sae_pk") != "0": raise Exception("Unexpected sae_pk STATUS value") @@ -146,17 +138,13 @@ def test_sae_pk_only(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - ssid = "SAE-PK test" - pw = "dwxm-zv66-p5ue" - m = "431ff8322f93b9dc50ded9f3d14ace22" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - - params = hostapd.wpa2_params(ssid=ssid) + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = pw + params['sae_password'] = SAE_PK_SEC2_PW hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", sae_pk="1", + dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + key_mgmt="SAE", sae_pk="1", scan_freq="2412", wait_connect=False) ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) @@ -167,9 +155,10 @@ def test_sae_pk_only(dev, apdev): dev[0].request("DISCONNECT") dev[0].dump_monitor() - params = hostapd.wpa2_params(ssid=ssid) + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + SAE_PK_SEC2_PK)] hapd2 = hostapd.add_ap(apdev[1], params) bssid2 = hapd2.own_addr() @@ -186,21 +175,18 @@ def test_sae_pk_modes(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - ssid = "SAE-PK test" - pw = "dwxm-zv66-p5ue" - m = "431ff8322f93b9dc50ded9f3d14ace22" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - - params = hostapd.wpa2_params(ssid=ssid) + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) params['wpa_key_mgmt'] = 'SAE' params["ieee80211w"] = "2" - params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + SAE_PK_SEC2_PK)] hapd = hostapd.add_ap(apdev[0], params) tests = [(2, 0), (1, 1), (0, 1)] for sae_pk, expected in tests: - dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", - sae_pk=str(sae_pk), ieee80211w="2", scan_freq="2412") + dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + key_mgmt="SAE", sae_pk=str(sae_pk), ieee80211w="2", + scan_freq="2412") val = dev[0].get_status_field("sae_pk") if val != str(expected): raise Exception("Unexpected sae_pk=%d result %s" % (sae_pk, val)) @@ -213,18 +199,15 @@ def test_sae_pk_transition_disable(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - ssid = "SAE-PK test" - pw = "dwxm-zv66-p5ue" - m = "431ff8322f93b9dc50ded9f3d14ace22" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - - params = hostapd.wpa2_params(ssid=ssid) + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + SAE_PK_SEC2_PK)] params['transition_disable'] = '0x02' hapd = hostapd.add_ap(apdev[0], params) - id = dev[0].connect(ssid, sae_password=pw, key_mgmt="SAE", scan_freq="2412") + id = dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + key_mgmt="SAE", scan_freq="2412") ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) if ev is None: raise Exception("Transition disable not indicated") From 0f2d5867e31d98a61dde7743f2a9470388efa047 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 12:04:14 +0300 Subject: [PATCH 0633/1105] tests: SAE-PK password, but no PK on AP Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index ecf179842..73dea23ff 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -194,6 +194,21 @@ def test_sae_pk_modes(dev, apdev): dev[0].wait_disconnected() dev[0].dump_monitor() +def test_sae_pk_not_on_ap(dev, apdev): + """SAE-PK password, but no PK on AP""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = SAE_PK_SEC2_PW + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + key_mgmt="SAE", scan_freq="2412") + if dev[0].get_status_field("sae_pk") == "1": + raise Exception("SAE-PK was claimed to be used") + def test_sae_pk_transition_disable(dev, apdev): """SAE-PK transition disable indication""" check_sae_pk_capab(dev[0]) From d654ca24de7752f00a2007a0abbe195787e833b9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 16:30:32 +0300 Subject: [PATCH 0634/1105] Clean up wpa_scan_res_match() Move the BSS-against-SSID matching into a separate helper function to make this overly long function a bit more readable and to allow that helper function to be used for other purposes. Signed-off-by: Jouni Malinen --- wpa_supplicant/events.c | 642 ++++++++++++++++++++-------------------- 1 file changed, 321 insertions(+), 321 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 99940d95c..cbe12967f 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1083,36 +1083,29 @@ static int disabled_freq(struct wpa_supplicant *wpa_s, int freq) } -struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, - int i, struct wpa_bss *bss, - struct wpa_ssid *group, - int only_first_ssid, int debug_print) +static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + const u8 *match_ssid, size_t match_ssid_len, + struct wpa_bss *bss, struct wpa_blacklist *e, + bool debug_print) { - u8 wpa_ie_len, rsn_ie_len; - int wpa; - struct wpa_blacklist *e; - const u8 *ie; - struct wpa_ssid *ssid; - int osen, rsn_osen = 0; -#ifdef CONFIG_SAE - u8 rsnxe_capa = 0; -#endif /* CONFIG_SAE */ + int res; + bool wpa, check_ssid, osen, rsn_osen = false; + struct wpa_ie_data data; #ifdef CONFIG_MBO const u8 *assoc_disallow; #endif /* CONFIG_MBO */ - const u8 *match_ssid; - size_t match_ssid_len; - struct wpa_ie_data data; +#ifdef CONFIG_SAE + u8 rsnxe_capa = 0; +#endif /* CONFIG_SAE */ + const u8 *ie; ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); - wpa_ie_len = ie ? ie[1] : 0; - + wpa = ie && ie[1]; ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); - rsn_ie_len = ie ? ie[1] : 0; + wpa |= ie && ie[1]; if (ie && wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) == 0 && (data.key_mgmt & WPA_KEY_MGMT_OSEN)) - rsn_osen = 1; - + rsn_osen = true; ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); osen = ie != NULL; @@ -1122,6 +1115,310 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, rsnxe_capa = ie[2]; #endif /* CONFIG_SAE */ + check_ssid = wpa || ssid->ssid_len > 0; + + if (wpas_network_disabled(wpa_s, ssid)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); + return false; + } + + res = wpas_temp_disabled(wpa_s, ssid); + if (res > 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - disabled temporarily for %d second(s)", + res); + return false; + } + +#ifdef CONFIG_WPS + if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - blacklisted (WPS)"); + return false; + } + + if (wpa && ssid->ssid_len == 0 && + wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) + check_ssid = false; + + if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { + /* Only allow wildcard SSID match if an AP advertises active + * WPS operation that matches our mode. */ + check_ssid = ssid->ssid_len > 0 || + !wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss); + } +#endif /* CONFIG_WPS */ + + if (ssid->bssid_set && ssid->ssid_len == 0 && + os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) + check_ssid = false; + + if (check_ssid && + (match_ssid_len != ssid->ssid_len || + os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch"); + return false; + } + + if (ssid->bssid_set && + os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch"); + return false; + } + + /* check blacklist */ + if (ssid->num_bssid_blacklist && + addr_in_list(bss->bssid, ssid->bssid_blacklist, + ssid->num_bssid_blacklist)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID blacklisted"); + return false; + } + + /* if there is a whitelist, only accept those APs */ + if (ssid->num_bssid_whitelist && + !addr_in_list(bss->bssid, ssid->bssid_whitelist, + ssid->num_bssid_whitelist)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID not in whitelist"); + return false; + } + + if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss, debug_print)) + return false; + + if (!osen && !wpa && + !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && + !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && + !(ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - non-WPA network not allowed"); + return false; + } + +#ifdef CONFIG_WEP + if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) && has_wep_key(ssid)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - ignore WPA/WPA2 AP for WEP network block"); + return false; + } +#endif /* CONFIG_WEP */ + + if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen && !rsn_osen) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - non-OSEN network not allowed"); + return false; + } + + if (!wpa_supplicant_match_privacy(bss, ssid)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy mismatch"); + return false; + } + + if (ssid->mode != WPAS_MODE_MESH && !bss_is_ess(bss) && + !bss_is_pbss(bss)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - not ESS, PBSS, or MBSS"); + return false; + } + + if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - PBSS mismatch (ssid %d bss %d)", + ssid->pbss, bss_is_pbss(bss)); + return false; + } + + if (!freq_allowed(ssid->freq_list, bss->freq)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - frequency not allowed"); + return false; + } + +#ifdef CONFIG_MESH + if (ssid->mode == WPAS_MODE_MESH && ssid->frequency > 0 && + ssid->frequency != bss->freq) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - frequency not allowed (mesh)"); + return false; + } +#endif /* CONFIG_MESH */ + + if (!rate_match(wpa_s, ssid, bss, debug_print)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - rate sets do not match"); + return false; + } + +#ifdef CONFIG_SAE + if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && + wpa_s->conf->sae_pwe != 3 && wpa_key_mgmt_sae(ssid->key_mgmt) && + !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - SAE H2E required, but not supported by the AP"); + return false; + } +#endif /* CONFIG_SAE */ + +#ifdef CONFIG_SAE_PK + if (ssid->sae_pk == SAE_PK_MODE_ONLY && + !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK))) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - SAE-PK required, but not supported by the AP"); + return false; + } +#endif /* CONFIG_SAE_PK */ + +#ifndef CONFIG_IBSS_RSN + if (ssid->mode == WPAS_MODE_IBSS && + !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - IBSS RSN not supported in the build"); + return false; + } +#endif /* !CONFIG_IBSS_RSN */ + +#ifdef CONFIG_P2P + if (ssid->p2p_group && + !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P IE seen"); + return false; + } + + if (!is_zero_ether_addr(ssid->go_p2p_dev_addr)) { + struct wpabuf *p2p_ie; + u8 dev_addr[ETH_ALEN]; + + ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); + if (!ie) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no P2P element"); + return false; + } + p2p_ie = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE); + if (!p2p_ie) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - could not fetch P2P element"); + return false; + } + + if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0 || + os_memcmp(dev_addr, ssid->go_p2p_dev_addr, ETH_ALEN) != 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no matching GO P2P Device Address in P2P element"); + wpabuf_free(p2p_ie); + return false; + } + wpabuf_free(p2p_ie); + } + + /* + * TODO: skip the AP if its P2P IE has Group Formation bit set in the + * P2P Group Capability Bitmap and we are not in Group Formation with + * that device. + */ +#endif /* CONFIG_P2P */ + + if (os_reltime_before(&bss->last_update, &wpa_s->scan_min_time)) { + struct os_reltime diff; + + os_reltime_sub(&wpa_s->scan_min_time, &bss->last_update, &diff); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - scan result not recent enough (%u.%06u seconds too old)", + (unsigned int) diff.sec, + (unsigned int) diff.usec); + return false; + } +#ifdef CONFIG_MBO +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->ignore_assoc_disallow) + goto skip_assoc_disallow; +#endif /* CONFIG_TESTING_OPTIONS */ + assoc_disallow = wpas_mbo_get_bss_attr(bss, MBO_ATTR_ID_ASSOC_DISALLOW); + if (assoc_disallow && assoc_disallow[1] >= 1) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - MBO association disallowed (reason %u)", + assoc_disallow[2]); + return false; + } + + if (wpa_is_bss_tmp_disallowed(wpa_s, bss)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - AP temporarily disallowed"); + return false; + } +#ifdef CONFIG_TESTING_OPTIONS +skip_assoc_disallow: +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_MBO */ + +#ifdef CONFIG_DPP + if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) && + !wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) && + (!ssid->dpp_connector || !ssid->dpp_netaccesskey || + !ssid->dpp_csign)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no PMKSA entry for DPP"); + return false; + } +#endif /* CONFIG_DPP */ + + /* Matching configuration found */ + return true; +} + + +struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, + int i, struct wpa_bss *bss, + struct wpa_ssid *group, + int only_first_ssid, int debug_print) +{ + u8 wpa_ie_len, rsn_ie_len; + struct wpa_blacklist *e; + const u8 *ie; + struct wpa_ssid *ssid; + int osen; + const u8 *match_ssid; + size_t match_ssid_len; + + ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); + wpa_ie_len = ie ? ie[1] : 0; + + ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); + rsn_ie_len = ie ? ie[1] : 0; + + ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); + osen = ie != NULL; + if (debug_print) { wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s", @@ -1189,307 +1486,10 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, return NULL; } - wpa = wpa_ie_len > 0 || rsn_ie_len > 0; - for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) { - int check_ssid = wpa ? 1 : (ssid->ssid_len != 0); - int res; - - if (wpas_network_disabled(wpa_s, ssid)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); - continue; - } - - res = wpas_temp_disabled(wpa_s, ssid); - if (res > 0) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - disabled temporarily for %d second(s)", - res); - continue; - } - -#ifdef CONFIG_WPS - if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - blacklisted (WPS)"); - continue; - } - - if (wpa && ssid->ssid_len == 0 && - wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) - check_ssid = 0; - - if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { - /* Only allow wildcard SSID match if an AP - * advertises active WPS operation that matches - * with our mode. */ - check_ssid = 1; - if (ssid->ssid_len == 0 && - wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) - check_ssid = 0; - } -#endif /* CONFIG_WPS */ - - if (ssid->bssid_set && ssid->ssid_len == 0 && - os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) - check_ssid = 0; - - if (check_ssid && - (match_ssid_len != ssid->ssid_len || - os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - SSID mismatch"); - continue; - } - - if (ssid->bssid_set && - os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - BSSID mismatch"); - continue; - } - - /* check blacklist */ - if (ssid->num_bssid_blacklist && - addr_in_list(bss->bssid, ssid->bssid_blacklist, - ssid->num_bssid_blacklist)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - BSSID blacklisted"); - continue; - } - - /* if there is a whitelist, only accept those APs */ - if (ssid->num_bssid_whitelist && - !addr_in_list(bss->bssid, ssid->bssid_whitelist, - ssid->num_bssid_whitelist)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - BSSID not in whitelist"); - continue; - } - - if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss, - debug_print)) - continue; - - if (!osen && !wpa && - !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && - !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && - !(ssid->key_mgmt & WPA_KEY_MGMT_OWE) && - !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - non-WPA network not allowed"); - continue; - } - -#ifdef CONFIG_WEP - if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) && - has_wep_key(ssid)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - ignore WPA/WPA2 AP for WEP network block"); - continue; - } -#endif /* CONFIG_WEP */ - - if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen && - !rsn_osen) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - non-OSEN network not allowed"); - continue; - } - - if (!wpa_supplicant_match_privacy(bss, ssid)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - privacy mismatch"); - continue; - } - - if (ssid->mode != WPAS_MODE_MESH && !bss_is_ess(bss) && - !bss_is_pbss(bss)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - not ESS, PBSS, or MBSS"); - continue; - } - - if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - PBSS mismatch (ssid %d bss %d)", - ssid->pbss, bss_is_pbss(bss)); - continue; - } - - if (!freq_allowed(ssid->freq_list, bss->freq)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - frequency not allowed"); - continue; - } - -#ifdef CONFIG_MESH - if (ssid->mode == WPAS_MODE_MESH && ssid->frequency > 0 && - ssid->frequency != bss->freq) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - frequency not allowed (mesh)"); - continue; - } -#endif /* CONFIG_MESH */ - - if (!rate_match(wpa_s, ssid, bss, debug_print)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - rate sets do not match"); - continue; - } - -#ifdef CONFIG_SAE - if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && - wpa_s->conf->sae_pwe != 3 && - wpa_key_mgmt_sae(ssid->key_mgmt) && - !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - SAE H2E required, but not supported by the AP"); - continue; - } -#endif /* CONFIG_SAE */ - -#ifdef CONFIG_SAE_PK - if (ssid->sae_pk == SAE_PK_MODE_ONLY && - !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK))) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - SAE-PK required, but not supported by the AP"); - continue; - } -#endif /* CONFIG_SAE_PK */ - -#ifndef CONFIG_IBSS_RSN - if (ssid->mode == WPAS_MODE_IBSS && - !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | - WPA_KEY_MGMT_WPA_NONE))) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - IBSS RSN not supported in the build"); - continue; - } -#endif /* !CONFIG_IBSS_RSN */ - -#ifdef CONFIG_P2P - if (ssid->p2p_group && - !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && - !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - no P2P IE seen"); - continue; - } - - if (!is_zero_ether_addr(ssid->go_p2p_dev_addr)) { - struct wpabuf *p2p_ie; - u8 dev_addr[ETH_ALEN]; - - ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); - if (ie == NULL) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - no P2P element"); - continue; - } - p2p_ie = wpa_bss_get_vendor_ie_multi( - bss, P2P_IE_VENDOR_TYPE); - if (p2p_ie == NULL) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - could not fetch P2P element"); - continue; - } - - if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0 - || os_memcmp(dev_addr, ssid->go_p2p_dev_addr, - ETH_ALEN) != 0) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - no matching GO P2P Device Address in P2P element"); - wpabuf_free(p2p_ie); - continue; - } - wpabuf_free(p2p_ie); - } - - /* - * TODO: skip the AP if its P2P IE has Group Formation - * bit set in the P2P Group Capability Bitmap and we - * are not in Group Formation with that device. - */ -#endif /* CONFIG_P2P */ - - if (os_reltime_before(&bss->last_update, &wpa_s->scan_min_time)) - { - struct os_reltime diff; - - os_reltime_sub(&wpa_s->scan_min_time, - &bss->last_update, &diff); - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - scan result not recent enough (%u.%06u seconds too old)", - (unsigned int) diff.sec, - (unsigned int) diff.usec); - continue; - } -#ifdef CONFIG_MBO -#ifdef CONFIG_TESTING_OPTIONS - if (wpa_s->ignore_assoc_disallow) - goto skip_assoc_disallow; -#endif /* CONFIG_TESTING_OPTIONS */ - assoc_disallow = wpas_mbo_get_bss_attr( - bss, MBO_ATTR_ID_ASSOC_DISALLOW); - if (assoc_disallow && assoc_disallow[1] >= 1) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - MBO association disallowed (reason %u)", - assoc_disallow[2]); - continue; - } - - if (wpa_is_bss_tmp_disallowed(wpa_s, bss)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - AP temporarily disallowed"); - continue; - } -#ifdef CONFIG_TESTING_OPTIONS - skip_assoc_disallow: -#endif /* CONFIG_TESTING_OPTIONS */ -#endif /* CONFIG_MBO */ - -#ifdef CONFIG_DPP - if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) && - !wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) && - (!ssid->dpp_connector || - !ssid->dpp_netaccesskey || - !ssid->dpp_csign)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - no PMKSA entry for DPP"); - continue; - } -#endif /* CONFIG_DPP */ - - /* Matching configuration found */ - return ssid; + if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len, + bss, e, debug_print)) + return ssid; } /* No matching configuration found */ From 5f48d36b4a107984314dc60953f213febe2ecd69 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 16:49:07 +0300 Subject: [PATCH 0635/1105] SAE-PK: Select SAE-PK network over SAE without PK If there is an acceptable BSS with SAE-PK enabled in the same ESS, select that over a BSS that does not enable SAE-PK when the network profile uses automatic SAE-PK selection. Signed-off-by: Jouni Malinen --- wpa_supplicant/events.c | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index cbe12967f..86eef1b81 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1083,6 +1083,51 @@ static int disabled_freq(struct wpa_supplicant *wpa_s, int freq) } +static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + const u8 *match_ssid, size_t match_ssid_len, + struct wpa_bss *bss, struct wpa_blacklist *e, + bool debug_print); + + +#ifdef CONFIG_SAE_PK +static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s, + struct wpa_bss *orig_bss, + struct wpa_ssid *ssid, + const u8 *match_ssid, + size_t match_ssid_len) +{ + struct wpa_bss *bss; + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + struct wpa_blacklist *e; + const u8 *ie; + u8 rsnxe_capa = 0; + + if (bss == orig_bss) + continue; + ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (ie && ie[1] >= 1) + rsnxe_capa = ie[2]; + if (!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK))) + continue; + + /* TODO: Could be more thorough in checking what kind of + * signal strength or throughput estimate would be acceptable + * compared to the originally selected BSS. */ + if (bss->est_throughput < 2000) + return false; + + e = wpa_blacklist_get(wpa_s, bss->bssid); + if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len, + bss, e, 0)) + return true; + } + + return false; +} +#endif /* CONFIG_SAE_PK */ + + static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, const u8 *match_ssid, size_t match_ssid_len, struct wpa_bss *bss, struct wpa_blacklist *e, @@ -1392,6 +1437,20 @@ skip_assoc_disallow: } #endif /* CONFIG_DPP */ +#ifdef CONFIG_SAE_PK + if (ssid->sae_pk == SAE_PK_MODE_AUTOMATIC && + wpa_key_mgmt_sae(ssid->key_mgmt) && + ssid->sae_password && sae_pk_valid_password(ssid->sae_password) && + !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) && + sae_pk_acceptable_bss_with_pk(wpa_s, bss, ssid, match_ssid, + match_ssid_len)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - another acceptable BSS with SAE-PK in the same ESS"); + return false; + } +#endif /* CONFIG_SAE_PK */ + /* Matching configuration found */ return true; } From 6d72833236689cde7061f5f10ef318d69368f3b1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 16:50:09 +0300 Subject: [PATCH 0636/1105] tests: SAE-PK mixed deployment Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 73dea23ff..14bfe42f4 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -232,3 +232,35 @@ def test_sae_pk_transition_disable(dev, apdev): val = dev[0].get_network(id, "sae_pk") if val != "1": raise Exception("Unexpected sae_pk value: " + str(val)) + +def test_sae_pk_mixed(dev, apdev): + """SAE-PK mixed deployment""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = SAE_PK_SEC2_PW + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + SAE_PK_SEC2_PK)] + # Disable HT from the SAE-PK BSS to make the station prefer the other BSS + # by default. + params['ieee80211n'] = '0' + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].scan_for_bss(bssid2, freq=2412) + + dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + key_mgmt="SAE", scan_freq="2412") + + if dev[0].get_status_field("sae_pk") != "1": + raise Exception("SAE-PK was not used") + if dev[0].get_status_field("bssid") != bssid2: + raise Exception("Unexpected BSSID selected") From 0c4ffce46488b591f39be2fc1b684d34a77e1c52 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 17:06:52 +0300 Subject: [PATCH 0637/1105] Allow transition_disable updates during the lifetime of a BSS This is mainly for testing purposes to allow more convenient checking of station behavior when a transition mode is disabled. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 3 +++ src/ap/wpa_auth.c | 8 ++++++++ src/ap/wpa_auth.h | 2 ++ 3 files changed, 13 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 8a79ef783..b470c5643 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1478,6 +1478,9 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) os_strcmp(cmd, "sae_pwe") == 0) { if (hapd->started) hostapd_setup_sae_pt(hapd->conf); + } else if (os_strcasecmp(cmd, "transition_disable") == 0) { + wpa_auth_set_transition_disable(hapd->wpa_auth, + hapd->conf->transition_disable); } #ifdef CONFIG_TESTING_OPTIONS diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 0efa28797..9e6c0cad3 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -5288,6 +5288,14 @@ void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z) #endif /* CONFIG_DPP2 */ +void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth, + u8 val) +{ + if (wpa_auth) + wpa_auth->conf.transition_disable = val; +} + + #ifdef CONFIG_TESTING_OPTIONS int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce, diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 59794a7f9..5f9df9c89 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -517,6 +517,8 @@ u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm, const u8 *req_ies, size_t req_ies_len); void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg); void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z); +void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth, + u8 val); int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce, void (*cb)(void *ctx1, void *ctx2), From 3a6e674adfba7650f369f9fb6bee1aa06aef7733 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 7 Jun 2020 17:07:57 +0300 Subject: [PATCH 0638/1105] tests: sigma_dut controlled AP and transition disabled indication change Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index c9e7c34c8..11e31fdcb 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4482,6 +4482,40 @@ def test_sigma_dut_ap_transition_disable(dev, apdev, params): finally: stop_sigma_dut(sigma) +def test_sigma_dut_ap_transition_disable_change(dev, apdev, params): + """sigma_dut controlled AP and transition disabled indication change""" + logdir = params['prefix'] + ".sigma-hostapd" + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678,PMF,Required") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is not None: + raise Exception("Unexpected transition disable indication") + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + sigma_dut_cmd_check("ap_set_rfeature,NAME,AP,Transition_Disable,1,Transition_Disable_Index,0") + dev[0].request("RECONNECT") + dev[0].wait_connected() + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "01": + raise Exception("Unexpected transition disable bitmap: " + ev) + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + def test_sigma_dut_ft_rsnxe_used_mismatch(dev, apdev): """sigma_dut controlled FT protocol with RSNXE Used mismatch""" if "SAE" not in dev[0].get_capability("auth_alg"): From 4ff0df39eb0eb1623ce496ae9b5706c8599e8bc4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 14:00:28 +0300 Subject: [PATCH 0639/1105] SAE-PK: Testing functionality to allow behavior overrides The new sae_commit_status and sae_pk_omit configuration parameters and an extra key at the end of sae_password pk argument can be used to override SAE-PK behavior for testing purposes. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 4 ++++ src/ap/ap_config.c | 4 ++++ src/ap/ap_config.h | 2 ++ src/ap/ieee802_11.c | 16 +++++++++++++++ src/common/sae.h | 6 ++++++ src/common/sae_pk.c | 47 ++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 76 insertions(+), 3 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 49894c5ba..dac0e8054 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4231,6 +4231,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->own_ie_override = tmp; } else if (os_strcmp(buf, "sae_reflection_attack") == 0) { bss->sae_reflection_attack = atoi(pos); + } else if (os_strcmp(buf, "sae_commit_status") == 0) { + bss->sae_commit_status = atoi(pos); + } else if (os_strcmp(buf, "sae_pk_omit") == 0) { + bss->sae_pk_omit = atoi(pos); } else if (os_strcmp(buf, "sae_commit_override") == 0) { wpabuf_free(bss->sae_commit_override); bss->sae_commit_override = wpabuf_parse_bin(pos); diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index a4e1bbb3d..1c6b4a00e 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -160,6 +160,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) /* Default to strict CRL checking. */ bss->check_crl_strict = 1; + +#ifdef CONFIG_TESTING_OPTIONS + bss->sae_commit_status = -1; +#endif /* CONFIG_TESTING_OPTIONS */ } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index cafc44edd..4c2e60095 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -678,6 +678,8 @@ struct hostapd_bss_config { u8 bss_load_test_set; struct wpabuf *own_ie_override; int sae_reflection_attack; + int sae_commit_status; + int sae_pk_omit; struct wpabuf *sae_commit_override; struct wpabuf *rsne_override_eapol; struct wpabuf *rsnxe_override_eapol; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index eca8b19ad..8b994d6a5 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -567,6 +567,13 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd, if (buf == NULL) return NULL; +#ifdef CONFIG_SAE_PK +#ifdef CONFIG_TESTING_OPTIONS + if (sta->sae->tmp) + sta->sae->tmp->omit_pk_elem = hapd->conf->sae_pk_omit; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_SAE_PK */ + if (sae_write_confirm(sta->sae, buf) < 0) { wpabuf_free(buf); return NULL; @@ -600,6 +607,15 @@ static int auth_sae_send_commit(struct hostapd_data *hapd, status = WLAN_STATUS_SAE_HASH_TO_ELEMENT; else status = WLAN_STATUS_SUCCESS; +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->sae_commit_status >= 0 && + hapd->conf->sae_commit_status != status) { + wpa_printf(MSG_INFO, + "TESTING: Override SAE commit status code %u --> %d", + status, hapd->conf->sae_commit_status); + status = hapd->conf->sae_commit_status; + } +#endif /* CONFIG_TESTING_OPTIONS */ reply_res = send_auth_reply(hapd, sta, sta->addr, bssid, WLAN_AUTH_SAE, 1, status, wpabuf_head(data), diff --git a/src/common/sae.h b/src/common/sae.h index 887cd4e9a..261935fdb 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -31,6 +31,9 @@ struct sae_pk { struct crypto_ec_key *key; int group; struct wpabuf *pubkey; /* DER encoded subjectPublicKey */ +#ifdef CONFIG_TESTING_OPTIONS + struct crypto_ec_key *sign_key_override; +#endif /* CONFIG_TESTING_OPTIONS */ }; @@ -73,6 +76,9 @@ struct sae_temporary_data { u8 ssid[32]; size_t ssid_len; bool reject_group; +#ifdef CONFIG_TESTING_OPTIONS + bool omit_pk_elem; +#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_SAE_PK */ }; diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index 806498c38..bb9c979a1 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -203,6 +203,9 @@ void sae_deinit_pk(struct sae_pk *pk) if (pk) { wpabuf_free(pk->m); crypto_ec_key_deinit(pk->key); +#ifdef CONFIG_TESTING_OPTIONS + crypto_ec_key_deinit(pk->sign_key_override); +#endif /* CONFIG_TESTING_OPTIONS */ wpabuf_free(pk->pubkey); os_free(pk); } @@ -213,9 +216,12 @@ struct sae_pk * sae_parse_pk(const char *val) { struct sae_pk *pk; const char *pos; +#ifdef CONFIG_TESTING_OPTIONS + const char *pos2; +#endif /* CONFIG_TESTING_OPTIONS */ size_t len; unsigned char *der; - size_t der_len; + size_t der_len, b_len; /* : */ @@ -239,7 +245,15 @@ struct sae_pk * sae_parse_pk(const char *val) } pos++; - der = base64_decode(pos, os_strlen(pos), &der_len); + b_len = os_strlen(pos); +#ifdef CONFIG_TESTING_OPTIONS + pos2 = os_strchr(pos, ':'); + if (pos2) { + b_len = pos2 - pos; + pos2++; + } +#endif /* CONFIG_TESTING_OPTIONS */ + der = base64_decode(pos, b_len, &der_len); if (!der) { wpa_printf(MSG_INFO, "SAE: Failed to base64 decode PK key"); goto fail; @@ -254,6 +268,22 @@ struct sae_pk * sae_parse_pk(const char *val) if (!pk->pubkey) goto fail; +#ifdef CONFIG_TESTING_OPTIONS + if (pos2) { + der = base64_decode(pos2, os_strlen(pos2), &der_len); + if (!der) { + wpa_printf(MSG_INFO, + "SAE: Failed to base64 decode PK key"); + goto fail; + } + + pk->sign_key_override = crypto_ec_key_parse_priv(der, der_len); + bin_clear_free(der, der_len); + if (!pk->sign_key_override) + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + return pk; fail: sae_deinit_pk(pk); @@ -342,6 +372,7 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) const struct sae_pk *pk; u8 hash[SAE_MAX_HASH_LEN]; size_t hash_len; + struct crypto_ec_key *key; if (!tmp) return -1; @@ -350,6 +381,16 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) if (!pk) return 0; + key = pk->key; +#ifdef CONFIG_TESTING_OPTIONS + if (tmp->omit_pk_elem) + return 0; + if (pk->sign_key_override) { + wpa_printf(MSG_INFO, "TESTING: Override SAE-PK signing key"); + key = pk->sign_key_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { wpa_printf(MSG_INFO, "SAE-PK: No KEK available for confirm"); return -1; @@ -368,7 +409,7 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) wpabuf_len(pk->m), wpabuf_head(pk->pubkey), wpabuf_len(pk->pubkey), hash) < 0) goto fail; - sig = crypto_ec_key_sign(pk->key, hash, hash_len); + sig = crypto_ec_key_sign(key, hash, hash_len); if (!sig) goto fail; wpa_hexdump_buf(MSG_DEBUG, "SAE-PK: KeyAuth = Sig_AP()", sig); From 232705e3c4b62ee5b8b1c4c2e49c764aa96f634a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 14:13:14 +0300 Subject: [PATCH 0640/1105] tests: SAE-PK AP misbehavior Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 62 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 14bfe42f4..cb9a7822c 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -264,3 +264,65 @@ def test_sae_pk_mixed(dev, apdev): raise Exception("SAE-PK was not used") if dev[0].get_status_field("bssid") != bssid2: raise Exception("Unexpected BSSID selected") + +def check_sae_pk_sta_connect_failure(dev): + dev.connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + key_mgmt="SAE", scan_freq="2412", wait_connect=False) + ev = dev.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) + if ev is None: + raise Exception("No result for the connection attempt") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + +def test_sae_pk_missing_ie(dev, apdev): + """SAE-PK and missing SAE-PK IE in confirm""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + SAE_PK_SEC2_PK)] + params['sae_pk_omit'] = '1' + hapd = hostapd.add_ap(apdev[0], params) + check_sae_pk_sta_connect_failure(dev[0]) + +def test_sae_pk_unexpected_status(dev, apdev): + """SAE-PK and unexpected status code in commit""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + SAE_PK_SEC2_PK)] + params['sae_commit_status'] = '126' + hapd = hostapd.add_ap(apdev[0], params) + check_sae_pk_sta_connect_failure(dev[0]) + +def test_sae_pk_invalid_signature(dev, apdev): + """SAE-PK and invalid signature""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + other = "MHcCAQEEILw+nTjFzRyhVea0G6KbwZu18oWrfhzppxj+MceUO3YLoAoGCCqGSM49AwEHoUQDQgAELdou6LuTDNiMVlMB65KsWhQFbPXR9url0EA6luWzUfAuGoDXYJUBTVz6Nv3mz6oQcDrSiDmz/LejndJ0YHGgfQ==" + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + SAE_PK_SEC2_PK, other)] + hapd = hostapd.add_ap(apdev[0], params) + check_sae_pk_sta_connect_failure(dev[0]) + +def test_sae_pk_invalid_fingerprint(dev, apdev): + """SAE-PK and invalid fingerprint""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + other = "431ff8322f93b9dc50ded9f3d14ace21" + params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, other, + SAE_PK_SEC2_PK)] + hapd = hostapd.add_ap(apdev[0], params) + check_sae_pk_sta_connect_failure(dev[0]) From 43a191b89095e28874f436a5af04afa48a5d784f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 17:09:56 +0300 Subject: [PATCH 0641/1105] tests: Remove too short SAE-PK passwords This is in preparation of implementation changes to check SAE-PK password length more accurately based on the Sec value. Signed-off-by: Jouni Malinen --- src/common/common_module_tests.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c index 8a7d9fe25..b6e714f68 100644 --- a/src/common/common_module_tests.c +++ b/src/common/common_module_tests.c @@ -563,9 +563,6 @@ static int sae_pk_tests(void) { "aaaa-aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00" }, { "aaaa-aaaa-aa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00" }, { "aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00" }, - { "7777-7777", (u8 *) "\xff\xff\xff\xff\xff" }, - { "7777-7777-7", (u8 *) "\xff\xff\xff\xff\xff\xf8" }, - { "7777-7777-77", (u8 *) "\xff\xff\xff\xff\xff\xff\xc0" }, { "7777-7777-777", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe" }, { "7777-7777-7777", (u8 *) "\xff\xff\xff\xff\xff\xff\xff\xf0" }, { "7777-7777-7777-7", From 4c3fbb23460efb30f9028f2190c5d7b22e9cee5d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 14:49:31 +0300 Subject: [PATCH 0642/1105] SAE-PK: Check minimum password length more accurate Get the Sec value from the password to check the minimum length based on the used Sec. Signed-off-by: Jouni Malinen --- src/common/sae_pk.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index bb9c979a1..60979aab3 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -25,14 +25,25 @@ static const char *sae_pk_base32_table = "abcdefghijklmnopqrstuvwxyz234567"; bool sae_pk_valid_password(const char *pw) { - int pos; + int pos, sec; + const char *idx; + size_t pw_len = os_strlen(pw); - if (os_strlen(pw) < 9) { - /* Not long enough to meet the minimum required resistance to - * preimage attacks, so do not consider this valid for SAE-PK. - */ + /* Check whether the password is long enough to meet the minimum + * required resistance to preimage attacks. This makes it less likely to + * recognize non-SAE-PK passwords as suitable for SAE-PK. */ + if (pw_len < 1) return false; - } + /* Fetch Sec from the two MSBs */ + idx = os_strchr(sae_pk_base32_table, pw[0]); + if (!idx) + return false; + sec = ((u8) ((idx - sae_pk_base32_table) & 0x1f)) >> 3; + if ((sec == 2 && pw_len < 14) || + (sec == 3 && pw_len < 13) || + (sec == 4 && pw_len < 11) || + (sec == 5 && pw_len < 9)) + return false; /* too short password */ for (pos = 0; pw[pos]; pos++) { if (pos && pos % 5 == 4) { From e30dcda3b18384629a3535a746c16b8d7ae631d0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 14:59:49 +0300 Subject: [PATCH 0643/1105] SAE-PK: Fix FILS Public Key element Key Type for ECDSA Use value 2 to point to RFC 5480 which describes the explicit indicatiotion of the public key being in compressed form. Signed-off-by: Jouni Malinen --- src/common/sae_pk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index 60979aab3..9e02611f7 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -444,7 +444,7 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) wpabuf_put_u8(elem, WLAN_EID_EXTENSION); wpabuf_put_u8(elem, 2 + wpabuf_len(pk->pubkey)); wpabuf_put_u8(elem, WLAN_EID_EXT_FILS_PUBLIC_KEY); - wpabuf_put_u8(elem, 3); /* Key Type: ECDSA public key */ + wpabuf_put_u8(elem, 2); /* Key Type: ECDSA public key */ wpabuf_put_buf(elem, pk->pubkey); /* FILS Key Confirmation element (KeyAuth) */ @@ -629,7 +629,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) "SAE-PK: No FILS Public Key element in SAE-PK element"); return -1; } - if (pos[3] != 3) { + if (pos[3] != 2) { wpa_printf(MSG_INFO, "SAE-PK: Unsupported public key type %u", pos[3]); return -1; From 5b78c8f961f25f4dc22d6f2b77ddd06d712cec63 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 3 Jun 2020 23:17:35 +0300 Subject: [PATCH 0644/1105] WPS UPnP: Do not allow event subscriptions with URLs to other networks The UPnP Device Architecture 2.0 specification errata ("UDA errata 16-04-2020.docx") addresses a problem with notifications being allowed to go out to other domains by disallowing such cases. Do such filtering for the notification callback URLs to avoid undesired connections to external networks based on subscriptions that any device in the local network could request when WPS support for external registrars is enabled (the upnp_iface parameter in hostapd configuration). Signed-off-by: Jouni Malinen --- src/wps/wps_er.c | 2 +- src/wps/wps_upnp.c | 38 ++++++++++++++++++++++++++++++++++++-- src/wps/wps_upnp_i.h | 3 ++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index 6bded1432..31d2e50e4 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -1298,7 +1298,7 @@ wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) "with %s", filter); } if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, - er->mac_addr)) { + NULL, er->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", er->ifname); wps_er_deinit(er, NULL, NULL); diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index 6e10e4bc0..7d4b74399 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -303,6 +303,14 @@ static void subscr_addr_free_all(struct subscription *s) } +static int local_network_addr(struct upnp_wps_device_sm *sm, + struct sockaddr_in *addr) +{ + return (addr->sin_addr.s_addr & sm->netmask.s_addr) == + (sm->ip_addr & sm->netmask.s_addr); +} + + /* subscr_addr_add_url -- add address(es) for one url to subscription */ static void subscr_addr_add_url(struct subscription *s, const char *url, size_t url_len) @@ -381,6 +389,7 @@ static void subscr_addr_add_url(struct subscription *s, const char *url, for (rp = result; rp; rp = rp->ai_next) { struct subscr_addr *a; + struct sockaddr_in *addr = (struct sockaddr_in *) rp->ai_addr; /* Limit no. of address to avoid denial of service attack */ if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) { @@ -389,6 +398,13 @@ static void subscr_addr_add_url(struct subscription *s, const char *url, break; } + if (!local_network_addr(s->sm, addr)) { + wpa_printf(MSG_INFO, + "WPS UPnP: Ignore a delivery URL that points to another network %s", + inet_ntoa(addr->sin_addr)); + continue; + } + a = os_zalloc(sizeof(*a) + alloc_len); if (a == NULL) break; @@ -890,11 +906,12 @@ static int eth_get(const char *device, u8 ea[ETH_ALEN]) * @net_if: Selected network interface name * @ip_addr: Buffer for returning IP address in network byte order * @ip_addr_text: Buffer for returning a pointer to allocated IP address text + * @netmask: Buffer for returning netmask or %NULL if not needed * @mac: Buffer for returning MAC address * Returns: 0 on success, -1 on failure */ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, - u8 mac[ETH_ALEN]) + struct in_addr *netmask, u8 mac[ETH_ALEN]) { struct ifreq req; int sock = -1; @@ -920,6 +937,19 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, in_addr.s_addr = *ip_addr; os_snprintf(*ip_addr_text, 16, "%s", inet_ntoa(in_addr)); + if (netmask) { + os_memset(&req, 0, sizeof(req)); + os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); + if (ioctl(sock, SIOCGIFNETMASK, &req) < 0) { + wpa_printf(MSG_ERROR, + "WPS UPnP: SIOCGIFNETMASK failed: %d (%s)", + errno, strerror(errno)); + goto fail; + } + addr = (struct sockaddr_in *) &req.ifr_netmask; + netmask->s_addr = addr->sin_addr.s_addr; + } + #ifdef __linux__ os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); if (ioctl(sock, SIOCGIFHWADDR, &req) < 0) { @@ -1026,11 +1056,15 @@ static int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if) /* Determine which IP and mac address we're using */ if (get_netif_info(net_if, &sm->ip_addr, &sm->ip_addr_text, - sm->mac_addr)) { + &sm->netmask, sm->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", net_if); goto fail; } + wpa_printf(MSG_DEBUG, "WPS UPnP: Local IP address %s netmask %s hwaddr " + MACSTR, + sm->ip_addr_text, inet_ntoa(sm->netmask), + MAC2STR(sm->mac_addr)); /* Listen for incoming TCP connections so that others * can fetch our "xml files" from us. diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h index e87a93232..6ead7b4e9 100644 --- a/src/wps/wps_upnp_i.h +++ b/src/wps/wps_upnp_i.h @@ -128,6 +128,7 @@ struct upnp_wps_device_sm { u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */ char *ip_addr_text; /* IP address of network i.f. we use */ unsigned ip_addr; /* IP address of network i.f. we use (host order) */ + struct in_addr netmask; int multicast_sd; /* send multicast messages over this socket */ int ssdp_sd; /* receive discovery UPD packets on socket */ int ssdp_sd_registered; /* nonzero if we must unregister */ @@ -158,7 +159,7 @@ struct subscription * subscription_find(struct upnp_wps_device_sm *sm, const u8 uuid[UUID_LEN]); void subscr_addr_delete(struct subscr_addr *a); int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, - u8 mac[ETH_ALEN]); + struct in_addr *netmask, u8 mac[ETH_ALEN]); /* wps_upnp_ssdp.c */ void msearchreply_state_machine_stop(struct advertisement_state_machine *a); From f7d268864a2660b7239b9a8ff5ad37faeeb751ba Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 3 Jun 2020 22:41:02 +0300 Subject: [PATCH 0645/1105] WPS UPnP: Fix event message generation using a long URL path More than about 700 character URL ended up overflowing the wpabuf used for building the event notification and this resulted in the wpabuf buffer overflow checks terminating the hostapd process. Fix this by allocating the buffer to be large enough to contain the full URL path. However, since that around 700 character limit has been the practical limit for more than ten years, start explicitly enforcing that as the limit or the callback URLs since any longer ones had not worked before and there is no need to enable them now either. Signed-off-by: Jouni Malinen --- src/wps/wps_upnp.c | 9 +++++++-- src/wps/wps_upnp_event.c | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index 7d4b74399..ab685d52e 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -328,9 +328,14 @@ static void subscr_addr_add_url(struct subscription *s, const char *url, int rerr; size_t host_len, path_len; - /* url MUST begin with http: */ - if (url_len < 7 || os_strncasecmp(url, "http://", 7)) + /* URL MUST begin with HTTP scheme. In addition, limit the length of + * the URL to 700 characters which is around the limit that was + * implicitly enforced for more than 10 years due to a bug in + * generating the event messages. */ + if (url_len < 7 || os_strncasecmp(url, "http://", 7) || url_len > 700) { + wpa_printf(MSG_DEBUG, "WPS UPnP: Reject an unacceptable URL"); goto fail; + } url += 7; url_len -= 7; diff --git a/src/wps/wps_upnp_event.c b/src/wps/wps_upnp_event.c index d7e6edcc6..08a23612f 100644 --- a/src/wps/wps_upnp_event.c +++ b/src/wps/wps_upnp_event.c @@ -147,7 +147,8 @@ static struct wpabuf * event_build_message(struct wps_event_ *e) struct wpabuf *buf; char *b; - buf = wpabuf_alloc(1000 + wpabuf_len(e->data)); + buf = wpabuf_alloc(1000 + os_strlen(e->addr->path) + + wpabuf_len(e->data)); if (buf == NULL) return NULL; wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path); From 85aac526af8612c21b3117dadc8ef5944985b476 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 4 Jun 2020 21:24:04 +0300 Subject: [PATCH 0646/1105] WPS UPnP: Handle HTTP initiation failures for events more properly While it is appropriate to try to retransmit the event to another callback URL on a failure to initiate the HTTP client connection, there is no point in trying the exact same operation multiple times in a row. Replve the event_retry() calls with event_addr_failure() for these cases to avoid busy loops trying to repeat the same failing operation. These potential busy loops would go through eloop callbacks, so the process is not completely stuck on handling them, but unnecessary CPU would be used to process the continues retries that will keep failing for the same reason. Signed-off-by: Jouni Malinen --- src/wps/wps_upnp_event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wps/wps_upnp_event.c b/src/wps/wps_upnp_event.c index 08a23612f..c0d9e41d9 100644 --- a/src/wps/wps_upnp_event.c +++ b/src/wps/wps_upnp_event.c @@ -294,7 +294,7 @@ static int event_send_start(struct subscription *s) buf = event_build_message(e); if (buf == NULL) { - event_retry(e, 0); + event_addr_failure(e); return -1; } @@ -302,7 +302,7 @@ static int event_send_start(struct subscription *s) event_http_cb, e); if (e->http_event == NULL) { wpabuf_free(buf); - event_retry(e, 0); + event_addr_failure(e); return -1; } From 5a8b366233f5585e68a4ffbb604fbb4a848eb325 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 17:48:57 +0300 Subject: [PATCH 0647/1105] tests: Make SAE-PK test cases more robust Clear scan results explicitly in test cases that check BSS entry flags to avoid incorrect failures based on results from earlier test cases. Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index cb9a7822c..e7574a155 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -39,6 +39,7 @@ def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None): def test_sae_pk(dev, apdev): """SAE-PK""" check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() dev[0].set("sae_groups", "") for i in range(14, len(SAE_PK_SEC2_PW_FULL) + 1): @@ -51,6 +52,7 @@ def test_sae_pk(dev, apdev): def test_sae_pk_group_negotiation(dev, apdev): """SAE-PK""" check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() dev[0].set("sae_groups", "20 19") try: @@ -62,6 +64,7 @@ def test_sae_pk_group_negotiation(dev, apdev): def test_sae_pk_sec_2(dev, apdev): """SAE-PK with Sec 2""" check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() dev[0].set("sae_groups", "") run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_SEC2_PW, @@ -70,6 +73,7 @@ def test_sae_pk_sec_2(dev, apdev): def test_sae_pk_sec_3(dev, apdev): """SAE-PK with Sec 3""" check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() dev[0].set("sae_groups", "") ssid = "SAE-PK test" @@ -82,6 +86,7 @@ def test_sae_pk_sec_3(dev, apdev): def test_sae_pk_sec_4(dev, apdev): """SAE-PK with Sec 4""" check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() dev[0].set("sae_groups", "") ssid = "SAE-PK test" @@ -94,6 +99,7 @@ def test_sae_pk_sec_4(dev, apdev): def test_sae_pk_sec_5(dev, apdev): """SAE-PK with Sec 5""" check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() dev[0].set("sae_groups", "") ssid = "SAE-PK test" @@ -106,6 +112,7 @@ def test_sae_pk_sec_5(dev, apdev): def test_sae_pk_group_20(dev, apdev): """SAE-PK with group 20""" check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() dev[0].set("sae_groups", "20") ssid = "SAE-PK test" From 9a0807ce36fbc4d3fe4e75b7870518e7902a1b13 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 19:17:53 +0300 Subject: [PATCH 0648/1105] tests: sigma_dut controlled AP using SAE-PK misbehavior Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 39 +++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 11e31fdcb..03caaa4fc 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4806,10 +4806,20 @@ def test_sigma_dut_sae_pk(dev, apdev): finally: stop_sigma_dut(sigma) -def run_sigma_dut_ap_sae_pk(conffile, dev, ssid, pw, keypair, m, failure): +def run_sigma_dut_ap_sae_pk(conffile, dev, ssid, pw, keypair, m, failure, + status=None, omit=False, immediate=False, sig=None): sigma_dut_cmd_check("ap_reset_default") sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,%s,MODE,11ng" % ssid) - sigma_dut_cmd_check("ap_set_security,NAME,AP,AKMSuiteType,8,PairwiseCipher,AES-CCMP-128,GroupCipher,AES-CCMP-128,GroupMgntCipher,BIP-CMAC-128,PMF,Required,PSK,%s,sae_pk,1,Transition_Disable,1,Transition_Disable_Index,0,SAE_PK_KeyPair,%s,SAE_PK_Modifier,%s" % (pw, keypair, m)) + cmd = "ap_set_security,NAME,AP,AKMSuiteType,8,PairwiseCipher,AES-CCMP-128,GroupCipher,AES-CCMP-128,GroupMgntCipher,BIP-CMAC-128,PMF,Required,PSK,%s,sae_pk,1,Transition_Disable,1,Transition_Disable_Index,0,SAE_PK_KeyPair,%s,SAE_PK_Modifier,%s" % (pw, keypair, m) + if status is not None: + cmd += ",SAE_Commit_StatusCode,%d" % status + if omit: + cmd += ",SAE_PK_Omit,1" + if immediate: + cmd += ",SAE_Confirm_Immediate,1" + if sig: + cmd += ",SAE_PK_KeyPairSigOverride," + sig + sigma_dut_cmd_check(cmd) sigma_dut_cmd_check("ap_config_commit,NAME,AP") bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") bssid = bssid.split(',')[3] @@ -4882,3 +4892,28 @@ def test_sigma_dut_ap_sae_pk(dev, apdev, params): failure) finally: stop_sigma_dut(sigma) + +def test_sigma_dut_ap_sae_pk_misbehavior(dev, apdev, params): + """sigma_dut controlled AP using SAE-PK misbehavior""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + ssid = "SAEPK-4.7.1" + pw = "fb4c-zpqh-bhdc" + keypair = "saepk.pem" + m = "2ec1f37b47b402252e9dc5001e81fd1c" + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + True, status=126) + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + True, omit=True) + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + True, status=126, omit=True, immediate=True) + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + True, sig="saepk8_sig.pem") + finally: + stop_sigma_dut(sigma) From fcef598ea27ae15d00c6441f517885e4c316c645 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 21:40:56 +0300 Subject: [PATCH 0649/1105] Do not try to connect with zero-length SSID It was possible to find a BSS to local network profile match for a BSS entry that has no known SSID when going through some of the SSID wildcard cases. At leas the OWE transition mode case without BSSID match could result in hitting this. Zero-length SSID (i.e., wildcard SSID) is not valid in (Re)Association Request frame, so such an association will fail. Skip such a BSS to avoid known-to-be-failing association attempts. Signed-off-by: Jouni Malinen --- wpa_supplicant/events.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 86eef1b81..b93c62c8e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1451,6 +1451,13 @@ skip_assoc_disallow: } #endif /* CONFIG_SAE_PK */ + if (bss->ssid_len == 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no SSID known for the BSS"); + return false; + } + /* Matching configuration found */ return true; } From 78c1cb88683a2496d83cd68baade2519458187f1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 8 Jun 2020 21:43:41 +0300 Subject: [PATCH 0650/1105] tests: OWE transition mode BSSID mismatches Signed-off-by: Jouni Malinen --- tests/hwsim/test_owe.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_owe.py b/tests/hwsim/test_owe.py index e0d356858..52c59491a 100644 --- a/tests/hwsim/test_owe.py +++ b/tests/hwsim/test_owe.py @@ -149,23 +149,38 @@ def test_owe_transition_mode_connect_cmd(dev, apdev): wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") run_owe_transition_mode([wpas], apdev) -def run_owe_transition_mode(dev, apdev): +def test_owe_transition_mode_mismatch1(dev, apdev): + """Opportunistic Wireless Encryption transition mode (mismatch 1)""" + run_owe_transition_mode(dev, apdev, adv_bssid0="02:11:22:33:44:55") + +def test_owe_transition_mode_mismatch2(dev, apdev): + """Opportunistic Wireless Encryption transition mode (mismatch 2)""" + run_owe_transition_mode(dev, apdev, adv_bssid1="02:11:22:33:44:66") + +def test_owe_transition_mode_mismatch3(dev, apdev): + """Opportunistic Wireless Encryption transition mode (mismatch 3)""" + run_owe_transition_mode(dev, apdev, adv_bssid0="02:11:22:33:44:55", + adv_bssid1="02:11:22:33:44:66") + +def run_owe_transition_mode(dev, apdev, adv_bssid0=None, adv_bssid1=None): if "OWE" not in dev[0].get_capability("key_mgmt"): raise HwsimSkip("OWE not supported") dev[0].flush_scan_cache() + adv_bssid = adv_bssid0 if adv_bssid0 else apdev[1]['bssid'] params = {"ssid": "owe-random", "wpa": "2", "wpa_key_mgmt": "OWE", "rsn_pairwise": "CCMP", "ieee80211w": "2", - "owe_transition_bssid": apdev[1]['bssid'], + "owe_transition_bssid": adv_bssid, "owe_transition_ssid": '"owe-test"', "ignore_broadcast_ssid": "1"} hapd = hostapd.add_ap(apdev[0], params) bssid = hapd.own_addr() + adv_bssid = adv_bssid1 if adv_bssid1 else apdev[0]['bssid'] params = {"ssid": "owe-test", - "owe_transition_bssid": apdev[0]['bssid'], + "owe_transition_bssid": adv_bssid, "owe_transition_ssid": '"owe-random"'} hapd2 = hostapd.add_ap(apdev[1], params) bssid2 = hapd2.own_addr() From 411e42673f59aa683ee08c5abcbb3de15d411981 Mon Sep 17 00:00:00 2001 From: Subrat Dash Date: Thu, 21 May 2020 10:33:39 +0530 Subject: [PATCH 0651/1105] Move local TX queue parameter parser into a common file This allows the same implementation to be used for wpa_supplicant as well. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 92 +--------------------------------- src/ap/ap_config.h | 9 ---- src/common/ieee802_11_common.c | 92 ++++++++++++++++++++++++++++++++++ src/common/ieee802_11_common.h | 12 +++++ 4 files changed, 105 insertions(+), 100 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index dac0e8054..0a181f2e1 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -943,35 +943,6 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) } -/* convert floats with one decimal place to value*10 int, i.e., - * "1.5" will return 15 */ -static int hostapd_config_read_int10(const char *value) -{ - int i, d; - char *pos; - - i = atoi(value); - pos = os_strchr(value, '.'); - d = 0; - if (pos) { - pos++; - if (*pos >= '0' && *pos <= '9') - d = *pos - '0'; - } - - return i * 10 + d; -} - - -static int valid_cw(int cw) -{ - return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || - cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 || - cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 || - cw == 32767); -} - - enum { IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */ IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */ @@ -979,67 +950,6 @@ enum { IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */ }; -static int hostapd_config_tx_queue(struct hostapd_config *conf, - const char *name, const char *val) -{ - int num; - const char *pos; - struct hostapd_tx_queue_params *queue; - - /* skip 'tx_queue_' prefix */ - pos = name + 9; - if (os_strncmp(pos, "data", 4) == 0 && - pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { - num = pos[4] - '0'; - pos += 6; - } else if (os_strncmp(pos, "after_beacon_", 13) == 0 || - os_strncmp(pos, "beacon_", 7) == 0) { - wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); - return 0; - } else { - wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); - return -1; - } - - if (num >= NUM_TX_QUEUES) { - /* for backwards compatibility, do not trigger failure */ - wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); - return 0; - } - - queue = &conf->tx_queue[num]; - - if (os_strcmp(pos, "aifs") == 0) { - queue->aifs = atoi(val); - if (queue->aifs < 0 || queue->aifs > 255) { - wpa_printf(MSG_ERROR, "Invalid AIFS value %d", - queue->aifs); - return -1; - } - } else if (os_strcmp(pos, "cwmin") == 0) { - queue->cwmin = atoi(val); - if (!valid_cw(queue->cwmin)) { - wpa_printf(MSG_ERROR, "Invalid cwMin value %d", - queue->cwmin); - return -1; - } - } else if (os_strcmp(pos, "cwmax") == 0) { - queue->cwmax = atoi(val); - if (!valid_cw(queue->cwmax)) { - wpa_printf(MSG_ERROR, "Invalid cwMax value %d", - queue->cwmax); - return -1; - } - } else if (os_strcmp(pos, "burst") == 0) { - queue->burst = hostapd_config_read_int10(val); - } else { - wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos); - return -1; - } - - return 0; -} - #ifdef CONFIG_IEEE80211R_AP @@ -3424,7 +3334,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { conf->ap_table_expiration_time = atoi(pos); } else if (os_strncmp(buf, "tx_queue_", 9) == 0) { - if (hostapd_config_tx_queue(conf, buf, pos)) { + if (hostapd_config_tx_queue(conf->tx_queue, buf, pos)) { wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item", line); return 1; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 4c2e60095..b705c378f 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -197,15 +197,6 @@ struct hostapd_radius_attr { #define NUM_TX_QUEUES 4 - -struct hostapd_tx_queue_params { - int aifs; - int cwmin; - int cwmax; - int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */ -}; - - #define MAX_ROAMING_CONSORTIUM_LEN 15 struct hostapd_roaming_consortium { diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 981652e47..5bfaece5a 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -763,6 +763,98 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[], } +/* convert floats with one decimal place to value*10 int, i.e., + * "1.5" will return 15 + */ +static int hostapd_config_read_int10(const char *value) +{ + int i, d; + char *pos; + + i = atoi(value); + pos = os_strchr(value, '.'); + d = 0; + if (pos) { + pos++; + if (*pos >= '0' && *pos <= '9') + d = *pos - '0'; + } + + return i * 10 + d; +} + + +static int valid_cw(int cw) +{ + return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || + cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 || + cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 || + cw == 32767); +} + + +int hostapd_config_tx_queue(struct hostapd_tx_queue_params tx_queue[], + const char *name, const char *val) +{ + int num; + const char *pos; + struct hostapd_tx_queue_params *queue; + + /* skip 'tx_queue_' prefix */ + pos = name + 9; + if (os_strncmp(pos, "data", 4) == 0 && + pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { + num = pos[4] - '0'; + pos += 6; + } else if (os_strncmp(pos, "after_beacon_", 13) == 0 || + os_strncmp(pos, "beacon_", 7) == 0) { + wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); + return 0; + } else { + wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); + return -1; + } + + if (num >= NUM_TX_QUEUES) { + /* for backwards compatibility, do not trigger failure */ + wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); + return 0; + } + + queue = &tx_queue[num]; + + if (os_strcmp(pos, "aifs") == 0) { + queue->aifs = atoi(val); + if (queue->aifs < 0 || queue->aifs > 255) { + wpa_printf(MSG_ERROR, "Invalid AIFS value %d", + queue->aifs); + return -1; + } + } else if (os_strcmp(pos, "cwmin") == 0) { + queue->cwmin = atoi(val); + if (!valid_cw(queue->cwmin)) { + wpa_printf(MSG_ERROR, "Invalid cwMin value %d", + queue->cwmin); + return -1; + } + } else if (os_strcmp(pos, "cwmax") == 0) { + queue->cwmax = atoi(val); + if (!valid_cw(queue->cwmax)) { + wpa_printf(MSG_ERROR, "Invalid cwMax value %d", + queue->cwmax); + return -1; + } + } else if (os_strcmp(pos, "burst") == 0) { + queue->burst = hostapd_config_read_int10(val); + } else { + wpa_printf(MSG_ERROR, "Unknown queue field '%s'", pos); + return -1; + } + + return 0; +} + + enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel) { u8 op_class; diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index cf4865014..4abe468ec 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -192,6 +192,18 @@ struct hostapd_wmm_ac_params { int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[], const char *name, const char *val); + +struct hostapd_tx_queue_params { + int aifs; + int cwmin; + int cwmax; + int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */ +}; + +#define NUM_TX_QUEUES 4 + +int hostapd_config_tx_queue(struct hostapd_tx_queue_params queue[], + 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); enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, From c7cb42d531ccc01dac97543cefd4f1061331c557 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Jun 2020 00:21:06 +0300 Subject: [PATCH 0652/1105] Remove unused enum values The last user of these was removed in commit 17fbb751e174 ("Remove user space client MLME") and there is no need to maintain these unused values anymore. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 0a181f2e1..8f7fcd8b7 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -943,14 +943,6 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) } -enum { - IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */ - IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */ - IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */ - IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */ -}; - - #ifdef CONFIG_IEEE80211R_AP static int rkh_derive_key(const char *pos, u8 *key, size_t key_len) From 790026c3daa23acc6f147b64c2dd4b604951d6d1 Mon Sep 17 00:00:00 2001 From: Subrat Dash Date: Sat, 6 Jun 2020 13:20:34 +0530 Subject: [PATCH 0653/1105] Allow TX queue parameters to be configured for wpa_supplicant AP/P2P GO Allow user to configure the TX queue parameters through the wpa_supplicant configuration file similarly to the way these can be set in hostapd. Parse the tx_queue_* parameters in the wpa_supplicant configuration file and update the TX queue configuration to the AP/P2P GO interface in the function wpa_supplicant_create_ap(). Signed-off-by: Jouni Malinen --- wpa_supplicant/ap.c | 3 +++ wpa_supplicant/config.c | 37 +++++++++++++++++++++++++++++++++++++ wpa_supplicant/config.h | 1 + 3 files changed, 41 insertions(+) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 624168205..2accf92cd 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -858,6 +858,9 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, wpa_s->conf->wmm_ac_params, sizeof(wpa_s->conf->wmm_ac_params)); + os_memcpy(wpa_s->ap_iface->conf->tx_queue, wpa_s->conf->tx_queue, + sizeof(wpa_s->conf->tx_queue)); + if (params.uapsd > 0) { conf->bss[0]->wmm_enabled = 1; conf->bss[0]->wmm_uapsd = 1; diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index a9726e2d6..0b4a66ad7 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4255,6 +4255,8 @@ int wpa_config_remove_blob(struct wpa_config *config, const char *name) struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, const char *driver_param) { +#define ecw2cw(ecw) ((1 << (ecw)) - 1) + struct wpa_config *config; const int aCWmin = 4, aCWmax = 10; const struct hostapd_wmm_ac_params ac_bk = @@ -4265,6 +4267,17 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 }; const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 }; + const struct hostapd_tx_queue_params txq_bk = + { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; + const struct hostapd_tx_queue_params txq_be = + { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0 }; + const struct hostapd_tx_queue_params txq_vi = + { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30 }; + const struct hostapd_tx_queue_params txq_vo = + { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, + (ecw2cw(aCWmin) + 1) / 2 - 1, 15 }; + +#undef ecw2cw config = os_zalloc(sizeof(*config)); if (config == NULL) @@ -4294,6 +4307,10 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->wmm_ac_params[1] = ac_bk; config->wmm_ac_params[2] = ac_vi; config->wmm_ac_params[3] = ac_vo; + config->tx_queue[0] = txq_vo; + config->tx_queue[1] = txq_vi; + config->tx_queue[2] = txq_be; + config->tx_queue[3] = txq_bk; config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY; config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME; config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD; @@ -5165,6 +5182,26 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) } if (i == NUM_GLOBAL_FIELDS) { #ifdef CONFIG_AP + if (os_strncmp(pos, "tx_queue_", 9) == 0) { + char *tmp = os_strchr(pos, '='); + + if (!tmp) { + if (line < 0) + wpa_printf(MSG_ERROR, + "Line %d: invalid line %s", + line, pos); + return -1; + } + *tmp++ = '\0'; + if (hostapd_config_tx_queue(config->tx_queue, pos, + tmp)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid TX queue item", + line); + return -1; + } + } + if (os_strncmp(pos, "wmm_ac_", 7) == 0) { char *tmp = os_strchr(pos, '='); if (tmp == NULL) { diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 2d4cb1b8f..a385da528 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -1058,6 +1058,7 @@ struct wpa_config { int p2p_go_max_inactivity; struct hostapd_wmm_ac_params wmm_ac_params[4]; + struct hostapd_tx_queue_params tx_queue[4]; /** * auto_interworking - Whether to use network selection automatically From cc2d03601b70667b23928882e2b4bae336de2b7c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Jun 2020 00:55:13 +0300 Subject: [PATCH 0654/1105] HS 2.0: Use global pmf=2 for the created network block Previously, PMF support was enabled in optional mode (ieee80211w=1) for Hotspot 2.0 network blocks automatically. This did not consider the global PMF parameter and unconditionally changed that value to optional. Since the newly added network block had an explicit ieee80211w parameter, this overrode the global parameter. To make this less surprising, use the global pmf parameter value to select whether to add network blocks for Hotspot 2.0 with PMF being optionally enabled (pmf=0 or pmf=1) or required (pmf=2). Signed-off-by: Jouni Malinen --- wpa_supplicant/interworking.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index a380123b3..b1ddd0925 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -959,7 +959,9 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP"; if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 || wpa_config_set(ssid, "proto", "RSN", 0) < 0 || - wpa_config_set(ssid, "ieee80211w", "1", 0) < 0 || + wpa_config_set(ssid, "ieee80211w", + wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_REQUIRED ? + "2" : "1", 0) < 0 || wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0) return -1; return 0; From 892ac42bdc487daabf16b9a888c57e46892657af Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Jun 2020 00:59:26 +0300 Subject: [PATCH 0655/1105] tests: wpa_supplicant global pmf parameter Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_hs20.py | 55 +++++++++++++++++++++++++++++++++++++ tests/hwsim/test_ap_pmf.py | 41 +++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index d9f2e08c6..c8ba76770 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -727,6 +727,61 @@ def test_ap_hs20_auto_interworking(dev, apdev): if status['hs20'] != "3": raise Exception("Unexpected HS 2.0 support indication") +def test_ap_hs20_auto_interworking_global_pmf(dev, apdev): + """Hotspot 2.0 connection with auto_interworking=1 and pmf=2""" + check_eap_capa(dev[0], "MSCHAPV2") + bssid = apdev[0]['bssid'] + params = hs20_ap_params() + params['hessid'] = bssid + hostapd.add_ap(apdev[0], params) + + dev[0].hs20_enable(auto_interworking=True) + id = dev[0].add_cred_values({'realm': "example.com", + 'username': "hs20-test", + 'password': "password", + 'ca_cert': "auth_serv/ca.pem", + 'domain': "example.com", + 'update_identifier': "1234"}) + try: + dev[0].set("pmf", "2") + dev[0].request("REASSOCIATE") + dev[0].wait_connected(timeout=15) + pmf = dev[0].get_status_field("pmf") + if pmf != "1": + raise Exception("Unexpected PMF state: " + str(pmf)) + finally: + dev[0].set("pmf", "0") + +def test_ap_hs20_auto_interworking_global_pmf_fail(dev, apdev): + """Hotspot 2.0 connection with auto_interworking=1 and pmf=2 failure""" + check_eap_capa(dev[0], "MSCHAPV2") + bssid = apdev[0]['bssid'] + params = hs20_ap_params() + params['ieee80211w'] = "0" + params['hessid'] = bssid + hostapd.add_ap(apdev[0], params) + + dev[0].hs20_enable(auto_interworking=True) + id = dev[0].add_cred_values({'realm': "example.com", + 'username': "hs20-test", + 'password': "password", + 'ca_cert': "auth_serv/ca.pem", + 'domain': "example.com", + 'update_identifier': "1234"}) + try: + dev[0].set("pmf", "2") + dev[0].request("REASSOCIATE") + for i in range(2): + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "INTERWORKING-SELECTED"], timeout=15) + if ev is None: + raise Exception("Connection result not reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + dev[0].request("DISCONNECT") + finally: + dev[0].set("pmf", "0") + @remote_compatible def test_ap_hs20_auto_interworking_no_match(dev, apdev): """Hotspot 2.0 connection with auto_interworking=1 and no matching network""" diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index 2bb4a3602..e0a6225db 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -1133,3 +1133,44 @@ def run_ap_pmf_beacon_protection_mismatch(dev, apdev, clear): ev = hapd.wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5) if ev is None: raise Exception("WNM-Notification Request frame not reported") + +def test_ap_pmf_sta_global_require(dev, apdev): + """WPA2-PSK AP with PMF optional and wpa_supplicant pmf=2""" + ssid = "test-pmf-optional" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK" + params["ieee80211w"] = "1" + hapd = hostapd.add_ap(apdev[0], params) + try: + dev[0].set("pmf", "2") + dev[0].connect(ssid, psk="12345678", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412") + pmf = dev[0].get_status_field("pmf") + if pmf != "1": + raise Exception("Unexpected PMF state: " + str(pmf)) + finally: + dev[0].set("pmf", "0") + +def test_ap_pmf_sta_global_require2(dev, apdev): + """WPA2-PSK AP with PMF optional and wpa_supplicant pmf=2 (2)""" + ssid = "test-pmf-optional" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK" + params["ieee80211w"] = "0" + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + try: + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].set("pmf", "2") + dev[0].connect(ssid, psk="12345678", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) + if ev is None: + raise Exception("Connection result not reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + finally: + dev[0].set("pmf", "0") From f119f8a04a5737a1fe8d0776a7c9c625cdd51298 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Jun 2020 12:43:53 +0300 Subject: [PATCH 0656/1105] WPS UPnP: Fix FreeBSD build struct ifreq does not include the ifr_netmask alternative on FreeBSD, so replace that more specific name with ifr_addr that works with both Linux and FreeBSD. Fixes: 5b78c8f961f2 ("WPS UPnP: Do not allow event subscriptions with URLs to other networks") Signed-off-by: Jouni Malinen --- src/wps/wps_upnp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index ab685d52e..16fefc77b 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -951,7 +951,7 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, errno, strerror(errno)); goto fail; } - addr = (struct sockaddr_in *) &req.ifr_netmask; + addr = (struct sockaddr_in *) &req.ifr_addr; netmask->s_addr = addr->sin_addr.s_addr; } From 2e80aeae4a021443c35ae03be082128f1f644b73 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Jun 2020 12:48:13 +0300 Subject: [PATCH 0657/1105] WPS UPnP: Support build on OS X Define MAC address fetching for OS X (by reusing the existing FreeBSD implementation) to allow full compile testing of the WPS implementation on a more BSD-like platform. Signed-off-by: Jouni Malinen --- src/wps/wps_upnp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index 16fefc77b..ff58cb938 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -862,7 +862,7 @@ fail: } -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) #include #include #include @@ -903,7 +903,7 @@ static int eth_get(const char *device, u8 ea[ETH_ALEN]) } return 0; } -#endif /* __FreeBSD__ */ +#endif /* __FreeBSD__ || __APPLE__ */ /** @@ -963,7 +963,7 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, goto fail; } os_memcpy(mac, req.ifr_addr.sa_data, 6); -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) if (eth_get(net_if, mac) < 0) { wpa_printf(MSG_ERROR, "WPS UPnP: Failed to get MAC address"); goto fail; From 363dbf1ece24a2d326d7684c8af55f409eab2a51 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Jun 2020 22:32:38 +0300 Subject: [PATCH 0658/1105] SAE-PK: Remove requirement of SAE group matching SAE-PK (K_AP) group This was clarified in the draft specification to not be a mandatory requirement for the AP and STA to enforce, i.e., matching security level is a recommendation for AP configuration rather than a protocol requirement. Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 35 ++++------------------------------- src/common/sae.c | 9 --------- src/common/sae.h | 1 - src/common/sae_pk.c | 10 ---------- 4 files changed, 4 insertions(+), 51 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 8b994d6a5..6723f33dd 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -594,10 +594,6 @@ static int auth_sae_send_commit(struct hostapd_data *hapd, data = auth_build_sae_commit(hapd, sta, update, status_code); if (!data && sta->sae->tmp && sta->sae->tmp->pw_id) return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; -#ifdef CONFIG_SAE_PK - if (!data && sta->sae->tmp && sta->sae->tmp->reject_group) - return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; -#endif /* CONFIG_SAE_PK */ if (data == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; @@ -1195,7 +1191,7 @@ static int sae_is_group_enabled(struct hostapd_data *hapd, int group) static int check_sae_rejected_groups(struct hostapd_data *hapd, - struct sae_data *sae, bool pk) + struct sae_data *sae) { const struct wpabuf *groups; size_t i, count; @@ -1216,29 +1212,8 @@ static int check_sae_rejected_groups(struct hostapd_data *hapd, group = WPA_GET_LE16(pos); pos += 2; enabled = sae_is_group_enabled(hapd, group); - -#ifdef CONFIG_SAE_PK - /* TODO: Could check more explicitly against the matching - * sae_password entry only for the somewhat theoretical case of - * different passwords using different groups for SAE-PK K_AP - * values. */ - if (pk) { - struct sae_password_entry *pw; - - enabled = false; - for (pw = hapd->conf->sae_passwords; pw; - pw = pw->next) { - if (pw->pk && pw->pk->group == group) { - enabled = true; - break; - } - } - } -#endif /* CONFIG_SAE_PK */ - - wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s%s", - group, enabled ? "enabled" : "disabled", - pk ? " (PK)" : ""); + wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s", + group, enabled ? "enabled" : "disabled"); if (enabled) return 1; } @@ -1442,9 +1417,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, if (resp != WLAN_STATUS_SUCCESS) goto reply; - if (check_sae_rejected_groups(hapd, sta->sae, - status_code == - WLAN_STATUS_SAE_PK)) { + if (check_sae_rejected_groups(hapd, sta->sae)) { resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto reply; } diff --git a/src/common/sae.c b/src/common/sae.c index c8e77aaec..77f3a0e8c 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -1392,15 +1392,6 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, os_memcpy(sae->tmp->ssid, pt->ssid, pt->ssid_len); sae->tmp->ssid_len = pt->ssid_len; sae->tmp->ap_pk = pk; - /* TODO: Could support alternative groups as long as the combination - * meets the requirements. */ - if (pk && pk->group != sae->group) { - wpa_printf(MSG_DEBUG, - "SAE-PK: Reject attempt to use group %d since K_AP use group %d", - sae->group, pk->group); - sae->tmp->reject_group = true; - return -1; - } #endif /* CONFIG_SAE_PK */ sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0; wpabuf_free(sae->tmp->own_rejected_groups); diff --git a/src/common/sae.h b/src/common/sae.h index 261935fdb..ee3c662c5 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -75,7 +75,6 @@ struct sae_temporary_data { size_t lambda; u8 ssid[32]; size_t ssid_len; - bool reject_group; #ifdef CONFIG_TESTING_OPTIONS bool omit_pk_elem; #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index 9e02611f7..5ccd601c2 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -686,16 +686,6 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) return -1; } - /* TODO: Could support alternative groups as long as the combination - * meets the requirements. */ - if (group != sae->group) { - wpa_printf(MSG_INFO, - "SAE-PK: K_AP group %d does not match SAE group %d", - group, sae->group); - crypto_ec_key_deinit(key); - return -1; - } - wpa_hexdump(MSG_DEBUG, "SAE-PK: Received KeyAuth", key_auth, key_auth_len); From cad9ae1dc43d403292cd15d4016616d2ee0457b6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Jun 2020 22:45:57 +0300 Subject: [PATCH 0659/1105] tests: SAE-PK with different SAE group combinations Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 45 +++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index e7574a155..8903f83b6 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -13,6 +13,10 @@ SAE_PK_SEC2_PW_FULL = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-ql SAE_PK_SEC2_M = "431ff8322f93b9dc50ded9f3d14ace22" SAE_PK_SEC2_PK = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" +SAE_PK_20_PW = "f3bh-5un3-wz7o-al3p" +SAE_PK_20_M = "50bf37ba0033ed110a74e3a7aa52f4e9" +SAE_PK_20_PK = "MIGkAgEBBDA4wpA6w/fK0g3a2V6QmcoxNoFCVuQPyzWvKYimJkgXsVsXt2ERXQ7dGOVXeycM5DqgBwYFK4EEACKhZANiAARTdszGBNe2PGCnc8Wvs+IDvdVEf4PPBrty0meRZf6UTbGouquTHpy6KKTq5sxrulYzsQFimg4op0UJBGxAzqo0EtTgMlLiBvY0I3Nl3N69MhWo8nvnmguvGGN32AAPXpQ=" + def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None): params = hostapd.wpa2_params(ssid=ssid) params['wpa_key_mgmt'] = 'SAE' @@ -115,13 +119,42 @@ def test_sae_pk_group_20(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "20") - ssid = "SAE-PK test" - pw = "f3bh-5un3-wz7o-al3p" - m = "50bf37ba0033ed110a74e3a7aa52f4e9" - pk = "MIGkAgEBBDA4wpA6w/fK0g3a2V6QmcoxNoFCVuQPyzWvKYimJkgXsVsXt2ERXQ7dGOVXeycM5DqgBwYFK4EEACKhZANiAARTdszGBNe2PGCnc8Wvs+IDvdVEf4PPBrty0meRZf6UTbGouquTHpy6KKTq5sxrulYzsQFimg4op0UJBGxAzqo0EtTgMlLiBvY0I3Nl3N69MhWo8nvnmguvGGN32AAPXpQ=" - try: - run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk, ap_groups="20") + run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_20_PW, + SAE_PK_20_M, SAE_PK_20_PK, ap_groups="20") + finally: + dev[0].set("sae_groups", "") + +def test_sae_pk_group_20_sae_group_19(dev, apdev): + """SAE-PK with group 20 with SAE group 19""" + check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() + dev[0].set("sae_groups", "19") + try: + run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_20_PW, + SAE_PK_20_M, SAE_PK_20_PK, ap_groups="19") + finally: + dev[0].set("sae_groups", "") + +def test_sae_pk_group_20_sae_group_21(dev, apdev): + """SAE-PK with group 20 with SAE group 21""" + check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() + dev[0].set("sae_groups", "21") + try: + run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_20_PW, + SAE_PK_20_M, SAE_PK_20_PK, ap_groups="21") + finally: + dev[0].set("sae_groups", "") + +def test_sae_pk_group_19_sae_group_20(dev, apdev): + """SAE-PK with group 19 with SAE group 20""" + check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() + dev[0].set("sae_groups", "20") + try: + run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_SEC2_PW, + SAE_PK_SEC2_M, SAE_PK_SEC2_PK, ap_groups="20") finally: dev[0].set("sae_groups", "") From f0704e72734fa9af23063a1d19a211358559f6e5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Jun 2020 22:54:35 +0300 Subject: [PATCH 0660/1105] tests: Clean up SAE-PK parameter use Use the global variables instead of copies of same values. Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 96 +++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 52 deletions(-) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 8903f83b6..9f544be04 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -7,11 +7,12 @@ import hostapd from utils import * -SAE_PK_SEC2_SSID = "SAE-PK test" +SAE_PK_SSID = "SAE-PK test" + SAE_PK_SEC2_PW = "dwxm-zv66-p5ue" SAE_PK_SEC2_PW_FULL = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-qleg" SAE_PK_SEC2_M = "431ff8322f93b9dc50ded9f3d14ace22" -SAE_PK_SEC2_PK = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" +SAE_PK_19_PK = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" SAE_PK_20_PW = "f3bh-5un3-wz7o-al3p" SAE_PK_20_M = "50bf37ba0033ed110a74e3a7aa52f4e9" @@ -50,8 +51,8 @@ def test_sae_pk(dev, apdev): p = SAE_PK_SEC2_PW_FULL[:i] if p.endswith('-'): continue - run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, p, SAE_PK_SEC2_M, - SAE_PK_SEC2_PK) + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, p, SAE_PK_SEC2_M, + SAE_PK_19_PK) def test_sae_pk_group_negotiation(dev, apdev): """SAE-PK""" @@ -60,8 +61,8 @@ def test_sae_pk_group_negotiation(dev, apdev): dev[0].set("sae_groups", "20 19") try: - run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_SEC2_PW, - SAE_PK_SEC2_M, SAE_PK_SEC2_PK, ap_groups="19 20") + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW, + SAE_PK_SEC2_M, SAE_PK_19_PK, ap_groups="19 20") finally: dev[0].set("sae_groups", "") @@ -71,8 +72,8 @@ def test_sae_pk_sec_2(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "") - run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_SEC2_PW, - SAE_PK_SEC2_M, SAE_PK_SEC2_PK) + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW, + SAE_PK_SEC2_M, SAE_PK_19_PK) def test_sae_pk_sec_3(dev, apdev): """SAE-PK with Sec 3""" @@ -80,12 +81,9 @@ def test_sae_pk_sec_3(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "") - ssid = "SAE-PK test" pw = "iian-qey6-pu5t" m = "128e51ddb5e2e24388f9ed14b687e2eb" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - - run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk) + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK) def test_sae_pk_sec_4(dev, apdev): """SAE-PK with Sec 4""" @@ -93,12 +91,9 @@ def test_sae_pk_sec_4(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "") - ssid = "SAE-PK test" pw = "ssko-2lmu-7hzs-bqct" m = "a5e38c7251ea310cc348fbcdadfa8bcb" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - - run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk) + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK) def test_sae_pk_sec_5(dev, apdev): """SAE-PK with Sec 5""" @@ -106,12 +101,9 @@ def test_sae_pk_sec_5(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "") - ssid = "SAE-PK test" pw = "3qqu-f4xq-dz37-fes3-fbgc" m = "d2e5fa27d1be8897f987f2d480d2af6b" - pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" - - run_sae_pk(apdev[0], dev[0], ssid, pw, m, pk) + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK) def test_sae_pk_group_20(dev, apdev): """SAE-PK with group 20""" @@ -120,7 +112,7 @@ def test_sae_pk_group_20(dev, apdev): dev[0].set("sae_groups", "20") try: - run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_20_PW, + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_20_PW, SAE_PK_20_M, SAE_PK_20_PK, ap_groups="20") finally: dev[0].set("sae_groups", "") @@ -131,7 +123,7 @@ def test_sae_pk_group_20_sae_group_19(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "19") try: - run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_20_PW, + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_20_PW, SAE_PK_20_M, SAE_PK_20_PK, ap_groups="19") finally: dev[0].set("sae_groups", "") @@ -142,7 +134,7 @@ def test_sae_pk_group_20_sae_group_21(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "21") try: - run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_20_PW, + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_20_PW, SAE_PK_20_M, SAE_PK_20_PK, ap_groups="21") finally: dev[0].set("sae_groups", "") @@ -153,8 +145,8 @@ def test_sae_pk_group_19_sae_group_20(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "20") try: - run_sae_pk(apdev[0], dev[0], SAE_PK_SEC2_SSID, SAE_PK_SEC2_PW, - SAE_PK_SEC2_M, SAE_PK_SEC2_PK, ap_groups="20") + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW, + SAE_PK_SEC2_M, SAE_PK_19_PK, ap_groups="20") finally: dev[0].set("sae_groups", "") @@ -163,12 +155,12 @@ def test_sae_pk_password_without_pk(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = SAE_PK_SEC2_PW hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, key_mgmt="SAE", scan_freq="2412") if dev[0].get_status_field("sae_pk") != "0": raise Exception("Unexpected sae_pk STATUS value") @@ -178,12 +170,12 @@ def test_sae_pk_only(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = SAE_PK_SEC2_PW hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, key_mgmt="SAE", sae_pk="1", scan_freq="2412", wait_connect=False) ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", @@ -195,10 +187,10 @@ def test_sae_pk_only(dev, apdev): dev[0].request("DISCONNECT") dev[0].dump_monitor() - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, - SAE_PK_SEC2_PK)] + SAE_PK_19_PK)] hapd2 = hostapd.add_ap(apdev[1], params) bssid2 = hapd2.own_addr() @@ -215,16 +207,16 @@ def test_sae_pk_modes(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params["ieee80211w"] = "2" params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, - SAE_PK_SEC2_PK)] + SAE_PK_19_PK)] hapd = hostapd.add_ap(apdev[0], params) tests = [(2, 0), (1, 1), (0, 1)] for sae_pk, expected in tests: - dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, key_mgmt="SAE", sae_pk=str(sae_pk), ieee80211w="2", scan_freq="2412") val = dev[0].get_status_field("sae_pk") @@ -239,12 +231,12 @@ def test_sae_pk_not_on_ap(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = SAE_PK_SEC2_PW hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, key_mgmt="SAE", scan_freq="2412") if dev[0].get_status_field("sae_pk") == "1": raise Exception("SAE-PK was claimed to be used") @@ -254,14 +246,14 @@ def test_sae_pk_transition_disable(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, - SAE_PK_SEC2_PK)] + SAE_PK_19_PK)] params['transition_disable'] = '0x02' hapd = hostapd.add_ap(apdev[0], params) - id = dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + id = dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, key_mgmt="SAE", scan_freq="2412") ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) if ev is None: @@ -278,16 +270,16 @@ def test_sae_pk_mixed(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = SAE_PK_SEC2_PW hapd = hostapd.add_ap(apdev[0], params) bssid = hapd.own_addr() - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, - SAE_PK_SEC2_PK)] + SAE_PK_19_PK)] # Disable HT from the SAE-PK BSS to make the station prefer the other BSS # by default. params['ieee80211n'] = '0' @@ -297,7 +289,7 @@ def test_sae_pk_mixed(dev, apdev): dev[0].scan_for_bss(bssid, freq=2412) dev[0].scan_for_bss(bssid2, freq=2412) - dev[0].connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, key_mgmt="SAE", scan_freq="2412") if dev[0].get_status_field("sae_pk") != "1": @@ -306,7 +298,7 @@ def test_sae_pk_mixed(dev, apdev): raise Exception("Unexpected BSSID selected") def check_sae_pk_sta_connect_failure(dev): - dev.connect(SAE_PK_SEC2_SSID, sae_password=SAE_PK_SEC2_PW, + dev.connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, key_mgmt="SAE", scan_freq="2412", wait_connect=False) ev = dev.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) @@ -320,10 +312,10 @@ def test_sae_pk_missing_ie(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, - SAE_PK_SEC2_PK)] + SAE_PK_19_PK)] params['sae_pk_omit'] = '1' hapd = hostapd.add_ap(apdev[0], params) check_sae_pk_sta_connect_failure(dev[0]) @@ -333,10 +325,10 @@ def test_sae_pk_unexpected_status(dev, apdev): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, - SAE_PK_SEC2_PK)] + SAE_PK_19_PK)] params['sae_commit_status'] = '126' hapd = hostapd.add_ap(apdev[0], params) check_sae_pk_sta_connect_failure(dev[0]) @@ -347,10 +339,10 @@ def test_sae_pk_invalid_signature(dev, apdev): dev[0].set("sae_groups", "") other = "MHcCAQEEILw+nTjFzRyhVea0G6KbwZu18oWrfhzppxj+MceUO3YLoAoGCCqGSM49AwEHoUQDQgAELdou6LuTDNiMVlMB65KsWhQFbPXR9url0EA6luWzUfAuGoDXYJUBTVz6Nv3mz6oQcDrSiDmz/LejndJ0YHGgfQ==" - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = ['%s|pk=%s:%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, - SAE_PK_SEC2_PK, other)] + SAE_PK_19_PK, other)] hapd = hostapd.add_ap(apdev[0], params) check_sae_pk_sta_connect_failure(dev[0]) @@ -360,9 +352,9 @@ def test_sae_pk_invalid_fingerprint(dev, apdev): dev[0].set("sae_groups", "") other = "431ff8322f93b9dc50ded9f3d14ace21" - params = hostapd.wpa2_params(ssid=SAE_PK_SEC2_SSID) + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, other, - SAE_PK_SEC2_PK)] + SAE_PK_19_PK)] hapd = hostapd.add_ap(apdev[0], params) check_sae_pk_sta_connect_failure(dev[0]) From a77d6d22032eece839813d9563e887c50bc940d9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 10 Jun 2020 00:59:09 +0300 Subject: [PATCH 0661/1105] SAE-PK: Update SAE confirm IE design Move the FILS Public Key element and the FILS Key Confirmation element to be separate IEs instead of being encapsulated within the SAE-PK element. This is also removing the unnecessary length field for the fixed-length EncryptedModifier. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_common.c | 4 + src/common/ieee802_11_common.h | 2 + src/common/ieee802_11_defs.h | 1 + src/common/sae_pk.c | 158 +++++++++++++-------------------- 4 files changed, 67 insertions(+), 98 deletions(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 5bfaece5a..9cd631783 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -136,6 +136,10 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, case DPP_CC_OUI_TYPE: /* DPP Configurator Connectivity element */ break; + case SAE_PK_OUI_TYPE: + elems->sae_pk = pos + 4; + elems->sae_pk_len = elen - 4; + break; default: wpa_printf(MSG_MSGDUMP, "Unknown WFA " "information element ignored " diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 4abe468ec..0ddba0692 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -114,6 +114,7 @@ struct ieee802_11_elems { const u8 *he_operation; const u8 *short_ssid_list; const u8 *he_6ghz_band_cap; + const u8 *sae_pk; u8 ssid_len; u8 supp_rates_len; @@ -166,6 +167,7 @@ struct ieee802_11_elems { u8 he_capabilities_len; u8 he_operation_len; u8 short_ssid_list_len; + u8 sae_pk_len; struct mb_ies_info mb_ies; struct frag_ies_info frag_ies; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 3fc4200a0..b7c69478d 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -1323,6 +1323,7 @@ struct ieee80211_ampe_ie { #define DPP_CC_IE_VENDOR_TYPE 0x506f9a1e #define DPP_CC_OUI_TYPE 0x1e #define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f +#define SAE_PK_OUI_TYPE 0x1f #define MULTI_AP_SUB_ELEM_TYPE 0x06 #define MULTI_AP_TEAR_DOWN BIT(4) diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index 5ccd601c2..b294312ef 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -375,8 +375,8 @@ fail: int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) { struct sae_temporary_data *tmp = sae->tmp; - struct wpabuf *elem = NULL, *sig = NULL; - size_t extra; + struct wpabuf *sig = NULL; + size_t need; int ret = -1; u8 *encr_mod; size_t encr_mod_len; @@ -425,14 +425,41 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) goto fail; wpa_hexdump_buf(MSG_DEBUG, "SAE-PK: KeyAuth = Sig_AP()", sig); - elem = wpabuf_alloc(1500 + wpabuf_len(sig)); - if (!elem) - goto fail; + /* TODO: fragmentation if any of the elements needs it for a group + * using sufficiently large primes (none of the currently supported + * ones do) */ - /* EncryptedModifier = AES-SIV-Q(M); no AAD */ encr_mod_len = wpabuf_len(pk->m) + AES_BLOCK_SIZE; - wpabuf_put_u8(elem, encr_mod_len); - encr_mod = wpabuf_put(elem, encr_mod_len); + need = 4 + wpabuf_len(pk->pubkey) + 3 + wpabuf_len(sig) + + 6 + encr_mod_len; + if (wpabuf_tailroom(buf) < need) { + wpa_printf(MSG_INFO, + "SAE-PK: No room in message buffer for SAE-PK elements (%zu < %zu)", + wpabuf_tailroom(buf), need); + goto fail; + } + + /* FILS Public Key element */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + wpabuf_put_u8(buf, 2 + wpabuf_len(pk->pubkey)); + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_PUBLIC_KEY); + wpabuf_put_u8(buf, 2); /* Key Type: ECDSA public key */ + wpabuf_put_buf(buf, pk->pubkey); + + /* FILS Key Confirmation element (KeyAuth) */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + wpabuf_put_u8(buf, 1 + wpabuf_len(sig)); + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM); + /* KeyAuth = Sig_AP(eleAP || eleSTA || scaAP || scaSTA || M || K_AP || + * AP-BSSID || STA-MAC) */ + wpabuf_put_buf(buf, sig); + + /* SAE-PK element */ + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(buf, 4 + encr_mod_len); + wpabuf_put_be32(buf, SAE_PK_IE_VENDOR_TYPE); + /* EncryptedModifier = AES-SIV-Q(M); no AAD */ + encr_mod = wpabuf_put(buf, encr_mod_len); if (aes_siv_encrypt(tmp->kek, tmp->kek_len, wpabuf_head(pk->m), wpabuf_len(pk->m), 0, NULL, NULL, encr_mod) < 0) @@ -440,40 +467,8 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier", encr_mod, encr_mod_len); - /* FILS Public Key element */ - wpabuf_put_u8(elem, WLAN_EID_EXTENSION); - wpabuf_put_u8(elem, 2 + wpabuf_len(pk->pubkey)); - wpabuf_put_u8(elem, WLAN_EID_EXT_FILS_PUBLIC_KEY); - wpabuf_put_u8(elem, 2); /* Key Type: ECDSA public key */ - wpabuf_put_buf(elem, pk->pubkey); - - /* FILS Key Confirmation element (KeyAuth) */ - wpabuf_put_u8(elem, WLAN_EID_EXTENSION); - wpabuf_put_u8(elem, 1 + wpabuf_len(sig)); - wpabuf_put_u8(elem, WLAN_EID_EXT_FILS_KEY_CONFIRM); - /* KeyAuth = Sig_AP(eleAP || eleSTA || scaAP || scaSTA || M || K_AP || - * AP-BSSID || STA-MAC) */ - wpabuf_put_buf(elem, sig); - - /* TODO: fragmentation */ - extra = 6; /* Vendor specific element header */ - - if (wpabuf_tailroom(elem) < extra + wpabuf_len(buf)) { - wpa_printf(MSG_INFO, - "SAE-PK: No room in message buffer for SAE-PK element (%zu < %zu)", - wpabuf_tailroom(buf), extra + wpabuf_len(buf)); - goto fail; - } - - /* SAE-PK element */ - wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); - wpabuf_put_u8(buf, 4 + wpabuf_len(elem)); - wpabuf_put_be32(buf, SAE_PK_IE_VENDOR_TYPE); - wpabuf_put_buf(buf, elem); - ret = 0; fail: - wpabuf_free(elem); wpabuf_free(sig); return ret; @@ -569,14 +564,15 @@ static bool sae_pk_valid_fingerprint(struct sae_data *sae, int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) { struct sae_temporary_data *tmp = sae->tmp; - const u8 *sae_pk, *pos, *end, *encr_mod, *k_ap, *key_auth; + const u8 *k_ap; u8 m[SAE_PK_M_LEN]; - size_t k_ap_len, key_auth_len; + size_t k_ap_len; struct crypto_ec_key *key; int res; u8 hash[SAE_MAX_HASH_LEN]; size_t hash_len; int group; + struct ieee802_11_elems elems; if (!tmp) return -1; @@ -597,71 +593,29 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) } wpa_hexdump(MSG_DEBUG, "SAE-PK: Received confirm IEs", ies, ies_len); - sae_pk = get_vendor_ie(ies, ies_len, SAE_PK_IE_VENDOR_TYPE); - if (!sae_pk) { - wpa_printf(MSG_INFO, "SAE-PK: No SAE-PK element included"); + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + wpa_printf(MSG_INFO, "SAE-PK: Failed to parse confirm IEs"); + return -1; + } + if (!elems.fils_pk || !elems.fils_key_confirm || !elems.sae_pk) { + wpa_printf(MSG_INFO, + "SAE-PK: Not all mandatory IEs included in confirm"); return -1; } - /* TODO: Fragment reassembly */ - pos = sae_pk + 2; - end = pos + sae_pk[1]; - if (end - pos < 4 + 1 + SAE_PK_M_LEN + AES_BLOCK_SIZE) { + /* TODO: Fragment reassembly */ + + if (elems.sae_pk_len < SAE_PK_M_LEN + AES_BLOCK_SIZE) { wpa_printf(MSG_INFO, "SAE-PK: No room for EncryptedModifier in SAE-PK element"); return -1; } - pos += 4; - if (*pos != SAE_PK_M_LEN + AES_BLOCK_SIZE) { - wpa_printf(MSG_INFO, - "SAE-PK: Unexpected EncryptedModifier length %u", - *pos); - return -1; - } - pos++; - encr_mod = pos; - pos += SAE_PK_M_LEN + AES_BLOCK_SIZE; - - if (end - pos < 4 || pos[0] != WLAN_EID_EXTENSION || pos[1] < 2 || - pos[1] > end - pos - 2 || - pos[2] != WLAN_EID_EXT_FILS_PUBLIC_KEY) { - wpa_printf(MSG_INFO, - "SAE-PK: No FILS Public Key element in SAE-PK element"); - return -1; - } - if (pos[3] != 2) { - wpa_printf(MSG_INFO, "SAE-PK: Unsupported public key type %u", - pos[3]); - return -1; - } - k_ap_len = pos[1] - 2; - pos += 4; - k_ap = pos; - pos += k_ap_len; - - if (end - pos < 4 || pos[0] != WLAN_EID_EXTENSION || pos[1] < 1 || - pos[1] > end - pos - 2 || - pos[2] != WLAN_EID_EXT_FILS_KEY_CONFIRM) { - wpa_printf(MSG_INFO, - "SAE-PK: No FILS Key Confirm element in SAE-PK element"); - return -1; - } - key_auth_len = pos[1] - 1; - pos += 3; - key_auth = pos; - pos += key_auth_len; - - if (pos < end) { - wpa_hexdump(MSG_DEBUG, - "SAE-PK: Extra data at the end of SAE-PK element", - pos, end - pos); - } wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier", - encr_mod, SAE_PK_M_LEN + AES_BLOCK_SIZE); + elems.sae_pk, SAE_PK_M_LEN + AES_BLOCK_SIZE); if (aes_siv_decrypt(tmp->kek, tmp->kek_len, - encr_mod, SAE_PK_M_LEN + AES_BLOCK_SIZE, + elems.sae_pk, SAE_PK_M_LEN + AES_BLOCK_SIZE, 0, NULL, NULL, m) < 0) { wpa_printf(MSG_INFO, "SAE-PK: Failed to decrypt EncryptedModifier"); @@ -669,6 +623,13 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) } wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Modifier M", m, SAE_PK_M_LEN); + if (elems.fils_pk[0] != 2) { + wpa_printf(MSG_INFO, "SAE-PK: Unsupported public key type %u", + elems.fils_pk[0]); + return -1; + } + k_ap_len = elems.fils_pk_len - 1; + k_ap = elems.fils_pk + 1; wpa_hexdump(MSG_DEBUG, "SAE-PK: Received K_AP", k_ap, k_ap_len); /* TODO: Check against the public key, if one is stored in the network * profile */ @@ -687,7 +648,7 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) } wpa_hexdump(MSG_DEBUG, "SAE-PK: Received KeyAuth", - key_auth, key_auth_len); + elems.fils_key_confirm, elems.fils_key_confirm_len); hash_len = sae_group_2_hash_len(group); if (sae_pk_hash_sig_data(sae, hash_len, false, m, SAE_PK_M_LEN, @@ -697,7 +658,8 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) } res = crypto_ec_key_verify_signature(key, hash, hash_len, - key_auth, key_auth_len); + elems.fils_key_confirm, + elems.fils_key_confirm_len); crypto_ec_key_deinit(key); if (res != 1) { From de36f6b7b31c5515ab2885ccfdafd0bcebeff9ab Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 10 Jun 2020 01:04:11 +0300 Subject: [PATCH 0662/1105] tests: SAE-PK with group 21 Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 9f544be04..311acc3c7 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -18,6 +18,10 @@ SAE_PK_20_PW = "f3bh-5un3-wz7o-al3p" SAE_PK_20_M = "50bf37ba0033ed110a74e3a7aa52f4e9" SAE_PK_20_PK = "MIGkAgEBBDA4wpA6w/fK0g3a2V6QmcoxNoFCVuQPyzWvKYimJkgXsVsXt2ERXQ7dGOVXeycM5DqgBwYFK4EEACKhZANiAARTdszGBNe2PGCnc8Wvs+IDvdVEf4PPBrty0meRZf6UTbGouquTHpy6KKTq5sxrulYzsQFimg4op0UJBGxAzqo0EtTgMlLiBvY0I3Nl3N69MhWo8nvnmguvGGN32AAPXpQ=" +SAE_PK_21_PW = "a5rp-4rgd-ewum-v4qr-v5jy" +SAE_PK_21_M = "2bf0a143b158b967a435cf75b07fc9e6" +SAE_PK_21_PK = "MIHcAgEBBEIBcch+ygKv1uL5344C+8Rt5h8cTYHG++L3/8/hH6I2J3pWboB0jtzTf/zdZVGqkEIi+zZ2O+5g65cS8my1B44n0g+gBwYFK4EEACOhgYkDgYYABAA49TXDQfBgQWuwGrvYSkw9yuLRTn7WKyWcfSqSFfJYY6piGRE0wdKsNsGbuqHsfjn3Jb3LhmPdcnaDXd5z7fhdgAGFaiL+ZtBJCw5LqjW71rb54oy1NookDiNILdZ9i1dwBzE3fpfOWVvfjnXj9weZKUWHLB+2RF2X1qB0mY/G5NuRXA==" + def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None): params = hostapd.wpa2_params(ssid=ssid) params['wpa_key_mgmt'] = 'SAE' @@ -117,6 +121,18 @@ def test_sae_pk_group_20(dev, apdev): finally: dev[0].set("sae_groups", "") +def test_sae_pk_group_21(dev, apdev): + """SAE-PK with group 21""" + check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() + dev[0].set("sae_groups", "21") + + try: + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_21_PW, + SAE_PK_21_M, SAE_PK_21_PK, ap_groups="21") + finally: + dev[0].set("sae_groups", "") + def test_sae_pk_group_20_sae_group_19(dev, apdev): """SAE-PK with group 20 with SAE group 19""" check_sae_pk_capab(dev[0]) From 518be614f1a506637aa4b9ead44e14daa89d4d24 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 10 Jun 2020 12:22:59 +0300 Subject: [PATCH 0663/1105] SAE-PK: Advertise RSNXE capability bit in STA mode Set the SAE-PK capability bit in RSNXE when sending out (Re)Association Request frame for a network profile that allows use of SAE-PK. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 3 +++ src/rsn_supp/wpa.h | 1 + src/rsn_supp/wpa_i.h | 1 + src/rsn_supp/wpa_ie.c | 9 +++++++-- wpa_supplicant/wpa_supplicant.c | 7 +++++++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 0ae73e8f3..63171021f 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3289,6 +3289,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_SAE_PWE: sm->sae_pwe = value; break; + case WPA_PARAM_SAE_PK: + sm->sae_pk = value; + break; case WPA_PARAM_DENY_PTK0_REKEY: sm->wpa_deny_ptk0_rekey = value; break; diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index a4512eadc..36a17df3d 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -103,6 +103,7 @@ enum wpa_sm_conf_params { WPA_PARAM_MFP, WPA_PARAM_OCV, WPA_PARAM_SAE_PWE, + WPA_PARAM_SAE_PK, WPA_PARAM_DENY_PTK0_REKEY, WPA_PARAM_EXT_KEY_ID, WPA_PARAM_USE_EXT_KEY_ID, diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index b2b43f4f0..8d7a7a93a 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -95,6 +95,7 @@ struct wpa_sm { int mfp; /* 0 = disabled, 1 = optional, 2 = mandatory */ int ocv; /* Operating Channel Validation */ int sae_pwe; /* SAE PWE generation options */ + int sae_pk; /* whether SAE-PK is used */ u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */ size_t assoc_wpa_ie_len; diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 9068781b1..20fdd6987 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -357,7 +357,7 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len) if (!wpa_key_mgmt_sae(sm->key_mgmt)) return 0; /* SAE not in use */ - if (sm->sae_pwe != 1 && sm->sae_pwe != 2) + if (sm->sae_pwe != 1 && sm->sae_pwe != 2 && !sm->sae_pk) return 0; /* no supported extended RSN capabilities */ if (rsnxe_len < 3) @@ -367,7 +367,12 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len) *pos++ = 1; /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is * used for now */ - *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E); + *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E); +#ifdef CONFIG_SAE_PK + if (sm->sae_pk) + *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK); +#endif /* CONFIG_SAE_PK */ + pos++; return pos - rsnxe; } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index f5a4c360b..4c1daf1fa 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1639,6 +1639,13 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, if (ssid->sae_password_id && sae_pwe != 3) sae_pwe = 1; wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe); +#ifdef CONFIG_SAE_PK + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK, + wpa_key_mgmt_sae(ssid->key_mgmt) && + ssid->sae_pk != SAE_PK_MODE_DISABLED && + ssid->sae_password && + sae_pk_valid_password(ssid->sae_password)); +#endif /* CONFIG_SAE_PK */ #ifdef CONFIG_TESTING_OPTIONS wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED, wpa_s->ft_rsnxe_used); From db294952bb7bc9cda6ef5ef6656449296abf944b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 28 May 2020 19:52:30 +0200 Subject: [PATCH 0664/1105] tests: Set VHT160 or VHT160-80PLUS80 capability If we want the test to actually use 160/80+80 we need to explicitly advertise that we support it ourselves, since the kernel is going to be a bit more strict about this. Signed-off-by: Johannes Berg --- tests/hwsim/test_ap_tdls.py | 4 +++- tests/hwsim/test_ap_vht.py | 5 +++++ tests/hwsim/test_he.py | 5 +++++ tests/hwsim/test_ocv.py | 2 ++ tests/hwsim/test_rrm.py | 1 + 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_tdls.py b/tests/hwsim/test_ap_tdls.py index 05c4ca3e4..ea14a08b2 100644 --- a/tests/hwsim/test_ap_tdls.py +++ b/tests/hwsim/test_ap_tdls.py @@ -413,6 +413,7 @@ def test_ap_open_tdls_vht80(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_capab": "", @@ -452,7 +453,7 @@ def test_ap_open_tdls_vht80plus80(dev, apdev): "ht_capab": "[HT40+]", "ieee80211n": "1", "ieee80211ac": "1", - "vht_capab": "", + "vht_capab": "[VHT160-80PLUS80]", "vht_oper_chwidth": "3", "vht_oper_centr_freq_seg0_idx": "42", "vht_oper_centr_freq_seg1_idx": "155"} @@ -494,6 +495,7 @@ def test_ap_open_tdls_vht160(dev, apdev): "hw_mode": "a", "channel": "104", "ht_capab": "[HT40-]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 358e192de..8ffa81895 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -361,6 +361,7 @@ def test_ap_vht160(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -436,6 +437,7 @@ def test_ap_vht160b(dev, apdev): "hw_mode": "a", "channel": "104", "ht_capab": "[HT40-]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -538,6 +540,7 @@ def run_ap_vht160_no_dfs(dev, apdev, channel, ht_capab): "hw_mode": "a", "channel": channel, "ht_capab": ht_capab, + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -616,6 +619,7 @@ def test_ap_vht80plus80(dev, apdev): "hw_mode": "a", "channel": "52", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "3", @@ -633,6 +637,7 @@ def test_ap_vht80plus80(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "3", diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index ce3199290..f033285a6 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -428,6 +428,7 @@ def test_he160(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -500,6 +501,7 @@ def test_he160b(dev, apdev): "hw_mode": "a", "channel": "104", "ht_capab": "[HT40-]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -605,6 +607,7 @@ def run_ap_he160_no_dfs(dev, apdev, channel, ht_capab): "hw_mode": "a", "channel": channel, "ht_capab": ht_capab, + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -689,6 +692,7 @@ def test_he80plus80(dev, apdev): "hw_mode": "a", "channel": "52", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -710,6 +714,7 @@ def test_he80plus80(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py index bfefcf6b5..fc939ff33 100644 --- a/tests/hwsim/test_ocv.py +++ b/tests/hwsim/test_ocv.py @@ -259,6 +259,7 @@ def run_wpa2_ocv_vht160(dev, apdev): "channel": channel, "country_code": "ZA", "ht_capab": capab, + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -301,6 +302,7 @@ def run_wpa2_ocv_vht80plus80(dev, apdev): "channel": channel, "country_code": "US", "ht_capab": capab, + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "3", diff --git a/tests/hwsim/test_rrm.py b/tests/hwsim/test_rrm.py index 2b43c4c59..b9de82de5 100644 --- a/tests/hwsim/test_rrm.py +++ b/tests/hwsim/test_rrm.py @@ -1729,6 +1729,7 @@ def test_rrm_beacon_req_passive_scan_vht160(dev, apdev): "hw_mode": "a", "channel": "104", "ht_capab": "[HT40-]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", From 4dd712bd36a761c0db96dab0fe8d2ce422072ba0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 28 May 2020 19:52:39 +0200 Subject: [PATCH 0665/1105] tests: Use bytes in a few places With python3 bytes are returned for stdout, so need to use b'' strings instead of normal strings. These are just a few places I ran into, almost certainly more places need it. Signed-off-by: Johannes Berg --- tests/hwsim/test_ap_vht.py | 2 +- tests/hwsim/test_he.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 8ffa81895..2b691ff71 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -553,7 +553,7 @@ def run_ap_vht160_no_dfs(dev, apdev, channel, ht_capab): cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) reg = cmd.stdout.readlines() for r in reg: - if "5490" in r and "DFS" in r: + if b"5490" in r and b"DFS" in r: raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed") raise Exception("AP setup timed out") diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index f033285a6..28123e853 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -623,7 +623,7 @@ def run_ap_he160_no_dfs(dev, apdev, channel, ht_capab): cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) reg = cmd.stdout.readlines() for r in reg: - if "5490" in r and "DFS" in r: + if b"5490" in r and b"DFS" in r: raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed") raise Exception("AP setup timed out") From 2f9e2f9044fbb6649eb69defff4fcdf55f4efa71 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 31 May 2020 11:40:32 +0200 Subject: [PATCH 0666/1105] tests: Check for mac80211_hwsim module before loading it Instead of checking if the kernel allows modules (via the presence of /proc/modules), check if mac80211_hwsim is already there and load it only if not. This gets rid of some ugly prints from modprobe in case code isn't even a module and cannot be found, etc. Signed-off-by: Johannes Berg --- tests/hwsim/start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/start.sh b/tests/hwsim/start.sh index 7a26d2825..ac43d10af 100755 --- a/tests/hwsim/start.sh +++ b/tests/hwsim/start.sh @@ -110,7 +110,7 @@ else NUM_CH=1 fi -test -f /proc/modules && sudo modprobe mac80211_hwsim radios=7 channels=$NUM_CH support_p2p_device=0 dyndbg=+p +test -d /sys/module/mac80211_hwsim || sudo modprobe mac80211_hwsim radios=7 channels=$NUM_CH support_p2p_device=0 dyndbg=+p sudo ifconfig hwsim0 up sudo $WLANTEST -i hwsim0 -n $LOGDIR/hwsim0.pcapng -c -dtN -L $LOGDIR/hwsim0 & From ddd821365a187001555fe572e9910e9975bedeec Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Mon, 8 Jun 2020 16:47:53 -0700 Subject: [PATCH 0667/1105] tests: Skip malformed SAE authentication frames The parsed 'length' field might pointsbeyond the end of the frame, for some malformed frames. I haven't figured the source of said packets (I'm using kernel 4.14.177, FWIW), but we can at least be safer about our handling of them here. Signed-off-by: Brian Norris --- tests/hwsim/test_sae.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index ed6ae89dc..3722cd427 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -1788,8 +1788,10 @@ def build_sae_commit(bssid, addr, group=21, token=None): def sae_rx_commit_token_req(sock, radiotap, send_two=False): msg = sock.recv(1500) - ver, pad, len, present = struct.unpack(' Date: Mon, 8 Jun 2020 16:47:54 -0700 Subject: [PATCH 0668/1105] tests: Add all-blacklist test Signed-off-by: Brian Norris --- tests/hwsim/test_ap_roam.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/hwsim/test_ap_roam.py b/tests/hwsim/test_ap_roam.py index 9047c7a80..50b4c7248 100644 --- a/tests/hwsim/test_ap_roam.py +++ b/tests/hwsim/test_ap_roam.py @@ -26,6 +26,35 @@ def test_ap_roam_open(dev, apdev): dev[0].roam(apdev[0]['bssid']) hwsim_utils.test_connectivity(dev[0], hapd0) +def test_ap_blacklist_all(dev, apdev, params): + """Ensure we clear the blacklist if all visible APs reject""" + hapd0 = hostapd.add_ap(apdev[0], {"ssid": "test-open", "max_num_sta": "0"}) + hapd1 = hostapd.add_ap(apdev[1], {"ssid": "test-open", "max_num_sta": "0"}) + bss0 = hapd0.own_addr() + bss1 = hapd1.own_addr() + + dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412", + wait_connect=False, bssid=bss0) + if not dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10): + raise Exception("AP 0 didn't reject us") + dev[0].request("REMOVE_NETWORK all") + dev[0].dump_monitor() + dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412", + wait_connect=False, bssid=bss1) + if not dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10): + raise Exception("AP 1 didn't reject us") + blacklist = get_blacklist(dev[0]) + if len(blacklist) != 2: + raise Exception("Unexpected blacklist: %s" % blacklist) + dev[0].request("REMOVE_NETWORK all") + dev[0].dump_monitor() + + hapd0.set("max_num_sta", "1") + # All visible APs were blacklisted; we should clear the blacklist and find + # the AP that now accepts us. + dev[0].scan_for_bss(bss0, freq=2412) + dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412", bssid=bss0) + @remote_compatible def test_ap_roam_open_failed(dev, apdev): """Roam failure due to rejected authentication""" From f25c51a9f4b4eabc292f6805b6fc1b31446d60c7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 10 Jun 2020 18:29:03 +0300 Subject: [PATCH 0669/1105] Sync with mac80211-next.git include/uapi/linux/nl80211.h This brings in nl80211 definitions as of 2020-05-31. Signed-off-by: Jouni Malinen --- src/drivers/nl80211_copy.h | 126 +++++++++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 26 deletions(-) diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index 9679d561f..dad8c8f85 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -296,13 +296,14 @@ * to get a list of all present wiphys. * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the - * attributes determining the channel width; this is used for setting - * monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT, - * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. - * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL - * instead, the support here is for backward compatibility only. + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_FREQ_OFFSET (and the attributes determining the + * channel width; this is used for setting monitor mode channel), + * %NL80211_ATTR_WIPHY_RETRY_SHORT, %NL80211_ATTR_WIPHY_RETRY_LONG, + * %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, and/or + * %NL80211_ATTR_WIPHY_RTS_THRESHOLD. However, for setting the channel, + * see %NL80211_CMD_SET_CHANNEL instead, the support here is for backward + * compatibility only. * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request * or rename notification. Has attributes %NL80211_ATTR_WIPHY and * %NL80211_ATTR_WIPHY_NAME. @@ -351,7 +352,8 @@ * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT, * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. * The channel to use can be set on the interface or be given using the - * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. + * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_WIPHY_FREQ_OFFSET, and the + * attributes determining channel width. * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP @@ -536,11 +538,12 @@ * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify * the SSID (mainly for association, but is included in authentication - * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used - * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE - * is used to specify the authentication type. %NL80211_ATTR_IE is used to - * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) - * to be added to the frame. + * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ + + * %NL80211_ATTR_WIPHY_FREQ_OFFSET is used to specify the frequence of the + * channel in MHz. %NL80211_ATTR_AUTH_TYPE is used to specify the + * authentication type. %NL80211_ATTR_IE is used to define IEs + * (VendorSpecificInfo, but also including RSN IE and FT IEs) to be added + * to the frame. * When used as an event, this reports reception of an Authentication * frame in station and IBSS modes when the local MLME processed the * frame, i.e., it was for the local STA and was received in correct @@ -595,8 +598,9 @@ * requests to connect to a specified network but without separating * auth and assoc steps. For this, you need to specify the SSID in a * %NL80211_ATTR_SSID attribute, and can optionally specify the association - * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, - * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, + * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, + * %NL80211_ATTR_USE_MFP, %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_FREQ_OFFSET, %NL80211_ATTR_CONTROL_PORT, * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, * %NL80211_ATTR_CONTROL_PORT_OVER_NL80211, %NL80211_ATTR_MAC_HINT, and @@ -1160,6 +1164,12 @@ * dropped because it did not include a valid MME MIC while beacon * protection was enabled (BIGTK configured in station mode). * + * @NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS: Report TX status of a control + * port frame transmitted with %NL80211_CMD_CONTROL_PORT_FRAME. + * %NL80211_ATTR_COOKIE identifies the TX command and %NL80211_ATTR_FRAME + * includes the contents of the frame. %NL80211_ATTR_ACK flag is included + * if the recipient acknowledged the frame. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1388,6 +1398,8 @@ enum nl80211_commands { NL80211_CMD_UNPROT_BEACON, + NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1433,7 +1445,8 @@ enum nl80211_commands { * of &enum nl80211_chan_width, describing the channel width. See the * documentation of the enum for more information. * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the - * channel, used for anything but 20 MHz bandwidth + * channel, used for anything but 20 MHz bandwidth. In S1G this is the + * operating channel center frequency. * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the * channel, used only for 80+80 MHz bandwidth * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ @@ -2480,9 +2493,17 @@ enum nl80211_commands { * entry without having to force a disconnection after the PMK timeout. If * no roaming occurs between the reauth threshold and PMK expiration, * disassociation is still forced. - * * @NL80211_ATTR_RECEIVE_MULTICAST: multicast flag for the * %NL80211_CMD_REGISTER_FRAME command, see the description there. + * @NL80211_ATTR_WIPHY_FREQ_OFFSET: offset of the associated + * %NL80211_ATTR_WIPHY_FREQ in positive KHz. Only valid when supplied with + * an %NL80211_ATTR_WIPHY_FREQ_OFFSET. + * @NL80211_ATTR_CENTER_FREQ1_OFFSET: Center frequency offset in KHz for the + * first channel segment specified in %NL80211_ATTR_CENTER_FREQ1. + * @NL80211_ATTR_SCAN_FREQ_KHZ: nested attribute with KHz frequencies + * + * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from + * association request when used with NL80211_CMD_NEW_STATION). * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined @@ -2960,6 +2981,11 @@ enum nl80211_attrs { NL80211_ATTR_PMK_REAUTH_THRESHOLD, NL80211_ATTR_RECEIVE_MULTICAST, + NL80211_ATTR_WIPHY_FREQ_OFFSET, + NL80211_ATTR_CENTER_FREQ1_OFFSET, + NL80211_ATTR_SCAN_FREQ_KHZ, + + NL80211_ATTR_HE_6GHZ_CAPABILITY, /* add attributes here, update the policy in nl80211.c */ @@ -3539,6 +3565,8 @@ enum nl80211_mpath_info { * defined in HE capabilities IE * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently * defined + * @NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA: HE 6GHz band capabilities (__le16), + * given for all 6 GHz band channels * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use */ enum nl80211_band_iftype_attr { @@ -3549,6 +3577,7 @@ enum nl80211_band_iftype_attr { NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, + NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, /* keep last */ __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, @@ -3682,6 +3711,7 @@ enum nl80211_wmm_rule { * (see &enum nl80211_wmm_rule) * @NL80211_FREQUENCY_ATTR_NO_HE: HE operation is not allowed on this channel * in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_OFFSET: frequency offset in KHz * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number * currently defined * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use @@ -3712,6 +3742,7 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_NO_10MHZ, NL80211_FREQUENCY_ATTR_WMM, NL80211_FREQUENCY_ATTR_NO_HE, + NL80211_FREQUENCY_ATTR_OFFSET, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, @@ -4482,6 +4513,7 @@ enum nl80211_bss_scan_width { * @NL80211_BSS_CHAIN_SIGNAL: per-chain signal strength of last BSS update. * Contains a nested array of signal strength attributes (u8, dBm), * using the nesting index as the antenna number. + * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz * @__NL80211_BSS_AFTER_LAST: internal * @NL80211_BSS_MAX: highest BSS attribute */ @@ -4506,6 +4538,7 @@ enum nl80211_bss { NL80211_BSS_PARENT_TSF, NL80211_BSS_PARENT_BSSID, NL80211_BSS_CHAIN_SIGNAL, + NL80211_BSS_FREQUENCY_OFFSET, /* keep last */ __NL80211_BSS_AFTER_LAST, @@ -4816,6 +4849,17 @@ enum nl80211_tid_config { NL80211_TID_CONFIG_DISABLE, }; +/* enum nl80211_tx_rate_setting - TX rate configuration type + * @NL80211_TX_RATE_AUTOMATIC: automatically determine TX rate + * @NL80211_TX_RATE_LIMITED: limit the TX rate by the TX rate parameter + * @NL80211_TX_RATE_FIXED: fix TX rate to the TX rate parameter + */ +enum nl80211_tx_rate_setting { + NL80211_TX_RATE_AUTOMATIC, + NL80211_TX_RATE_LIMITED, + NL80211_TX_RATE_FIXED, +}; + /* enum nl80211_tid_config_attr - TID specific configuration. * @NL80211_TID_CONFIG_ATTR_PAD: pad attribute for 64-bit values * @NL80211_TID_CONFIG_ATTR_VIF_SUPP: a bitmap (u64) of attributes supported @@ -4823,12 +4867,10 @@ enum nl80211_tid_config { * (%NL80211_TID_CONFIG_ATTR_TIDS, %NL80211_TID_CONFIG_ATTR_OVERRIDE). * @NL80211_TID_CONFIG_ATTR_PEER_SUPP: same as the previous per-vif one, but * per peer instead. - * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribue, if no peer - * is selected, if set indicates that the new configuration overrides - * all previous peer configurations, otherwise previous peer specific - * configurations should be left untouched. If peer is selected then - * it will reset particular TID configuration of that peer and it will - * not accept other TID config attributes along with peer. + * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribue, if set indicates + * that the new configuration overrides all previous peer + * configurations, otherwise previous peer specific configurations + * should be left untouched. * @NL80211_TID_CONFIG_ATTR_TIDS: a bitmask value of TIDs (bit 0 to 7) * Its type is u16. * @NL80211_TID_CONFIG_ATTR_NOACK: Configure ack policy for the TID. @@ -4844,12 +4886,23 @@ enum nl80211_tid_config { * &NL80211_CMD_SET_TID_CONFIG. Its type is u8, min value is 1 and * the max value is advertised by the driver in this attribute on * output in wiphy capabilities. - * @NL80211_TID_CONFIG_ATTR_AMPDU_CTRL: Enable/Disable aggregation for the TIDs - * specified in %NL80211_TID_CONFIG_ATTR_TIDS. Its type is u8, using - * the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_AMPDU_CTRL: Enable/Disable MPDU aggregation + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. + * Its type is u8, using the values from &nl80211_tid_config. * @NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL: Enable/Disable RTS_CTS for the TIDs * specified in %NL80211_TID_CONFIG_ATTR_TIDS. It is u8 type, using * the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_AMSDU_CTRL: Enable/Disable MSDU aggregation + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. + * Its type is u8, using the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE: This attribute will be useful + * to notfiy the driver that what type of txrate should be used + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. using + * the values form &nl80211_tx_rate_setting. + * @NL80211_TID_CONFIG_ATTR_TX_RATE: Data frame TX rate mask should be applied + * with the parameters passed through %NL80211_ATTR_TX_RATES. + * configuration is applied to the data frame for the tid to that connected + * station. */ enum nl80211_tid_config_attr { __NL80211_TID_CONFIG_ATTR_INVALID, @@ -4863,6 +4916,9 @@ enum nl80211_tid_config_attr { NL80211_TID_CONFIG_ATTR_RETRY_LONG, NL80211_TID_CONFIG_ATTR_AMPDU_CTRL, NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL, + NL80211_TID_CONFIG_ATTR_AMSDU_CTRL, + NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, + NL80211_TID_CONFIG_ATTR_TX_RATE, /* keep last */ __NL80211_TID_CONFIG_ATTR_AFTER_LAST, @@ -5340,6 +5396,8 @@ enum plink_actions { #define NL80211_KCK_LEN 16 #define NL80211_KEK_LEN 16 +#define NL80211_KCK_EXT_LEN 24 +#define NL80211_KEK_EXT_LEN 32 #define NL80211_REPLAY_CTR_LEN 8 /** @@ -5348,6 +5406,7 @@ enum plink_actions { * @NL80211_REKEY_DATA_KEK: key encryption key (binary) * @NL80211_REKEY_DATA_KCK: key confirmation key (binary) * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary) + * @NL80211_REKEY_DATA_AKM: AKM data (OUI, suite type) * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal) * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal) */ @@ -5356,6 +5415,7 @@ enum nl80211_rekey_data { NL80211_REKEY_DATA_KEK, NL80211_REKEY_DATA_KCK, NL80211_REKEY_DATA_REPLAY_CTR, + NL80211_REKEY_DATA_AKM, /* keep last */ NUM_NL80211_REKEY_DATA, @@ -5705,6 +5765,14 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS: management frame registrations * are possible for multicast frames and those will be reported properly. * + * @NL80211_EXT_FEATURE_SCAN_FREQ_KHZ: This driver supports receiving and + * reporting scan request with %NL80211_ATTR_SCAN_FREQ_KHZ. In order to + * report %NL80211_ATTR_SCAN_FREQ_KHZ, %NL80211_SCAN_FLAG_FREQ_KHZ must be + * included in the scan request. + * + * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS: The driver + * can report tx status for control port over nl80211 tx operations. + * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ @@ -5758,6 +5826,8 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_DEL_IBSS_STA, NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS, NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT, + NL80211_EXT_FEATURE_SCAN_FREQ_KHZ, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, @@ -5869,6 +5939,9 @@ enum nl80211_timeout_reason { * @NL80211_SCAN_FLAG_MIN_PREQ_CONTENT: minimize probe request content to * only have supported rates and no additional capabilities (unless * added by userspace explicitly.) + * @NL80211_SCAN_FLAG_FREQ_KHZ: report scan results with + * %NL80211_ATTR_SCAN_FREQ_KHZ. This also means + * %NL80211_ATTR_SCAN_FREQUENCIES will not be included. */ enum nl80211_scan_flags { NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, @@ -5884,6 +5957,7 @@ enum nl80211_scan_flags { NL80211_SCAN_FLAG_HIGH_ACCURACY = 1<<10, NL80211_SCAN_FLAG_RANDOM_SN = 1<<11, NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12, + NL80211_SCAN_FLAG_FREQ_KHZ = 1<<13, }; /** From 9272ebae83e6caf087fa9ec72b459f997ca60331 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 1 Jun 2020 23:14:24 -0700 Subject: [PATCH 0670/1105] nl80211: Fetch HE 6 GHz capability from the driver Read mode specific HE 6 GHz capability from phy info. This is needed for futher user config validation and IE construction. Signed-off-by: Rajkumar Manoharan --- src/drivers/driver.h | 1 + src/drivers/driver_nl80211_capa.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 350c1cb57..0ecda49dd 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -197,6 +197,7 @@ struct he_capabilities { u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE]; u8 mcs[HE_MAX_MCS_CAPAB_SIZE]; u8 ppet[HE_MAX_PPET_CAPAB_SIZE]; + u16 he_6ghz_capa; }; #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 3e8dcef2a..b9eb6e220 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1790,6 +1790,13 @@ static void phy_info_iftype_copy(struct he_capabilities *he_capab, nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]), len); } + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA]) { + u16 capa; + + capa = nla_get_u16(tb[NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA]); + he_capab->he_6ghz_capa = le_to_host16(capa); + } } From 6a34bd30077912075d440325872ac8089f0067f1 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 1 Jun 2020 23:14:25 -0700 Subject: [PATCH 0671/1105] HE: Use device HE capability instead of HT/VHT for 6 GHz IEs Previously, 6 GHz Band Capability element was derived from HT and VHT capabilities of the device. Removes such unnecessary dependency by relying directly on the HE capability. In addition, clean up the struct ieee80211_he_6ghz_band_cap definition to use a 16-bit little endian field instead of two 8-bit fields to match the definition in P802.11ax. Signed-off-by: Rajkumar Manoharan --- src/ap/ieee802_11_he.c | 35 ++++++++-------------------------- src/common/ieee802_11_defs.h | 37 +++++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 42 deletions(-) diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index f1f2442fc..85b714090 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -314,45 +314,26 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid) u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid) { struct hostapd_hw_modes *mode = hapd->iface->current_mode; + struct he_capabilities *he_cap; struct ieee80211_he_6ghz_band_cap *cap; - u32 vht_cap; - u8 ht_info; - u8 params; + u16 capab; u8 *pos; - if (!mode || !is_6ghz_op_class(hapd->iconf->op_class)) + if (!mode || !is_6ghz_op_class(hapd->iconf->op_class) || + !is_6ghz_freq(hapd->iface->freq)) return eid; - vht_cap = hapd->iface->conf->vht_capab; - ht_info = mode->a_mpdu_params; + he_cap = &mode->he_capab[IEEE80211_MODE_AP]; + capab = he_cap->he_6ghz_capa; + capab |= HE_6GHZ_BAND_CAP_SMPS_DISABLED; pos = eid; *pos++ = WLAN_EID_EXTENSION; *pos++ = 1 + sizeof(*cap); *pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP; - /* Minimum MPDU Start Spacing B0..B2 */ - params = (ht_info >> 2) & HE_6GHZ_BAND_CAP_MIN_MPDU_START_SPACE_MASK; - - /* Maximum A-MPDU Length Exponent B3..B5 */ - params |= ((((vht_cap & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >> - VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT) & - HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) << - HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT); - - /* Maximum MPDU Length B6..B7 */ - params |= ((((vht_cap & VHT_CAP_MAX_MPDU_LENGTH_MASK) >> - VHT_CAP_MAX_MPDU_LENGTH_MASK_SHIFT) & - HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_MASK) << - HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_SHIFT); - cap = (struct ieee80211_he_6ghz_band_cap *) pos; - cap->a_mpdu_params = params; - cap->info = HE_6GHZ_BAND_CAP_SMPS_DISABLED; - if (vht_cap & VHT_CAP_RX_ANTENNA_PATTERN) - cap->info |= HE_6GHZ_BAND_CAP_RX_ANTENNA_PATTERN; - if (vht_cap & VHT_CAP_TX_ANTENNA_PATTERN) - cap->info |= HE_6GHZ_BAND_CAP_TX_ANTENNA_PATTERN; + cap->capab = host_to_le16(capab); pos += sizeof(*cap); return pos; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index b7c69478d..da0e7bdcf 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2173,23 +2173,30 @@ struct ieee80211_he_6ghz_band_cap { /* Minimum MPDU Start Spacing B0..B2 * Maximum A-MPDU Length Exponent B3..B5 * Maximum MPDU Length B6..B7 */ - u8 a_mpdu_params; /* B0..B7 */ - u8 info; /* B8..B15 */ + le16 capab; } STRUCT_PACKED; -#define HE_6GHZ_BAND_CAP_MIN_MPDU_START_SPACE_MASK 0x7 -#define HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK 0x7 -#define HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 3 -#define HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_MASK 0x3 -#define HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_SHIFT 6 - -#define HE_6GHZ_BAND_CAP_SMPS_MASK (BIT(1) | BIT(2)) -#define HE_6GHZ_BAND_CAP_SMPS_STATIC 0 -#define HE_6GHZ_BAND_CAP_SMPS_DYNAMIC BIT(1) -#define HE_6GHZ_BAND_CAP_SMPS_DISABLED (BIT(1) | BIT(2)) -#define HE_6GHZ_BAND_CAP_RD_RESPONDER BIT(3) -#define HE_6GHZ_BAND_CAP_RX_ANTENNA_PATTERN BIT(4) -#define HE_6GHZ_BAND_CAP_TX_ANTENNA_PATTERN BIT(5) +#define HE_6GHZ_BAND_CAP_MIN_MPDU_START (BIT(0) | BIT(1) | BIT(2)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_16K BIT(3) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_32K BIT(4) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_64K (BIT(3) | BIT(4)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_128K BIT(5) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_256K (BIT(3) | BIT(5)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_512K (BIT(4) | BIT(5)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_1024K (BIT(3) | BIT(4) | BIT(5)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK (BIT(3) | BIT(4) | BIT(5)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT 3 +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_7991 BIT(6) +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_11454 BIT(7) +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK (BIT(6) | BIT(7)) +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT 6 +#define HE_6GHZ_BAND_CAP_SMPS_MASK (BIT(9) | BIT(10)) +#define HE_6GHZ_BAND_CAP_SMPS_STATIC 0 +#define HE_6GHZ_BAND_CAP_SMPS_DYNAMIC BIT(9) +#define HE_6GHZ_BAND_CAP_SMPS_DISABLED (BIT(9) | BIT(10)) +#define HE_6GHZ_BAND_CAP_RD_RESPONDER BIT(11) +#define HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS BIT(12) +#define HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS BIT(13) /* * IEEE P802.11ax/D4.0, 9.4.2.246 Spatial Reuse Parameter Set element From 088bef178656c97d096e503382f64ff13a041067 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 1 Jun 2020 23:14:27 -0700 Subject: [PATCH 0672/1105] AP: Restrict Vendor VHT to 2.4 GHz only Vendor VHT IE is used only on the 2.4 GHz band. Restrict the use of vendor VHT element to 2.4 GHz. This will ensure that invalid/wrong user configuration will not impact beacon data in other than the 2.4 GHz band. Signed-off-by: Rajkumar Manoharan --- src/ap/ieee802_11_vht.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index f50f142dc..425b192e1 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -425,7 +425,9 @@ u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid) { u8 *pos = eid; - if (!hapd->iface->current_mode) + /* Vendor VHT is applicable only to 2.4 GHz */ + if (!hapd->iface->current_mode || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) return eid; *pos++ = WLAN_EID_VENDOR_SPECIFIC; From 1f72bbbefb5d7aed5636415b6edbfde4d15fff9d Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 1 Jun 2020 23:14:28 -0700 Subject: [PATCH 0673/1105] AP: Reject association request upon invalid HE capabilities Operation in the 6 GHz band mandates valid HE capabilities element in station negotiation. Reject association request upon receiving invalid or missing HE elements. Signed-off-by: Rajkumar Manoharan --- src/ap/ieee802_11.c | 7 +++++++ src/common/ieee802_11_common.c | 1 + src/common/ieee802_11_defs.h | 1 + 3 files changed, 9 insertions(+) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 6723f33dd..4f4e548c8 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3230,6 +3230,13 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (resp != WLAN_STATUS_SUCCESS) return resp; if (is_6ghz_op_class(hapd->iconf->op_class)) { + if (!(sta->flags & WLAN_STA_HE)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station does not support mandatory HE PHY - reject association"); + return WLAN_STATUS_DENIED_HE_NOT_SUPPORTED; + } resp = copy_sta_he_6ghz_capab(hapd, sta, elems.he_6ghz_band_cap); if (resp != WLAN_STATUS_SUCCESS) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 9cd631783..c4e744693 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1762,6 +1762,7 @@ const char * status2str(u16 status) S2S(FILS_AUTHENTICATION_FAILURE) S2S(UNKNOWN_AUTHENTICATION_SERVER) S2S(UNKNOWN_PASSWORD_IDENTIFIER) + S2S(DENIED_HE_NOT_SUPPORTED) S2S(SAE_HASH_TO_ELEMENT) S2S(SAE_PK) } diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index da0e7bdcf..4d3037eee 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -204,6 +204,7 @@ #define WLAN_STATUS_FILS_AUTHENTICATION_FAILURE 112 #define WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER 113 #define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123 +#define WLAN_STATUS_DENIED_HE_NOT_SUPPORTED 124 #define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126 #define WLAN_STATUS_SAE_PK 127 From d51b1b7a660b5cba2e8059ccf8fb8955f6ee890f Mon Sep 17 00:00:00 2001 From: Muna Sinada Date: Mon, 18 May 2020 06:57:15 -0700 Subject: [PATCH 0674/1105] Move hostapd_eid_wb_chsw_wrapper() to non-VHT-specific file Move hostapd_eid_wb_chsw_wrapper() from VHT specific ieee802_11_vht.c to ieee802_11.c since this can be used for both HE and VHT. This commit does not change any functionality to enable the HE use case, i.e., the function is just moved as-is. Signed-off-by: Muna Sinada --- src/ap/ieee802_11.c | 52 ++++++++++++++++++++++++++++++++++++++++ src/ap/ieee802_11_vht.c | 53 ----------------------------------------- 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 4f4e548c8..917670084 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -5564,4 +5564,56 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, } +u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid) +{ + u8 bw, chan1, chan2 = 0; + int freq1; + + if (!hapd->cs_freq_params.channel || + !hapd->cs_freq_params.vht_enabled) + return eid; + + /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */ + switch (hapd->cs_freq_params.bandwidth) { + case 40: + bw = 0; + break; + case 80: + /* check if it's 80+80 */ + if (!hapd->cs_freq_params.center_freq2) + bw = 1; + else + bw = 3; + break; + case 160: + bw = 2; + break; + default: + /* not valid VHT bandwidth or not in CSA */ + return eid; + } + + freq1 = hapd->cs_freq_params.center_freq1 ? + hapd->cs_freq_params.center_freq1 : + hapd->cs_freq_params.freq; + if (ieee80211_freq_to_chan(freq1, &chan1) != + HOSTAPD_MODE_IEEE80211A) + return eid; + + if (hapd->cs_freq_params.center_freq2 && + ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2, + &chan2) != HOSTAPD_MODE_IEEE80211A) + return eid; + + *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER; + *eid++ = 5; /* Length of Channel Switch Wrapper */ + *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH; + *eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */ + *eid++ = bw; /* New Channel Width */ + *eid++ = chan1; /* New Channel Center Frequency Segment 0 */ + *eid++ = chan2; /* New Channel Center Frequency Segment 1 */ + + return eid; +} + #endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index 425b192e1..c925bf12c 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -167,59 +167,6 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode, } -u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid) -{ - u8 bw, chan1, chan2 = 0; - int freq1; - - if (!hapd->cs_freq_params.channel || - !hapd->cs_freq_params.vht_enabled) - return eid; - - /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */ - switch (hapd->cs_freq_params.bandwidth) { - case 40: - bw = 0; - break; - case 80: - /* check if it's 80+80 */ - if (!hapd->cs_freq_params.center_freq2) - bw = 1; - else - bw = 3; - break; - case 160: - bw = 2; - break; - default: - /* not valid VHT bandwidth or not in CSA */ - return eid; - } - - freq1 = hapd->cs_freq_params.center_freq1 ? - hapd->cs_freq_params.center_freq1 : - hapd->cs_freq_params.freq; - if (ieee80211_freq_to_chan(freq1, &chan1) != - HOSTAPD_MODE_IEEE80211A) - return eid; - - if (hapd->cs_freq_params.center_freq2 && - ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2, - &chan2) != HOSTAPD_MODE_IEEE80211A) - return eid; - - *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER; - *eid++ = 5; /* Length of Channel Switch Wrapper */ - *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH; - *eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */ - *eid++ = bw; /* New Channel Width */ - *eid++ = chan1; /* New Channel Center Frequency Segment 0 */ - *eid++ = chan2; /* New Channel Center Frequency Segment 1 */ - - return eid; -} - - u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) { struct hostapd_iface *iface = hapd->iface; From 621745917f66932210e878dc674635800e47d680 Mon Sep 17 00:00:00 2001 From: Muna Sinada Date: Mon, 18 May 2020 06:57:16 -0700 Subject: [PATCH 0675/1105] Allow HE-without-VHT to add the Channel Switch Wrapper element Modify the check for VHT to include an option for HE in hostapd_eid_wb_chsw_wrapper() and its callers to allow the Channel Switch Wrapper element with the Wide Bandwidth Channel Switch subelement to be included in Beacon and Probe Response frames when AP is operating in HE mode without VHT. Signed-off-by: Muna Sinada --- src/ap/beacon.c | 10 ++++++++-- src/ap/ieee802_11.c | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 22e672c8d..b3b33b7fa 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -560,10 +560,13 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_vht_capabilities(hapd, pos, 0); pos = hostapd_eid_vht_operation(hapd, pos); pos = hostapd_eid_txpower_envelope(hapd, pos); - pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); } #endif /* CONFIG_IEEE80211AC */ + if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || + hapd->iconf->ieee80211ax) + pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); + pos = hostapd_eid_fils_indic(hapd, pos, 0); pos = hostapd_get_rsnxe(hapd, pos, epos - pos); @@ -1281,10 +1284,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0); tailpos = hostapd_eid_vht_operation(hapd, tailpos); tailpos = hostapd_eid_txpower_envelope(hapd, tailpos); - tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); } #endif /* CONFIG_IEEE80211AC */ + if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || + hapd->iconf->ieee80211ax) + tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); + tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0); tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 917670084..b91640070 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -5570,7 +5570,8 @@ u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid) int freq1; if (!hapd->cs_freq_params.channel || - !hapd->cs_freq_params.vht_enabled) + (!hapd->cs_freq_params.vht_enabled && + !hapd->cs_freq_params.he_enabled)) return eid; /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */ From 6dc2c0118ae0ca92dfbc80a7cfac2d6dac4d70d7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 11 Jun 2020 21:53:24 +0300 Subject: [PATCH 0676/1105] Update DFS terminology in attribute value documentation Use "client device" as the term for the device that operates under a guidance of the device responsible for enforcing DFS rules. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index c6a19b7bf..2136c020c 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -4839,9 +4839,9 @@ enum qca_wlan_vendor_channel_prop_flags_ext { QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_ADHOC = 1 << 6, /* Station only channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_HOSTAP = 1 << 7, - /* DFS radar history for slave device (STA mode) */ + /* DFS radar history for client device (STA mode) */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_HISTORY_RADAR = 1 << 8, - /* DFS CAC valid for slave device (STA mode) */ + /* DFS CAC valid for client device (STA mode) */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CAC_VALID = 1 << 9, }; From c7e6dbdad8ee043a9d7f856502196dbeb65cb4ac Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Jun 2020 20:18:12 +0300 Subject: [PATCH 0677/1105] base64: Add no-LF variant for encoding base64_encode_no_lf() is otherwise identical to base64_encode(), but it does not add line-feeds to split the output. Signed-off-by: Jouni Malinen --- src/utils/base64.c | 24 ++++++++++++++++++------ src/utils/base64.h | 1 + 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/utils/base64.c b/src/utils/base64.c index a17d2d36d..0d121c198 100644 --- a/src/utils/base64.c +++ b/src/utils/base64.c @@ -9,6 +9,7 @@ #include "includes.h" #include +#include "utils/common.h" #include "os.h" #include "base64.h" @@ -18,6 +19,10 @@ static const char base64_url_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +#define BASE64_PAD BIT(0) +#define BASE64_LF BIT(1) + + static char * base64_gen_encode(const unsigned char *src, size_t len, size_t *out_len, const char *table, int add_pad) { @@ -29,7 +34,7 @@ static char * base64_gen_encode(const unsigned char *src, size_t len, if (len >= SIZE_MAX / 4) return NULL; olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ - if (add_pad) + if (add_pad & BASE64_LF) olen += olen / 72; /* line feeds */ olen++; /* nul termination */ if (olen < len) @@ -49,7 +54,7 @@ static char * base64_gen_encode(const unsigned char *src, size_t len, *pos++ = table[in[2] & 0x3f]; in += 3; line_len += 4; - if (add_pad && line_len >= 72) { + if ((add_pad & BASE64_LF) && line_len >= 72) { *pos++ = '\n'; line_len = 0; } @@ -59,19 +64,19 @@ static char * base64_gen_encode(const unsigned char *src, size_t len, *pos++ = table[(in[0] >> 2) & 0x3f]; if (end - in == 1) { *pos++ = table[((in[0] & 0x03) << 4) & 0x3f]; - if (add_pad) + if (add_pad & BASE64_PAD) *pos++ = '='; } else { *pos++ = table[(((in[0] & 0x03) << 4) | (in[1] >> 4)) & 0x3f]; *pos++ = table[((in[1] & 0x0f) << 2) & 0x3f]; } - if (add_pad) + if (add_pad & BASE64_PAD) *pos++ = '='; line_len += 4; } - if (add_pad && line_len) + if ((add_pad & BASE64_LF) && line_len) *pos++ = '\n'; *pos = '\0'; @@ -164,7 +169,14 @@ static unsigned char * base64_gen_decode(const char *src, size_t len, */ char * base64_encode(const void *src, size_t len, size_t *out_len) { - return base64_gen_encode(src, len, out_len, base64_table, 1); + return base64_gen_encode(src, len, out_len, base64_table, + BASE64_PAD | BASE64_LF); +} + + +char * base64_encode_no_lf(const void *src, size_t len, size_t *out_len) +{ + return base64_gen_encode(src, len, out_len, base64_table, BASE64_PAD); } diff --git a/src/utils/base64.h b/src/utils/base64.h index 6216f44e5..d545b2931 100644 --- a/src/utils/base64.h +++ b/src/utils/base64.h @@ -10,6 +10,7 @@ #define BASE64_H char * base64_encode(const void *src, size_t len, size_t *out_len); +char * base64_encode_no_lf(const void *src, size_t len, size_t *out_len); unsigned char * base64_decode(const char *src, size_t len, size_t *out_len); char * base64_url_encode(const void *src, size_t len, size_t *out_len); unsigned char * base64_url_decode(const char *src, size_t len, size_t *out_len); From 608adae5ba9a7647e9d7afdbca81c868be72ede3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Jun 2020 20:19:19 +0300 Subject: [PATCH 0678/1105] JSON: Add base64 helper functions These functions are similar to the base64url helpers but with the base64 (not url) alphabet. Signed-off-by: Jouni Malinen --- src/utils/json.c | 36 ++++++++++++++++++++++++++++++++++++ src/utils/json.h | 4 ++++ 2 files changed, 40 insertions(+) diff --git a/src/utils/json.c b/src/utils/json.c index 5a0edf211..dd12f1b6e 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -528,6 +528,28 @@ struct wpabuf * json_get_member_base64url(struct json_token *json, } +struct wpabuf * json_get_member_base64(struct json_token *json, + const char *name) +{ + struct json_token *token; + unsigned char *buf; + size_t buflen; + struct wpabuf *ret; + + token = json_get_member(json, name); + if (!token || token->type != JSON_STRING) + return NULL; + buf = base64_decode(token->string, os_strlen(token->string), &buflen); + if (!buf) + return NULL; + ret = wpabuf_alloc_ext_data(buf, buflen); + if (!ret) + os_free(buf); + + return ret; +} + + static const char * json_type_str(enum json_type type) { switch (type) { @@ -620,6 +642,20 @@ int json_add_base64url(struct wpabuf *json, const char *name, const void *val, } +int json_add_base64(struct wpabuf *json, const char *name, const void *val, + size_t len) +{ + char *b64; + + b64 = base64_encode_no_lf(val, len, NULL); + if (!b64) + return -1; + json_add_string(json, name, b64); + os_free(b64); + return 0; +} + + void json_start_object(struct wpabuf *json, const char *name) { if (name) diff --git a/src/utils/json.h b/src/utils/json.h index ca4a2e47e..8448bb0c5 100644 --- a/src/utils/json.h +++ b/src/utils/json.h @@ -37,6 +37,8 @@ void json_free(struct json_token *json); struct json_token * json_get_member(struct json_token *json, const char *name); struct wpabuf * json_get_member_base64url(struct json_token *json, const char *name); +struct wpabuf * json_get_member_base64(struct json_token *json, + const char *name); void json_print_tree(struct json_token *root, char *buf, size_t buflen); void json_add_int(struct wpabuf *json, const char *name, int val); void json_add_string(struct wpabuf *json, const char *name, const char *val); @@ -44,6 +46,8 @@ int json_add_string_escape(struct wpabuf *json, const char *name, const void *val, size_t len); int json_add_base64url(struct wpabuf *json, const char *name, const void *val, size_t len); +int json_add_base64(struct wpabuf *json, const char *name, const void *val, + size_t len); void json_start_object(struct wpabuf *json, const char *name); void json_end_object(struct wpabuf *json); void json_start_array(struct wpabuf *json, const char *name); From 68ac45d53c53061cd25c14663627faf87979bb6e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Jun 2020 21:20:44 +0300 Subject: [PATCH 0679/1105] GAS server: Support comeback delay from the request handler Allow GAS request handler function to request comeback delay before providing the response. Signed-off-by: Jouni Malinen --- src/common/gas_server.c | 123 +++++++++++++++++++++++++------- src/common/gas_server.h | 8 ++- wpa_supplicant/dpp_supplicant.c | 4 +- 3 files changed, 106 insertions(+), 29 deletions(-) diff --git a/src/common/gas_server.c b/src/common/gas_server.c index ca46758ce..5a1ea7899 100644 --- a/src/common/gas_server.c +++ b/src/common/gas_server.c @@ -1,6 +1,7 @@ /* * Generic advertisement service (GAS) server * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2020, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -23,8 +24,9 @@ struct gas_server_handler { struct dl_list list; u8 adv_proto_id[MAX_ADV_PROTO_ID_LEN]; u8 adv_proto_id_len; - struct wpabuf * (*req_cb)(void *ctx, const u8 *sa, - const u8 *query, size_t query_len); + struct wpabuf * (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, + const u8 *query, size_t query_len, + u16 *comeback_delay); void (*status_cb)(void *ctx, struct wpabuf *resp, int ok); void *ctx; struct gas_server *gas; @@ -39,6 +41,7 @@ struct gas_server_response { u8 dst[ETH_ALEN]; u8 dialog_token; struct gas_server_handler *handler; + u16 comeback_delay; }; struct gas_server { @@ -61,7 +64,8 @@ static void gas_server_response_timeout(void *eloop_ctx, void *user_ctx) response, MAC2STR(response->dst), response->dialog_token, response->freq, response->frag_id, (unsigned long) response->offset, - (unsigned long) wpabuf_len(response->resp)); + (unsigned long) (response->resp ? + wpabuf_len(response->resp) : 0)); response->handler->status_cb(response->handler->ctx, response->resp, 0); response->resp = NULL; @@ -83,30 +87,27 @@ static void gas_server_free_response(struct gas_server_response *response) static void gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler, + struct gas_server_response *response, const u8 *da, int freq, u8 dialog_token, - struct wpabuf *query_resp) + struct wpabuf *query_resp, u16 comeback_delay) { size_t max_len = (freq > 56160) ? 928 : 1400; size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2; size_t resp_frag_len; struct wpabuf *resp; - u16 comeback_delay; - struct gas_server_response *response; - if (!query_resp) + if (comeback_delay == 0 && !query_resp) return; - response = os_zalloc(sizeof(*response)); - if (!response) { - wpabuf_free(query_resp); - return; - } - wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response); response->freq = freq; response->handler = handler; os_memcpy(response->dst, da, ETH_ALEN); response->dialog_token = dialog_token; - if (hdr_len + wpabuf_len(query_resp) > max_len) { + if (comeback_delay) { + /* Need more time to prepare the response */ + resp_frag_len = 0; + response->comeback_delay = comeback_delay; + } else if (hdr_len + wpabuf_len(query_resp) > max_len) { /* Need to use comeback to initiate fragmentation */ comeback_delay = 1; resp_frag_len = 0; @@ -135,10 +136,12 @@ gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler, /* Query Response Length */ wpabuf_put_le16(resp, resp_frag_len); - if (!comeback_delay) + if (!comeback_delay && query_resp) wpabuf_put_buf(resp, query_resp); - if (comeback_delay) { + if (comeback_delay && !query_resp) { + wpa_printf(MSG_DEBUG, "GAS: No response available yet"); + } else if (comeback_delay) { wpa_printf(MSG_DEBUG, "GAS: Need to fragment query response"); } else { @@ -165,6 +168,7 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa, u16 query_req_len; struct gas_server_handler *handler; struct wpabuf *resp; + struct gas_server_response *response; wpa_hexdump(MSG_MSGDUMP, "GAS: Received GAS Initial Request frame", data, len); @@ -210,8 +214,15 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa, pos, end - pos); } + response = os_zalloc(sizeof(*response)); + if (!response) + return -1; + + wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response); dl_list_for_each(handler, &gas->handlers, struct gas_server_handler, list) { + u16 comeback_delay = 0; + if (adv_proto_len < 1 + handler->adv_proto_id_len || os_memcmp(adv_proto + 1, handler->adv_proto_id, handler->adv_proto_id_len) != 0) @@ -219,17 +230,22 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa, wpa_printf(MSG_DEBUG, "GAS: Calling handler for the requested Advertisement Protocol ID"); - resp = handler->req_cb(handler->ctx, sa, query_req, - query_req_len); + resp = handler->req_cb(handler->ctx, response, sa, query_req, + query_req_len, &comeback_delay); wpa_hexdump_buf(MSG_MSGDUMP, "GAS: Response from the handler", resp); - gas_server_send_resp(gas, handler, sa, freq, dialog_token, - resp); + if (comeback_delay) + wpa_printf(MSG_DEBUG, + "GAS: Handler requested comeback delay: %u TU", + comeback_delay); + gas_server_send_resp(gas, handler, response, sa, freq, + dialog_token, resp, comeback_delay); return 0; } wpa_printf(MSG_DEBUG, "GAS: No registered handler for the requested Advertisement Protocol ID"); + gas_server_free_response(response); return -1; } @@ -243,6 +259,31 @@ gas_server_handle_rx_comeback_req(struct gas_server_response *response) size_t hdr_len = 24 + 2 + 6 + 3 + handler->adv_proto_id_len + 2; size_t remaining, resp_frag_len; struct wpabuf *resp; + unsigned int wait_time = 0; + + if (!response->resp) { + resp = gas_build_comeback_resp(response->dialog_token, + WLAN_STATUS_SUCCESS, 0, 0, + response->comeback_delay, + handler->adv_proto_id_len); + if (!resp) { + dl_list_del(&response->list); + gas_server_free_response(response); + return; + } + + /* Advertisement Protocol element */ + wpabuf_put_u8(resp, WLAN_EID_ADV_PROTO); + wpabuf_put_u8(resp, 1 + handler->adv_proto_id_len); /* Length */ + wpabuf_put_u8(resp, 0x7f); + /* Advertisement Protocol ID */ + wpabuf_put_data(resp, handler->adv_proto_id, + handler->adv_proto_id_len); + + /* Query Response Length */ + wpabuf_put_le16(resp, 0); + goto send_resp; + } remaining = wpabuf_len(response->resp) - response->offset; if (hdr_len + remaining > max_len) @@ -279,8 +320,11 @@ gas_server_handle_rx_comeback_req(struct gas_server_response *response) response->offset += resp_frag_len; - gas->tx(gas->ctx, response->freq, response->dst, resp, - remaining > resp_frag_len ? 2000 : 0); + if (remaining > resp_frag_len) + wait_time = 2000; + +send_resp: + gas->tx(gas->ctx, response->freq, response->dst, resp, wait_time); wpabuf_free(resp); } @@ -359,12 +403,19 @@ int gas_server_rx(struct gas_server *gas, const u8 *da, const u8 *sa, static void gas_server_handle_tx_status(struct gas_server_response *response, int ack) { - if (ack && response->offset < wpabuf_len(response->resp)) { + if (ack && response->resp && + response->offset < wpabuf_len(response->resp)) { wpa_printf(MSG_DEBUG, "GAS: More fragments remaining - keep pending entry"); return; } + if (ack && !response->resp && response->comeback_delay) { + wpa_printf(MSG_DEBUG, + "GAS: Waiting for response - keep pending entry"); + return; + } + if (!ack) wpa_printf(MSG_DEBUG, "GAS: No ACK received - drop pending entry"); @@ -415,6 +466,27 @@ void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data, } +int gas_server_set_resp(struct gas_server *gas, void *resp_ctx, + struct wpabuf *resp) +{ + struct gas_server_response *tmp, *response = NULL; + + dl_list_for_each(tmp, &gas->responses, struct gas_server_response, + list) { + if (tmp == resp_ctx) { + response = tmp; + break; + } + } + + if (!response || response->resp) + return -1; + + response->resp = resp; + return 0; +} + + struct gas_server * gas_server_init(void *ctx, void (*tx)(void *ctx, int freq, const u8 *da, @@ -461,8 +533,9 @@ void gas_server_deinit(struct gas_server *gas) int gas_server_register(struct gas_server *gas, const u8 *adv_proto_id, u8 adv_proto_id_len, struct wpabuf * - (*req_cb)(void *ctx, const u8 *sa, - const u8 *query, size_t query_len), + (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, + const u8 *query, size_t query_len, + u16 *comeback_delay), void (*status_cb)(void *ctx, struct wpabuf *resp, int ok), void *ctx) diff --git a/src/common/gas_server.h b/src/common/gas_server.h index 299f529f7..2611ddedc 100644 --- a/src/common/gas_server.h +++ b/src/common/gas_server.h @@ -1,6 +1,7 @@ /* * Generic advertisement service (GAS) server * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2020, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -22,8 +23,9 @@ void gas_server_deinit(struct gas_server *gas); int gas_server_register(struct gas_server *gas, const u8 *adv_proto_id, u8 adv_proto_id_len, struct wpabuf * - (*req_cb)(void *ctx, const u8 *sa, - const u8 *query, size_t query_len), + (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, + const u8 *query, size_t query_len, + u16 *comeback_delay), void (*status_cb)(void *ctx, struct wpabuf *resp, int ok), void *ctx); @@ -32,6 +34,8 @@ int gas_server_rx(struct gas_server *gas, const u8 *da, const u8 *sa, int freq); void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data, size_t data_len, int ack); +int gas_server_set_resp(struct gas_server *gas, void *resp_ctx, + struct wpabuf *resp); #else /* CONFIG_GAS_SERVER */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index a41b3f5c0..66aad2916 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2647,8 +2647,8 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, static struct wpabuf * -wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query, - size_t query_len) +wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa, + const u8 *query, size_t query_len, u16 *comeback_delay) { struct wpa_supplicant *wpa_s = ctx; struct dpp_authentication *auth = wpa_s->dpp_auth; From 4b834df5e08a41c5b018881ad888f637ba66b1ee Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 16 Jun 2020 17:47:50 +0300 Subject: [PATCH 0680/1105] OpenSSL: Support PEM encoded chain from client_cert blob Allow a chain of certificates to be configured through a client_cert blob. Signed-off-by: Jouni Malinen --- src/crypto/tls_openssl.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index a6a4ce4b9..160578e0e 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -3241,8 +3241,31 @@ static int tls_connection_client_cert(struct tls_connection *conn, "OK"); return 0; } else if (client_cert_blob) { + BIO *bio; + X509 *x509; + tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_ASN1 failed"); + bio = BIO_new(BIO_s_mem()); + if (!bio) + return -1; + BIO_write(bio, client_cert_blob, client_cert_blob_len); + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (!x509 || SSL_use_certificate(conn->ssl, x509) != 1) { + X509_free(x509); + BIO_free(bio); + return -1; + } + X509_free(x509); + wpa_printf(MSG_DEBUG, + "OpenSSL: Found PEM encoded certificate from blob"); + while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL))) { + wpa_printf(MSG_DEBUG, + "OpenSSL: Added an additional certificate into the chain"); + SSL_add0_chain_cert(conn->ssl, x509); + } + BIO_free(bio); + return 0; } if (client_cert == NULL) From 812d52ae271a2a806881287115b2473165d7ab37 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 16 Jun 2020 17:48:47 +0300 Subject: [PATCH 0681/1105] OpenSSL: Support EC key from private_key blob Try to parse the private_key blob as an ECPrivateKey in addition to the previously supported RSA and DSA. Signed-off-by: Jouni Malinen --- src/crypto/tls_openssl.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 160578e0e..29c7688a5 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -3772,6 +3772,17 @@ static int tls_connection_private_key(struct tls_data *data, break; } +#ifndef OPENSSL_NO_EC + if (SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, conn->ssl, + (u8 *) private_key_blob, + private_key_blob_len) == 1) { + wpa_printf(MSG_DEBUG, + "OpenSSL: SSL_use_PrivateKey_ASN1(EVP_PKEY_EC) --> OK"); + ok = 1; + break; + } +#endif /* OPENSSL_NO_EC */ + if (SSL_use_RSAPrivateKey_ASN1(conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { From 4643b2feec34470ce9f5af1fffc071748f5fbfc8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Jun 2020 20:20:50 +0300 Subject: [PATCH 0682/1105] DPP2: Enterprise provisioning definitions for dot1x AKM Add shared AKM definitions for provisioning enterprise (EAP-TLS) credentials. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 16 +++++++++++++++- src/common/dpp.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index ca3b8b50c..2ca906283 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -916,6 +916,8 @@ struct dpp_configuration * dpp_configuration_alloc(const char *type) conf->akm = DPP_AKM_PSK_SAE_DPP; else if (bin_str_eq(type, len, "dpp")) conf->akm = DPP_AKM_DPP; + else if (bin_str_eq(type, len, "dot1x")) + conf->akm = DPP_AKM_DOT1X; else goto fail; @@ -2371,6 +2373,8 @@ const char * dpp_akm_str(enum dpp_akm akm) return "dpp+sae"; case DPP_AKM_PSK_SAE_DPP: return "dpp+psk+sae"; + case DPP_AKM_DOT1X: + return "dot1x"; default: return "??"; } @@ -2392,6 +2396,8 @@ const char * dpp_akm_selector_str(enum dpp_akm akm) return "506F9A02+000FAC08"; case DPP_AKM_PSK_SAE_DPP: return "506F9A02+000FAC08+000FAC02+000FAC06"; + case DPP_AKM_DOT1X: + return "000FAC01+000FAC05"; default: return "??"; } @@ -2401,7 +2407,7 @@ const char * dpp_akm_selector_str(enum dpp_akm akm) static enum dpp_akm dpp_akm_from_str(const char *akm) { const char *pos; - int dpp = 0, psk = 0, sae = 0; + int dpp = 0, psk = 0, sae = 0, dot1x = 0; if (os_strcmp(akm, "psk") == 0) return DPP_AKM_PSK; @@ -2415,6 +2421,8 @@ static enum dpp_akm dpp_akm_from_str(const char *akm) return DPP_AKM_SAE_DPP; if (os_strcmp(akm, "dpp+psk+sae") == 0) return DPP_AKM_PSK_SAE_DPP; + if (os_strcmp(akm, "dot1x") == 0) + return DPP_AKM_DOT1X; pos = akm; while (*pos) { @@ -2428,6 +2436,10 @@ static enum dpp_akm dpp_akm_from_str(const char *akm) psk = 1; else if (os_strncasecmp(pos, "000FAC08", 8) == 0) sae = 1; + else if (os_strncasecmp(pos, "000FAC01", 8) == 0) + dot1x = 1; + else if (os_strncasecmp(pos, "000FAC05", 8) == 0) + dot1x = 1; pos += 8; if (*pos != '+') break; @@ -2446,6 +2458,8 @@ static enum dpp_akm dpp_akm_from_str(const char *akm) return DPP_AKM_SAE; if (psk) return DPP_AKM_PSK; + if (dot1x) + return DPP_AKM_DOT1X; return DPP_AKM_UNKNOWN; } diff --git a/src/common/dpp.h b/src/common/dpp.h index c0927d9b8..c430c2856 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -196,6 +196,7 @@ enum dpp_akm { DPP_AKM_PSK_SAE, DPP_AKM_SAE_DPP, DPP_AKM_PSK_SAE_DPP, + DPP_AKM_DOT1X, }; enum dpp_netrole { From 6568e5d203315a7feb54d88588e858ad1ceac788 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Jun 2020 20:20:50 +0300 Subject: [PATCH 0683/1105] DPP2: Enterprise provisioning (Configurator) Add Configurator functionality for provisioning enterprise (EAP-TLS) configuration object. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 121 +++++++++++++++++++++++++++++--- src/common/dpp.h | 13 ++++ src/common/wpa_ctrl.h | 1 + wpa_supplicant/ctrl_iface.c | 3 + wpa_supplicant/dpp_supplicant.c | 99 ++++++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.h | 1 + 6 files changed, 228 insertions(+), 10 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 2ca906283..db8a68401 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -17,6 +17,7 @@ #include "common/ieee802_11_common.h" #include "common/wpa_ctrl.h" #include "common/gas.h" +#include "eap_common/eap_defs.h" #include "crypto/crypto.h" #include "crypto/random.h" #include "crypto/aes.h" @@ -980,6 +981,7 @@ void dpp_configuration_free(struct dpp_configuration *conf) return; str_clear_free(conf->passphrase); os_free(conf->group_id); + os_free(conf->csrattrs); bin_clear_free(conf, sizeof(*conf)); } @@ -990,6 +992,7 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth, const char *pos, *end; struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL; struct dpp_configuration *conf = NULL; + size_t len; pos = os_strstr(cmd, " conf=sta-"); if (pos) { @@ -1094,6 +1097,17 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth, conf->netaccesskey_expiry = val; } + pos = os_strstr(cmd, " csrattrs="); + if (pos) { + pos += 10; + end = os_strchr(pos, ' '); + len = end ? (size_t) (end - pos) : os_strlen(pos); + conf->csrattrs = os_zalloc(len + 1); + if (!conf->csrattrs) + goto fail; + os_memcpy(conf->csrattrs, pos, len); + } + if (!dpp_configuration_valid(conf)) goto fail; @@ -1482,6 +1496,15 @@ skip_groups: tailroom += os_strlen(signed_conn); if (incl_legacy) tailroom += 1000; + if (akm == DPP_AKM_DOT1X) { + if (auth->certbag) + tailroom += 2 * wpabuf_len(auth->certbag); + if (auth->cacert) + tailroom += 2 * wpabuf_len(auth->cacert); + if (auth->trusted_eap_server_name) + tailroom += os_strlen(auth->trusted_eap_server_name); + tailroom += 1000; + } buf = dpp_build_conf_start(auth, conf, tailroom); if (!buf) goto fail; @@ -1497,6 +1520,30 @@ skip_groups: dpp_build_legacy_cred_params(buf, conf); json_value_sep(buf); } + if (akm == DPP_AKM_DOT1X) { + json_start_object(buf, "entCreds"); + if (!auth->certbag) + goto fail; + json_add_base64(buf, "certBag", wpabuf_head(auth->certbag), + wpabuf_len(auth->certbag)); + if (auth->cacert) { + json_value_sep(buf); + json_add_base64(buf, "caCert", + wpabuf_head(auth->cacert), + wpabuf_len(auth->cacert)); + } + if (auth->trusted_eap_server_name) { + json_value_sep(buf); + json_add_string(buf, "trustedEapServerName", + auth->trusted_eap_server_name); + } + json_value_sep(buf); + json_start_array(buf, "eapMethods"); + wpabuf_printf(buf, "%d", EAP_TYPE_TLS); + json_end_array(buf); + json_end_object(buf); + json_value_sep(buf); + } wpabuf_put_str(buf, "\"signedConnector\":\""); wpabuf_put_str(buf, signed_conn); wpabuf_put_str(buf, "\""); @@ -1556,7 +1603,7 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth, static struct wpabuf * dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, - int idx) + int idx, bool cert_req) { struct dpp_configuration *conf = NULL; @@ -1589,15 +1636,28 @@ dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, return NULL; } + if (conf->akm == DPP_AKM_DOT1X) { + if (!auth->conf) { + wpa_printf(MSG_DEBUG, + "DPP: No Configurator data available"); + return NULL; + } + if (!cert_req && !auth->certbag) { + wpa_printf(MSG_DEBUG, + "DPP: No certificate data available for dot1x configuration"); + return NULL; + } + return dpp_build_conf_obj_dpp(auth, conf); + } if (dpp_akm_dpp(conf->akm) || (auth->peer_version >= 2 && auth->conf)) return dpp_build_conf_obj_dpp(auth, conf); return dpp_build_conf_obj_legacy(auth, conf); } -static struct wpabuf * +struct wpabuf * dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, - u16 e_nonce_len, enum dpp_netrole netrole) + u16 e_nonce_len, enum dpp_netrole netrole, bool cert_req) { struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL; size_t clear_len, attr_len; @@ -1612,16 +1672,22 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, env_data = dpp_build_enveloped_data(auth); #endif /* CONFIG_DPP2 */ } else { - conf = dpp_build_conf_obj(auth, netrole, 0); + conf = dpp_build_conf_obj(auth, netrole, 0, cert_req); if (conf) { wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON", wpabuf_head(conf), wpabuf_len(conf)); - conf2 = dpp_build_conf_obj(auth, netrole, 1); + conf2 = dpp_build_conf_obj(auth, netrole, 1, cert_req); } } - status = (conf || env_data) ? DPP_STATUS_OK : - DPP_STATUS_CONFIGURE_FAILURE; + + if (conf || env_data) + status = DPP_STATUS_OK; + else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta && + auth->conf_sta->akm == DPP_AKM_DOT1X && !auth->waiting_csr) + status = DPP_STATUS_CSR_NEEDED; + else + status = DPP_STATUS_CONFIGURE_FAILURE; auth->conf_resp_status = status; /* { E-nonce, configurationObject[, sendConnStatus]}ke */ @@ -1635,6 +1701,9 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, if (auth->peer_version >= 2 && auth->send_conn_status && netrole == DPP_NETROLE_STA) clear_len += 4; + if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta && + auth->conf_sta->csrattrs) + clear_len += 4 + os_strlen(auth->conf_sta->csrattrs); clear = wpabuf_alloc(clear_len); attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE; #ifdef CONFIG_TESTING_OPTIONS @@ -1697,12 +1766,21 @@ skip_e_nonce: } if (auth->peer_version >= 2 && auth->send_conn_status && - netrole == DPP_NETROLE_STA) { + netrole == DPP_NETROLE_STA && status == DPP_STATUS_OK) { wpa_printf(MSG_DEBUG, "DPP: sendConnStatus"); wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS); wpabuf_put_le16(clear, 0); } + if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta && + auth->conf_sta->csrattrs) { + auth->waiting_csr = true; + wpa_printf(MSG_DEBUG, "DPP: CSR Attributes Request"); + wpabuf_put_le16(clear, DPP_ATTR_CSR_ATTR_REQ); + wpabuf_put_le16(clear, os_strlen(auth->conf_sta->csrattrs)); + wpabuf_put_str(clear, auth->conf_sta->csrattrs); + } + #ifdef CONFIG_TESTING_OPTIONS skip_config_obj: if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) { @@ -1773,6 +1851,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, struct wpabuf *resp = NULL; struct json_token *root = NULL, *token; enum dpp_netrole netrole; + struct wpabuf *cert_req = NULL; #ifdef CONFIG_TESTING_OPTIONS if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) { @@ -1881,6 +1960,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, dpp_auth_fail(auth, "Unsupported netRole"); goto fail; } + auth->e_netrole = netrole; token = json_get_member(root, "mudurl"); if (token && token->type == JSON_STRING) { @@ -1927,9 +2007,30 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, txt); } - resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole); +#ifdef CONFIG_DPP2 + cert_req = json_get_member_base64(root, "pkcs10"); + if (cert_req) { + char *txt; + + wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req); + txt = base64_encode_no_lf(wpabuf_head(cert_req), + wpabuf_len(cert_req), NULL); + if (!txt) + goto fail; + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_CSR "peer=%d csr=%s", + auth->peer_bi ? (int) auth->peer_bi->id : -1, txt); + os_free(txt); + auth->waiting_csr = false; + auth->waiting_cert = true; + goto fail; + } +#endif /* CONFIG_DPP2 */ + + resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole, + cert_req); fail: + wpabuf_free(cert_req); json_free(root); os_free(unwrapped); return resp; @@ -3216,7 +3317,7 @@ int dpp_configurator_own_config(struct dpp_authentication *auth, auth->peer_protocol_key = auth->own_protocol_key; dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign); - conf_obj = dpp_build_conf_obj(auth, ap, 0); + conf_obj = dpp_build_conf_obj(auth, ap, 0, NULL); if (!conf_obj) { wpabuf_free(auth->conf_obj[0].c_sign_key); auth->conf_obj[0].c_sign_key = NULL; diff --git a/src/common/dpp.h b/src/common/dpp.h index c430c2856..8ca41abd2 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -222,6 +222,8 @@ struct dpp_configuration { char *passphrase; u8 psk[32]; int psk_set; + + char *csrattrs; }; struct dpp_asymmetric_key { @@ -253,6 +255,7 @@ struct dpp_authentication { u8 e_nonce[DPP_MAX_NONCE_LEN]; u8 i_capab; u8 r_capab; + enum dpp_netrole e_netrole; EVP_PKEY *own_protocol_key; EVP_PKEY *peer_protocol_key; EVP_PKEY *reconfig_old_protocol_key; @@ -319,6 +322,12 @@ struct dpp_authentication { int akm_use_selector; int configurator_set; u8 transaction_id; + bool waiting_csr; + bool waiting_cert; + char *trusted_eap_server_name; + struct wpabuf *cacert; + struct wpabuf *certbag; + void *cert_resp_ctx; #ifdef CONFIG_TESTING_OPTIONS char *config_obj_override; char *discovery_override; @@ -517,6 +526,10 @@ void dpp_configuration_free(struct dpp_configuration *conf); int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd); void dpp_auth_deinit(struct dpp_authentication *auth); struct wpabuf * +dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, + u16 e_nonce_len, enum dpp_netrole netrole, + bool cert_req); +struct wpabuf * dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, size_t attr_len); int dpp_conf_resp_rx(struct dpp_authentication *auth, diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 488e4addc..1fa141520 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -192,6 +192,7 @@ extern "C" { #define DPP_EVENT_CHIRP_STOPPED "DPP-CHIRP-STOPPED " #define DPP_EVENT_MUD_URL "DPP-MUD-URL " #define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT " +#define DPP_EVENT_CSR "DPP-CSR " /* MESH events */ #define MESH_GROUP_STARTED "MESH-GROUP-STARTED " diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 298f3c442..8d2ccbae5 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11204,6 +11204,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, ssid = wpa_config_get_network(wpa_s->conf, atoi(buf + 13)); if (!ssid || wpas_dpp_reconfig(wpa_s, ssid) < 0) reply_len = -1; + } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) { + if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0) + reply_len = -1; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ } else { diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 66aad2916..b0b657f5e 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -12,6 +12,7 @@ #include "utils/common.h" #include "utils/eloop.h" #include "utils/ip_addr.h" +#include "utils/base64.h" #include "common/dpp.h" #include "common/gas.h" #include "common/gas_server.h" @@ -2679,6 +2680,16 @@ wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa, wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR, MAC2STR(sa)); resp = dpp_conf_req_rx(auth, query, query_len); + +#ifdef CONFIG_DPP2 + if (!resp && auth->waiting_cert) { + wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); + auth->cert_resp_ctx = resp_ctx; + *comeback_delay = 500; + return NULL; + } +#endif /* CONFIG_DPP2 */ + if (!resp) wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); auth->conf_resp = resp; @@ -2704,6 +2715,14 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok) return; } +#ifdef CONFIG_DPP2 + if (auth->waiting_csr && ok) { + wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR"); + wpabuf_free(resp); + return; + } +#endif /* CONFIG_DPP2 */ + wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)", ok); eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); @@ -3449,4 +3468,84 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL); } + +int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) +{ + int peer; + const char *pos, *value; + struct dpp_authentication *auth = wpa_s->dpp_auth; + u8 *bin; + size_t bin_len; + struct wpabuf *buf; + + if (!auth || !auth->waiting_cert) { + wpa_printf(MSG_DEBUG, + "DPP: No authentication exchange waiting for certificate information"); + return -1; + } + + pos = os_strstr(cmd, " peer="); + if (pos) { + peer = atoi(pos + 6); + if (!auth->peer_bi || + (unsigned int) peer != auth->peer_bi->id) { + wpa_printf(MSG_DEBUG, "DPP: Peer mismatch"); + return -1; + } + } + + pos = os_strstr(cmd, " value="); + if (!pos) + return -1; + value = pos + 7; + + pos = os_strstr(cmd, " name="); + if (!pos) + return -1; + pos += 6; + + if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) { + os_free(auth->trusted_eap_server_name); + auth->trusted_eap_server_name = os_strdup(value); + return auth->trusted_eap_server_name ? 0 : -1; + } + + bin = base64_decode(value, os_strlen(value), &bin_len); + if (!bin) + return -1; + buf = wpabuf_alloc_copy(bin, bin_len); + os_free(bin); + + if (os_strncmp(pos, "caCert ", 7) == 0) { + wpabuf_free(auth->cacert); + auth->cacert = buf; + return 0; + } + + if (os_strncmp(pos, "certBag ", 8) == 0) { + struct wpabuf *resp; + + wpabuf_free(auth->certbag); + auth->certbag = buf; + + resp = dpp_build_conf_resp(auth, auth->e_nonce, + auth->curve->nonce_len, + auth->e_netrole, true); + if (!resp) + return -1; + if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx, + resp) < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Could not find pending GAS response"); + wpabuf_free(resp); + return -1; + } + auth->conf_resp = resp; + return 0; + } + + wpabuf_free(buf); + return -1; +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h index 2dc86e09e..081615b95 100644 --- a/wpa_supplicant/dpp_supplicant.h +++ b/wpa_supplicant/dpp_supplicant.h @@ -40,5 +40,6 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s, int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd); void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s); int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd); #endif /* DPP_SUPPLICANT_H */ From ace3723d987987ef96c8905680a00497e7e1161c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Jun 2020 20:20:50 +0300 Subject: [PATCH 0684/1105] DPP2: Enterprise provisioning (Enrollee) Add initial Enrollee functionality for provisioning enterprise (EAP-TLS) configuration object. This commit is handling only the most basic case and a number of TODO items remains to handle more complete CSR generation and config object processing. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 121 ++++++++++++++++++++++++ src/common/dpp.h | 11 +++ src/common/dpp_crypto.c | 156 +++++++++++++++++++++++++++++++ src/common/wpa_ctrl.h | 3 + wpa_supplicant/dpp_supplicant.c | 161 +++++++++++++++++++++++++++++++- 5 files changed, 451 insertions(+), 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index db8a68401..9a57a7095 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -829,6 +829,7 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, const char *tech = "infra"; const char *dpp_name; struct wpabuf *buf, *json; + char *csr = NULL; #ifdef CONFIG_TESTING_OPTIONS if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) { @@ -845,6 +846,17 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4; if (mud_url && mud_url[0]) len += 10 + os_strlen(mud_url); +#ifdef CONFIG_DPP2 + if (auth->csr) { + size_t csr_len; + + csr = base64_encode_no_lf(wpabuf_head(auth->csr), + wpabuf_len(auth->csr), &csr_len); + if (!csr) + return NULL; + len += 30 + csr_len; + } +#endif /* CONFIG_DPP2 */ json = wpabuf_alloc(len); if (!json) return NULL; @@ -871,10 +883,15 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]); json_end_array(json); } + if (csr) { + json_value_sep(json); + json_add_string(json, "pkcs10", csr); + } json_end_object(json); buf = dpp_build_conf_req(auth, wpabuf_head(json)); wpabuf_free(json); + os_free(csr); return buf; } @@ -1263,9 +1280,19 @@ void dpp_auth_deinit(struct dpp_authentication *auth) os_free(conf->connector); wpabuf_free(conf->c_sign_key); + wpabuf_free(conf->certbag); + wpabuf_free(conf->certs); + wpabuf_free(conf->cacert); + os_free(conf->server_name); } #ifdef CONFIG_DPP2 dpp_free_asymmetric_key(auth->conf_key_pkg); + os_free(auth->csrattrs); + wpabuf_free(auth->csr); + wpabuf_free(auth->priv_key); + wpabuf_free(auth->cacert); + wpabuf_free(auth->certbag); + os_free(auth->trusted_eap_server_name); #endif /* CONFIG_DPP2 */ wpabuf_free(auth->net_access_key); dpp_bootstrap_info_free(auth->tmp_own_bi); @@ -2459,6 +2486,58 @@ fail: } +#ifdef CONFIG_DPP2 +static int dpp_parse_cred_dot1x(struct dpp_authentication *auth, + struct dpp_config_obj *conf, + struct json_token *cred) +{ + struct json_token *ent, *name; + + ent = json_get_member(cred, "entCreds"); + if (!ent || ent->type != JSON_OBJECT) { + dpp_auth_fail(auth, "No entCreds in JSON"); + return -1; + } + + conf->certbag = json_get_member_base64(ent, "certBag"); + if (!conf->certbag) { + dpp_auth_fail(auth, "No certBag in JSON"); + return -1; + } + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received certBag", conf->certbag); + conf->certs = dpp_pkcs7_certs(conf->certbag); + if (!conf->certs) { + dpp_auth_fail(auth, "No certificates in certBag"); + return -1; + } + + conf->cacert = json_get_member_base64(ent, "caCert"); + if (conf->cacert) + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received caCert", + conf->cacert); + + name = json_get_member(ent, "trustedEapServerName"); + if (name && + (name->type != JSON_STRING || + has_ctrl_char((const u8 *) name->string, + os_strlen(name->string)))) { + dpp_auth_fail(auth, + "Invalid trustedEapServerName type in JSON"); + return -1; + } + if (name->string) { + wpa_printf(MSG_DEBUG, "DPP: Received trustedEapServerName: %s", + name->string); + conf->server_name = os_strdup(name->string); + if (!conf->server_name) + return -1; + } + + return 0; +} +#endif /* CONFIG_DPP2 */ + + const char * dpp_akm_str(enum dpp_akm akm) { switch (akm) { @@ -2678,6 +2757,12 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth, (auth->peer_version >= 2 && dpp_akm_legacy(conf->akm))) { if (dpp_parse_cred_dpp(auth, conf, cred) < 0) goto fail; +#ifdef CONFIG_DPP2 + } else if (conf->akm == DPP_AKM_DOT1X) { + if (dpp_parse_cred_dot1x(auth, conf, cred) < 0 || + dpp_parse_cred_dpp(auth, conf, cred) < 0) + goto fail; +#endif /* CONFIG_DPP2 */ } else { wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s", token->string); @@ -2694,6 +2779,20 @@ fail: } +#ifdef CONFIG_DPP2 +static u8 * dpp_get_csr_attrs(const u8 *attrs, size_t attrs_len, size_t *len) +{ + const u8 *b64; + u16 b64_len; + + b64 = dpp_get_attr(attrs, attrs_len, DPP_ATTR_CSR_ATTR_REQ, &b64_len); + if (!b64) + return NULL; + return base64_decode((const char *) b64, b64_len, len); +} +#endif /* CONFIG_DPP2 */ + + int dpp_conf_resp_rx(struct dpp_authentication *auth, const struct wpabuf *resp) { @@ -2771,6 +2870,28 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth, } auth->conf_resp_status = status[0]; wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); +#ifdef CONFIG_DPP2 + if (status[0] == DPP_STATUS_CSR_NEEDED) { + u8 *csrattrs; + size_t csrattrs_len; + + wpa_printf(MSG_DEBUG, "DPP: Configurator requested CSR"); + + csrattrs = dpp_get_csr_attrs(unwrapped, unwrapped_len, + &csrattrs_len); + if (!csrattrs) { + dpp_auth_fail(auth, + "Missing or invalid CSR Attributes Request attribute"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: CsrAttrs", csrattrs, csrattrs_len); + os_free(auth->csrattrs); + auth->csrattrs = csrattrs; + auth->csrattrs_len = csrattrs_len; + ret = -2; + goto fail; + } +#endif /* CONFIG_DPP2 */ if (status[0] != DPP_STATUS_OK) { dpp_auth_fail(auth, "Configurator rejected configuration"); goto fail; diff --git a/src/common/dpp.h b/src/common/dpp.h index 8ca41abd2..a84cdc656 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -312,6 +312,10 @@ struct dpp_authentication { int psk_set; enum dpp_akm akm; struct wpabuf *c_sign_key; + struct wpabuf *certbag; + struct wpabuf *certs; + struct wpabuf *cacert; + char *server_name; } conf_obj[DPP_MAX_CONF_OBJ]; unsigned int num_conf_obj; struct dpp_asymmetric_key *conf_key_pkg; @@ -322,7 +326,11 @@ struct dpp_authentication { int akm_use_selector; int configurator_set; u8 transaction_id; + u8 *csrattrs; + size_t csrattrs_len; bool waiting_csr; + struct wpabuf *csr; + struct wpabuf *priv_key; /* DER-encoded private key used for csr */ bool waiting_cert; char *trusted_eap_server_name; struct wpabuf *cacert; @@ -606,6 +614,9 @@ struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len); void dpp_pfs_free(struct dpp_pfs *pfs); +struct wpabuf * dpp_build_csr(struct dpp_authentication *auth); +struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7); + struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp, const char *uri); struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp, diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 8f884fd61..1990b82ff 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "utils/common.h" #include "utils/base64.h" @@ -2664,6 +2665,161 @@ void dpp_pfs_free(struct dpp_pfs *pfs) os_free(pfs); } + +struct wpabuf * dpp_build_csr(struct dpp_authentication *auth) +{ + X509_REQ *req = NULL; + struct wpabuf *buf = NULL; + unsigned char *der; + int der_len; + EVP_PKEY *key; + const EVP_MD *sign_md; + unsigned int hash_len = auth->curve->hash_len; + EC_KEY *eckey; + BIO *out = NULL; + + /* TODO: use auth->csrattrs */ + + /* TODO: support generation of a new private key if csrAttrs requests + * a specific group to be used */ + key = auth->own_protocol_key; + + eckey = EVP_PKEY_get1_EC_KEY(key); + if (!eckey) + goto fail; + der = NULL; + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len <= 0) + goto fail; + wpabuf_free(auth->priv_key); + auth->priv_key = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + if (!auth->priv_key) + goto fail; + + req = X509_REQ_new(); + if (!req || !X509_REQ_set_pubkey(req, key)) + goto fail; + + /* TODO */ + + /* TODO: hash func selection based on csrAttrs */ + if (hash_len == SHA256_MAC_LEN) { + sign_md = EVP_sha256(); + } else if (hash_len == SHA384_MAC_LEN) { + sign_md = EVP_sha384(); + } else if (hash_len == SHA512_MAC_LEN) { + sign_md = EVP_sha512(); + } else { + wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); + goto fail; + } + + if (!X509_REQ_sign(req, key, sign_md)) + goto fail; + + der = NULL; + der_len = i2d_X509_REQ(req, &der); + if (der_len < 0) + goto fail; + buf = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf); + +fail: + BIO_free_all(out); + X509_REQ_free(req); + return buf; +} + + +struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7) +{ +#ifdef OPENSSL_IS_BORINGSSL + CBS pkcs7_cbs; +#else /* OPENSSL_IS_BORINGSSL */ + PKCS7 *p7 = NULL; + const unsigned char *p = wpabuf_head(pkcs7); +#endif /* OPENSSL_IS_BORINGSSL */ + STACK_OF(X509) *certs; + int i, num; + BIO *out = NULL; + size_t rlen; + struct wpabuf *pem = NULL; + int res; + +#ifdef OPENSSL_IS_BORINGSSL + certs = sk_X509_new_null(); + if (!certs) + goto fail; + CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7)); + if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) { + wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } +#else /* OPENSSL_IS_BORINGSSL */ + p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7)); + if (!p7) { + wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + switch (OBJ_obj2nid(p7->type)) { + case NID_pkcs7_signed: + certs = p7->d.sign->cert; + break; + case NID_pkcs7_signedAndEnveloped: + certs = p7->d.signed_and_enveloped->cert; + break; + default: + certs = NULL; + break; + } +#endif /* OPENSSL_IS_BORINGSSL */ + + if (!certs || ((num = sk_X509_num(certs)) == 0)) { + wpa_printf(MSG_INFO, + "DPP: No certificates found in PKCS#7 object"); + goto fail; + } + + out = BIO_new(BIO_s_mem()); + if (!out) + goto fail; + + for (i = 0; i < num; i++) { + X509 *cert = sk_X509_value(certs, i); + + PEM_write_bio_X509(out, cert); + } + + rlen = BIO_ctrl_pending(out); + pem = wpabuf_alloc(rlen); + if (!pem) + goto fail; + res = BIO_read(out, wpabuf_put(pem, 0), rlen); + if (res <= 0) { + wpabuf_free(pem); + goto fail; + } + wpabuf_put(pem, res); + +fail: +#ifdef OPENSSL_IS_BORINGSSL + if (certs) + sk_X509_pop_free(certs, X509_free); +#else /* OPENSSL_IS_BORINGSSL */ + PKCS7_free(p7); +#endif /* OPENSSL_IS_BORINGSSL */ + if (out) + BIO_free_all(out); + + return pem; +} + #endif /* CONFIG_DPP2 */ diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 1fa141520..58ce10141 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -179,6 +179,9 @@ extern "C" { #define DPP_EVENT_CONNECTOR "DPP-CONNECTOR " #define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY " #define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY " +#define DPP_EVENT_SERVER_NAME "DPP-SERVER-NAME " +#define DPP_EVENT_CERTBAG "DPP-CERTBAG " +#define DPP_EVENT_CACERT "DPP-CACERT " #define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR " #define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID " #define DPP_EVENT_CONFIGURATOR_ID "DPP-CONFIGURATOR-ID " diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index b0b657f5e..19d729f4d 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -49,6 +49,7 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s, #ifdef CONFIG_DPP2 static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx); +static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s); #endif /* CONFIG_DPP2 */ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -1218,6 +1219,106 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, } } +#ifdef CONFIG_DPP2 + if (conf->akm == DPP_AKM_DOT1X) { + int i; + char name[100], blobname[128]; + struct wpa_config_blob *blob; + + ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; + + if (conf->cacert) { + /* caCert is DER-encoded X.509v3 certificate for the + * server certificate if that is different from the + * trust root included in certBag. */ + /* TODO: ssid->eap.cert.ca_cert */ + } + + if (conf->certs) { + wpa_hexdump_buf(MSG_INFO, "JKM:certs", + conf->certs); + for (i = 0; ; i++) { + os_snprintf(name, sizeof(name), "dpp-certs-%d", + i); + if (!wpa_config_get_blob(wpa_s->conf, name)) + break; + } + + blob = os_zalloc(sizeof(*blob)); + if (!blob) + goto fail; + blob->len = wpabuf_len(conf->certs); + blob->name = os_strdup(name); + blob->data = os_malloc(blob->len); + if (!blob->name || !blob->data) { + wpa_config_free_blob(blob); + goto fail; + } + os_memcpy(blob->data, wpabuf_head(conf->certs), + blob->len); + os_snprintf(blobname, sizeof(blobname), "blob://%s", + name); + wpa_config_set_blob(wpa_s->conf, blob); + wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s", + name); + ssid->eap.cert.client_cert = os_strdup(blobname); + if (!ssid->eap.cert.client_cert) + goto fail; + + /* TODO: ssid->eap.identity from own certificate */ + if (wpa_config_set(ssid, "identity", "\"dpp-ent\"", + 0) < 0) + goto fail; + } + + if (auth->priv_key) { + for (i = 0; ; i++) { + os_snprintf(name, sizeof(name), "dpp-key-%d", + i); + if (!wpa_config_get_blob(wpa_s->conf, name)) + break; + } + + wpa_hexdump_buf(MSG_INFO, "JKM:privkey", + auth->priv_key); + blob = os_zalloc(sizeof(*blob)); + if (!blob) + goto fail; + blob->len = wpabuf_len(auth->priv_key); + blob->name = os_strdup(name); + blob->data = os_malloc(blob->len); + if (!blob->name || !blob->data) { + wpa_config_free_blob(blob); + goto fail; + } + os_memcpy(blob->data, wpabuf_head(auth->priv_key), + blob->len); + os_snprintf(blobname, sizeof(blobname), "blob://%s", + name); + wpa_config_set_blob(wpa_s->conf, blob); + wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s", + name); + ssid->eap.cert.private_key = os_strdup(blobname); + if (!ssid->eap.cert.private_key) + goto fail; + } + + if (conf->server_name) { + ssid->eap.cert.domain_suffix_match = + os_strdup(conf->server_name); + if (!ssid->eap.cert.domain_suffix_match) + goto fail; + } + + /* TODO: Use entCreds::eapMethods */ + if (wpa_config_set(ssid, "eap", "TLS", 0) < 0) + goto fail; + } +#endif /* CONFIG_DPP2 */ + os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len); wpa_s->dpp_last_ssid_len = conf->ssid_len; @@ -1346,6 +1447,32 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s, } } +#ifdef CONFIG_DPP2 + if (conf->certbag) { + char *b64; + + b64 = base64_encode_no_lf(wpabuf_head(conf->certbag), + wpabuf_len(conf->certbag), NULL); + if (b64) + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64); + os_free(b64); + } + + if (conf->cacert) { + char *b64; + + b64 = base64_encode_no_lf(wpabuf_head(conf->cacert), + wpabuf_len(conf->cacert), NULL); + if (b64) + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64); + os_free(b64); + } + + if (conf->server_name) + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s", + conf->server_name); +#endif /* CONFIG_DPP2 */ + return wpas_dpp_process_config(wpa_s, auth, conf); } @@ -1376,6 +1503,29 @@ static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s, } +#ifdef CONFIG_DPP2 +static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct dpp_authentication *auth = wpa_s->dpp_auth; + + if (!auth || !auth->csrattrs) + return; + + wpa_printf(MSG_DEBUG, "DPP: Build CSR"); + wpabuf_free(auth->csr); + /* TODO: Additional information needed for CSR based on csrAttrs */ + auth->csr = dpp_build_csr(auth); + if (!auth->csr) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + } + + wpas_dpp_start_gas_client(wpa_s); +} +#endif /* CONFIG_DPP2 */ + + static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, @@ -1420,7 +1570,15 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, goto fail; } - if (dpp_conf_resp_rx(auth, resp) < 0) { + res = dpp_conf_resp_rx(auth, resp); +#ifdef CONFIG_DPP2 + if (res == -2) { + wpa_printf(MSG_DEBUG, "DPP: CSR needed"); + eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL); + return; + } +#endif /* CONFIG_DPP2 */ + if (res < 0) { wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); goto fail; } @@ -3115,6 +3273,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL); dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = NULL; wpas_dpp_chirp_stop(wpa_s); From 5abf8ad9b2bf2fcec31adec86dd4e8346f51406b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 15 Jun 2020 20:20:50 +0300 Subject: [PATCH 0685/1105] tests: DPP enterprise provisioning Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 146 +++++++++++++++++++++++++++++++++++ tests/hwsim/wpasupplicant.py | 6 +- 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index a15a8a689..9e79e4e00 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5619,3 +5619,149 @@ def test_dpp_qr_code_auth_rand_mac_addr(dev, apdev): run_dpp_qr_code_auth_unicast(dev, apdev, None) finally: dev[0].set("gas_rand_mac_addr", "0") + +def dpp_sign_cert(cacert, cakey, csr_der): + csr = OpenSSL.crypto.load_certificate_request(OpenSSL.crypto.FILETYPE_ASN1, + csr_der) + cert = OpenSSL.crypto.X509() + cert.set_serial_number(12345) + cert.gmtime_adj_notBefore(-10) + cert.gmtime_adj_notAfter(100000) + cert.set_pubkey(csr.get_pubkey()) + dn = cert.get_subject() + dn.CN = "dpp-tls-test" + cert.set_subject(dn) + cert.set_version(2) + cert.add_extensions([ + OpenSSL.crypto.X509Extension(b"basicConstraints", True, + b"CA:FALSE"), + OpenSSL.crypto.X509Extension(b"subjectKeyIdentifier", False, + b"hash", subject=cert), + OpenSSL.crypto.X509Extension(b"authorityKeyIdentifier", False, + b"keyid:always", issuer=cacert), + ]) + cert.set_issuer(cacert.get_subject()) + cert.sign(cakey, "sha256") + return cert + +def test_dpp_enterprise(dev, apdev, params): + """DPP and enterprise EAP-TLS provisioning""" + try: + dev[0].set("dpp_config_processing", "2") + run_dpp_enterprise(dev, apdev, params) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_enterprise(dev, apdev, params): + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + cert_file = params['prefix'] + ".cert.pem" + pkcs7_file = params['prefix'] + ".pkcs7.der" + + params = {"ssid": "dpp-ent", + "wpa": "2", + "wpa_key_mgmt": "WPA-EAP", + "rsn_pairwise": "CCMP", + "ieee8021x": "1", + "eap_server": "1", + "eap_user_file": "auth_serv/eap_user.conf", + "ca_cert": "auth_serv/ec-ca.pem", + "server_cert": "auth_serv/ec-server.pem", + "private_key": "auth_serv/ec-server.key"} + hapd = hostapd.add_ap(apdev[0], params) + + with open("auth_serv/ec-ca.pem", "rb") as f: + res = f.read() + cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + res) + + with open("auth_serv/ec-ca.key", "rb") as f: + res = f.read() + cakey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, res) + + conf_id = dev[1].dpp_configurator_add() + id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) + uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + dev[0].dpp_listen(2412) + csrattrs = "MAsGCSqGSIb3DQEJBw==" + id1 = dev[1].dpp_auth_init(uri=uri0, configurator=conf_id, conf="sta-dot1x", + csrattrs=csrattrs, ssid="dpp-ent") + + ev = dev[1].wait_event(["DPP-CSR"], timeout=10) + if ev is None: + raise Exception("Configurator did not receive CSR") + id1_csr = int(ev.split(' ')[1].split('=')[1]) + if id1 != id1_csr: + raise Exception("Peer bootstrapping ID mismatch in CSR event") + csr = ev.split(' ')[2] + if not csr.startswith("csr="): + raise Exception("Could not parse CSR event: " + ev) + csr = csr[4:] + csr = base64.b64decode(csr.encode()) + logger.info("CSR: " + binascii.hexlify(csr).decode()) + + cert = dpp_sign_cert(cacert, cakey, csr) + with open(cert_file, 'wb') as f: + f.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, + cert)) + subprocess.check_call(['openssl', 'crl2pkcs7', '-nocrl', + '-certfile', cert_file, + '-certfile', 'auth_serv/ec-ca.pem', + '-outform', 'DER', '-out', pkcs7_file]) + + #caCert = base64.b64encode(b"TODO").decode() + #res = dev[1].request("DPP_CA_SET peer=%d name=caCert value=%s" % (id1, caCert)) + #if "OK" not in res: + # raise Exception("Failed to set caCert") + + name = "server.w1.fi" + res = dev[1].request("DPP_CA_SET peer=%d name=trustedEapServerName value=%s" % (id1, name)) + if "OK" not in res: + raise Exception("Failed to set trustedEapServerName") + + with open(pkcs7_file, 'rb') as f: + pkcs7_der = f.read() + certbag = base64.b64encode(pkcs7_der).decode() + res = dev[1].request("DPP_CA_SET peer=%d name=certBag value=%s" % (id1, certbag)) + if "OK" not in res: + raise Exception("Failed to set certBag") + + ev = dev[1].wait_event(["DPP-CONF-SENT", "DPP-CONF-FAILED"], timeout=5) + if ev is None: + raise Exception("DPP configuration not completed (Configurator)") + if "DPP-CONF-FAILED" in ev: + raise Exception("DPP configuration did not succeed (Configurator)") + + ev = dev[0].wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"], + timeout=1) + if ev is None: + raise Exception("DPP configuration not completed (Enrollee)") + if "DPP-CONF-FAILED" in ev: + raise Exception("DPP configuration did not succeed (Enrollee)") + + ev = dev[0].wait_event(["DPP-CERTBAG"], timeout=1) + if ev is None: + raise Exception("DPP-CERTBAG not reported") + certbag = base64.b64decode(ev.split(' ')[1].encode()) + if certbag != pkcs7_der: + raise Exception("DPP-CERTBAG mismatch") + + #ev = dev[0].wait_event(["DPP-CACERT"], timeout=1) + #if ev is None: + # raise Exception("DPP-CACERT not reported") + + ev = dev[0].wait_event(["DPP-SERVER-NAME"], timeout=1) + if ev is None: + raise Exception("DPP-SERVER-NAME not reported") + if ev.split(' ')[1] != name: + raise Exception("DPP-SERVER-NAME mismatch: " + ev) + + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1) + if ev is None: + raise Exception("DPP network profile not generated") + id = ev.split(' ')[1] + + dev[0].wait_connected() diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 88e64340a..92c855227 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1529,7 +1529,8 @@ class WpaSupplicant: extra=None, own=None, role=None, neg_freq=None, ssid=None, passphrase=None, expect_fail=False, tcp_addr=None, tcp_port=None, conn_status=False, - ssid_charset=None, nfc_uri=None, netrole=None): + ssid_charset=None, nfc_uri=None, netrole=None, + csrattrs=None): cmd = "DPP_AUTH_INIT" if peer is None: if nfc_uri: @@ -1563,6 +1564,8 @@ class WpaSupplicant: cmd += " conn_status=1" if netrole: cmd += " netrole=" + netrole + if csrattrs: + cmd += " csrattrs=" + csrattrs res = self.request(cmd) if expect_fail: if "FAIL" not in res: @@ -1570,6 +1573,7 @@ class WpaSupplicant: return if "OK" not in res: raise Exception("Failed to initiate DPP Authentication") + return int(peer) def dpp_pkex_init(self, identifier, code, role=None, key=None, curve=None, extra=None, use_id=None, allow_fail=False): From dbbb0d5b82e388f25480a76af538cfdd7d332231 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 16 Jun 2020 13:16:39 +0300 Subject: [PATCH 0686/1105] OpenSSL: Use EVP-based interface for ECDSA sign/verify The low level ECDSA interface is not available in BoringSSL and has been deprecetated in OpenSSL 3.0, so move to using a higher layer EVP-based interface for performing the ECDSA sign/verify operations. Signed-off-by: Jouni Malinen --- src/crypto/crypto_openssl.c | 43 +++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index 54bfcd25f..72f93c192 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -2187,8 +2187,6 @@ size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) struct crypto_ec_key { EVP_PKEY *pkey; EC_KEY *eckey; - BIGNUM *kinv; - BIGNUM *rp; }; @@ -2215,8 +2213,6 @@ struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len) goto fail; } - if (ECDSA_sign_setup(key->eckey, NULL, &key->kinv, &key->rp) != 1) - goto fail; return key; fail: crypto_ec_key_deinit(key); @@ -2253,8 +2249,6 @@ void crypto_ec_key_deinit(struct crypto_ec_key *key) { if (key) { EVP_PKEY_free(key->pkey); - BN_clear_free(key->kinv); - BN_clear_free(key->rp); os_free(key); } } @@ -2282,22 +2276,27 @@ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, size_t len) { + EVP_PKEY_CTX *pkctx; struct wpabuf *sig_der; - int res; - unsigned int sig_len; + size_t sig_len; - sig_len = ECDSA_size(key->eckey); + sig_len = EVP_PKEY_size(key->pkey); sig_der = wpabuf_alloc(sig_len); if (!sig_der) return NULL; - res = ECDSA_sign_ex(0, data, len, wpabuf_put(sig_der, 0), &sig_len, - key->kinv, key->rp, key->eckey); - if (res != 1) { - wpabuf_free(sig_der); - return NULL; - } - wpabuf_put(sig_der, sig_len); + pkctx = EVP_PKEY_CTX_new(key->pkey, NULL); + if (!pkctx || + EVP_PKEY_sign_init(pkctx) <= 0 || + EVP_PKEY_sign(pkctx, wpabuf_put(sig_der, 0), &sig_len, + data, len) <= 0) { + wpabuf_free(sig_der); + sig_der = NULL; + } else { + wpabuf_put(sig_der, sig_len); + } + + EVP_PKEY_CTX_free(pkctx); return sig_der; } @@ -2305,15 +2304,21 @@ struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, size_t len, const u8 *sig, size_t sig_len) { + EVP_PKEY_CTX *pkctx; int ret; - ret = ECDSA_verify(0, data, len, sig, sig_len, key->eckey); + pkctx = EVP_PKEY_CTX_new(key->pkey, NULL); + if (!pkctx || EVP_PKEY_verify_init(pkctx) <= 0) { + EVP_PKEY_CTX_free(pkctx); + return -1; + } + + ret = EVP_PKEY_verify(pkctx, sig, sig_len, data, len); + EVP_PKEY_CTX_free(pkctx); if (ret == 1) return 1; /* signature ok */ if (ret == 0) return 0; /* incorrect signature */ - wpa_printf(MSG_INFO, "OpenSSL: ECDSA_verify() failed: %s", - ERR_error_string(ERR_get_error(), NULL)); return -1; } From c98db9f1f83d1759a1f278da50b6b3d8bf521820 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 17 Jun 2020 12:22:08 +0300 Subject: [PATCH 0687/1105] DPP2: Add challengePassword into CSR Derive challengePassword from bk and add it into the CSR. Signed-off-by: Jouni Malinen --- src/common/dpp.h | 1 + src/common/dpp_crypto.c | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/common/dpp.h b/src/common/dpp.h index a84cdc656..a43b85fc2 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -120,6 +120,7 @@ enum dpp_connector_key { #define DPP_MAX_NONCE_LEN 32 #define DPP_MAX_HASH_LEN 64 #define DPP_MAX_SHARED_SECRET_LEN 66 +#define DPP_CP_LEN 64 struct dpp_curve_params { const char *name; diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 1990b82ff..744f099ce 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2677,6 +2677,10 @@ struct wpabuf * dpp_build_csr(struct dpp_authentication *auth) unsigned int hash_len = auth->curve->hash_len; EC_KEY *eckey; BIO *out = NULL; + u8 cp[DPP_CP_LEN]; + char *password; + size_t password_len; + int res; /* TODO: use auth->csrattrs */ @@ -2701,6 +2705,26 @@ struct wpabuf * dpp_build_csr(struct dpp_authentication *auth) if (!req || !X509_REQ_set_pubkey(req, key)) goto fail; + /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ + if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, + "CSR challengePassword", cp, DPP_CP_LEN) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", + cp, DPP_CP_LEN); + password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len); + forced_memzero(cp, DPP_CP_LEN); + if (!password) + goto fail; + + res = X509_REQ_add1_attr_by_NID(req, NID_pkcs9_challengePassword, + V_ASN1_UTF8STRING, + (const unsigned char *) password, + password_len); + bin_clear_free(password, password_len); + if (!res) + goto fail; + /* TODO */ /* TODO: hash func selection based on csrAttrs */ From 3b60f11741ed59e17baa5578316b29166749d8b5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 17 Jun 2020 20:33:07 +0300 Subject: [PATCH 0688/1105] DPP2: Validate CSR on Configurator before forwarding to CA/RA Parse the received CSR, verify that it has been signed correctly, and verify that the challengePassword is present and matches the derived cp. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 13 +++++ src/common/dpp.h | 2 + src/common/dpp_crypto.c | 119 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+) diff --git a/src/common/dpp.c b/src/common/dpp.c index 9a57a7095..dc66ce913 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1694,6 +1694,11 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, size_t len[1]; enum dpp_status_error status; + if (auth->force_conf_resp_status != DPP_STATUS_OK) { + status = auth->force_conf_resp_status; + goto forced_status; + } + if (netrole == DPP_NETROLE_CONFIGURATOR) { #ifdef CONFIG_DPP2 env_data = dpp_build_enveloped_data(auth); @@ -1715,6 +1720,7 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, status = DPP_STATUS_CSR_NEEDED; else status = DPP_STATUS_CONFIGURE_FAILURE; +forced_status: auth->conf_resp_status = status; /* { E-nonce, configurationObject[, sendConnStatus]}ke */ @@ -2040,6 +2046,12 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, char *txt; wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req); + if (dpp_validate_csr(auth, cert_req) < 0) { + wpa_printf(MSG_DEBUG, "DPP: CSR is not valid"); + auth->force_conf_resp_status = DPP_STATUS_CSR_BAD; + goto cont; + } + wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA"); txt = base64_encode_no_lf(wpabuf_head(cert_req), wpabuf_len(cert_req), NULL); if (!txt) @@ -2051,6 +2063,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, auth->waiting_cert = true; goto fail; } +cont: #endif /* CONFIG_DPP2 */ resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole, diff --git a/src/common/dpp.h b/src/common/dpp.h index a43b85fc2..f4398aa0d 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -250,6 +250,7 @@ struct dpp_authentication { enum dpp_connector_key reconfig_connector_key; enum dpp_status_error auth_resp_status; enum dpp_status_error conf_resp_status; + enum dpp_status_error force_conf_resp_status; u8 peer_mac_addr[ETH_ALEN]; u8 i_nonce[DPP_MAX_NONCE_LEN]; u8 r_nonce[DPP_MAX_NONCE_LEN]; @@ -617,6 +618,7 @@ void dpp_pfs_free(struct dpp_pfs *pfs); struct wpabuf * dpp_build_csr(struct dpp_authentication *auth); struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7); +int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr); struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp, const char *uri); diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 744f099ce..916aeeff8 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2844,6 +2844,125 @@ fail: return pem; } + +int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr) +{ + X509_REQ *req; + const unsigned char *pos; + EVP_PKEY *pkey; + int res, loc, ret = -1; + X509_ATTRIBUTE *attr; + ASN1_TYPE *type; + ASN1_STRING *str; + unsigned char *utf8 = NULL; + unsigned char *cp = NULL; + size_t cp_len; + u8 exp_cp[DPP_CP_LEN]; + unsigned int hash_len = auth->curve->hash_len; + + pos = wpabuf_head(csr); + req = d2i_X509_REQ(NULL, &pos, wpabuf_len(csr)); + if (!req) { + wpa_printf(MSG_DEBUG, "DPP: Failed to parse CSR"); + return -1; + } + + pkey = X509_REQ_get_pubkey(req); + if (!pkey) { + wpa_printf(MSG_DEBUG, "DPP: Failed to get public key from CSR"); + goto fail; + } + + res = X509_REQ_verify(req, pkey); + EVP_PKEY_free(pkey); + if (res != 1) { + wpa_printf(MSG_DEBUG, + "DPP: CSR does not have a valid signature"); + goto fail; + } + + loc = X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1); + if (loc < 0) { + wpa_printf(MSG_DEBUG, + "DPP: CSR does not include challengePassword"); + goto fail; + } + + attr = X509_REQ_get_attr(req, loc); + if (!attr) { + wpa_printf(MSG_DEBUG, + "DPP: Could not get challengePassword attribute"); + goto fail; + } + + type = X509_ATTRIBUTE_get0_type(attr, 0); + if (!type) { + wpa_printf(MSG_DEBUG, + "DPP: Could not get challengePassword attribute type"); + goto fail; + } + + res = ASN1_TYPE_get(type); + /* This is supposed to be UTF8String, but allow other strings as well + * since challengePassword is using ASCII (base64 encoded). */ + if (res != V_ASN1_UTF8STRING && res != V_ASN1_PRINTABLESTRING && + res != V_ASN1_IA5STRING) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected challengePassword attribute type %d", + res); + goto fail; + } + + str = X509_ATTRIBUTE_get0_data(attr, 0, res, NULL); + if (!str) { + wpa_printf(MSG_DEBUG, + "DPP: Could not get ASN.1 string for challengePassword"); + goto fail; + } + + res = ASN1_STRING_to_UTF8(&utf8, str); + if (res < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Could not get UTF8 version of challengePassword"); + goto fail; + } + + cp = base64_decode((const char *) utf8, res, &cp_len); + OPENSSL_free(utf8); + if (!cp) { + wpa_printf(MSG_DEBUG, + "DPP: Could not base64 decode challengePassword"); + goto fail; + } + if (cp_len != DPP_CP_LEN) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected cp length (%zu) in CSR challengePassword", + cp_len); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword", + cp, cp_len); + + /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ + if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, + "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", + exp_cp, DPP_CP_LEN); + if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: CSR challengePassword does not match calculated cp"); + goto fail; + } + + ret = 0; +fail: + os_free(cp); + X509_REQ_free(req); + return ret; +} + #endif /* CONFIG_DPP2 */ From 3a3eded0dc4a797651d75467d75f81a95fd85eb8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 17 Jun 2020 21:39:47 +0300 Subject: [PATCH 0689/1105] DPP2: Allow CSR processing by CA/RA to reject configuration "DPP_CA_SET name=status value=" can now be used to explicitly indicate that CSR was rejected by CA/RA. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 44 ++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 19d729f4d..9c3776f19 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3628,6 +3628,27 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) } +static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s, + struct dpp_authentication *auth) +{ + struct wpabuf *resp; + + resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len, + auth->e_netrole, true); + if (!resp) + return -1; + if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx, + resp) < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Could not find pending GAS response"); + wpabuf_free(resp); + return -1; + } + auth->conf_resp = resp; + return 0; +} + + int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) { int peer; @@ -3663,6 +3684,11 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) return -1; pos += 6; + if (os_strncmp(pos, "status ", 7) == 0) { + auth->force_conf_resp_status = atoi(value); + return wpas_dpp_build_conf_resp(wpa_s, auth); + } + if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) { os_free(auth->trusted_eap_server_name); auth->trusted_eap_server_name = os_strdup(value); @@ -3682,25 +3708,9 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) } if (os_strncmp(pos, "certBag ", 8) == 0) { - struct wpabuf *resp; - wpabuf_free(auth->certbag); auth->certbag = buf; - - resp = dpp_build_conf_resp(auth, auth->e_nonce, - auth->curve->nonce_len, - auth->e_netrole, true); - if (!resp) - return -1; - if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx, - resp) < 0) { - wpa_printf(MSG_DEBUG, - "DPP: Could not find pending GAS response"); - wpabuf_free(resp); - return -1; - } - auth->conf_resp = resp; - return 0; + return wpas_dpp_build_conf_resp(wpa_s, auth); } wpabuf_free(buf); From 725d98a513429a49feadbc1e55263d3fc41bb703 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 17 Jun 2020 21:42:35 +0300 Subject: [PATCH 0690/1105] tests: DPP and enterprise provisioning and CSR getting rejected Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 9e79e4e00..4de7dd396 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5765,3 +5765,37 @@ def run_dpp_enterprise(dev, apdev, params): id = ev.split(' ')[1] dev[0].wait_connected() + +def test_dpp_enterprise_reject(dev, apdev, params): + """DPP and enterprise EAP-TLS provisioning and CSR getting rejected""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + conf_id = dev[1].dpp_configurator_add() + id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) + uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + dev[0].dpp_listen(2412) + csrattrs = "MAsGCSqGSIb3DQEJBw==" + id1 = dev[1].dpp_auth_init(uri=uri0, configurator=conf_id, conf="sta-dot1x", + csrattrs=csrattrs, ssid="dpp-ent") + + ev = dev[1].wait_event(["DPP-CSR"], timeout=10) + if ev is None: + raise Exception("Configurator did not receive CSR") + + res = dev[1].request("DPP_CA_SET peer=%d name=status value=5" % id1) + if "OK" not in res: + raise Exception("Failed to set status") + + ev = dev[1].wait_event(["DPP-CONF-SENT", "DPP-CONF-FAILED"], timeout=5) + if ev is None: + raise Exception("DPP configuration not completed (Configurator)") + if "DPP-CONF-FAILED" in ev: + raise Exception("DPP configuration did not succeed (Configurator)") + + ev = dev[0].wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"], + timeout=1) + if ev is None: + raise Exception("DPP configuration not completed (Enrollee)") + if "DPP-CONF-FAILED" not in ev: + raise Exception("DPP configuration did not fail (Enrollee)") From ffc8ae507e47bf7fd5e352017899828bfcf47f5c Mon Sep 17 00:00:00 2001 From: Alan Chen Date: Tue, 16 Jun 2020 15:33:18 -0700 Subject: [PATCH 0691/1105] Define a new QCA vendor attribute for Optimized Power Management Define a new attribute configuring Optimized Power Management. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 2136c020c..73b0aba31 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2216,6 +2216,10 @@ enum qca_wlan_vendor_attr_config { * higher value configuration shall be returned with a failure. */ QCA_WLAN_VENDOR_ATTR_CONFIG_NSS = 70, + /* 8-bit unsigned value to trigger Optimized Power Management: + * 1-Enable, 0-Disable + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT = 71, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, From 697fa0c4bde095b2a509d156f85a27fc91f3effc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 18 Jun 2020 12:09:00 +0300 Subject: [PATCH 0692/1105] DPP2: Do not try to proceed with GAS client if CSR building fails This error path was supposed to stop instead of continuing to wpas_dpp_start_gas_client(). Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 9c3776f19..7e2cdcd31 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1519,6 +1519,7 @@ static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx) if (!auth->csr) { dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; + return; } wpas_dpp_start_gas_client(wpa_s); From 1f86b2c248379920d4e40a667061563622a2cefc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 18 Jun 2020 12:10:23 +0300 Subject: [PATCH 0693/1105] DPP2: CSR generation in TCP Client/Enrollee This was previously covered for the DPP over Public Action frames, but the DPP over TCP case was missed. Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index fc53b8a0b..2cf251652 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -68,6 +68,7 @@ static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx); static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx); static void dpp_controller_auth_success(struct dpp_connection *conn, int initiator); +static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx); static void dpp_connection_free(struct dpp_connection *conn) @@ -81,6 +82,7 @@ static void dpp_connection_free(struct dpp_connection *conn) } eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout, conn, NULL); + eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL); wpabuf_free(conn->msg); wpabuf_free(conn->msg_out); dpp_auth_deinit(conn->auth); @@ -1047,6 +1049,27 @@ static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, } +static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + struct dpp_authentication *auth = conn->auth; + + if (!auth || !auth->csrattrs) + return; + + wpa_printf(MSG_DEBUG, "DPP: Build CSR"); + wpabuf_free(auth->csr); + /* TODO: Additional information needed for CSR based on csrAttrs */ + auth->csr = dpp_build_csr(auth); + if (!auth->csr) { + dpp_connection_remove(conn); + return; + } + + dpp_controller_start_gas_client(conn); +} + + static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) { struct dpp_authentication *auth = conn->auth; @@ -1062,6 +1085,11 @@ static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) else res = -1; wpabuf_free(resp); + if (res == -2) { + wpa_printf(MSG_DEBUG, "DPP: CSR needed"); + eloop_register_timeout(0, 0, dpp_tcp_build_csr, conn, NULL); + return 0; + } if (res < 0) { wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); return -1; From 0f9463d6ee027c915cd775c8b161d71788c04bd4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 18 Jun 2020 12:56:51 +0300 Subject: [PATCH 0694/1105] DPP2: CSR wait in Configurator when using TCP Make Configurator wait for CSR (i.e., another Config Request) when using DPP over TCP similarly to the over Public Action frame case. Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 2cf251652..6b21b8102 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -143,6 +143,12 @@ static void dpp_controller_gas_done(struct dpp_connection *conn) struct dpp_authentication *auth = conn->auth; void *msg_ctx; + if (auth->waiting_csr) { + wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR"); + conn->on_tcp_tx_complete_gas_done = 0; + return; + } + if (auth->peer_version >= 2 && auth->conf_resp_status == DPP_STATUS_OK) { wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); From a352c7230d2ef45dc19fd9489ebbb92cd1cb3c6c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 18 Jun 2020 13:03:29 +0300 Subject: [PATCH 0695/1105] DPP2: Comeback delay response for certificate in over TCP case Send out the GAS Initial Response with comeback delay when Configurator is operating over TCP. Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 6b21b8102..632cb4ccd 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -1023,6 +1023,30 @@ static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, return -1; resp = dpp_conf_req_rx(auth, pos, slen); + if (!resp && auth->waiting_cert) { + wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); + buf = wpabuf_alloc(4 + 18); + if (!buf) + return -1; + + wpabuf_put_be32(buf, 18); + + wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP); + wpabuf_put_u8(buf, dialog_token); + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + wpabuf_put_le16(buf, 500); /* GAS Comeback Delay */ + + dpp_write_adv_proto(buf); + wpabuf_put_le16(buf, 0); /* Query Response Length */ + + /* Send Config Response over TCP */ + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = buf; + dpp_tcp_send(conn); + return 0; + } if (!resp) return -1; From 68d9586a4683888189143441141fc22ccb540cb5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 18 Jun 2020 13:14:25 +0300 Subject: [PATCH 0696/1105] DPP2: GAS Comeback Request for the TCP case Make the Enrollee handle GAS comeback delay when performing DPP over TCP. Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 47 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 632cb4ccd..de52d3afa 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -38,6 +38,7 @@ struct dpp_connection { unsigned int on_tcp_tx_complete_gas_done:1; unsigned int on_tcp_tx_complete_remove:1; unsigned int on_tcp_tx_complete_auth_ok:1; + u8 gas_dialog_token; }; /* Remote Controller */ @@ -69,6 +70,7 @@ static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx); static void dpp_controller_auth_success(struct dpp_connection *conn, int initiator); static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx); +static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx); static void dpp_connection_free(struct dpp_connection *conn) @@ -83,6 +85,7 @@ static void dpp_connection_free(struct dpp_connection *conn) eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout, conn, NULL); eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL); + eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL); wpabuf_free(conn->msg); wpabuf_free(conn->msg_out); dpp_auth_deinit(conn->auth); @@ -1150,13 +1153,38 @@ static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) } +static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + struct dpp_authentication *auth = conn->auth; + struct wpabuf *msg; + + if (!auth) + return; + + wpa_printf(MSG_DEBUG, "DPP: Send GAS Comeback Request"); + msg = wpabuf_alloc(4 + 2); + if (!msg) + return; + wpabuf_put_be32(msg, 2); + wpabuf_put_u8(msg, WLAN_PA_GAS_COMEBACK_REQ); + wpabuf_put_u8(msg, conn->gas_dialog_token); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); + + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = msg; + dpp_tcp_send(conn); +} + + static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, size_t len) { struct wpabuf *buf; u8 dialog_token; const u8 *pos, *end, *next, *adv_proto; - u16 status, slen; + u16 status, slen, comeback_delay; if (len < 5 + 2) return -1; @@ -1174,7 +1202,8 @@ static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, return -1; } pos += 2; - pos += 2; /* ignore GAS Comeback Delay */ + comeback_delay = WPA_GET_LE16(pos); + pos += 2; adv_proto = pos++; slen = *pos++; @@ -1199,6 +1228,20 @@ static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, if (slen > end - pos) return -1; + if (comeback_delay) { + unsigned int secs, usecs; + + conn->gas_dialog_token = dialog_token; + secs = (comeback_delay * 1024) / 1000000; + usecs = comeback_delay * 1024 - secs * 1000000; + wpa_printf(MSG_DEBUG, "DPP: Comeback delay: %u", + comeback_delay); + eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL); + eloop_register_timeout(secs, usecs, dpp_tcp_gas_query_comeback, + conn, NULL); + return 0; + } + buf = wpabuf_alloc(slen); if (!buf) return -1; From 18e013a93fd5d71e75cbaec1e547141456d5d8fb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 18 Jun 2020 13:38:37 +0300 Subject: [PATCH 0697/1105] DPP2: GAS comeback request processing for Configurator over TCP Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 173 +++++++++++++++++++++++++++++++------------ 1 file changed, 127 insertions(+), 46 deletions(-) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index de52d3afa..39cb6fd3e 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -38,7 +38,9 @@ struct dpp_connection { unsigned int on_tcp_tx_complete_gas_done:1; unsigned int on_tcp_tx_complete_remove:1; unsigned int on_tcp_tx_complete_auth_ok:1; + unsigned int gas_comeback_in_progress:1; u8 gas_dialog_token; + struct wpabuf *gas_resp; }; /* Remote Controller */ @@ -88,6 +90,7 @@ static void dpp_connection_free(struct dpp_connection *conn) eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL); wpabuf_free(conn->msg); wpabuf_free(conn->msg_out); + wpabuf_free(conn->gas_resp); dpp_auth_deinit(conn->auth); os_free(conn); } @@ -976,14 +979,91 @@ static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, } +static int dpp_tcp_send_comeback_delay(struct dpp_connection *conn, u8 action) +{ + struct wpabuf *buf; + size_t len = 18; + + if (action == WLAN_PA_GAS_COMEBACK_RESP) + len++; + + buf = wpabuf_alloc(4 + len); + if (!buf) + return -1; + + wpabuf_put_be32(buf, len); + + wpabuf_put_u8(buf, action); + wpabuf_put_u8(buf, conn->gas_dialog_token); + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + if (action == WLAN_PA_GAS_COMEBACK_RESP) + wpabuf_put_u8(buf, 0); + wpabuf_put_le16(buf, 500); /* GAS Comeback Delay */ + + dpp_write_adv_proto(buf); + wpabuf_put_le16(buf, 0); /* Query Response Length */ + + /* Send Config Response over TCP */ + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = buf; + dpp_tcp_send(conn); + return 0; +} + + +static int dpp_tcp_send_gas_resp(struct dpp_connection *conn, u8 action, + struct wpabuf *resp) +{ + struct wpabuf *buf; + size_t len; + + if (!resp) + return -1; + + len = 18 + wpabuf_len(resp); + if (action == WLAN_PA_GAS_COMEBACK_RESP) + len++; + + buf = wpabuf_alloc(4 + len); + if (!buf) { + wpabuf_free(resp); + return -1; + } + + wpabuf_put_be32(buf, len); + + wpabuf_put_u8(buf, action); + wpabuf_put_u8(buf, conn->gas_dialog_token); + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + if (action == WLAN_PA_GAS_COMEBACK_RESP) + wpabuf_put_u8(buf, 0); + wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */ + + dpp_write_adv_proto(buf); + dpp_write_gas_query(buf, resp); + wpabuf_free(resp); + + /* Send Config Response over TCP; GAS fragmentation is taken care of by + * the Relay */ + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = buf; + conn->on_tcp_tx_complete_gas_done = 1; + dpp_tcp_send(conn); + return 0; +} + + static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, size_t len) { const u8 *pos, *end, *next; - u8 dialog_token; const u8 *adv_proto; u16 slen; - struct wpabuf *resp, *buf; + struct wpabuf *resp; struct dpp_authentication *auth = conn->auth; if (len < 1 + 2) @@ -1001,7 +1081,7 @@ static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, pos = msg; end = msg + len; - dialog_token = *pos++; + conn->gas_dialog_token = *pos++; adv_proto = pos++; slen = *pos++; if (*adv_proto != WLAN_EID_ADV_PROTO || @@ -1028,57 +1108,53 @@ static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, resp = dpp_conf_req_rx(auth, pos, slen); if (!resp && auth->waiting_cert) { wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); - buf = wpabuf_alloc(4 + 18); - if (!buf) - return -1; - - wpabuf_put_be32(buf, 18); - - wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP); - wpabuf_put_u8(buf, dialog_token); - wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); - wpabuf_put_le16(buf, 500); /* GAS Comeback Delay */ - - dpp_write_adv_proto(buf); - wpabuf_put_le16(buf, 0); /* Query Response Length */ - - /* Send Config Response over TCP */ - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = buf; - dpp_tcp_send(conn); - return 0; + conn->gas_comeback_in_progress = 1; + return dpp_tcp_send_comeback_delay(conn, + WLAN_PA_GAS_INITIAL_RESP); } - if (!resp) + + return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_INITIAL_RESP, resp); +} + + +static int dpp_controller_rx_gas_comeback_req(struct dpp_connection *conn, + const u8 *msg, size_t len) +{ + u8 dialog_token; + struct dpp_authentication *auth = conn->auth; + struct wpabuf *resp; + + if (len < 1) return -1; - buf = wpabuf_alloc(4 + 18 + wpabuf_len(resp)); - if (!buf) { - wpabuf_free(resp); + wpa_printf(MSG_DEBUG, + "DPP: Received DPP Configuration Request over TCP (comeback)"); + + if (!auth || (!conn->ctrl && !auth->configurator) || + (!auth->auth_success && !auth->reconfig_success) || + !conn->gas_comeback_in_progress) { + wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return -1; } - wpabuf_put_be32(buf, 18 + wpabuf_len(resp)); + dialog_token = msg[0]; + if (dialog_token != conn->gas_dialog_token) { + wpa_printf(MSG_DEBUG, "DPP: Dialog token mismatch (%u != %u)", + dialog_token, conn->gas_dialog_token); + return -1; + } - wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP); - wpabuf_put_u8(buf, dialog_token); - wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); - wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */ + if (!conn->gas_resp) { + wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); + return dpp_tcp_send_comeback_delay(conn, + WLAN_PA_GAS_COMEBACK_RESP); + } - dpp_write_adv_proto(buf); - dpp_write_gas_query(buf, resp); - wpabuf_free(resp); - - /* Send Config Response over TCP; GAS fragmentation is taken care of by - * the Relay */ - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = buf; - conn->on_tcp_tx_complete_gas_done = 1; - dpp_tcp_send(conn); - return 0; + wpa_printf(MSG_DEBUG, + "DPP: Configuration response is ready to be sent out"); + resp = conn->gas_resp; + conn->gas_resp = NULL; + return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_COMEBACK_RESP, resp); } @@ -1369,6 +1445,11 @@ static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx) wpabuf_len(conn->msg) - 1) < 0) dpp_connection_remove(conn); break; + case WLAN_PA_GAS_COMEBACK_REQ: + if (dpp_controller_rx_gas_comeback_req( + conn, pos + 1, wpabuf_len(conn->msg) - 1) < 0) + dpp_connection_remove(conn); + break; default: wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u", *pos); From 11aa77e00f2609034516630eb33b100e6edd2c76 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 18 Jun 2020 13:39:53 +0300 Subject: [PATCH 0698/1105] DPP2: GAS comeback response processing for Enrollee over TCP This is almost identical to processing of the GAS initial response. Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 39cb6fd3e..4ed4a3b71 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -1255,14 +1255,14 @@ static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx) static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, - size_t len) + size_t len, bool comeback) { struct wpabuf *buf; u8 dialog_token; const u8 *pos, *end, *next, *adv_proto; u16 status, slen, comeback_delay; - if (len < 5 + 2) + if (len < 5 + 2 + (comeback ? 1 : 0)) return -1; wpa_printf(MSG_DEBUG, @@ -1278,6 +1278,8 @@ static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, return -1; } pos += 2; + if (comeback) + pos++; /* ignore Fragment ID */ comeback_delay = WPA_GET_LE16(pos); pos += 2; @@ -1441,8 +1443,10 @@ static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx) dpp_connection_remove(conn); break; case WLAN_PA_GAS_INITIAL_RESP: + case WLAN_PA_GAS_COMEBACK_RESP: if (dpp_rx_gas_resp(conn, pos + 1, - wpabuf_len(conn->msg) - 1) < 0) + wpabuf_len(conn->msg) - 1, + *pos == WLAN_PA_GAS_COMEBACK_RESP) < 0) dpp_connection_remove(conn); break; case WLAN_PA_GAS_COMEBACK_REQ: From b25ddfe9d3cb5ffb1fb10f7c9221d433fb026ab7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 18 Jun 2020 21:06:10 +0300 Subject: [PATCH 0699/1105] DPP2: Add Enrollee name into CSR as the commonName Signed-off-by: Jouni Malinen --- src/common/dpp.h | 6 ++++-- src/common/dpp_crypto.c | 15 ++++++++++++++- src/common/dpp_tcp.c | 11 ++++++++--- wpa_supplicant/dpp_supplicant.c | 6 ++++-- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/common/dpp.h b/src/common/dpp.h index f4398aa0d..58a220dc6 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -616,7 +616,8 @@ struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len); void dpp_pfs_free(struct dpp_pfs *pfs); -struct wpabuf * dpp_build_csr(struct dpp_authentication *auth); +struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, + const char *name); struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7); int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr); @@ -660,7 +661,8 @@ int dpp_controller_start(struct dpp_global *dpp, struct dpp_controller_config *config); void dpp_controller_stop(struct dpp_global *dpp); int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, - const struct hostapd_ip_addr *addr, int port); + const struct hostapd_ip_addr *addr, int port, + const char *name); struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); struct dpp_global_config { diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 916aeeff8..e83ab9c60 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2666,7 +2666,7 @@ void dpp_pfs_free(struct dpp_pfs *pfs) } -struct wpabuf * dpp_build_csr(struct dpp_authentication *auth) +struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name) { X509_REQ *req = NULL; struct wpabuf *buf = NULL; @@ -2705,6 +2705,19 @@ struct wpabuf * dpp_build_csr(struct dpp_authentication *auth) if (!req || !X509_REQ_set_pubkey(req, key)) goto fail; + if (name) { + X509_NAME *n; + + n = X509_REQ_get_subject_name(req); + if (!n) + goto fail; + + if (X509_NAME_add_entry_by_txt( + n, "CN", MBSTRING_UTF8, + (const unsigned char *) name, -1, -1, 0) != 1) + goto fail; + } + /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, "CSR challengePassword", cp, DPP_CP_LEN) < 0) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 4ed4a3b71..b7d9294e3 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -41,6 +41,7 @@ struct dpp_connection { unsigned int gas_comeback_in_progress:1; u8 gas_dialog_token; struct wpabuf *gas_resp; + char *name; }; /* Remote Controller */ @@ -92,6 +93,7 @@ static void dpp_connection_free(struct dpp_connection *conn) wpabuf_free(conn->msg_out); wpabuf_free(conn->gas_resp); dpp_auth_deinit(conn->auth); + os_free(conn->name); os_free(conn); } @@ -258,8 +260,10 @@ static void dpp_controller_start_gas_client(struct dpp_connection *conn) struct dpp_authentication *auth = conn->auth; struct wpabuf *buf; int netrole_ap = 0; /* TODO: make this configurable */ + const char *dpp_name; - buf = dpp_build_conf_req_helper(auth, "Test", netrole_ap, NULL, NULL); + dpp_name = conn->name ? conn->name : "Test"; + buf = dpp_build_conf_req_helper(auth, dpp_name, netrole_ap, NULL, NULL); if (!buf) { wpa_printf(MSG_DEBUG, "DPP: No configuration request data available"); @@ -1169,7 +1173,7 @@ static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx) wpa_printf(MSG_DEBUG, "DPP: Build CSR"); wpabuf_free(auth->csr); /* TODO: Additional information needed for CSR based on csrAttrs */ - auth->csr = dpp_build_csr(auth); + auth->csr = dpp_build_csr(auth, conn->name ? conn->name : "Test"); if (!auth->csr) { dpp_connection_remove(conn); return; @@ -1513,7 +1517,7 @@ fail: int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, - const struct hostapd_ip_addr *addr, int port) + const struct hostapd_ip_addr *addr, int port, const char *name) { struct dpp_connection *conn; struct sockaddr_storage saddr; @@ -1535,6 +1539,7 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, return -1; } + conn->name = os_strdup(name ? name : "Test"); conn->global = dpp; conn->auth = auth; conn->sock = socket(AF_INET, SOCK_STREAM, 0); diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 7e2cdcd31..68846e63d 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -831,7 +831,8 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) #ifdef CONFIG_DPP2 if (tcp) - return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port); + return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port, + wpa_s->conf->dpp_name); #endif /* CONFIG_DPP2 */ wpa_s->dpp_auth = auth; @@ -1515,7 +1516,8 @@ static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx) wpa_printf(MSG_DEBUG, "DPP: Build CSR"); wpabuf_free(auth->csr); /* TODO: Additional information needed for CSR based on csrAttrs */ - auth->csr = dpp_build_csr(auth); + auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ? + wpa_s->conf->dpp_name : "Test"); if (!auth->csr) { dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; From 8f88dcf050bf5c6166bf2bf74856bd8574ec5ea3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 19 Jun 2020 00:08:33 +0300 Subject: [PATCH 0700/1105] DPP2: Add an automatic peer_bi entry for CSR matching if needed This allows the DPP_CA_SET command to be targeting a specific DPP-CST event in cases where the Configurator did not receive the bootstrapping information for the peer. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 26 ++++++++++++++++++++- src/common/dpp.h | 4 ++++ src/common/dpp_tcp.c | 30 ++++++++++++++++++++----- wpa_supplicant/dpp_supplicant.c | 40 +++++++++++++++++++++++---------- 4 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index dc66ce913..2cf1f6a13 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1293,9 +1293,14 @@ void dpp_auth_deinit(struct dpp_authentication *auth) wpabuf_free(auth->cacert); wpabuf_free(auth->certbag); os_free(auth->trusted_eap_server_name); + wpabuf_free(auth->conf_resp_tcp); #endif /* CONFIG_DPP2 */ wpabuf_free(auth->net_access_key); dpp_bootstrap_info_free(auth->tmp_own_bi); + if (auth->tmp_peer_bi) { + dl_list_del(&auth->tmp_peer_bi->list); + dpp_bootstrap_info_free(auth->tmp_peer_bi); + } #ifdef CONFIG_TESTING_OPTIONS os_free(auth->config_obj_override); os_free(auth->discovery_override); @@ -2044,6 +2049,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, cert_req = json_get_member_base64(root, "pkcs10"); if (cert_req) { char *txt; + int id; wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req); if (dpp_validate_csr(auth, cert_req) < 0) { @@ -2051,13 +2057,31 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, auth->force_conf_resp_status = DPP_STATUS_CSR_BAD; goto cont; } + + if (auth->peer_bi) { + id = auth->peer_bi->id; + } else if (auth->tmp_peer_bi) { + id = auth->tmp_peer_bi->id; + } else { + struct dpp_bootstrap_info *bi; + + bi = os_zalloc(sizeof(*bi)); + if (!bi) + goto fail; + bi->id = dpp_next_id(auth->global); + dl_list_add(&auth->global->bootstrap, &bi->list); + auth->tmp_peer_bi = bi; + id = bi->id; + } + wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA"); txt = base64_encode_no_lf(wpabuf_head(cert_req), wpabuf_len(cert_req), NULL); if (!txt) goto fail; + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_CSR "peer=%d csr=%s", - auth->peer_bi ? (int) auth->peer_bi->id : -1, txt); + id, txt); os_free(txt); auth->waiting_csr = false; auth->waiting_cert = true; diff --git a/src/common/dpp.h b/src/common/dpp.h index 58a220dc6..cff996095 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -244,6 +244,7 @@ struct dpp_authentication { struct dpp_bootstrap_info *peer_bi; struct dpp_bootstrap_info *own_bi; struct dpp_bootstrap_info *tmp_own_bi; + struct dpp_bootstrap_info *tmp_peer_bi; u8 waiting_pubkey_hash[SHA256_MAC_LEN]; int response_pending; int reconfig; @@ -298,6 +299,7 @@ struct dpp_authentication { bool reconfig_success; struct wpabuf *conf_req; const struct wpabuf *conf_resp; /* owned by GAS server */ + struct wpabuf *conf_resp_tcp; struct dpp_configuration *conf_ap; struct dpp_configuration *conf2_ap; struct dpp_configuration *conf_sta; @@ -660,6 +662,8 @@ int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data, int dpp_controller_start(struct dpp_global *dpp, struct dpp_controller_config *config); void dpp_controller_stop(struct dpp_global *dpp); +struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, + unsigned int id); int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port, const char *name); diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index b7d9294e3..9994c67cd 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -40,7 +40,6 @@ struct dpp_connection { unsigned int on_tcp_tx_complete_auth_ok:1; unsigned int gas_comeback_in_progress:1; u8 gas_dialog_token; - struct wpabuf *gas_resp; char *name; }; @@ -91,7 +90,6 @@ static void dpp_connection_free(struct dpp_connection *conn) eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL); wpabuf_free(conn->msg); wpabuf_free(conn->msg_out); - wpabuf_free(conn->gas_resp); dpp_auth_deinit(conn->auth); os_free(conn->name); os_free(conn); @@ -1148,7 +1146,7 @@ static int dpp_controller_rx_gas_comeback_req(struct dpp_connection *conn, return -1; } - if (!conn->gas_resp) { + if (!auth->conf_resp_tcp) { wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); return dpp_tcp_send_comeback_delay(conn, WLAN_PA_GAS_COMEBACK_RESP); @@ -1156,8 +1154,8 @@ static int dpp_controller_rx_gas_comeback_req(struct dpp_connection *conn, wpa_printf(MSG_DEBUG, "DPP: Configuration response is ready to be sent out"); - resp = conn->gas_resp; - conn->gas_resp = NULL; + resp = auth->conf_resp_tcp; + auth->conf_resp_tcp = NULL; return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_COMEBACK_RESP, resp); } @@ -1665,6 +1663,28 @@ void dpp_controller_stop(struct dpp_global *dpp) } +struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, + unsigned int id) +{ + struct dpp_controller *ctrl = dpp->controller; + struct dpp_connection *conn; + + if (!ctrl) + return NULL; + + dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) { + struct dpp_authentication *auth = conn->auth; + + if (auth && + ((auth->peer_bi && auth->peer_bi->id == id) || + (auth->tmp_peer_bi && auth->tmp_peer_bi->id == id))) + return auth; + } + + return NULL; +} + + void dpp_tcp_init_flush(struct dpp_global *dpp) { struct dpp_connection *conn, *tmp; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 68846e63d..b065ff721 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3632,7 +3632,7 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s, - struct dpp_authentication *auth) + struct dpp_authentication *auth, bool tcp) { struct wpabuf *resp; @@ -3640,6 +3640,12 @@ static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s, auth->e_netrole, true); if (!resp) return -1; + + if (tcp) { + auth->conf_resp_tcp = resp; + return 0; + } + if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx, resp) < 0) { wpa_printf(MSG_DEBUG, @@ -3654,12 +3660,23 @@ static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s, int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) { - int peer; + int peer = -1; const char *pos, *value; struct dpp_authentication *auth = wpa_s->dpp_auth; u8 *bin; size_t bin_len; struct wpabuf *buf; + bool tcp = false; + + pos = os_strstr(cmd, " peer="); + if (pos) { + peer = atoi(pos + 6); + if (!auth || !auth->waiting_cert || + (unsigned int) peer != auth->peer_bi->id) { + auth = dpp_controller_get_auth(wpa_s->dpp, peer); + tcp = true; + } + } if (!auth || !auth->waiting_cert) { wpa_printf(MSG_DEBUG, @@ -3667,14 +3684,13 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) return -1; } - pos = os_strstr(cmd, " peer="); - if (pos) { - peer = atoi(pos + 6); - if (!auth->peer_bi || - (unsigned int) peer != auth->peer_bi->id) { - wpa_printf(MSG_DEBUG, "DPP: Peer mismatch"); - return -1; - } + if (peer >= 0 && + (!auth->peer_bi || + (unsigned int) peer != auth->peer_bi->id) && + (!auth->tmp_peer_bi || + (unsigned int) peer != auth->tmp_peer_bi->id)) { + wpa_printf(MSG_DEBUG, "DPP: Peer mismatch"); + return -1; } pos = os_strstr(cmd, " value="); @@ -3689,7 +3705,7 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) if (os_strncmp(pos, "status ", 7) == 0) { auth->force_conf_resp_status = atoi(value); - return wpas_dpp_build_conf_resp(wpa_s, auth); + return wpas_dpp_build_conf_resp(wpa_s, auth, tcp); } if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) { @@ -3713,7 +3729,7 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) if (os_strncmp(pos, "certBag ", 8) == 0) { wpabuf_free(auth->certbag); auth->certbag = buf; - return wpas_dpp_build_conf_resp(wpa_s, auth); + return wpas_dpp_build_conf_resp(wpa_s, auth, tcp); } wpabuf_free(buf); From 0bbab646563155701f7fa71dc59910aacb254d58 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 19 Jun 2020 00:10:51 +0300 Subject: [PATCH 0701/1105] DPP2: Fix dot1x config object parsing without trustedEapServerName Need to check that the JSON node was found before using its value. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 2cf1f6a13..de8a4a4ad 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -2562,7 +2562,7 @@ static int dpp_parse_cred_dot1x(struct dpp_authentication *auth, "Invalid trustedEapServerName type in JSON"); return -1; } - if (name->string) { + if (name && name->string) { wpa_printf(MSG_DEBUG, "DPP: Received trustedEapServerName: %s", name->string); conf->server_name = os_strdup(name->string); From a758a6672509b5b6e8afc49e4c27836f4988d898 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 19 Jun 2020 00:12:56 +0300 Subject: [PATCH 0702/1105] tests: DPP over TCP for enterprise provisioning Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 84 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 4de7dd396..fa12c43de 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5799,3 +5799,87 @@ def test_dpp_enterprise_reject(dev, apdev, params): raise Exception("DPP configuration not completed (Enrollee)") if "DPP-CONF-FAILED" not in ev: raise Exception("DPP configuration did not fail (Enrollee)") + +def test_dpp_enterprise_tcp(dev, apdev, params): + """DPP over TCP for enterprise provisioning""" + try: + run_dpp_enterprise_tcp(dev, apdev, params) + finally: + dev[1].request("DPP_CONTROLLER_STOP") + +def run_dpp_enterprise_tcp(dev, apdev, params): + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + cap_lo = params['prefix'] + ".lo.pcap" + cert_file = params['prefix'] + ".cert.pem" + pkcs7_file = params['prefix'] + ".pkcs7.der" + + with open("auth_serv/ec-ca.pem", "rb") as f: + res = f.read() + cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + res) + + with open("auth_serv/ec-ca.key", "rb") as f: + res = f.read() + cakey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, res) + + wt = WlantestCapture('lo', cap_lo) + time.sleep(1) + + # Controller + conf_id = dev[1].dpp_configurator_add() + csrattrs = "MAsGCSqGSIb3DQEJBw==" + dev[1].set("dpp_configurator_params", + "conf=sta-dot1x configurator=%d csrattrs=%s" % (conf_id, csrattrs)) + id_c = dev[1].dpp_bootstrap_gen() + uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + res = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_c) + req = "DPP_CONTROLLER_START" + if "OK" not in dev[1].request(req): + raise Exception("Failed to start Controller") + + dev[0].dpp_auth_init(uri=uri_c, role="enrollee", tcp_addr="127.0.0.1") + + ev = dev[1].wait_event(["DPP-CSR"], timeout=10) + if ev is None: + raise Exception("Configurator did not receive CSR") + id1_csr = int(ev.split(' ')[1].split('=')[1]) + csr = ev.split(' ')[2] + if not csr.startswith("csr="): + raise Exception("Could not parse CSR event: " + ev) + csr = csr[4:] + csr = base64.b64decode(csr.encode()) + logger.info("CSR: " + binascii.hexlify(csr).decode()) + + cert = dpp_sign_cert(cacert, cakey, csr) + with open(cert_file, 'wb') as f: + f.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, + cert)) + subprocess.check_call(['openssl', 'crl2pkcs7', '-nocrl', + '-certfile', cert_file, + '-certfile', 'auth_serv/ec-ca.pem', + '-outform', 'DER', '-out', pkcs7_file]) + + with open(pkcs7_file, 'rb') as f: + pkcs7_der = f.read() + certbag = base64.b64encode(pkcs7_der).decode() + res = dev[1].request("DPP_CA_SET peer=%d name=certBag value=%s" % (id1_csr, certbag)) + if "OK" not in res: + raise Exception("Failed to set certBag") + + ev = dev[1].wait_event(["DPP-CONF-SENT", "DPP-CONF-FAILED"], timeout=5) + if ev is None: + raise Exception("DPP configuration not completed (Configurator)") + if "DPP-CONF-FAILED" in ev: + raise Exception("DPP configuration did not succeed (Configurator)") + + ev = dev[0].wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"], + timeout=1) + if ev is None: + raise Exception("DPP configuration not completed (Enrollee)") + if "DPP-CONF-RECEIVED" not in ev: + raise Exception("DPP configuration did not succeed (Enrollee)") + + time.sleep(0.5) + wt.close() From 1046145093df96ea6c0a1a4f9d8a1c18ad273ff8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 19 Jun 2020 00:36:44 +0300 Subject: [PATCH 0703/1105] tests: Copy subject from CSR to certificate Instead of overriding the subject field with something arbitrary, use the value that is included in the CSR now that there is something there. Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index fa12c43de..e28e04f85 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5628,8 +5628,7 @@ def dpp_sign_cert(cacert, cakey, csr_der): cert.gmtime_adj_notBefore(-10) cert.gmtime_adj_notAfter(100000) cert.set_pubkey(csr.get_pubkey()) - dn = cert.get_subject() - dn.CN = "dpp-tls-test" + dn = csr.get_subject() cert.set_subject(dn) cert.set_version(2) cert.add_extensions([ From fa09b85c4e7988f43384fe7e9a1d80c71edf039d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 19 Jun 2020 00:37:40 +0300 Subject: [PATCH 0704/1105] DPP2: Remove forgetten development time debug prints Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index b065ff721..2d56b2f9d 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1239,8 +1239,6 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, } if (conf->certs) { - wpa_hexdump_buf(MSG_INFO, "JKM:certs", - conf->certs); for (i = 0; ; i++) { os_snprintf(name, sizeof(name), "dpp-certs-%d", i); @@ -1283,8 +1281,6 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, break; } - wpa_hexdump_buf(MSG_INFO, "JKM:privkey", - auth->priv_key); blob = os_zalloc(sizeof(*blob)); if (!blob) goto fail; From 2ff5a1fdb1cbf57c6a8cd0c303ef5c327091d5ab Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Mon, 1 Jun 2020 17:10:13 -0700 Subject: [PATCH 0705/1105] Use lookup-table instead of macro for TX rate estimates Change INTERPOLATE_RATE() macro to a lookup-table instead for the sake of readability. Signed-off-by: Matthew Wang --- wpa_supplicant/scan.c | 122 ++++++++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 47 deletions(-) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index b47573094..1c62c2ecf 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -2187,6 +2187,60 @@ void scan_snr(struct wpa_scan_res *res) } +/* Minimum SNR required to achieve a certain bitrate. */ +struct minsnr_bitrate_entry { + int minsnr; + unsigned int bitrate; /* in Mbps */ +}; + +/* VHT needs to be enabled in order to achieve MCS8 and MCS9 rates. */ +static const int vht_mcs = 8; + +static const struct minsnr_bitrate_entry vht20_table[] = { + { 0, 0 }, + { 2, 6500 }, /* HT20 MCS0 */ + { 5, 13000 }, /* HT20 MCS1 */ + { 9, 19500 }, /* HT20 MCS2 */ + { 11, 26000 }, /* HT20 MCS3 */ + { 15, 39000 }, /* HT20 MCS4 */ + { 18, 52000 }, /* HT20 MCS5 */ + { 20, 58500 }, /* HT20 MCS6 */ + { 25, 65000 }, /* HT20 MCS7 */ + { 29, 78000 }, /* VHT20 MCS8 */ + { -1, 78000 } /* SNR > 29 */ +}; + +static const struct minsnr_bitrate_entry vht40_table[] = { + { 0, 0 }, + { 5, 13500 }, /* HT40 MCS0 */ + { 8, 27000 }, /* HT40 MCS1 */ + { 12, 40500 }, /* HT40 MCS2 */ + { 14, 54000 }, /* HT40 MCS3 */ + { 18, 81000 }, /* HT40 MCS4 */ + { 21, 108000 }, /* HT40 MCS5 */ + { 23, 121500 }, /* HT40 MCS6 */ + { 28, 135000 }, /* HT40 MCS7 */ + { 32, 162000 }, /* VHT40 MCS8 */ + { 34, 180000 }, /* VHT40 MCS9 */ + { -1, 180000 } /* SNR > 34 */ +}; + +static const struct minsnr_bitrate_entry vht80_table[] = { + { 0, 0 }, + { 8, 29300 }, /* VHT80 MCS0 */ + { 11, 58500 }, /* VHT80 MCS1 */ + { 15, 87800 }, /* VHT80 MCS2 */ + { 17, 117000 }, /* VHT80 MCS3 */ + { 21, 175500 }, /* VHT80 MCS4 */ + { 24, 234000 }, /* VHT80 MCS5 */ + { 26, 263300 }, /* VHT80 MCS6 */ + { 31, 292500 }, /* VHT80 MCS7 */ + { 35, 351000 }, /* VHT80 MCS8 */ + { 37, 390000 }, /* VHT80 MCS9 */ + { -1, 390000 } /* SNR > 37 */ +}; + + static unsigned int interpolate_rate(int snr, int snr0, int snr1, int rate0, int rate1) { @@ -2194,68 +2248,42 @@ static unsigned int interpolate_rate(int snr, int snr0, int snr1, } -#define INTERPOLATE_RATE(snr0, snr1, rate0, rate1) \ - if (snr < (snr1)) \ - return interpolate_rate(snr, (snr0), (snr1), (rate0), (rate1)) +static unsigned int max_rate(const struct minsnr_bitrate_entry table[], + int snr, int vht) +{ + const struct minsnr_bitrate_entry *prev, *entry = table; + + while ((entry->minsnr != -1) && + (snr >= entry->minsnr) && + (vht || entry - table <= vht_mcs)) + entry++; + if (entry == table) + return entry->bitrate; + prev = entry - 1; + if (entry->minsnr == -1 || (!vht && entry - table > vht_mcs)) + return prev->bitrate; + return interpolate_rate(snr, prev->minsnr, entry->minsnr, prev->bitrate, + entry->bitrate); +} + static unsigned int max_ht20_rate(int snr, int vht) { - if (snr < 0) - return 0; - INTERPOLATE_RATE(0, 2, 0, 6500); /* HT20 MCS0 */ - INTERPOLATE_RATE(2, 5, 6500, 13000); /* HT20 MCS1 */ - INTERPOLATE_RATE(5, 9, 13000, 19500); /* HT20 MCS2 */ - INTERPOLATE_RATE(9, 11, 19500, 26000); /* HT20 MCS3 */ - INTERPOLATE_RATE(11, 15, 26000, 39000); /* HT20 MCS4 */ - INTERPOLATE_RATE(15, 18, 39000, 52000); /* HT20 MCS5 */ - INTERPOLATE_RATE(18, 20, 52000, 58500); /* HT20 MCS6 */ - INTERPOLATE_RATE(20, 25, 58500, 65000); /* HT20 MCS7 */ - if (!vht) - return 65000; - INTERPOLATE_RATE(25, 29, 65000, 78000); /* VHT20 MCS8 */ - return 78000; + return max_rate(vht20_table, snr, vht); } static unsigned int max_ht40_rate(int snr, int vht) { - if (snr < 0) - return 0; - INTERPOLATE_RATE(0, 5, 0, 13500); /* HT40 MCS0 */ - INTERPOLATE_RATE(5, 8, 13500, 27000); /* HT40 MCS1 */ - INTERPOLATE_RATE(8, 12, 27000, 40500); /* HT40 MCS2 */ - INTERPOLATE_RATE(12, 14, 40500, 54000); /* HT40 MCS3 */ - INTERPOLATE_RATE(14, 18, 54000, 81000); /* HT40 MCS4 */ - INTERPOLATE_RATE(18, 21, 81000, 108000); /* HT40 MCS5 */ - INTERPOLATE_RATE(21, 23, 108000, 121500); /* HT40 MCS6 */ - INTERPOLATE_RATE(23, 28, 121500, 135000); /* HT40 MCS7 */ - if (!vht) - return 135000; - INTERPOLATE_RATE(28, 32, 135000, 162000); /* VHT40 MCS8 */ - INTERPOLATE_RATE(32, 34, 162000, 180000); /* VHT40 MCS9 */ - return 180000; + return max_rate(vht40_table, snr, vht); } static unsigned int max_vht80_rate(int snr) { - if (snr < 0) - return 0; - INTERPOLATE_RATE(0, 8, 0, 29300); /* VHT80 MCS0 */ - INTERPOLATE_RATE(8, 11, 29300, 58500); /* VHT80 MCS1 */ - INTERPOLATE_RATE(11, 15, 58500, 87800); /* VHT80 MCS2 */ - INTERPOLATE_RATE(15, 17, 87800, 117000); /* VHT80 MCS3 */ - INTERPOLATE_RATE(17, 21, 117000, 175500); /* VHT80 MCS4 */ - INTERPOLATE_RATE(21, 24, 175500, 234000); /* VHT80 MCS5 */ - INTERPOLATE_RATE(24, 26, 234000, 263300); /* VHT80 MCS6 */ - INTERPOLATE_RATE(26, 31, 263300, 292500); /* VHT80 MCS7 */ - INTERPOLATE_RATE(31, 35, 292500, 351000); /* VHT80 MCS8 */ - INTERPOLATE_RATE(35, 37, 351000, 390000); /* VHT80 MCS9 */ - return 390000; + return max_rate(vht80_table, snr, 1); } -#undef INTERPOLATE_RATE - unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, const u8 *ies, size_t ies_len, int rate, From d6b450e890e0cd6a84b4023873a2015c2f49226e Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Mon, 1 Jun 2020 17:10:15 -0700 Subject: [PATCH 0706/1105] Refactor wpa_supplicant_need_to_roam() Pull all the within-ESS roam code out of wpa_supplicant_need_to_roam() and into its own function, wpa_supplicant_need_to_roam_within_ess(). This way, we avoid interleaving several #ifndef's in the original function and wrap the new function in one big #ifndef. This also modularizes the within-ESS roam code and makes it easier to test. Signed-off-by: Matthew Wang --- wpa_supplicant/events.c | 82 +++++++++++++++++-------------- wpa_supplicant/wpa_supplicant_i.h | 3 ++ 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index b93c62c8e..e3cf85393 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1855,52 +1855,18 @@ wpas_get_est_throughput_from_bss_snr(const struct wpa_supplicant *wpa_s, return wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr); } -#endif /* CONFIG_NO_ROAMING */ - -static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, - struct wpa_bss *selected, - struct wpa_ssid *ssid) +int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s, + struct wpa_bss *current_bss, + struct wpa_bss *selected) { - struct wpa_bss *current_bss = NULL; -#ifndef CONFIG_NO_ROAMING int min_diff, diff; int to_5ghz; int cur_level; unsigned int cur_est, sel_est; struct wpa_signal_info si; int cur_snr = 0; -#endif /* CONFIG_NO_ROAMING */ - if (wpa_s->reassociate) - return 1; /* explicit request to reassociate */ - if (wpa_s->wpa_state < WPA_ASSOCIATED) - return 1; /* we are not associated; continue */ - if (wpa_s->current_ssid == NULL) - return 1; /* unknown current SSID */ - if (wpa_s->current_ssid != ssid) - return 1; /* different network block */ - - if (wpas_driver_bss_selection(wpa_s)) - return 0; /* Driver-based roaming */ - - if (wpa_s->current_ssid->ssid) - current_bss = wpa_bss_get(wpa_s, wpa_s->bssid, - wpa_s->current_ssid->ssid, - wpa_s->current_ssid->ssid_len); - if (!current_bss) - current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid); - - if (!current_bss) - return 1; /* current BSS not seen in scan results */ - - if (current_bss == selected) - return 0; - - if (selected->last_update_idx > current_bss->last_update_idx) - return 1; /* current BSS not seen in the last scan */ - -#ifndef CONFIG_NO_ROAMING wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation"); wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR " freq=%d level=%d snr=%d est_throughput=%u", @@ -2026,6 +1992,48 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, "Allow reassociation due to difference in signal level (%d >= %d)", diff, min_diff); return 1; +} + +#endif /* CONFIG_NO_ROAMING */ + + +static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid) +{ + struct wpa_bss *current_bss = NULL; + + if (wpa_s->reassociate) + return 1; /* explicit request to reassociate */ + if (wpa_s->wpa_state < WPA_ASSOCIATED) + return 1; /* we are not associated; continue */ + if (wpa_s->current_ssid == NULL) + return 1; /* unknown current SSID */ + if (wpa_s->current_ssid != ssid) + return 1; /* different network block */ + + if (wpas_driver_bss_selection(wpa_s)) + return 0; /* Driver-based roaming */ + + if (wpa_s->current_ssid->ssid) + current_bss = wpa_bss_get(wpa_s, wpa_s->bssid, + wpa_s->current_ssid->ssid, + wpa_s->current_ssid->ssid_len); + if (!current_bss) + current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid); + + if (!current_bss) + return 1; /* current BSS not seen in scan results */ + + if (current_bss == selected) + return 0; + + if (selected->last_update_idx > current_bss->last_update_idx) + return 1; /* current BSS not seen in the last scan */ + +#ifndef CONFIG_NO_ROAMING + return wpa_supplicant_need_to_roam_within_ess(wpa_s, current_bss, + selected); #else /* CONFIG_NO_ROAMING */ return 0; #endif /* CONFIG_NO_ROAMING */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 28867f04e..341d84156 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1523,6 +1523,9 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s, struct channel_list_changed *info); +int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s, + struct wpa_bss *current_bss, + struct wpa_bss *seleceted); /* eap_register.c */ int eap_register_methods(void); From b97aa038b7e2be722b9d362c8645a763009969d6 Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Mon, 1 Jun 2020 17:10:18 -0700 Subject: [PATCH 0707/1105] Add WPA_EVENT_{DO,SKIP}_ROAM events Add events for within-ESS reassociation. This allows us to monitor roam events, both skipped and allowed, in tests. Signed-off-by: Matthew Wang --- src/common/wpa_ctrl.h | 4 ++++ wpa_supplicant/events.c | 22 ++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 58ce10141..f5199de9a 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -97,6 +97,10 @@ extern "C" { "CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER " /** Unprotected Beacon frame dropped */ #define WPA_EVENT_UNPROT_BEACON "CTRL-EVENT-UNPROT-BEACON " +/** Decision made to do a within-ESS roam */ +#define WPA_EVENT_DO_ROAM "CTRL-EVENT-DO-ROAM " +/** Decision made to skip a within-ESS roam */ +#define WPA_EVENT_SKIP_ROAM "CTRL-EVENT-SKIP-ROAM " /** IP subnet status change notification * diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e3cf85393..0fcb1762e 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1866,6 +1866,7 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s, unsigned int cur_est, sel_est; struct wpa_signal_info si; int cur_snr = 0; + int ret = 0; wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation"); wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR @@ -1985,13 +1986,22 @@ int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference in signal level (%d < %d)", diff, min_diff); - return 0; + ret = 0; + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "Allow reassociation due to difference in signal level (%d >= %d)", + diff, min_diff); + ret = 1; } - - wpa_dbg(wpa_s, MSG_DEBUG, - "Allow reassociation due to difference in signal level (%d >= %d)", - diff, min_diff); - return 1; + wpa_msg_ctrl(wpa_s, MSG_INFO, "%scur_bssid=" MACSTR + " cur_freq=%d cur_level=%d cur_est=%d sel_bssid=" MACSTR + " sel_freq=%d sel_level=%d sel_est=%d", + ret ? WPA_EVENT_DO_ROAM : WPA_EVENT_SKIP_ROAM, + MAC2STR(current_bss->bssid), + current_bss->freq, cur_level, cur_est, + MAC2STR(selected->bssid), + selected->freq, selected->level, sel_est); + return ret; } #endif /* CONFIG_NO_ROAMING */ From b5dab03a131720143e5a8cd8aac95aa2869ea460 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 19 Jun 2020 17:28:25 +0300 Subject: [PATCH 0708/1105] Convert int to bool for throughput estimate tables Signed-off-by: Jouni Malinen --- wpa_supplicant/scan.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 1c62c2ecf..7415eae9f 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -2249,7 +2249,7 @@ static unsigned int interpolate_rate(int snr, int snr0, int snr1, static unsigned int max_rate(const struct minsnr_bitrate_entry table[], - int snr, int vht) + int snr, bool vht) { const struct minsnr_bitrate_entry *prev, *entry = table; @@ -2267,13 +2267,13 @@ static unsigned int max_rate(const struct minsnr_bitrate_entry table[], } -static unsigned int max_ht20_rate(int snr, int vht) +static unsigned int max_ht20_rate(int snr, bool vht) { return max_rate(vht20_table, snr, vht); } -static unsigned int max_ht40_rate(int snr, int vht) +static unsigned int max_ht40_rate(int snr, bool vht) { return max_rate(vht40_table, snr, vht); } @@ -2337,7 +2337,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) { ie = get_ie(ies, ies_len, WLAN_EID_HT_CAP); if (ie) { - tmp = max_ht20_rate(snr, 0); + tmp = max_ht20_rate(snr, false); if (tmp > est) est = tmp; } @@ -2347,7 +2347,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION); if (ie && ie[1] >= 2 && (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { - tmp = max_ht40_rate(snr, 0); + tmp = max_ht40_rate(snr, false); if (tmp > est) est = tmp; } @@ -2357,7 +2357,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, /* Use +1 to assume VHT is always faster than HT */ ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP); if (ie) { - tmp = max_ht20_rate(snr, 1) + 1; + tmp = max_ht20_rate(snr, true) + 1; if (tmp > est) est = tmp; @@ -2365,7 +2365,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (ie && ie[1] >= 2 && (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { - tmp = max_ht40_rate(snr, 1) + 1; + tmp = max_ht40_rate(snr, true) + 1; if (tmp > est) est = tmp; } From 9593ce6587238f197f394f7b894604932f9bb068 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 20 Jun 2020 18:04:51 +0300 Subject: [PATCH 0709/1105] OpenSSL: Provide access to peer subject and own certificate use These are needed for EAP-TEAP server and client side implementation to allow Phase 2 to be skipped based on client certificate use during Phase 1. Signed-off-by: Jouni Malinen --- src/crypto/tls.h | 14 ++++++++++++++ src/crypto/tls_openssl.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/crypto/tls.h b/src/crypto/tls.h index c8b1a824e..09fb73b1a 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -670,4 +670,18 @@ int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len); */ u16 tls_connection_get_cipher_suite(struct tls_connection *conn); +/** + * tls_connection_get_peer_subject - Get peer subject + * @conn: Connection context data from tls_connection_init() + * Returns: Peer subject or %NULL if not authenticated or not available + */ +const char * tls_connection_get_peer_subject(struct tls_connection *conn); + +/** + * tls_connection_get_own_cert_used - Was own certificate used + * @conn: Connection context data from tls_connection_init() + * Returns: true if own certificate was used during authentication + */ +bool tls_connection_get_own_cert_used(struct tls_connection *conn); + #endif /* TLS_H */ diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 29c7688a5..0f9664ec5 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -265,6 +265,7 @@ struct tls_connection { X509 *peer_cert; X509 *peer_issuer; X509 *peer_issuer_issuer; + char *peer_subject; /* peer subject info for authenticated peer */ unsigned char client_random[SSL3_RANDOM_SIZE]; unsigned char server_random[SSL3_RANDOM_SIZE]; @@ -1629,6 +1630,7 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) os_free(conn->domain_match); os_free(conn->check_cert_subject); os_free(conn->session_ticket); + os_free(conn->peer_subject); os_free(conn); } @@ -2579,6 +2581,11 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_SUCCESS, NULL); + if (depth == 0 && preverify_ok) { + os_free(conn->peer_subject); + conn->peer_subject = os_strdup(buf); + } + return preverify_ok; } @@ -3180,7 +3187,11 @@ int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, if (conn == NULL) return -1; - if (verify_peer) { + if (verify_peer == 2) { + conn->ca_cert_verify = 1; + SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | + SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); + } else if (verify_peer) { conn->ca_cert_verify = 1; SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | @@ -5683,3 +5694,19 @@ u16 tls_connection_get_cipher_suite(struct tls_connection *conn) return SSL_CIPHER_get_id(cipher) & 0xFFFF; #endif } + + +const char * tls_connection_get_peer_subject(struct tls_connection *conn) +{ + if (conn) + return conn->peer_subject; + return NULL; +} + + +bool tls_connection_get_own_cert_used(struct tls_connection *conn) +{ + if (conn) + return SSL_get_certificate(conn->ssl) != NULL; + return false; +} From 51962939265917184f52c81f3ed1f228956cb130 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 20 Jun 2020 18:05:46 +0300 Subject: [PATCH 0710/1105] EAP-TEAP (client): Allow Phase 2 to be skipped if certificate is used The EAP-TEAP server may skip Phase 2 if the client authentication could be completed during Phase 1 based on client certificate. Handle this similarly to the case of PAC use. Signed-off-by: Jouni Malinen --- src/eap_peer/eap_teap.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/eap_peer/eap_teap.c b/src/eap_peer/eap_teap.c index 76179a329..e8cc7844c 100644 --- a/src/eap_peer/eap_teap.c +++ b/src/eap_peer/eap_teap.c @@ -1388,6 +1388,15 @@ static int eap_teap_process_decrypted(struct eap_sm *sm, "EAP-TEAP: PAC used - server may decide to skip inner authentication"); ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; + } else if (data->result_success_done && + tls_connection_get_own_cert_used(data->ssl.conn) && + eap_teap_derive_msk(data) == 0) { + /* Assume the server might accept authentication without going + * through inner authentication. */ + wpa_printf(MSG_DEBUG, + "EAP-TEAP: Client certificate used - server may decide to skip inner authentication"); + ret->methodState = METHOD_MAY_CONT; + ret->decision = DECISION_COND_SUCC; } if (tlv.pac) { From cd99a8c432e3261855e5856cd5a605ea95d1b135 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 20 Jun 2020 18:07:04 +0300 Subject: [PATCH 0711/1105] EAP-TEAP (server): Allow Phase 2 skip based on client certificate eap_teap_auth=2 can now be used to configure hostapd to skip Phase 2 if the peer can be authenticated based on client certificate during Phase 1. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 +- hostapd/hostapd.conf | 2 ++ src/eap_server/eap_server_teap.c | 24 ++++++++++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 8f7fcd8b7..1861b5203 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2555,7 +2555,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "eap_teap_auth") == 0) { int val = atoi(pos); - if (val < 0 || val > 1) { + if (val < 0 || val > 2) { wpa_printf(MSG_ERROR, "Line %d: Invalid eap_teap_auth value", line); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 2b0f762e5..060738c34 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1229,6 +1229,8 @@ eap_server=0 # EAP-TEAP authentication type # 0 = inner EAP (default) # 1 = Basic-Password-Auth +# 2 = Do not require Phase 2 authentication if client can be authenticated +# during Phase 1 #eap_teap_auth=0 # EAP-TEAP authentication behavior when using PAC diff --git a/src/eap_server/eap_server_teap.c b/src/eap_server/eap_server_teap.c index d7b1b0995..691b44a8d 100644 --- a/src/eap_server/eap_server_teap.c +++ b/src/eap_server/eap_server_teap.c @@ -64,7 +64,7 @@ struct eap_teap_data { struct wpabuf *pending_phase2_resp; struct wpabuf *server_outer_tlvs; struct wpabuf *peer_outer_tlvs; - u8 *identity; /* from PAC-Opaque */ + u8 *identity; /* from PAC-Opaque or client certificate */ size_t identity_len; int eap_seq; int tnc_started; @@ -365,7 +365,9 @@ static void * eap_teap_init(struct eap_sm *sm) data->teap_version = EAP_TEAP_VERSION; data->state = START; - if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_TEAP)) { + if (eap_server_tls_ssl_init(sm, &data->ssl, + sm->cfg->eap_teap_auth == 2 ? 2 : 0, + EAP_TYPE_TEAP)) { wpa_printf(MSG_INFO, "EAP-TEAP: Failed to initialize SSL."); eap_teap_reset(sm, data); return NULL; @@ -502,6 +504,19 @@ static int eap_teap_phase1_done(struct eap_sm *sm, struct eap_teap_data *data) wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 1 done, starting Phase 2"); + if (!data->identity && sm->cfg->eap_teap_auth == 2) { + const char *subject; + + subject = tls_connection_get_peer_subject(data->ssl.conn); + if (subject) { + wpa_printf(MSG_DEBUG, + "EAP-TEAP: Peer subject from Phase 1 client certificate: '%s'", + subject); + data->identity = (u8 *) os_strdup(subject); + data->identity_len = os_strlen(subject); + } + } + data->tls_cs = tls_connection_get_cipher_suite(data->ssl.conn); wpa_printf(MSG_DEBUG, "EAP-TEAP: TLS cipher suite 0x%04x", data->tls_cs); @@ -1775,9 +1790,10 @@ static int eap_teap_process_phase2_start(struct eap_sm *sm, next_vendor = EAP_VENDOR_IETF; next_type = EAP_TYPE_NONE; eap_teap_state(data, PHASE2_METHOD); - } else if (sm->cfg->eap_teap_pac_no_inner) { + } else if (sm->cfg->eap_teap_pac_no_inner || + sm->cfg->eap_teap_auth == 2) { wpa_printf(MSG_DEBUG, - "EAP-TEAP: Used PAC and identity already known - skip inner auth"); + "EAP-TEAP: Used PAC or client certificate and identity already known - skip inner auth"); data->skipped_inner_auth = 1; /* FIX: Need to derive CMK here. However, how is that * supposed to be done? RFC 7170 does not tell that for From 948bd894f7a92c902e1fd4f17a878c241c723f88 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 20 Jun 2020 18:08:12 +0300 Subject: [PATCH 0712/1105] tests: EAP-TEAP with client certificate in Phase 1 Signed-off-by: Jouni Malinen --- tests/hwsim/auth_serv/eap_user.conf | 2 ++ tests/hwsim/test_eap.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/tests/hwsim/auth_serv/eap_user.conf b/tests/hwsim/auth_serv/eap_user.conf index 7343f40a3..b5c65f178 100644 --- a/tests/hwsim/auth_serv/eap_user.conf +++ b/tests/hwsim/auth_serv/eap_user.conf @@ -83,6 +83,8 @@ radius_accept_attr=27:d:3 "phase1-user" MSCHAPV2,MD5,GTC "password" +"/C=FI/O=w1.fi/CN=Test User" TLS [2] + "020000000000" MACACL "020000000000" "020000000100" MACACL "020000000100" diff --git a/tests/hwsim/test_eap.py b/tests/hwsim/test_eap.py index f1bf904bd..144e4d314 100644 --- a/tests/hwsim/test_eap.py +++ b/tests/hwsim/test_eap.py @@ -574,3 +574,29 @@ def test_eap_teap_eap_vendor(dev, apdev): anonymous_identity="TEAP", ca_cert="auth_serv/ca.pem", phase2="auth=VENDOR-TEST", pac_file="blob://teap_pac") + +def test_eap_teap_client_cert(dev, apdev): + """EAP-TEAP with client certificate in Phase 1""" + check_eap_capa(dev[0], "TEAP") + params = int_teap_server_params(eap_teap_auth="2") + hapd = hostapd.add_ap(apdev[0], params) + + # verify server accept a client with certificate, but no Phase 2 + # configuration + eap_connect(dev[0], hapd, "TEAP", "user", + anonymous_identity="TEAP", + phase1="teap_provisioning=2", + client_cert="auth_serv/user.pem", + private_key="auth_serv/user.key", + ca_cert="auth_serv/ca.pem", + pac_file="blob://teap_pac") + dev[0].dump_monitor() + res = eap_reauth(dev[0], "TEAP") + if res['tls_session_reused'] != '1': + raise Exception("EAP-TEAP could not use PAC session ticket") + + # verify server accepts a client without certificate + eap_connect(dev[1], hapd, "TEAP", "user", + anonymous_identity="TEAP", password="password", + ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2", + pac_file="blob://teap_pac") From 73ea1ad7f20903eddf17d090d94cab960ffd774d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 21 Jun 2020 16:44:51 +0300 Subject: [PATCH 0713/1105] nl80211: Clean up SO_WIFI_STATUS error reporting Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 72189da24..361cc6dd7 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2121,13 +2121,15 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS, &enabled, sizeof(enabled)) < 0) { wpa_printf(MSG_DEBUG, - "nl80211: wifi status sockopt failed\n"); + "nl80211: wifi status sockopt failed: %s", + strerror(errno)); drv->data_tx_status = 0; if (!drv->use_monitor) drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; } else { - eloop_register_read_sock(drv->eapol_tx_sock, + eloop_register_read_sock( + drv->eapol_tx_sock, wpa_driver_nl80211_handle_eapol_tx_status, drv, NULL); } From f7c657b79f2cb569f1e47c302de9e06992c41657 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 10 Jun 2020 10:32:56 +0200 Subject: [PATCH 0714/1105] nl80211: Add custom ack handler arguments to send_and_recv() This is a preliminary patch for using extack cookies for TX control port handling. Custom ack handler arguments for send_and_recv() and friends is introduced therefore. This commit does not actually use the provided values, i.e., that will be added in a separate commit. Signed-off-by: Markus Theil --- src/drivers/driver_nl80211.c | 234 +++++++++++++++++------------- src/drivers/driver_nl80211.h | 4 +- src/drivers/driver_nl80211_capa.c | 17 ++- src/drivers/driver_nl80211_scan.c | 23 +-- 4 files changed, 157 insertions(+), 121 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 361cc6dd7..d2b423c30 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -352,7 +352,9 @@ static void nl80211_nlmsg_clear(struct nl_msg *msg) static int send_and_recv(struct nl80211_global *global, struct nl_sock *nl_handle, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) + void *valid_data, + int (*ack_handler_custom)(struct nl_msg *, void *), + void *ack_data) { struct nl_cb *cb; int err = -ENOMEM, opt; @@ -430,10 +432,13 @@ static int send_and_recv(struct nl80211_global *global, int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) + void *valid_data, + int (*ack_handler_custom)(struct nl_msg *, void *), + void *ack_data) { return send_and_recv(drv->global, drv->global->nl, msg, - valid_handler, valid_data); + valid_handler, valid_data, + ack_handler_custom, ack_data); } @@ -447,7 +452,10 @@ static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv, struct nl_sock *handle, int set_owner, int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) + void *valid_data, + int (*ack_handler_custom)(struct nl_msg *, + void *), + void *ack_data) { /* Control port over nl80211 needs the flags and attributes below. * @@ -469,7 +477,8 @@ static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv, return -1; return send_and_recv(drv->global, handle ? handle : drv->global->nl, - msg, valid_handler, valid_data); + msg, valid_handler, valid_data, + ack_handler_custom, ack_data); } @@ -537,7 +546,8 @@ static int nl_get_multicast_id(struct nl80211_global *global, return -1; } - ret = send_and_recv(global, global->nl, msg, family_handler, &res); + ret = send_and_recv(global, global->nl, msg, family_handler, &res, + NULL, NULL); if (ret == 0) ret = res.id; return ret; @@ -654,7 +664,8 @@ int nl80211_get_wiphy_index(struct i802_bss *bss) if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) return -1; - if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0) + if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data, + NULL, NULL) == 0) return data.wiphy_idx; return -1; } @@ -671,7 +682,8 @@ static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss) if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) return NL80211_IFTYPE_UNSPECIFIED; - if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0) + if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data, + NULL, NULL) == 0) return data.nlmode; return NL80211_IFTYPE_UNSPECIFIED; } @@ -687,7 +699,8 @@ static int nl80211_get_macaddr(struct i802_bss *bss) if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) return -1; - return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data); + return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data, + NULL, NULL); } @@ -707,7 +720,8 @@ static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv, return -1; } - ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL); + ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Register beacons command " "failed: ret=%d (%s)", @@ -1403,7 +1417,7 @@ try_again: os_memset(&arg, 0, sizeof(arg)); arg.drv = drv; ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler, - &arg); + &arg, NULL, NULL); if (ret == -EAGAIN) { count++; if (count >= 10) { @@ -1437,7 +1451,7 @@ try_again: os_memset(&arg, 0, sizeof(arg)); arg.drv = drv; ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler, - &arg); + &arg, NULL, NULL); if (ret == -EAGAIN) { count++; if (count >= 10) { @@ -1540,7 +1554,7 @@ int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv, return -ENOBUFS; } - return send_and_recv_msgs(drv, msg, get_link_signal, sig); + return send_and_recv_msgs(drv, msg, get_link_signal, sig, NULL, NULL); } @@ -1597,7 +1611,8 @@ int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv, sig_change->frequency = drv->assoc_freq; msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); - return send_and_recv_msgs(drv, msg, get_link_noise, sig_change); + return send_and_recv_msgs(drv, msg, get_link_noise, sig_change, + NULL, NULL); } @@ -1661,7 +1676,7 @@ static int nl80211_channel_info(void *priv, struct wpa_channel_info *ci) struct nl_msg *msg; msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE); - return send_and_recv_msgs(drv, msg, get_channel_info, ci); + return send_and_recv_msgs(drv, msg, get_channel_info, ci, NULL, NULL); } @@ -1710,7 +1725,7 @@ static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg) nlmsg_free(msg); return -EINVAL; } - if (send_and_recv_msgs(drv, msg, NULL, NULL)) + if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL)) return -EINVAL; return 0; } @@ -1746,7 +1761,8 @@ static int wpa_driver_nl80211_get_country(void *priv, char *alpha2) nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG); alpha2[0] = '\0'; - ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2); + ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2, + NULL, NULL); if (!alpha2[0]) ret = -1; @@ -2189,7 +2205,8 @@ static int nl80211_register_frame(struct i802_bss *bss, return -1; } - ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL); + ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Register frame command " "failed (type=%u): ret=%d (%s)", @@ -2429,7 +2446,8 @@ static int nl80211_register_spurious_class3(struct i802_bss *bss) int ret; msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UNEXPECTED_FRAME); - ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL); + ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 " "failed: ret=%d (%s)", @@ -2583,7 +2601,7 @@ static void nl80211_del_p2pdev(struct i802_bss *bss) int ret; msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_INTERFACE); - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s", bss->ifname, (long long unsigned int) bss->wdev_id, @@ -2598,7 +2616,7 @@ static int nl80211_set_p2pdev(struct i802_bss *bss, int start) msg = nl80211_cmd_msg(bss, 0, start ? NL80211_CMD_START_P2P_DEVICE : NL80211_CMD_STOP_P2P_DEVICE); - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s", start ? "Start" : "Stop", @@ -2669,7 +2687,8 @@ static void qca_vendor_test(struct wpa_driver_nl80211_data *drv) } nla_nest_end(msg, params); - ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv); + ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv, + NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: QCA vendor test command returned %d (%s)", ret, strerror(-ret)); @@ -2794,7 +2813,7 @@ static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss) drv->ifindex); nl80211_put_wiphy_data_ap(bss); msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -3056,7 +3075,7 @@ static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv, nlmsg_free(msg); return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); + ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Key management set key failed: ret=%d (%s)", @@ -3096,7 +3115,7 @@ static int nl80211_set_pmk(struct wpa_driver_nl80211_data *drv, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); + ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Set PMK failed: ret=%d (%s)", ret, strerror(-ret)); @@ -3262,7 +3281,8 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL); + ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL, + NULL, NULL); if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE) ret = 0; if (ret) @@ -3324,7 +3344,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; err=%d %s", @@ -3448,9 +3468,10 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, } if (nl_connect) - ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL); + ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL, + NULL, NULL); else - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: MLME command failed: reason=%u ret=%d (%s)", @@ -3698,7 +3719,7 @@ retry: goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_dbg(drv->ctx, MSG_DEBUG, @@ -3976,7 +3997,7 @@ static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble, return -ENOBUFS; } - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -4020,7 +4041,7 @@ static int wpa_driver_nl80211_set_acl(void *priv, } nlmsg_free(acl); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)", ret, strerror(-ret)); @@ -4072,7 +4093,7 @@ static int nl80211_set_mesh_config(void *priv, return ret; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_ERROR, "nl80211: Mesh config set failed: %d (%s)", @@ -4197,7 +4218,7 @@ static int nl80211_set_multicast_to_unicast(struct i802_bss *bss, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); switch (ret) { case 0: @@ -4486,7 +4507,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, #endif /* CONFIG_IEEE80211AX */ ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1, - NULL, NULL); + NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", ret, strerror(-ret)); @@ -4655,7 +4676,7 @@ static int nl80211_set_channel(struct i802_bss *bss, return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret == 0) { bss->freq = freq->freq; return 0; @@ -4933,7 +4954,7 @@ static int wpa_driver_nl80211_sta_add(void *priv, nla_nest_end(msg, wme); } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION " @@ -5005,7 +5026,7 @@ static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR " --> %d (%s)", bss->ifname, MAC2STR(addr), ret, strerror(-ret)); @@ -5036,7 +5057,7 @@ void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx) } msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE); - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) + if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL) == 0) return; wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx); } @@ -5116,7 +5137,7 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv, if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER)) goto fail; - ret = send_and_recv_msgs(drv, msg, handler, arg); + ret = send_and_recv_msgs(drv, msg, handler, arg, NULL, NULL); msg = NULL; if (ret) { fail: @@ -5291,7 +5312,7 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest, return -ENOBUFS; } - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: tx_control_port failed: ret=%d (%s)", @@ -5447,7 +5468,7 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr, if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) goto fail; - return send_and_recv_msgs(bss->drv, msg, NULL, NULL); + return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); fail: nlmsg_free(msg); return -ENOBUFS; @@ -5469,7 +5490,7 @@ static int driver_nl80211_sta_set_airtime_weight(void *priv, const u8 *addr, nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight)) goto fail; - return send_and_recv_msgs(bss->drv, msg, NULL, NULL); + return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); fail: nlmsg_free(msg); return -ENOBUFS; @@ -5515,7 +5536,7 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv, msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS); ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(drv->first_bss), 1, - NULL, NULL); + NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d " "(%s)", ret, strerror(-ret)); @@ -5649,7 +5670,7 @@ retry: ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(drv->first_bss), 1, - NULL, NULL); + NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)", @@ -6051,7 +6072,7 @@ skip_auth_type: goto fail; ret = send_and_recv_msgs_owner(drv, msg, nl_connect, 1, NULL, - (void *) -1); + (void *) -1, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " @@ -6167,7 +6188,7 @@ static int wpa_driver_nl80211_associate( ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(drv->first_bss), 1, - NULL, NULL); + NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_dbg(drv->ctx, MSG_DEBUG, @@ -6198,7 +6219,7 @@ static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv, if (!msg || nla_put_u32(msg, NL80211_ATTR_IFTYPE, mode)) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (!ret) return 0; @@ -6459,7 +6480,7 @@ static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized) return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (!ret) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)", @@ -6524,7 +6545,7 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, memset(seq, 0, 6); - return send_and_recv_msgs(drv, msg, get_key_handler, seq); + return send_and_recv_msgs(drv, msg, get_key_handler, seq, NULL, NULL); } @@ -6547,7 +6568,7 @@ static int i802_set_rts(void *priv, int rts) return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (!ret) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: " @@ -6575,7 +6596,7 @@ static int i802_set_frag(void *priv, int frag) return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (!ret) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold " @@ -6597,7 +6618,7 @@ static int i802_flush(void *priv) * XXX: FIX! this needs to flush all VLANs too */ msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION); - res = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + res = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); if (res) { wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d " "(%s)", res, strerror(-res)); @@ -6806,7 +6827,8 @@ static int i802_read_sta_data(struct i802_bss *bss, return -ENOBUFS; } - return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data); + return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data, + NULL, NULL); } @@ -6863,7 +6885,7 @@ static int i802_set_tx_queue_params(void *priv, int queue, int aifs, nla_nest_end(msg, txq); - res = send_and_recv_msgs(drv, msg, NULL, NULL); + res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: TX queue param set: queue=%d aifs=%d cw_min=%d cw_max=%d burst_time=%d --> res=%d", queue, aifs, cw_min, cw_max, burst_time, res); @@ -6896,7 +6918,7 @@ static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret < 0) { wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr=" MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)", @@ -7743,7 +7765,7 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss, goto fail; cookie = 0; - ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); + ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d " @@ -7850,7 +7872,7 @@ static void nl80211_frame_wait_cancel(struct i802_bss *bss, u64 cookie) return; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d " "(%s)", ret, strerror(-ret)); @@ -7898,7 +7920,7 @@ static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq, } cookie = 0; - ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); + ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL); if (ret == 0) { wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie " "0x%llx for freq=%u MHz duration=%u", @@ -7938,7 +7960,7 @@ static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv) return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret == 0) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: " @@ -8035,7 +8057,7 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, nla_nest_end(msg, bands); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d " "(%s)", ret, strerror(-ret)); @@ -8132,7 +8154,7 @@ static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis) } nla_nest_end(msg, cqm); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -8170,7 +8192,7 @@ static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg; msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE); - return send_and_recv_msgs(drv, msg, get_channel_width, sig); + return send_and_recv_msgs(drv, msg, get_channel_width, sig, NULL, NULL); } @@ -8368,7 +8390,7 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd, return -ENOBUFS; } - return send_and_recv_msgs(bss->drv, msg, NULL, (void *) -1); + return send_and_recv_msgs(bss->drv, msg, NULL, (void *) -1, NULL, NULL); } @@ -8433,7 +8455,7 @@ static int nl80211_flush_pmkid(void *priv) msg = nl80211_bss_msg(bss, 0, NL80211_CMD_FLUSH_PMKSA); if (!msg) return -ENOBUFS; - return send_and_recv_msgs(bss->drv, msg, NULL, NULL); + return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); } @@ -8598,7 +8620,7 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq) do { wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data"); err = send_and_recv_msgs(drv, msg, survey_handler, - survey_results); + survey_results, NULL, NULL); } while (err > 0); if (err) @@ -8638,7 +8660,7 @@ static void nl80211_set_rekey_info(void *priv, const u8 *kek, size_t kek_len, nla_nest_end(msg, replay_nested); - ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); + ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL); if (ret == -EOPNOTSUPP) { wpa_printf(MSG_DEBUG, "nl80211: Driver does not support rekey offload"); @@ -8705,7 +8727,7 @@ static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr, return; } - ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); + ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL); if (ret < 0) { wpa_printf(MSG_DEBUG, "nl80211: Client probe request for " MACSTR " failed: ret=%d (%s)", @@ -8731,7 +8753,7 @@ static int nl80211_set_power_save(struct i802_bss *bss, int enabled) return -ENOBUFS; } - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); if (ret < 0) { wpa_printf(MSG_DEBUG, "nl80211: Setting PS state %s failed: %d (%s)", @@ -8791,7 +8813,7 @@ static int nl80211_start_radar_detection(void *priv, return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret == 0) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: " @@ -8838,7 +8860,7 @@ static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code, nla_put(msg, NL80211_ATTR_IE, len, buf)) goto fail; - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); fail: nlmsg_free(msg); @@ -8888,7 +8910,7 @@ static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer) return -ENOBUFS; } - res = send_and_recv_msgs(drv, msg, NULL, NULL); + res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: TDLS_OPER: oper=%d mac=" MACSTR " --> res=%d (%s)", nl80211_oper, MAC2STR(peer), res, strerror(-res)); @@ -8922,7 +8944,7 @@ nl80211_tdls_enable_channel_switch(void *priv, const u8 *addr, u8 oper_class, return ret; } - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -8948,7 +8970,7 @@ nl80211_tdls_disable_channel_switch(void *priv, const u8 *addr) return -ENOBUFS; } - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } #endif /* CONFIG TDLS */ @@ -9091,7 +9113,7 @@ static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed " "err=%d (%s)", ret, strerror(-ret)); @@ -9119,7 +9141,7 @@ static int nl80211_update_dh_ie(void *priv, const u8 *peer_mac, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: update_dh_ie failed err=%d (%s)", @@ -9324,7 +9346,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen) nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG) && nla_put_u32(msg, NL80211_ATTR_WIPHY, drv->wiphy_idx) == 0) { if (send_and_recv_msgs(drv, msg, nl80211_get_country, - alpha2) == 0 && + alpha2, NULL, NULL) == 0 && alpha2[0]) { res = os_snprintf(pos, end - pos, "country=%s\n", alpha2); @@ -9475,7 +9497,7 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings) goto fail; nla_nest_end(msg, beacon_csa); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)", ret, strerror(-ret)); @@ -9516,7 +9538,7 @@ static int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: add_ts failed err=%d (%s)", ret, strerror(-ret)); @@ -9543,7 +9565,7 @@ static int nl80211_del_ts(void *priv, u8 tsid, const u8 *addr) return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: del_ts failed err=%d (%s)", ret, strerror(-ret)); @@ -9628,7 +9650,8 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, * of send_and_recv_msgs(). */ ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 0, - cmd_reply_handler, buf); + cmd_reply_handler, buf, + NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d", ret); @@ -9643,7 +9666,8 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, nla_put(msg, NL80211_ATTR_VENDOR_DATA, data_len, data))) goto fail; - ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf); + ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf, + NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d", ret); @@ -9672,7 +9696,7 @@ static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed"); @@ -9707,7 +9731,8 @@ static int nl80211_get_wowlan(void *priv) msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_WOWLAN); - ret = send_and_recv_msgs(drv, msg, get_wowlan_handler, &wowlan_enabled); + ret = send_and_recv_msgs(drv, msg, get_wowlan_handler, &wowlan_enabled, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Getting wowlan status failed"); return 0; @@ -9754,7 +9779,7 @@ static int nl80211_set_wowlan(void *priv, nla_nest_end(msg, wowlan_triggers); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed"); @@ -9793,7 +9818,7 @@ static int nl80211_roaming(void *priv, int allowed, const u8 *bssid) } nla_nest_end(msg, params); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -9821,7 +9846,7 @@ static int nl80211_disable_fils(void *priv, int disable) } nla_nest_end(msg, params); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -9877,7 +9902,7 @@ static int nl80211_set_bssid_blacklist(void *priv, unsigned int num_bssid, nla_nest_end(msg, nlbssids); nla_nest_end(msg, params); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); fail: nlmsg_free(msg); @@ -9915,7 +9940,7 @@ static int nl80211_add_sta_node(void *priv, const u8 *addr, u16 auth_alg) } nla_nest_end(msg, params); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } #endif /* CONFIG_DRIVER_NL80211_QCA */ @@ -10084,7 +10109,7 @@ static int nl80211_join_mesh(struct i802_bss *bss, goto fail; ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1, - NULL, NULL); + NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)", @@ -10142,7 +10167,7 @@ static int wpa_driver_nl80211_leave_mesh(void *priv) wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex); msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH); ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 0, - NULL, NULL); + NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)", ret, strerror(-ret)); @@ -10176,7 +10201,7 @@ static int nl80211_probe_mesh_link(void *priv, const u8 *addr, const u8 *eth, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: mesh link probe to " MACSTR " failed: ret=%d (%s)", @@ -10588,7 +10613,7 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params) params->hw_mode, params->ht_enabled, params->ht40_enabled, params->vht_enabled, params->ch_width, params->edmg_enabled); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Failed to invoke driver ACS function: %s", @@ -10635,7 +10660,7 @@ static int nl80211_set_band(void *priv, enum set_band band) } nla_nest_end(msg, data); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Driver setband function failed: %s", @@ -10768,7 +10793,8 @@ static int nl80211_get_pref_freq_list(void *priv, nla_nest_end(msg, params); os_memset(freq_list, 0, *num * sizeof(freq_list[0])); - ret = send_and_recv_msgs(drv, msg, preferred_freq_info_handler, ¶m); + ret = send_and_recv_msgs(drv, msg, preferred_freq_info_handler, ¶m, + NULL, NULL); if (ret) { wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs", __func__); @@ -10820,7 +10846,7 @@ static int nl80211_set_prob_oper_freq(void *priv, unsigned int freq) } nla_nest_end(msg, params); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs", @@ -10876,7 +10902,7 @@ static int nl80211_p2p_lo_start(void *priv, unsigned int freq, goto fail; nla_nest_end(msg, container); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, @@ -10911,7 +10937,7 @@ static int nl80211_p2p_lo_stop(void *priv) return -1; } - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -10950,7 +10976,7 @@ static int nl80211_set_tdls_mode(void *priv, int tdls_external_control) nla_nest_end(msg, params); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, @@ -11143,7 +11169,7 @@ nl80211_get_bss_transition_status(void *priv, struct wpa_bss_trans_info *params) ret = send_and_recv_msgs(drv, msg, nl80211_get_bss_transition_status_handler, - info); + info, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, @@ -11196,7 +11222,7 @@ static int nl80211_ignore_assoc_disallow(void *priv, int ignore_disallow) nla_nest_end(msg, attr); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, @@ -11399,7 +11425,7 @@ static int nl80211_update_connection_params( nl80211_put_fils_connect_params(drv, params, msg)) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) wpa_dbg(drv->ctx, MSG_DEBUG, @@ -11442,7 +11468,7 @@ static int nl80211_send_external_auth_status(void *priv, (params->bssid && nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid))) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, @@ -11482,7 +11508,7 @@ static int nl80211_set_4addr_mode(void *priv, const char *bridge_ifname, bss->added_if_into_bridge = 0; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (!ret) { if (bridge_ifname[0] && val && diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 1dd5aee8b..e4cbcc6e2 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -231,7 +231,9 @@ struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags, struct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd); int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), - void *valid_data); + void *valid_data, + int (*ack_handler_custom)(struct nl_msg *, void *), + void *ack_data); struct nl_sock * get_connect_handle(struct i802_bss *bss); int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, const char *ifname, enum nl80211_iftype iftype, diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index b9eb6e220..5d2558153 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -49,7 +49,8 @@ static u32 get_nl80211_protocol_features(struct wpa_driver_nl80211_data *drv) return 0; } - if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat) == 0) + if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat, + NULL, NULL) == 0) return feat; return 0; @@ -1052,7 +1053,7 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv, return -1; } - if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info)) + if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info, NULL, NULL)) return -1; if (info->auth_supported) @@ -1158,7 +1159,8 @@ static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data *drv) return; } - ret = send_and_recv_msgs(drv, msg, dfs_info_handler, &dfs_capability); + ret = send_and_recv_msgs(drv, msg, dfs_info_handler, &dfs_capability, + NULL, NULL); if (!ret && dfs_capability) drv->capa.flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD; } @@ -1245,7 +1247,8 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv) os_memset(&info, 0, sizeof(info)); info.capa = &drv->capa; - ret = send_and_recv_msgs(drv, msg, features_info_handler, &info); + ret = send_and_recv_msgs(drv, msg, features_info_handler, &info, + NULL, NULL); if (ret || !info.flags) return; @@ -2327,7 +2330,8 @@ static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv, } } - return send_and_recv_msgs(drv, msg, nl80211_get_reg, results); + return send_and_recv_msgs(drv, msg, nl80211_get_reg, results, + NULL, NULL); } @@ -2416,7 +2420,8 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags, return NULL; } - if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) { + if (send_and_recv_msgs(drv, msg, phy_info_handler, &result, + NULL, NULL) == 0) { struct hostapd_hw_modes *modes; nl80211_set_regulatory_flags(drv, &result); diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index dc91a2901..233175d19 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -82,7 +82,8 @@ static int nl80211_get_noise_for_scan_results( os_memset(info, 0, sizeof(*info)); msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); - return send_and_recv_msgs(drv, msg, get_noise_for_scan_results, info); + return send_and_recv_msgs(drv, msg, get_noise_for_scan_results, info, + NULL, NULL); } @@ -94,7 +95,7 @@ static int nl80211_abort_scan(struct i802_bss *bss) wpa_printf(MSG_DEBUG, "nl80211: Abort scan"); msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)", ret, strerror(-ret)); @@ -125,7 +126,7 @@ static int nl80211_abort_vendor_scan(struct wpa_driver_nl80211_data *drv, nla_nest_end(msg, params); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_INFO, @@ -365,7 +366,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss, goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " @@ -618,7 +619,7 @@ int wpa_driver_nl80211_sched_scan(void *priv, params->sched_scan_start_delay)) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); /* TODO: if we get an error here, we should fall back to normal scan */ @@ -655,7 +656,7 @@ int wpa_driver_nl80211_stop_sched_scan(void *priv) #endif /* ANDROID */ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_STOP_SCHED_SCAN); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop failed: ret=%d (%s)", @@ -944,7 +945,7 @@ try_again: arg.drv = drv; arg.res = res; - ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); + ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg, NULL, NULL); if (ret == -EAGAIN) { count++; if (count >= 10) { @@ -1028,7 +1029,8 @@ void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv) ctx.idx = 0; msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP, NL80211_CMD_GET_SCAN); if (msg) - send_and_recv_msgs(drv, msg, nl80211_dump_scan_handler, &ctx); + send_and_recv_msgs(drv, msg, nl80211_dump_scan_handler, &ctx, + NULL, NULL); } @@ -1221,7 +1223,8 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss, nla_nest_end(msg, attr); - ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie); + ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie, + NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, @@ -1284,7 +1287,7 @@ int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len) nla_nest_end(msg, attr); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, From 6f19cc4d7887c7c4c718bc746b661f9a9aadcff4 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 10 Jun 2020 10:32:57 +0200 Subject: [PATCH 0715/1105] nl80211: Handle control port TX status events over nl80211 In order to retransmit faster in AP mode, hostapd can handle TX status notifications. When using nl80211, this is currently only possible with socket control messages. Add support for receiving such events directly over nl80211 and detecting, if this feature is supported. This finally allows for a clean separation between management/control path (over nl80211) and in-kernel data path. A follow up commit enables the feature in AP mode. Control port TX status contains the original frame content for matching with the current hostapd code. Furthermore, a cookie is included, which allows for matching against outstanding cookies in the future. This commit only prints the cookie value for debugging purposes on TX status receive. Signed-off-by: Markus Theil --- src/drivers/driver.h | 2 ++ src/drivers/driver_common.c | 1 + src/drivers/driver_nl80211_capa.c | 4 ++++ src/drivers/driver_nl80211_event.c | 36 ++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 0ecda49dd..cb412cbfe 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1931,6 +1931,8 @@ struct wpa_driver_capa { /** Driver supports a separate control port RX for EAPOL frames */ #define WPA_DRIVER_FLAGS2_CONTROL_PORT_RX 0x0000000000000001ULL +/** Driver supports TX status reports for EAPOL frames through control port */ +#define WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS 0x0000000000000002ULL u64 flags2; #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 23a6a4293..a7ebe9566 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -328,6 +328,7 @@ const char * driver_flag2_to_string(u64 flag2) #define DF2S(x) case WPA_DRIVER_FLAGS2_ ## x: return #x switch (flag2) { DF2S(CONTROL_PORT_RX); + DF2S(CONTROL_PORT_TX_STATUS); } return "UNKNOWN"; #undef DF2S diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 5d2558153..46f61fdbf 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -620,6 +620,10 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH)) capa->flags2 |= WPA_DRIVER_FLAGS2_CONTROL_PORT_RX; + if (ext_feature_isset( + ext_features, len, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS)) + capa->flags2 |= WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS; if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_VLAN_OFFLOAD)) diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 6a2de1f3c..1873b1826 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -138,6 +138,8 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd) C2S(NL80211_CMD_CONTROL_PORT_FRAME) C2S(NL80211_CMD_UPDATE_OWE_INFO) C2S(NL80211_CMD_UNPROT_BEACON) + C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS) + default: return "NL80211_CMD_UNKNOWN"; } @@ -2557,6 +2559,37 @@ static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv, } +static void +nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv, + struct nlattr **tb) +{ + bool acked = tb[NL80211_ATTR_ACK]; + union wpa_event_data event; + const u8 *frame; + size_t frame_len; + + if (!tb[NL80211_ATTR_FRAME] || !tb[NL80211_ATTR_COOKIE]) + return; + + frame = nla_data(tb[NL80211_ATTR_FRAME]); + frame_len = nla_len(tb[NL80211_ATTR_FRAME]); + if (frame_len < ETH_HLEN) + return; + + wpa_printf(MSG_DEBUG, + "nl80211: Control port TX status (ack=%d), cookie=%llu", + acked, (long long unsigned int) + nla_get_u64(tb[NL80211_ATTR_COOKIE])); + + os_memset(&event, 0, sizeof(event)); + event.eapol_tx_status.dst = frame; + event.eapol_tx_status.data = frame + ETH_HLEN; + event.eapol_tx_status.data_len = frame_len - ETH_HLEN; + event.eapol_tx_status.ack = acked; + wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event); +} + + static void do_process_drv_event(struct i802_bss *bss, int cmd, struct nlattr **tb) { @@ -2775,6 +2808,9 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, mlme_event_unprot_beacon(drv, nla_data(frame), nla_len(frame)); break; + case NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS: + nl80211_control_port_frame_tx_status(drv, tb); + break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", cmd); From 87065881b11732ccaff3607ee51b582926059710 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 10 Jun 2020 10:32:59 +0200 Subject: [PATCH 0716/1105] nl80211: Use ext ack handler for TX control port Allow custom ack handler to be registered and use the ext ack handler for TX control port to fetch the cookie information. If these cookies are not supported by the current kernel, a value of 0 is returned. Signed-off-by: Markus Theil --- src/drivers/driver_nl80211.c | 58 ++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index d2b423c30..da7038fea 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -278,6 +278,43 @@ static int ack_handler(struct nl_msg *msg, void *arg) return NL_STOP; } + +struct nl80211_ack_ext_arg { + int *err; + void *ext_data; +}; + + +static int ack_handler_cookie(struct nl_msg *msg, void *arg) +{ + struct nl80211_ack_ext_arg *ext_arg = arg; + struct nlattr *tb[NLMSGERR_ATTR_MAX + 1]; + u64 *cookie = ext_arg->ext_data; + struct nlattr *attrs; + size_t ack_len, attr_len; + + *ext_arg->err = 0; + ack_len = sizeof(struct nlmsghdr) + sizeof(int) + + sizeof(struct nlmsghdr); + attrs = (struct nlattr *) + ((u8 *) nlmsg_data(nlmsg_hdr(msg)) + sizeof(struct nlmsghdr) + + sizeof(int)); + if (nlmsg_hdr(msg)->nlmsg_len <= ack_len) + return NL_STOP; + + attr_len = nlmsg_hdr(msg)->nlmsg_len - ack_len; + + if(!(nlmsg_hdr(msg)->nlmsg_flags & NLM_F_ACK_TLVS)) + return NL_STOP; + + nla_parse(tb, NLMSGERR_ATTR_MAX, attrs, attr_len, NULL); + if (tb[NLMSGERR_ATTR_COOKIE]) + *cookie = nla_get_u64(tb[NLMSGERR_ATTR_COOKIE]); + + return NL_STOP; +} + + static int finish_handler(struct nl_msg *msg, void *arg) { int *ret = arg; @@ -392,7 +429,15 @@ static int send_and_recv(struct nl80211_global *global, nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); - nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + if (ack_handler_custom) { + struct nl80211_ack_ext_arg *ext_arg = ack_data; + + ext_arg->err = &err; + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, + ack_handler_custom, ack_data); + } else { + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + } if (valid_handler) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, @@ -5292,8 +5337,10 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest, u16 proto, const u8 *buf, size_t len, int no_encrypt) { + struct nl80211_ack_ext_arg ext_arg; struct i802_bss *bss = priv; struct nl_msg *msg; + u64 cookie = 0; int ret; wpa_printf(MSG_DEBUG, @@ -5312,11 +5359,18 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest, return -ENOBUFS; } - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); + os_memset(&ext_arg, 0, sizeof(struct nl80211_ack_ext_arg)); + ext_arg.ext_data = &cookie; + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, + ack_handler_cookie, &ext_arg); if (ret) wpa_printf(MSG_DEBUG, "nl80211: tx_control_port failed: ret=%d (%s)", ret, strerror(-ret)); + else + wpa_printf(MSG_DEBUG, + "nl80211: tx_control_port cookie=0x%llx", + (long long unsigned int) cookie); return ret; } From 569497bf4fdd188634e874f743b6ec3504a9fc2c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 21 Jun 2020 17:32:00 +0300 Subject: [PATCH 0717/1105] nl80211: Work around misdelivered control port TX status The kernel commit "mac80211: support control port TX status reporting" seems to be delivering the TX status events for EAPOL frames over control port using NL80211_CMD_FRAME_TX_STATUS due to incorrect check on whether the frame is a Management or Data frame. Use the pending cookie value from EAPOL TX operation to detect this incorrect behavior and redirect the event internally to allow it to be used to get full TX control port functionality available for AP mode. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 8 ++++-- src/drivers/driver_nl80211.h | 1 + src/drivers/driver_nl80211_event.c | 44 ++++++++++++++++++++---------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index da7038fea..7e3b3f40d 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5363,14 +5363,18 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest, ext_arg.ext_data = &cookie; ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, ack_handler_cookie, &ext_arg); - if (ret) + if (ret) { wpa_printf(MSG_DEBUG, "nl80211: tx_control_port failed: ret=%d (%s)", ret, strerror(-ret)); - else + } else { + struct wpa_driver_nl80211_data *drv = bss->drv; + wpa_printf(MSG_DEBUG, "nl80211: tx_control_port cookie=0x%llx", (long long unsigned int) cookie); + drv->eapol_tx_cookie = cookie; + } return ret; } diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index e4cbcc6e2..017c025a0 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -181,6 +181,7 @@ struct wpa_driver_nl80211_data { #define MAX_SEND_FRAME_COOKIES 20 u64 send_frame_cookies[MAX_SEND_FRAME_COOKIES]; unsigned int num_send_frame_cookies; + u64 eapol_tx_cookie; unsigned int last_mgmt_freq; diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 1873b1826..ce95e9cd3 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -20,6 +20,12 @@ #include "driver_nl80211.h" +static void +nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv, + const u8 *frame, size_t len, + struct nlattr *ack, struct nlattr *cookie); + + static const char * nl80211_command_to_string(enum nl80211_commands cmd) { #define C2S(x) case x: return #x; @@ -700,6 +706,16 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv, WLAN_FC_GET_STYPE(fc), (long long unsigned int) cookie_val, cookie ? "" : "(N/A)", ack != NULL); + if (cookie_val && cookie_val == drv->eapol_tx_cookie && + len >= ETH_HLEN && + WPA_GET_BE16(frame + 2 * ETH_ALEN) == ETH_P_PAE) { + wpa_printf(MSG_DEBUG, + "nl80211: Work around misdelivered control port TX status for EAPOL"); + nl80211_control_port_frame_tx_status(drv, frame, len, ack, + cookie); + return; + } + if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) return; @@ -2561,31 +2577,23 @@ static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv, static void nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv, - struct nlattr **tb) + const u8 *frame, size_t len, + struct nlattr *ack, struct nlattr *cookie) { - bool acked = tb[NL80211_ATTR_ACK]; union wpa_event_data event; - const u8 *frame; - size_t frame_len; - if (!tb[NL80211_ATTR_FRAME] || !tb[NL80211_ATTR_COOKIE]) - return; - - frame = nla_data(tb[NL80211_ATTR_FRAME]); - frame_len = nla_len(tb[NL80211_ATTR_FRAME]); - if (frame_len < ETH_HLEN) + if (!cookie || len < ETH_HLEN) return; wpa_printf(MSG_DEBUG, "nl80211: Control port TX status (ack=%d), cookie=%llu", - acked, (long long unsigned int) - nla_get_u64(tb[NL80211_ATTR_COOKIE])); + ack != NULL, (long long unsigned int) nla_get_u64(cookie)); os_memset(&event, 0, sizeof(event)); event.eapol_tx_status.dst = frame; event.eapol_tx_status.data = frame + ETH_HLEN; - event.eapol_tx_status.data_len = frame_len - ETH_HLEN; - event.eapol_tx_status.ack = acked; + event.eapol_tx_status.data_len = len - ETH_HLEN; + event.eapol_tx_status.ack = ack != NULL; wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event); } @@ -2809,7 +2817,13 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, nla_len(frame)); break; case NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS: - nl80211_control_port_frame_tx_status(drv, tb); + if (!frame) + break; + nl80211_control_port_frame_tx_status(drv, + nla_data(frame), + nla_len(frame), + tb[NL80211_ATTR_ACK], + tb[NL80211_ATTR_COOKIE]); break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " From 67efd19e0a6019c11fd83a47f68a3573da1db520 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 10 Jun 2020 10:32:58 +0200 Subject: [PATCH 0718/1105] nl80211: Use control port TX (status) in AP mode if possible Check if nl80211 control port TX status is available in the kernel and enable control port TX if so. With this feature, nl80211 control path is able to provide the same feature set as nl80211 (management) + AF_PACKET socket (control) before. For debugging and testing, this can explicitly be disabled with the driver parameter control_port_ap=0. Signed-off-by: Markus Theil --- src/drivers/driver_nl80211.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 7e3b3f40d..87a11a595 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2172,6 +2172,11 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params)) goto failed; + if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS) { + drv->control_port_ap = 1; + goto skip_wifi_status; + } + drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0); if (drv->eapol_tx_sock < 0) goto failed; @@ -2195,6 +2200,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, drv, NULL); } } +skip_wifi_status: if (drv->global) { nl80211_check_global(drv->global); @@ -8313,12 +8319,19 @@ static int nl80211_set_param(void *priv, const char *param) if (os_strstr(param, "control_port=0")) { drv->capa.flags &= ~WPA_DRIVER_FLAGS_CONTROL_PORT; - drv->capa.flags2 &= ~WPA_DRIVER_FLAGS2_CONTROL_PORT_RX; + drv->capa.flags2 &= ~(WPA_DRIVER_FLAGS2_CONTROL_PORT_RX | + WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS); + drv->control_port_ap = 0; } if (os_strstr(param, "control_port_ap=1")) drv->control_port_ap = 1; + if (os_strstr(param, "control_port_ap=0")) { + drv->capa.flags2 &= ~WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS; + drv->control_port_ap = 0; + } + if (os_strstr(param, "full_ap_client_state=0")) drv->capa.flags &= ~WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE; From b649fa4f4260c7a071b953df74e5736c420ee349 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 21 Jun 2020 17:32:00 +0300 Subject: [PATCH 0719/1105] tests: nl80211 control port in AP mode disabled/enabled Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_psk.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index 116733a1b..e79380e90 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -3362,10 +3362,17 @@ def test_ap_wpa2_psk_no_control_port(dev, apdev): def test_ap_wpa2_psk_ap_control_port(dev, apdev): """WPA2-PSK AP with nl80211 control port in AP mode""" + run_ap_wpa2_psk_ap_control_port(dev, apdev, ctrl_val=1) + +def test_ap_wpa2_psk_ap_control_port_disabled(dev, apdev): + """WPA2-PSK AP with nl80211 control port in AP mode disabled""" + run_ap_wpa2_psk_ap_control_port(dev, apdev, ctrl_val=0) + +def run_ap_wpa2_psk_ap_control_port(dev, apdev, ctrl_val): ssid = "test-wpa2-psk" passphrase = 'qwertyuiop' params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) - params['driver_params'] = "control_port_ap=1" + params['driver_params'] = "control_port_ap=%d" % ctrl_val hapd = hostapd.add_ap(apdev[0], params) flags = hapd.request("DRIVER_FLAGS").splitlines()[1:] From 4f4a52c3cc0f617281297930f9278e783b9e96da Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 22 Jun 2020 20:00:31 +0300 Subject: [PATCH 0720/1105] DPP: Clear bootstrap entries only after clearing authentication state This fixes an issue where the pending authentication might have held a reference to auth->tmp_peer_bi and dpp_auth_deinit() would try to free that bootstrapping entry. This needs to happen before the call to dpp_global_clear() to avoid double-removal of the bootstrapping entry from the list. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 2d56b2f9d..0cda38542 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3260,7 +3260,6 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) #endif /* CONFIG_TESTING_OPTIONS */ if (!wpa_s->dpp) return; - dpp_global_clear(wpa_s->dpp); eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); @@ -3284,6 +3283,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN); os_free(wpa_s->dpp_configurator_params); wpa_s->dpp_configurator_params = NULL; + dpp_global_clear(wpa_s->dpp); } From b62e46f6908bdb627c8d31006dd878fc7a3ffeec Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 22 Jun 2020 21:45:10 +0300 Subject: [PATCH 0721/1105] DPP2: Fix DPP_CA_SET processing with authentication not having peer BI Need to check for auth->peer_bi being set before using it here. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 0cda38542..801e372bb 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3668,7 +3668,8 @@ int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) if (pos) { peer = atoi(pos + 6); if (!auth || !auth->waiting_cert || - (unsigned int) peer != auth->peer_bi->id) { + (auth->peer_bi && + (unsigned int) peer != auth->peer_bi->id)) { auth = dpp_controller_get_auth(wpa_s->dpp, peer); tcp = true; } From fc005be6c133532a08beeb788d188fa45ded4f43 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 22 Jun 2020 21:45:57 +0300 Subject: [PATCH 0722/1105] tests: sigma_dut DPP Configurator for dot1x Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 03caaa4fc..992cce740 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -1530,6 +1530,21 @@ def test_sigma_dut_dpp_qr_resp_10(dev, apdev): """sigma_dut DPP/QR responder (conf index 10)""" run_sigma_dut_dpp_qr_resp(dev, apdev, 10) +def test_sigma_dut_dpp_qr_resp_11(dev, apdev, params): + """sigma_dut DPP/QR responder (conf index 11)""" + logdir = params['logdir'] + with open("auth_serv/ec-ca.pem", "rb") as f: + res = f.read() + with open(os.path.join(logdir, "dpp-ca.pem"), "wb") as f: + f.write(res) + with open("auth_serv/ec-ca.key", "rb") as f: + res = f.read() + with open(os.path.join(logdir, "dpp-ca.key"), "wb") as f: + f.write(res) + with open(os.path.join(logdir, "dpp-ca-csrattrs"), "wb") as f: + f.write(b'MAsGCSqGSIb3DQEJBw==') + run_sigma_dut_dpp_qr_resp(dev, apdev, 11, cert_path=logdir) + def test_sigma_dut_dpp_qr_resp_chan_list(dev, apdev): """sigma_dut DPP/QR responder (channel list override)""" run_sigma_dut_dpp_qr_resp(dev, apdev, 1, chan_list='81/2 81/6 81/1', @@ -1554,10 +1569,10 @@ def test_sigma_dut_dpp_qr_resp_configurator(dev, apdev): def run_sigma_dut_dpp_qr_resp(dev, apdev, conf_idx, chan_list=None, listen_chan=None, status_query=False, - enrollee_role="STA"): + enrollee_role="STA", cert_path=None): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) - sigma = start_sigma_dut(dev[0].ifname) + sigma = start_sigma_dut(dev[0].ifname, cert_path=cert_path) try: cmd = "dev_exec_action,program,DPP,DPPActionType,GetLocalBootstrap,DPPCryptoIdentifier,P-256,DPPBS,QR" if chan_list: From 27ade5952439dd32fcbbe80320d5bd5692f31772 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 22 Jun 2020 23:38:36 +0300 Subject: [PATCH 0723/1105] tests: sigma_dut sta_scan WaitCompletion,1 Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 992cce740..0c230b72e 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3393,6 +3393,15 @@ def test_sigma_dut_sta_scan_short_ssid(dev, apdev): if not found: raise Exception("AP not found in scan results") +def test_sigma_dut_sta_scan_wait_completion(dev, apdev): + """sigma_dut sta_scan WaitCompletion,1""" + sigma = start_sigma_dut(dev[0].ifname) + try: + cmd = "sta_scan,Interface,%s,ChnlFreq,2412,WaitCompletion,1" % dev[0].ifname + res = sigma_dut_cmd(cmd, timeout=10) + finally: + stop_sigma_dut(sigma) + def test_sigma_dut_ap_osen(dev, apdev, params): """sigma_dut controlled AP with OSEN""" logdir = os.path.join(params['logdir'], From eddf22e1f2dd263077c15a776d1d1c13a329766f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 23 Jun 2020 00:57:18 +0300 Subject: [PATCH 0724/1105] dpp-nfc: Update debug print for tag-read-only operation Be clearer about only a tag read being allowed when dpp-nfc is configured to not allow connection handover. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 188354553..8ce8456d6 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -810,7 +810,10 @@ def main(): clear_raw_mode() if was_in_raw_mode: print("\r") - summary("Waiting for a tag or peer to be touched") + if args.tag_read_only: + summary("Waiting for a tag to be touched") + else: + summary("Waiting for a tag or peer to be touched") wait_connection = True try: if args.tag_read_only: From 5908fedc100b723c0ff4e5637ea6d09578b89570 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 23 Jun 2020 13:24:38 +0300 Subject: [PATCH 0725/1105] dpp-nfc: Support channel list negotiation If the peer's channel list in negotiated handover does not have any common channels and the local end is configured with an alternative channel list, try to initiate another negotiation handover with the alternative channels. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 41 +++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 8ce8456d6..5230dc59d 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -179,12 +179,15 @@ def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, raise Exception("Failed to generate bootstrapping info") return int(res) -def wpas_get_nfc_uri(start_listen=True, pick_channel=False): +def wpas_get_nfc_uri(start_listen=True, pick_channel=False, chan_override=None): wpas = wpas_connect() if wpas is None: return None global own_id, chanlist - chan = chanlist + if chan_override: + chan = chan_override + else: + chan = chanlist if chan is None and get_status_field(wpas, "bssid[0]"): freq = get_status_field(wpas, "freq") if freq: @@ -219,8 +222,12 @@ def wpas_report_handover_sel(uri): cmd = "DPP_NFC_HANDOVER_SEL own=%d uri=%s" % (own_id, uri) return wpas.request(cmd) -def dpp_handover_client(llc): - uri = wpas_get_nfc_uri(start_listen=False) +def dpp_handover_client(llc, alt=False): + chan_override = None + if alt: + global altchanlist + chan_override = altchanlist + uri = wpas_get_nfc_uri(start_listen=False, chan_override=chan_override) if uri is None: summary("Cannot start handover client - no bootstrap URI available") return @@ -346,6 +353,10 @@ def dpp_handover_client(llc): if not dpp_found: summary("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") + my_crn_ready = False + my_crn = None + peer_crn = None + hs_sent = False client.close() summary("Returning from dpp_handover_client") return @@ -374,6 +385,7 @@ class HandoverServer(nfc.handover.HandoverServer): self.ho_server_processing = False self.success = False self.try_own = False + self.llc = llc def process_handover_request_message(self, records): self.ho_server_processing = True @@ -439,6 +451,11 @@ class HandoverServer(nfc.handover.HandoverServer): res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: summary("DPP handover request processing failed") + global altchanlist + if altchanlist: + data = wpas_get_nfc_uri(start_listen=False, + chan_override=altchanlist) + summary("Own URI (try another channel list): %s" % data) continue found = True @@ -492,9 +509,14 @@ class HandoverServer(nfc.handover.HandoverServer): summary("Sending handover select: " + str(sel)) if found: + summary("Handover completed successfully") self.success = True else: + summary("Try to initiate with alternative parameters") self.try_own = True + if not init_on_touch and no_input: + # Need to start client thread now + threading.Thread(target=llcp_worker, args=(self.llc,)).start() global hs_sent hs_sent = True return sel @@ -648,7 +670,12 @@ def llcp_worker(llc): if srv.try_own: srv.try_own = False summary("Try to initiate another handover with own parameters") - dpp_handover_client(llc) + global peer_crn, my_crn, my_crn_ready, hs_sent + my_crn_ready = False + my_crn = None + peer_crn = None + hs_sent = False + dpp_handover_client(llc, alt=True) summary("Exiting llcp_worker thread (retry with own parameters)") return if srv.ho_server_processing: @@ -737,6 +764,7 @@ def main(): help='success file for writing success update') parser.add_argument('--device', default='usb', help='NFC device to open') parser.add_argument('--chan', default=None, help='channel list') + parser.add_argument('--altchan', default=None, help='alternative channel list') parser.add_argument('command', choices=['write-nfc-uri', 'write-nfc-hs'], nargs='?') @@ -749,8 +777,9 @@ def main(): global no_wait no_wait = args.no_wait - global chanlist + global chanlist, altchanlist chanlist = args.chan + altchanlist = args.altchan logging.basicConfig(level=args.loglevel) From 52a32576218e88450e8460792ff9600f1ba9eeb7 Mon Sep 17 00:00:00 2001 From: Wu Gao Date: Mon, 8 Jun 2020 14:27:12 +0800 Subject: [PATCH 0726/1105] 6 GHz: Change 6 GHz channels per IEEE P802.11ax/D6.1 The channel numbering/center frequencies was changed in IEEE P802.11ax/D6.1. The center frequencies of the channels were shifted by 10 MHz. Also, a new operating class 136 was defined with a single channel 2. Add required support to change the channelization as per IEEE P802.11ax/D6.1. Signed-off-by: Wu Gao Signed-off-by: Vamsi Krishna --- hostapd/hostapd.conf | 8 ++++---- src/common/ieee802_11_common.c | 37 +++++++++++++++++++++++++--------- wpa_supplicant/op_classes.c | 6 +++--- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 060738c34..91ac96785 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -210,7 +210,7 @@ channel=1 # Frequency list can be provided as range using hyphen ('-') or individual # frequencies can be specified by comma (',') separated values # Default: all frequencies allowed in selected hw_mode -#freqlist=2437,5945,5965 +#freqlist=2437,5955,5975 #freqlist=2437,5985-6105 # Exclude DFS channels from ACS @@ -822,11 +822,11 @@ wmm_ac_vo_acm=0 #he_rts_threshold=0 # HE operating channel information; see matching vht_* parameters for details. -# On the 6 GHz band the center freq calculation starts from 5.940 GHz offset. -# For example idx=3 would result in 5955 MHz center frequency. In addition, +# On the 6 GHz band the center freq calculation starts from 5.950 GHz offset. +# For example idx=3 would result in 5965 MHz center frequency. In addition, # he_oper_chwidth is ignored, and the channel width is derived from the # configured operating class or center frequency indexes (see -# IEEE P802.11ax/D4.3 Annex E, Table E-4). +# IEEE P802.11ax/D6.1 Annex E, Table E-4). #he_oper_chwidth #he_oper_centr_freq_seg0_idx #he_oper_centr_freq_seg1_idx diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index c4e744693..c0c569bc6 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1029,9 +1029,9 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, return HOSTAPD_MODE_IEEE80211A; } - if (freq > 5940 && freq <= 7105) { + if (freq > 5950 && freq <= 7115) { int bw; - u8 idx = (freq - 5940) / 5; + u8 idx = (freq - 5950) / 5; bw = center_idx_to_bw_6ghz(idx); if (bw < 0) @@ -1042,6 +1042,12 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, return HOSTAPD_MODE_IEEE80211A; } + if (freq == 5935) { + *op_class = 136; + *channel = (freq - 5925) / 5; + return HOSTAPD_MODE_IEEE80211A; + } + /* 56.16 GHz, channel 1..6 */ if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) { if (sec_channel) @@ -1418,7 +1424,11 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan) case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */ if (chan < 1 || chan > 233) return -1; - return 5940 + chan * 5; + return 5950 + chan * 5; + case 136: /* UHB channels, 20 MHz: 2 */ + if (chan == 2) + return 5935; + return -1; case 180: /* 60 GHz band, channels 1..8 */ if (chan < 1 || chan > 8) return -1; @@ -2208,10 +2218,13 @@ int center_idx_to_bw_6ghz(u8 idx) int is_6ghz_freq(int freq) { - if (freq < 5940 || freq > 7105) + if (freq < 5935 || freq > 7115) return 0; - if (center_idx_to_bw_6ghz((freq - 5940) / 5) < 0) + if (freq == 5935) + return 1; + + if (center_idx_to_bw_6ghz((freq - 5950) / 5) < 0) return 0; return 1; @@ -2220,7 +2233,7 @@ int is_6ghz_freq(int freq) int is_6ghz_op_class(u8 op_class) { - return op_class >= 131 && op_class <= 135; + return op_class >= 131 && op_class <= 136; } @@ -2228,14 +2241,14 @@ int is_6ghz_psc_frequency(int freq) { int i; - if (!is_6ghz_freq(freq)) + if (!is_6ghz_freq(freq) || freq == 5935) return 0; - if ((((freq - 5940) / 5) & 0x3) != 0x1) + if ((((freq - 5950) / 5) & 0x3) != 0x1) return 0; - i = (freq - 5940 + 55) % 80; + i = (freq - 5950 + 55) % 80; if (i == 0) - i = (freq - 5940 + 55) / 80; + i = (freq - 5950 + 55) / 80; if (i >= 1 && i <= 15) return 1; @@ -2471,6 +2484,8 @@ int op_class_to_bandwidth(u8 op_class) case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */ case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */ return 160; + case 136: /* UHB channels, 20 MHz: 2 */ + return 20; case 180: /* 60 GHz band, channels 1..8 */ return 2160; case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */ @@ -2531,6 +2546,8 @@ int op_class_to_ch_width(u8 op_class) return CHANWIDTH_160MHZ; case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */ return CHANWIDTH_80P80MHZ; + case 136: /* UHB channels, 20 MHz: 2 */ + return CHANWIDTH_USE_HT; case 180: /* 60 GHz band, channels 1..8 */ return CHANWIDTH_2160MHZ; case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */ diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c index 983801faa..bd97fee54 100644 --- a/wpa_supplicant/op_classes.c +++ b/wpa_supplicant/op_classes.c @@ -22,13 +22,13 @@ static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, unsigned int *flags) { int i; - int is_6ghz = op_class >= 131 && op_class <= 135; + int is_6ghz = op_class >= 131 && op_class <= 136; for (i = 0; i < mode->num_channels; i++) { int chan_is_6ghz; - chan_is_6ghz = mode->channels[i].freq > 5940 && - mode->channels[i].freq <= 7105; + chan_is_6ghz = mode->channels[i].freq >= 5935 && + mode->channels[i].freq <= 7115; if (is_6ghz == chan_is_6ghz && mode->channels[i].chan == chan) break; } From 70b80c31f9355df2002c20cc31a5bd1cc547b1e3 Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Tue, 19 May 2020 17:43:22 +0530 Subject: [PATCH 0727/1105] nl80211: Do not send FILS ERP sequence number without rRK FILS ERP cannot be used without rRK, so include these attributes only together. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 87a11a595..ea16d8daf 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5781,13 +5781,13 @@ static int nl80211_put_fils_connect_params(struct wpa_driver_nl80211_data *drv, return -1; } - wpa_printf(MSG_DEBUG, " * FILS ERP next seq %u", - params->fils_erp_next_seq_num); - if (nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM, - params->fils_erp_next_seq_num)) - return -1; - if (params->fils_erp_rrk_len) { + wpa_printf(MSG_DEBUG, " * FILS ERP next seq %u", + params->fils_erp_next_seq_num); + if (nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM, + params->fils_erp_next_seq_num)) + return -1; + wpa_printf(MSG_DEBUG, " * FILS ERP rRK (len=%lu)", (unsigned long) params->fils_erp_rrk_len); if (nla_put(msg, NL80211_ATTR_FILS_ERP_RRK, From d0819a11ccf00cc11f9c7f2b023c43401249bbde Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Tue, 19 May 2020 17:43:22 +0530 Subject: [PATCH 0728/1105] FILS: Use FILS auth alg when connecting using PMKSA caching When a PMKSA cache entry is available and used for connection with FILS key management suite, use FILS authentication algorithm for connection even if ERP keys are not available. This scenario may happen when applications using wpa_supplicant cache persistently only PMKSA but not ERP keys and reconfigures wpa_supplicant with PMKSA cache after restarting wpa_supplicant. The previous implementation correctly handles SME-in-wpa_supplicant cases. However, SME-in-driver cases, complete FILS authentication without PMKSA caching is performed. Fix SME-in-driver behavior by setting authentication algorithm to WPA_AUTH_ALG_FILS when connecting to a FILS AP using PMKSA caching. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 4c1daf1fa..e7989baef 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2752,9 +2752,9 @@ static u8 * wpas_populate_assoc_ies( #ifdef CONFIG_MBO const u8 *mbo_ie; #endif -#ifdef CONFIG_SAE - int sae_pmksa_cached = 0; -#endif /* CONFIG_SAE */ +#if defined(CONFIG_SAE) || defined(CONFIG_FILS) + int pmksa_cached = 0; +#endif /* CONFIG_SAE || CONFIG_FILS */ #ifdef CONFIG_FILS const u8 *realm, *username, *rrk; size_t realm_len, username_len, rrk_len; @@ -2794,9 +2794,9 @@ static u8 * wpas_populate_assoc_ies( ssid, try_opportunistic, cache_id, 0) == 0) { eapol_sm_notify_pmkid_attempt(wpa_s->eapol); -#ifdef CONFIG_SAE - sae_pmksa_cached = 1; -#endif /* CONFIG_SAE */ +#if defined(CONFIG_SAE) || defined(CONFIG_FILS) + pmksa_cached = 1; +#endif /* CONFIG_SAE || CONFIG_FILS */ } wpa_ie_len = max_wpa_ie_len; if (wpa_supplicant_set_suites(wpa_s, bss, ssid, @@ -2895,6 +2895,10 @@ static u8 * wpas_populate_assoc_ies( if (mask) *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO; + } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) && + ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) && + pmksa_cached) { + algs = WPA_AUTH_ALG_FILS; } #endif /* CONFIG_FILS */ #endif /* IEEE8021X_EAPOL */ @@ -2911,7 +2915,7 @@ static u8 * wpas_populate_assoc_ies( } #ifdef CONFIG_SAE - if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) { + if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) { wpa_dbg(wpa_s, MSG_DEBUG, "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt"); algs = WPA_AUTH_ALG_OPEN; From c9dc075fcd06df0b66e3015560b0c6950712818b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 24 Jun 2020 22:37:52 +0300 Subject: [PATCH 0729/1105] dpp-nfc: Fix connection handover renegotiation The use of the alternative channel list did not work properly for the case were both ends were trying to initiate the negotiated connection handover. Fix this by always starting a new connection handover client thread for sending the alternative proposal and ignoring peer messages (likely something from the first attempt) during this modified attempt. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 5230dc59d..3281ca606 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -241,7 +241,7 @@ def dpp_handover_client(llc, alt=False): summary("NFC Handover Request message for DPP: " + str(message)) global peer_crn - if peer_crn is not None: + if peer_crn is not None and not alt: summary("NFC handover request from peer was already received - do not send own") return client = nfc.handover.HandoverClient(llc) @@ -258,7 +258,7 @@ def dpp_handover_client(llc, alt=False): client.close() return - if peer_crn is not None: + if peer_crn is not None and not alt: summary("NFC handover request from peer was already received - do not send own") client.close() return @@ -507,18 +507,17 @@ class HandoverServer(nfc.handover.HandoverServer): sel = [hs, carrier] break + global hs_sent summary("Sending handover select: " + str(sel)) if found: summary("Handover completed successfully") self.success = True + hs_sent = True else: summary("Try to initiate with alternative parameters") self.try_own = True - if not init_on_touch and no_input: - # Need to start client thread now - threading.Thread(target=llcp_worker, args=(self.llc,)).start() - global hs_sent - hs_sent = True + hs_sent = False + threading.Thread(target=llcp_worker, args=(self.llc, True)).start() return sel def clear_raw_mode(): @@ -651,12 +650,18 @@ def rdwr_connected(tag): return not no_wait -def llcp_worker(llc): +def llcp_worker(llc, try_alt): + print("Start of llcp_worker()") + if try_alt: + summary("Starting handover client (try_alt)") + dpp_handover_client(llc, alt=True) + summary("Exiting llcp_worker thread (try_alt)") + return global init_on_touch if init_on_touch: - summary("Starting handover client") + summary("Starting handover client (init_on_touch)") dpp_handover_client(llc) - summary("Exiting llcp_worker thread (init_in_touch)") + summary("Exiting llcp_worker thread (init_on_touch)") return global no_input @@ -716,7 +721,7 @@ def llcp_connected(llc): global srv srv.start() if init_on_touch or not no_input: - threading.Thread(target=llcp_worker, args=(llc,)).start() + threading.Thread(target=llcp_worker, args=(llc, False)).start() return True def llcp_release(llc): From 0ce6883f64b5085368c5eea0711cb89fea7efedd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 25 Jun 2020 01:38:50 +0300 Subject: [PATCH 0730/1105] tests: Fix SAE-PK password module tests Couple of the test values were not actually valid, so remove them. Signed-off-by: Jouni Malinen --- src/common/common_module_tests.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c index b6e714f68..2af179b42 100644 --- a/src/common/common_module_tests.c +++ b/src/common/common_module_tests.c @@ -557,12 +557,9 @@ static int sae_pk_tests(void) const u8 *val; } valid[] = { { "a2bc-de3f-ghi4", (u8 *) "\x06\x82\x21\x93\x65\x31\xd1\xc0" }, - { "ci2f-m6e2", (u8 *) "\x12\x34\x56\x78\x9a" }, { "aaaa-aaaa-aaaa-a", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, { "aaaa-aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00" }, - { "aaaa-aaaa-aa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00" }, - { "aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00" }, { "7777-7777-777", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe" }, { "7777-7777-7777", (u8 *) "\xff\xff\xff\xff\xff\xff\xff\xf0" }, { "7777-7777-7777-7", From 5d8c5f344e1c3be8a49d782b6d59e0b3a6742d97 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 25 Jun 2020 01:18:30 +0300 Subject: [PATCH 0731/1105] SAE-PK: Fix password validation check for Sec The 0..3 value decoded from the password was not incremented to the actual 2..5 range for Sec. This resulted in not properly detecting the minimum password length. Signed-off-by: Jouni Malinen --- src/common/sae_pk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index b294312ef..b1c35d100 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -38,7 +38,7 @@ bool sae_pk_valid_password(const char *pw) idx = os_strchr(sae_pk_base32_table, pw[0]); if (!idx) return false; - sec = ((u8) ((idx - sae_pk_base32_table) & 0x1f)) >> 3; + sec = (((u8) ((idx - sae_pk_base32_table) & 0x1f)) >> 3) + 2; if ((sec == 2 && pw_len < 14) || (sec == 3 && pw_len < 13) || (sec == 4 && pw_len < 11) || From 7700146de03e6861c6c014e0342c8cd075806f14 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 25 Jun 2020 01:19:51 +0300 Subject: [PATCH 0732/1105] tests: SAE-PK password minimum length Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 311acc3c7..03a21c042 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -374,3 +374,30 @@ def test_sae_pk_invalid_fingerprint(dev, apdev): SAE_PK_19_PK)] hapd = hostapd.add_ap(apdev[0], params) check_sae_pk_sta_connect_failure(dev[0]) + +def test_sae_pk_password_min_len(dev, apdev): + """SAE-PK password minimum length""" + check_sae_pk_capab(dev[0]) + ssid = SAE_PK_SSID + pk = SAE_PK_19_PK + tests = [("dwxm-zv66-p5u", "431ff8322f93b9dc50ded9f3d14ace22", False), + ("dwxm-zv66-p5ue", "431ff8322f93b9dc50ded9f3d14ace22", True), + ("iian-qey6-pu", "128e51ddb5e2e24388f9ed14b687e2eb", False), + ("iian-qey6-pu5", "128e51ddb5e2e24388f9ed14b687e2eb", True), + ("ssko-2lmu", "a5e38c7251ea310cc348fbcdadfa8bcb", False), + ("ssko-2lmu-7", "a5e38c7251ea310cc348fbcdadfa8bcb", True), + ("3qqu-f4x", "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("3qqu-f4xq", "d2e5fa27d1be8897f987f2d480d2af6b", True)] + for pw, m, success in tests: + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE' + params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + try: + hapd = hostapd.add_ap(apdev[0], params, no_enable=True) + if not success: + raise Exception("Unexpected success with password %s" % pw) + except Exception as e: + if str(e).startswith("Unexpected success with password"): + raise + if success: + raise Exception("Unexpected failure with password %s" % pw) From 2f4c6a5bf319148b93c2f5c909d413e3dcaa96e1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 25 Jun 2020 01:20:06 +0300 Subject: [PATCH 0733/1105] tests: sigma_dut SAE-PK AP with additional SAE_PK_KeyPair values Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 0c230b72e..3edeafcba 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4906,7 +4906,13 @@ def test_sigma_dut_ap_sae_pk(dev, apdev, params): ("SAEPK-5.7.2.4", "geoh-2rvn-ivwu", "saepk8_sig.pem", "61a84a86ffb1b9e23f576a0275ddcc78", True), ("SAEPK-5.7.3", "hbhh-r4um-jzjs", "saepk9.pem", - "af9b55bce52040892634bb3e41d557ee", False)] + "af9b55bce52040892634bb3e41d557ee", False), + ("SAE-PK-5.7.1.13", "dop4-pi5w-72g2", "saepk13.pem", + "c269116268faaa6728fccd27fa5e9003", False), + ("SAE-PK test", "ssko-2lmu-7", "saepk5.7.1Run4thru12.pem", + "a5e38c7251ea310cc348fbcdadfa8bcb", False), + ("SAE-PK test", "3qqu-f4xq", "saepk5.7.1Run4thru12.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False)] with HWSimRadio() as (radio, iface): sigma = start_sigma_dut(iface, hostapd_logdir=logdir) From d93df9989f5d31b0752165b258a7dbc3f63242c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Jun 2020 20:37:30 +0300 Subject: [PATCH 0734/1105] DPP2: Debug print reason for rejecting reconfiguration This makes it easier to understand why Reconfig Authentication Request gets ignored. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 801e372bb..6e1ff7aa5 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2101,17 +2101,29 @@ wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from " MACSTR, MAC2STR(src)); - if (!wpa_s->dpp || wpa_s->dpp_auth || - !wpa_s->dpp_reconfig_announcement || !wpa_s->dpp_reconfig_ssid) + if (!wpa_s->dpp) return; + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Not ready for reconfiguration - pending authentication exchange in progress"); + return; + } + if (!wpa_s->dpp_reconfig_announcement || !wpa_s->dpp_reconfig_ssid) { + wpa_printf(MSG_DEBUG, + "DPP: Not ready for reconfiguration - not requested"); + return; + } for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { if (ssid == wpa_s->dpp_reconfig_ssid && ssid->id == wpa_s->dpp_reconfig_ssid_id) break; } if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey || - !ssid->dpp_csign) + !ssid->dpp_csign) { + wpa_printf(MSG_DEBUG, + "DPP: Not ready for reconfiguration - no matching network profile with Connector found"); return; + } auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector, ssid->dpp_netaccesskey, From a7ae422961dd73fb4963acb6b6ddfe4186365def Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Jun 2020 20:40:40 +0300 Subject: [PATCH 0735/1105] DPP2: Do not allow reconfiguration to be started with pending auth The pending authentication exchange will make us ignore Reconfig Authentication Request, so do not allow reconfiguration to be started in that state. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 6e1ff7aa5..8fd0d063b 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3620,6 +3620,12 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) !ssid->dpp_csign) return -1; + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Not ready to start reconfiguration - pending authentication exchange in progress"); + return -1; + } + wpas_dpp_chirp_stop(wpa_s); wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; wpa_s->dpp_qr_mutual = 0; From 8632dea4ae3575f838d8119a02b29b90947164d3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Jun 2020 20:50:23 +0300 Subject: [PATCH 0736/1105] DPP2: Make sure dpp_auth gets cleared with external config processing wpa_s->dpp_auth did not get cleaner if dpp_config_processing=1 is used. Clear this after having received TX status for Configuration Result to avoid leaving behind the completed provisioning instance. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 8fd0d063b..edbe46f27 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1625,6 +1625,8 @@ fail: wpabuf_free(msg); /* This exchange will be terminated in the TX status handler */ + if (wpa_s->conf->dpp_config_processing < 2) + auth->remove_on_tx_status = 1; return; } fail2: From 58b384f467224a1d43f3f947fd53e08b019cbcd3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Jun 2020 21:06:12 +0300 Subject: [PATCH 0737/1105] tests: sigma_dut DPP reconfiguration Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 112 ++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 3edeafcba..ec85bcd1b 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3291,6 +3291,118 @@ def test_sigma_dut_dpp_nfc_static_write_enrollee(dev, apdev): dev[0].set("dpp_config_processing", "0") stop_sigma_dut(sigma) +def test_sigma_dut_dpp_reconfig_enrollee(dev, apdev): + """sigma_dut DPP reconfiguration (Enrollee)""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + hapd = start_dpp_ap(apdev[0]) + sigma = start_sigma_dut(dev[0].ifname) + try: + cmd = "DPP_CONFIGURATOR_ADD key=" + csign + res = dev[1].request(cmd) + if "FAIL" in res: + raise Exception("Failed to add configurator") + conf_id = int(res) + + id0 = dev[1].dpp_bootstrap_gen(chan="81/6", mac=True) + uri0 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + + dev[1].set("dpp_configurator_params", + " conf=sta-dpp ssid=%s configurator=%d" % (to_hex("DPPNET01"), conf_id)) + cmd = "DPP_LISTEN 2437 role=configurator" + if "OK" not in dev[1].request(cmd): + raise Exception("Failed to start listen operation") + + ifname = dev[0].ifname + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,DPP" % ifname) + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,QR" % to_hex(uri0)) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPAuthDirection,Single,DPPProvisioningRole,Enrollee,DPPBS,QR,DPPTimeout,6,DPPWaitForConnect,Yes", timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK,NetworkIntroResult,OK,NetworkConnectResult,OK" not in res: + raise Exception("Unexpected result: " + res) + + hapd.disable() + dev[0].dump_monitor() + + ssid = "reconfig" + passphrase = "secret passphrase" + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + hapd = hostapd.add_ap(apdev[0], params) + + dev[1].set("dpp_configurator_params", + "conf=sta-psk ssid=%s pass=%s conn_status=1" % (binascii.hexlify(ssid.encode()).decode(), binascii.hexlify(passphrase.encode()).decode())) + cmd = "DPP_LISTEN 2437 role=configurator" + if "OK" not in dev[1].request(cmd): + raise Exception("Failed to start listen operation") + dev[1].dump_monitor() + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,DPPReconfigure,DPPTimeout,6,DPPWaitForConnect,Yes", timeout=10) + if "status,COMPLETE,ReconfigAuthResult,OK,ConfResult,OK,NetworkConnectResult,OK" not in res: + raise Exception("Unexpected reconfiguration result: " + res) + + ev = dev[1].wait_event(["DPP-CONF-SENT"], timeout=15) + if ev is None: + raise Exception("DPP Config Response (reconfig) not transmitted") + + dev[0].wait_connected() + finally: + dev[0].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + +def test_sigma_dut_dpp_reconfig_configurator(dev, apdev): + """sigma_dut DPP reconfiguration (Configurator)""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + sigma = start_sigma_dut(dev[0].ifname) + try: + dev[1].set("dpp_config_processing", "1") + id0 = dev[1].dpp_bootstrap_gen(chan="81/6", mac=True) + uri0 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + cmd = "DPP_LISTEN 2437" + if "OK" not in dev[1].request(cmd): + raise Exception("Failed to start listen operation") + + ifname = dev[0].ifname + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,DPP" % ifname) + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,QR" % to_hex(uri0)) + if "status,COMPLETE" not in res: + raise Exception("dev_exec_action did not succeed: " + res) + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPAuthDirection,Single,DPPProvisioningRole,Configurator,DPPConfEnrolleeRole,STA,DPPSigningKeyECC,P-256,DPPConfIndex,1,DPPBS,QR,DPPTimeout,6", timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: + raise Exception("Unexpected result: " + res) + + dev[0].dump_monitor() + + ev = dev[1].wait_event(["DPP-NETWORK-ID"], timeout=1) + if ev is None: + raise Exception("No network profile created") + id = int(ev.split(' ')[1]) + + ev = dev[1].wait_event(["DPP-TX-STATUS"], timeout=5) + if ev is None: + raise Exception("Configuration Result not sent") + dev[1].dump_monitor() + cmd = "DPP_RECONFIG %d" % id + if "OK" not in dev[1].request(cmd): + raise Exception("Failed to start reconfiguration") + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,DPPReconfigure,DPPProvisioningRole,Configurator,DPPConfEnrolleeRole,STA,DPPSigningKeyECC,P-256,DPPConfIndex,2,DPPListenChannel,6,DPPTimeout,6", timeout=10) + if "status,COMPLETE,ReconfigAuthResult,OK,ConfResult,OK" not in res: + raise Exception("Unexpected reconfiguration result: " + res) + + ev = dev[1].wait_event(["DPP-CONF-RECEIVED"], timeout=15) + if ev is None: + raise Exception("DPP Config Response (reconfig) not received") + finally: + dev[0].set("dpp_config_processing", "0") + dev[1].set("dpp_config_processing", "0") + stop_sigma_dut(sigma) + @reset_ignore_old_scan_res def test_sigma_dut_preconfigured_profile(dev, apdev): """sigma_dut controlled connection using preconfigured profile""" From 4df892c781b8d02a10fa78c15d639e7601e2a8dc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 26 Jun 2020 22:50:13 +0300 Subject: [PATCH 0738/1105] tests: sigma_dut client privacy Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index ec85bcd1b..9f3b23e19 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -23,6 +23,7 @@ from utils import * from hwsim import HWSimRadio import hwsim_utils from wlantest import Wlantest +from tshark import run_tshark from test_dpp import check_dpp_capab, update_hapd_config, wait_auth_success from test_suite_b import check_suite_b_192_capa, suite_b_as_params, suite_b_192_rsa_ap_params from test_ap_eap import check_eap_capa, int_eap_server_params, check_domain_match, check_domain_suffix_match @@ -5059,3 +5060,43 @@ def test_sigma_dut_ap_sae_pk_misbehavior(dev, apdev, params): True, sig="saepk8_sig.pem") finally: stop_sigma_dut(sigma) + +def test_sigma_dut_client_privacy(dev, apdev, params): + """sigma_dut client privacy""" + logdir = params['logdir'] + + ssid = "test" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + hapd = hostapd.add_ap(apdev[0], params) + + ifname = dev[0].ifname + addr = dev[0].own_addr() + sigma = start_sigma_dut(ifname) + try: + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ClientPrivacy,1" % ifname) + cmd = "sta_scan,Interface,%s,ChnlFreq,2412,WaitCompletion,1" % dev[0].ifname + sigma_dut_cmd_check(cmd, timeout=10) + time.sleep(2) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_psk,interface,%s,ssid,%s,passphrase,%s,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, ssid, "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, ssid), + timeout=10) + sigma_dut_wait_connected(ifname) + sigma_dut_cmd_check("sta_get_ip_config,interface," + ifname) + sigma_dut_cmd_check("sta_disconnect,interface," + ifname) + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + dev[1].set("mac_addr", "0", allow_fail=True) + dev[1].set("rand_addr_lifetime", "60", allow_fail=True) + dev[1].set("preassoc_mac_addr", "0", allow_fail=True) + dev[1].set("gas_rand_mac_addr", "0", allow_fail=True) + dev[1].set("gas_rand_addr_lifetime", "60", allow_fail=True) + + out = run_tshark(os.path.join(logdir, "hwsim0.pcapng"), + "wlan.addr == " + addr, + display=["wlan.ta"]) + res = out.splitlines() + if len(res) > 0: + raise Exception("Permanent address used unexpectedly") From 885097125ccbd9b1e18479c90e6b772ecab014eb Mon Sep 17 00:00:00 2001 From: Yu Wang Date: Wed, 8 Jul 2020 02:18:47 +0800 Subject: [PATCH 0739/1105] mesh: Fix peer link counting when removing a mesh peer When removing a mesh peer with control interface commands (ACCEPT_ACL DEL_MAC/DENY_ACL ADD_MAC/MESH_PEER_REMOVE) the plink count was not decreased from its last connection. This resulted in peer link count leakage and wpa_supplicant rejecting the connections after reaching max_peer_links (default: 99). Fix this by decreasing the plink count when removing a mesh peer which is in PLINK_ESTAB state. Signed-off-by: Yu Wang --- wpa_supplicant/mesh_mpm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index ea62abf5b..3abbe09d0 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -533,6 +533,8 @@ static int mesh_mpm_plink_close(struct hostapd_data *hapd, struct sta_info *sta, int reason = WLAN_REASON_MESH_PEERING_CANCELLED; if (sta) { + if (sta->plink_state == PLINK_ESTAB) + hapd->num_plinks--; wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING); mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason); wpa_printf(MSG_DEBUG, "MPM closing plink sta=" MACSTR, From a57f98754e255e928f5da6b641ca643a75bc2c4a Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Chitrapu Date: Tue, 16 Jun 2020 00:57:58 -0700 Subject: [PATCH 0740/1105] Fix enabling 40/80 MHz bandwidth support in the 6 GHz band 40/80 MHz bandwidth setting was being rejected due to incorrect sanity check on the channel index. Fix that for the bandwidths larger than 20 MHz. Fixes: d7c2c5c98c4f ("AP: Add initial support for 6 GHz band") Signed-off-by: Pradeep Kumar Chitrapu --- src/common/hw_features_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c index f6c67a375..1d9387f70 100644 --- a/src/common/hw_features_common.c +++ b/src/common/hw_features_common.c @@ -415,7 +415,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, return -1; } - if (center_idx_to_bw_6ghz(channel) != 0) { + if (center_idx_to_bw_6ghz(channel) < 0) { wpa_printf(MSG_ERROR, "Invalid control channel for 6 GHz band"); return -1; From cc6153a8a4555407562a4200f298554e6a27eea1 Mon Sep 17 00:00:00 2001 From: Seevalamuthu Mariappan Date: Thu, 11 Jun 2020 17:07:35 +0530 Subject: [PATCH 0741/1105] nl80211: Fix sending proper VLAN ID attr value when using VLAN offload The NL80211_ATTR_VLAN_ID attribute expects non-zero values, but vlan_id with value 0 has been set in VLAN offload case. Due to this, station connection failure is observed if the driver advertises VLAN_OFFLOAD support: nl80211: NL80211_ATTR_STA_VLAN (addr=8c:fd:f0:22:19:15 ifname=wlan0 vlan_id=0) failed: -34 (Result not representable) wlan0: STA 8c:fd:f0:22:19:15 IEEE 802.11: could not bind the STA entry to vlan_id=0 Fix this by setting only non-zero values. Fixes: 0f903f37dca1 ("nl80211: VLAN offload support") Signed-off-by: Seevalamuthu Mariappan --- src/drivers/driver_nl80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index ea16d8daf..d70b56ba8 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -6975,7 +6975,7 @@ static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr, MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id); if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || - ((drv->capa.flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD) && + (vlan_id && (drv->capa.flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD) && nla_put_u16(msg, NL80211_ATTR_VLAN_ID, vlan_id)) || nla_put_u32(msg, NL80211_ATTR_STA_VLAN, if_nametoindex(ifname))) { nlmsg_free(msg); From 8f396ad685f80059f08bac99bd8ee2df113716c3 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Thu, 18 Jun 2020 13:47:14 +0530 Subject: [PATCH 0742/1105] Enhance the qca_set_band enum values to be used as a bitmap Also introduce a new attribute QCA_WLAN_VENDOR_ATTR_SETBAND_MASK to carry this new bitmask enum. This attribute shall consider the bitmask combinations to define the respective band combinations and substitutes QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE. The old attribute use remains same as before. In addition, document the previously undocumented, but defined, QCA_NL80211_VENDOR_SUBCMD_SETBAND. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 73b0aba31..28fa741cb 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -174,6 +174,22 @@ enum qca_radiotap_vendor_ids { * to notify the connected station's status. The attributes for this * command are defined in enum qca_wlan_vendor_attr_link_properties. * + * @QCA_NL80211_VENDOR_SUBCMD_SETBAND: Command to configure the enabled band(s) + * to the driver. This command sets the band(s) through either the + * attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE or + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK (or both). + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE refers enum qca_set_band as unsigned + * integer values and QCA_WLAN_VENDOR_ATTR_SETBAND_MASK refers it as 32 + * bit unsigned bitmask values. The allowed values for + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE are limited to QCA_SETBAND_AUTO, + * QCA_SETBAND_5G, and QCA_SETBAND_2G. Other values/bitmasks are valid for + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. The attribute + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE is deprecated and the recommendation + * is to use the QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. If the both attributes + * are included for backwards compatibility, the configurations through + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK will take the precedence with drivers + * that support both attributes. + * * @QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY: This command is used to configure * DFS policy and channel hint for ACS operation. This command uses the * attributes defined in enum qca_wlan_vendor_attr_acs_config and @@ -862,7 +878,11 @@ enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11, - /* Unsigned 32-bit value from enum qca_set_band. */ + /* Unsigned 32-bit value from enum qca_set_band. The allowed values for + * this attribute are limited to QCA_SETBAND_AUTO, QCA_SETBAND_5G, and + * QCA_SETBAND_2G. This attribute is deprecated. Recommendation is to + * use QCA_WLAN_VENDOR_ATTR_SETBAND_MASK instead. + */ QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12, /* Dummy (NOP) attribute for 64 bit padding */ QCA_WLAN_VENDOR_ATTR_PAD = 13, @@ -1025,6 +1045,15 @@ enum qca_wlan_vendor_attr { */ QCA_WLAN_VENDOR_ATTR_FW_STATE = 42, + /* Unsigned 32-bitmask value from enum qca_set_band. Substitutes the + * attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE for which only a subset + * of single values from enum qca_set_band are valid. This attribute + * uses bitmask combinations to define the respective allowed band + * combinations and this attributes takes precedence over + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE if both attributes are included. + */ + QCA_WLAN_VENDOR_ATTR_SETBAND_MASK = 43, + /* keep last */ QCA_WLAN_VENDOR_ATTR_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1, @@ -1572,9 +1601,10 @@ enum qca_iface_type { }; enum qca_set_band { - QCA_SETBAND_AUTO, - QCA_SETBAND_5G, - QCA_SETBAND_2G, + QCA_SETBAND_AUTO = 0, + QCA_SETBAND_5G = BIT(0), + QCA_SETBAND_2G = BIT(1), + QCA_SETBAND_6G = BIT(2), }; /** From 29e47c41652d0ba3ec1fb8b570887a87dab715c0 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Thu, 25 Jun 2020 16:19:27 +0530 Subject: [PATCH 0743/1105] Vendor command to configure TWT This commit defines a new vendor interface QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT to configure TWT. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 65 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 28fa741cb..af1a3ca89 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -668,6 +668,9 @@ enum qca_radiotap_vendor_ids { * This command can only be used in STA mode and the STA must be * associated with an AP when the command is issued. Uses attributes * defined in enum qca_wlan_vendor_attr_config_tspec. + * + * @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT: Vendor subcommand to configure TWT. + * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -848,6 +851,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO = 188, QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON = 189, QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC = 190, + QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT = 191, }; enum qca_wlan_vendor_attr { @@ -7376,6 +7380,61 @@ enum qca_wlan_vendor_attr_wifi_test_config { QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST - 1, }; +/** + * enum qca_wlan_twt_operation - Operation of the config TWT request + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION. + * + * @QCA_WLAN_TWT_SET: Setup a TWT session. Required parameters are configured + * through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. + * + * @QCA_WLAN_TWT_GET: Get the configured TWT parameters. Required parameters are + * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. + * + * @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Does not carry any + * parameters. Valid only after the TWT session is setup. + * + * @QCA_WLAN_TWT_SUSPEND: Terminate the TWT session. Does not carry any + * parameters. Valid only after the TWT session is setup. + * + * @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are + * configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_resume. + */ +enum qca_wlan_twt_operation { + QCA_WLAN_TWT_SET = 0, + QCA_WLAN_TWT_GET = 1, + QCA_WLAN_TWT_TERMINATE = 2, + QCA_WLAN_TWT_SUSPEND = 3, + QCA_WLAN_TWT_RESUME = 4, +}; + +/** + * enum qca_wlan_vendor_attr_config_twt: Defines attributes used by + * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION: u8 attribute. Specify the TWT + * operation of this request. Possible values are defined in enum + * qca_wlan_twt_operation. The parameters for the respective operation is + * specified through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the + * parameters configured for TWT. These parameters are represented by + * enum qca_wlan_vendor_attr_twt_setup or enum qca_wlan_vendor_attr_twt_resume + * based on the operation. + */ +enum qca_wlan_vendor_attr_config_twt { + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION = 1, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX = + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST - 1, +}; + /** * enum qca_wlan_vendor_attr_bss_filter - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. @@ -7527,7 +7586,8 @@ enum qca_wlan_vendor_attr_nan_params { * enum qca_wlan_vendor_attr_twt_setup: Represents attributes for * TWT (Target Wake Time) setup request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and - * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by + * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST: Flag attribute. * Disable (flag attribute not present) - Individual TWT @@ -7606,7 +7666,8 @@ enum qca_wlan_vendor_attr_twt_setup { * enum qca_wlan_vendor_attr_twt_resume: Represents attributes for * TWT (Target Wake Time) resume request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME and - * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by + * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT: Optional (u8) * This attribute is used as the SP offset which is the offset from From d91fb3ce32620dc6a1746e699d47db524199831b Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Fri, 26 Jun 2020 17:45:52 +0530 Subject: [PATCH 0744/1105] Add a vendor command to fetch the currently enabled band(s) Introduces a vendor command to get the currently enabled band(s) through QCA_NL80211_VENDOR_SUBCMD_GETBAND. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index af1a3ca89..3304ea80c 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -671,6 +671,10 @@ enum qca_radiotap_vendor_ids { * * @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT: Vendor subcommand to configure TWT. * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt. + * + * @QCA_NL80211_VENDOR_SUBCMD_GETBAND: Command to get the enabled band(s) from + * the driver. The band configurations obtained are referred through + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -852,6 +856,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON = 189, QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC = 190, QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT = 191, + QCA_NL80211_VENDOR_SUBCMD_GETBAND = 192, }; enum qca_wlan_vendor_attr { From ebd5e764f99b394d73ba6be8f28ade312c2ea67f Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Fri, 26 Jun 2020 17:47:13 +0530 Subject: [PATCH 0745/1105] Vendor attribute to configure QoS/AC upgrade for UDP frames Introduce a new attribute QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE to configure access category override for UDP frames. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 3304ea80c..448d52682 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2260,6 +2260,18 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT = 71, + /* 8-bit unsigned value. This attribute takes the QoS/access category + * value represented by the enum qca_wlan_ac_type and expects the driver + * to upgrade the UDP frames to this access category. The value of + * QCA_WLAN_AC_ALL is invalid for this attribute. This will override the + * DSCP value configured in the frame with the intention to only upgrade + * the access category. That said, it is not intended to downgrade the + * access category for the frames. + * Set the value to 0 (corresponding to BE) if the QoS upgrade needs + * to be disabled. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE = 72, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = From 288c0ffaaa27512efc7124a695a2b932dd815faf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Jul 2020 01:30:30 +0300 Subject: [PATCH 0746/1105] dpp-nfc: Do not hardcode netrole for NFC Tag writing cases Allow netrole to be specified for NFC Tag writing cases. Previously, this was hardcoded to use netrole=configurator when starting the listen operation. Now the netrole parameter is not included by default, but any netrole value can be specified with the new --netrole command line argument. In addition, fix the listening frequency for the case where a channel is picked. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 3281ca606..a9465411e 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -38,6 +38,7 @@ my_crn_ready = False my_crn = None peer_crn = None hs_sent = False +netrole = None mutex = threading.Lock() def summary(txt): @@ -180,6 +181,7 @@ def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, return int(res) def wpas_get_nfc_uri(start_listen=True, pick_channel=False, chan_override=None): + listen_freq = 2412 wpas = wpas_connect() if wpas is None: return None @@ -195,15 +197,23 @@ def wpas_get_nfc_uri(start_listen=True, pick_channel=False, chan_override=None): if freq >= 2412 and freq <= 2462: chan = "81/%d" % ((freq - 2407) / 5) summary("Use current AP operating channel (%d MHz) as the URI channel list (%s)" % (freq, chan)) + listen_freq = freq if chan is None and pick_channel: chan = "81/6" summary("Use channel 2437 MHz since no other preference provided") + listen_freq = 2437 own_id = dpp_bootstrap_gen(wpas, type="nfc-uri", chan=chan, mac=True) res = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in res: return None if start_listen: - wpas.request("DPP_LISTEN 2412 netrole=configurator") + cmd = "DPP_LISTEN %d" % listen_freq + global netrole + if netrole: + cmd += " netrole=" + netrole + res = wpas.request(cmd) + if "OK" not in res: + raise Exception("Failed to start listen operation (%s)" % cmd) return res def wpas_report_handover_req(uri): @@ -770,6 +780,7 @@ def main(): parser.add_argument('--device', default='usb', help='NFC device to open') parser.add_argument('--chan', default=None, help='channel list') parser.add_argument('--altchan', default=None, help='alternative channel list') + parser.add_argument('--netrole', default=None, help='netrole for Enrollee') parser.add_argument('command', choices=['write-nfc-uri', 'write-nfc-hs'], nargs='?') @@ -782,9 +793,10 @@ def main(): global no_wait no_wait = args.no_wait - global chanlist, altchanlist + global chanlist, altchanlist, netrole chanlist = args.chan altchanlist = args.altchan + netrole = args.netrole logging.basicConfig(level=args.loglevel) From 1e4a42c7453ac86cb6f9f011c29b1e761bf03ed2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Jul 2020 11:27:27 +0300 Subject: [PATCH 0747/1105] dpp-nfc: Detect a non-NDEF tag when trying to write Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index a9465411e..8bf219a06 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -584,6 +584,9 @@ def dpp_tag_read(tag): def rdwr_connected_write_tag(tag): summary("Tag found - writing - " + str(tag)) + if not tag.ndef: + summary("Not a formatted NDEF tag") + return if not tag.ndef.is_writeable: summary("Not a writable tag") return From 09c22bb782cf3cfc754b48aea896651d9849b55e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Jul 2020 11:32:21 +0300 Subject: [PATCH 0748/1105] dpp-nfc: Fix regression in NFC Tag writing The change to checking DPP_LISTEN return value ended up overwriting the actual URI information from wpas_get_nfc_uri(). Fixes: 288c0ffaaa27 ("dpp-nfc: Do not hardcode netrole for NFC Tag writing cases") Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 8bf219a06..c5073df5c 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -211,8 +211,8 @@ def wpas_get_nfc_uri(start_listen=True, pick_channel=False, chan_override=None): global netrole if netrole: cmd += " netrole=" + netrole - res = wpas.request(cmd) - if "OK" not in res: + res2 = wpas.request(cmd) + if "OK" not in res2: raise Exception("Failed to start listen operation (%s)" % cmd) return res From 7e2edfbc1ad992087f8b6e547b4d2d65410337a7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Jul 2020 12:10:26 +0300 Subject: [PATCH 0749/1105] dpp-nfc: Add color and details for interactive operations Make the debug output easier to read when performing interactive NFC operations on a device that has a terminal showing the log. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 83 ++++++++++++++++++------------ 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index c5073df5c..c0f67f7d4 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -41,9 +41,19 @@ hs_sent = False netrole = None mutex = threading.Lock() -def summary(txt): +C_NORMAL = '\033[0m' +C_RED = '\033[91m' +C_GREEN = '\033[92m' +C_BLUE = '\033[94m' +C_MAGENTA = '\033[95m' +C_CYAN = '\033[96m' + +def summary(txt, color=None): with mutex: - print(txt) + if color: + print(color + txt + C_NORMAL) + else: + print(txt) if summary_file: with open(summary_file, 'a') as f: f.write(txt + "\n") @@ -85,7 +95,7 @@ def dpp_nfc_uri_process(uri): return False peer_id = wpas.request("DPP_NFC_URI " + uri) if "FAIL" in peer_id: - summary("Could not parse DPP URI from NFC URI record") + summary("Could not parse DPP URI from NFC URI record", color=C_RED) return False peer_id = int(peer_id) summary("peer_id=%d for URI from NFC Tag: %s" % (peer_id, uri)) @@ -100,7 +110,7 @@ def dpp_nfc_uri_process(uri): summary("Initiate DPP authentication: " + cmd) res = wpas.request(cmd) if "OK" not in res: - summary("Failed to initiate DPP Authentication") + summary("Failed to initiate DPP Authentication", color=C_RED) return False summary("DPP Authentication initiated") return True @@ -111,20 +121,20 @@ def dpp_hs_tag_read(record): return False summary(record) if len(record.data) < 5: - summary("Too short DPP HS") + summary("Too short DPP HS", color=C_RED) return False if record.data[0] != 0: - summary("Unexpected URI Identifier Code") + summary("Unexpected URI Identifier Code", color=C_RED) return False uribuf = record.data[1:] try: uri = uribuf.decode() except: - summary("Invalid URI payload") + summary("Invalid URI payload", color=C_RED) return False summary("URI: " + uri) if not uri.startswith("DPP:"): - summary("Not a DPP URI") + summary("Not a DPP URI", color=C_RED) return False return dpp_nfc_uri_process(uri) @@ -239,7 +249,8 @@ def dpp_handover_client(llc, alt=False): chan_override = altchanlist uri = wpas_get_nfc_uri(start_listen=False, chan_override=chan_override) if uri is None: - summary("Cannot start handover client - no bootstrap URI available") + summary("Cannot start handover client - no bootstrap URI available", + color=C_RED) return uri = ndef.UriRecord(uri) summary("NFC URI record for DPP: " + str(uri)) @@ -280,7 +291,7 @@ def dpp_handover_client(llc, alt=False): if not client.send_records(message): my_crn_ready = False - summary("Failed to send handover request") + summary("Failed to send handover request", color=C_RED) client.close() return @@ -294,13 +305,13 @@ def dpp_handover_client(llc, alt=False): if hs_sent: summary("Client receive failed as expected since I'm the handover server: %s" % str(e)) else: - summary("Client receive failed: %s" % str(e)) + summary("Client receive failed: %s" % str(e), color=C_RED) message = None if message is None: if hs_sent: summary("No response received as expected since I'm the handover server") else: - summary("No response received") + summary("No response received", color=C_RED) client.close() return summary("Received message: " + str(message)) @@ -320,7 +331,7 @@ def dpp_handover_client(llc, alt=False): summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": if len(carrier.data) == 0 or carrier.data[0] != 0: - summary("URI Identifier Code 'None' not seen") + summary("URI Identifier Code 'None' not seen", color=C_RED) continue summary("DPP carrier type match - send to wpa_supplicant") dpp_found = True @@ -328,7 +339,7 @@ def dpp_handover_client(llc, alt=False): summary("DPP URI: " + uri) res = wpas_report_handover_sel(uri) if res is None or "FAIL" in res: - summary("DPP handover report rejected") + summary("DPP handover report rejected", color=C_RED) break success_report("DPP handover reported successfully (initiator)") @@ -348,7 +359,7 @@ def dpp_handover_client(llc, alt=False): # TODO: Single Configurator instance res = wpas.request("DPP_CONFIGURATOR_ADD") if "FAIL" in res: - summary("Failed to initiate Configurator") + summary("Failed to initiate Configurator", color=C_RED) break conf_id = int(res) extra = " conf=sta-dpp configurator=%d" % conf_id @@ -358,7 +369,7 @@ def dpp_handover_client(llc, alt=False): cmd += extra res = wpas.request(cmd) if "FAIL" in res: - summary("Failed to initiate DPP authentication") + summary("Failed to initiate DPP authentication", color=C_RED) break if not dpp_found: @@ -450,7 +461,7 @@ class HandoverServer(nfc.handover.HandoverServer): if carrier.type == "application/vnd.wfa.dpp": summary("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: - summary("URI Identifier Code 'None' not seen") + summary("URI Identifier Code 'None' not seen", color=C_RED) continue uri = carrier.data[1:].decode("utf-8") summary("Received DPP URI: " + uri) @@ -460,7 +471,8 @@ class HandoverServer(nfc.handover.HandoverServer): res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: - summary("DPP handover request processing failed") + summary("DPP handover request processing failed", + color=C_RED) global altchanlist if altchanlist: data = wpas_get_nfc_uri(start_listen=False, @@ -508,7 +520,7 @@ class HandoverServer(nfc.handover.HandoverServer): summary(cmd) res = wpas.request(cmd) if "OK" not in res: - summary("Failed to start DPP listen") + summary("Failed to start DPP listen", color=C_RED) break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) @@ -585,18 +597,22 @@ def dpp_tag_read(tag): def rdwr_connected_write_tag(tag): summary("Tag found - writing - " + str(tag)) if not tag.ndef: - summary("Not a formatted NDEF tag") + summary("Not a formatted NDEF tag", color=C_RED) return if not tag.ndef.is_writeable: - summary("Not a writable tag") + summary("Not a writable tag", color=C_RED) return global dpp_tag_data if tag.ndef.capacity < len(dpp_tag_data): summary("Not enough room for the message") return - tag.ndef.records = dpp_tag_data + try: + tag.ndef.records = dpp_tag_data + except ValueError as e: + summary("Writing the tag failed: %s" % str(e), color=C_RED) + return success_report("Tag write succeeded") - summary("Done - remove tag") + summary("Tag writing completed - remove tag", color=C_GREEN) global only_one if only_one: global continue_loop @@ -608,7 +624,7 @@ def write_nfc_uri(clf, wait_remove=True): summary("Write NFC URI record") data = wpas_get_nfc_uri() if data is None: - summary("Could not get NFC URI from wpa_supplicant") + summary("Could not get NFC URI from wpa_supplicant", color=C_RED) return global dpp_sel_wait_remove @@ -617,7 +633,7 @@ def write_nfc_uri(clf, wait_remove=True): uri = ndef.UriRecord(data) summary(uri) - summary("Touch an NFC tag") + summary("Touch an NFC tag to write URI record", color=C_CYAN) global dpp_tag_data dpp_tag_data = [uri] clf.connect(rdwr={'on-connect': rdwr_connected_write_tag}) @@ -626,7 +642,7 @@ def write_nfc_hs(clf, wait_remove=True): summary("Write NFC Handover Select record on a tag") data = wpas_get_nfc_uri() if data is None: - summary("Could not get NFC URI from wpa_supplicant") + summary("Could not get NFC URI from wpa_supplicant", color=C_RED) return global dpp_sel_wait_remove @@ -640,7 +656,7 @@ def write_nfc_hs(clf, wait_remove=True): summary(hs) summary(carrier) - summary("Touch an NFC tag") + summary("Touch an NFC tag to write HS record", color=C_CYAN) global dpp_tag_data dpp_tag_data = [hs, carrier] summary(dpp_tag_data) @@ -658,7 +674,7 @@ def rdwr_connected(tag): global continue_loop continue_loop = False else: - summary("Not an NDEF tag - remove tag") + summary("Not an NDEF tag - remove tag", color=C_RED) return True return not no_wait @@ -841,7 +857,7 @@ def main(): try: if not clf.open(args.device): - summary("Could not open connection with an NFC device") + summary("Could not open connection with an NFC device", color=C_RED) raise SystemExit if args.command == "write-nfc-uri": @@ -859,10 +875,13 @@ def main(): clear_raw_mode() if was_in_raw_mode: print("\r") - if args.tag_read_only: - summary("Waiting for a tag to be touched") + if args.handover_only: + summary("Waiting a peer to be touched", color=C_MAGENTA) + elif args.tag_read_only: + summary("Waiting for a tag to be touched", color=C_BLUE) else: - summary("Waiting for a tag or peer to be touched") + summary("Waiting for a tag or peer to be touched", + color=C_GREEN) wait_connection = True try: if args.tag_read_only: From 74cd38ac69cd31e9bdd120dd7df1ab5060aeebc4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Jul 2020 12:26:46 +0300 Subject: [PATCH 0750/1105] dpp-nfc: Return failure status if operation fails For now, this is done only for the case where the NFC Device is not usable and if writing a single tag fails. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index c0f67f7d4..bd0330859 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -39,6 +39,7 @@ my_crn = None peer_crn = None hs_sent = False netrole = None +operation_success = False mutex = threading.Lock() C_NORMAL = '\033[0m' @@ -613,7 +614,8 @@ def rdwr_connected_write_tag(tag): return success_report("Tag write succeeded") summary("Tag writing completed - remove tag", color=C_GREEN) - global only_one + global only_one, operation_success + operation_success = True if only_one: global continue_loop continue_loop = False @@ -858,14 +860,18 @@ def main(): try: if not clf.open(args.device): summary("Could not open connection with an NFC device", color=C_RED) - raise SystemExit + raise SystemExit(1) if args.command == "write-nfc-uri": write_nfc_uri(clf, wait_remove=not args.no_wait) + if not operation_success: + raise SystemExit(1) raise SystemExit if args.command == "write-nfc-hs": write_nfc_hs(clf, wait_remove=not args.no_wait) + if not operation_success: + raise SystemExit(1) raise SystemExit global continue_loop From 15018d4f4a88b628cdac115f3a281331c70d1193 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Jul 2020 17:57:28 +0300 Subject: [PATCH 0751/1105] DPP2: Fix auth termination after receiving Configurator backup remove_on_tx_status needs to be set in this case even if dpp_config_processing=2 is used since there will be no connection attempt when receiving a Configurator backup instead of station config object. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 5 ++++- wpa_supplicant/wpa_supplicant_i.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index edbe46f27..cc35030c9 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1485,6 +1485,7 @@ static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup"); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED); + wpa_s->dpp_conf_backup_received = true; while (key) { res = dpp_configurator_from_backup(wpa_s->dpp, key); @@ -1582,6 +1583,7 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, goto fail; } + wpa_s->dpp_conf_backup_received = false; for (i = 0; i < auth->num_conf_obj; i++) { res = wpas_dpp_handle_config_obj(wpa_s, auth, &auth->conf_obj[i]); @@ -1625,7 +1627,8 @@ fail: wpabuf_free(msg); /* This exchange will be terminated in the TX status handler */ - if (wpa_s->conf->dpp_config_processing < 2) + if (wpa_s->conf->dpp_config_processing < 2 || + wpa_s->dpp_conf_backup_received) auth->remove_on_tx_status = 1; return; } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 341d84156..d845ae2ae 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1277,6 +1277,7 @@ struct wpa_supplicant { unsigned int dpp_resp_retry_time; u8 dpp_last_ssid[SSID_MAX_LEN]; size_t dpp_last_ssid_len; + bool dpp_conf_backup_received; #ifdef CONFIG_DPP2 struct dpp_pfs *dpp_pfs; int dpp_pfs_fallback; From 268433ecd071224cdbecc4f2c3a789302b20fa3d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 23 Jul 2020 17:34:15 +0300 Subject: [PATCH 0752/1105] tests: DPP Configurator enrolling followed by use of the new Configurator Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 44 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index e28e04f85..8f530bb0a 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -303,6 +303,34 @@ def test_dpp_configurator_enrollee_brainpoolP512r1(dev, apdev): """DPP Configurator enrolling (brainpoolP512r1)""" run_dpp_configurator_enrollee(dev, apdev, conf_curve="brainpoolP512r1") +def test_dpp_configurator_enroll_conf(dev, apdev): + """DPP Configurator enrolling followed by use of the new Configurator""" + try: + dev[0].set("dpp_config_processing", "2") + run_dpp_configurator_enroll_conf(dev, apdev) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_configurator_enroll_conf(dev, apdev): + run_dpp_qr_code_auth_unicast(dev, apdev, None, netrole="configurator", + configurator=True, conf="configurator", + qr="mutual", stop_responder=False) + ev = dev[0].wait_event(["DPP-CONFIGURATOR-ID"], timeout=2) + if ev is None: + raise Exception("No Configurator instance added") + dev[1].reset() + dev[0].dump_monitor() + + ssid = "test-network" + passphrase = "test-passphrase" + dev[0].set("dpp_configurator_params", + "conf=sta-psk ssid=%s pass=%s" % (binascii.hexlify(ssid.encode()).decode(), binascii.hexlify(passphrase.encode()).decode())) + dev[0].dpp_listen(2412, role="configurator") + id0 = dev[0].dpp_bootstrap_gen(chan="81/1") + uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + dev[1].dpp_auth_init(uri=uri0, role="enrollee") + wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1]) + def test_dpp_qr_code_curve_prime256v1(dev, apdev): """DPP QR Code and curve prime256v1""" run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1") @@ -335,7 +363,7 @@ def run_dpp_qr_code_auth_unicast(dev, apdev, curve, netrole=None, key=None, require_conf_success=False, init_extra=None, require_conf_failure=False, configurator=False, conf_curve=None, - conf=None): + conf=None, qr=None, stop_responder=True): check_dpp_capab(dev[0], curve and "brainpool" in curve) check_dpp_capab(dev[1], curve and "brainpool" in curve) if configurator: @@ -343,19 +371,27 @@ def run_dpp_qr_code_auth_unicast(dev, apdev, curve, netrole=None, key=None, else: conf_id = None + if qr == "mutual": + logger.info("dev1 displays QR Code and dev0 scans it") + id1 = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True, curve=curve) + uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + id1c = dev[0].dpp_qr_code(uri1) + else: + id1 = None + logger.info("dev0 displays QR Code") id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True, curve=curve, key=key) uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) logger.info("dev1 scans QR Code and initiates DPP Authentication") - dev[0].dpp_listen(2412, netrole=netrole) + dev[0].dpp_listen(2412, netrole=netrole, qr=qr) dev[1].dpp_auth_init(uri=uri0, extra=init_extra, configurator=conf_id, - conf=conf) + conf=conf, own=id1) wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0], allow_enrollee_failure=True, allow_configurator_failure=not require_conf_success, require_configurator_failure=require_conf_failure, - stop_responder=True) + stop_responder=stop_responder) def test_dpp_qr_code_auth_mutual(dev, apdev): """DPP QR Code and authentication exchange (mutual)""" From f8c756c5b85194d8d63a397319f57301a543770c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Jul 2020 12:02:11 +0300 Subject: [PATCH 0753/1105] FT: Rename temporary blocking of nonresponsive R0KH Avoid use of the "blacklist" term here to reduce undesired connotations. Signed-off-by: Jouni Malinen --- hostapd/hostapd.conf | 2 +- src/ap/wpa_auth_ft.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 91ac96785..25b4e4927 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1968,7 +1968,7 @@ own_ip_addr=127.0.0.1 # Wildcard entry: # Upon receiving a response from R0KH, it will be added to this list, so # subsequent requests won't be broadcast. If R0KH does not reply, it will be -# blacklisted. +# temporarily blocked (see rkh_neg_timeout). #r0kh=ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff # List of R1KHs in the same Mobility Domain diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index db272d41e..9caac194e 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -1898,7 +1898,7 @@ static void wpa_ft_block_r0kh(struct wpa_authenticator *wpa_auth, return; } - wpa_hexdump(MSG_DEBUG, "FT: Blacklist R0KH-ID", + wpa_hexdump(MSG_DEBUG, "FT: Temporarily block R0KH-ID", f_r0kh_id, f_r0kh_id_len); if (r0kh) { @@ -1986,7 +1986,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, return -1; } if (is_zero_ether_addr(r0kh->addr)) { - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is blacklisted", + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is temporarily blocked", sm->r0kh_id, sm->r0kh_id_len); return -1; } From f4877083ec4b766b822d1c8ff31f1c1e336b65e3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Jul 2020 12:13:19 +0300 Subject: [PATCH 0754/1105] Rename driver op for temporarily disallowed BSSIDs Use the "tmp_disallow" name more consistently so that both the core wpa_supplicant functionality (struct wpa_bss_tmp_disallowed) and the wpa_driver_ops callback have more similar names. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 10 +++++----- src/drivers/driver_nl80211.c | 9 +++++---- wpa_supplicant/driver_i.h | 12 ++++++------ wpa_supplicant/wpa_supplicant.c | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index cb412cbfe..e8defaba2 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4387,13 +4387,13 @@ struct wpa_driver_ops { int (*ignore_assoc_disallow)(void *priv, int ignore_disallow); /** - * set_bssid_blacklist - Set blacklist of BSSIDs to the driver + * set_bssid_tmp_disallow - Set disallowed BSSIDs to the driver * @priv: Private driver interface data - * @num_bssid: Number of blacklist BSSIDs - * @bssids: List of blacklisted BSSIDs + * @num_bssid: Number of temporarily disallowed BSSIDs + * @bssids: List of temporarily disallowed BSSIDs */ - int (*set_bssid_blacklist)(void *priv, unsigned int num_bssid, - const u8 *bssid); + int (*set_bssid_tmp_disallow)(void *priv, unsigned int num_bssid, + const u8 *bssid); /** * update_connect_params - Update the connection parameters diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index d70b56ba8..14179f79b 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -9924,8 +9924,8 @@ static int nl80211_disable_fils(void *priv, int disable) /* Reserved QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID value for wpa_supplicant */ #define WPA_SUPPLICANT_CLIENT_ID 1 -static int nl80211_set_bssid_blacklist(void *priv, unsigned int num_bssid, - const u8 *bssid) +static int nl80211_set_bssid_tmp_disallow(void *priv, unsigned int num_bssid, + const u8 *bssid) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -9933,7 +9933,8 @@ static int nl80211_set_bssid_blacklist(void *priv, unsigned int num_bssid, struct nlattr *params, *nlbssids, *attr; unsigned int i; - wpa_printf(MSG_DEBUG, "nl80211: Set blacklist BSSID (num=%u)", + wpa_printf(MSG_DEBUG, + "nl80211: Set temporarily disallowed BSSIDs (num=%u)", num_bssid); if (!drv->roam_vendor_cmd_avail) @@ -11745,7 +11746,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .get_bss_transition_status = nl80211_get_bss_transition_status, .ignore_assoc_disallow = nl80211_ignore_assoc_disallow, #endif /* CONFIG_MBO */ - .set_bssid_blacklist = nl80211_set_bssid_blacklist, + .set_bssid_tmp_disallow = nl80211_set_bssid_tmp_disallow, .add_sta_node = nl80211_add_sta_node, #endif /* CONFIG_DRIVER_NL80211_QCA */ .configure_data_frame_filters = nl80211_configure_data_frame_filters, diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 54ae03b5a..ba8cc552b 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -1069,14 +1069,14 @@ static inline int wpa_drv_ignore_assoc_disallow(struct wpa_supplicant *wpa_s, return wpa_s->driver->ignore_assoc_disallow(wpa_s->drv_priv, val); } -static inline int wpa_drv_set_bssid_blacklist(struct wpa_supplicant *wpa_s, - unsigned int num_bssid, - const u8 *bssids) +static inline int wpa_drv_set_bssid_tmp_disallow(struct wpa_supplicant *wpa_s, + unsigned int num_bssid, + const u8 *bssids) { - if (!wpa_s->driver->set_bssid_blacklist) + if (!wpa_s->driver->set_bssid_tmp_disallow) return -1; - return wpa_s->driver->set_bssid_blacklist(wpa_s->drv_priv, num_bssid, - bssids); + return wpa_s->driver->set_bssid_tmp_disallow(wpa_s->drv_priv, num_bssid, + bssids); } static inline int wpa_drv_update_connect_params( diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index e7989baef..bda9fe5e4 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -7929,7 +7929,7 @@ static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s) ETH_ALEN); num_bssid++; } - ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids); + ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids); os_free(bssids); return ret; } From 730fc307b10643917d24398f85500dca1c66fd5c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Jul 2020 12:23:56 +0300 Subject: [PATCH 0755/1105] Update documentation for vendor attributes to ignore BSSIDs during roaming Replace some of the "blacklist" term to reduce undesired connotations. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 448d52682..df0053cff 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -4078,7 +4078,7 @@ enum qca_vendor_attr_roam_control { * Represents the Request ID for the specific set of commands. * This also helps to map specific set of commands to the respective * ID / client. e.g., helps to identify the user entity configuring the - * Blacklist BSSID and accordingly clear the respective ones with the + * ignored BSSIDs and accordingly clear the respective ones with the * matching ID. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: Unsigned @@ -4145,17 +4145,18 @@ enum qca_vendor_attr_roam_control { * the BSSID for the purpose of comparing it with other roam candidate. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS: Nested attribute, - * represents the BSSIDs to get blacklisted for roaming. + * represents the BSSIDs to get ignored for roaming. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID: Unsigned - * 32-bit value, represents the number of blacklisted BSSIDs. + * 32-bit value, represents the number of ignored BSSIDs. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID: 6-byte MAC - * address representing the Blacklisted BSSID. + * address representing the ignored BSSID. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT: Flag attribute, - * indicates this BSSID blacklist as a hint to the driver. The driver can - * select this BSSID in the worst case (when no other BSSIDs are better). + * indicates this request to ignore the BSSID as a hint to the driver. The + * driver can select this BSSID in the worst case (when no other BSSIDs are + * better). * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL: Nested attribute to * set/get/clear the roam control config as @@ -4190,11 +4191,11 @@ enum qca_wlan_vendor_attr_roaming_config_params { QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID = 16, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER = 17, - /* Attribute for set_blacklist bssid params */ + /* Attribute for setting ignored BSSID parameters */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS = 18, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID = 19, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID = 20, - /* Flag attribute indicates this BSSID blacklist as a hint */ + /* Flag attribute indicates this entry as a hint */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT = 21, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL = 22, @@ -4230,9 +4231,9 @@ enum qca_wlan_vendor_attr_roaming_config_params { * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS to set the BSSID * preference. * - * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the Blacklist - * BSSIDs. Refers QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to - * set the same. + * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the list of BSSIDs + * to ignore in roaming decision. Uses + * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to set the list. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET: Command to set the * roam control config to the driver with the attribute From 6eaee933d73db7fc32890938f4008e47fd05ee44 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Jul 2020 00:30:38 +0300 Subject: [PATCH 0756/1105] dpp-nfc: Add test mode for negotiated connection handover Allow all actual DPP processing steps in wpa_supplicant to be skipped by specifying hardcoded URI values. Also allow a hardcoded crn to be specified to force specific handover requestor/selector roles. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 129 ++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 41 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index bd0330859..fda97918c 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -248,7 +248,12 @@ def dpp_handover_client(llc, alt=False): if alt: global altchanlist chan_override = altchanlist - uri = wpas_get_nfc_uri(start_listen=False, chan_override=chan_override) + global test_uri, test_alt_uri + if test_uri: + summary("TEST MODE: Using specified URI (alt=%s)" % str(alt)) + uri = test_alt_uri if alt else test_uri + else: + uri = wpas_get_nfc_uri(start_listen=False, chan_override=chan_override) if uri is None: summary("Cannot start handover client - no bootstrap URI available", color=C_RED) @@ -256,7 +261,14 @@ def dpp_handover_client(llc, alt=False): uri = ndef.UriRecord(uri) summary("NFC URI record for DPP: " + str(uri)) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) - crn = os.urandom(2) + global test_crn + if test_crn: + prev, = struct.unpack('>H', test_crn) + summary("TEST MODE: Use specified crn %d" % prev) + crn = test_crn + test_crn = struct.pack('>H', prev + 0x10) + else: + crn = os.urandom(2) hr = ndef.HandoverRequestRecord(version="1.4", crn=crn) hr.add_alternative_carrier('active', carrier.name) message = [hr, carrier] @@ -338,6 +350,9 @@ def dpp_handover_client(llc, alt=False): dpp_found = True uri = carrier.data[1:].decode("utf-8") summary("DPP URI: " + uri) + if test_uri: + summary("TEST MODE: Fake processing") + break res = wpas_report_handover_sel(uri) if res is None or "FAIL" in res: summary("DPP handover report rejected", color=C_RED) @@ -467,10 +482,20 @@ class HandoverServer(nfc.handover.HandoverServer): uri = carrier.data[1:].decode("utf-8") summary("Received DPP URI: " + uri) - data = wpas_get_nfc_uri(start_listen=False, pick_channel=True) + global test_uri, test_alt_uri + if test_uri: + summary("TEST MODE: Using specified URI") + data = test_sel_uri if test_sel_uri else test_uri + else: + data = wpas_get_nfc_uri(start_listen=False, + pick_channel=True) summary("Own URI (pre-processing): %s" % data) - res = wpas_report_handover_req(uri) + if test_uri: + summary("TEST MODE: Fake processing") + res = "OK" + else: + res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: summary("DPP handover request processing failed", color=C_RED) @@ -481,48 +506,54 @@ class HandoverServer(nfc.handover.HandoverServer): summary("Own URI (try another channel list): %s" % data) continue + if test_alt_uri: + summary("TEST MODE: Reject initial proposal") + continue + found = True - wpas = wpas_connect() - if wpas is None: - continue - global own_id - data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() - if "FAIL" in data: - continue + if not test_uri: + wpas = wpas_connect() + if wpas is None: + continue + global own_id + data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() + if "FAIL" in data: + continue summary("Own URI (post-processing): %s" % data) uri = ndef.UriRecord(data) summary("Own bootstrapping NFC URI record: " + str(uri)) - info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) - freq = None - for line in info.splitlines(): - if line.startswith("use_freq="): - freq = int(line.split('=')[1]) - if freq is None or freq == 0: - summary("No channel negotiated over NFC - use channel 6") - freq = 2437 - else: - summary("Negotiated channel: %d MHz" % freq) - if get_status_field(wpas, "bssid[0]"): - summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) - if get_status_field(wpas, "beacon_set", extra="DRIVER") is None: - summary("Enable beaconing to have radio ready for RX") - wpas.request("DISABLE") - wpas.request("SET start_disabled 0") - wpas.request("ENABLE") - cmd = "DPP_LISTEN %d" % freq - global enrollee_only - global configurator_only - if enrollee_only: - cmd += " role=enrollee" - elif configurator_only: - cmd += " role=configurator" - summary(cmd) - res = wpas.request(cmd) - if "OK" not in res: - summary("Failed to start DPP listen", color=C_RED) - break + if not test_uri: + info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) + freq = None + for line in info.splitlines(): + if line.startswith("use_freq="): + freq = int(line.split('=')[1]) + if freq is None or freq == 0: + summary("No channel negotiated over NFC - use channel 6") + freq = 2437 + else: + summary("Negotiated channel: %d MHz" % freq) + if get_status_field(wpas, "bssid[0]"): + summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) + if get_status_field(wpas, "beacon_set", extra="DRIVER") is None: + summary("Enable beaconing to have radio ready for RX") + wpas.request("DISABLE") + wpas.request("SET start_disabled 0") + wpas.request("ENABLE") + cmd = "DPP_LISTEN %d" % freq + global enrollee_only + global configurator_only + if enrollee_only: + cmd += " role=enrollee" + elif configurator_only: + cmd += " role=configurator" + summary(cmd) + res = wpas.request(cmd) + if "OK" not in res: + summary("Failed to start DPP listen", color=C_RED) + break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) summary("Own DPP carrier record: " + str(carrier)) @@ -802,6 +833,14 @@ def main(): parser.add_argument('--chan', default=None, help='channel list') parser.add_argument('--altchan', default=None, help='alternative channel list') parser.add_argument('--netrole', default=None, help='netrole for Enrollee') + parser.add_argument('--test-uri', default=None, + help='test mode: initial URI') + parser.add_argument('--test-alt-uri', default=None, + help='test mode: alternative URI') + parser.add_argument('--test-sel-uri', default=None, + help='test mode: handover select URI') + parser.add_argument('--test-crn', default=None, + help='test mode: hardcoded crn') parser.add_argument('command', choices=['write-nfc-uri', 'write-nfc-hs'], nargs='?') @@ -814,10 +853,18 @@ def main(): global no_wait no_wait = args.no_wait - global chanlist, altchanlist, netrole + global chanlist, altchanlist, netrole, test_uri, test_alt_uri, test_sel_uri + global test_crn chanlist = args.chan altchanlist = args.altchan netrole = args.netrole + test_uri = args.test_uri + test_alt_uri = args.test_alt_uri + test_sel_uri = args.test_sel_uri + if args.test_crn: + test_crn = struct.pack('>H', int(args.test_crn)) + else: + test_crn = None logging.basicConfig(level=args.loglevel) From 7d27bcb8e79ba3e4266e79978fb4b6b45165c30a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Jul 2020 00:51:49 +0300 Subject: [PATCH 0757/1105] dpp-nfc: Do not allow more than one alternative channel proposal This avoids potential loops of endless alternative URI exchanges over NFC negotiated connection handover. Only allow one such alternative proposal and declarare the handover as a failure if another alternative were needed. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index fda97918c..24826e0f6 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -41,6 +41,7 @@ hs_sent = False netrole = None operation_success = False mutex = threading.Lock() +no_alt_proposal = False C_NORMAL = '\033[0m' C_RED = '\033[91m' @@ -388,7 +389,10 @@ def dpp_handover_client(llc, alt=False): summary("Failed to initiate DPP authentication", color=C_RED) break - if not dpp_found: + global no_alt_proposal + if not dpp_found and no_alt_proposal: + summary("DPP carrier not seen in response - do not allow alternative proposal anymore") + elif not dpp_found: summary("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") my_crn_ready = False my_crn = None @@ -561,16 +565,21 @@ class HandoverServer(nfc.handover.HandoverServer): sel = [hs, carrier] break - global hs_sent + global hs_sent, no_alt_proposal summary("Sending handover select: " + str(sel)) if found: summary("Handover completed successfully") self.success = True hs_sent = True + elif no_alt_proposal: + summary("Do not try alternative proposal anymore - handover failed", + color=C_RED) + hs_sent = True else: summary("Try to initiate with alternative parameters") self.try_own = True hs_sent = False + no_alt_proposal = True threading.Thread(target=llcp_worker, args=(self.llc, True)).start() return sel @@ -775,11 +784,13 @@ def llcp_startup(llc): def llcp_connected(llc): summary("P2P LLCP connected") global wait_connection, my_crn, peer_crn, my_crn_ready, hs_sent + global no_alt_proposal wait_connection = False my_crn_ready = False my_crn = None peer_crn = None hs_sent = False + no_alt_proposal = False global srv srv.start() if init_on_touch or not no_input: From e9c192ffc701a1f99cf86dd70ab026fd4dd22bf8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 24 Jul 2020 12:46:20 +0300 Subject: [PATCH 0758/1105] dpp-nfc: Ignore (no) response to initial handover request If an alternative proposal (second handover request) is sent, the response (or lack of it) to the initial handover request should be ignored. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 24826e0f6..a1a542ae4 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -246,9 +246,11 @@ def wpas_report_handover_sel(uri): def dpp_handover_client(llc, alt=False): chan_override = None + global alt_proposal_used if alt: global altchanlist chan_override = altchanlist + alt_proposal_used = True global test_uri, test_alt_uri if test_uri: summary("TEST MODE: Using specified URI (alt=%s)" % str(alt)) @@ -318,12 +320,16 @@ def dpp_handover_client(llc, alt=False): # This is fine if we are the handover selector if hs_sent: summary("Client receive failed as expected since I'm the handover server: %s" % str(e)) + elif alt_proposal_used and not alt: + summary("Client received failed for initial proposal as expected since alternative proposal was also used: %s" % str(e)) else: summary("Client receive failed: %s" % str(e), color=C_RED) message = None if message is None: if hs_sent: summary("No response received as expected since I'm the handover server") + elif alt_proposal_used and not alt: + summary("No response received for initial proposal as expected since alternative proposal was also used") else: summary("No response received", color=C_RED) client.close() @@ -338,6 +344,11 @@ def dpp_handover_client(llc, alt=False): summary("Received handover select message") summary("alternative carriers: " + str(message[0].alternative_carriers)) + if alt_proposal_used and not alt: + summary("Ignore received handover select for the initial proposal since alternative proposal was sent") + client.close() + return + dpp_found = False for carrier in message: if isinstance(carrier, ndef.HandoverSelectRecord): @@ -784,13 +795,14 @@ def llcp_startup(llc): def llcp_connected(llc): summary("P2P LLCP connected") global wait_connection, my_crn, peer_crn, my_crn_ready, hs_sent - global no_alt_proposal + global no_alt_proposal, alt_proposal_used wait_connection = False my_crn_ready = False my_crn = None peer_crn = None hs_sent = False no_alt_proposal = False + alt_proposal_used = False global srv srv.start() if init_on_touch or not no_input: From a80ab0ea9593a9e7fb7b976be98aa04a432bbb16 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 28 Jul 2020 16:44:41 +0300 Subject: [PATCH 0759/1105] tests: sigma_dut DPP Configurator reporting MUD URL Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 9f3b23e19..de5495199 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -2021,9 +2021,14 @@ def test_sigma_dut_dpp_qr_init_configurator_neg_freq(dev, apdev): """sigma_dut DPP/QR initiator as Configurator (neg_freq)""" run_sigma_dut_dpp_qr_init_configurator(dev, apdev, 1, extra='DPPSubsequentChannel,81/11') +def test_sigma_dut_dpp_qr_init_configurator_mud_url(dev, apdev): + """sigma_dut DPP/QR initiator as Configurator (MUD URL)""" + run_sigma_dut_dpp_qr_init_configurator(dev, apdev, 1, + mud_url="https://example.com/mud") + def run_sigma_dut_dpp_qr_init_configurator(dev, apdev, conf_idx, prov_role="Configurator", - extra=None): + extra=None, mud_url=None): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) sigma = start_sigma_dut(dev[0].ifname) @@ -2031,6 +2036,8 @@ def run_sigma_dut_dpp_qr_init_configurator(dev, apdev, conf_idx, id0 = dev[1].dpp_bootstrap_gen(chan="81/6", mac=True) uri0 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + if mud_url: + dev[1].set("dpp_mud_url", mud_url) cmd = "DPP_LISTEN 2437 role=enrollee" if "OK" not in dev[1].request(cmd): raise Exception("Failed to start listen operation") @@ -2045,7 +2052,10 @@ def run_sigma_dut_dpp_qr_init_configurator(dev, apdev, conf_idx, res = sigma_dut_cmd(cmd) if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: raise Exception("Unexpected result: " + res) + if mud_url and ",MUDURL," + mud_url not in res: + raise Exception("Unexpected result (missing MUD URL): " + res) finally: + dev[1].set("dpp_mud_url", "") stop_sigma_dut(sigma) def test_sigma_dut_dpp_incompatible_roles_init(dev, apdev): From 1d3e16d0b05df3ff12a419f252782ddef9f275b6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 30 Jul 2020 12:51:56 +0300 Subject: [PATCH 0760/1105] dpp-nfc: Skip P2P management interfaces Do not try to perform DPP operations on the P2P management interface when no specific interface has been identified. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index a1a542ae4..bbfc303a8 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -80,15 +80,18 @@ def wpas_connect(): return None for ctrl in ifaces: - if ifname: - if ifname not in ctrl: - continue + if ifname and ifname not in ctrl: + continue + if os.path.basename(ctrl).startswith("p2p-dev-"): + # skip P2P management interface + continue try: summary("Trying to use control interface " + ctrl) wpas = wpaspy.Ctrl(ctrl) return wpas except Exception as e: pass + summary("Could not connect to wpa_supplicant") return None def dpp_nfc_uri_process(uri): From 7c04bab710cd7ef9b1de61eca65d40dcb70f066d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 30 Jul 2020 13:52:14 +0300 Subject: [PATCH 0761/1105] tests: AES-CTR encrypt test vectors Verify AES-CTR encryption implementation against the test vectors in NIST SP 800-38a. This implementations was already tested against AES SIV and EAX mode test vectors, but this adds more explicit testing against published CTR mode test vectors. Signed-off-by: Jouni Malinen --- src/crypto/crypto_module_tests.c | 150 +++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/src/crypto/crypto_module_tests.c b/src/crypto/crypto_module_tests.c index 1cc73d8ec..fafb688b4 100644 --- a/src/crypto/crypto_module_tests.c +++ b/src/crypto/crypto_module_tests.c @@ -744,6 +744,155 @@ static int test_key_wrap(void) } +static int test_aes_ctr(void) +{ + int res = 0; + +#if defined(CONFIG_MESH) || defined(CONFIG_PSK) + /* CTR-AES*.Encrypt test vectors from NIST SP 800-38a */ + const u8 key128[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + const u8 counter128[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + const u8 plain128[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + const u8 cipher128[] = { + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, + 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, + 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, + 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, + 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, + 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, + 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, + 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee + }; + const u8 key192[] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b + }; + const u8 counter192[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + const u8 plain192[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + const u8 cipher192[] = { + 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, + 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b, + 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, + 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94, + 0x1e, 0x36, 0xb2, 0x6b, 0xd1, 0xeb, 0xc6, 0x70, + 0xd1, 0xbd, 0x1d, 0x66, 0x56, 0x20, 0xab, 0xf7, + 0x4f, 0x78, 0xa7, 0xf6, 0xd2, 0x98, 0x09, 0x58, + 0x5a, 0x97, 0xda, 0xec, 0x58, 0xc6, 0xb0, 0x50 + }; + const u8 key256[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 + }; + const u8 counter256[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + const u8 plain256[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + const u8 cipher256[] = { + 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, + 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, + 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, + 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5, + 0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, + 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d, + 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, + 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6 + }; + size_t len; + u8 *tmp; + + wpa_printf(MSG_DEBUG, "CTR-AES128.Encrypt"); + len = sizeof(plain128); + tmp = os_malloc(len); + if (!tmp) + return -1; + os_memcpy(tmp, plain128, len); + if (aes_ctr_encrypt(key128, sizeof(key128), counter128, tmp, len) < 0) { + wpa_printf(MSG_ERROR, "aes_ctr_encrypt() failed"); + res = -1; + } else if (os_memcmp(tmp, cipher128, len) != 0) { + wpa_printf(MSG_ERROR, + "CTR-AES128.Encrypt test vector did not match"); + res = -1; + } + os_free(tmp); + + wpa_printf(MSG_DEBUG, "CTR-AES192.Encrypt"); + len = sizeof(plain192); + tmp = os_malloc(len); + if (!tmp) + return -1; + os_memcpy(tmp, plain192, len); + if (aes_ctr_encrypt(key192, sizeof(key192), counter192, tmp, len) < 0) { + wpa_printf(MSG_ERROR, "aes_ctr_encrypt() failed"); + res = -1; + } else if (os_memcmp(tmp, cipher192, len) != 0) { + wpa_printf(MSG_ERROR, + "CTR-AES192.Encrypt test vector did not match"); + res = -1; + } + os_free(tmp); + + wpa_printf(MSG_DEBUG, "CTR-AES256.Encrypt"); + len = sizeof(plain256); + tmp = os_malloc(len); + if (!tmp) + return -1; + os_memcpy(tmp, plain256, len); + if (aes_ctr_encrypt(key256, sizeof(key256), counter256, tmp, len) < 0) { + wpa_printf(MSG_ERROR, "aes_ctr_encrypt() failed"); + res = -1; + } else if (os_memcmp(tmp, cipher256, len) != 0) { + wpa_printf(MSG_ERROR, + "CTR-AES256.Encrypt test vector did not match"); + res = -1; + } + os_free(tmp); +#endif + + return res; +} + + static int test_md5(void) { #ifndef CONFIG_FIPS @@ -2154,6 +2303,7 @@ int crypto_module_tests(void) test_cbc() || test_ecb() || test_key_wrap() || + test_aes_ctr() || test_md5() || test_sha1() || test_sha256() || From 3021b14c490493bf8cec7e51f12796ae05bb0a97 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 30 Jul 2020 16:49:40 +0300 Subject: [PATCH 0762/1105] dpp-nfc: Enable more verbose nfcpy debugging Set logging level to various upper layer nfcpy modules to enable more detailed debugging of the actual NFC operations when requested (-d on the command line). Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index bbfc303a8..ef6370598 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -893,6 +893,14 @@ def main(): test_crn = None logging.basicConfig(level=args.loglevel) + for l in ['nfc.clf.rcs380', + 'nfc.clf.transport', + 'nfc.clf.device', + 'nfc.clf.__init__', + 'nfc.llcp', + 'nfc.handover']: + log = logging.getLogger(l) + log.setLevel(args.loglevel) global init_on_touch init_on_touch = args.init_on_touch From 6e904441c80bc5560ea37f27636234288a1b49fe Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 30 Jul 2020 20:35:10 +0300 Subject: [PATCH 0763/1105] dpp-nfc: Add peer URI into the HS in testing mode This makes it easier to confirm that the correct pair of the HR and the HS were used. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index ef6370598..e793643e8 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -512,6 +512,7 @@ class HandoverServer(nfc.handover.HandoverServer): if test_uri: summary("TEST MODE: Fake processing") res = "OK" + data += " [%s]" % uri else: res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: From 66d74626baa3cb1a82918b739b4b326be67ffcd4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 30 Jul 2020 17:09:56 +0300 Subject: [PATCH 0764/1105] dpp-nfc: Reuse the same handover client for alternative URI Postpone closing of the handover client to allow the same client to be used for sending both handover request messages if an alternative URI needs to be tried. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 77 +++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index e793643e8..86f0ef39d 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -30,6 +30,8 @@ in_raw_mode = False prev_tcgetattr = 0 no_input = False srv = None +hs_client = None +need_client = False continue_loop = True terminate_now = False summary_file = None @@ -41,7 +43,9 @@ hs_sent = False netrole = None operation_success = False mutex = threading.Lock() +client_mutex = threading.Lock() no_alt_proposal = False +i_m_selector = False C_NORMAL = '\033[0m' C_RED = '\033[91m' @@ -248,6 +252,19 @@ def wpas_report_handover_sel(uri): return wpas.request(cmd) def dpp_handover_client(llc, alt=False): + summary("About to start run_dpp_handover_client (alt=%s)" % str(alt)) + if alt: + global need_client + need_client = True + with client_mutex: + summary("Start run_dpp_handover_client (client_mutex held; alt=%s))" % str(alt)) + if alt: + global i_m_selector + i_m_selector = False + run_dpp_handover_client(llc, alt) + summary("Done run_dpp_handover_client (alt=%s)" % str(alt)) + +def run_dpp_handover_client(llc, alt=False): chan_override = None global alt_proposal_used if alt: @@ -284,33 +301,40 @@ def dpp_handover_client(llc, alt=False): if peer_crn is not None and not alt: summary("NFC handover request from peer was already received - do not send own") return - client = nfc.handover.HandoverClient(llc) - try: - summary("Trying to initiate NFC connection handover") - client.connect() - summary("Connected for handover") - except nfc.llcp.ConnectRefused: - summary("Handover connection refused") - client.close() - return - except Exception as e: - summary("Other exception: " + str(e)) - client.close() - return + global hs_client + if hs_client: + summary("Use already started handover client") + client = hs_client + else: + summary("Start handover client") + client = nfc.handover.HandoverClient(llc) + try: + summary("Trying to initiate NFC connection handover") + client.connect() + summary("Connected for handover") + except nfc.llcp.ConnectRefused: + summary("Handover connection refused") + client.close() + return + except Exception as e: + summary("Other exception: " + str(e)) + client.close() + return + hs_client = client; if peer_crn is not None and not alt: summary("NFC handover request from peer was already received - do not send own") - client.close() return summary("Sending handover request") - global my_crn, my_crn_ready, hs_sent + global my_crn, my_crn_ready, hs_sent, need_client my_crn_ready = True if not client.send_records(message): my_crn_ready = False summary("Failed to send handover request", color=C_RED) + hs_client = None client.close() return @@ -333,19 +357,27 @@ def dpp_handover_client(llc, alt=False): summary("No response received as expected since I'm the handover server") elif alt_proposal_used and not alt: summary("No response received for initial proposal as expected since alternative proposal was also used") + elif need_client: + summary("No response received, but handover client is still needed") else: summary("No response received", color=C_RED) - client.close() + hs_client = None + client.close() return summary("Received message: " + str(message)) if len(message) < 1 or \ not isinstance(message[0], ndef.HandoverSelectRecord): summary("Response was not Hs - received: " + message.type) + hs_client = None client.close() return summary("Received handover select message") summary("alternative carriers: " + str(message[0].alternative_carriers)) + global i_m_selector + if i_m_selector: + summary("Ignore the received select since I'm the handover selector") + return if alt_proposal_used and not alt: summary("Ignore received handover select for the initial proposal since alternative proposal was sent") @@ -412,11 +444,13 @@ def dpp_handover_client(llc, alt=False): my_crn = None peer_crn = None hs_sent = False + hs_client = None client.close() summary("Returning from dpp_handover_client") return summary("Remove peer") + hs_client = None client.close() summary("Done with handover") global only_one @@ -477,7 +511,8 @@ class HandoverServer(nfc.handover.HandoverServer): if ((my_crn & 1) == (peer_crn & 1) and my_crn > peer_crn) or \ ((my_crn & 1) != (peer_crn & 1) and my_crn < peer_crn): summary("I'm the Handover Selector Device") - pass + global i_m_selector + i_m_selector = True else: summary("Peer is the Handover Selector device") summary("Ignore the received request.") @@ -799,7 +834,7 @@ def llcp_startup(llc): def llcp_connected(llc): summary("P2P LLCP connected") global wait_connection, my_crn, peer_crn, my_crn_ready, hs_sent - global no_alt_proposal, alt_proposal_used + global no_alt_proposal, alt_proposal_used, need_client, i_m_selector wait_connection = False my_crn_ready = False my_crn = None @@ -807,6 +842,8 @@ def llcp_connected(llc): hs_sent = False no_alt_proposal = False alt_proposal_used = False + need_client = False + i_m_selector = False global srv srv.start() if init_on_touch or not no_input: @@ -815,6 +852,10 @@ def llcp_connected(llc): def llcp_release(llc): summary("LLCP release") + global hs_client + if hs_client: + hs_client.close() + hs_client = None return True def terminate_loop(): From aaa8638ed2c0452812e85ba52bbef9b24a7e3ceb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 30 Jul 2020 20:58:08 +0300 Subject: [PATCH 0765/1105] dpp-nfc: Add a class for maintaining connection handover state This cleans up the shared state between the handover server and client. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 225 +++++++++++++---------------- 1 file changed, 104 insertions(+), 121 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 86f0ef39d..882356f67 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -29,23 +29,14 @@ init_on_touch = False in_raw_mode = False prev_tcgetattr = 0 no_input = False -srv = None -hs_client = None -need_client = False continue_loop = True terminate_now = False summary_file = None success_file = None -my_crn_ready = False -my_crn = None -peer_crn = None -hs_sent = False netrole = None operation_success = False mutex = threading.Lock() client_mutex = threading.Lock() -no_alt_proposal = False -i_m_selector = False C_NORMAL = '\033[0m' C_RED = '\033[91m' @@ -251,26 +242,22 @@ def wpas_report_handover_sel(uri): cmd = "DPP_NFC_HANDOVER_SEL own=%d uri=%s" % (own_id, uri) return wpas.request(cmd) -def dpp_handover_client(llc, alt=False): +def dpp_handover_client(handover, alt=False): summary("About to start run_dpp_handover_client (alt=%s)" % str(alt)) if alt: - global need_client - need_client = True + handover.need_client = True with client_mutex: summary("Start run_dpp_handover_client (client_mutex held; alt=%s))" % str(alt)) if alt: - global i_m_selector - i_m_selector = False - run_dpp_handover_client(llc, alt) + handover.i_m_selector = False + run_dpp_handover_client(handover, alt) summary("Done run_dpp_handover_client (alt=%s)" % str(alt)) -def run_dpp_handover_client(llc, alt=False): +def run_dpp_handover_client(handover, alt=False): chan_override = None - global alt_proposal_used if alt: - global altchanlist - chan_override = altchanlist - alt_proposal_used = True + chan_override = handover.altchanlist + handover.alt_proposal_used = True global test_uri, test_alt_uri if test_uri: summary("TEST MODE: Using specified URI (alt=%s)" % str(alt)) @@ -297,17 +284,15 @@ def run_dpp_handover_client(llc, alt=False): message = [hr, carrier] summary("NFC Handover Request message for DPP: " + str(message)) - global peer_crn - if peer_crn is not None and not alt: + if handover.peer_crn is not None and not alt: summary("NFC handover request from peer was already received - do not send own") return - global hs_client - if hs_client: + if handover.client: summary("Use already started handover client") - client = hs_client + client = handover.client else: summary("Start handover client") - client = nfc.handover.HandoverClient(llc) + client = nfc.handover.HandoverClient(handover.llc) try: summary("Trying to initiate NFC connection handover") client.connect() @@ -320,66 +305,58 @@ def run_dpp_handover_client(llc, alt=False): summary("Other exception: " + str(e)) client.close() return - hs_client = client; + handover.client = client - if peer_crn is not None and not alt: + if handover.peer_crn is not None and not alt: summary("NFC handover request from peer was already received - do not send own") return summary("Sending handover request") - global my_crn, my_crn_ready, hs_sent, need_client - my_crn_ready = True + handover.my_crn_ready = True if not client.send_records(message): - my_crn_ready = False + handover.my_crn_ready = False summary("Failed to send handover request", color=C_RED) - hs_client = None - client.close() return - my_crn, = struct.unpack('>H', crn) + handover.my_crn, = struct.unpack('>H', crn) summary("Receiving handover response") try: message = client.recv_records(timeout=3.0) except Exception as e: # This is fine if we are the handover selector - if hs_sent: + if handover.hs_sent: summary("Client receive failed as expected since I'm the handover server: %s" % str(e)) - elif alt_proposal_used and not alt: + elif handover.alt_proposal_used and not alt: summary("Client received failed for initial proposal as expected since alternative proposal was also used: %s" % str(e)) else: summary("Client receive failed: %s" % str(e), color=C_RED) message = None if message is None: - if hs_sent: + if handover.hs_sent: summary("No response received as expected since I'm the handover server") - elif alt_proposal_used and not alt: + elif handover.alt_proposal_used and not alt: summary("No response received for initial proposal as expected since alternative proposal was also used") - elif need_client: + elif handover.need_client: summary("No response received, but handover client is still needed") else: summary("No response received", color=C_RED) - hs_client = None - client.close() return summary("Received message: " + str(message)) if len(message) < 1 or \ not isinstance(message[0], ndef.HandoverSelectRecord): summary("Response was not Hs - received: " + message.type) - hs_client = None - client.close() return summary("Received handover select message") summary("alternative carriers: " + str(message[0].alternative_carriers)) - global i_m_selector - if i_m_selector: + if handover.i_m_selector: summary("Ignore the received select since I'm the handover selector") return - if alt_proposal_used and not alt: + if handover.alt_proposal_used and not alt: summary("Ignore received handover select for the initial proposal since alternative proposal was sent") client.close() return @@ -435,23 +412,19 @@ def run_dpp_handover_client(llc, alt=False): summary("Failed to initiate DPP authentication", color=C_RED) break - global no_alt_proposal - if not dpp_found and no_alt_proposal: + if not dpp_found and handover.no_alt_proposal: summary("DPP carrier not seen in response - do not allow alternative proposal anymore") elif not dpp_found: summary("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") - my_crn_ready = False - my_crn = None - peer_crn = None - hs_sent = False - hs_client = None - client.close() + handover.my_crn_ready = False + handover.my_crn = None + handover.peer_crn = None + handover.hs_sent = False summary("Returning from dpp_handover_client") return summary("Remove peer") - hs_client = None - client.close() + handover.close() summary("Done with handover") global only_one if only_one: @@ -468,15 +441,17 @@ def run_dpp_handover_client(llc, alt=False): summary("Returning from dpp_handover_client") class HandoverServer(nfc.handover.HandoverServer): - def __init__(self, llc): + def __init__(self, handover, llc): super(HandoverServer, self).__init__(llc) self.sent_carrier = None self.ho_server_processing = False self.success = False self.try_own = False self.llc = llc + self.handover = handover def process_handover_request_message(self, records): + handover = self.handover self.ho_server_processing = True global in_raw_mode was_in_raw_mode = in_raw_mode @@ -485,34 +460,33 @@ class HandoverServer(nfc.handover.HandoverServer): print("\n") summary("HandoverServer - request received: " + str(records)) - global my_crn, peer_crn, my_crn_ready - for carrier in records: if not isinstance(carrier, ndef.HandoverRequestRecord): continue if carrier.collision_resolution_number: - peer_crn = carrier.collision_resolution_number - summary("peer_crn: %d" % peer_crn) + handover.peer_crn = carrier.collision_resolution_number + summary("peer_crn: %d" % handover.peer_crn) - if my_crn is None and my_crn_ready: + if handover.my_crn is None and handover.my_crn_ready: summary("Still trying to send own handover request - wait a moment to see if that succeeds before checking crn values") for i in range(10): - if my_crn is not None: + if handover.my_crn is not None: break time.sleep(0.01) - if my_crn is not None: - summary("my_crn: %d" % my_crn) + if handover.my_crn is not None: + summary("my_crn: %d" % handover.my_crn) - if my_crn is not None and peer_crn is not None: - if my_crn == peer_crn: + if handover.my_crn is not None and handover.peer_crn is not None: + if handover.my_crn == handover.peer_crn: summary("Same crn used - automatic collision resolution failed") # TODO: Should generate a new Handover Request message return '' - if ((my_crn & 1) == (peer_crn & 1) and my_crn > peer_crn) or \ - ((my_crn & 1) != (peer_crn & 1) and my_crn < peer_crn): + if ((handover.my_crn & 1) == (handover.peer_crn & 1) and \ + handover.my_crn > handover.peer_crn) or \ + ((handover.my_crn & 1) != (handover.peer_crn & 1) and \ + handover.my_crn < handover.peer_crn): summary("I'm the Handover Selector Device") - global i_m_selector - i_m_selector = True + handover.i_m_selector = True else: summary("Peer is the Handover Selector device") summary("Ignore the received request.") @@ -553,10 +527,9 @@ class HandoverServer(nfc.handover.HandoverServer): if res is None or "FAIL" in res: summary("DPP handover request processing failed", color=C_RED) - global altchanlist - if altchanlist: + if handover.altchanlist: data = wpas_get_nfc_uri(start_listen=False, - chan_override=altchanlist) + chan_override=handover.altchanlist) summary("Own URI (try another channel list): %s" % data) continue @@ -615,21 +588,20 @@ class HandoverServer(nfc.handover.HandoverServer): sel = [hs, carrier] break - global hs_sent, no_alt_proposal summary("Sending handover select: " + str(sel)) if found: summary("Handover completed successfully") self.success = True - hs_sent = True - elif no_alt_proposal: + handover.hs_sent = True + elif handover.no_alt_proposal: summary("Do not try alternative proposal anymore - handover failed", color=C_RED) - hs_sent = True + handover.hs_sent = True else: summary("Try to initiate with alternative parameters") self.try_own = True - hs_sent = False - no_alt_proposal = True + handover.hs_sent = False + handover.no_alt_proposal = True threading.Thread(target=llcp_worker, args=(self.llc, True)).start() return sel @@ -772,16 +744,17 @@ def rdwr_connected(tag): return not no_wait def llcp_worker(llc, try_alt): + global handover print("Start of llcp_worker()") if try_alt: summary("Starting handover client (try_alt)") - dpp_handover_client(llc, alt=True) + dpp_handover_client(handover, alt=True) summary("Exiting llcp_worker thread (try_alt)") return global init_on_touch if init_on_touch: summary("Starting handover client (init_on_touch)") - dpp_handover_client(llc) + dpp_handover_client(handover) summary("Exiting llcp_worker thread (init_on_touch)") return @@ -790,21 +763,18 @@ def llcp_worker(llc, try_alt): summary("Wait for handover to complete") else: print("Wait for handover to complete - press 'i' to initiate") - global srv - global wait_connection - while not wait_connection and srv.sent_carrier is None: - if srv.try_own: - srv.try_own = False + while not handover.wait_connection and handover.srv.sent_carrier is None: + if handover.srv.try_own: + handover.srv.try_own = False summary("Try to initiate another handover with own parameters") - global peer_crn, my_crn, my_crn_ready, hs_sent - my_crn_ready = False - my_crn = None - peer_crn = None - hs_sent = False - dpp_handover_client(llc, alt=True) + handover.my_crn_ready = False + handover.my_crn = None + handover.peer_crn = None + handover.hs_sent = False + dpp_handover_client(handover, alt=True) summary("Exiting llcp_worker thread (retry with own parameters)") return - if srv.ho_server_processing: + if handover.srv.ho_server_processing: time.sleep(0.025) elif no_input: time.sleep(0.5) @@ -814,7 +784,7 @@ def llcp_worker(llc, try_alt): continue clear_raw_mode() summary("Starting handover client") - dpp_handover_client(llc) + dpp_handover_client(handover) summary("Exiting llcp_worker thread (manual init)") return @@ -825,37 +795,49 @@ def llcp_worker(llc, try_alt): print("\r") summary("Exiting llcp_worker thread") +class ConnectionHandover(): + def __init__(self): + self.client = None + self.reset() + + def reset(self): + self.wait_connection = False + self.my_crn_ready = False + self.my_crn = None + self.peer_crn = None + self.hs_sent = False + self.no_alt_proposal = False + self.alt_proposal_used = False + self.need_client = False + self.i_m_selector = False + + def start_handover_server(self, llc): + summary("Start handover server") + self.llc = llc + self.srv = HandoverServer(self, llc) + + def close(self): + if self.client: + self.client.close() + self.client = None + def llcp_startup(llc): - summary("Start LLCP server") - global srv - srv = HandoverServer(llc) + global handover + handover.start_handover_server(llc) return llc def llcp_connected(llc): summary("P2P LLCP connected") - global wait_connection, my_crn, peer_crn, my_crn_ready, hs_sent - global no_alt_proposal, alt_proposal_used, need_client, i_m_selector - wait_connection = False - my_crn_ready = False - my_crn = None - peer_crn = None - hs_sent = False - no_alt_proposal = False - alt_proposal_used = False - need_client = False - i_m_selector = False - global srv - srv.start() + global handover + handover.srv.start() if init_on_touch or not no_input: threading.Thread(target=llcp_worker, args=(llc, False)).start() return True def llcp_release(llc): summary("LLCP release") - global hs_client - if hs_client: - hs_client.close() - hs_client = None + global handover + handover.close() return True def terminate_loop(): @@ -915,16 +897,19 @@ def main(): args = parser.parse_args() summary(args) + global handover + handover = ConnectionHandover() + global only_one only_one = args.only_one global no_wait no_wait = args.no_wait - global chanlist, altchanlist, netrole, test_uri, test_alt_uri, test_sel_uri + global chanlist, netrole, test_uri, test_alt_uri, test_sel_uri global test_crn chanlist = args.chan - altchanlist = args.altchan + handover.altchanlist = args.altchan netrole = args.netrole test_uri = args.test_uri test_alt_uri = args.test_alt_uri @@ -978,7 +963,6 @@ def main(): no_input = True clf = nfc.ContactlessFrontend() - global wait_connection try: if not clf.open(args.device): @@ -1011,7 +995,7 @@ def main(): else: summary("Waiting for a tag or peer to be touched", color=C_GREEN) - wait_connection = True + handover.wait_connection = True try: if args.tag_read_only: if not clf.connect(rdwr={'on-connect': rdwr_connected}): @@ -1033,8 +1017,7 @@ def main(): summary("clf.connect failed: " + str(e)) break - global srv - if only_one and srv and srv.success: + if only_one and handover.srv and handover.srv.success: raise SystemExit except KeyboardInterrupt: From bbfb7b9feb82011b5a840c3908539ca8c43b373b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 30 Jul 2020 23:29:18 +0300 Subject: [PATCH 0766/1105] dpp-nfc: Use a single handover client thread Avoid extra complexity from use a separate thread to send out the alternative proposal. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 36 +++++++++++++++++++----------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 882356f67..2a22fb77f 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -36,7 +36,6 @@ success_file = None netrole = None operation_success = False mutex = threading.Lock() -client_mutex = threading.Lock() C_NORMAL = '\033[0m' C_RED = '\033[91m' @@ -245,13 +244,15 @@ def wpas_report_handover_sel(uri): def dpp_handover_client(handover, alt=False): summary("About to start run_dpp_handover_client (alt=%s)" % str(alt)) if alt: - handover.need_client = True - with client_mutex: - summary("Start run_dpp_handover_client (client_mutex held; alt=%s))" % str(alt)) - if alt: - handover.i_m_selector = False - run_dpp_handover_client(handover, alt) - summary("Done run_dpp_handover_client (alt=%s)" % str(alt)) + handover.i_m_selector = False + run_dpp_handover_client(handover, alt) + summary("Done run_dpp_handover_client (alt=%s)" % str(alt)) + +def run_client_alt(handover, alt): + if handover.start_client_alt and not alt: + handover.start_client_alt = False + summary("Try to send alternative handover request") + dpp_handover_client(handover, alt=True) def run_dpp_handover_client(handover, alt=False): chan_override = None @@ -318,6 +319,7 @@ def run_dpp_handover_client(handover, alt=False): if not client.send_records(message): handover.my_crn_ready = False summary("Failed to send handover request", color=C_RED) + run_client_alt(handover, alt) return handover.my_crn, = struct.unpack('>H', crn) @@ -339,10 +341,9 @@ def run_dpp_handover_client(handover, alt=False): summary("No response received as expected since I'm the handover server") elif handover.alt_proposal_used and not alt: summary("No response received for initial proposal as expected since alternative proposal was also used") - elif handover.need_client: - summary("No response received, but handover client is still needed") else: summary("No response received", color=C_RED) + run_client_alt(handover, alt) return summary("Received message: " + str(message)) if len(message) < 1 or \ @@ -354,6 +355,7 @@ def run_dpp_handover_client(handover, alt=False): summary("alternative carriers: " + str(message[0].alternative_carriers)) if handover.i_m_selector: summary("Ignore the received select since I'm the handover selector") + run_client_alt(handover, alt) return if handover.alt_proposal_used and not alt: @@ -602,7 +604,12 @@ class HandoverServer(nfc.handover.HandoverServer): self.try_own = True handover.hs_sent = False handover.no_alt_proposal = True - threading.Thread(target=llcp_worker, args=(self.llc, True)).start() + if handover.client_thread: + handover.start_client_alt = True + else: + handover.client_thread = threading.Thread(target=llcp_worker, + args=(self.llc, True)) + handover.client_thread.start() return sel def clear_raw_mode(): @@ -798,6 +805,7 @@ def llcp_worker(llc, try_alt): class ConnectionHandover(): def __init__(self): self.client = None + self.client_thread = None self.reset() def reset(self): @@ -808,8 +816,8 @@ class ConnectionHandover(): self.hs_sent = False self.no_alt_proposal = False self.alt_proposal_used = False - self.need_client = False self.i_m_selector = False + self.start_client_alt = False def start_handover_server(self, llc): summary("Start handover server") @@ -831,7 +839,9 @@ def llcp_connected(llc): global handover handover.srv.start() if init_on_touch or not no_input: - threading.Thread(target=llcp_worker, args=(llc, False)).start() + handover.client_thread = threading.Thread(target=llcp_worker, + args=(llc, False)) + handover.client_thread.start() return True def llcp_release(llc): From b00bbbfe54313bbd0afd4003e7234acd3f284e79 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 30 Jul 2020 23:51:30 +0300 Subject: [PATCH 0767/1105] dpp-nfc: Optimize HandoverClient message receiving for alternative HR case Use a shorter polling interval in recv_octets() to be able to send out the alternative HR more quickly when using a single thread and handover client. In addition, fix recv_records() to handle normal exception cases like not receiving anything. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 43 +++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 2a22fb77f..efd170a19 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -7,6 +7,7 @@ # This software may be distributed under the terms of the BSD license. # See README for more details. +import binascii import os import struct import sys @@ -254,6 +255,46 @@ def run_client_alt(handover, alt): summary("Try to send alternative handover request") dpp_handover_client(handover, alt=True) +class HandoverClient(nfc.handover.HandoverClient): + def __init__(self, handover, llc): + super(HandoverClient, self).__init__(llc) + self.handover = handover + + def recv_records(self, timeout=None): + msg = self.recv_octets(timeout) + if msg is None: + return None + records = list(ndef.message_decoder(msg, 'relax')) + if records and records[0].type == 'urn:nfc:wkt:Hs': + summary("Handover client received message '{0}'".format(records[0].type)) + return list(ndef.message_decoder(msg, 'relax')) + summary("Handover client received invalid message: %s" + binascii.hexlify(msg)) + return None + + def recv_octets(self, timeout=None): + start = time.time() + msg = bytearray() + poll_timeout = 0.1 if timeout is None or timeout > 0.1 else timeout + while self.socket.poll('recv', poll_timeout): + try: + r = self.socket.recv() + if r is None: + return None + msg += r + except TypeError: + return b'' + try: + list(ndef.message_decoder(msg, 'strict', {})) + return bytes(msg) + except ndef.DecodeError: + if timeout: + timeout -= time.time() - start + if timeout <= 0: + return None + start = time.time() + continue + return None + def run_dpp_handover_client(handover, alt=False): chan_override = None if alt: @@ -293,7 +334,7 @@ def run_dpp_handover_client(handover, alt=False): client = handover.client else: summary("Start handover client") - client = nfc.handover.HandoverClient(handover.llc) + client = HandoverClient(handover, handover.llc) try: summary("Trying to initiate NFC connection handover") client.connect() From dc0795e4ff952d3f7da601594594e550188afbdb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 00:16:12 +0300 Subject: [PATCH 0768/1105] dpp-nfc: Stop process after successful handover client completion terminate_now was not being set in the only_one case with connection handover. Set it for that case as well as the tag cases to automatically close down the link once it is not needed anymore. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index efd170a19..d4a050a5e 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -476,8 +476,8 @@ def run_dpp_handover_client(handover, alt=False): continue_loop = False global no_wait - if no_wait: - print("Trying to exit..") + if no_wait or only_one: + summary("Trying to exit..") global terminate_now terminate_now = True From 475b34665cb7785ef04ea01d68255b513453a123 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 00:38:42 +0300 Subject: [PATCH 0769/1105] dpp-nfc: Improved version of HandoverServer::serve() Fix processing of the case where no handover select is sent out and add automatic (delayed) termination of the link on completing the handover successfully. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 59 ++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index d4a050a5e..3bec4573a 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -8,6 +8,7 @@ # See README for more details. import binascii +import errno import os import struct import sys @@ -493,6 +494,48 @@ class HandoverServer(nfc.handover.HandoverServer): self.llc = llc self.handover = handover + def serve(self, socket): + peer_sap = socket.getpeername() + summary("Serving handover client on remote sap {0}".format(peer_sap)) + send_miu = socket.getsockopt(nfc.llcp.SO_SNDMIU) + try: + while socket.poll("recv"): + req = bytearray() + while socket.poll("recv"): + r = socket.recv() + if r is None: + return None + summary("Received %d octets" % len(r)) + req += r + if len(req) == 0: + continue + try: + list(ndef.message_decoder(req, 'strict', {})) + except ndef.DecodeError: + continue + summary("Full message received") + resp = self._process_request_data(req) + if resp is None or len(resp) == 0: + summary("No handover select to send out - wait for a possible alternative handover request") + req = bytearray() + continue + + for offset in range(0, len(resp), send_miu): + if not socket.send(resp[offset:offset + send_miu]): + summary("Failed to send handover select - connection closed") + return + summary("Sent out full handover select") + if handover.terminate_on_hs_send_completion: + handover.delayed_exit() + + except nfc.llcp.Error as e: + global terminate_now + summary("HandoverServer exception: %s" % e, + color=None if e.errno == errno.EPIPE or terminate_now else C_RED) + finally: + socket.close() + summary("Handover serve thread exiting") + def process_handover_request_message(self, records): handover = self.handover self.ho_server_processing = True @@ -634,6 +677,7 @@ class HandoverServer(nfc.handover.HandoverServer): summary("Sending handover select: " + str(sel)) if found: summary("Handover completed successfully") + handover.terminate_on_hs_send_completion = True self.success = True handover.hs_sent = True elif handover.no_alt_proposal: @@ -848,6 +892,7 @@ class ConnectionHandover(): self.client = None self.client_thread = None self.reset() + self.exit_thread = None def reset(self): self.wait_connection = False @@ -859,6 +904,7 @@ class ConnectionHandover(): self.alt_proposal_used = False self.i_m_selector = False self.start_client_alt = False + self.terminate_on_hs_send_completion = False def start_handover_server(self, llc): summary("Start handover server") @@ -870,6 +916,19 @@ class ConnectionHandover(): self.client.close() self.client = None + def run_delayed_exit(self): + summary("Trying to exit (delayed)..") + time.sleep(0.25) + summary("Trying to exit (after wait)..") + global terminate_now + terminate_now = True + + def delayed_exit(self): + global only_one + if only_one: + self.exit_thread = threading.Thread(target=self.run_delayed_exit) + self.exit_thread.start() + def llcp_startup(llc): global handover handover.start_handover_server(llc) From f7b5a1d347b4d8dc015e3a8b7b6b05a83e92bee4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 00:48:46 +0300 Subject: [PATCH 0770/1105] dpp-nfc: Do not indicate no initial HS as failure if alt HR will be sent Do not use red color for the "No response receive" message in case another HR will be sent after this. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 3bec4573a..fcb656987 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -383,6 +383,8 @@ def run_dpp_handover_client(handover, alt=False): summary("No response received as expected since I'm the handover server") elif handover.alt_proposal_used and not alt: summary("No response received for initial proposal as expected since alternative proposal was also used") + elif handover.try_own and not alt: + summary("No response received for initial proposal as expected since alternative proposal will also be sent") else: summary("No response received", color=C_RED) run_client_alt(handover, alt) @@ -490,7 +492,6 @@ class HandoverServer(nfc.handover.HandoverServer): self.sent_carrier = None self.ho_server_processing = False self.success = False - self.try_own = False self.llc = llc self.handover = handover @@ -686,7 +687,7 @@ class HandoverServer(nfc.handover.HandoverServer): handover.hs_sent = True else: summary("Try to initiate with alternative parameters") - self.try_own = True + handover.try_own = True handover.hs_sent = False handover.no_alt_proposal = True if handover.client_thread: @@ -856,8 +857,8 @@ def llcp_worker(llc, try_alt): else: print("Wait for handover to complete - press 'i' to initiate") while not handover.wait_connection and handover.srv.sent_carrier is None: - if handover.srv.try_own: - handover.srv.try_own = False + if handover.try_own: + handover.try_own = False summary("Try to initiate another handover with own parameters") handover.my_crn_ready = False handover.my_crn = None @@ -905,6 +906,7 @@ class ConnectionHandover(): self.i_m_selector = False self.start_client_alt = False self.terminate_on_hs_send_completion = False + self.try_own = False def start_handover_server(self, llc): summary("Start handover server") From 4d546184249e4c27e514043407c2a52d96972dd0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 01:09:31 +0300 Subject: [PATCH 0771/1105] dpp-nfc: Stop only_one run after failed handover attempt Do not require connection handover to succeed before stopping the loop in the only_one case. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index fcb656987..02a7e2f45 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -907,6 +907,7 @@ class ConnectionHandover(): self.start_client_alt = False self.terminate_on_hs_send_completion = False self.try_own = False + self.connected = False def start_handover_server(self, llc): summary("Start handover server") @@ -939,6 +940,7 @@ def llcp_startup(llc): def llcp_connected(llc): summary("P2P LLCP connected") global handover + handover.connected = True handover.srv.start() if init_on_touch or not no_input: handover.client_thread = threading.Thread(target=llcp_worker, @@ -1129,8 +1131,8 @@ def main(): summary("clf.connect failed: " + str(e)) break - if only_one and handover.srv and handover.srv.success: - raise SystemExit + if only_one and handover.connected: + break except KeyboardInterrupt: raise SystemExit From 38ef655eb5a65d184ff408cec3f610fd28afa35a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 01:23:39 +0300 Subject: [PATCH 0772/1105] dpp-nfc: Report negotiated connection handover result Print out a summary of the result in yellow text. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 02a7e2f45..5c5d947f0 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -42,6 +42,7 @@ mutex = threading.Lock() C_NORMAL = '\033[0m' C_RED = '\033[91m' C_GREEN = '\033[92m' +C_YELLOW = '\033[93m' C_BLUE = '\033[94m' C_MAGENTA = '\033[95m' C_CYAN = '\033[96m' @@ -311,6 +312,7 @@ def run_dpp_handover_client(handover, alt=False): summary("Cannot start handover client - no bootstrap URI available", color=C_RED) return + handover.my_uri = uri uri = ndef.UriRecord(uri) summary("NFC URI record for DPP: " + str(uri)) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) @@ -420,6 +422,7 @@ def run_dpp_handover_client(handover, alt=False): dpp_found = True uri = carrier.data[1:].decode("utf-8") summary("DPP URI: " + uri) + handover.peer_uri = uri if test_uri: summary("TEST MODE: Fake processing") break @@ -635,6 +638,8 @@ class HandoverServer(nfc.handover.HandoverServer): if "FAIL" in data: continue summary("Own URI (post-processing): %s" % data) + handover.my_uri = data + handover.peer_uri = uri uri = ndef.UriRecord(data) summary("Own bootstrapping NFC URI record: " + str(uri)) @@ -681,6 +686,7 @@ class HandoverServer(nfc.handover.HandoverServer): handover.terminate_on_hs_send_completion = True self.success = True handover.hs_sent = True + handover.i_m_selector = True elif handover.no_alt_proposal: summary("Do not try alternative proposal anymore - handover failed", color=C_RED) @@ -907,6 +913,8 @@ class ConnectionHandover(): self.start_client_alt = False self.terminate_on_hs_send_completion = False self.try_own = False + self.my_uri = None + self.peer_uri = None self.connected = False def start_handover_server(self, llc): @@ -1132,6 +1140,16 @@ def main(): break if only_one and handover.connected: + role = "selector" if handover.i_m_selector else "requestor" + summary("Connection handover result: I'm the %s" % role, + color=C_YELLOW) + if handover.peer_uri: + summary("Peer URI: " + handover.peer_uri, color=C_YELLOW) + if handover.my_uri: + summary("My URI: " + handover.my_uri, color=C_YELLOW) + if not (handover.peer_uri and handover.my_uri): + summary("Negotiated connection handover failed", + color=C_YELLOW) break except KeyboardInterrupt: From 9d00efd8296fe1e45daf55115b3e49f46ecd8c6d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 10:09:33 +0300 Subject: [PATCH 0773/1105] tests: Skip sigma_dut_dpp_qr_resp_11 if dpp-ca.py does not exist Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index de5495199..e53be642a 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -1533,6 +1533,8 @@ def test_sigma_dut_dpp_qr_resp_10(dev, apdev): def test_sigma_dut_dpp_qr_resp_11(dev, apdev, params): """sigma_dut DPP/QR responder (conf index 11)""" + if not os.path.exists("./dpp-ca.py"): + raise HwsimSkip("dpp-ca.py not available") logdir = params['logdir'] with open("auth_serv/ec-ca.pem", "rb") as f: res = f.read() From 240e9af4d1fc46bf13edf7639ddda2bd25488e7c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 19:59:52 +0300 Subject: [PATCH 0774/1105] SAE-PK: Make no-KEK debug prints distinct Debug logs did not make it clear whether the failure happens when checking a received SAE confirm or when writing own SAE confirm. Those cases have different checks on when to go through SAE-PK processing, so it is useful to make this part clear in the debug log. Signed-off-by: Jouni Malinen --- src/common/sae_pk.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index b1c35d100..cd0ccb729 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -403,7 +403,8 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) #endif /* CONFIG_TESTING_OPTIONS */ if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { - wpa_printf(MSG_INFO, "SAE-PK: No KEK available for confirm"); + wpa_printf(MSG_INFO, + "SAE-PK: No KEK available for writing confirm"); return -1; } @@ -580,7 +581,8 @@ int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) return 0; if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { - wpa_printf(MSG_INFO, "SAE-PK: No KEK available for confirm"); + wpa_printf(MSG_INFO, + "SAE-PK: No KEK available for checking confirm"); return -1; } From 87971ff0595dc987cb47d4c61a3d07fc7af7a6d4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 20:32:35 +0300 Subject: [PATCH 0775/1105] SAE-PK: Fix SAE confirm writing in some AP cases with transition mode sae_check_confirm_pk() and sae_write_confirm_pk() were using different checks for determining whether SAE-PK was used. It was apparently possible to miss the checks in sae_write_confirm_pk() in some AP cases where SAE H2E is being used. Fix this by checking sae->pk in the write-confirm case similarly to the way this was done in check-confirm. Signed-off-by: Jouni Malinen --- src/common/sae_pk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index cd0ccb729..e839bde4e 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -389,7 +389,7 @@ int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) return -1; pk = tmp->ap_pk; - if (!pk) + if (!sae->pk || !pk) return 0; key = pk->key; From 8c936926f04e68a3ad93fd514911a055506830ac Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 31 Jul 2020 20:34:38 +0300 Subject: [PATCH 0776/1105] tests: SAE-PK with immediate confirm on AP Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 03a21c042..7feee54df 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -22,12 +22,15 @@ SAE_PK_21_PW = "a5rp-4rgd-ewum-v4qr-v5jy" SAE_PK_21_M = "2bf0a143b158b967a435cf75b07fc9e6" SAE_PK_21_PK = "MIHcAgEBBEIBcch+ygKv1uL5344C+8Rt5h8cTYHG++L3/8/hH6I2J3pWboB0jtzTf/zdZVGqkEIi+zZ2O+5g65cS8my1B44n0g+gBwYFK4EEACOhgYkDgYYABAA49TXDQfBgQWuwGrvYSkw9yuLRTn7WKyWcfSqSFfJYY6piGRE0wdKsNsGbuqHsfjn3Jb3LhmPdcnaDXd5z7fhdgAGFaiL+ZtBJCw5LqjW71rb54oy1NookDiNILdZ9i1dwBzE3fpfOWVvfjnXj9weZKUWHLB+2RF2X1qB0mY/G5NuRXA==" -def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None): +def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None, + confirm_immediate=False): params = hostapd.wpa2_params(ssid=ssid) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] if ap_groups: params['sae_groups'] = ap_groups + if confirm_immediate: + params['sae_confirm_immediate'] = '1' hapd = hostapd.add_ap(apdev, params) bssid = hapd.own_addr() @@ -283,12 +286,21 @@ def test_sae_pk_transition_disable(dev, apdev): def test_sae_pk_mixed(dev, apdev): """SAE-PK mixed deployment""" + run_sae_pk_mixed(dev, apdev) + +def test_sae_pk_mixed_immediate_confirm(dev, apdev): + """SAE-PK mixed deployment with immediate confirm on AP""" + run_sae_pk_mixed(dev, apdev, confirm_immediate=True) + +def run_sae_pk_mixed(dev, apdev, confirm_immediate=False): check_sae_pk_capab(dev[0]) dev[0].set("sae_groups", "") params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params['sae_password'] = SAE_PK_SEC2_PW + if confirm_immediate: + params['sae_confirm_immediate'] = '1' hapd = hostapd.add_ap(apdev[0], params) bssid = hapd.own_addr() @@ -401,3 +413,12 @@ def test_sae_pk_password_min_len(dev, apdev): raise if success: raise Exception("Unexpected failure with password %s" % pw) + +def test_sae_pk_confirm_immediate(dev, apdev): + """SAE-PK with immediate confirm on AP""" + check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() + dev[0].set("sae_groups", "") + + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW, + SAE_PK_SEC2_M, SAE_PK_19_PK, confirm_immediate=True) From d309dd52b0d9fff04811646d6dbecb4ee071e331 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Fri, 31 Jul 2020 20:27:05 +0530 Subject: [PATCH 0777/1105] Fix the documentation for QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE The documentation for the QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE attribute had incorrectly specified the value of 0 (corresponding to BE) to disable the QoS upgrade. BK (1) is a lower priority AC compared to BE and if BE is used to disable the upgrade, there would be no possibility for configured UDP AC upgrade to replace BK-from-DSCP with BE. Thus, correct this by specifying that the value of BK (1) is used to disable this UDP AC upgrade. Fixes: ebd5e764f99b ("Vendor attribute to configure QoS/AC upgrade for UDP frames") Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index df0053cff..72ebc0e1d 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2267,8 +2267,9 @@ enum qca_wlan_vendor_attr_config { * DSCP value configured in the frame with the intention to only upgrade * the access category. That said, it is not intended to downgrade the * access category for the frames. - * Set the value to 0 (corresponding to BE) if the QoS upgrade needs - * to be disabled. + * Set the value to QCA_WLAN_AC_BK if the QoS upgrade needs to be + * disabled, as BK is of the lowest priority and an upgrade to it does + * not result in any changes for the frames. */ QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE = 72, From b28b9dfcbf6f581ad9bbf0474e056c2090dc3a57 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 26 Jun 2020 13:49:14 +0530 Subject: [PATCH 0778/1105] OCV: OCI channel override support for testing (STA) Add override parameters to use the specified channel while populating OCI element in EAPOL-Key group msg 2/2, FT reassoc request, FILS assoc request and WNM sleep request frames. Signed-off-by: Veerendranath Jakkam --- src/rsn_supp/wpa.c | 27 +++++++++++++++++++++++++++ src/rsn_supp/wpa.h | 3 +++ src/rsn_supp/wpa_ft.c | 8 ++++++++ src/rsn_supp/wpa_i.h | 3 +++ wpa_supplicant/ctrl_iface.c | 18 ++++++++++++++++++ wpa_supplicant/wnm_sta.c | 9 +++++++++ wpa_supplicant/wpa_supplicant.c | 6 ++++++ wpa_supplicant/wpa_supplicant_i.h | 4 ++++ 8 files changed, 78 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 63171021f..7b1218f16 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2039,6 +2039,15 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, os_free(rbuf); return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->oci_freq_override_eapol_g2) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, + sm->oci_freq_override_eapol_g2); + ci.frequency = sm->oci_freq_override_eapol_g2; + } +#endif /* CONFIG_TESTING_OPTIONS */ pos = key_mic + mic_len + 2; /* Key Data */ if (ocv_insert_oci_kde(&ci, &pos) < 0) { @@ -3308,6 +3317,15 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_OCI_FREQ_EAPOL: sm->oci_freq_override_eapol = value; break; + case WPA_PARAM_OCI_FREQ_EAPOL_G2: + sm->oci_freq_override_eapol_g2 = value; + break; + case WPA_PARAM_OCI_FREQ_FT_ASSOC: + sm->oci_freq_override_ft_assoc = value; + break; + case WPA_PARAM_OCI_FREQ_FILS_ASSOC: + sm->oci_freq_override_fils_assoc = value; + break; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_DPP2 case WPA_PARAM_DPP_PFS: @@ -4565,6 +4583,15 @@ struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek, wpabuf_free(buf); return NULL; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->oci_freq_override_fils_assoc) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, + sm->oci_freq_override_fils_assoc); + ci.frequency = sm->oci_freq_override_fils_assoc; + } +#endif /* CONFIG_TESTING_OPTIONS */ pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN); if (ocv_insert_extended_oci(&ci, pos) < 0) { diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 36a17df3d..2142772d7 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -110,6 +110,9 @@ enum wpa_sm_conf_params { WPA_PARAM_FT_RSNXE_USED, WPA_PARAM_DPP_PFS, WPA_PARAM_OCI_FREQ_EAPOL, + WPA_PARAM_OCI_FREQ_EAPOL_G2, + WPA_PARAM_OCI_FREQ_FT_ASSOC, + WPA_PARAM_OCI_FREQ_FILS_ASSOC, }; struct rsn_supp_config { diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 00151df59..bcaf42fe6 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -353,6 +353,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, os_free(buf); return NULL; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->oci_freq_override_ft_assoc) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, sm->oci_freq_override_ft_assoc); + ci.frequency = sm->oci_freq_override_ft_assoc; + } +#endif /* CONFIG_TESTING_OPTIONS */ *pos++ = FTIE_SUBELEM_OCI; *pos++ = OCV_OCI_LEN; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 8d7a7a93a..96b07fc68 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -156,6 +156,9 @@ struct wpa_sm { struct wpabuf *test_assoc_ie; int ft_rsnxe_used; unsigned int oci_freq_override_eapol; + unsigned int oci_freq_override_eapol_g2; + unsigned int oci_freq_override_ft_assoc; + unsigned int oci_freq_override_fils_assoc; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_FILS diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 8d2ccbae5..6dfce2aaa 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -757,6 +757,20 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, wpa_s->oci_freq_override_saquery_req = atoi(value); } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) { wpa_s->oci_freq_override_saquery_resp = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) { + wpa_s->oci_freq_override_eapol_g2 = atoi(value); + /* Populate value to wpa_sm if already associated. */ + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2, + wpa_s->oci_freq_override_eapol_g2); + } else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) { + wpa_s->oci_freq_override_ft_assoc = atoi(value); + /* Populate value to wpa_sm if already associated. */ + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC, + wpa_s->oci_freq_override_ft_assoc); + } else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) { + wpa_s->oci_freq_override_fils_assoc = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) { + wpa_s->oci_freq_override_wnm_sleep = atoi(value); } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) { wpabuf_free(wpa_s->rsne_override_eapol); if (os_strcmp(value, "NULL") == 0) @@ -8438,6 +8452,10 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->oci_freq_override_eapol = 0; wpa_s->oci_freq_override_saquery_req = 0; wpa_s->oci_freq_override_saquery_resp = 0; + wpa_s->oci_freq_override_eapol_g2 = 0; + wpa_s->oci_freq_override_ft_assoc = 0; + wpa_s->oci_freq_override_fils_assoc = 0; + wpa_s->oci_freq_override_wnm_sleep = 0; #ifdef CONFIG_DPP os_free(wpa_s->dpp_config_obj_override); wpa_s->dpp_config_obj_override = NULL; diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 411ce886d..d0c9f0f45 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -121,6 +121,15 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s, os_free(wnmtfs_ie); return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->oci_freq_override_wnm_sleep) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, + wpa_s->oci_freq_override_wnm_sleep); + ci.frequency = wpa_s->oci_freq_override_wnm_sleep; + } +#endif /* CONFIG_TESTING_OPTIONS */ oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie = os_zalloc(oci_ie_len); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index bda9fe5e4..51e5321e0 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1651,6 +1651,12 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_s->ft_rsnxe_used); wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL, wpa_s->oci_freq_override_eapol); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2, + wpa_s->oci_freq_override_eapol_g2); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC, + wpa_s->oci_freq_override_ft_assoc); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC, + wpa_s->oci_freq_override_fils_assoc); #endif /* CONFIG_TESTING_OPTIONS */ /* Extended Key ID is only supported in infrastructure BSS so far */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index d845ae2ae..6dff477bf 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1152,6 +1152,10 @@ struct wpa_supplicant { unsigned int oci_freq_override_eapol; unsigned int oci_freq_override_saquery_req; unsigned int oci_freq_override_saquery_resp; + unsigned int oci_freq_override_eapol_g2; + unsigned int oci_freq_override_ft_assoc; + unsigned int oci_freq_override_fils_assoc; + unsigned int oci_freq_override_wnm_sleep; #endif /* CONFIG_TESTING_OPTIONS */ struct wmm_ac_assoc_data *wmm_ac_assoc_info; From 5579da7d5f7f0489e548ab95ae186a8fa718a8c4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 3 Aug 2020 11:44:53 +0300 Subject: [PATCH 0779/1105] tests: sigma_dut and WPA3 frame inject Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index e53be642a..58143d560 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -5112,3 +5112,35 @@ def test_sigma_dut_client_privacy(dev, apdev, params): res = out.splitlines() if len(res) > 0: raise Exception("Permanent address used unexpectedly") + +def test_sigma_dut_wpa3_inject_frame(dev, apdev): + """sigma_dut and WPA3 frame inject""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params["ocv"] = "1" + params['sae_groups'] = '19 20 21' + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ocvc,1" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + sigma_dut_wait_connected(ifname) + sigma_dut_cmd("dev_send_frame,interface,%s,program,WPA3,framename,SAQueryReq,OCIChannel,2" % ifname) + sigma_dut_cmd("dev_send_frame,interface,%s,program,WPA3,framename,SAQueryReq,OCIChannel,1" % ifname) + sigma_dut_cmd("dev_send_frame,interface,%s,program,WPA3,framename,ReassocReq" % ifname) + hwsim_utils.test_connectivity(dev[0], hapd) + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) From 2f858254ccf8f71e8cac76f07a552d57e309796e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 3 Aug 2020 15:38:30 +0300 Subject: [PATCH 0780/1105] Extend GET_PMK to check PMKSA cache on the AP This allows the testing command GET_PMK to return a PMK in cases where the association fails (e.g., when using SAE and getting a valid PMKSA entry added before association) or after the association has been lost. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index b470c5643..ae63acd47 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -47,6 +47,7 @@ #include "ap/ap_config.h" #include "ap/ieee802_1x.h" #include "ap/wpa_auth.h" +#include "ap/pmksa_cache_auth.h" #include "ap/ieee802_11.h" #include "ap/sta_info.h" #include "ap/wps_hostapd.h" @@ -2456,6 +2457,19 @@ static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd, } +static int hostapd_ctrl_get_pmksa_pmk(struct hostapd_data *hapd, const u8 *addr, + char *buf, size_t buflen) +{ + struct rsn_pmksa_cache_entry *pmksa; + + pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, addr, NULL); + if (!pmksa) + return -1; + + return wpa_snprintf_hex(buf, buflen, pmksa->pmk, pmksa->pmk_len); +} + + static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd, char *buf, size_t buflen) { @@ -2471,13 +2485,13 @@ static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd, if (!sta || !sta->wpa_sm) { wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR, MAC2STR(addr)); - return -1; + return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen); } pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); - if (!pmk) { + if (!pmk || !pmk_len) { wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR, MAC2STR(addr)); - return -1; + return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen); } return wpa_snprintf_hex(buf, buflen, pmk, pmk_len); From 02f4946172dea335d1ed7fde7e8de3ebbdef859a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 3 Aug 2020 15:39:45 +0300 Subject: [PATCH 0781/1105] tests: SAE with OCV and fetching PMK Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae.py | 65 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index 3722cd427..3ab29be80 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -2605,3 +2605,68 @@ def test_sae_pmf_roam(dev, apdev): dev[0].roam(bssid) dev[0].dump_monitor() + +def test_sae_ocv_pmk(dev, apdev): + """SAE with OCV and fetching PMK (successful 4-way handshake)""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", + passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params['ieee80211w'] = '2' + params['ocv'] = '1' + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].set("sae_groups", "") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ocv="1", + ieee80211w="2", scan_freq="2412") + hapd.wait_sta() + + pmk_h = hapd.request("GET_PMK " + dev[0].own_addr()) + if "FAIL" in pmk_h or len(pmk_h) == 0: + raise Exception("Failed to fetch PMK from hostapd during a successful authentication") + + pmk_w = dev[0].get_pmk(id) + if pmk_h != pmk_w: + raise Exception("Fetched PMK does not match: hostapd %s, wpa_supplicant %s" % (pmk_h, pmk_w)) + +def test_sae_ocv_pmk_failure(dev, apdev): + """SAE with OCV and fetching PMK (failed 4-way handshake)""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", + passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params['ieee80211w'] = '2' + params['ocv'] = '1' + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].set("sae_groups", "") + dev[0].set("oci_freq_override_eapol", "2462") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ocv="1", + ieee80211w="2", scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=15) + if ev is None: + raise Exception("No connection result reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + + pmk_h = hapd.request("GET_PMK " + dev[0].own_addr()) + if "FAIL" in pmk_h or len(pmk_h) == 0: + raise Exception("Failed to fetch PMK from hostapd during a successful authentication") + + res = dev[0].request("PMKSA_GET %d" % id) + if not res.startswith(hapd.own_addr()): + raise Exception("PMKSA from wpa_supplicant does not have matching BSSID") + pmk_w = res.split(' ')[2] + if pmk_h != pmk_w: + raise Exception("Fetched PMK does not match: hostapd %s, wpa_supplicant %s" % (pmk_h, pmk_w)) + + dev[0].request("DISCONNECT") + time.sleep(0.1) + pmk_h2 = hapd.request("GET_PMK " + dev[0].own_addr()) + res = dev[0].request("PMKSA_GET %d" % id) + pmk_w2 = res.split(' ')[2] + if pmk_h2 != pmk_h: + raise Exception("hostapd did not report correct PMK after disconnection") + if pmk_w2 != pmk_w: + raise Exception("wpa_supplicant did not report correct PMK after disconnection") From 0a9d7b169ed7bbbc0c73d57af231c49b2f43ed6f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 5 Aug 2020 17:44:32 +0300 Subject: [PATCH 0782/1105] SAE-PK: Update design for fingerprint encoding into password Update the SAE-PK implementation to match the changes in the protocol design: - allow only Sec values 3 and 5 and encode this as a single bit field with multiple copies - add a checksum character Signed-off-by: Jouni Malinen --- hostapd/sae_pk_gen.c | 70 +++++-- src/common/common_module_tests.c | 15 +- src/common/sae.c | 3 - src/common/sae.h | 8 +- src/common/sae_pk.c | 326 +++++++++++++++++++++++++------ tests/hwsim/test_sae_pk.py | 135 +++++-------- tests/hwsim/test_sigma_dut.py | 84 ++++---- 7 files changed, 428 insertions(+), 213 deletions(-) diff --git a/hostapd/sae_pk_gen.c b/hostapd/sae_pk_gen.c index 6570e9ed9..c31eff75b 100644 --- a/hostapd/sae_pk_gen.c +++ b/hostapd/sae_pk_gen.c @@ -25,11 +25,15 @@ int main(int argc, char *argv[]) char *b64 = NULL, *pw = NULL, *pos, *src; int sec, j; int ret = -1; - u8 hash[SAE_MAX_HASH_LEN], fingerprint[SAE_MAX_HASH_LEN]; + u8 hash[SAE_MAX_HASH_LEN]; + char hash_hex[2 * SAE_MAX_HASH_LEN + 1]; + u8 pw_base_bin[SAE_MAX_HASH_LEN]; + u8 *dst; int group; size_t hash_len; unsigned long long i, expected; char m_hex[2 * SAE_PK_M_LEN + 1]; + u32 sec_1b, val20; wpa_debug_level = MSG_INFO; if (os_program_init() < 0) @@ -37,15 +41,17 @@ int main(int argc, char *argv[]) if (argc != 4) { fprintf(stderr, - "usage: sae_pk_gen \n"); + "usage: sae_pk_gen \n"); goto fail; } sec = atoi(argv[2]); - if (sec < 2 || sec > 5) { - fprintf(stderr, "Invalid Sec value (allowed range: 2..5)\n"); + if (sec != 3 && sec != 5) { + fprintf(stderr, + "Invalid Sec value (allowed values: 3 and 5)\n"); goto fail; } + sec_1b = sec == 3; expected = 1; for (j = 0; j < sec; j++) expected *= 256; @@ -106,7 +112,7 @@ int main(int argc, char *argv[]) goto fail; } if (hash[0] == 0 && hash[1] == 0) { - if (sec == 2 || (hash[2] & 0xf0) == 0) + if ((hash[2] & 0xf0) == 0) fprintf(stderr, "\r%3.2f%%", 100.0 * (double) i / (double) expected); for (j = 2; j < sec; j++) { @@ -119,18 +125,14 @@ int main(int argc, char *argv[]) inc_byte_array(m, SAE_PK_M_LEN); } - fprintf(stderr, "\nFound a valid hash in %llu iterations\n", i); - wpa_hexdump(MSG_DEBUG, "Valid hash", hash, hash_len); - fingerprint[0] = (sec - 2) << 6 | hash[sec] >> 2; - for (i = 1; i < hash_len - sec; i++) - fingerprint[i] = hash[sec + i - 1] << 6 | hash[sec + i] >> 2; - wpa_hexdump(MSG_DEBUG, "Fingerprint part for password", - fingerprint, hash_len - sec); + if (wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0 || + wpa_snprintf_hex(hash_hex, sizeof(hash_hex), hash, hash_len) < 0) + goto fail; + fprintf(stderr, "\nFound a valid hash in %llu iterations: %s\n", + i + 1, hash_hex); b64 = base64_encode(der, der_len, NULL); - pw = sae_pk_base32_encode(fingerprint, (hash_len - sec) * 8 - 2); - if (!b64 || !pw || - wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0) + if (!b64) goto fail; src = pos = b64; while (*src) { @@ -140,10 +142,44 @@ int main(int argc, char *argv[]) } *pos = '\0'; + /* Skip 8*Sec bits and add Sec_1b as the every 20th bit starting with + * one. */ + os_memset(pw_base_bin, 0, sizeof(pw_base_bin)); + dst = pw_base_bin; + for (j = 0; j < 8 * (int) hash_len / 20; j++) { + val20 = sae_pk_get_be19(hash + sec); + val20 |= sec_1b << 19; + sae_pk_buf_shift_left_19(hash + sec, hash_len - sec); + + if (j & 1) { + *dst |= (val20 >> 16) & 0x0f; + dst++; + *dst++ = (val20 >> 8) & 0xff; + *dst++ = val20 & 0xff; + } else { + *dst++ = (val20 >> 12) & 0xff; + *dst++ = (val20 >> 4) & 0xff; + *dst = (val20 << 4) & 0xf0; + } + } + if (wpa_snprintf_hex(hash_hex, sizeof(hash_hex), + pw_base_bin, hash_len - sec) >= 0) + fprintf(stderr, "PasswordBase binary data for base32: %s", + hash_hex); + + pw = sae_pk_base32_encode(pw_base_bin, 20 * 3 - 5); + if (!pw) + goto fail; + printf("# SAE-PK password/M/private key for Sec=%d.\n", sec); - printf("# The password can be truncated from right to improve\n"); - printf("# usability at the cost of security.\n"); printf("sae_password=%s|pk=%s:%s\n", pw, m_hex, b64); + printf("# Longer passwords can be used for improved security at the cost of usability:\n"); + for (j = 4; j <= ((int) hash_len * 8 + 5 - 8 * sec) / 19; j++) { + os_free(pw); + pw = sae_pk_base32_encode(pw_base_bin, 20 * j - 5); + if (pw) + printf("# %s\n", pw); + } ret = 0; fail: diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c index 2af179b42..00308d41e 100644 --- a/src/common/common_module_tests.c +++ b/src/common/common_module_tests.c @@ -551,19 +551,14 @@ fail: static int sae_pk_tests(void) { #ifdef CONFIG_SAE_PK - const char *invalid[] = { "a2bc-de3f-ghi4-", "a2bcde3fghi4", "", NULL }; + const char *invalid[] = { "a2bc-de3f-ghim-", "a2bcde3fghim", "", NULL }; struct { const char *pw; const u8 *val; } valid[] = { - { "a2bc-de3f-ghi4", (u8 *) "\x06\x82\x21\x93\x65\x31\xd1\xc0" }, - { "aaaa-aaaa-aaaa-a", - (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00" }, - { "aaaa-aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00" }, - { "7777-7777-777", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe" }, - { "7777-7777-7777", (u8 *) "\xff\xff\xff\xff\xff\xff\xff\xf0" }, - { "7777-7777-7777-7", - (u8 *) "\xff\xff\xff\xff\xff\xff\xff\xff\x80" }, + { "a2bc-de3f-ghim", (u8 *) "\x06\x82\x21\x93\x65\x31\xd0\xc0" }, + { "aaaa-aaaa-aaaj", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x90" }, + { "7777-7777-777f", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe\x50" }, { NULL, NULL } }; int i; @@ -617,7 +612,7 @@ static int sae_pk_tests(void) } os_free(res); - b32 = sae_pk_base32_encode(val, bits); + b32 = sae_pk_base32_encode(val, bits - 5); if (!b32) { wpa_printf(MSG_ERROR, "SAE-PK: Failed to encode password '%s'", diff --git a/src/common/sae.c b/src/common/sae.c index 77f3a0e8c..72b5f3fab 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -112,9 +112,6 @@ void sae_clear_temp_data(struct sae_data *sae) wpabuf_free(tmp->own_rejected_groups); wpabuf_free(tmp->peer_rejected_groups); os_free(tmp->pw_id); -#ifdef CONFIG_SAE_PK - bin_clear_free(tmp->pw, tmp->pw_len); -#endif /* CONFIG_SAE_PK */ bin_clear_free(tmp, sizeof(*tmp)); sae->tmp = NULL; } diff --git a/src/common/sae.h b/src/common/sae.h index ee3c662c5..2243c0f33 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -70,9 +70,11 @@ struct sae_temporary_data { const struct sae_pk *ap_pk; u8 own_addr[ETH_ALEN]; u8 peer_addr[ETH_ALEN]; - u8 *pw; - size_t pw_len; + u8 fingerprint[SAE_MAX_HASH_LEN]; + size_t fingerprint_bytes; + size_t fingerprint_bits; size_t lambda; + unsigned int sec; u8 ssid[32]; size_t ssid_len; #ifdef CONFIG_TESTING_OPTIONS @@ -164,5 +166,7 @@ struct sae_pk * sae_parse_pk(const char *val); int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf); int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len); int sae_hash(size_t hash_len, const u8 *data, size_t len, u8 *hash); +u32 sae_pk_get_be19(const u8 *buf); +void sae_pk_buf_shift_left_19(u8 *buf, size_t len); #endif /* SAE_H */ diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c index e839bde4e..df79e5f2c 100644 --- a/src/common/sae_pk.c +++ b/src/common/sae_pk.c @@ -23,40 +23,173 @@ static const char *sae_pk_base32_table = "abcdefghijklmnopqrstuvwxyz234567"; +static const u8 d_mult_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, + 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, + 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, + 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, + 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, + 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, + 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, + 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, + 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, + 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, + 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, + 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, + 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, + 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, + 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, + 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, + 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, + 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, + 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, + 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, + 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, + 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +}; + +static const u8 d_perm_table[] = { + 7, 2, 1, 30, 16, 20, 27, 11, 31, 6, 8, 13, 29, 5, 10, 21, + 22, 3, 24, 0, 23, 25, 12, 9, 28, 14, 4, 15, 17, 18, 19, 26 +}; + + +static u8 d_permute(u8 val, unsigned int iter) +{ + if (iter == 0) + return val; + return d_permute(d_perm_table[val], iter - 1); +} + + +static u8 d_invert(u8 val) +{ + if (val > 0 && val < 16) + return 16 - val; + return val; +} + + +static char d_check_char(const char *str, size_t len) +{ + size_t i; + u8 val = 0; + u8 dtable[256]; + unsigned int iter = 1; + int j; + + os_memset(dtable, 0x80, 256); + for (i = 0; sae_pk_base32_table[i]; i++) + dtable[(u8) sae_pk_base32_table[i]] = i; + + for (j = len - 1; j >= 0; j--) { + u8 c, p; + + c = dtable[(u8) str[j]]; + if (c == 0x80) + continue; + p = d_permute(c, iter); + iter++; + val = d_mult_table[val * 32 + p]; + } + + return sae_pk_base32_table[d_invert(val)]; +} + + bool sae_pk_valid_password(const char *pw) { - int pos, sec; - const char *idx; - size_t pw_len = os_strlen(pw); + int pos; + size_t i, pw_len = os_strlen(pw); + u8 sec_1b; + u8 dtable[256]; - /* Check whether the password is long enough to meet the minimum - * required resistance to preimage attacks. This makes it less likely to - * recognize non-SAE-PK passwords as suitable for SAE-PK. */ - if (pw_len < 1) + os_memset(dtable, 0x80, 256); + for (i = 0; sae_pk_base32_table[i]; i++) + dtable[(u8) sae_pk_base32_table[i]] = i; + + /* SAE-PK password has at least three four character components + * separated by hyphens. */ + if (pw_len < 14 || pw_len % 5 != 4) { + wpa_printf(MSG_DEBUG, "SAE-PK: Not a valid password (length)"); return false; - /* Fetch Sec from the two MSBs */ - idx = os_strchr(sae_pk_base32_table, pw[0]); - if (!idx) - return false; - sec = (((u8) ((idx - sae_pk_base32_table) & 0x1f)) >> 3) + 2; - if ((sec == 2 && pw_len < 14) || - (sec == 3 && pw_len < 13) || - (sec == 4 && pw_len < 11) || - (sec == 5 && pw_len < 9)) - return false; /* too short password */ + } for (pos = 0; pw[pos]; pos++) { if (pos && pos % 5 == 4) { - if (pw[pos] != '-') + if (pw[pos] != '-') { + wpa_printf(MSG_DEBUG, + "SAE-PK: Not a valid password (separator)"); return false; + } continue; } - if (!os_strchr(sae_pk_base32_table, pw[pos])) + if (dtable[(u8) pw[pos]] == 0x80) { + wpa_printf(MSG_DEBUG, + "SAE-PK: Not a valid password (character)"); return false; + } } - if (pos == 0) + + /* Verify that the checksum character is valid */ + if (pw[pw_len - 1] != d_check_char(pw, pw_len - 1)) { + wpa_printf(MSG_DEBUG, + "SAE-PK: Not a valid password (checksum)"); return false; - return pw[pos - 1] != '-'; + } + + /* Verify that Sec_1b bits match */ + sec_1b = dtable[(u8) pw[0]] & BIT(4); + for (i = 5; i < pw_len; i += 5) { + if (sec_1b != (dtable[(u8) pw[i]] & BIT(4))) { + wpa_printf(MSG_DEBUG, + "SAE-PK: Not a valid password (Sec_1b)"); + return false; + } + } + return true; } @@ -76,6 +209,7 @@ static char * add_char(const char *start, char *pos, u8 idx, size_t *bits) } +/* Base32 encode a password and add hyper separators and checksum */ char * sae_pk_base32_encode(const u8 *src, size_t len_bits) { char *out, *pos; @@ -90,7 +224,7 @@ char * sae_pk_base32_encode(const u8 *src, size_t len_bits) return NULL; olen = len * 8 / 5 + 1; olen += olen / 4; /* hyphen separators */ - pos = out = os_zalloc(olen + 1); + pos = out = os_zalloc(olen + 2); /* include room for ChkSum and nul */ if (!out) return NULL; @@ -107,6 +241,8 @@ char * sae_pk_base32_encode(const u8 *src, size_t len_bits) } } + *pos = d_check_char(out, os_strlen(out)); + return out; } @@ -178,19 +314,107 @@ u8 * sae_pk_base32_decode(const char *src, size_t len, size_t *out_len) } +u32 sae_pk_get_be19(const u8 *buf) +{ + return (buf[0] << 11) | (buf[1] << 3) | (buf[2] >> 5); +} + + +/* shift left by two octets and three bits; fill in zeros from right; + * len must be at least three */ +void sae_pk_buf_shift_left_19(u8 *buf, size_t len) +{ + u8 *dst, *src, *end; + + dst = buf; + src = buf + 2; + end = buf + len; + + while (src + 1 < end) { + *dst++ = (src[0] << 3) | (src[1] >> 5); + src++; + } + *dst++ = *src << 3; + *dst++ = 0; + *dst++ = 0; +} + + +static void sae_pk_buf_shift_left_1(u8 *buf, size_t len) +{ + u8 *dst, *src, *end; + + dst = buf; + src = buf; + end = buf + len; + + while (src + 1 < end) { + *dst++ = (src[0] << 1) | (src[1] >> 7); + src++; + } + *dst++ = *src << 1; +} + + int sae_pk_set_password(struct sae_data *sae, const char *password) { struct sae_temporary_data *tmp = sae->tmp; - size_t len; + size_t len, pw_len; + u8 *pw, *pos; + int bits; + u32 val = 0, val19; + unsigned int val_bits = 0; - len = os_strlen(password); - if (!tmp || len < 1) + if (!tmp) return -1; - bin_clear_free(tmp->pw, tmp->pw_len); - tmp->pw = sae_pk_base32_decode(password, len, &tmp->pw_len); + os_memset(tmp->fingerprint, 0, sizeof(tmp->fingerprint)); + tmp->fingerprint_bytes = tmp->fingerprint_bits = 0; + + len = os_strlen(password); + if (len < 1 || !sae_pk_valid_password(password)) + return -1; + + pw = sae_pk_base32_decode(password, len, &pw_len); + if (!pw) + return -1; + + tmp->sec = (pw[0] & BIT(7)) ? 3 : 5; tmp->lambda = len - len / 5; - return tmp->pw ? 0 : -1; + tmp->fingerprint_bits = 8 * tmp->sec + 19 * tmp->lambda / 4 - 5; + wpa_printf(MSG_DEBUG, "SAE-PK: Sec=%u Lambda=%zu fingerprint_bits=%zu", + tmp->sec, tmp->lambda, tmp->fingerprint_bits); + + /* Construct Fingerprint from PasswordBase by prefixing with Sec zero + * octets and skipping the Sec_1b bits */ + pos = &tmp->fingerprint[tmp->sec]; + bits = tmp->fingerprint_bits - 8 * tmp->sec; + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: PasswordBase", pw, pw_len); + while (bits > 0) { + if (val_bits < 8) { + sae_pk_buf_shift_left_1(pw, pw_len); /* Sec_1b */ + val19 = sae_pk_get_be19(pw); + sae_pk_buf_shift_left_19(pw, pw_len); + val = (val << 19) | val19; + val_bits += 19; + } + if (val_bits >= 8) { + if (bits < 8) + break; + *pos++ = (val >> (val_bits - 8)) & 0xff; + val_bits -= 8; + bits -= 8; + } + } + if (bits > 0) { + val >>= val_bits - bits; + *pos++ = val << (8 - bits); + } + tmp->fingerprint_bytes = pos - tmp->fingerprint; + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Fingerprint", + tmp->fingerprint, tmp->fingerprint_bytes); + bin_clear_free(pw, pw_len); + return 0; } @@ -481,19 +705,19 @@ static bool sae_pk_valid_fingerprint(struct sae_data *sae, const u8 *k_ap, size_t k_ap_len, int group) { struct sae_temporary_data *tmp = sae->tmp; - size_t sec, i; - u8 *fingerprint_exp, *hash_data, *pos; - size_t hash_len, hash_data_len, fingerprint_bits, fingerprint_bytes; + u8 *hash_data, *pos; + size_t hash_len, hash_data_len; u8 hash[SAE_MAX_HASH_LEN]; int res; - if (!tmp->pw || tmp->pw_len < 1) { + if (!tmp->fingerprint_bytes) { wpa_printf(MSG_DEBUG, "SAE-PK: No PW available for K_AP fingerprint check"); return false; } - /* Fingerprint = L(Hash(SSID || M || K_AP), 0, 8*Sec + 5*Lambda - 2) */ + /* Fingerprint = L(Hash(SSID || M || K_AP), 0, 8*Sec + 19*Lambda/4 - 5) + */ hash_len = sae_group_2_hash_len(group); hash_data_len = tmp->ssid_len + m_len + k_ap_len; @@ -516,44 +740,26 @@ static bool sae_pk_valid_fingerprint(struct sae_data *sae, wpa_hexdump(MSG_DEBUG, "SAE-PK: Hash(SSID || M || K_AP)", hash, hash_len); - wpa_hexdump_key(MSG_DEBUG, "SAE-PK: PW", tmp->pw, tmp->pw_len); - sec = (tmp->pw[0] >> 6) + 2; - fingerprint_bits = 8 * sec + 5 * tmp->lambda - 2; - wpa_printf(MSG_DEBUG, "SAE-PK: Sec=%zu Lambda=%zu fingerprint_bits=%zu", - sec, tmp->lambda, fingerprint_bits); - if (fingerprint_bits > hash_len * 8) { + if (tmp->fingerprint_bits > hash_len * 8) { wpa_printf(MSG_INFO, "SAE-PK: Not enough hash output bits for the fingerprint"); return false; } - fingerprint_bytes = (fingerprint_bits + 7) / 8; - if (fingerprint_bits % 8) { + if (tmp->fingerprint_bits % 8) { size_t extra; /* Zero out the extra bits in the last octet */ - extra = 8 - fingerprint_bits % 8; - pos = &hash[fingerprint_bits / 8]; + extra = 8 - tmp->fingerprint_bits % 8; + pos = &hash[tmp->fingerprint_bits / 8]; *pos = (*pos >> extra) << extra; } - wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint", hash, fingerprint_bytes); - - fingerprint_exp = os_zalloc(sec + tmp->pw_len); - if (!fingerprint_exp) - return false; - pos = fingerprint_exp + sec; - for (i = 0; i < tmp->pw_len; i++) { - u8 next = i + 1 < tmp->pw_len ? tmp->pw[i + 1] : 0; - - *pos++ = tmp->pw[i] << 2 | next >> 6; - } - - wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint_Expected", - fingerprint_exp, fingerprint_bytes); - res = os_memcmp_const(hash, fingerprint_exp, fingerprint_bytes); - bin_clear_free(fingerprint_exp, tmp->pw_len); - + wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint", hash, + tmp->fingerprint_bytes); + res = os_memcmp_const(hash, tmp->fingerprint, tmp->fingerprint_bytes); if (res) { wpa_printf(MSG_DEBUG, "SAE-PK: K_AP fingerprint mismatch"); + wpa_hexdump(MSG_DEBUG, "SAE-PK: Expected fingerprint", + tmp->fingerprint, tmp->fingerprint_bytes); return false; } diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 7feee54df..e01b5a3bd 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -9,18 +9,17 @@ from utils import * SAE_PK_SSID = "SAE-PK test" -SAE_PK_SEC2_PW = "dwxm-zv66-p5ue" -SAE_PK_SEC2_PW_FULL = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-qleg" -SAE_PK_SEC2_M = "431ff8322f93b9dc50ded9f3d14ace22" +SAE_PK_SEC3_PW = "r6cr-6ksa-56og" +SAE_PK_SEC3_M = "089ec11475d55f0d38403f5117a6d64d" SAE_PK_19_PK = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" -SAE_PK_20_PW = "f3bh-5un3-wz7o-al3p" -SAE_PK_20_M = "50bf37ba0033ed110a74e3a7aa52f4e9" +SAE_PK_20_PW = "4zsy-uspe-xbfr-3ifo" +SAE_PK_20_M = "206902f9f09b62e3fafcd487c65f5c64" SAE_PK_20_PK = "MIGkAgEBBDA4wpA6w/fK0g3a2V6QmcoxNoFCVuQPyzWvKYimJkgXsVsXt2ERXQ7dGOVXeycM5DqgBwYFK4EEACKhZANiAARTdszGBNe2PGCnc8Wvs+IDvdVEf4PPBrty0meRZf6UTbGouquTHpy6KKTq5sxrulYzsQFimg4op0UJBGxAzqo0EtTgMlLiBvY0I3Nl3N69MhWo8nvnmguvGGN32AAPXpQ=" -SAE_PK_21_PW = "a5rp-4rgd-ewum-v4qr-v5jy" -SAE_PK_21_M = "2bf0a143b158b967a435cf75b07fc9e6" -SAE_PK_21_PK = "MIHcAgEBBEIBcch+ygKv1uL5344C+8Rt5h8cTYHG++L3/8/hH6I2J3pWboB0jtzTf/zdZVGqkEIi+zZ2O+5g65cS8my1B44n0g+gBwYFK4EEACOhgYkDgYYABAA49TXDQfBgQWuwGrvYSkw9yuLRTn7WKyWcfSqSFfJYY6piGRE0wdKsNsGbuqHsfjn3Jb3LhmPdcnaDXd5z7fhdgAGFaiL+ZtBJCw5LqjW71rb54oy1NookDiNILdZ9i1dwBzE3fpfOWVvfjnXj9weZKUWHLB+2RF2X1qB0mY/G5NuRXA==" +SAE_PK_21_PW = "vluk-umpa-3mbw-zrhe-s2n2" +SAE_PK_21_M = "1c63c1b17e9a999f0693b4341a970a63" +SAE_PK_21_PK = "MIHcAgEBBEIBnFBjU0ywxo1dLTYcg2aZdMfNY7JHt4GTADRTgJ7RRo9qzRIlfmK7p+BP1c8YM8ia8v7YDTut00rDOfzkdmLOi0WgBwYFK4EEACOhgYkDgYYABAD6n3DHI+qaj/lElhe2sUSKqAe4sweckMlr9bhdmwp8Wsx5lKR/Tt7WPexeqFrA47nChw5WMWy6qJanCKNFvGYG0ADUWnxesYczGtCdUYJQgs3X5tHSapMssz6tP8QL0X9adTI/H3tFYhiVIdor03eZDUVnej78/F31CcHcjGBEyItVfw==" def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None, confirm_immediate=False): @@ -54,11 +53,18 @@ def test_sae_pk(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "") - for i in range(14, len(SAE_PK_SEC2_PW_FULL) + 1): - p = SAE_PK_SEC2_PW_FULL[:i] - if p.endswith('-'): - continue - run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, p, SAE_PK_SEC2_M, + passwords = [SAE_PK_SEC3_PW, + "r6cr-6ksa-56oo-5557", + "r6cr-6ksa-56oo-555p-wi44", + "r6cr-6ksa-56oo-555p-wi4b-vghb", + "r6cr-6ksa-56oo-555p-wi4b-vghv-vwro", + "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taqj", + "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taq5-4zfq", + "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taq5-4zfa-ye3x", + "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taq5-4zfa-ye35-4rne", + "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taq5-4zfa-ye35-4rny-5yqz"] + for p in passwords: + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, p, SAE_PK_SEC3_M, SAE_PK_19_PK) def test_sae_pk_group_negotiation(dev, apdev): @@ -68,39 +74,19 @@ def test_sae_pk_group_negotiation(dev, apdev): dev[0].set("sae_groups", "20 19") try: - run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW, - SAE_PK_SEC2_M, SAE_PK_19_PK, ap_groups="19 20") + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW, + SAE_PK_SEC3_M, SAE_PK_19_PK, ap_groups="19 20") finally: dev[0].set("sae_groups", "") -def test_sae_pk_sec_2(dev, apdev): - """SAE-PK with Sec 2""" - check_sae_pk_capab(dev[0]) - dev[0].flush_scan_cache() - dev[0].set("sae_groups", "") - - run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW, - SAE_PK_SEC2_M, SAE_PK_19_PK) - def test_sae_pk_sec_3(dev, apdev): """SAE-PK with Sec 3""" check_sae_pk_capab(dev[0]) dev[0].flush_scan_cache() dev[0].set("sae_groups", "") - pw = "iian-qey6-pu5t" - m = "128e51ddb5e2e24388f9ed14b687e2eb" - run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK) - -def test_sae_pk_sec_4(dev, apdev): - """SAE-PK with Sec 4""" - check_sae_pk_capab(dev[0]) - dev[0].flush_scan_cache() - dev[0].set("sae_groups", "") - - pw = "ssko-2lmu-7hzs-bqct" - m = "a5e38c7251ea310cc348fbcdadfa8bcb" - run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK) + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW, SAE_PK_SEC3_M, + SAE_PK_19_PK) def test_sae_pk_sec_5(dev, apdev): """SAE-PK with Sec 5""" @@ -108,7 +94,7 @@ def test_sae_pk_sec_5(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "") - pw = "3qqu-f4xq-dz37-fes3-fbgc" + pw = "hbbi-f4xq-b457-jjew-muei" m = "d2e5fa27d1be8897f987f2d480d2af6b" run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK) @@ -164,8 +150,8 @@ def test_sae_pk_group_19_sae_group_20(dev, apdev): dev[0].flush_scan_cache() dev[0].set("sae_groups", "20") try: - run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW, - SAE_PK_SEC2_M, SAE_PK_19_PK, ap_groups="20") + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW, + SAE_PK_SEC3_M, SAE_PK_19_PK, ap_groups="20") finally: dev[0].set("sae_groups", "") @@ -176,10 +162,10 @@ def test_sae_pk_password_without_pk(dev, apdev): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = SAE_PK_SEC2_PW + params['sae_password'] = SAE_PK_SEC3_PW hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", scan_freq="2412") if dev[0].get_status_field("sae_pk") != "0": raise Exception("Unexpected sae_pk STATUS value") @@ -191,10 +177,10 @@ def test_sae_pk_only(dev, apdev): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = SAE_PK_SEC2_PW + params['sae_password'] = SAE_PK_SEC3_PW hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", sae_pk="1", scan_freq="2412", wait_connect=False) ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", @@ -208,7 +194,7 @@ def test_sae_pk_only(dev, apdev): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M, SAE_PK_19_PK)] hapd2 = hostapd.add_ap(apdev[1], params) bssid2 = hapd2.own_addr() @@ -229,13 +215,13 @@ def test_sae_pk_modes(dev, apdev): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' params["ieee80211w"] = "2" - params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M, SAE_PK_19_PK)] hapd = hostapd.add_ap(apdev[0], params) tests = [(2, 0), (1, 1), (0, 1)] for sae_pk, expected in tests: - dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", sae_pk=str(sae_pk), ieee80211w="2", scan_freq="2412") val = dev[0].get_status_field("sae_pk") @@ -252,10 +238,10 @@ def test_sae_pk_not_on_ap(dev, apdev): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = SAE_PK_SEC2_PW + params['sae_password'] = SAE_PK_SEC3_PW hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", scan_freq="2412") if dev[0].get_status_field("sae_pk") == "1": raise Exception("SAE-PK was claimed to be used") @@ -267,12 +253,12 @@ def test_sae_pk_transition_disable(dev, apdev): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M, SAE_PK_19_PK)] params['transition_disable'] = '0x02' hapd = hostapd.add_ap(apdev[0], params) - id = dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, + id = dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", scan_freq="2412") ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) if ev is None: @@ -298,7 +284,7 @@ def run_sae_pk_mixed(dev, apdev, confirm_immediate=False): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = SAE_PK_SEC2_PW + params['sae_password'] = SAE_PK_SEC3_PW if confirm_immediate: params['sae_confirm_immediate'] = '1' hapd = hostapd.add_ap(apdev[0], params) @@ -306,7 +292,7 @@ def run_sae_pk_mixed(dev, apdev, confirm_immediate=False): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M, SAE_PK_19_PK)] # Disable HT from the SAE-PK BSS to make the station prefer the other BSS # by default. @@ -317,7 +303,7 @@ def run_sae_pk_mixed(dev, apdev, confirm_immediate=False): dev[0].scan_for_bss(bssid, freq=2412) dev[0].scan_for_bss(bssid2, freq=2412) - dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", scan_freq="2412") if dev[0].get_status_field("sae_pk") != "1": @@ -326,7 +312,7 @@ def run_sae_pk_mixed(dev, apdev, confirm_immediate=False): raise Exception("Unexpected BSSID selected") def check_sae_pk_sta_connect_failure(dev): - dev.connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW, + dev.connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", scan_freq="2412", wait_connect=False) ev = dev.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) @@ -342,7 +328,7 @@ def test_sae_pk_missing_ie(dev, apdev): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M, SAE_PK_19_PK)] params['sae_pk_omit'] = '1' hapd = hostapd.add_ap(apdev[0], params) @@ -355,7 +341,7 @@ def test_sae_pk_unexpected_status(dev, apdev): params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M, SAE_PK_19_PK)] params['sae_commit_status'] = '126' hapd = hostapd.add_ap(apdev[0], params) @@ -369,7 +355,7 @@ def test_sae_pk_invalid_signature(dev, apdev): other = "MHcCAQEEILw+nTjFzRyhVea0G6KbwZu18oWrfhzppxj+MceUO3YLoAoGCCqGSM49AwEHoUQDQgAELdou6LuTDNiMVlMB65KsWhQFbPXR9url0EA6luWzUfAuGoDXYJUBTVz6Nv3mz6oQcDrSiDmz/LejndJ0YHGgfQ==" params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M, + params['sae_password'] = ['%s|pk=%s:%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M, SAE_PK_19_PK, other)] hapd = hostapd.add_ap(apdev[0], params) check_sae_pk_sta_connect_failure(dev[0]) @@ -382,43 +368,16 @@ def test_sae_pk_invalid_fingerprint(dev, apdev): other = "431ff8322f93b9dc50ded9f3d14ace21" params = hostapd.wpa2_params(ssid=SAE_PK_SSID) params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, other, + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, other, SAE_PK_19_PK)] hapd = hostapd.add_ap(apdev[0], params) check_sae_pk_sta_connect_failure(dev[0]) -def test_sae_pk_password_min_len(dev, apdev): - """SAE-PK password minimum length""" - check_sae_pk_capab(dev[0]) - ssid = SAE_PK_SSID - pk = SAE_PK_19_PK - tests = [("dwxm-zv66-p5u", "431ff8322f93b9dc50ded9f3d14ace22", False), - ("dwxm-zv66-p5ue", "431ff8322f93b9dc50ded9f3d14ace22", True), - ("iian-qey6-pu", "128e51ddb5e2e24388f9ed14b687e2eb", False), - ("iian-qey6-pu5", "128e51ddb5e2e24388f9ed14b687e2eb", True), - ("ssko-2lmu", "a5e38c7251ea310cc348fbcdadfa8bcb", False), - ("ssko-2lmu-7", "a5e38c7251ea310cc348fbcdadfa8bcb", True), - ("3qqu-f4x", "d2e5fa27d1be8897f987f2d480d2af6b", False), - ("3qqu-f4xq", "d2e5fa27d1be8897f987f2d480d2af6b", True)] - for pw, m, success in tests: - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_key_mgmt'] = 'SAE' - params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] - try: - hapd = hostapd.add_ap(apdev[0], params, no_enable=True) - if not success: - raise Exception("Unexpected success with password %s" % pw) - except Exception as e: - if str(e).startswith("Unexpected success with password"): - raise - if success: - raise Exception("Unexpected failure with password %s" % pw) - def test_sae_pk_confirm_immediate(dev, apdev): """SAE-PK with immediate confirm on AP""" check_sae_pk_capab(dev[0]) dev[0].flush_scan_cache() dev[0].set("sae_groups", "") - run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW, - SAE_PK_SEC2_M, SAE_PK_19_PK, confirm_immediate=True) + run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW, + SAE_PK_SEC3_M, SAE_PK_19_PK, confirm_immediate=True) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 58143d560..f12b6c0db 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -4930,8 +4930,8 @@ def test_sigma_dut_sae_pk(dev, apdev): sigma = start_sigma_dut(ifname) ssid = "SAE-PK test" - pw = "dwxm-zv66-p5ue" - m = "431ff8322f93b9dc50ded9f3d14ace22" + pw = "hbbi-f4xq-b45g" + m = "d2e5fa27d1be8897f987f2d480d2af6b" pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" try: @@ -5012,32 +5012,50 @@ def test_sigma_dut_ap_sae_pk(dev, apdev, params): conffile = params['prefix'] + ".sigma-conf" if "SAE" not in dev[0].get_capability("auth_alg"): raise HwsimSkip("SAE not supported") - tests = [("SAEPK-4.7.1", "fb4c-zpqh-bhdc", "saepk.pem", - "2ec1f37b47b402252e9dc5001e81fd1c", False), - ("SAEPK-5.7.1.1", "amro-yjrs-zzda", "saepk1.pem", - "f42baa90420032486b3229ab0890878a", False), - ("SAEPK-5.7.1.2", "eh56-tjce-cnzg-ymhq", "saepk2.pem", - "efb8b7a87e0638a93b056cb4aadf4a71", False), - ("SAEPK-5.7.1.3", "knny-r45l-ww3w", "saepk3.pem", - "6502721b2c2dfea3c9aefc5324eee9c9", False), - ("SAEPK-5.7.2.1", "fvys-4brw-d67c", "saepk4.pem", - "b63662c6f0bdd12bf5a2075ccfd7e132", False), - ("SAEPK-5.7.2.2", "cnj6-khsf-dgzh", "saepk5.pem", - "126d37fae167a53d4ebb08a235cef1da", False), - ("SAEPK-5.7.2.3", "hr7j-3cdr-wtq6", "saepk6.pem", - "61a84a86ffb1b9e23f576a0275ddcc78", True), - ("SAEPK-5.7.2.4", "geoh-2rvn-ivwu", "saepk7.pem", - "61a84a86ffb1b9e23f576a0275ddcc78", False), - ("SAEPK-5.7.2.4", "geoh-2rvn-ivwu", "saepk8_sig.pem", - "61a84a86ffb1b9e23f576a0275ddcc78", True), - ("SAEPK-5.7.3", "hbhh-r4um-jzjs", "saepk9.pem", - "af9b55bce52040892634bb3e41d557ee", False), - ("SAE-PK-5.7.1.13", "dop4-pi5w-72g2", "saepk13.pem", - "c269116268faaa6728fccd27fa5e9003", False), - ("SAE-PK test", "ssko-2lmu-7", "saepk5.7.1Run4thru12.pem", - "a5e38c7251ea310cc348fbcdadfa8bcb", False), - ("SAE-PK test", "3qqu-f4xq", "saepk5.7.1Run4thru12.pem", - "d2e5fa27d1be8897f987f2d480d2af6b", False)] + tests = [("SAEPK-4.7.1.1", "ya3o-zvm2-r4so", "saepk1.pem", + "faa1ef5094bdb4cb2836332ca2c09839", False), + ("SAEPK-4.7.1.2", "xcc2-qwru-yg23", "saepk1.pem", + "b1b30107eb74de2f25afd079bb4196c1", False), + ("SAEPK-4.7.1.3", "skqz-6scq-zcqv", "saepk1.pem", + "4c0ff61465e0f298510254ff54916c71", False), + ("SAEPK-4.7.1.4", "r6em-rya4-tqfa", "saepkP384.pem", + "fb811655209e9edf347a675ddd3e9c82", False), + ("SAEPK-4.7.1.5", "6kjo-umvi-7x3w", "saepkP521.pem", + "cccb76bc0f113ab754826ba9538d66f5", False), + ("SAEPK-5.7.1.1", "sw4h-re63-wgqg", "saepk1.pem", + "0d126f302d85ac809a6a4229dbbe3c75", False), + ("SAEPK-5.7.1.2", "wewq-r4kg-4ioz-xb2p", "saepk1.pem", + "d6b1d8924b1a462677e67b3bbfe73977", False), + ("SAEPK-5.7.1.3", "vb3v-5skk-5eft-v4hu-w2c5", "saepk1.pem", + "41f8cfceb96ebc5c8af9677d22749fad", False), + ("SAEPK-5.7.1.4", "2qsw-6tgy-xnwa-s7lo-75tq-qggr", "saepk1.pem", + "089e8d4a3a79ec637c54dd7bd61972f2", False), + ("SAE-PK test", "hbbi-f4xq-b45g", "saepkP256.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("SAE-PK test", "hbbi-f4xq-b457-jje4", "saepkP256.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("SAE-PK test", "hbbi-f4xq-b457-jjew-muei", "saepkP256.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("SAE-PK test", "hbbi-f4xq-b457-jjew-muey-fod3", "saepkP256.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("SAEPK-5.7.1.1", "sw4h-re63-wgqg", "saepk1.pem", + "0d126f302d85ac809a6a4229dbbe3c75", False), + ("SAEPK-5.7.1.10", "tkor-7nb3-r7tv", "saepkP384.pem", + "af1a3df913fc0103f65f105ed1472277", False), + ("SAEPK-5.7.1.11", "yjl3-vfvu-w6r3", "saepkP521.pem", + "24dadf9d253c4169c9647a21cb54fc57", False), + ("SAEPK-5.7.2.1", "rntm-tkrp-xgke", "saepk1.pem", + "cd38ccce3baff627d09bee7b9530d6ce", False), + ("SAEPK-5.7.2.2", "7lt7-7dqt-6abk", "saepk1.pem", + "a22fc8489932597c9e83de62dec02b21", False), + ("SAEPK-5.7.2.3", "sw4h-re63-wgqg", "saepk2.pem", + "1f4a4c7d290d97e0b6ab0cbbbfa0726d", True), + ("SAEPK-5.7.2.4", "rmj3-ya7b-42k4", "saepk1.pem", + "5f65e2bc37f8494de7a605ff615c8b6a", False), + ("SAEPK-5.7.2.4", "rmj3-ya7b-42k4", "saepk2.pem", + "5f65e2bc37f8494de7a605ff615c8b6a", True), + ("SAEPK-5.7.3", "4322-ufus-4bhm", "saepk1.pem", + "21ede99abc46679646693cafe4677d4e", False)] with HWSimRadio() as (radio, iface): sigma = start_sigma_dut(iface, hostapd_logdir=logdir) @@ -5054,10 +5072,10 @@ def test_sigma_dut_ap_sae_pk_misbehavior(dev, apdev, params): conffile = params['prefix'] + ".sigma-conf" if "SAE" not in dev[0].get_capability("auth_alg"): raise HwsimSkip("SAE not supported") - ssid = "SAEPK-4.7.1" - pw = "fb4c-zpqh-bhdc" - keypair = "saepk.pem" - m = "2ec1f37b47b402252e9dc5001e81fd1c" + ssid = "SAEPK-4.7.1.1" + pw = "rmj3-ya7b-42k4" + keypair = "saepk1.pem" + m = "faa1ef5094bdb4cb2836332ca2c09839" with HWSimRadio() as (radio, iface): sigma = start_sigma_dut(iface, hostapd_logdir=logdir) @@ -5069,7 +5087,7 @@ def test_sigma_dut_ap_sae_pk_misbehavior(dev, apdev, params): run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, True, status=126, omit=True, immediate=True) run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, - True, sig="saepk8_sig.pem") + True, sig="saepk2.pem") finally: stop_sigma_dut(sigma) From 844ecc70a3f6d983e966279e72e4f46d580d6c1d Mon Sep 17 00:00:00 2001 From: Rajasekaran Kalidoss Date: Fri, 31 Jul 2020 22:08:35 +0530 Subject: [PATCH 0783/1105] Additional TWT attributes for response path and resume Introduce additional attributes for the TWT response parameters from the host driver. Also, add ATTR_TWT_RESUME_FLOW_ID for TWT Resume request. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 94 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 72ebc0e1d..e31f2d251 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7661,6 +7661,28 @@ enum qca_wlan_vendor_attr_nan_params { * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA: Required (u32) * This attribute is used to configure wake interval mantissa. * The units are in TU. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS: Required (u8) + * This field is applicable for TWT response only. + * This contains status values in enum qca_wlan_vendor_twt_status + * and is passed to the userspace. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE: Required (u8) + * This field is applicable for TWT response only. + * This field contains response type from the TWT responder and is + * passed to the userspace. The values for this field are defined in + * enum qca_wlan_vendor_twt_setup_resp_type. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64) + * This field is applicable for TWT response only. + * This field contains absolute TSF value of the wake time received + * from the TWT responder and is passed to the userspace. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED: Flag attribute. + * Enable (flag attribute present) - Indicates that the TWT responder + * supports reception of TWT information frame from the TWT requestor. + * Disable (flag attribute not present) - Indicates that the responder + * doesn't support reception of TWT information frame from requestor. */ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0, @@ -7675,6 +7697,12 @@ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION = 9, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA = 10, + /* TWT Response only attributes */ + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS = 11, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE = 12, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF = 13, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED = 14, + /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX = @@ -7682,7 +7710,44 @@ enum qca_wlan_vendor_attr_twt_setup { }; /** - * enum qca_wlan_vendor_attr_twt_resume: Represents attributes for + * enum qca_wlan_vendor_twt_status - Represents the status of the requested + * TWT operation + * + * @QCA_WLAN_VENDOR_TWT_STATUS_OK: TWT request successfully completed + * @QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED: TWT not enabled + * @QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID: TWT dialog ID is already used + * @QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY: TWT session is busy + * @QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST: TWT session does not exist + * @QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED: TWT session not in suspend state + * @QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM: Invalid parameters + * @QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY: FW not ready + * @QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE: FW resource exhausted + * @QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK: Peer AP/STA did not ACK the + * request/response frame + * @QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE: Peer AP did not send the response + * frame + * @QCA_WLAN_VENDOR_TWT_STATUS_DENIED: AP did not accept the request + * @QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR: Adding TWT dialog failed due to an + * unknown reason + */ +enum qca_wlan_vendor_twt_status { + QCA_WLAN_VENDOR_TWT_STATUS_OK = 0, + QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED = 1, + QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID = 2, + QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY = 3, + QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST = 4, + QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED = 5, + QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM = 6, + QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY = 7, + QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE = 8, + QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK = 9, + QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE = 10, + QCA_WLAN_VENDOR_TWT_STATUS_DENIED = 11, + QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR = 12, +}; + +/** + * enum qca_wlan_vendor_attr_twt_resume - Represents attributes for * TWT (Target Wake Time) resume request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME and * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by @@ -7696,11 +7761,16 @@ enum qca_wlan_vendor_attr_twt_setup { * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE: Required (u32) * This attribute represents the next TWT subfield size. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID: Required (u8). + * Flow ID is the unique identifier for each TWT session. This attribute + * represents the respective TWT session to resume. */ enum qca_wlan_vendor_attr_twt_resume { QCA_WLAN_VENDOR_ATTR_TWT_RESUME_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT = 1, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE = 2, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST, @@ -7708,6 +7778,28 @@ enum qca_wlan_vendor_attr_twt_resume { QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST - 1, }; +/** + * enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by + * the TWT responder + * + * @QCA_WLAN_VENDOR_TWT_RESP_ALTERNATE: TWT responder suggests TWT + * parameters that are different from TWT requesting STA suggested + * or demanded TWT parameters + * @QCA_WLAN_VENDOR_TWT_RESP_DICTATE: TWT responder demands TWT + * parameters that are different from TWT requesting STA TWT suggested + * or demanded parameters + * @QCA_WLAN_VENDOR_TWT_RESP_REJECT: TWT responder rejects TWT + * setup + * @QCA_WLAN_VENDOR_TWT_RESP_ACCEPT: TWT responder accepts the TWT + * setup. + */ +enum qca_wlan_vendor_twt_setup_resp_type { + QCA_WLAN_VENDOR_TWT_RESP_ALTERNATE = 1, + QCA_WLAN_VENDOR_TWT_RESP_DICTATE = 2, + QCA_WLAN_VENDOR_TWT_RESP_REJECT = 3, + QCA_WLAN_VENDOR_TWT_RESP_ACCEPT = 4, +}; + /** * enum qca_wlan_vendor_twt_setup_req_type - Required (u8) * Represents the setup type being requested for TWT. From 7ca81190a8e2e8198629402f6522e2a1198bb885 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 6 Aug 2020 23:49:19 +0300 Subject: [PATCH 0784/1105] SAE-PK: Allow SAE-PK style wpa_passphrase if SAE-PK is enabled with same This prevents use of a SAE-PK style password as the WPA-PSK passphrase only if the same password is not also enabled through sae_password for use with SAE-PK. Signed-off-by: Jouni Malinen --- src/ap/ap_config.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 1c6b4a00e..769f7fab6 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -1123,17 +1123,21 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss) { struct sae_password_entry *pw; + bool res = false; if (bss->ssid.wpa_passphrase && sae_pk_valid_password(bss->ssid.wpa_passphrase)) - return true; + res = true; for (pw = bss->sae_passwords; pw; pw = pw->next) { if (!pw->pk && sae_pk_valid_password(pw->password)) return true; + if (bss->ssid.wpa_passphrase && res && pw->pk && + os_strcmp(bss->ssid.wpa_passphrase, pw->password) == 0) + res = false; } - return false; + return res; } #endif /* CONFIG_SAE_PK */ From 2a58968d395a1a16eef5047f18c3c2714d150431 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Aug 2020 00:47:15 +0300 Subject: [PATCH 0785/1105] SAE-PK: Allow SAE-PK password to be set using the psk parameter Only the sae_password parameter was previously accepted for SAE-PK use. That is not sufficient for covering mixed SAE+PSK cases. Extend this by allowing the psk parameter to be used as well just like it can be used for SAE without SAE-PK. Signed-off-by: Jouni Malinen --- wpa_supplicant/sme.c | 5 ++++- wpa_supplicant/wpa_supplicant.c | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index f45bab27a..c761fdad1 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -151,7 +151,10 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, #ifdef CONFIG_SAE_PK if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) && ssid->sae_pk != SAE_PK_MODE_DISABLED && - ssid->sae_password && sae_pk_valid_password(ssid->sae_password)) { + ((ssid->sae_password && + sae_pk_valid_password(ssid->sae_password)) || + (!ssid->sae_password && ssid->passphrase && + sae_pk_valid_password(ssid->passphrase)))) { use_pt = 1; use_pk = true; } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 51e5321e0..6eb09f496 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1643,8 +1643,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK, wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_pk != SAE_PK_MODE_DISABLED && - ssid->sae_password && - sae_pk_valid_password(ssid->sae_password)); + ((ssid->sae_password && + sae_pk_valid_password(ssid->sae_password)) || + (!ssid->sae_password && ssid->passphrase && + sae_pk_valid_password(ssid->passphrase)))); #endif /* CONFIG_SAE_PK */ #ifdef CONFIG_TESTING_OPTIONS wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED, From 5e6919fd52a8d50dad4adf08286dae44aa48f20e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 6 Aug 2020 23:53:37 +0300 Subject: [PATCH 0786/1105] tests: SAE-PK and PSK Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index e01b5a3bd..540fe58c0 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -381,3 +381,35 @@ def test_sae_pk_confirm_immediate(dev, apdev): run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW, SAE_PK_SEC3_M, SAE_PK_19_PK, confirm_immediate=True) + +def test_sae_pk_and_psk(dev, apdev): + """SAE-PK and PSK""" + check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() + dev[0].set("sae_groups", "") + dev[2].set("sae_groups", "") + + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) + params['wpa_key_mgmt'] = 'SAE WPA-PSK' + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, + SAE_PK_SEC3_M, + SAE_PK_19_PK)] + params['wpa_passphrase'] = SAE_PK_SEC3_PW + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", + scan_freq="2412") + dev[1].connect(SAE_PK_SSID, psk=SAE_PK_SEC3_PW, key_mgmt="WPA-PSK", + scan_freq="2412") + dev[2].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, key_mgmt="SAE", + sae_pk="2", scan_freq="2412") + dev[0].request("REMOVE_NETWORK *") + dev[0].wait_disconnected() + dev[0].dump_monitor() + dev[0].connect(SAE_PK_SSID, psk=SAE_PK_SEC3_PW, key_mgmt="SAE", + scan_freq="2412") + status = dev[0].get_status() + if "sae_h2e" not in status or "sae_pk" not in status or \ + status["sae_h2e"] != "1" or status["sae_pk"] != "1": + raise Exception("SAE-PK or H2E not indicated in STATUS") From abd950be90828b2c8bed4fdeaabd3a7ed95af6e4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Aug 2020 00:10:26 +0300 Subject: [PATCH 0787/1105] tests: sigma_dut controlled AP using SAE-PK(disabled) and PSK Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index f12b6c0db..bddb97fc1 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -5091,6 +5091,49 @@ def test_sigma_dut_ap_sae_pk_misbehavior(dev, apdev, params): finally: stop_sigma_dut(sigma) +def run_sigma_dut_ap_sae_pk_mixed(conffile, dev, ssid, pw, keypair, m, failure): + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,%s,MODE,11ng" % ssid) + cmd = "ap_set_security,NAME,AP,AKMSuiteType,2;8,PairwiseCipher,AES-CCMP-128,GroupCipher,AES-CCMP-128,GroupMgntCipher,BIP-CMAC-128,PMF,Required,PSK,%s,sae_pk,0,Transition_Disable,0" % (pw) + sigma_dut_cmd_check(cmd) + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + bssid = bssid.split(',')[3] + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "ab") as f2: + f2.write(f.read()) + f2.write('\n'.encode()) + + sigma_dut_cmd_check("ap_set_rfeature,NAME,AP,type,WPA3,Transition_Disable,1,Transition_Disable_Index,0") + + dev[0].set("sae_groups", "") + dev[0].connect(ssid, key_mgmt="SAE", sae_password=pw, ieee80211w="2", + scan_freq="2412") + dev[1].connect(ssid, key_mgmt="WPA-PSK", psk=pw, ieee80211w="2", + scan_freq="2412") + + sigma_dut_cmd_check("ap_reset_default") + +def test_sigma_dut_ap_sae_pk_mixed(dev, apdev, params): + """sigma_dut controlled AP using SAE-PK(disabled) and PSK""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + ssid = "SAEPK-5.7.3" + pw = "4322-ufus-4bhm" + keypair = "saepk1.pem" + m = "21ede99abc46679646693cafe4677d4e" + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + run_sigma_dut_ap_sae_pk_mixed(conffile, dev, ssid, pw, keypair, + m, False) + finally: + stop_sigma_dut(sigma) + def test_sigma_dut_client_privacy(dev, apdev, params): """sigma_dut client privacy""" logdir = params['logdir'] From 1837648e71e087d37e78c5c97a7745ef840cc030 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Aug 2020 01:09:06 +0300 Subject: [PATCH 0788/1105] tests: SAE-PK and PSK using invalid password combination Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index 540fe58c0..b425b9083 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -413,3 +413,19 @@ def test_sae_pk_and_psk(dev, apdev): if "sae_h2e" not in status or "sae_pk" not in status or \ status["sae_h2e"] != "1" or status["sae_pk"] != "1": raise Exception("SAE-PK or H2E not indicated in STATUS") + +def test_sae_pk_and_psk_invalid_password(dev, apdev): + """SAE-PK and PSK using invalid password combination""" + check_sae_pk_capab(dev[0]) + dev[0].flush_scan_cache() + + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) + params['wpa_key_mgmt'] = 'SAE WPA-PSK' + params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, + SAE_PK_SEC3_M, + SAE_PK_19_PK)] + params['wpa_passphrase'] = SAE_PK_20_PW + hapd = hostapd.add_ap(apdev[0], params, no_enable=True) + res = hapd.request("ENABLE") + if "FAIL" not in res: + raise Exception("Invalid configuration accepted") From e5be6e68c8ea4cce1235a4870517f60a71ef9d20 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 6 Aug 2020 19:47:28 +0300 Subject: [PATCH 0789/1105] DPP2: Add Enrollee netAccessKey group into Reconfig Announcement This was added to the protocol design to support cases where the C-sign-key uses a different group than the netAccessKey. The Enrollee now indicates its netAccessKey group in Reconfig Announcement and the Configurator builds it own reconfig Connector using that group instead of the group used for the C-sign-key. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 17 +++++++-- src/common/dpp.h | 6 ++-- src/common/dpp_crypto.c | 16 +++++++-- src/common/dpp_i.h | 1 + src/common/dpp_reconfig.c | 63 +++++++++++++++++++++++++-------- src/common/dpp_tcp.c | 17 +++++++-- wpa_supplicant/dpp_supplicant.c | 21 ++++++++--- 7 files changed, 113 insertions(+), 28 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 178fd126e..ca225894a 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1235,11 +1235,12 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, unsigned int freq) { - const u8 *csign_hash; - u16 csign_hash_len; + const u8 *csign_hash, *fcgroup; + u16 csign_hash_len, fcgroup_len; struct dpp_configurator *conf; struct dpp_authentication *auth; unsigned int wait_time, max_wait_time; + u16 group; if (hapd->dpp_auth) { wpa_printf(MSG_DEBUG, @@ -1271,8 +1272,18 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, return; } + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, - conf, freq); + conf, freq, group); if (!auth) return; hostapd_dpp_set_testing_options(hapd, auth); diff --git a/src/common/dpp.h b/src/common/dpp.h index cff996095..f6e4e25f2 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -683,10 +683,12 @@ void dpp_global_deinit(struct dpp_global *dpp); /* dpp_reconfig.c */ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, - size_t csign_key_len); + size_t csign_key_len, + const u8 *net_access_key, + size_t net_access_key_len); struct dpp_authentication * dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, - struct dpp_configurator *conf, unsigned int freq); + struct dpp_configurator *conf, unsigned int freq, u16 group); struct dpp_authentication * dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, const char *own_connector, diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index e83ab9c60..6752aaa31 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -130,6 +130,18 @@ const struct dpp_curve_params * dpp_get_curve_nid(int nid) } +const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (dpp_curves[i].ike_group == group) + return &dpp_curves[i]; + } + return NULL; +} + + void dpp_debug_print_point(const char *title, const EC_GROUP *group, const EC_POINT *point) { @@ -2272,7 +2284,7 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, if (auth->curve != curve) { wpa_printf(MSG_DEBUG, - "DPP: Mismatching netAccessKey curves (%s != %s)", + "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", auth->curve->name, curve->name); goto fail; } @@ -2381,7 +2393,7 @@ int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, dpp_debug_print_key("DPP: Received netAccessKey", peer_key); if (auth->curve != curve) { wpa_printf(MSG_DEBUG, - "DPP: Mismatching netAccessKey curves (%s != %s)", + "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", auth->curve->name, curve->name); goto fail; } diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index e66eb6cfd..cf3dedd01 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -73,6 +73,7 @@ dpp_check_signed_connector(struct dpp_signed_connector_info *info, const struct dpp_curve_params * dpp_get_curve_name(const char *name); const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name); const struct dpp_curve_params * dpp_get_curve_nid(int nid); +const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group); int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len); struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix); diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 0bb00cc1d..5d7ab6802 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -34,9 +34,11 @@ static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash) struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, - size_t csign_key_len) + size_t csign_key_len, + const u8 *net_access_key, + size_t net_access_key_len) { - struct wpabuf *msg; + struct wpabuf *msg = NULL; EVP_PKEY *csign = NULL; const unsigned char *p; struct wpabuf *uncomp; @@ -44,39 +46,61 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, const u8 *addr[1]; size_t len[1]; int res; + size_t attr_len; + const struct dpp_curve_params *own_curve; + EVP_PKEY *own_key; wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame"); + own_key = dpp_set_keypair(&own_curve, net_access_key, + net_access_key_len); + if (!own_key) { + wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); + goto fail; + } + p = csign_key; csign = d2i_PUBKEY(NULL, &p, csign_key_len); if (!csign) { wpa_printf(MSG_ERROR, "DPP: Failed to parse local C-sign-key information"); - return NULL; + goto fail; } uncomp = dpp_get_pubkey_point(csign, 1); EVP_PKEY_free(csign); if (!uncomp) - return NULL; + goto fail; addr[0] = wpabuf_head(uncomp); len[0] = wpabuf_len(uncomp); wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed C-sign key", addr[0], len[0]); res = sha256_vector(1, addr, len, hash); wpabuf_free(uncomp); if (res < 0) - return NULL; + goto fail; wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)", hash, SHA256_MAC_LEN); - msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, 4 + SHA256_MAC_LEN); + attr_len = 4 + SHA256_MAC_LEN; + attr_len += 4 + 2; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len); if (!msg) - return NULL; + goto fail; /* Configurator C-sign key Hash */ dpp_build_attr_csign_key_hash(msg, hash); + + /* Finite Cyclic Group attribute */ + wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u", + own_curve->ike_group); + wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); + wpabuf_put_le16(msg, 2); + wpabuf_put_le16(msg, own_curve->ike_group); + wpa_hexdump_buf(MSG_DEBUG, "DPP: Reconfig Announcement frame attributes", msg); +fail: + EVP_PKEY_free(own_key); return msg; } @@ -121,7 +145,9 @@ static struct wpabuf * dpp_reconfig_build_req(struct dpp_authentication *auth) } -static int dpp_configurator_build_own_connector(struct dpp_configurator *conf) +static int +dpp_configurator_build_own_connector(struct dpp_configurator *conf, + const struct dpp_curve_params *curve) { struct wpabuf *dppcon = NULL; int ret = -1; @@ -132,12 +158,12 @@ static int dpp_configurator_build_own_connector(struct dpp_configurator *conf) wpa_printf(MSG_DEBUG, "DPP: Sign own Configurator Connector for reconfiguration with curve %s", conf->curve->name); - conf->connector_key = dpp_gen_keypair(conf->curve); + conf->connector_key = dpp_gen_keypair(curve); if (!conf->connector_key) goto fail; /* Connector (JSON dppCon object) */ - dppcon = wpabuf_alloc(1000 + 2 * conf->curve->prime_len * 4 / 3); + dppcon = wpabuf_alloc(1000 + 2 * curve->prime_len * 4 / 3); if (!dppcon) goto fail; json_start_object(dppcon, NULL); @@ -150,7 +176,7 @@ static int dpp_configurator_build_own_connector(struct dpp_configurator *conf) json_end_array(dppcon); json_value_sep(dppcon); if (dpp_build_jwk(dppcon, "netAccessKey", conf->connector_key, NULL, - conf->curve) < 0) { + curve) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); goto fail; } @@ -172,9 +198,18 @@ fail: struct dpp_authentication * dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, - struct dpp_configurator *conf, unsigned int freq) + struct dpp_configurator *conf, unsigned int freq, u16 group) { struct dpp_authentication *auth; + const struct dpp_curve_params *curve; + + curve = dpp_get_curve_ike_group(group); + if (!curve) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported group %u - cannot reconfigure", + group); + return NULL; + } auth = dpp_alloc_auth(dpp, msg_ctx); if (!auth) @@ -186,12 +221,12 @@ dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, auth->waiting_auth_resp = 1; auth->allowed_roles = DPP_CAPAB_CONFIGURATOR; auth->configurator = 1; - auth->curve = conf->curve; + auth->curve = curve; auth->transaction_id = 1; if (freq && dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) goto fail; - if (dpp_configurator_build_own_connector(conf) < 0) + if (dpp_configurator_build_own_connector(conf, curve) < 0) goto fail; if (random_get_bytes(auth->i_nonce, auth->curve->nonce_len)) { diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 9994c67cd..a4ec81398 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -844,11 +844,12 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, const u8 *hdr, const u8 *buf, size_t len) { - const u8 *csign_hash; - u16 csign_hash_len; + const u8 *csign_hash, *fcgroup; + u16 csign_hash_len, fcgroup_len; struct dpp_configurator *conf; struct dpp_global *dpp = conn->ctrl->global; struct dpp_authentication *auth; + u16 group; if (conn->auth) { wpa_printf(MSG_DEBUG, @@ -874,7 +875,17 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, return -1; } - auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0); + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return -1; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + + auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0, group); if (!auth) return -1; if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) { diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index cc35030c9..9c0056c5b 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2022,11 +2022,12 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, unsigned int freq) { - const u8 *csign_hash; - u16 csign_hash_len; + const u8 *csign_hash, *fcgroup; + u16 csign_hash_len, fcgroup_len; struct dpp_configurator *conf; struct dpp_authentication *auth; unsigned int wait_time, max_wait_time; + u16 group; if (!wpa_s->dpp) return; @@ -2056,7 +2057,17 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, return; } - auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq); + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + + auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group); if (!auth) return; wpas_dpp_set_testing_options(wpa_s, auth); @@ -3636,7 +3647,9 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) wpa_s->dpp_qr_mutual = 0; wpa_s->dpp_reconfig_announcement = dpp_build_reconfig_announcement(ssid->dpp_csign, - ssid->dpp_csign_len); + ssid->dpp_csign_len, + ssid->dpp_netaccesskey, + ssid->dpp_netaccesskey_len); if (!wpa_s->dpp_reconfig_announcement) return -1; wpa_s->dpp_reconfig_ssid = ssid; From ad2119cbc63a56554017c77b56b005fd5e608b5b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Aug 2020 15:26:15 +0300 Subject: [PATCH 0790/1105] tests: DPP reconfiguration connector with different groups Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 8f530bb0a..8910f4d99 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5437,7 +5437,14 @@ def test_dpp_reconfig_connector(dev, apdev): finally: dev[0].set("dpp_config_processing", "0", allow_fail=True) -def run_dpp_reconfig_connector(dev, apdev): +def test_dpp_reconfig_connector_different_groups(dev, apdev): + """DPP reconfiguration connector with different groups""" + try: + run_dpp_reconfig_connector(dev, apdev, conf_curve="secp384r1") + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_reconfig_connector(dev, apdev, conf_curve=None): check_dpp_capab(dev[0], min_ver=2) check_dpp_capab(dev[1], min_ver=2) @@ -5451,7 +5458,7 @@ def run_dpp_reconfig_connector(dev, apdev): id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) dev[0].dpp_listen(2412) - configurator = dev[1].dpp_configurator_add() + configurator = dev[1].dpp_configurator_add(curve=conf_curve) conf = 'sta-psk' dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid=ssid, passphrase=passphrase, configurator=configurator, From c6d0e5a93d4aa3185bab3311daf26bcd791dd51b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 6 Aug 2020 19:47:28 +0300 Subject: [PATCH 0791/1105] DPP2: Add E-id in Reconfig Announcement Add an encrypted Enrollee identifier into Reconfig Announcement frames and decrypt that on the Configurator side. The actual E-id value is currently not used for anything, but it can be used in the future to provide better control over reconfiguration. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 10 +- src/common/dpp.h | 15 ++- src/common/dpp_crypto.c | 187 ++++++++++++++++++++++++++++++ src/common/dpp_i.h | 10 ++ src/common/dpp_reconfig.c | 70 ++++++++++- src/common/dpp_tcp.c | 10 +- wpa_supplicant/dpp_supplicant.c | 25 +++- wpa_supplicant/wpa_supplicant_i.h | 1 + 8 files changed, 314 insertions(+), 14 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index ca225894a..70027ad6e 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1235,8 +1235,8 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, unsigned int freq) { - const u8 *csign_hash, *fcgroup; - u16 csign_hash_len, fcgroup_len; + const u8 *csign_hash, *fcgroup, *a_nonce, *e_id; + u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len; struct dpp_configurator *conf; struct dpp_authentication *auth; unsigned int wait_time, max_wait_time; @@ -1282,8 +1282,12 @@ hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, group = WPA_GET_LE16(fcgroup); wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len); + e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len); + auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, - conf, freq, group); + conf, freq, group, a_nonce, a_nonce_len, + e_id, e_id_len); if (!auth) return; hostapd_dpp_set_testing_options(hapd, auth); diff --git a/src/common/dpp.h b/src/common/dpp.h index f6e4e25f2..8243a97b6 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -21,6 +21,7 @@ struct crypto_ecdh; struct hostapd_ip_addr; struct dpp_global; struct json_token; +struct dpp_reconfig_id; #ifdef CONFIG_TESTING_OPTIONS #define DPP_VERSION (dpp_version_override) @@ -87,6 +88,8 @@ enum dpp_attribute_id { DPP_ATTR_RECONFIG_FLAGS = 0x101D, DPP_ATTR_C_SIGN_KEY_HASH = 0x101E, DPP_ATTR_CSR_ATTR_REQ = 0x101F, + DPP_ATTR_A_NONCE = 0x1020, + DPP_ATTR_E_PRIME_ID = 0x1021, }; enum dpp_status_error { @@ -685,10 +688,13 @@ void dpp_global_deinit(struct dpp_global *dpp); struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, size_t csign_key_len, const u8 *net_access_key, - size_t net_access_key_len); + size_t net_access_key_len, + struct dpp_reconfig_id *id); struct dpp_authentication * dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, - struct dpp_configurator *conf, unsigned int freq, u16 group); + struct dpp_configurator *conf, unsigned int freq, u16 group, + const u8 *a_nonce_attr, size_t a_nonce_len, + const u8 *e_id_attr, size_t e_id_len); struct dpp_authentication * dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, const char *own_connector, @@ -702,5 +708,10 @@ dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len); +struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, + size_t csign_key_len); +int dpp_update_reconfig_id(struct dpp_reconfig_id *id); +void dpp_free_reconfig_id(struct dpp_reconfig_id *id); + #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 6752aaa31..9dff7c653 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2988,6 +2988,193 @@ fail: return ret; } + +struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, + size_t csign_key_len) +{ + const unsigned char *p; + EVP_PKEY *csign = NULL; + struct dpp_reconfig_id *id = NULL; + BN_CTX *ctx = NULL; + BIGNUM *bn = NULL, *q = NULL; + const EC_KEY *eckey; + const EC_GROUP *group; + EC_POINT *e_id = NULL; + + p = csign_key; + csign = d2i_PUBKEY(NULL, &p, csign_key_len); + if (!csign) + goto fail; + + eckey = EVP_PKEY_get0_EC_KEY(csign); + if (!eckey) + goto fail; + group = EC_KEY_get0_group(eckey); + if (!group) + goto fail; + + e_id = EC_POINT_new(group); + ctx = BN_CTX_new(); + bn = BN_new(); + q = BN_new(); + if (!e_id || !ctx || !bn || !q || + !EC_GROUP_get_order(group, q, ctx) || + !BN_rand_range(bn, q) || + !EC_POINT_mul(group, e_id, bn, NULL, NULL, ctx)) + goto fail; + + dpp_debug_print_point("DPP: Generated random point E-id", group, e_id); + + id = os_zalloc(sizeof(*id)); + if (!id) + goto fail; + id->group = group; + id->e_id = e_id; + e_id = NULL; + id->csign = csign; + csign = NULL; +fail: + EC_POINT_free(e_id); + EVP_PKEY_free(csign); + BN_clear_free(bn); + BN_CTX_free(ctx); + return id; +} + + +static EVP_PKEY * dpp_pkey_from_point(const EC_GROUP *group, + const EC_POINT *point) +{ + EC_KEY *eckey; + EVP_PKEY *pkey = NULL; + + eckey = EC_KEY_new(); + if (!eckey || + EC_KEY_set_group(eckey, group) != 1 || + EC_KEY_set_public_key(eckey, point) != 1) { + wpa_printf(MSG_ERROR, + "DPP: Failed to set EC_KEY: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { + wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); + EVP_PKEY_free(pkey); + pkey = NULL; + goto fail; + } + +fail: + EC_KEY_free(eckey); + return pkey; +} + + +int dpp_update_reconfig_id(struct dpp_reconfig_id *id) +{ + BN_CTX *ctx = NULL; + BIGNUM *bn = NULL, *q = NULL; + EC_POINT *e_prime_id = NULL, *a_nonce = NULL; + int ret = -1; + const EC_KEY *csign; + const EC_POINT *csign_point; + + csign = EVP_PKEY_get0_EC_KEY(id->csign); + if (!csign) + goto fail; + csign_point = EC_KEY_get0_public_key(csign); + e_prime_id = EC_POINT_new(id->group); + a_nonce = EC_POINT_new(id->group); + ctx = BN_CTX_new(); + bn = BN_new(); + q = BN_new(); + /* Generate random 0 <= a-nonce < q + * A-NONCE = a-nonce * G + * E'-id = E-id + a-nonce * S_C */ + if (!csign_point || !e_prime_id || !a_nonce || !ctx || !bn || !q || + !EC_GROUP_get_order(id->group, q, ctx) || + !BN_rand_range(bn, q) || /* bn = a-nonce */ + !EC_POINT_mul(id->group, a_nonce, bn, NULL, NULL, ctx) || + !EC_POINT_mul(id->group, e_prime_id, NULL, csign_point, bn, ctx) || + !EC_POINT_add(id->group, e_prime_id, id->e_id, e_prime_id, ctx)) + goto fail; + + dpp_debug_print_point("DPP: Generated A-NONCE", id->group, a_nonce); + dpp_debug_print_point("DPP: Encrypted E-id to E'-id", + id->group, e_prime_id); + + EVP_PKEY_free(id->a_nonce); + EVP_PKEY_free(id->e_prime_id); + id->a_nonce = dpp_pkey_from_point(id->group, a_nonce); + id->e_prime_id = dpp_pkey_from_point(id->group, e_prime_id); + if (!id->a_nonce || !id->e_prime_id) + goto fail; + + ret = 0; + +fail: + EC_POINT_free(e_prime_id); + EC_POINT_free(a_nonce); + BN_clear_free(bn); + BN_CTX_free(ctx); + return ret; +} + + +void dpp_free_reconfig_id(struct dpp_reconfig_id *id) +{ + if (id) { + EC_POINT_clear_free(id->e_id); + EVP_PKEY_free(id->csign); + EVP_PKEY_free(id->a_nonce); + EVP_PKEY_free(id->e_prime_id); + os_free(id); + } +} + + +EC_POINT * dpp_decrypt_e_id(EVP_PKEY *csign, EVP_PKEY *a_nonce, + EVP_PKEY *e_prime_id) +{ + const EC_KEY *csign_ec, *a_nonce_ec, *e_prime_id_ec; + const BIGNUM *csign_bn; + const EC_GROUP *group; + EC_POINT *e_id = NULL; + const EC_POINT *a_nonce_point, *e_prime_id_point; + BN_CTX *ctx = NULL; + + /* E-id = E'-id - s_C * A-NONCE */ + csign_ec = EVP_PKEY_get0_EC_KEY(csign); + a_nonce_ec = EVP_PKEY_get0_EC_KEY(a_nonce); + e_prime_id_ec = EVP_PKEY_get0_EC_KEY(e_prime_id); + if (!csign_ec || !a_nonce_ec || !e_prime_id_ec) + return NULL; + csign_bn = EC_KEY_get0_private_key(csign_ec); + group = EC_KEY_get0_group(csign_ec); + a_nonce_point = EC_KEY_get0_public_key(a_nonce_ec); + e_prime_id_point = EC_KEY_get0_public_key(e_prime_id_ec); + ctx = BN_CTX_new(); + if (!csign_bn || !group || !a_nonce_point || !e_prime_id_point || !ctx) + goto fail; + e_id = EC_POINT_new(group); + if (!e_id || + !EC_POINT_mul(group, e_id, NULL, a_nonce_point, csign_bn, ctx) || + !EC_POINT_invert(group, e_id, ctx) || + !EC_POINT_add(group, e_id, e_prime_id_point, e_id, ctx)) { + EC_POINT_clear_free(e_id); + goto fail; + } + + dpp_debug_print_point("DPP: Decrypted E-id", group, e_id); + +fail: + BN_CTX_free(ctx); + return e_id; +} + #endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index cf3dedd01..f2164c789 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -133,11 +133,21 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, const u8 *r_proto, u16 r_proto_len, struct json_token *net_access_key); +EC_POINT * dpp_decrypt_e_id(EVP_PKEY *csign, EVP_PKEY *a_nonce, + EVP_PKEY *e_prime_id); char * dpp_sign_connector(struct dpp_configurator *conf, const struct wpabuf *dppcon); int dpp_test_gen_invalid_key(struct wpabuf *msg, const struct dpp_curve_params *curve); +struct dpp_reconfig_id { + const EC_GROUP *group; + EC_POINT *e_id; /* E-id */ + EVP_PKEY *csign; + EVP_PKEY *a_nonce; /* A-NONCE */ + EVP_PKEY *e_prime_id; /* E'-id */ +}; + /* dpp_tcp.c */ void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 5d7ab6802..b12c4f7d0 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -36,7 +36,8 @@ static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash) struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, size_t csign_key_len, const u8 *net_access_key, - size_t net_access_key_len) + size_t net_access_key_len, + struct dpp_reconfig_id *id) { struct wpabuf *msg = NULL; EVP_PKEY *csign = NULL; @@ -49,6 +50,7 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, size_t attr_len; const struct dpp_curve_params *own_curve; EVP_PKEY *own_key; + struct wpabuf *a_nonce = NULL, *e_id = NULL; wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame"); @@ -81,8 +83,20 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)", hash, SHA256_MAC_LEN); + if (dpp_update_reconfig_id(id) < 0) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate E'-id"); + goto fail; + } + + a_nonce = dpp_get_pubkey_point(id->a_nonce, 0); + e_id = dpp_get_pubkey_point(id->e_prime_id, 0); + if (!a_nonce || !e_id) + goto fail; + attr_len = 4 + SHA256_MAC_LEN; attr_len += 4 + 2; + attr_len += 4 + wpabuf_len(a_nonce); + attr_len += 4 + wpabuf_len(e_id); msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len); if (!msg) goto fail; @@ -97,9 +111,21 @@ struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, wpabuf_put_le16(msg, 2); wpabuf_put_le16(msg, own_curve->ike_group); + /* A-NONCE */ + wpabuf_put_le16(msg, DPP_ATTR_A_NONCE); + wpabuf_put_le16(msg, wpabuf_len(a_nonce)); + wpabuf_put_buf(msg, a_nonce); + + /* E'-id */ + wpabuf_put_le16(msg, DPP_ATTR_E_PRIME_ID); + wpabuf_put_le16(msg, wpabuf_len(e_id)); + wpabuf_put_buf(msg, e_id); + wpa_hexdump_buf(MSG_DEBUG, "DPP: Reconfig Announcement frame attributes", msg); fail: + wpabuf_free(a_nonce); + wpabuf_free(e_id); EVP_PKEY_free(own_key); return msg; } @@ -198,10 +224,14 @@ fail: struct dpp_authentication * dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, - struct dpp_configurator *conf, unsigned int freq, u16 group) + struct dpp_configurator *conf, unsigned int freq, u16 group, + const u8 *a_nonce_attr, size_t a_nonce_len, + const u8 *e_id_attr, size_t e_id_len) { struct dpp_authentication *auth; const struct dpp_curve_params *curve; + EVP_PKEY *a_nonce, *e_prime_id; + EC_POINT *e_id; curve = dpp_get_curve_ike_group(group); if (!curve) { @@ -211,6 +241,42 @@ dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, return NULL; } + if (!a_nonce_attr) { + wpa_printf(MSG_INFO, "DPP: Missing required A-NONCE attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: A-NONCE", a_nonce_attr, a_nonce_len); + a_nonce = dpp_set_pubkey_point(conf->csign, a_nonce_attr, a_nonce_len); + if (!a_nonce) { + wpa_printf(MSG_INFO, "DPP: Invalid A-NONCE"); + return NULL; + } + dpp_debug_print_key("A-NONCE", a_nonce); + + if (!e_id_attr) { + wpa_printf(MSG_INFO, "DPP: Missing required E'-id attribute"); + return NULL; + } + e_prime_id = dpp_set_pubkey_point(conf->csign, e_id_attr, e_id_len); + if (!e_prime_id) { + wpa_printf(MSG_INFO, "DPP: Invalid E'-id"); + EVP_PKEY_free(a_nonce); + return NULL; + } + dpp_debug_print_key("E'-id", e_prime_id); + e_id = dpp_decrypt_e_id(conf->csign, a_nonce, e_prime_id); + EVP_PKEY_free(a_nonce); + EVP_PKEY_free(e_prime_id); + if (!e_id) { + wpa_printf(MSG_INFO, "DPP: Could not decrypt E'-id"); + return NULL; + } + /* TODO: could use E-id to determine whether reconfiguration with this + * Enrollee has already been started and is waiting for updated + * configuration instead of replying again before such configuration + * becomes available */ + EC_POINT_clear_free(e_id); + auth = dpp_alloc_auth(dpp, msg_ctx); if (!auth) return NULL; diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index a4ec81398..639ff8c9f 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -844,8 +844,8 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, const u8 *hdr, const u8 *buf, size_t len) { - const u8 *csign_hash, *fcgroup; - u16 csign_hash_len, fcgroup_len; + const u8 *csign_hash, *fcgroup, *a_nonce, *e_id; + u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len; struct dpp_configurator *conf; struct dpp_global *dpp = conn->ctrl->global; struct dpp_authentication *auth; @@ -885,7 +885,11 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, group = WPA_GET_LE16(fcgroup); wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); - auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0, group); + a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len); + e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len); + + auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0, group, + a_nonce, a_nonce_len, e_id, e_id_len); if (!auth) return -1; if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) { diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 9c0056c5b..1184591e4 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2022,8 +2022,8 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *hdr, const u8 *buf, size_t len, unsigned int freq) { - const u8 *csign_hash, *fcgroup; - u16 csign_hash_len, fcgroup_len; + const u8 *csign_hash, *fcgroup, *a_nonce, *e_id; + u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len; struct dpp_configurator *conf; struct dpp_authentication *auth; unsigned int wait_time, max_wait_time; @@ -2067,7 +2067,11 @@ wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, group = WPA_GET_LE16(fcgroup); wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); - auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group); + a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len); + e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len); + + auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group, + a_nonce, a_nonce_len, e_id, e_id_len); if (!auth) return; wpas_dpp_set_testing_options(wpa_s, auth); @@ -3303,6 +3307,8 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = NULL; wpas_dpp_chirp_stop(wpa_s); + dpp_free_reconfig_id(wpa_s->dpp_reconfig_id); + wpa_s->dpp_reconfig_id = NULL; #endif /* CONFIG_DPP2 */ offchannel_send_action_done(wpa_s); wpas_dpp_listen_stop(wpa_s); @@ -3642,14 +3648,25 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) return -1; } + dpp_free_reconfig_id(wpa_s->dpp_reconfig_id); + wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign, + ssid->dpp_csign_len); + if (!wpa_s->dpp_reconfig_id) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to generate E-id for reconfiguration"); + return -1; + } wpas_dpp_chirp_stop(wpa_s); wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; wpa_s->dpp_qr_mutual = 0; + /* TODO: regenerate Reconfig Announcement frame to update A-NONCE/E'-id + * for each retransmission */ wpa_s->dpp_reconfig_announcement = dpp_build_reconfig_announcement(ssid->dpp_csign, ssid->dpp_csign_len, ssid->dpp_netaccesskey, - ssid->dpp_netaccesskey_len); + ssid->dpp_netaccesskey_len, + wpa_s->dpp_reconfig_id); if (!wpa_s->dpp_reconfig_announcement) return -1; wpa_s->dpp_reconfig_ssid = ssid; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 6dff477bf..d3a3da6e1 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1296,6 +1296,7 @@ struct wpa_supplicant { int dpp_chirp_listen; struct wpa_ssid *dpp_reconfig_ssid; int dpp_reconfig_ssid_id; + struct dpp_reconfig_id *dpp_reconfig_id; #endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS char *dpp_config_obj_override; From 6d0217119e1743557708150155d4e9ff62ed01b4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Aug 2020 23:22:31 +0300 Subject: [PATCH 0792/1105] DPP2: Allow iteration count to be configured for DPP_RECONFIG Add an optional iter=# parameter to DPP_RECONFIG similarly to the way this was handled with DPP_CHIRP. Signed-off-by: Jouni Malinen --- wpa_supplicant/ctrl_iface.c | 5 +---- wpa_supplicant/dpp_supplicant.c | 23 +++++++++++++++++++---- wpa_supplicant/dpp_supplicant.h | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 6dfce2aaa..4b669b057 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -11217,10 +11217,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { wpas_dpp_chirp_stop(wpa_s); } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) { - struct wpa_ssid *ssid; - - ssid = wpa_config_get_network(wpa_s->conf, atoi(buf + 13)); - if (!ssid || wpas_dpp_reconfig(wpa_s, ssid) < 0) + if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0) reply_len = -1; } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) { if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 1184591e4..346fd9e28 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3636,11 +3636,26 @@ void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s) } -int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) +int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd) { - if (!ssid->dpp_connector || !ssid->dpp_netaccesskey || - !ssid->dpp_csign) + struct wpa_ssid *ssid; + int iter = 1; + const char *pos; + + ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); + if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey || + !ssid->dpp_csign) { + wpa_printf(MSG_DEBUG, + "DPP: Not a valid network profile for reconfiguration"); return -1; + } + + pos = os_strstr(cmd, " iter="); + if (pos) { + iter = atoi(pos + 6); + if (iter <= 0) + return -1; + } if (wpa_s->dpp_auth) { wpa_printf(MSG_DEBUG, @@ -3671,7 +3686,7 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) return -1; wpa_s->dpp_reconfig_ssid = ssid; wpa_s->dpp_reconfig_ssid_id = ssid->id; - wpa_s->dpp_chirp_iter = 1; + wpa_s->dpp_chirp_iter = iter; wpa_s->dpp_chirp_round = 0; wpa_s->dpp_chirp_scan_done = 0; wpa_s->dpp_chirp_listen = 0; diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h index 081615b95..b0d5fcf18 100644 --- a/wpa_supplicant/dpp_supplicant.h +++ b/wpa_supplicant/dpp_supplicant.h @@ -39,7 +39,7 @@ void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s, enum dpp_status_error result); int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd); void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s); -int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd); #endif /* DPP_SUPPLICANT_H */ From b591810f9b1766ee3f88035ae6875ea762a9bfbc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Aug 2020 23:33:59 +0300 Subject: [PATCH 0793/1105] DPP2: Add DPP Status attribute into Reconfig Auth Confirm Add and process DPP Status at the end of reconfig authentication. Signed-off-by: Jouni Malinen --- src/common/dpp_reconfig.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index b12c4f7d0..ae796b945 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -627,11 +627,16 @@ dpp_reconfig_build_conf(struct dpp_authentication *auth) wpabuf_put_buf(clear, reconfig_flags); attr_len = 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; + attr_len += 4 + 1; msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_CONF, attr_len); if (!msg) goto fail; attr_start = wpabuf_put(msg, 0); + + /* DPP Status */ + dpp_build_attr_status(msg, DPP_STATUS_OK); + attr_end = wpabuf_put(msg, 0); /* OUI, OUI type, Crypto Suite, DPP frame type */ @@ -860,9 +865,9 @@ int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len) { const u8 *trans_id, *version, *wrapped_data, *i_nonce, *r_nonce, - *reconfig_flags; + *reconfig_flags, *status; u16 trans_id_len, version_len, wrapped_data_len, i_nonce_len, - r_nonce_len, reconfig_flags_len; + r_nonce_len, reconfig_flags_len, status_len; const u8 *addr[2]; size_t len[2]; u8 *unwrapped = NULL; @@ -882,11 +887,26 @@ int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, } wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", wrapped_data, wrapped_data_len); + attr_len = wrapped_data - 4 - attr_start; + + status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, + &status_len); + if (!status || status_len < 1) { + dpp_auth_fail(auth, + "Missing or invalid required DPP Status attribute"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); + if (status[0] != DPP_STATUS_OK) { + dpp_auth_fail(auth, + "Reconfiguration did not complete successfully"); + goto fail; + } addr[0] = hdr; len[0] = DPP_HDR_LEN; addr[1] = attr_start; - len[1] = 0; + len[1] = attr_len; wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", From 9304d1b3c3caa7dd9b708657ab68517354732158 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Aug 2020 23:43:51 +0300 Subject: [PATCH 0794/1105] DPP2: Regenerate Reconfig Announcement for each transmission This is needed to generate a new unique A-NONCE and E'-id values. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 37 +++++++++++++++++-------------- wpa_supplicant/wpa_supplicant_i.h | 1 - 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 346fd9e28..224c40b9b 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -2128,7 +2128,7 @@ wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, "DPP: Not ready for reconfiguration - pending authentication exchange in progress"); return; } - if (!wpa_s->dpp_reconfig_announcement || !wpa_s->dpp_reconfig_ssid) { + if (!wpa_s->dpp_reconfig_ssid) { wpa_printf(MSG_DEBUG, "DPP: Not ready for reconfiguration - not requested"); return; @@ -3392,13 +3392,26 @@ static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s, static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s) { - struct wpabuf *msg; + struct wpabuf *msg, *announce = NULL; int type; msg = wpa_s->dpp_presence_announcement; type = DPP_PA_PRESENCE_ANNOUNCEMENT; if (!msg) { - msg = wpa_s->dpp_reconfig_announcement; + struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid; + + if (ssid && wpa_s->dpp_reconfig_id && + wpa_config_get_network(wpa_s->conf, + wpa_s->dpp_reconfig_ssid_id) == + ssid) { + announce = dpp_build_reconfig_announcement( + ssid->dpp_csign, + ssid->dpp_csign_len, + ssid->dpp_netaccesskey, + ssid->dpp_netaccesskey_len, + wpa_s->dpp_reconfig_id); + msg = announce; + } if (!msg) return; type = DPP_PA_RECONFIG_ANNOUNCEMENT; @@ -3412,6 +3425,8 @@ static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s) wpabuf_head(msg), wpabuf_len(msg), 2000, wpas_dpp_chirp_tx_status, 0) < 0) wpas_dpp_chirp_stop(wpa_s); + + wpabuf_free(announce); } @@ -3424,7 +3439,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, int c; struct wpa_bss *bss; - if (!bi && !wpa_s->dpp_reconfig_announcement) + if (!bi && !wpa_s->dpp_reconfig_ssid) return; wpa_s->dpp_chirp_scan_done = 1; @@ -3612,15 +3627,13 @@ int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd) void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s) { if (wpa_s->dpp_presence_announcement || - wpa_s->dpp_reconfig_announcement) { + wpa_s->dpp_reconfig_ssid) { offchannel_send_action_done(wpa_s); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED); } wpa_s->dpp_chirp_bi = NULL; wpabuf_free(wpa_s->dpp_presence_announcement); wpa_s->dpp_presence_announcement = NULL; - wpabuf_free(wpa_s->dpp_reconfig_announcement); - wpa_s->dpp_reconfig_announcement = NULL; if (wpa_s->dpp_chirp_listen) wpas_dpp_listen_stop(wpa_s); wpa_s->dpp_chirp_listen = 0; @@ -3674,16 +3687,6 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd) wpas_dpp_chirp_stop(wpa_s); wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; wpa_s->dpp_qr_mutual = 0; - /* TODO: regenerate Reconfig Announcement frame to update A-NONCE/E'-id - * for each retransmission */ - wpa_s->dpp_reconfig_announcement = - dpp_build_reconfig_announcement(ssid->dpp_csign, - ssid->dpp_csign_len, - ssid->dpp_netaccesskey, - ssid->dpp_netaccesskey_len, - wpa_s->dpp_reconfig_id); - if (!wpa_s->dpp_reconfig_announcement) - return -1; wpa_s->dpp_reconfig_ssid = ssid; wpa_s->dpp_reconfig_ssid_id = ssid->id; wpa_s->dpp_chirp_iter = iter; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index d3a3da6e1..9f513c6fe 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1285,7 +1285,6 @@ struct wpa_supplicant { #ifdef CONFIG_DPP2 struct dpp_pfs *dpp_pfs; int dpp_pfs_fallback; - struct wpabuf *dpp_reconfig_announcement; struct wpabuf *dpp_presence_announcement; struct dpp_bootstrap_info *dpp_chirp_bi; int dpp_chirp_freq; From b58cd7aa1c5204b933891527e7a07973e6dcefdd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 7 Aug 2020 23:45:58 +0300 Subject: [PATCH 0795/1105] tests: DPP reconfiguration retries Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 8910f4d99..59999e0a4 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5444,7 +5444,21 @@ def test_dpp_reconfig_connector_different_groups(dev, apdev): finally: dev[0].set("dpp_config_processing", "0", allow_fail=True) -def run_dpp_reconfig_connector(dev, apdev, conf_curve=None): +@long_duration_test +def test_dpp_reconfig_retries(dev, apdev): + """DPP reconfiguration retries""" + try: + run_dpp_reconfig_connector(dev, apdev, test_retries=True) + for i in range(4): + ev = dev[0].wait_event(["DPP-TX "], timeout=120) + if ev is None or "type=14" not in ev: + raise Exception("Reconfig Announcement not sent") + dev[0].request("DPP_STOP_LISTEN") + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_reconfig_connector(dev, apdev, conf_curve=None, + test_retries=False): check_dpp_capab(dev[0], min_ver=2) check_dpp_capab(dev[1], min_ver=2) @@ -5529,6 +5543,12 @@ def run_dpp_reconfig_connector(dev, apdev, conf_curve=None): dev[0].dump_monitor() dev[1].dump_monitor() + if test_retries: + dev[1].request("DPP_STOP_LISTEN") + if "OK" not in dev[0].request("DPP_RECONFIG %s iter=10" % id): + raise Exception("Failed to start reconfiguration") + return + dev[1].set("dpp_configurator_params", "conf=sta-psk ssid=%s pass=%s conn_status=1" % (binascii.hexlify(ssid.encode()).decode(), binascii.hexlify(passphrase2.encode()).decode())) dev[1].dpp_listen(2437) From 5caf4e094a3c07adccee3f5a571a5480ad9a7d05 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 10 Aug 2020 10:41:20 +0300 Subject: [PATCH 0796/1105] DPP2: Support RA/CA functionality in Controller initiated case Extend dpp_control_get_auth() to find the ongoing session for enterprise credential provisioning in cases where the Controller/Configurator initiated the exchange. Only the other direction was supported previously. Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 639ff8c9f..33874400e 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -1678,6 +1678,29 @@ void dpp_controller_stop(struct dpp_global *dpp) } +static bool dpp_tcp_peer_id_match(struct dpp_authentication *auth, + unsigned int id) +{ + return auth && + ((auth->peer_bi && auth->peer_bi->id == id) || + (auth->tmp_peer_bi && auth->tmp_peer_bi->id == id)); +} + + +static struct dpp_authentication * dpp_tcp_get_auth(struct dpp_global *dpp, + unsigned int id) +{ + struct dpp_connection *conn; + + dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) { + if (dpp_tcp_peer_id_match(conn->auth, id)) + return conn->auth; + } + + return NULL; +} + + struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, unsigned int id) { @@ -1685,18 +1708,14 @@ struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, struct dpp_connection *conn; if (!ctrl) - return NULL; + return dpp_tcp_get_auth(dpp, id); dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) { - struct dpp_authentication *auth = conn->auth; - - if (auth && - ((auth->peer_bi && auth->peer_bi->id == id) || - (auth->tmp_peer_bi && auth->tmp_peer_bi->id == id))) - return auth; + if (dpp_tcp_peer_id_match(conn->auth, id)) + return conn->auth; } - return NULL; + return dpp_tcp_get_auth(dpp, id); } From 57e2e5ed7a5d6207ec693f22baa754758eb7fbd7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 10 Aug 2020 10:42:49 +0300 Subject: [PATCH 0797/1105] tests: DPP over TCP for enterprise provisioning (Controller initiating) Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 69 ++++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 59999e0a4..e5a57bd5f 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5874,17 +5874,6 @@ def run_dpp_enterprise_tcp(dev, apdev, params): check_dpp_capab(dev[1]) cap_lo = params['prefix'] + ".lo.pcap" - cert_file = params['prefix'] + ".cert.pem" - pkcs7_file = params['prefix'] + ".pkcs7.der" - - with open("auth_serv/ec-ca.pem", "rb") as f: - res = f.read() - cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, - res) - - with open("auth_serv/ec-ca.key", "rb") as f: - res = f.read() - cakey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, res) wt = WlantestCapture('lo', cap_lo) time.sleep(1) @@ -5902,6 +5891,20 @@ def run_dpp_enterprise_tcp(dev, apdev, params): raise Exception("Failed to start Controller") dev[0].dpp_auth_init(uri=uri_c, role="enrollee", tcp_addr="127.0.0.1") + run_dpp_enterprise_tcp_end(params, dev, wt) + +def run_dpp_enterprise_tcp_end(params, dev, wt): + cert_file = params['prefix'] + ".cert.pem" + pkcs7_file = params['prefix'] + ".pkcs7.der" + + with open("auth_serv/ec-ca.pem", "rb") as f: + res = f.read() + cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + res) + + with open("auth_serv/ec-ca.key", "rb") as f: + res = f.read() + cakey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, res) ev = dev[1].wait_event(["DPP-CSR"], timeout=10) if ev is None: @@ -5945,3 +5948,47 @@ def run_dpp_enterprise_tcp(dev, apdev, params): time.sleep(0.5) wt.close() + +def test_dpp_enterprise_tcp2(dev, apdev, params): + """DPP over TCP for enterprise provisioning (Controller initiating)""" + try: + run_dpp_enterprise_tcp2(dev, apdev, params) + finally: + dev[0].request("DPP_CONTROLLER_STOP") + dev[1].request("DPP_CONTROLLER_STOP") + +def run_dpp_enterprise_tcp2(dev, apdev, params): + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + cap_lo = params['prefix'] + ".lo.pcap" + cert_file = params['prefix'] + ".cert.pem" + pkcs7_file = params['prefix'] + ".pkcs7.der" + + with open("auth_serv/ec-ca.pem", "rb") as f: + res = f.read() + cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + res) + + with open("auth_serv/ec-ca.key", "rb") as f: + res = f.read() + cakey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, res) + + wt = WlantestCapture('lo', cap_lo) + time.sleep(1) + + # Client/Enrollee/Responder + id_e = dev[0].dpp_bootstrap_gen() + uri_e = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id_e) + req = "DPP_CONTROLLER_START" + if "OK" not in dev[0].request(req): + raise Exception("Failed to start Client/Enrollee") + + # Controller/Configurator/Initiator + conf_id = dev[1].dpp_configurator_add() + csrattrs = "MAsGCSqGSIb3DQEJBw==" + dev[1].dpp_auth_init(uri=uri_e, role="configurator", configurator=conf_id, + conf="sta-dot1x", csrattrs=csrattrs, + tcp_addr="127.0.0.1") + + run_dpp_enterprise_tcp_end(params, dev, wt) From 66ffe9d246b104e3ff82fded016fd74cea327a89 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 10 Aug 2020 17:36:56 +0300 Subject: [PATCH 0798/1105] DPP2: Update Reconfig Flags attribute format This was simplified by replacing the JSON encoded value with a single octet. Signed-off-by: Jouni Malinen --- src/common/dpp_reconfig.c | 60 +++++++-------------------------------- 1 file changed, 11 insertions(+), 49 deletions(-) diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index ae796b945..a361131db 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -563,40 +563,19 @@ fail: } -static struct wpabuf * -dpp_build_reconfig_flags(enum dpp_connector_key connector_key) -{ - struct wpabuf *json; - - json = wpabuf_alloc(100); - if (!json) - return NULL; - json_start_object(json, NULL); - json_add_int(json, "connectorKey", connector_key); - json_end_object(json); - wpa_hexdump_ascii(MSG_DEBUG, "DPP: Reconfig-Flags JSON", - wpabuf_head(json), wpabuf_len(json)); - - return json; -} - - struct wpabuf * dpp_reconfig_build_conf(struct dpp_authentication *auth) { - struct wpabuf *msg = NULL, *clear = NULL, *reconfig_flags; + struct wpabuf *msg = NULL, *clear; u8 *attr_start, *attr_end; size_t clear_len, attr_len, len[2]; const u8 *addr[2]; u8 *wrapped; - - reconfig_flags = dpp_build_reconfig_flags(DPP_CONFIG_REPLACEKEY); - if (!reconfig_flags) - goto fail; + u8 flags; /* Build DPP Reconfig Authentication Confirm frame attributes */ clear_len = 4 + 1 + 4 + 1 + 2 * (4 + auth->curve->nonce_len) + - 4 + wpabuf_len(reconfig_flags); + 4 + 1; clear = wpabuf_alloc(clear_len); if (!clear) goto fail; @@ -622,9 +601,10 @@ dpp_reconfig_build_conf(struct dpp_authentication *auth) wpabuf_put_data(clear, auth->r_nonce, auth->curve->nonce_len); /* Reconfig-Flags (wrapped) */ + flags = DPP_CONFIG_REPLACEKEY; wpabuf_put_le16(clear, DPP_ATTR_RECONFIG_FLAGS); - wpabuf_put_le16(clear, wpabuf_len(reconfig_flags)); - wpabuf_put_buf(clear, reconfig_flags); + wpabuf_put_le16(clear, 1); + wpabuf_put_u8(clear, flags); attr_len = 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; attr_len += 4 + 1; @@ -665,7 +645,6 @@ dpp_reconfig_build_conf(struct dpp_authentication *auth) msg); out: - wpabuf_free(reconfig_flags); wpabuf_free(clear); return msg; fail: @@ -872,8 +851,8 @@ int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, size_t len[2]; u8 *unwrapped = NULL; size_t unwrapped_len = 0; - struct json_token *root = NULL, *token; int res = -1; + u8 flags; if (!auth->reconfig || auth->configurator) goto fail; @@ -967,34 +946,17 @@ int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_RECONFIG_FLAGS, &reconfig_flags_len); - if (!reconfig_flags) { + if (!reconfig_flags || reconfig_flags_len < 1) { dpp_auth_fail(auth, "Missing or invalid Reconfig-Flags"); goto fail; } - wpa_hexdump_ascii(MSG_DEBUG, "DPP: Reconfig-Flags", - reconfig_flags, reconfig_flags_len); - root = json_parse((const char *) reconfig_flags, reconfig_flags_len); - if (!root) { - dpp_auth_fail(auth, "Could not parse Reconfig-Flags"); - goto fail; - } - token = json_get_member(root, "connectorKey"); - if (!token || token->type != JSON_NUMBER) { - dpp_auth_fail(auth, "No connectorKey in Reconfig-Flags"); - goto fail; - } - if (token->number != DPP_CONFIG_REUSEKEY && - token->number != DPP_CONFIG_REPLACEKEY) { - dpp_auth_fail(auth, - "Unsupported connectorKey value in Reconfig-Flags"); - goto fail; - } - auth->reconfig_connector_key = token->number; + flags = reconfig_flags[0] & BIT(0); + wpa_printf(MSG_DEBUG, "DPP: Reconfig Flags connectorKey=%u", flags); + auth->reconfig_connector_key = flags; auth->reconfig_success = true; res = 0; fail: - json_free(root); bin_clear_free(unwrapped, unwrapped_len); return res; } From 315422196ab5109930c20a2f77cdd88204b9a1b6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 10 Aug 2020 23:52:11 +0300 Subject: [PATCH 0799/1105] dpp-nfc: Update listen channel based on channel list when writing a tag Do not use the hardcoded channel 1 (2412 MHz) with DPP_LISTEN if a channel list is specified when writing an NFC Tag. Instead, pick the first channel from that list as the listen channel. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 5c5d947f0..4027c5e23 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -202,6 +202,8 @@ def wpas_get_nfc_uri(start_listen=True, pick_channel=False, chan_override=None): chan = chan_override else: chan = chanlist + if chan and chan.startswith("81/"): + listen_freq = int(chan[3:].split(',')[0]) * 5 + 2407 if chan is None and get_status_field(wpas, "bssid[0]"): freq = get_status_field(wpas, "freq") if freq: From 86fd6755cbe59ee438e35237cc96ae1f46ed417b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 11 Aug 2020 23:44:48 +0300 Subject: [PATCH 0800/1105] dpp-nfc: Use --altchan value in handover server Use the alternative channel list in the handover server role when processing an alternative proposal. This was previously done only in the handover client role, but with the updated design, both roles act in a similar manner for the case where the alternative channel list is specified. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 4027c5e23..e0d11f412 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -467,6 +467,7 @@ def run_dpp_handover_client(handover, alt=False): summary("DPP carrier not seen in response - do not allow alternative proposal anymore") elif not dpp_found: summary("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") + handover.alt_proposal = True handover.my_crn_ready = False handover.my_crn = None handover.peer_crn = None @@ -523,6 +524,7 @@ class HandoverServer(nfc.handover.HandoverServer): resp = self._process_request_data(req) if resp is None or len(resp) == 0: summary("No handover select to send out - wait for a possible alternative handover request") + handover.alt_proposal = True req = bytearray() continue @@ -605,6 +607,11 @@ class HandoverServer(nfc.handover.HandoverServer): if test_uri: summary("TEST MODE: Using specified URI") data = test_sel_uri if test_sel_uri else test_uri + elif handover.alt_proposal and handover.altchanlist: + summary("Use alternative channel list while processing alternative proposal from peer") + data = wpas_get_nfc_uri(start_listen=False, + chan_override=handover.altchanlist, + pick_channel=True) else: data = wpas_get_nfc_uri(start_listen=False, pick_channel=True) @@ -918,6 +925,7 @@ class ConnectionHandover(): self.my_uri = None self.peer_uri = None self.connected = False + self.alt_proposal = False def start_handover_server(self, llc): summary("Start handover server") From 61c249c490d5bad6f158987c0bc02c696e986055 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Thu, 6 Aug 2020 13:01:49 +0530 Subject: [PATCH 0801/1105] Add QCA vendor attribute to configure number of TX/RX chains Add support to configure the number of TX chains and the number of RX chains to be used during a connection. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index e31f2d251..e1a57f67b 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2273,6 +2273,23 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE = 72, + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of chains to be used for transmitting data. This + * configuration is allowed only when in connected state and will be + * effective until disconnected. The driver rejects this configuration + * if the number of spatial streams being used in the current connection + * cannot be supported by this configuration. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS = 73, + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of chains to be used for receiving data. This + * configuration is allowed only when in connected state and will be + * effective until disconnected. The driver rejects this configuration + * if the number of spatial streams being used in the current connection + * cannot be supported by this configuration. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS = 74, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = From e4e95aabbfbc080f7ff91a6ee96a637217a73b1f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 12 Aug 2020 11:41:52 +0300 Subject: [PATCH 0802/1105] DPP2: Allow Controller to be configured to require QR mutual auth Extend the DPP_CONTROLLER_START command to accept the optional qr=mutual parameter similarly to the DPP_LISTEN case. Signed-off-by: Jouni Malinen --- src/common/dpp.h | 1 + src/common/dpp_tcp.c | 2 +- wpa_supplicant/dpp_supplicant.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/dpp.h b/src/common/dpp.h index 8243a97b6..feee8e1e8 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -384,6 +384,7 @@ struct dpp_controller_config { const char *configurator_params; int tcp_port; u8 allowed_roles; + int qr_mutual; }; #ifdef CONFIG_TESTING_OPTIONS diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 33874400e..53fe67f81 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -1622,7 +1622,7 @@ int dpp_controller_start(struct dpp_global *dpp, os_strdup(config->configurator_params); dl_list_init(&ctrl->conn); ctrl->allowed_roles = config->allowed_roles; - ctrl->qr_mutual = 0; + ctrl->qr_mutual = config->qr_mutual; ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); if (ctrl->sock < 0) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 224c40b9b..3119445ac 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3350,6 +3350,8 @@ int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) else return -1; } + + config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL; } config.configurator_params = wpa_s->dpp_configurator_params; return dpp_controller_start(wpa_s->dpp, &config); From 2e956c37d2237581c1f31bd86d1972c8d46d0c29 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 12 Aug 2020 11:52:25 +0300 Subject: [PATCH 0803/1105] DPP2: Do not close TCP socket when waiting for full Auth Resp The case where mutual authentication with QR Code bootstrapping is used with scanning of the QR Code during the exchange resulted in the Controller closing the TCP socket too early. Fix this by leaving the socket open while waiting for the full Authentication Response message. Signed-off-by: Jouni Malinen --- src/common/dpp_tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 53fe67f81..90dd38fc0 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -661,7 +661,7 @@ static int dpp_controller_rx_auth_resp(struct dpp_connection *conn, if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { wpa_printf(MSG_DEBUG, "DPP: Start wait for full response"); - return -1; + return 0; } wpa_printf(MSG_DEBUG, "DPP: No confirm generated"); dpp_connection_remove(conn); From fc3efe0834e64eafca38236700111e0f9ab32329 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 12 Aug 2020 12:04:25 +0300 Subject: [PATCH 0804/1105] DPP2: Support mutual auth with QR in scan-during-auth-exchange case Extend DPP authentication session search for the DPP_QR_CODE command to cover the ongoing exchanges in Controller/Responder. Signed-off-by: Jouni Malinen --- src/common/dpp.h | 2 ++ src/common/dpp_tcp.c | 22 ++++++++++++++++++++++ wpa_supplicant/dpp_supplicant.c | 4 ++++ 3 files changed, 28 insertions(+) diff --git a/src/common/dpp.h b/src/common/dpp.h index feee8e1e8..a8526b14d 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -668,6 +668,8 @@ int dpp_controller_start(struct dpp_global *dpp, void dpp_controller_stop(struct dpp_global *dpp); struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, unsigned int id); +void dpp_controller_new_qr_code(struct dpp_global *dpp, + struct dpp_bootstrap_info *bi); int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port, const char *name); diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 90dd38fc0..83aff1ca9 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -1719,6 +1719,28 @@ struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, } +void dpp_controller_new_qr_code(struct dpp_global *dpp, + struct dpp_bootstrap_info *bi) +{ + struct dpp_controller *ctrl = dpp->controller; + struct dpp_connection *conn; + + if (!ctrl) + return; + + dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) { + struct dpp_authentication *auth = conn->auth; + + if (!auth->response_pending || + dpp_notify_new_qr_code(auth, bi) != 1) + continue; + wpa_printf(MSG_DEBUG, + "DPP: Sending out pending authentication response"); + dpp_tcp_send_msg(conn, conn->auth->resp_msg); + } +} + + void dpp_tcp_init_flush(struct dpp_global *dpp) { struct dpp_connection *conn, *tmp; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 3119445ac..7d226ac76 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -90,6 +90,10 @@ int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd) 500, wpas_dpp_tx_status, 0); } +#ifdef CONFIG_DPP2 + dpp_controller_new_qr_code(wpa_s->dpp, bi); +#endif /* CONFIG_DPP2 */ + return bi->id; } From ab676bc1fa7c42899e859031bc392ca8014b1dbf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 12 Aug 2020 12:08:26 +0300 Subject: [PATCH 0805/1105] tests: DPP over TCP (mutual) Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index e5a57bd5f..736248f92 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -4787,7 +4787,15 @@ def test_dpp_tcp_port(dev, apdev, params): finally: dev[1].request("DPP_CONTROLLER_STOP") -def run_dpp_tcp(dev, apdev, cap_lo, port=None): +def test_dpp_tcp_mutual(dev, apdev, params): + """DPP over TCP (mutual)""" + cap_lo = os.path.join(params['prefix'], ".lo.pcap") + try: + run_dpp_tcp(dev, apdev, cap_lo, mutual=True) + finally: + dev[1].request("DPP_CONTROLLER_STOP") + +def run_dpp_tcp(dev, apdev, cap_lo, port=None, mutual=False): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) @@ -4812,12 +4820,36 @@ def run_dpp_tcp(dev, apdev, cap_lo, port=None): req = "DPP_CONTROLLER_START" if port: req += " tcp_port=" + port + if mutual: + req += " qr=mutual" + id0 = dev[0].dpp_bootstrap_gen() + uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + own = id0 + else: + own = None if "OK" not in dev[1].request(req): raise Exception("Failed to start Controller") # Initiate from Enrollee with broadcast DPP Authentication Request - dev[0].dpp_auth_init(uri=uri_c, role="enrollee", tcp_addr="127.0.0.1", - tcp_port=port) + dev[0].dpp_auth_init(uri=uri_c, own=own, role="enrollee", + tcp_addr="127.0.0.1", tcp_port=port) + + if mutual: + ev = dev[0].wait_event(["DPP-RESPONSE-PENDING"], timeout=5) + if ev is None: + raise Exception("Pending response not reported") + ev = dev[1].wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5) + if ev is None: + raise Exception("QR Code scan for mutual authentication not requested") + + id1 = dev[1].dpp_qr_code(uri0) + + ev = dev[0].wait_event(["DPP-AUTH-DIRECTION"], timeout=5) + if ev is None: + raise Exception("DPP authentication direction not indicated (Initiator)") + if "mutual=1" not in ev: + raise Exception("Mutual authentication not used") + wait_auth_success(dev[1], dev[0], configurator=dev[1], enrollee=dev[0], allow_enrollee_failure=True, allow_configurator_failure=True) From 574a8fa6c84efad4f98df294cddbe102114e1bfd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 12 Aug 2020 17:57:21 +0300 Subject: [PATCH 0806/1105] DPP: Do not interpret unknown channel as missing channel list for NFC While the listed unknown operating class/channel number pairs need to be ignored, that should be done in a manner than prevents the parsed bootstrapping info from being used as if it had no channel list (i.e., allowing any channel) if there are no known operating class/channel number pairs. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 5 +++-- src/common/dpp.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index de8a4a4ad..bc349229b 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -245,6 +245,7 @@ int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi, wpa_printf(MSG_DEBUG, "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d", opclass, channel, freq); + bi->channels_listed = true; if (freq < 0) { wpa_printf(MSG_DEBUG, "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)", @@ -4030,11 +4031,11 @@ static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi, u8 op_class, channel; char chan[20]; - if (peer_bi->num_freq == 0) + if (peer_bi->num_freq == 0 && !peer_bi->channels_listed) return 0; /* no channel preference/constraint */ for (i = 0; i < peer_bi->num_freq; i++) { - if (own_bi->num_freq == 0 || + if ((own_bi->num_freq == 0 && !own_bi->channels_listed) || freq_included(own_bi->freq, own_bi->num_freq, peer_bi->freq[i])) { freq = peer_bi->freq[i]; diff --git a/src/common/dpp.h b/src/common/dpp.h index a8526b14d..9cf1019ae 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -153,6 +153,7 @@ struct dpp_bootstrap_info { char *pk; unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; unsigned int num_freq; + bool channels_listed; u8 version; int own; EVP_PKEY *pubkey; From 2afc46a0a9a66cf2896404b3646ffce68f6efe79 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 13 Aug 2020 17:01:32 +0300 Subject: [PATCH 0807/1105] tests: sigma_dut and second DPP reconfiguration Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index bddb97fc1..6f66399ef 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3361,6 +3361,28 @@ def test_sigma_dut_dpp_reconfig_enrollee(dev, apdev): raise Exception("DPP Config Response (reconfig) not transmitted") dev[0].wait_connected() + ev = dev[1].wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20) + if ev is None: + raise Exception("No connection status reported") + if "result=0" not in ev: + raise Exception("Connection status did not report success: " + ev) + + time.sleep(1) + cmd = "DPP_LISTEN 2437 role=configurator" + if "OK" not in dev[1].request(cmd): + raise Exception("Failed to start listen operation") + dev[0].dump_monitor() + dev[1].dump_monitor() + + res = sigma_dut_cmd("dev_exec_action,program,DPP,DPPActionType,DPPReconfigure,DPPTimeout,6,DPPWaitForConnect,Yes", timeout=30) + if "status,COMPLETE,ReconfigAuthResult,OK,ConfResult,OK,NetworkConnectResult,OK" not in res: + raise Exception("Unexpected reconfiguration [2] result: " + res) + + ev = dev[1].wait_event(["DPP-CONF-SENT"], timeout=5) + if ev is None: + raise Exception("DPP Config Response (reconfig) not transmitted [2]") + + dev[0].wait_connected() finally: dev[0].set("dpp_config_processing", "0") stop_sigma_dut(sigma) From 3adc1c623e8ebf44b5ad0ff0aac279686b030e3e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 13 Aug 2020 17:05:49 +0300 Subject: [PATCH 0808/1105] DPP2: Disconnect before starting reconfiguration The offchannel operations (scan, Public Action frame TX/RX) have significantly more latency when performed while connected, so disconnect when requested to initiate DPP reconfiguration to avoid this. The old network profile (i.e., likely the current connection) is going to be replaced in practice and as such, there is no need to try continue that association any further. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 7d226ac76..6dc0002eb 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3690,6 +3690,12 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd) "DPP: Failed to generate E-id for reconfiguration"); return -1; } + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { + wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration"); + wpa_s->own_disconnect_req = 1; + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + } wpas_dpp_chirp_stop(wpa_s); wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; wpa_s->dpp_qr_mutual = 0; From 096456c0c2cd316a3ab5635ab940794939dc81b9 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Thu, 6 Aug 2020 20:27:14 +0530 Subject: [PATCH 0809/1105] Enhancements to the TWT attributes/parameters (vendor command) This commit does the following enhancements to the TWT interface: Corrects the documentation for QCA_WLAN_TWT_SUSPEND and QCA_WLAN_TWT_TERMINATE. Specifies that these operations carry the parameters obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. This interface is very recently introduced and missed to document the same. There are no user space or driver components using this interface yet. Hence, enhancing/modifying the interface. Corrects the documentation for QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION. Mentions that the units it represent is a multiple of 256 microseconds rather than a TU. The host driver always interpreted this as an unit in 256 microseconds and there are no user space implementations that are impacted with this change in the unit. Hence, modifying the documentation. Introduces QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT_SIZE, which is similar to that of QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT, but carries an offset/data of u32 size. Introduces MAC_ADDR attribute to represent the peer for the TWT setup and resume operations. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 99 +++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 14 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index e1a57f67b..2637abc6e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7428,15 +7428,17 @@ enum qca_wlan_vendor_attr_wifi_test_config { * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_setup. * - * @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Does not carry any - * parameters. Valid only after the TWT session is setup. + * @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Required parameters are + * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup. * - * @QCA_WLAN_TWT_SUSPEND: Terminate the TWT session. Does not carry any - * parameters. Valid only after the TWT session is setup. + * @QCA_WLAN_TWT_SUSPEND: Suspend the TWT session. Required parameters are + * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup. * * @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are * configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum - * qca_wlan_vendor_attr_twt_resume. + * qca_wlan_vendor_attr_twt_resume. Valid only after the TWT session is setup. */ enum qca_wlan_twt_operation { QCA_WLAN_TWT_SET = 0, @@ -7633,10 +7635,13 @@ enum qca_wlan_vendor_attr_nan_params { * STA and AP. * Broadcast means the session is across multiple STAs and an AP. The * configuration parameters are announced in Beacon frames by the AP. + * This is used in + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE: Required (u8). * Unsigned 8-bit qca_wlan_vendor_twt_setup_req_type to - * specify the TWT request type + * specify the TWT request type. This is used in TWT SET operation. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER: Flag attribute * Enable (flag attribute present) - TWT with trigger support. @@ -7644,62 +7649,113 @@ enum qca_wlan_vendor_attr_nan_params { * Trigger means the AP will send the trigger frame to allow STA to send data. * Without trigger, the STA will wait for the MU EDCA timer before * transmitting the data. + * This is used in + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE: Required (u8) * 0 - Announced TWT - In this mode, STA may skip few service periods to * save more power. If STA wants to wake up, it will send a PS-POLL/QoS * NULL frame to AP. * 1 - Unannounced TWT - The STA will wakeup during every SP. + * This is a required parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID: Optional (u8) * Flow ID is the unique identifier for each TWT session. - * Currently this is not required and dialog ID will be set to zero. + * If not provided then dialog ID will be set to zero. + * This is an optional parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Request and Response + * 3. TWT TERMINATE Request and Response + * 4. TWT SUSPEND Request and Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8) * This attribute (exp) is used along with the mantissa to derive the * wake interval using the following formula: * pow(2,exp) = wake_intvl_us/wake_intvl_mantis * Wake interval is the interval between 2 successive SP. + * This is a required parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION: Flag attribute * Enable (flag attribute present) - Protection required. * Disable (flag attribute not present) - Protection not required. * If protection is enabled, then the AP will use protection * mechanism using RTS/CTS to self to reserve the airtime. + * This is used in + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME: Optional (u32) * This attribute is used as the SP offset which is the offset from * TSF after which the wake happens. The units are in microseconds. If * this attribute is not provided, then the value will be set to zero. + * This is an optional parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION: Required (u32) - * This is the duration of the service period. The units are in TU. + * This is the duration of the service period. This is specified as + * multiples of 256 microseconds. Valid values are 0x1 to 0xFF. + * This is a required parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA: Required (u32) * This attribute is used to configure wake interval mantissa. * The units are in TU. + * This is a required parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS: Required (u8) * This field is applicable for TWT response only. * This contains status values in enum qca_wlan_vendor_twt_status - * and is passed to the userspace. + * and is passed to the userspace. This is used in TWT SET operation. + * This is a required parameter for + * 1. TWT SET Response + * 2. TWT TERMINATE Response + * 3. TWT SUSPEND Response + * 4. TWT RESUME Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE: Required (u8) * This field is applicable for TWT response only. * This field contains response type from the TWT responder and is * passed to the userspace. The values for this field are defined in - * enum qca_wlan_vendor_twt_setup_resp_type. + * enum qca_wlan_vendor_twt_setup_resp_type. This is used in TWT SET + * response. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64) * This field is applicable for TWT response only. * This field contains absolute TSF value of the wake time received * from the TWT responder and is passed to the userspace. + * This is a required parameter for + * 1. TWT SET Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED: Flag attribute. * Enable (flag attribute present) - Indicates that the TWT responder * supports reception of TWT information frame from the TWT requestor. * Disable (flag attribute not present) - Indicates that the responder * doesn't support reception of TWT information frame from requestor. + * This is used in + * 1. TWT SET Response + * 2. TWT GET Response + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer for which the TWT session + * is being configured. This is used in AP mode to represent the respective + * client. In AP mode, this is an optional parameter for response and is + * a required parameter for + * 1. TWT SET Request + * 2. TWT GET Request + * 3. TWT TERMINATE Request + * 4. TWT SUSPEND Request + * In STA mode, this is an optional parameter in request and response for + * the above four TWT operations. */ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0, @@ -7720,6 +7776,8 @@ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF = 13, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED = 14, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR = 15, + /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX = @@ -7771,23 +7829,36 @@ enum qca_wlan_vendor_twt_status { * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT: Optional (u8) - * This attribute is used as the SP offset which is the offset from - * TSF after which the wake happens. The units are in microseconds. - * If this attribute is not provided, then the value will be set to - * zero. + * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT: Optional (u32) + * These attributes are used as the SP offset which is the offset from TSF after + * which the wake happens. The units are in microseconds. Please note that + * _NEXT_TWT is limited to u8 whereas _NEXT2_TWT takes the u32 data. + * _NEXT2_TWT takes the precedence over _NEXT_TWT and thus the recommendation + * is to use _NEXT2_TWT. If neither of these attributes is provided, the value + * will be set to zero. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE: Required (u32) * This attribute represents the next TWT subfield size. + * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits, + * and 4 for 64 bits. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID: Required (u8). * Flow ID is the unique identifier for each TWT session. This attribute * represents the respective TWT session to resume. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer to which TWT Resume is + * being sent. This is used in AP mode to represent the respective + * client and is a required parameter. In STA mode, this is an optional + * parameter */ enum qca_wlan_vendor_attr_twt_resume { QCA_WLAN_VENDOR_ATTR_TWT_RESUME_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT = 1, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE = 2, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID = 3, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT = 4, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR = 5, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST, From 9f9c110484fed16b0f6bdbcec3a6a6c37149b896 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Fri, 7 Aug 2020 13:09:39 +0530 Subject: [PATCH 0810/1105] Fix QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO interface documentation All QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_* attributes are also nested within QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO, not only QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO* attributes in the current implementation. Fix QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO documentation accordingly. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 2637abc6e..f45fdfde5 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -3467,7 +3467,7 @@ enum qca_wlan_vendor_attr_ll_stats_results { QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS = 66, /* Signifies the nested list of channel attributes - * QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_* + * QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_* */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO = 67, From f5388b34eb287c9ed133470df4b40b87fe38ba97 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Mon, 3 Aug 2020 18:04:06 +0530 Subject: [PATCH 0811/1105] Add channel TX/RX times to QCA vendor interface of LL stats Currently the driver/firmware indicates CCA busy time which includes own TX and RX time and as such, does not allow the CCA busy time due to other nodes to be computed. Add separate statistics to indicate own radio TX time and own radio RX time to facilitate userspace applications to compute CCA busy time because of traffic unintended to this device. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index f45fdfde5..659ae9c5f 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -3529,6 +3529,17 @@ enum qca_wlan_vendor_attr_ll_stats_results { */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_PENDING_MSDU = 83, + /* u32 value representing total time in milliseconds for which the radio + * is transmitting on this channel. This attribute will be nested + * within QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_TX_TIME = 84, + /* u32 value representing total time in milliseconds for which the radio + * is receiving all 802.11 frames intended for this device on this + * channel. This attribute will be nested within + * QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85, /* keep last */ QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX = From dbe485a35af87d416ef2c3665b1ad2b68aa49d98 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Mon, 10 Aug 2020 01:01:28 +0530 Subject: [PATCH 0812/1105] SAE-PK: Check psk param also to look for SAE-PK acceptable BSS SAE-PK password can be set using psk parameter also in case of mixed SAE+PSK networks, so look for acceptable SAE-PK BSS when SAE password not set and psk parameter meets SAE-PK password criteria. Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/events.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 0fcb1762e..f19165373 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1440,7 +1440,10 @@ skip_assoc_disallow: #ifdef CONFIG_SAE_PK if (ssid->sae_pk == SAE_PK_MODE_AUTOMATIC && wpa_key_mgmt_sae(ssid->key_mgmt) && - ssid->sae_password && sae_pk_valid_password(ssid->sae_password) && + ((ssid->sae_password && + sae_pk_valid_password(ssid->sae_password)) || + (!ssid->sae_password && ssid->passphrase && + sae_pk_valid_password(ssid->passphrase))) && !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) && sae_pk_acceptable_bss_with_pk(wpa_s, bss, ssid, match_ssid, match_ssid_len)) { From 1289ecf4cc4e1dd9a10a4430060d3fdc7de0ccbb Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Tue, 11 Aug 2020 01:19:49 +0530 Subject: [PATCH 0813/1105] GAS: Ignore preassoc_mac_addr when gas_rand_mac_addr enabled Skip unnecessary random MAC generation due to preassoc_mac_addr parameter when gas_rand_mac_addr parameter is enabled. Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/gas_query.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c index 4b3fcfcfa..941692111 100644 --- a/wpa_supplicant/gas_query.c +++ b/wpa_supplicant/gas_query.c @@ -694,7 +694,7 @@ static void gas_query_start_cb(struct wpa_radio_work *work, int deinit) return; } - if (!query->maintain_addr && + if (!query->maintain_addr && !wpa_s->conf->gas_rand_mac_addr && wpas_update_random_addr_disassoc(wpa_s) < 0) { wpa_msg(wpa_s, MSG_INFO, "Failed to assign random MAC address for GAS"); From 43106e122b27811e9d47b48c6f5feca838858fc1 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Tue, 11 Aug 2020 01:31:49 +0530 Subject: [PATCH 0814/1105] GAS: Update source MAC address on preassoc_mac_addr randomization The GAS query source MAC address was not getting updated correctly when preassoc_mac_addr is enabled. Fix this by copying the current MAC address to the GAS query source address. Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/gas_query.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c index 941692111..e60a8c1fe 100644 --- a/wpa_supplicant/gas_query.c +++ b/wpa_supplicant/gas_query.c @@ -694,13 +694,15 @@ static void gas_query_start_cb(struct wpa_radio_work *work, int deinit) return; } - if (!query->maintain_addr && !wpa_s->conf->gas_rand_mac_addr && - wpas_update_random_addr_disassoc(wpa_s) < 0) { - wpa_msg(wpa_s, MSG_INFO, - "Failed to assign random MAC address for GAS"); - gas_query_free(query, 1); - radio_work_done(work); - return; + if (!query->maintain_addr && !wpa_s->conf->gas_rand_mac_addr) { + if (wpas_update_random_addr_disassoc(wpa_s) < 0) { + wpa_msg(wpa_s, MSG_INFO, + "Failed to assign random MAC address for GAS"); + gas_query_free(query, 1); + radio_work_done(work); + return; + } + os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN); } gas->work = work; From 170775232d615e149484e3a68341211af04a8efe Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Tue, 11 Aug 2020 17:53:17 +0530 Subject: [PATCH 0815/1105] ANQP: Add support to specify frequency in ANQP_GET command Previously, wpa_supplicant fetched BSS channel info from scan results to send ANQP Query frames. If the scan results for the specified BSS are not available, the ANQP_GET command request was getting rejected. Add support to send ANQP Query frame on the specified frequency without requiring the scan results to be available. The control interface command format: - ANQP_GET [freq=] [,,..] Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/ctrl_iface.c | 13 +++++++++++-- wpa_supplicant/interworking.c | 21 ++++++++++++++------- wpa_supplicant/interworking.h | 2 +- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 4b669b057..0dcb0398c 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -7466,7 +7466,7 @@ static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst, static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) { u8 dst_addr[ETH_ALEN]; - int used; + int used, freq = 0; char *pos; #define MAX_ANQP_INFO_ID 100 u16 id[MAX_ANQP_INFO_ID]; @@ -7480,6 +7480,15 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) pos = dst + used; if (*pos == ' ') pos++; + + if (os_strncmp(pos, "freq=", 5) == 0) { + freq = atoi(pos + 5); + pos = os_strchr(pos, ' '); + if (!pos) + return -1; + pos++; + } + while (num_id < MAX_ANQP_INFO_ID) { if (os_strncmp(pos, "hs20:", 5) == 0) { #ifdef CONFIG_HS20 @@ -7514,7 +7523,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) if (num_id == 0 && !subtypes && !mbo_subtypes) return -1; - return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes, + return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes, mbo_subtypes); } diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index b1ddd0925..00e1492c6 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -2750,27 +2750,27 @@ void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s) } -int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, +int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, int freq, u16 info_ids[], size_t num_ids, u32 subtypes, u32 mbo_subtypes) { struct wpabuf *buf; struct wpabuf *extra_buf = NULL; int ret = 0; - int freq; struct wpa_bss *bss; int res; bss = wpa_bss_get_bssid(wpa_s, dst); - if (!bss) { + if (!bss && !freq) { wpa_printf(MSG_WARNING, - "ANQP: Cannot send query to unknown BSS " - MACSTR, MAC2STR(dst)); + "ANQP: Cannot send query without BSS freq info"); return -1; } - wpa_bss_anqp_unshare_alloc(bss); - freq = bss->freq; + if (bss) + wpa_bss_anqp_unshare_alloc(bss); + if (bss && !freq) + freq = bss->freq; wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Query Request to " MACSTR " for %u id(s)", @@ -2789,6 +2789,13 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, if (mbo_subtypes) { struct wpabuf *mbo; + if (!bss) { + wpa_printf(MSG_WARNING, + "ANQP: Cannot send MBO query to unknown BSS " + MACSTR, MAC2STR(dst)); + return -1; + } + mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_subtypes); if (mbo) { if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) { diff --git a/wpa_supplicant/interworking.h b/wpa_supplicant/interworking.h index 37ee2e904..77b2c91bd 100644 --- a/wpa_supplicant/interworking.h +++ b/wpa_supplicant/interworking.h @@ -11,7 +11,7 @@ enum gas_query_result; -int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, +int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, int freq, u16 info_ids[], size_t num_ids, u32 subtypes, u32 mbo_subtypes); void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, From 97e6ead42348bcc76f5dcc29f720a321a3e2e025 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 13 Aug 2020 17:49:16 +0300 Subject: [PATCH 0816/1105] tests: GAS/ANQP query without scan Signed-off-by: Jouni Malinen --- tests/hwsim/test_gas.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/hwsim/test_gas.py b/tests/hwsim/test_gas.py index ec132f712..5d60779e9 100644 --- a/tests/hwsim/test_gas.py +++ b/tests/hwsim/test_gas.py @@ -487,6 +487,25 @@ def test_gas_anqp_get(dev, apdev): if "FAIL" not in dev[0].request("HS20_ANQP_GET " + cmd): raise Exception("Invalid HS20_ANQP_GET accepted") +def test_gas_anqp_get_no_scan(dev, apdev): + """GAS/ANQP query without scan""" + hapd = start_ap(apdev[0]) + bssid = apdev[0]['bssid'] + if "OK" not in dev[0].request("ANQP_GET " + bssid + " freq=2412 258"): + raise Exception("ANQP_GET command failed") + ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) + if ev is None: + raise Exception("ANQP query timed out") + dev[0].dump_monitor() + + if "OK" not in dev[0].request("ANQP_GET 02:11:22:33:44:55 freq=2417 258"): + raise Exception("ANQP_GET command failed") + ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) + if ev is None: + raise Exception("ANQP query timed out [2]") + if "result=FAILURE" not in ev: + raise Exception("Unexpected result: " + ev) + def test_gas_anqp_get_oom(dev, apdev): """GAS/ANQP query OOM""" hapd = start_ap(apdev[0]) From cc9fe46b3ac217d1092104a913124d7512788c0b Mon Sep 17 00:00:00 2001 From: Harshal Udas Date: Fri, 24 Jul 2020 12:39:32 -0700 Subject: [PATCH 0817/1105] Add AllPlay type to the QCA vendor element Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 659ae9c5f..b3a661314 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -1,7 +1,7 @@ /* * Qualcomm Atheros OUI and vendor specific assignments * Copyright (c) 2014-2017, Qualcomm Atheros, Inc. - * Copyright (c) 2018-2019, The Linux Foundation + * Copyright (c) 2018-2020, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -1741,6 +1741,8 @@ enum qca_vendor_attr_wisa_cmd { * (not including the Element ID Extension field). Please note that the * draft is still work in progress and this element payload is subject to * change. + * + * @QCA_VENDOR_ELEM_ALLPLAY: Allplay element */ enum qca_vendor_element_id { QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0, @@ -1749,6 +1751,7 @@ enum qca_vendor_element_id { QCA_VENDOR_ELEM_RAPS = 3, QCA_VENDOR_ELEM_MU_EDCA_PARAMS = 4, QCA_VENDOR_ELEM_BSS_COLOR_CHANGE = 5, + QCA_VENDOR_ELEM_ALLPLAY = 6, }; /** From cd708e8ff945a5914f5e3224ce8b275d5be6659a Mon Sep 17 00:00:00 2001 From: Min Liu Date: Mon, 20 Jul 2020 19:27:11 +0800 Subject: [PATCH 0818/1105] Add a vendor command for medium assessment Introduce a vendor command for medium assessment through QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS. Signed-off-by: Min Liu --- src/common/qca-vendor.h | 98 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index b3a661314..3f97f857e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -675,6 +675,10 @@ enum qca_radiotap_vendor_ids { * @QCA_NL80211_VENDOR_SUBCMD_GETBAND: Command to get the enabled band(s) from * the driver. The band configurations obtained are referred through * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. + * + * @QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS: Vendor subcommand/event for medium + * assessment. + * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -857,6 +861,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC = 190, QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT = 191, QCA_NL80211_VENDOR_SUBCMD_GETBAND = 192, + QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193, }; enum qca_wlan_vendor_attr { @@ -9572,4 +9577,97 @@ enum qca_wlan_vendor_attr_oci_override { QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_AFTER_LAST - 1, }; +/** + * enum qca_wlan_medium_assess_type - Type of medium assess request + * + * Values for %QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE. + */ +enum qca_wlan_medium_assess_type { + QCA_WLAN_MEDIUM_ASSESS_CCA = 0, + QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT = 1, +}; + +/** + * enum qca_wlan_vendor_attr_medium_assess - Attributes used by + * %QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS vendor command. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE: + * u8 attribute. Mandatory in all kinds of medium assess requests/responses. + * Specify the type of medium assess request and indicate its type in response. + * Possible values are defined in enum qca_wlan_medium_assess_type. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_PERIOD: + * u32 attribute. Mandatory in CCA request. + * Specify the assessment period in terms of seconds. Assessment result will be + * sent as the response to the CCA request after the assessment period. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TOTAL_CYCLE_COUNT: + * u32 attribute. Mandatory in response to CCA request. + * Total timer tick count of the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IDLE_COUNT: + * u32 attribute. Mandatory in response to CCA request. + * Timer tick count of idle time in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IBSS_RX_COUNT: + * u32 attribute. Mandatory in response to CCA request. + * Timer tick count of Intra BSS traffic RX time in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_OBSS_RX_COUNT: + * u32 attribute. Mandatory in response to CCA request. + * Timer tick count of Overlapping BSS traffic RX time in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX_IBSS_RSSI: + * s32 attribute. Mandatory in response to CCA request. + * Maximum RSSI of Intra BSS traffic in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MIN_IBSS_RSSI: + * s32 attribute. Mandatory in response to CCA request. + * Minimum RSSI of Intra BSS traffic in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_ENABLE: + * u8 attribute. Mandatory in congestion report request. + * 1-enable 0-disable. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_THRESHOLD: + * u8 attribute. Mandatory in congestion report enable request and will be + * ignored if present in congestion report disable request. Possible values are + * 0-100. A vendor event QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS with the type + * QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT will be sent to userspace if + * congestion percentage reaches the configured threshold. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_INTERVAL: + * u8 attribute. Optional in congestion report enable request and will be + * ignored if present in congestion report disable request. + * Specify the interval of congestion report event in terms of seconds. Possible + * values are 1-255. Default value 1 will be used if this attribute is omitted + * or using invalid values. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_PERCENTAGE: + * u8 attribute. Mandatory in congestion report event. + * Indicate the actual congestion percentage. Possible values are 0-100. + */ +enum qca_wlan_vendor_attr_medium_assess { + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE = 1, + + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_PERIOD = 2, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TOTAL_CYCLE_COUNT = 3, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IDLE_COUNT = 4, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IBSS_RX_COUNT = 5, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_OBSS_RX_COUNT = 6, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX_IBSS_RSSI = 7, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MIN_IBSS_RSSI = 8, + + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_ENABLE = 9, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_THRESHOLD = 10, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_INTERVAL = 11, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_PERCENTAGE = 12, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX = + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST - 1, +}; + #endif /* QCA_VENDOR_H */ From 5644b23de1f0ed384b489d77db92af2036f2e3df Mon Sep 17 00:00:00 2001 From: Pooventhiran G Date: Wed, 8 Jul 2020 17:30:05 +0530 Subject: [PATCH 0819/1105] QCA vendor command to update SSID Add a QCA vendor subcommand QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID to update the new SSID in hostapd. NL80211_ATTR_SSID is used to encapsulate the new SSID. Signed-off-by: Pooventhiran G --- src/common/qca-vendor.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 3f97f857e..eed44f7b7 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -679,6 +679,10 @@ enum qca_radiotap_vendor_ids { * @QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS: Vendor subcommand/event for medium * assessment. * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess. + * + * @QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID: This acts as a vendor event and is + * used to update SSID information in hostapd when it is updated in the + * driver. Uses the attribute NL80211_ATTR_SSID. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -862,6 +866,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT = 191, QCA_NL80211_VENDOR_SUBCMD_GETBAND = 192, QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193, + QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194, }; enum qca_wlan_vendor_attr { From 0fa274d2bf608a574114f5c051c4c35edc706f7c Mon Sep 17 00:00:00 2001 From: Rohan Date: Thu, 16 Jul 2020 19:35:14 +0530 Subject: [PATCH 0820/1105] Derive seg0_idx and seg1_idx for 6 GHz when processing channel switch The function hostapd_event_ch_switch() derived the seg0_idx and seg1_idx values only for the 5 GHz and 2.4 GHz bands and the 6 GHz case ended up using incorrect calculation based on the 5 GHz channel definitions. Fix this by adding support for 6 GHz frequencies. Signed-off-by: Rohan --- src/ap/drv_callbacks.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 36678e7a3..9faac0ddc 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -893,9 +893,18 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, switch (hapd->iface->current_mode->mode) { case HOSTAPD_MODE_IEEE80211A: - if (cf1 > 5000) + if (cf1 == 5935) + seg0_idx = (cf1 - 5925) / 5; + else if (cf1 > 5950) + seg0_idx = (cf1 - 5950) / 5; + else if (cf1 > 5000) seg0_idx = (cf1 - 5000) / 5; - if (cf2 > 5000) + + if (cf2 == 5935) + seg1_idx = (cf2 - 5925) / 5; + else if (cf2 > 5950) + seg1_idx = (cf2 - 5950) / 5; + else if (cf2 > 5000) seg1_idx = (cf2 - 5000) / 5; break; default: From 596d99567ae185419499ac4fe672418e140547a9 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Sun, 2 Aug 2020 16:55:05 +0530 Subject: [PATCH 0821/1105] SME: Process channel switch event in SME only when supplicant's SME is used Do not process channel switch event in wpa_supplicant's SME when SME is offloaded to the driver/firmware to avoid SA Query initiation from both wpa_supplicant and the driver/firmware for the OCV case. Signed-off-by: Jouni Malinen --- wpa_supplicant/events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index f19165373..bd1af8915 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4945,7 +4945,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, } #endif /* CONFIG_AP */ - sme_event_ch_switch(wpa_s); + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) + sme_event_ch_switch(wpa_s); + wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS); wnm_clear_coloc_intf_reporting(wpa_s); break; From 1733e356e42166bbe2481ac4c41be335ac5fe7c1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 14 Aug 2020 00:11:44 +0300 Subject: [PATCH 0822/1105] dpp-nfc: Fix handover client wait for receiving handover select This was supposed to wait for up to 3.0 seconds for the handover select, but the incorrect loop terminated ended up limiting this to a single iteration of 0.1 second wait. This was too fast for some cases like the AP mode operation where it may take significant time to enable the radio for listening to DPP authentication messages. Fix the loop to allow that full three second wait for the response to be used. In addition, report the amount of time it takes to receive the response. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index e0d11f412..83241330d 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -278,8 +278,15 @@ class HandoverClient(nfc.handover.HandoverClient): def recv_octets(self, timeout=None): start = time.time() msg = bytearray() - poll_timeout = 0.1 if timeout is None or timeout > 0.1 else timeout - while self.socket.poll('recv', poll_timeout): + while True: + poll_timeout = 0.1 if timeout is None or timeout > 0.1 else timeout + if self.socket.poll('recv', poll_timeout) is None: + if timeout: + timeout -= time.time() - start + if timeout <= 0: + return None + start = time.time() + continue try: r = self.socket.recv() if r is None: @@ -372,7 +379,10 @@ def run_dpp_handover_client(handover, alt=False): summary("Receiving handover response") try: + start = time.time() message = client.recv_records(timeout=3.0) + end = time.time() + summary("Received {} record(s) in {} seconds".format(len(message) if message is not None else -1, end - start)) except Exception as e: # This is fine if we are the handover selector if handover.hs_sent: From a118047245b0861acdf6a9f8410237705f12d995 Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Tue, 4 Aug 2020 20:12:24 +0530 Subject: [PATCH 0823/1105] MSCS: Add support to send MSCS Request frames Add support to send MSCS add/change/remove types of Action frames to the connected AP. Signed-off-by: Vinita S. Maloo --- src/common/ieee802_11_defs.h | 19 ++++++ wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + wpa_supplicant/ctrl_iface.c | 76 ++++++++++++++++++++++++ wpa_supplicant/robust_av.c | 98 +++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant.c | 5 +- wpa_supplicant/wpa_supplicant_i.h | 16 +++++ 7 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 wpa_supplicant/robust_av.c diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 4d3037eee..1e09e1610 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -478,6 +478,8 @@ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 #define WLAN_EID_EXT_EDMG_CAPABILITIES 61 #define WLAN_EID_EXT_EDMG_OPERATION 62 +#define WLAN_EID_EXT_MSCS_DESCRIPTOR 88 +#define WLAN_EID_EXT_TCLAS_MASK 89 #define WLAN_EID_EXT_REJECTED_GROUPS 92 #define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93 @@ -562,6 +564,7 @@ #define WLAN_EXT_CAPAB_SAE_PW_ID 81 #define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82 #define WLAN_EXT_CAPAB_BEACON_PROTECTION 84 +#define WLAN_EXT_CAPAB_MSCS 85 #define WLAN_EXT_CAPAB_SAE_PK_EXCLUSIVELY 88 /* Extended RSN Capabilities */ @@ -2340,4 +2343,20 @@ enum edmg_bw_config { /* DPP Public Action frame identifiers - OUI_WFA */ #define DPP_OUI_TYPE 0x1A +/* Robust AV streaming Action field values */ +enum robust_av_streaming_action { + ROBUST_AV_SCS_REQ = 0, + ROBUST_AV_SCS_RESP = 1, + ROBUST_AV_GROUP_MEMBERSHIP_REQ = 2, + ROBUST_AV_GROUP_MEMBERSHIP_RESP = 3, + ROBUST_AV_MSCS_REQ = 4, + ROBUST_AV_MSCS_RESP = 5, +}; + +enum scs_request_type { + SCS_REQ_ADD = 0, + SCS_REQ_REMOVE = 1, + SCS_REQ_CHANGE = 2, +}; + #endif /* IEEE802_11_DEFS_H */ diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 0f24d7b71..ed7e358ac 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -98,6 +98,7 @@ OBJS += src/utils/crc32.c OBJS += wmm_ac.c OBJS += op_classes.c OBJS += rrm.c +OBJS += robust_av.c OBJS_p = wpa_passphrase.c OBJS_p += src/utils/common.c OBJS_p += src/utils/wpa_debug.c diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 09ac7a493..a01a32982 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -107,6 +107,7 @@ OBJS += ../src/utils/ip_addr.o OBJS += ../src/utils/crc32.o OBJS += op_classes.o OBJS += rrm.o +OBJS += robust_av.o OBJS_p = wpa_passphrase.o OBJS_p += ../src/utils/common.o OBJS_p += ../src/utils/wpa_debug.o diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 0dcb0398c..5048ee83e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8483,6 +8483,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->next_scan_bssid_wildcard_ssid = 0; os_free(wpa_s->select_network_scan_freqs); wpa_s->select_network_scan_freqs = NULL; + os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data)); wpa_bss_flush(wpa_s); if (!dl_list_empty(&wpa_s->bss)) { @@ -8508,6 +8509,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_supplicant_update_channel_list(wpa_s, NULL); free_bss_tmp_disallowed(wpa_s); + + os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data)); } @@ -10342,6 +10345,76 @@ static int wpas_ctrl_cmd_debug_level(const char *cmd) } +static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s, + const char *cmd) +{ + size_t frame_classifier_len; + const char *pos, *end; + struct robust_av_data *robust_av = &wpa_s->robust_av; + int val; + + /* + * format: + * [up_bitmap=] [up_limit=] + * [stream_timeout=] [frame_classifier=] + */ + os_memset(robust_av, 0, sizeof(struct robust_av_data)); + if (os_strncmp(cmd, "add ", 4) == 0) { + robust_av->request_type = SCS_REQ_ADD; + } else if (os_strcmp(cmd, "remove") == 0) { + robust_av->request_type = SCS_REQ_REMOVE; + robust_av->valid_config = false; + return wpas_send_mscs_req(wpa_s); + } else if (os_strncmp(cmd, "change ", 7) == 0) { + robust_av->request_type = SCS_REQ_CHANGE; + } else { + return -1; + } + + pos = os_strstr(cmd, "up_bitmap="); + if (!pos) + return -1; + + val = hex2byte(pos + 10); + if (val < 0) + return -1; + robust_av->up_bitmap = val; + + pos = os_strstr(cmd, "up_limit="); + if (!pos) + return -1; + + robust_av->up_limit = atoi(pos + 9); + + pos = os_strstr(cmd, "stream_timeout="); + if (!pos) + return -1; + + robust_av->stream_timeout = atoi(pos + 15); + if (robust_av->stream_timeout == 0) + return -1; + + pos = os_strstr(cmd, "frame_classifier="); + if (!pos) + return -1; + + pos += 17; + end = os_strchr(pos, ' '); + if (!end) + end = pos + os_strlen(pos); + + frame_classifier_len = (end - pos) / 2; + if (frame_classifier_len > sizeof(robust_av->frame_classifier) || + hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len)) + return -1; + + robust_av->frame_classifier_len = frame_classifier_len; + robust_av->valid_config = true; + + return wpas_send_mscs_req(wpa_s); +} + + char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char *buf, size_t *resp_len) { @@ -11233,6 +11306,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ + } else if (os_strncmp(buf, "MSCS ", 5) == 0) { + if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5)) + reply_len = -1; } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c new file mode 100644 index 000000000..6bb4e3e95 --- /dev/null +++ b/wpa_supplicant/robust_av.c @@ -0,0 +1,98 @@ +/* + * wpa_supplicant - Robust AV procedures + * Copyright (c) 2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "common/wpa_ctrl.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "bss.h" + + +void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, + struct wpabuf *buf) +{ + u8 *len, *len1; + + /* MSCS descriptor element */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + len = wpabuf_put(buf, 1); + wpabuf_put_u8(buf, WLAN_EID_EXT_MSCS_DESCRIPTOR); + wpabuf_put_u8(buf, robust_av->request_type); + wpabuf_put_u8(buf, robust_av->up_bitmap); + wpabuf_put_u8(buf, robust_av->up_limit); + wpabuf_put_le32(buf, robust_av->stream_timeout); + + if (robust_av->request_type != SCS_REQ_REMOVE) { + /* TCLAS mask element */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + len1 = wpabuf_put(buf, 1); + wpabuf_put_u8(buf, WLAN_EID_EXT_TCLAS_MASK); + + /* Frame classifier */ + wpabuf_put_data(buf, robust_av->frame_classifier, + robust_av->frame_classifier_len); + *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1; + } + + *len = (u8 *) wpabuf_put(buf, 0) - len - 1; +} + + +int wpas_send_mscs_req(struct wpa_supplicant *wpa_s) +{ + struct wpabuf *buf; + const u8 *ext_capab = NULL; + size_t buf_len; + int ret; + + if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) + return 0; + + if (wpa_s->current_bss) + ext_capab = wpa_bss_get_ie(wpa_s->current_bss, + WLAN_EID_EXT_CAPAB); + + if (!ext_capab || ext_capab[1] < 11 || !(ext_capab[12] & 0x20)) { + wpa_dbg(wpa_s, MSG_INFO, + "AP does not support MSCS - could not send MSCS Req"); + return -1; + } + + buf_len = 3 + /* Action frame header */ + 3 + /* MSCS descriptor IE header */ + 1 + /* Request type */ + 2 + /* User priority control */ + 4 + /* Stream timeout */ + 3 + /* TCLAS Mask IE header */ + wpa_s->robust_av.frame_classifier_len; + + buf = wpabuf_alloc(buf_len); + if (!buf) { + wpa_printf(MSG_ERROR, "Failed to allocate MSCS req"); + return -1; + } + + wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING); + wpabuf_put_u8(buf, ROBUST_AV_MSCS_REQ); + wpa_s->robust_av.dialog_token++; + wpabuf_put_u8(buf, wpa_s->robust_av.dialog_token); + + /* MSCS descriptor element */ + wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf); + + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", wpabuf_head(buf)); + ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0); + if (ret < 0) + wpa_dbg(wpa_s, MSG_INFO, "MSCS: Failed to send MSCS Request"); + + wpabuf_free(buf); + return ret; +} diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 6eb09f496..4134d089b 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1899,6 +1899,9 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) *pos |= 0x01; #endif /* CONFIG_FILS */ break; + case 10: /* Bits 80-87 */ + *pos |= 0x20; /* Bit 85 - Mirrored SCS */ + break; } } @@ -1906,7 +1909,7 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen) { u8 *pos = buf; - u8 len = 10, i; + u8 len = 11, i; if (len < wpa_s->extended_capa_len) len = wpa_s->extended_capa_len; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 9f513c6fe..44f5f375a 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -491,6 +491,17 @@ struct driver_signal_override { int scan_level; }; +struct robust_av_data { + u8 dialog_token; + enum scs_request_type request_type; + u8 up_bitmap; + u8 up_limit; + u32 stream_timeout; + u8 frame_classifier[48]; + size_t frame_classifier_len; + bool valid_config; +}; + /** * struct wpa_supplicant - Internal data for wpa_supplicant interface * @@ -1315,6 +1326,7 @@ struct wpa_supplicant { unsigned int multi_ap_ie:1; unsigned int multi_ap_backhaul:1; unsigned int multi_ap_fronthaul:1; + struct robust_av_data robust_av; }; @@ -1623,4 +1635,8 @@ int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s); void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s); +int wpas_send_mscs_req(struct wpa_supplicant *wpa_s); +void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, + struct wpabuf *buf); + #endif /* WPA_SUPPLICANT_I_H */ From bbd3178af45b49c66ed50c2a4da7a26d93a73430 Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Wed, 3 Jun 2020 20:54:04 +0530 Subject: [PATCH 0824/1105] MSCS: Add support to process MSCS Response frames Add support to receive and process MSCS Response frames from the AP and indicate the status to upper layers. Signed-off-by: Vinita S. Maloo --- src/common/wpa_ctrl.h | 2 ++ src/drivers/driver_nl80211.c | 4 ++++ wpa_supplicant/events.c | 7 +++++++ wpa_supplicant/robust_av.c | 23 +++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 3 +++ 5 files changed, 39 insertions(+) diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index f5199de9a..4e42c890f 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -126,6 +126,8 @@ extern "C" { #define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT " /** Frequency ranges that the driver recommends to avoid */ #define WPA_EVENT_AVOID_FREQ "CTRL-EVENT-AVOID-FREQ " +/** Result of MSCS setup */ +#define WPA_EVENT_MSCS_RESULT "CTRL-EVENT-MSCS-RESULT " /** WPS overlap detected in PBC mode */ #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " /** Available WPS AP with active PBC found in scan results */ diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 14179f79b..2ee34d11d 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -2451,6 +2451,10 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) (nl80211_register_action_frame(bss, (u8 *) "\x05\x02", 2) < 0)) ret = -1; + /* Robust AV MSCS Response */ + if (nl80211_register_action_frame(bss, (u8 *) "\x13\x05", 2) < 0) + ret = -1; + nl80211_mgmt_handle_register_eloop(bss); return ret; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index bd1af8915..3b169dae4 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4245,6 +4245,13 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_DPP */ + if (category == WLAN_ACTION_ROBUST_AV_STREAMING && + payload[0] == ROBUST_AV_MSCS_RESP) { + wpas_handle_robust_av_recv_action(wpa_s, mgmt->sa, + payload + 1, plen - 1); + return; + } + wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, category, payload, plen, freq); if (wpa_s->ifmsh) diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c index 6bb4e3e95..f7e4100e5 100644 --- a/wpa_supplicant/robust_av.c +++ b/wpa_supplicant/robust_av.c @@ -96,3 +96,26 @@ int wpas_send_mscs_req(struct wpa_supplicant *wpa_s) wpabuf_free(buf); return ret; } + + +void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, + const u8 *src, const u8 *buf, size_t len) +{ + u8 dialog_token; + u16 status_code; + + if (len < 3) + return; + + dialog_token = *buf++; + if (dialog_token != wpa_s->robust_av.dialog_token) { + wpa_printf(MSG_INFO, + "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u", + dialog_token, wpa_s->robust_av.dialog_token); + return; + } + + status_code = *buf; + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR + " status_code=%u", MAC2STR(src), status_code); +} diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 44f5f375a..9ed886ff5 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1638,5 +1638,8 @@ void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s); int wpas_send_mscs_req(struct wpa_supplicant *wpa_s); void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, struct wpabuf *buf); +void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, + const u8 *src, const u8 *buf, + size_t len); #endif /* WPA_SUPPLICANT_I_H */ From c504ff5398faa07b80bbf10becbcf0ebda516f29 Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Tue, 16 Jun 2020 20:21:30 +0530 Subject: [PATCH 0825/1105] MSCS: Add support to populate MSCS Descriptor IE in (Re)AssocReq Include the MSCS Descriptor IE in the (Re)Association Request frames to setup MSCS between the AP and the STA during association. Signed-off-by: Vinita S. Maloo --- wpa_supplicant/sme.c | 36 +++++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant.c | 34 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index c761fdad1..789846905 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1880,6 +1880,42 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, pfs_fail: #endif /* CONFIG_DPP2 */ + if (wpa_s->current_bss && wpa_s->robust_av.valid_config) { + struct wpabuf *mscs_ie; + size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len; + + if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS)) + goto mscs_fail; + + buf_len = 3 + /* MSCS descriptor IE header */ + 1 + /* Request type */ + 2 + /* User priority control */ + 4 + /* Stream timeout */ + 3 + /* TCLAS Mask IE header */ + wpa_s->robust_av.frame_classifier_len; + mscs_ie = wpabuf_alloc(buf_len); + if (!mscs_ie) { + wpa_printf(MSG_INFO, + "MSCS: Failed to allocate MSCS IE"); + goto mscs_fail; + } + + wpa_ie_len = &wpa_s->sme.assoc_req_ie_len; + max_ie_len = sizeof(wpa_s->sme.assoc_req_ie); + wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie); + if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) { + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", + wpabuf_head(mscs_ie)); + mscs_ie_len = wpabuf_len(mscs_ie); + os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len, + wpabuf_head(mscs_ie), mscs_ie_len); + *wpa_ie_len += mscs_ie_len; + } + + wpabuf_free(mscs_ie); + } +mscs_fail: + if (ssid && ssid->multi_ap_backhaul_sta) { size_t multi_ap_ie_len; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 4134d089b..9365c0717 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3192,6 +3192,40 @@ pfs_fail: wpa_ie_len += wpa_s->rsnxe_len; } + if (bss && wpa_s->robust_av.valid_config) { + struct wpabuf *mscs_ie; + size_t mscs_ie_len, buf_len; + + if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) + goto mscs_fail; + + buf_len = 3 + /* MSCS descriptor IE header */ + 1 + /* Request type */ + 2 + /* User priority control */ + 4 + /* Stream timeout */ + 3 + /* TCLAS Mask IE header */ + wpa_s->robust_av.frame_classifier_len; + mscs_ie = wpabuf_alloc(buf_len); + if (!mscs_ie) { + wpa_printf(MSG_INFO, + "MSCS: Failed to allocate MSCS IE"); + goto mscs_fail; + } + + wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie); + if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) { + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", + wpabuf_head(mscs_ie)); + mscs_ie_len = wpabuf_len(mscs_ie); + os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie), + mscs_ie_len); + wpa_ie_len += mscs_ie_len; + } + + wpabuf_free(mscs_ie); + } +mscs_fail: + if (ssid->multi_ap_backhaul_sta) { size_t multi_ap_ie_len; From af8ab3208d03ba841b63ca6a91e4a1094e35f8fb Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Wed, 5 Aug 2020 22:55:32 +0530 Subject: [PATCH 0826/1105] MSCS: Parse result of MSCS setup in (Re)Association Response frames Add support to parse the (Re)Association Response frames to check if the AP has accepted/declined the MSCS request in response to the corresponding (Re)Association Request frame. AP indicates the result by setting it in the optional MSCS Status subelement of MSCS Descriptor element in (Re)Association Response frame. This MSCS Status subelement is defined in the process of being added into P802.11-REVmd/D4.0 (11-20-0516-17-000m-cr-mscs-and-cid4158). Signed-off-by: Vinita S. Maloo --- src/common/ieee802_11_defs.h | 5 +++++ wpa_supplicant/events.c | 15 ++++++++++----- wpa_supplicant/robust_av.c | 27 +++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 2 ++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 1e09e1610..86d71c156 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2359,4 +2359,9 @@ enum scs_request_type { SCS_REQ_CHANGE = 2, }; +/* Optional subelement IDs for MSCS Descriptor element */ +enum mscs_description_subelem { + MCSC_SUBELEM_STATUS = 1, +}; + #endif /* IEEE802_11_DEFS_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 3b169dae4..80b803f5c 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2678,11 +2678,11 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, { int l, len, found = 0, found_x = 0, wpa_found, rsn_found; const u8 *p; -#if defined(CONFIG_IEEE80211R) || defined(CONFIG_OWE) u8 bssid[ETH_ALEN]; -#endif /* CONFIG_IEEE80211R || CONFIG_OWE */ + bool bssid_known; wpa_dbg(wpa_s, MSG_DEBUG, "Association info event"); + bssid_known = wpa_drv_get_bssid(wpa_s, bssid) == 0; if (data->assoc_info.req_ies) wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies, data->assoc_info.req_ies_len); @@ -2799,7 +2799,7 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, #ifdef CONFIG_OWE if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && - (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + (!bssid_known || owe_process_assoc_resp(wpa_s->wpa, bssid, data->assoc_info.resp_ies, data->assoc_info.resp_ies_len) < 0)) { @@ -2834,7 +2834,7 @@ no_pfs: #ifdef CONFIG_IEEE80211R #ifdef CONFIG_SME if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) { - if (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + if (!bssid_known || wpa_ft_validate_reassoc_resp(wpa_s->wpa, data->assoc_info.resp_ies, data->assoc_info.resp_ies_len, @@ -2894,7 +2894,7 @@ no_pfs: /* Process FT when SME is in the driver */ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && wpa_ft_is_completed(wpa_s->wpa)) { - if (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + if (!bssid_known || wpa_ft_validate_reassoc_resp(wpa_s->wpa, data->assoc_info.resp_ies, data->assoc_info.resp_ies_len, @@ -2912,6 +2912,11 @@ no_pfs: data->assoc_info.resp_ies_len); #endif /* CONFIG_IEEE80211R */ + if (bssid_known) + wpas_handle_assoc_resp_mscs(wpa_s, bssid, + data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); + /* WPA/RSN IE from Beacon/ProbeResp */ p = data->assoc_info.beacon_ies; l = data->assoc_info.beacon_ies_len; diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c index f7e4100e5..86f47d295 100644 --- a/wpa_supplicant/robust_av.c +++ b/wpa_supplicant/robust_av.c @@ -9,6 +9,7 @@ #include "utils/includes.h" #include "utils/common.h" #include "common/wpa_ctrl.h" +#include "common/ieee802_11_common.h" #include "wpa_supplicant_i.h" #include "driver_i.h" #include "bss.h" @@ -119,3 +120,29 @@ void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR " status_code=%u", MAC2STR(src), status_code); } + + +void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, + const u8 *ies, size_t ies_len) +{ + const u8 *mscs_desc_ie, *mscs_status; + u16 status; + + /* Process optional MSCS Status subelement when MSCS IE is in + * (Re)Association Response frame */ + if (!ies || ies_len == 0 || !wpa_s->robust_av.valid_config) + return; + + mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR); + if (!mscs_desc_ie || mscs_desc_ie[1] < 1) + return; + + mscs_status = get_ie(mscs_desc_ie, mscs_desc_ie[1], + MCSC_SUBELEM_STATUS); + if (!mscs_status || mscs_status[1] < 2) + return; + + status = WPA_GET_LE16(mscs_status + 2); + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR + " status_code=%u", MAC2STR(bssid), status); +} diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 9ed886ff5..775590058 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1641,5 +1641,7 @@ void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *buf, size_t len); +void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, + const u8 *ies, size_t ies_len); #endif /* WPA_SUPPLICANT_I_H */ From d21dde9dacd3a6ae2f671cc029f1d439c152e477 Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Wed, 5 Aug 2020 00:03:24 +0530 Subject: [PATCH 0827/1105] MSCS: Send MSCS change/remove frames only if MSCS setup exists Allow MSCS change/remove request to be sent only after an initial setup, i.e., after an add request has been accepted. Signed-off-by: Vinita S. Maloo --- wpa_supplicant/robust_av.c | 9 +++++++++ wpa_supplicant/sme.c | 1 + wpa_supplicant/wpa_supplicant.c | 1 + wpa_supplicant/wpa_supplicant_i.h | 1 + 4 files changed, 12 insertions(+) diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c index 86f47d295..31315517a 100644 --- a/wpa_supplicant/robust_av.c +++ b/wpa_supplicant/robust_av.c @@ -65,6 +65,13 @@ int wpas_send_mscs_req(struct wpa_supplicant *wpa_s) return -1; } + if (!wpa_s->mscs_setup_done && + wpa_s->robust_av.request_type != SCS_REQ_ADD) { + wpa_msg(wpa_s, MSG_INFO, + "MSCS: Failed to send MSCS Request: request type invalid"); + return -1; + } + buf_len = 3 + /* Action frame header */ 3 + /* MSCS descriptor IE header */ 1 + /* Request type */ @@ -119,6 +126,7 @@ void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, status_code = *buf; wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR " status_code=%u", MAC2STR(src), status_code); + wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS; } @@ -145,4 +153,5 @@ void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, status = WPA_GET_LE16(mscs_status + 2); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR " status_code=%u", MAC2STR(bssid), status); + wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS; } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 789846905..592c742fa 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1880,6 +1880,7 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, pfs_fail: #endif /* CONFIG_DPP2 */ + wpa_s->mscs_setup_done = false; if (wpa_s->current_bss && wpa_s->robust_av.valid_config) { struct wpabuf *mscs_ie; size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 9365c0717..3d2c0a985 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3540,6 +3540,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0); wpa_s->rsnxe_len = 0; + wpa_s->mscs_setup_done = false; wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, ¶ms, NULL); if (!wpa_ie) { diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 775590058..31a9b7427 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1327,6 +1327,7 @@ struct wpa_supplicant { unsigned int multi_ap_backhaul:1; unsigned int multi_ap_fronthaul:1; struct robust_av_data robust_av; + bool mscs_setup_done; }; From 6aa7aa808907749bc54000b456519a196a5d5991 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 14 Aug 2020 16:44:38 +0300 Subject: [PATCH 0828/1105] DPP2: hostapd/AP as Enrollee/Initiator over TCP Extend DPP support in hostapd to allow AP Enrollee role when initiating the exchange using TCP. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 59 +++++++++++++++++++++++++-------- src/common/dpp.h | 2 +- src/common/dpp_tcp.c | 9 +++-- wpa_supplicant/dpp_supplicant.c | 2 +- 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 70027ad6e..9b9232d4c 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -490,8 +490,15 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) { const char *pos; struct dpp_bootstrap_info *peer_bi, *own_bi = NULL; + struct dpp_authentication *auth; u8 allowed_roles = DPP_CAPAB_CONFIGURATOR; unsigned int neg_freq = 0; + int tcp = 0; +#ifdef CONFIG_DPP2 + int tcp_port = DPP_TCP_PORT; + struct hostapd_ip_addr ipaddr; + char *addr; +#endif /* CONFIG_DPP2 */ pos = os_strstr(cmd, " peer="); if (!pos) @@ -504,6 +511,25 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) return -1; } +#ifdef CONFIG_DPP2 + pos = os_strstr(cmd, " tcp_port="); + if (pos) { + pos += 10; + tcp_port = atoi(pos); + } + + addr = get_param(cmd, " tcp_addr="); + if (addr) { + int res; + + res = hostapd_parse_ip_addr(addr, &ipaddr); + os_free(addr); + if (res) + return -1; + tcp = 1; + } +#endif /* CONFIG_DPP2 */ + pos = os_strstr(cmd, " own="); if (pos) { pos += 5; @@ -541,7 +567,7 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) if (pos) neg_freq = atoi(pos + 10); - if (hapd->dpp_auth) { + if (!tcp && hapd->dpp_auth) { eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); @@ -555,26 +581,31 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) dpp_auth_deinit(hapd->dpp_auth); } - hapd->dpp_auth = dpp_auth_init(hapd->iface->interfaces->dpp, - hapd->msg_ctx, peer_bi, own_bi, - allowed_roles, neg_freq, - hapd->iface->hw_features, - hapd->iface->num_hw_features); - if (!hapd->dpp_auth) + auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, + peer_bi, own_bi, allowed_roles, neg_freq, + hapd->iface->hw_features, + hapd->iface->num_hw_features); + if (!auth) goto fail; - hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); - if (dpp_set_configurator(hapd->dpp_auth, cmd) < 0) { - dpp_auth_deinit(hapd->dpp_auth); - hapd->dpp_auth = NULL; + hostapd_dpp_set_testing_options(hapd, auth); + if (dpp_set_configurator(auth, cmd) < 0) { + dpp_auth_deinit(auth); goto fail; } - hapd->dpp_auth->neg_freq = neg_freq; + auth->neg_freq = neg_freq; if (!is_zero_ether_addr(peer_bi->mac_addr)) - os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr, - ETH_ALEN); + os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN); +#ifdef CONFIG_DPP2 + if (tcp) + return dpp_tcp_init(hapd->iface->interfaces->dpp, auth, + &ipaddr, tcp_port, hapd->conf->dpp_name, + DPP_NETROLE_AP); +#endif /* CONFIG_DPP2 */ + + hapd->dpp_auth = auth; return hostapd_dpp_auth_init_next(hapd); fail: return -1; diff --git a/src/common/dpp.h b/src/common/dpp.h index 9cf1019ae..810ecb81b 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -673,7 +673,7 @@ void dpp_controller_new_qr_code(struct dpp_global *dpp, struct dpp_bootstrap_info *bi); int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port, - const char *name); + const char *name, enum dpp_netrole netrole); struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); struct dpp_global_config { diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 83aff1ca9..97b015d67 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -41,6 +41,7 @@ struct dpp_connection { unsigned int gas_comeback_in_progress:1; u8 gas_dialog_token; char *name; + enum dpp_netrole netrole; }; /* Remote Controller */ @@ -257,11 +258,11 @@ static void dpp_controller_start_gas_client(struct dpp_connection *conn) { struct dpp_authentication *auth = conn->auth; struct wpabuf *buf; - int netrole_ap = 0; /* TODO: make this configurable */ const char *dpp_name; dpp_name = conn->name ? conn->name : "Test"; - buf = dpp_build_conf_req_helper(auth, dpp_name, netrole_ap, NULL, NULL); + buf = dpp_build_conf_req_helper(auth, dpp_name, conn->netrole, NULL, + NULL); if (!buf) { wpa_printf(MSG_DEBUG, "DPP: No configuration request data available"); @@ -1530,7 +1531,8 @@ fail: int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, - const struct hostapd_ip_addr *addr, int port, const char *name) + const struct hostapd_ip_addr *addr, int port, const char *name, + enum dpp_netrole netrole) { struct dpp_connection *conn; struct sockaddr_storage saddr; @@ -1553,6 +1555,7 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, } conn->name = os_strdup(name ? name : "Test"); + conn->netrole = netrole; conn->global = dpp; conn->auth = auth; conn->sock = socket(AF_INET, SOCK_STREAM, 0); diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 6dc0002eb..43dcaae05 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -836,7 +836,7 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) #ifdef CONFIG_DPP2 if (tcp) return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port, - wpa_s->conf->dpp_name); + wpa_s->conf->dpp_name, DPP_NETROLE_STA); #endif /* CONFIG_DPP2 */ wpa_s->dpp_auth = auth; From 7f366fcbdc7dca411b4ae3de02870d3d9e61044e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 14 Aug 2020 16:53:42 +0300 Subject: [PATCH 0829/1105] DPP: Add msg_ctx into TCP connection data struct This is needed to avoid issues with hostapd not having set msg_ctx in dpp_global. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 2 +- src/common/dpp.h | 2 +- src/common/dpp_tcp.c | 39 ++++++++++++++------------------- wpa_supplicant/dpp_supplicant.c | 3 ++- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 9b9232d4c..cafbc8302 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -602,7 +602,7 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) if (tcp) return dpp_tcp_init(hapd->iface->interfaces->dpp, auth, &ipaddr, tcp_port, hapd->conf->dpp_name, - DPP_NETROLE_AP); + DPP_NETROLE_AP, hapd->msg_ctx); #endif /* CONFIG_DPP2 */ hapd->dpp_auth = auth; diff --git a/src/common/dpp.h b/src/common/dpp.h index 810ecb81b..5a81a9bf9 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -673,7 +673,7 @@ void dpp_controller_new_qr_code(struct dpp_global *dpp, struct dpp_bootstrap_info *bi); int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port, - const char *name, enum dpp_netrole netrole); + const char *name, enum dpp_netrole netrole, void *msg_ctx); struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); struct dpp_global_config { diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 97b015d67..07be26d6b 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -25,6 +25,7 @@ struct dpp_connection { struct dpp_relay_controller *relay; struct dpp_global *global; struct dpp_authentication *auth; + void *msg_ctx; int sock; u8 mac_addr[ETH_ALEN]; unsigned int freq; @@ -148,7 +149,6 @@ dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash) static void dpp_controller_gas_done(struct dpp_connection *conn) { struct dpp_authentication *auth = conn->auth; - void *msg_ctx; if (auth->waiting_csr) { wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR"); @@ -163,11 +163,7 @@ static void dpp_controller_gas_done(struct dpp_connection *conn) return; } - if (conn->ctrl) - msg_ctx = conn->ctrl->global->msg_ctx; - else - msg_ctx = auth->msg_ctx; - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); dpp_connection_remove(conn); } @@ -283,7 +279,7 @@ static void dpp_controller_auth_success(struct dpp_connection *conn, return; wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded"); - wpa_msg(conn->global->msg_ctx, MSG_INFO, + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d", initiator); #ifdef CONFIG_TESTING_OPTIONS if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { @@ -373,6 +369,7 @@ dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src, conn->global = ctrl->global; conn->relay = ctrl; + conn->msg_ctx = ctrl->global->msg_ctx; os_memcpy(conn->mac_addr, src, ETH_ALEN); conn->freq = freq; @@ -625,8 +622,7 @@ static int dpp_controller_rx_auth_req(struct dpp_connection *conn, return 0; } - conn->auth = dpp_auth_req_rx(conn->ctrl->global, - conn->ctrl->global->msg_ctx, + conn->auth = dpp_auth_req_rx(conn->ctrl->global, conn->msg_ctx, conn->ctrl->allowed_roles, conn->ctrl->qr_mutual, peer_bi, own_bi, -1, hdr, buf, len); @@ -709,7 +705,7 @@ void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, wpa_printf(MSG_DEBUG, "DPP: Timeout while waiting for Connection Status Result"); - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "timeout"); dpp_connection_remove(conn); } @@ -721,7 +717,7 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn, { struct dpp_authentication *auth = conn->auth; enum dpp_status_error status; - void *msg_ctx; + void *msg_ctx = conn->msg_ctx; if (!conn->ctrl && (!auth || !auth->configurator)) return 0; @@ -733,10 +729,6 @@ static int dpp_controller_rx_conf_result(struct dpp_connection *conn, "DPP: No DPP Configuration waiting for result - drop"); return -1; } - if (conn->ctrl) - msg_ctx = conn->ctrl->global->msg_ctx; - else - msg_ctx = auth->msg_ctx; status = dpp_conf_result_rx(auth, hdr, buf, len); if (status == DPP_STATUS_OK && auth->send_conn_status) { @@ -782,8 +774,7 @@ static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn, status = dpp_conn_status_result_rx(auth, hdr, buf, len, ssid, &ssid_len, &channel_list); - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONN_STATUS_RESULT + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT "result=%d ssid=%s channel_list=%s", status, wpa_ssid_txt(ssid, ssid_len), channel_list ? channel_list : "N/A"); @@ -813,7 +804,7 @@ static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, &r_bootstrap_len); if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { - wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "Missing or invalid required Responder Bootstrapping Key Hash attribute"); return -1; } @@ -826,7 +817,7 @@ static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, return -1; } - auth = dpp_auth_init(dpp, dpp->msg_ctx, peer_bi, NULL, + auth = dpp_auth_init(dpp, conn->msg_ctx, peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, -1, NULL, 0); if (!auth) return -1; @@ -863,7 +854,7 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, &csign_hash_len); if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { - wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "Missing or invalid required Configurator C-sign key Hash attribute"); return -1; } @@ -879,7 +870,7 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, &fcgroup_len); if (!fcgroup || fcgroup_len != 2) { - wpa_msg(dpp->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "Missing or invalid required Finite Cyclic Group attribute"); return -1; } @@ -889,7 +880,7 @@ static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len); e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len); - auth = dpp_reconfig_init(dpp, dpp->msg_ctx, conf, 0, group, + auth = dpp_reconfig_init(dpp, conn->msg_ctx, conf, 0, group, a_nonce, a_nonce_len, e_id, e_id_len); if (!auth) return -1; @@ -1506,6 +1497,7 @@ static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) conn->global = ctrl->global; conn->ctrl = ctrl; + conn->msg_ctx = ctrl->global->msg_ctx; conn->sock = fd; if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { @@ -1532,7 +1524,7 @@ fail: int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port, const char *name, - enum dpp_netrole netrole) + enum dpp_netrole netrole, void *msg_ctx) { struct dpp_connection *conn; struct sockaddr_storage saddr; @@ -1554,6 +1546,7 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, return -1; } + conn->msg_ctx = msg_ctx; conn->name = os_strdup(name ? name : "Test"); conn->netrole = netrole; conn->global = dpp; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 43dcaae05..1e4a6072a 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -836,7 +836,8 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) #ifdef CONFIG_DPP2 if (tcp) return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port, - wpa_s->conf->dpp_name, DPP_NETROLE_STA); + wpa_s->conf->dpp_name, DPP_NETROLE_STA, + wpa_s); #endif /* CONFIG_DPP2 */ wpa_s->dpp_auth = auth; From c6a760b9c4da3c6f5e95e8608b0a0786d4f96ed1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 14 Aug 2020 17:04:11 +0300 Subject: [PATCH 0830/1105] DPP: Add process_conf_obj into TCP connection data struct This is needed to avoid issues with hostapd not having set this function pointer in dpp_global. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 22 +++++++++++++++++++++- src/common/dpp.h | 6 +++++- src/common/dpp_tcp.c | 17 +++++++++++++---- wpa_supplicant/dpp_supplicant.c | 4 +++- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index cafbc8302..c886103fb 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -29,6 +29,9 @@ static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd); #ifdef CONFIG_DPP2 static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx); +static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd, + struct dpp_authentication *auth, + struct dpp_config_obj *conf); #endif /* CONFIG_DPP2 */ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -486,6 +489,22 @@ static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd) } +#ifdef CONFIG_DPP2 +static int hostapd_dpp_process_conf_obj(void *ctx, + struct dpp_authentication *auth) +{ + struct hostapd_data *hapd = ctx; + unsigned int i; + + for (i = 0; i < auth->num_conf_obj; i++) + hostapd_dpp_handle_config_obj(hapd, auth, + &auth->conf_obj[i]); + + return 0; +} +#endif /* CONFIG_DPP2 */ + + int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) { const char *pos; @@ -602,7 +621,8 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) if (tcp) return dpp_tcp_init(hapd->iface->interfaces->dpp, auth, &ipaddr, tcp_port, hapd->conf->dpp_name, - DPP_NETROLE_AP, hapd->msg_ctx); + DPP_NETROLE_AP, hapd->msg_ctx, hapd, + hostapd_dpp_process_conf_obj); #endif /* CONFIG_DPP2 */ hapd->dpp_auth = auth; diff --git a/src/common/dpp.h b/src/common/dpp.h index 5a81a9bf9..b3d505cc7 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -673,7 +673,11 @@ void dpp_controller_new_qr_code(struct dpp_global *dpp, struct dpp_bootstrap_info *bi); int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port, - const char *name, enum dpp_netrole netrole, void *msg_ctx); + const char *name, enum dpp_netrole netrole, void *msg_ctx, + void *cb_ctx, + int (*process_conf_obj)(void *ctx, + struct dpp_authentication *auth)); + struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); struct dpp_global_config { diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 07be26d6b..e243a6d44 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -26,6 +26,8 @@ struct dpp_connection { struct dpp_global *global; struct dpp_authentication *auth; void *msg_ctx; + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); int sock; u8 mac_addr[ETH_ALEN]; unsigned int freq; @@ -370,6 +372,8 @@ dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src, conn->global = ctrl->global; conn->relay = ctrl; conn->msg_ctx = ctrl->global->msg_ctx; + conn->cb_ctx = ctrl->global->cb_ctx; + conn->process_conf_obj = ctrl->global->process_conf_obj; os_memcpy(conn->mac_addr, src, ETH_ALEN); conn->freq = freq; @@ -1213,9 +1217,8 @@ static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) return -1; } - if (conn->global->process_conf_obj) - res = conn->global->process_conf_obj(conn->global->cb_ctx, - auth); + if (conn->process_conf_obj) + res = conn->process_conf_obj(conn->cb_ctx, auth); else res = 0; @@ -1498,6 +1501,8 @@ static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) conn->global = ctrl->global; conn->ctrl = ctrl; conn->msg_ctx = ctrl->global->msg_ctx; + conn->cb_ctx = ctrl->global->cb_ctx; + conn->process_conf_obj = ctrl->global->process_conf_obj; conn->sock = fd; if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { @@ -1524,7 +1529,9 @@ fail: int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, const struct hostapd_ip_addr *addr, int port, const char *name, - enum dpp_netrole netrole, void *msg_ctx) + enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx, + int (*process_conf_obj)(void *ctx, + struct dpp_authentication *auth)) { struct dpp_connection *conn; struct sockaddr_storage saddr; @@ -1547,6 +1554,8 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, } conn->msg_ctx = msg_ctx; + conn->cb_ctx = cb_ctx; + conn->process_conf_obj = process_conf_obj; conn->name = os_strdup(name ? name : "Test"); conn->netrole = netrole; conn->global = dpp; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 1e4a6072a..fdb9cbd2b 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -50,6 +50,8 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s, static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx); static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s); +static int wpas_dpp_process_conf_obj(void *ctx, + struct dpp_authentication *auth); #endif /* CONFIG_DPP2 */ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -837,7 +839,7 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) if (tcp) return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port, wpa_s->conf->dpp_name, DPP_NETROLE_STA, - wpa_s); + wpa_s, wpa_s, wpas_dpp_process_conf_obj); #endif /* CONFIG_DPP2 */ wpa_s->dpp_auth = auth; From f6ddda443ddf104970722b0d94bc5be11907b83a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 14 Aug 2020 17:04:56 +0300 Subject: [PATCH 0831/1105] tests: sigma_dut DPP AP as TCP Enrollee/initiator Signed-off-by: Jouni Malinen --- tests/hwsim/test_sigma_dut.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/hwsim/test_sigma_dut.py b/tests/hwsim/test_sigma_dut.py index 6f66399ef..e2151cfe9 100644 --- a/tests/hwsim/test_sigma_dut.py +++ b/tests/hwsim/test_sigma_dut.py @@ -3084,6 +3084,37 @@ def test_sigma_dut_dpp_tcp_enrollee_init(dev, apdev): stop_sigma_dut(sigma) dev[1].request("DPP_CONTROLLER_STOP") +def test_sigma_dut_ap_dpp_tcp_enrollee_init(dev, apdev, params): + """sigma_dut DPP AP as TCP Enrollee/initiator""" + logdir = params['prefix'] + ".sigma-hostapd" + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + run_sigma_dut_ap_dpp_tcp_enrollee_init(dev, apdev) + finally: + stop_sigma_dut(sigma) + dev[1].request("DPP_CONTROLLER_STOP") + +def run_sigma_dut_ap_dpp_tcp_enrollee_init(dev, apdev): + check_dpp_capab(dev[1]) + # Controller + conf_id = dev[1].dpp_configurator_add() + dev[1].set("dpp_configurator_params", + "conf=ap-dpp configurator=%d" % conf_id) + id_c = dev[1].dpp_bootstrap_gen() + uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + if "OK" not in dev[1].request("DPP_CONTROLLER_START"): + raise Exception("Failed to start Controller") + + sigma_dut_cmd_check("ap_reset_default,program,DPP") + sigma_dut_cmd_check("ap_preset_testparameters,Program,DPP,NAME,AP,oper_chn,6") + sigma_dut_cmd_check("dev_exec_action,program,DPP,DPPActionType,SetPeerBootstrap,DPPBootstrappingdata,%s,DPPBS,QR" % to_hex(uri_c)) + + cmd = "dev_exec_action,program,DPP,DPPActionType,AutomaticDPP,DPPAuthRole,Initiator,DPPProvisioningRole,Enrollee,DPPBS,QR,DPPOverTCP,127.0.0.1,DPPTimeout,6" + res = sigma_dut_cmd(cmd, timeout=10) + if "BootstrapResult,OK,AuthResult,OK,ConfResult,OK" not in res: + raise Exception("Unexpected result: " + res) + def test_sigma_dut_dpp_tcp_enrollee_init_mutual(dev, apdev): """sigma_dut DPP TCP Enrollee as initiator with mutual authentication""" check_dpp_capab(dev[0], min_ver=2) From 5d2218e6184843ddffe485a0098e081d0038dd28 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 14 Aug 2020 14:50:45 +0530 Subject: [PATCH 0832/1105] Add get_sta_info vendor attrs to get BIP failure counters for STA mode Add support to get number of MIC errors, missing MME incidents, and packet replay incidents observed while using IGTK/BIGTK keys when PMF and/or beacon protection features are enabled. These counters are applicable only for STA mode and can be fetched through the QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command. Signed-off-by: Veerendranath Jakkam --- src/common/qca-vendor.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index eed44f7b7..4ef2dac0e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -9204,6 +9204,26 @@ enum qca_vendor_wlan_sta_guard_interval { * disconnect reason for the last disconnection if the disconnection is * triggered from the host driver. The values are referred from * enum qca_disconnect_reason_codes. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT: u32, used in STA mode + * only. This represents the number of group addressed robust management frames + * received from this station with an invalid MIC or a missing MME when PMF is + * enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT: u32, used in STA mode + * only. This represents the number of group addressed robust management frames + * received from this station with the packet number less than or equal to the + * last received packet number when PMF is enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT: u32, used in STA + * mode only. This represents the number of Beacon frames received from this + * station with an invalid MIC or a missing MME when beacon protection is + * enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT: u32, used in STA mode + * only. This represents number of Beacon frames received from this station with + * the packet number less than or equal to the last received packet number when + * beacon protection is enabled. */ enum qca_wlan_vendor_attr_get_sta_info { QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0, @@ -9245,6 +9265,10 @@ enum qca_wlan_vendor_attr_get_sta_info { QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_IES = 36, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PROBE_RESP_IES = 37, QCA_WLAN_VENDOR_ATTR_GET_STA_DRIVER_DISCONNECT_REASON = 38, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT = 39, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT = 40, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT = 41, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT = 42, /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST, From a2d35b49e7cc08fa837c33bf42e4334a83e484f8 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 14 Aug 2020 18:35:29 +0530 Subject: [PATCH 0833/1105] Fix documentation for the test configuration attributes of FT-SAE/OCV These vendor attributes for FT/OCV/SAE testing can be configured only when the STA is in connected state. Update the documentation of the attributes to reflect the same. Fixes: 18f3f99ac467 ("Add vendor attributes to configure testing functionality for FT/OCV/SAE") Signed-off-by: Veerendranath Jakkam --- src/common/qca-vendor.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 4ef2dac0e..74b553ae6 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7408,9 +7408,8 @@ enum qca_wlan_vendor_attr_wifi_test_config { * Request frame. * 0 - Default behavior, 1 - override with 1, 2 - override with 0. * This attribute is used to configure the testbed device. - * This attribute can be configured when STA is in disconnected or - * associated state and the configuration is valid until the next - * disconnection. + * This attribute can be configured only when STA is in associated state + * and the configuration is valid until the disconnection. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED = 40, @@ -7418,9 +7417,8 @@ enum qca_wlan_vendor_attr_wifi_test_config { * Switch Announcement) when STA is in connected state. * 0 - Default behavior, 1 - Ignore CSA. * This attribute is used to configure the testbed device. - * This attribute can be configured when STA is in disconnected or - * associated state and the configuration is valid until the next - * disconnection. + * This attribute can be configured only when STA is in associated state + * and the configuration is valid until the disconnection. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA = 41, @@ -7428,9 +7426,8 @@ enum qca_wlan_vendor_attr_wifi_test_config { * Information). Attributes defined in enum * qca_wlan_vendor_attr_oci_override are nested within this attribute. * This attribute is used to configure the testbed device. - * This attribute can be configured when STA is in disconnected or - * associated state and the configuration is valid until the next - * disconnection. + * This attribute can be configured only when STA is in associated state + * and the configuration is valid until the disconnection. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE = 42, From 90e05626f0dec7b6ead5de60b9ec3d9f81b7b637 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 14 Aug 2020 14:06:23 +0530 Subject: [PATCH 0834/1105] Add test configuration to ignore SA Query timeout Add a new QCA vendor attribute to configure the driver/firmware to ignore SA Query timeout. If this configuration is enabled the driver/firmware shall not send Deauthentication frame when SA Query times out. This is required to support STA testbed role. Signed-off-by: Veerendranath Jakkam --- src/common/qca-vendor.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 74b553ae6..b7dc1c7f8 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7431,6 +7431,17 @@ enum qca_wlan_vendor_attr_wifi_test_config { */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE = 42, + /* 8-bit unsigned value to configure the driver/firmware to ignore SA + * Query timeout. If this configuration is enabled STA shall not send + * Deauthentication frmae when SA Query times out (mainly, after a + * channel switch when OCV is enabled). + * 0 - Default behavior, 1 - Ignore SA Query timeout. + * This attribute is used to configure the testbed device. + * This attribute can be configured only when STA is in associated state + * and the configuration is valid until the disconnection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT = 43, + /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX = From 55a366d7a8880d962a1a0855b758150814d8ebd1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 15 Aug 2020 00:19:46 +0300 Subject: [PATCH 0835/1105] dpp-nfc: Fix recv_octets() regression The updated socket.poll() loop did not terminate properly in cases where no response is available. Fix that to check for both False and None. Fixes: 1733e356e421 ("dpp-nfc: Fix handover client wait for receiving handover select") Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 83241330d..9f7fefb10 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -280,7 +280,7 @@ class HandoverClient(nfc.handover.HandoverClient): msg = bytearray() while True: poll_timeout = 0.1 if timeout is None or timeout > 0.1 else timeout - if self.socket.poll('recv', poll_timeout) is None: + if not self.socket.poll('recv', poll_timeout): if timeout: timeout -= time.time() - start if timeout <= 0: From 5dedbd582ad7e2ace79307ad9f025889913e8752 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Aug 2020 11:12:17 +0300 Subject: [PATCH 0836/1105] tests: Fix wnm fuzzer build regression Addition of MSCS support broke the test tool build due to references to a functions from a new file. Fix this by bringing in that file to the fuzzer build as well. Signed-off-by: Jouni Malinen --- tests/fuzzing/wnm/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fuzzing/wnm/Makefile b/tests/fuzzing/wnm/Makefile index 2c7e2f776..b8d33ac04 100644 --- a/tests/fuzzing/wnm/Makefile +++ b/tests/fuzzing/wnm/Makefile @@ -32,6 +32,7 @@ OBJS += $(WPAS_SRC)/interworking.o OBJS += $(WPAS_SRC)/notify.o OBJS += $(WPAS_SRC)/offchannel.o OBJS += $(WPAS_SRC)/op_classes.o +OBJS += $(WPAS_SRC)/robust_av.o OBJS += $(WPAS_SRC)/rrm.o OBJS += $(WPAS_SRC)/scan.o OBJS += $(WPAS_SRC)/wmm_ac.o From 2caff11d7aa53ec00fcad7ae0d9c12b2deadbdd0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Aug 2020 11:32:01 +0300 Subject: [PATCH 0837/1105] LibreSSL: Fix build with LibreSSL versions older than 2.9.1 SSL_add0_chain_cert() was not available in LibreSSL before version 2.9.1. Fixes: 4b834df5e08a ("OpenSSL: Support PEM encoded chain from client_cert blob") Signed-off-by: Jouni Malinen --- src/crypto/tls_openssl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index 0f9664ec5..e73dd7f5b 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -3252,6 +3252,10 @@ static int tls_connection_client_cert(struct tls_connection *conn, "OK"); return 0; } else if (client_cert_blob) { +#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20901000L + tls_show_errors(MSG_DEBUG, __func__, + "SSL_use_certificate_ASN1 failed"); +#else BIO *bio; X509 *x509; @@ -3277,6 +3281,7 @@ static int tls_connection_client_cert(struct tls_connection *conn, } BIO_free(bio); return 0; +#endif } if (client_cert == NULL) From 22c06de911dfa3e3459817f87f19722d04386819 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 19 Aug 2020 12:44:46 -0700 Subject: [PATCH 0838/1105] wlantest: Avoid heap-overflow on unexpected data We're doing a sort of bounds check, based on the previous loop, but only after we've already tried to read off the end. This squashes some ASAN errors I'm seeing when running the ap_ft hwsim test module. Signed-off-by: Brian Norris --- wlantest/rx_eapol.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index d75ed92ba..44388fdda 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -722,8 +722,8 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, } p += 2 + p[1]; } - if (p && p > decrypted && *p == 0xdd && - p + 1 == decrypted + decrypted_len) { + if (p && p > decrypted && p + 1 == decrypted + decrypted_len && + *p == 0xdd) { /* Remove padding */ p--; plain_len = p - decrypted; From 9bc8811538137c692d5bf92234ee3f6574413f4b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Aug 2020 12:49:05 +0300 Subject: [PATCH 0839/1105] DPP2: Fix build without IEEE8021X_EAPOL The local network profile parameters for EAP are not available without IEEE8021X_EAPOL, so do not try to set these in builds that do not include any EAP support. Signed-off-by: Jouni Malinen --- wpa_supplicant/dpp_supplicant.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index fdb9cbd2b..4f7546e27 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1227,7 +1227,7 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, } } -#ifdef CONFIG_DPP2 +#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL) if (conf->akm == DPP_AKM_DOT1X) { int i; char name[100], blobname[128]; @@ -1321,7 +1321,7 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, if (wpa_config_set(ssid, "eap", "TLS", 0) < 0) goto fail; } -#endif /* CONFIG_DPP2 */ +#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */ os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len); wpa_s->dpp_last_ssid_len = conf->ssid_len; From 27ac632ae369bfdb8e4142666f3ed58d91cda50c Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Sun, 9 Aug 2020 18:28:52 +0200 Subject: [PATCH 0840/1105] gitignore: Ignore ctags tags file Signed-off-by: Yegor Yefremov --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6a985a75d..e057b54ea 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ wlantest/test_vectors wlantest/wlantest wlantest/wlantest_cli **/parallel-vm.log +tags From 96e63008fb4378de67e4634b7a893e69c35728d7 Mon Sep 17 00:00:00 2001 From: Chittur Subramanian Raman Date: Wed, 19 Aug 2020 14:36:39 +0530 Subject: [PATCH 0841/1105] OWE: Do not add DH Params element in AssocResp with PMKSA caching As per RFC 8110 (Opportunistic Wireless Encryption), if the AP has the PMK identified by the PMKID and wishes to perform PMK caching, it will include the PMKID in the Association Response frame RSNE but does not include the Diffie-Hellman Parameter element. This was already addressed for most cases with owe_process_assoc_req() not setting sta->owe_ecdh in case PMKSA caching is used. However, it was possible to an old STA entry to maintain the initial sta->owe_ecdh value if reassociation back to the same AP was used to initiate the PMKSA caching attempt. Cover that case by adding an explicit check for the time when the Association Response frame is being generated. Signed-off-by: Chittur Subramanian Raman --- src/ap/ieee802_11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index b91640070..c98e77103 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3890,7 +3890,8 @@ rsnxe_done: #ifdef CONFIG_OWE if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS && - wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) { + wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE && + !wpa_auth_sta_get_pmksa(sta->wpa_sm)) { struct wpabuf *pub; pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); From 8aa91282a135d2ac611980338912ae00305b6f68 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Aug 2020 14:00:34 +0300 Subject: [PATCH 0842/1105] Fix EAPOL-Key msg 1/4 processing in a corner case If reassoc_same_bss_optim=1 is used to optimize reassociation back to the same BSS, it was possible for sm->pmk_len to be 0 due to a disconnection event getting processed after sending out the reassociation request. This resulted in wpa_sm_rx_eapol() calling wpa_mic_len() with incorrect PMK length when PMKSA caching was being attempted. That resulted in incorrect mic_len getting determined and not finding the correct Key Data Length field value. This could result in failing to complete 4-way handshake successfully. Fix this by updating the current PMK length based on the selected PMKSA cache entry if sm->pmk_len is not set when processing EAPOL-Key msg 1/4. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 7b1218f16..b41e6e427 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2451,13 +2451,16 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, u8 *tmp = NULL; int ret = -1; u8 *mic, *key_data; - size_t mic_len, keyhdrlen; + size_t mic_len, keyhdrlen, pmk_len; #ifdef CONFIG_IEEE80211R sm->ft_completed = 0; #endif /* CONFIG_IEEE80211R */ - mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); + pmk_len = sm->pmk_len; + if (!pmk_len && sm->cur_pmksa) + pmk_len = sm->cur_pmksa->pmk_len; + mic_len = wpa_mic_len(sm->key_mgmt, pmk_len); keyhdrlen = sizeof(*key) + mic_len + 2; if (len < sizeof(*hdr) + keyhdrlen) { From 29ff74aef004ca5bb12b05f1a5147e28e86d8db9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Aug 2020 14:03:30 +0300 Subject: [PATCH 0843/1105] tests: Additional coverage for OWE PMKSA caching Signed-off-by: Jouni Malinen --- tests/hwsim/test_owe.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/hwsim/test_owe.py b/tests/hwsim/test_owe.py index 52c59491a..95c6b19b8 100644 --- a/tests/hwsim/test_owe.py +++ b/tests/hwsim/test_owe.py @@ -67,13 +67,19 @@ def test_owe_groups(dev, apdev): def test_owe_pmksa_caching(dev, apdev): """Opportunistic Wireless Encryption and PMKSA caching""" - run_owe_pmksa_caching(dev, apdev) + try: + run_owe_pmksa_caching(dev, apdev) + finally: + dev[0].set("reassoc_same_bss_optim", "0") def test_owe_pmksa_caching_connect_cmd(dev, apdev): """Opportunistic Wireless Encryption and PMKSA caching using cfg80211 connect command""" wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") - run_owe_pmksa_caching([wpas], apdev) + try: + run_owe_pmksa_caching([wpas], apdev) + finally: + wpas.set("reassoc_same_bss_optim", "0") def run_owe_pmksa_caching(dev, apdev): if "OWE" not in dev[0].get_capability("key_mgmt"): @@ -85,8 +91,10 @@ def run_owe_pmksa_caching(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) bssid = hapd.own_addr() + dev[0].set("reassoc_same_bss_optim", "1") dev[0].scan_for_bss(bssid, freq="2412") id = dev[0].connect("owe", key_mgmt="OWE") + hapd.wait_sta() hwsim_utils.test_connectivity(dev[0], hapd) pmksa = dev[0].get_pmksa(bssid) dev[0].request("DISCONNECT") @@ -95,6 +103,7 @@ def run_owe_pmksa_caching(dev, apdev): dev[0].select_network(id, 2412) dev[0].wait_connected() + hapd.wait_sta() hwsim_utils.test_connectivity(dev[0], hapd) pmksa2 = dev[0].get_pmksa(bssid) dev[0].request("DISCONNECT") @@ -106,11 +115,9 @@ def run_owe_pmksa_caching(dev, apdev): dev[0].select_network(id, 2412) dev[0].wait_connected() + hapd.wait_sta() hwsim_utils.test_connectivity(dev[0], hapd) pmksa3 = dev[0].get_pmksa(bssid) - dev[0].request("DISCONNECT") - dev[0].wait_disconnected() - dev[0].dump_monitor() if pmksa is None or pmksa2 is None or pmksa3 is None: raise Exception("PMKSA entry missing") @@ -119,6 +126,12 @@ def run_owe_pmksa_caching(dev, apdev): if pmksa['pmkid'] == pmksa3['pmkid']: raise Exception("PMKID did not change after PMKSA cache flush") + dev[0].request("REASSOCIATE") + dev[0].wait_connected() + pmksa4 = dev[0].get_pmksa(bssid) + if pmksa3['pmkid'] != pmksa4['pmkid']: + raise Exception("Unexpected PMKID change when using PMKSA caching [2]") + def test_owe_and_psk(dev, apdev): """Opportunistic Wireless Encryption and WPA2-PSK enabled""" if "OWE" not in dev[0].get_capability("key_mgmt"): From e4adbacafddae602e883a65686b87146d94ca488 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 22 Aug 2020 23:47:44 +0300 Subject: [PATCH 0844/1105] GAS: Fix memory leak on some DPP error paths One of the code paths left behind a response buffer. Free this properly on this missed code path as well. Signed-off-by: Jouni Malinen --- src/common/gas_server.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/gas_server.c b/src/common/gas_server.c index 5a1ea7899..c000aeb60 100644 --- a/src/common/gas_server.c +++ b/src/common/gas_server.c @@ -96,8 +96,10 @@ gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler, size_t resp_frag_len; struct wpabuf *resp; - if (comeback_delay == 0 && !query_resp) + if (comeback_delay == 0 && !query_resp) { + gas_server_free_response(response); return; + } response->freq = freq; response->handler = handler; From ba3081f1dc537c0b7727ae5aa28bf8ecdc0ca1c0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 24 Aug 2020 23:41:13 +0300 Subject: [PATCH 0845/1105] dpp-nfc: Start listen operation more completely for NFC Tag write cases Share the same setup steps from the negotiated connection handover to fix issues with NFC Tag write cases in AP mode. This addresses issues in the AP mode DPP listen operation not actually receiving anything when the write-a-tag code path was used. Signed-off-by: Jouni Malinen --- wpa_supplicant/examples/dpp-nfc.py | 53 ++++++++++++++++-------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index 9f7fefb10..8e865f3fc 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -192,6 +192,31 @@ def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, raise Exception("Failed to generate bootstrapping info") return int(res) +def dpp_start_listen(wpas, freq): + if get_status_field(wpas, "bssid[0]"): + summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) + if get_status_field(wpas, "beacon_set", extra="DRIVER") is None: + summary("Enable beaconing to have radio ready for RX") + wpas.request("DISABLE") + wpas.request("SET start_disabled 0") + wpas.request("ENABLE") + cmd = "DPP_LISTEN %d" % freq + global enrollee_only + global configurator_only + if enrollee_only: + cmd += " role=enrollee" + elif configurator_only: + cmd += " role=configurator" + global netrole + if netrole: + cmd += " netrole=" + netrole + summary(cmd) + res = wpas.request(cmd) + if "OK" not in res: + summary("Failed to start DPP listen", color=C_RED) + return False + return True + def wpas_get_nfc_uri(start_listen=True, pick_channel=False, chan_override=None): listen_freq = 2412 wpas = wpas_connect() @@ -221,13 +246,8 @@ def wpas_get_nfc_uri(start_listen=True, pick_channel=False, chan_override=None): if "FAIL" in res: return None if start_listen: - cmd = "DPP_LISTEN %d" % listen_freq - global netrole - if netrole: - cmd += " netrole=" + netrole - res2 = wpas.request(cmd) - if "OK" not in res2: - raise Exception("Failed to start listen operation (%s)" % cmd) + if not dpp_start_listen(wpas, listen_freq): + raise Exception("Failed to start listen operation on %d MHz" % listen_freq) return res def wpas_report_handover_req(uri): @@ -673,24 +693,7 @@ class HandoverServer(nfc.handover.HandoverServer): freq = 2437 else: summary("Negotiated channel: %d MHz" % freq) - if get_status_field(wpas, "bssid[0]"): - summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) - if get_status_field(wpas, "beacon_set", extra="DRIVER") is None: - summary("Enable beaconing to have radio ready for RX") - wpas.request("DISABLE") - wpas.request("SET start_disabled 0") - wpas.request("ENABLE") - cmd = "DPP_LISTEN %d" % freq - global enrollee_only - global configurator_only - if enrollee_only: - cmd += " role=enrollee" - elif configurator_only: - cmd += " role=configurator" - summary(cmd) - res = wpas.request(cmd) - if "OK" not in res: - summary("Failed to start DPP listen", color=C_RED) + if not dpp_start_listen(wpas, freq): break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) From cd17f6877c27ae932f388bd59d0ac5001b003e34 Mon Sep 17 00:00:00 2001 From: Chaithanya Garrepalli Date: Tue, 18 Aug 2020 21:41:20 +0530 Subject: [PATCH 0846/1105] Add QCA vendor event for firmware statistics Firmware statistics are received in the driver as opaque data. The host target needs to send this opaque data to userspace wifistats application. This new event is used to transfer this opaque data to the application. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index b7dc1c7f8..ce554fbe3 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -683,6 +683,17 @@ enum qca_radiotap_vendor_ids { * @QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID: This acts as a vendor event and is * used to update SSID information in hostapd when it is updated in the * driver. Uses the attribute NL80211_ATTR_SSID. + * + * @QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS: This vendor subcommand is used by + * the driver to send opaque data from the firmware to userspace. The + * driver sends an event to userspace whenever such data is received from + * the firmware. + * + * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to + * send this opaque data for this event. + * + * The format of the opaque data is specific to the particular firmware + * version and there is no guarantee of the format remaining same. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -867,6 +878,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_GETBAND = 192, QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193, QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194, + QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195, }; enum qca_wlan_vendor_attr { From 4ecb6dd16b33a3220df12892f52ad2a7647d77a5 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 25 Aug 2020 15:53:08 +0300 Subject: [PATCH 0847/1105] DPP2: Controller support in hostapd Extend hostapd support for DPP Controller to cover the DPP_CONTROLLER_* cases that were previously implemented only in wpa_supplicant. This allows hostapd/AP to be provisioned using DPP over TCP. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 8 +++++++ src/ap/dpp_hostapd.c | 39 +++++++++++++++++++++++++++++++++ src/ap/dpp_hostapd.h | 1 + src/common/dpp.h | 4 ++++ src/common/dpp_tcp.c | 15 ++++++++++--- wpa_supplicant/dpp_supplicant.c | 4 ++++ 6 files changed, 68 insertions(+), 3 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index ae63acd47..5b71a7bc4 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -3768,6 +3768,14 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0) reply_len = -1; #ifdef CONFIG_DPP2 + } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) { + if (hostapd_dpp_controller_start(hapd, buf + 20) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) { + if (hostapd_dpp_controller_start(hapd, NULL) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) { + dpp_controller_stop(hapd->iface->interfaces->dpp); } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) { if (hostapd_dpp_chirp(hapd, buf + 9) < 0) reply_len = -1; diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index c886103fb..bf62e63be 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -2222,6 +2222,45 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd) #ifdef CONFIG_DPP2 +int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd) +{ + struct dpp_controller_config config; + const char *pos; + + os_memset(&config, 0, sizeof(config)); + config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; + config.netrole = DPP_NETROLE_AP; + config.msg_ctx = hapd->msg_ctx; + config.cb_ctx = hapd; + config.process_conf_obj = hostapd_dpp_process_conf_obj; + if (cmd) { + pos = os_strstr(cmd, " tcp_port="); + if (pos) { + pos += 10; + config.tcp_port = atoi(pos); + } + + pos = os_strstr(cmd, " role="); + if (pos) { + pos += 6; + if (os_strncmp(pos, "configurator", 12) == 0) + config.allowed_roles = DPP_CAPAB_CONFIGURATOR; + else if (os_strncmp(pos, "enrollee", 8) == 0) + config.allowed_roles = DPP_CAPAB_ENROLLEE; + else if (os_strncmp(pos, "either", 6) == 0) + config.allowed_roles = DPP_CAPAB_CONFIGURATOR | + DPP_CAPAB_ENROLLEE; + else + return -1; + } + + config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL; + } + config.configurator_params = hapd->dpp_configurator_params; + return dpp_controller_start(hapd->iface->interfaces->dpp, &config); +} + + static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx); static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx) diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h index 7e74185ca..264d3e4c0 100644 --- a/src/ap/dpp_hostapd.h +++ b/src/ap/dpp_hostapd.h @@ -41,6 +41,7 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd); void hostapd_dpp_init_global(struct hapd_interfaces *ifaces); void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces); +int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd); void hostapd_dpp_chirp_stop(struct hostapd_data *hapd); void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi); diff --git a/src/common/dpp.h b/src/common/dpp.h index b3d505cc7..ee88560c7 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -386,6 +386,10 @@ struct dpp_controller_config { int tcp_port; u8 allowed_roles; int qr_mutual; + enum dpp_netrole netrole; + void *msg_ctx; + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); }; #ifdef CONFIG_TESTING_OPTIONS diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index e243a6d44..5bd17cdb0 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -69,6 +69,10 @@ struct dpp_controller { int sock; struct dl_list conn; /* struct dpp_connection */ char *configurator_params; + enum dpp_netrole netrole; + void *msg_ctx; + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); }; static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx); @@ -1500,10 +1504,11 @@ static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) conn->global = ctrl->global; conn->ctrl = ctrl; - conn->msg_ctx = ctrl->global->msg_ctx; - conn->cb_ctx = ctrl->global->cb_ctx; - conn->process_conf_obj = ctrl->global->process_conf_obj; + conn->msg_ctx = ctrl->msg_ctx; + conn->cb_ctx = ctrl->cb_ctx; + conn->process_conf_obj = ctrl->process_conf_obj; conn->sock = fd; + conn->netrole = ctrl->netrole; if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", @@ -1628,6 +1633,10 @@ int dpp_controller_start(struct dpp_global *dpp, dl_list_init(&ctrl->conn); ctrl->allowed_roles = config->allowed_roles; ctrl->qr_mutual = config->qr_mutual; + ctrl->netrole = config->netrole; + ctrl->msg_ctx = config->msg_ctx; + ctrl->cb_ctx = config->cb_ctx; + ctrl->process_conf_obj = config->process_conf_obj; ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); if (ctrl->sock < 0) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 4f7546e27..df6ddfc5b 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3337,6 +3337,10 @@ int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) os_memset(&config, 0, sizeof(config)); config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; + config.netrole = DPP_NETROLE_STA; + config.msg_ctx = wpa_s; + config.cb_ctx = wpa_s; + config.process_conf_obj = wpas_dpp_process_conf_obj; if (cmd) { pos = os_strstr(cmd, " tcp_port="); if (pos) { From c043b1e00069b7b340d3c2834e1df16958cee8d2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 25 Aug 2020 16:00:56 +0300 Subject: [PATCH 0848/1105] DPP: Remove unnecessary dpp_global_config parameters These were not really used anymore since the AP/Relay case did not set msg_ctx or process_conf_obj in the global DPP context. Get the appropriate pointers more directly from the more specific data structures instead and remove these global values. Signed-off-by: Jouni Malinen --- hostapd/main.c | 1 - src/common/dpp.c | 2 -- src/common/dpp.h | 3 +-- src/common/dpp_tcp.c | 5 +++-- wpa_supplicant/dpp_supplicant.c | 2 -- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/hostapd/main.c b/hostapd/main.c index 353b20a80..4f2d1f216 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -675,7 +675,6 @@ int main(int argc, char *argv[]) #ifdef CONFIG_DPP os_memset(&dpp_conf, 0, sizeof(dpp_conf)); dpp_conf.cb_ctx = &interfaces; - /* TODO: dpp_conf.msg_ctx? */ #ifdef CONFIG_DPP2 dpp_conf.remove_bi = hostapd_dpp_remove_bi; #endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp.c b/src/common/dpp.c index bc349229b..3922edb63 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -4278,10 +4278,8 @@ struct dpp_global * dpp_global_init(struct dpp_global_config *config) dpp = os_zalloc(sizeof(*dpp)); if (!dpp) return NULL; - dpp->msg_ctx = config->msg_ctx; #ifdef CONFIG_DPP2 dpp->cb_ctx = config->cb_ctx; - dpp->process_conf_obj = config->process_conf_obj; dpp->remove_bi = config->remove_bi; #endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp.h b/src/common/dpp.h index ee88560c7..2213593a3 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -374,6 +374,7 @@ struct dpp_relay_config { const struct hostapd_ip_addr *ipaddr; const u8 *pkhash; + void *msg_ctx; void *cb_ctx; void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg, size_t len); @@ -685,9 +686,7 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); struct dpp_global_config { - void *msg_ctx; void *cb_ctx; - int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); }; diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c index 5bd17cdb0..7e330d689 100644 --- a/src/common/dpp_tcp.c +++ b/src/common/dpp_tcp.c @@ -53,6 +53,7 @@ struct dpp_relay_controller { struct dpp_global *global; u8 pkhash[SHA256_MAC_LEN]; struct hostapd_ip_addr ipaddr; + void *msg_ctx; void *cb_ctx; void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg, size_t len); @@ -126,6 +127,7 @@ int dpp_relay_add_controller(struct dpp_global *dpp, ctrl->global = dpp; os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr)); os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN); + ctrl->msg_ctx = config->msg_ctx; ctrl->cb_ctx = config->cb_ctx; ctrl->tx = config->tx; ctrl->gas_resp_tx = config->gas_resp_tx; @@ -375,9 +377,8 @@ dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src, conn->global = ctrl->global; conn->relay = ctrl; - conn->msg_ctx = ctrl->global->msg_ctx; + conn->msg_ctx = ctrl->msg_ctx; conn->cb_ctx = ctrl->global->cb_ctx; - conn->process_conf_obj = ctrl->global->process_conf_obj; os_memcpy(conn->mac_addr, src, ETH_ALEN); conn->freq = freq; diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index df6ddfc5b..28404b8d7 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3275,10 +3275,8 @@ int wpas_dpp_init(struct wpa_supplicant *wpa_s) return -1; os_memset(&config, 0, sizeof(config)); - config.msg_ctx = wpa_s; config.cb_ctx = wpa_s; #ifdef CONFIG_DPP2 - config.process_conf_obj = wpas_dpp_process_conf_obj; config.remove_bi = wpas_dpp_remove_bi; #endif /* CONFIG_DPP2 */ wpa_s->dpp = dpp_global_init(&config); From 7ddb71224bfd5bc43b76fc694e335c6128f4eb9f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 25 Aug 2020 16:10:41 +0300 Subject: [PATCH 0849/1105] DPP2: Support QR mutual auth scan-during-auth-exchange (hostapd) Extend DPP authentication session search for the DPP_QR_CODE command to cover the ongoing exchanges in Controller/Responder. This was previously done for wpa_supplicant, but not for hostapd, so complete this support on the hostapd side. Signed-off-by: Jouni Malinen --- src/ap/dpp_hostapd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index bf62e63be..15aa82b85 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -66,6 +66,10 @@ int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd) wpabuf_len(hapd->dpp_auth->resp_msg)); } +#ifdef CONFIG_DPP2 + dpp_controller_new_qr_code(hapd->iface->interfaces->dpp, bi); +#endif /* CONFIG_DPP2 */ + return bi->id; } From 255e29fcae045aac7013e456d688db0682bcbd3c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 25 Aug 2020 15:54:19 +0300 Subject: [PATCH 0850/1105] tests: DPP Controller in hostapd Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 82 +++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 736248f92..0f7d19fde 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -4774,7 +4774,7 @@ def test_dpp_tcp(dev, apdev, params): prefix = "dpp_tcp" cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap") try: - run_dpp_tcp(dev, apdev, cap_lo) + run_dpp_tcp(dev[0], dev[1], cap_lo) finally: dev[1].request("DPP_CONTROLLER_STOP") @@ -4783,7 +4783,7 @@ def test_dpp_tcp_port(dev, apdev, params): prefix = "dpp_tcp_port" cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap") try: - run_dpp_tcp(dev, apdev, cap_lo, port="23456") + run_dpp_tcp(dev[0], dev[1], cap_lo, port="23456") finally: dev[1].request("DPP_CONTROLLER_STOP") @@ -4791,24 +4791,30 @@ def test_dpp_tcp_mutual(dev, apdev, params): """DPP over TCP (mutual)""" cap_lo = os.path.join(params['prefix'], ".lo.pcap") try: - run_dpp_tcp(dev, apdev, cap_lo, mutual=True) + run_dpp_tcp(dev[0], dev[1], cap_lo, mutual=True) finally: dev[1].request("DPP_CONTROLLER_STOP") -def run_dpp_tcp(dev, apdev, cap_lo, port=None, mutual=False): - check_dpp_capab(dev[0]) - check_dpp_capab(dev[1]) +def test_dpp_tcp_mutual_hostapd_conf(dev, apdev, params): + """DPP over TCP (mutual, hostapd as Configurator)""" + cap_lo = os.path.join(params['prefix'], ".lo.pcap") + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"}) + run_dpp_tcp(dev[0], hapd, cap_lo, mutual=True) + +def run_dpp_tcp(dev0, dev1, cap_lo, port=None, mutual=False): + check_dpp_capab(dev0) + check_dpp_capab(dev1) wt = WlantestCapture('lo', cap_lo) time.sleep(1) # Controller - conf_id = dev[1].dpp_configurator_add() - dev[1].set("dpp_configurator_params", - " conf=sta-dpp configurator=%d" % conf_id) - id_c = dev[1].dpp_bootstrap_gen() - uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) - res = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_c) + conf_id = dev1.dpp_configurator_add() + dev1.set("dpp_configurator_params", + " conf=sta-dpp configurator=%d" % conf_id) + id_c = dev1.dpp_bootstrap_gen() + uri_c = dev1.request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + res = dev1.request("DPP_BOOTSTRAP_INFO %d" % id_c) pkhash = None for line in res.splitlines(): name, value = line.split('=') @@ -4822,35 +4828,35 @@ def run_dpp_tcp(dev, apdev, cap_lo, port=None, mutual=False): req += " tcp_port=" + port if mutual: req += " qr=mutual" - id0 = dev[0].dpp_bootstrap_gen() - uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + id0 = dev0.dpp_bootstrap_gen() + uri0 = dev0.request("DPP_BOOTSTRAP_GET_URI %d" % id0) own = id0 else: own = None - if "OK" not in dev[1].request(req): + if "OK" not in dev1.request(req): raise Exception("Failed to start Controller") # Initiate from Enrollee with broadcast DPP Authentication Request - dev[0].dpp_auth_init(uri=uri_c, own=own, role="enrollee", - tcp_addr="127.0.0.1", tcp_port=port) + dev0.dpp_auth_init(uri=uri_c, own=own, role="enrollee", + tcp_addr="127.0.0.1", tcp_port=port) if mutual: - ev = dev[0].wait_event(["DPP-RESPONSE-PENDING"], timeout=5) + ev = dev0.wait_event(["DPP-RESPONSE-PENDING"], timeout=5) if ev is None: raise Exception("Pending response not reported") - ev = dev[1].wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5) + ev = dev1.wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5) if ev is None: raise Exception("QR Code scan for mutual authentication not requested") - id1 = dev[1].dpp_qr_code(uri0) + id1 = dev1.dpp_qr_code(uri0) - ev = dev[0].wait_event(["DPP-AUTH-DIRECTION"], timeout=5) + ev = dev0.wait_event(["DPP-AUTH-DIRECTION"], timeout=5) if ev is None: raise Exception("DPP authentication direction not indicated (Initiator)") if "mutual=1" not in ev: raise Exception("Mutual authentication not used") - wait_auth_success(dev[1], dev[0], configurator=dev[1], enrollee=dev[0], + wait_auth_success(dev1, dev0, configurator=dev1, enrollee=dev0, allow_enrollee_failure=True, allow_configurator_failure=True) time.sleep(0.5) @@ -4860,31 +4866,37 @@ def test_dpp_tcp_conf_init(dev, apdev, params): """DPP over TCP (Configurator initiates)""" cap_lo = os.path.join(params['prefix'], ".lo.pcap") try: - run_dpp_tcp_conf_init(dev, apdev, cap_lo) + run_dpp_tcp_conf_init(dev[0], dev[1], cap_lo) finally: dev[1].request("DPP_CONTROLLER_STOP") -def run_dpp_tcp_conf_init(dev, apdev, cap_lo, port=None): - check_dpp_capab(dev[0], min_ver=2) - check_dpp_capab(dev[1], min_ver=2) +def test_dpp_tcp_conf_init_hostapd_enrollee(dev, apdev, params): + """DPP over TCP (Configurator initiates, hostapd as Enrollee)""" + cap_lo = os.path.join(params['prefix'], ".lo.pcap") + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"}) + run_dpp_tcp_conf_init(dev[0], hapd, cap_lo, conf="ap-dpp") + +def run_dpp_tcp_conf_init(dev0, dev1, cap_lo, port=None, conf="sta-dpp"): + check_dpp_capab(dev0, min_ver=2) + check_dpp_capab(dev1, min_ver=2) wt = WlantestCapture('lo', cap_lo) time.sleep(1) - id_c = dev[1].dpp_bootstrap_gen() - uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c) - res = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_c) + id_c = dev1.dpp_bootstrap_gen() + uri_c = dev1.request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + res = dev1.request("DPP_BOOTSTRAP_INFO %d" % id_c) req = "DPP_CONTROLLER_START role=enrollee" if port: req += " tcp_port=" + port - if "OK" not in dev[1].request(req): + if "OK" not in dev1.request(req): raise Exception("Failed to start Controller") - conf_id = dev[0].dpp_configurator_add() - dev[0].dpp_auth_init(uri=uri_c, role="configurator", conf="sta-dpp", - configurator=conf_id, - tcp_addr="127.0.0.1", tcp_port=port) - wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1], + conf_id = dev0.dpp_configurator_add() + dev0.dpp_auth_init(uri=uri_c, role="configurator", conf=conf, + configurator=conf_id, + tcp_addr="127.0.0.1", tcp_port=port) + wait_auth_success(dev1, dev0, configurator=dev0, enrollee=dev1, allow_enrollee_failure=True, allow_configurator_failure=True) time.sleep(0.5) From d335ca953653e0f87ad16ffedd1cf63e5c57915e Mon Sep 17 00:00:00 2001 From: Chaoli Zhou Date: Fri, 28 Aug 2020 11:12:54 +0800 Subject: [PATCH 0851/1105] Update QCA vendor interface for GPIO configuration Add a new vendor attribute for GPIO configuration. In addition, document the previously defined attributes. Signed-off-by: Chaoli Zhou --- src/common/qca-vendor.h | 112 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index ce554fbe3..6c287b8ce 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2384,19 +2384,54 @@ enum qca_wlan_vendor_attr_sap_conditional_chan_switch { /** * enum qca_wlan_gpio_attr - Parameters for GPIO configuration + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND: Required (u32) + * value to specify the GPIO command. Please refer to enum qca_gpio_cmd_type + * for the available values. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM: Required (u32) + * value to specify the GPIO number. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG or %QCA_WLAN_VENDOR_GPIO_OUTPUT. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE: Required (u32) + * value to specify the GPIO output level. Please refer to enum qca_gpio_value + * for the available values. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_OUTPUT. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Required (u32) + * value to specify the GPIO pull type. Please refer to enum qca_gpio_pull_type + * for the available values. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Required (u32) + * value to specify the GPIO interrupt mode. Please refer to enum + * qca_gpio_interrupt_mode for the available values. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Required (u32) + * value to specify the GPIO direction. Please refer to enum qca_gpio_direction + * for the available values. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. */ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0, /* Unsigned 32-bit attribute for GPIO command */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND = 1, /* Unsigned 32-bit attribute for GPIO PIN number to configure */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM = 2, /* Unsigned 32-bit attribute for GPIO value to configure */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE = 3, /* Unsigned 32-bit attribute for GPIO pull type */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE = 4, /* Unsigned 32-bit attribute for GPIO interrupt mode */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE = 5, + /* Unsigned 32-bit attribute for GPIO direction to configure */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR = 6, /* keep last */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST, @@ -2404,6 +2439,73 @@ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST - 1 }; +/** + * enum gpio_cmd_type - GPIO configuration command type + * @QCA_WLAN_VENDOR_GPIO_CONFIG: Set GPIO configuration info + * @QCA_WLAN_VENDOR_GPIO_OUTPUT: Set GPIO output level + */ +enum qca_gpio_cmd_type { + QCA_WLAN_VENDOR_GPIO_CONFIG = 0, + QCA_WLAN_VENDOR_GPIO_OUTPUT = 1, +}; + +/** + * enum qca_gpio_pull_type - GPIO pull type + * @QCA_WLAN_GPIO_PULL_NONE: Set GPIO pull type to none + * @QCA_WLAN_GPIO_PULL_UP: Set GPIO pull up + * @QCA_WLAN_GPIO_PULL_DOWN: Set GPIO pull down + */ +enum qca_gpio_pull_type { + QCA_WLAN_GPIO_PULL_NONE = 0, + QCA_WLAN_GPIO_PULL_UP = 1, + QCA_WLAN_GPIO_PULL_DOWN = 2, + QCA_WLAN_GPIO_PULL_MAX, +}; + +/** + * enum qca_gpio_direction - GPIO direction + * @QCA_WLAN_GPIO_INPUT: Set GPIO as input mode + * @QCA_WLAN_GPIO_OUTPUT: Set GPIO as output mode + * @QCA_WLAN_GPIO_VALUE_MAX: Invalid value + */ +enum qca_gpio_direction { + QCA_WLAN_GPIO_INPUT = 0, + QCA_WLAN_GPIO_OUTPUT = 1, + QCA_WLAN_GPIO_DIR_MAX, +}; + +/** + * enum qca_gpio_value - GPIO Value + * @QCA_WLAN_GPIO_LEVEL_LOW: set gpio output level to low + * @QCA_WLAN_GPIO_LEVEL_HIGH: set gpio output level to high + * @QCA_WLAN_GPIO_LEVEL_MAX: Invalid value + */ +enum qca_gpio_value { + QCA_WLAN_GPIO_LEVEL_LOW = 0, + QCA_WLAN_GPIO_LEVEL_HIGH = 1, + QCA_WLAN_GPIO_LEVEL_MAX, +}; + +/** + * enum gpio_interrupt_mode - GPIO interrupt mode + * @QCA_WLAN_GPIO_INTMODE_DISABLE: Disable interrupt trigger + * @QCA_WLAN_GPIO_INTMODE_RISING_EDGE: Interrupt with GPIO rising edge trigger + * @QCA_WLAN_GPIO_INTMODE_FALLING_EDGE: Interrupt with GPIO falling edge trigger + * @QCA_WLAN_GPIO_INTMODE_BOTH_EDGE: Interrupt with GPIO both edge trigger + * @QCA_WLAN_GPIO_INTMODE_LEVEL_LOW: Interrupt with GPIO level low trigger + * @QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH: Interrupt with GPIO level high trigger + * @QCA_WLAN_GPIO_INTMODE_MAX: Invalid value + */ +enum qca_gpio_interrupt_mode { + QCA_WLAN_GPIO_INTMODE_DISABLE = 0, + QCA_WLAN_GPIO_INTMODE_RISING_EDGE = 1, + QCA_WLAN_GPIO_INTMODE_FALLING_EDGE = 2, + QCA_WLAN_GPIO_INTMODE_BOTH_EDGE = 3, + QCA_WLAN_GPIO_INTMODE_LEVEL_LOW = 4, + QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH = 5, + QCA_WLAN_GPIO_INTMODE_MAX, +}; + /** * qca_wlan_set_qdepth_thresh_attr - Parameters for setting * MSDUQ depth threshold per peer per tid in the target From c85206ba4030350990a02c54e908310c8ad79427 Mon Sep 17 00:00:00 2001 From: Hu Wang Date: Thu, 9 Jul 2020 11:35:23 +0800 Subject: [PATCH 0852/1105] QCA vendor attributes for setting ANI level Define QCA vendor attribute in SET(GET)_WIFI_CONFIGURATION to dynamically configure ANI level. Signed-off-by: Hu Wang --- src/common/qca-vendor.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 6c287b8ce..2e9a44de5 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2315,6 +2315,17 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS = 74, + /* 8-bit unsigned value to configure ANI setting type. + * See &enum qca_wlan_ani_setting for possible values. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING = 75, + /* 32-bit signed value to configure ANI level. This is used when + * ANI settings type is &QCA_WLAN_ANI_SETTING_FIXED. + * The set and get of ANI level with &QCA_WLAN_ANI_SETTING_AUTO + * is invalid, the driver will return a failure. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL = 76, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = @@ -2329,6 +2340,16 @@ enum qca_wlan_vendor_attr_config { #define QCA_WLAN_VENDOR_ATTR_BEACON_REPORT_FAIL \ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL +/** + * enum qca_wlan_ani_setting - ANI setting type + * @QCA_WLAN_ANI_SETTING_AUTO: Automatically determine ANI level + * @QCA_WLAN_ANI_SETTING_FIXED: Fix ANI level to the dBm parameter + */ +enum qca_wlan_ani_setting { + QCA_WLAN_ANI_SETTING_AUTO = 0, + QCA_WLAN_ANI_SETTING_FIXED = 1, +}; + /** * enum qca_wlan_vendor_attr_sap_config - Parameters for AP configuration * From 9afb68b03976d019bb450e5e33b0d8e48867691c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 8 Sep 2020 17:55:36 +0300 Subject: [PATCH 0853/1105] OpenSSL: Allow systemwide secpolicy overrides for TLS version Explicit configuration to enable TLS v1.0 and/or v1.1 did not work with systemwide OpenSSL secpolicy=2 cases (e.g., Ubuntu 20.04). Allow such systemwide configuration to be overridden if the older TLS versions have been explicitly enabled in the network profile. The default behavior follows the systemwide policy, but this allows compatibility with old authentication servers without having to touch the systemwide policy. Signed-off-by: Jouni Malinen --- src/crypto/tls_openssl.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index e73dd7f5b..f7dfecbbf 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -2995,16 +2995,12 @@ static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags, /* Explicit request to enable TLS versions even if needing to * override systemwide policies. */ - if (flags & TLS_CONN_ENABLE_TLSv1_0) { + if (flags & TLS_CONN_ENABLE_TLSv1_0) version = TLS1_VERSION; - } else if (flags & TLS_CONN_ENABLE_TLSv1_1) { - if (!(flags & TLS_CONN_DISABLE_TLSv1_0)) - version = TLS1_1_VERSION; - } else if (flags & TLS_CONN_ENABLE_TLSv1_2) { - if (!(flags & (TLS_CONN_DISABLE_TLSv1_0 | - TLS_CONN_DISABLE_TLSv1_1))) - version = TLS1_2_VERSION; - } + else if (flags & TLS_CONN_ENABLE_TLSv1_1) + version = TLS1_1_VERSION; + else if (flags & TLS_CONN_ENABLE_TLSv1_2) + version = TLS1_2_VERSION; if (!version) { wpa_printf(MSG_DEBUG, "OpenSSL: Invalid TLS version configuration"); @@ -3018,6 +3014,18 @@ static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags, } } #endif /* >= 1.1.0 */ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(LIBRESSL_VERSION_NUMBER) && \ + !defined(OPENSSL_IS_BORINGSSL) + if ((flags & (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) && + SSL_get_security_level(ssl) >= 2) { + /* + * Need to drop to security level 1 to allow TLS versions older + * than 1.2 to be used when explicitly enabled in configuration. + */ + SSL_set_security_level(conn->ssl, 1); + } +#endif #ifdef CONFIG_SUITEB #ifdef OPENSSL_IS_BORINGSSL From 0f84a5621962b2b11dfd2b59fd7f2dd9d441fa06 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 8 Sep 2020 17:58:06 +0300 Subject: [PATCH 0854/1105] tests: More explicit TLS version enabling in version tests This is needed to allow the test cases to work on systems using secpolicy=2 default (e.g., Ubuntu 20.04). Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_eap.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 0eed03500..7395c79cc 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -5839,7 +5839,17 @@ def check_tls_ver(dev, hapd, phase1, expected): def test_ap_wpa2_eap_tls_versions(dev, apdev): """EAP-TLS and TLS version configuration""" - params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + params = {"ssid": "test-wpa2-eap", + "wpa": "2", + "wpa_key_mgmt": "WPA-EAP", + "rsn_pairwise": "CCMP", + "ieee8021x": "1", + "eap_server": "1", + "tls_flags": "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][ENABLE-TLSv1.3]", + "eap_user_file": "auth_serv/eap_user.conf", + "ca_cert": "auth_serv/ca.pem", + "server_cert": "auth_serv/server.pem", + "private_key": "auth_serv/server.key"} hapd = hostapd.add_ap(apdev[0], params) tls = dev[0].request("GET tls_library") @@ -5858,9 +5868,9 @@ def test_ap_wpa2_eap_tls_versions(dev, apdev): check_tls_ver(dev[0], hapd, "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1", "TLSv1.2") check_tls_ver(dev[1], hapd, - "tls_disable_tlsv1_0=1 tls_disable_tlsv1_2=1", "TLSv1.1") + "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=1", "TLSv1.1") check_tls_ver(dev[2], hapd, - "tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1") + "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1") if "run=OpenSSL 1.1.1" in tls: check_tls_ver(dev[0], hapd, "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1 tls_disable_tlsv1_3=0", "TLSv1.3") @@ -5886,7 +5896,7 @@ def test_ap_wpa2_eap_tls_versions_server(dev, apdev): hapd.disable() hapd.set("tls_flags", flags) hapd.enable() - check_tls_ver(dev[0], hapd, "", exp) + check_tls_ver(dev[0], hapd, "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=0 tls_disable_tlsv1_3=0", exp) def test_ap_wpa2_eap_tls_13(dev, apdev): """EAP-TLS and TLS 1.3""" From 93a73ce028ab2d721ed97b4e21e4a86182466d76 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 19 Aug 2020 15:00:32 +0530 Subject: [PATCH 0855/1105] MSCS: Fix issues due to incorrect usage of wpa_hexdump_buf() Previously wpabuf_head() of the buffer is passed to wpa_hexdump_buf() instead of the wpabuf struct itself and it was causing wpa_supplicant to crash. Fix this by using the correct pointer in the debug prints. Fixes: a118047245b0 ("MSCS: Add support to send MSCS Request frames") Fixes: c504ff5398fa ("MSCS: Add support to populate MSCS Descriptor IE in (Re)AssocReq") Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/robust_av.c | 2 +- wpa_supplicant/sme.c | 3 +-- wpa_supplicant/wpa_supplicant.c | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c index 31315517a..4ac1a2bb9 100644 --- a/wpa_supplicant/robust_av.c +++ b/wpa_supplicant/robust_av.c @@ -94,7 +94,7 @@ int wpas_send_mscs_req(struct wpa_supplicant *wpa_s) /* MSCS descriptor element */ wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf); - wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", wpabuf_head(buf)); + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", buf); ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, wpa_s->own_addr, wpa_s->bssid, wpabuf_head(buf), wpabuf_len(buf), 0); diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 592c742fa..2faaff930 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1905,8 +1905,7 @@ pfs_fail: max_ie_len = sizeof(wpa_s->sme.assoc_req_ie); wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie); if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) { - wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", - wpabuf_head(mscs_ie)); + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie); mscs_ie_len = wpabuf_len(mscs_ie); os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len, wpabuf_head(mscs_ie), mscs_ie_len); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 3d2c0a985..39e92fb68 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3214,8 +3214,7 @@ pfs_fail: wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie); if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) { - wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", - wpabuf_head(mscs_ie)); + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie); mscs_ie_len = wpabuf_len(mscs_ie); os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie), mscs_ie_len); From 99f8506d30e3167168d6153f60c496abf59574cb Mon Sep 17 00:00:00 2001 From: Srinivas Pitla Date: Sat, 29 Aug 2020 23:22:31 -0700 Subject: [PATCH 0856/1105] Add QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS This change adds QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS, and enum for qca_wlan_vendor_attr_mbssid_tx_vdev_status to notify Tx VDEV status. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 2e9a44de5..aae56f935 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -694,6 +694,12 @@ enum qca_radiotap_vendor_ids { * * The format of the opaque data is specific to the particular firmware * version and there is no guarantee of the format remaining same. + * + * @QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS: This acts as an event. + * The host driver selects Tx VDEV, and notifies user. The attributes + * used with this event are defined in enum + * qca_wlan_vendor_attr_mbssid_tx_vdev_status. + * */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -879,6 +885,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193, QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194, QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195, + QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196, }; enum qca_wlan_vendor_attr { @@ -9842,4 +9849,23 @@ enum qca_wlan_vendor_attr_medium_assess { QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST - 1, }; +/** + * enum qca_wlan_vendor_attr_mbssid_tx_vdev_status - Defines attributes + * used by QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS vendor command. + * + * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL: + * u8 attribute. Notify the TX VDEV status. Possible values 0, 1 + * belonging to MBSSID/EMA_AP configuration. 0 means Non-Tx VDEV, + * 1 means Tx VDEV. Mandatory attribute for all MBSSID VDEV status events. + */ +enum qca_wlan_vendor_attr_mbssid_tx_vdev_status { + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL = 1, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_MAX = + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST - 1, +}; + #endif /* QCA_VENDOR_H */ From 0ebf5aa346a2bd25485df1c00eab079d659d35d0 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 9 Sep 2020 23:06:14 +0300 Subject: [PATCH 0857/1105] DPP2: Replace I/R-nonce with C/E-nonce in reconfiguration These nonces were renamed/replaced in the protocol design, so update implementation to match. Signed-off-by: Jouni Malinen --- src/common/dpp.h | 2 + src/common/dpp_crypto.c | 16 ++--- src/common/dpp_reconfig.c | 124 +++++++++++++++++++------------------- 3 files changed, 72 insertions(+), 70 deletions(-) diff --git a/src/common/dpp.h b/src/common/dpp.h index 2213593a3..011098f03 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -90,6 +90,7 @@ enum dpp_attribute_id { DPP_ATTR_CSR_ATTR_REQ = 0x101F, DPP_ATTR_A_NONCE = 0x1020, DPP_ATTR_E_PRIME_ID = 0x1021, + DPP_ATTR_CONFIGURATOR_NONCE = 0x1022, }; enum dpp_status_error { @@ -260,6 +261,7 @@ struct dpp_authentication { u8 i_nonce[DPP_MAX_NONCE_LEN]; u8 r_nonce[DPP_MAX_NONCE_LEN]; u8 e_nonce[DPP_MAX_NONCE_LEN]; + u8 c_nonce[DPP_MAX_NONCE_LEN]; u8 i_capab; u8 r_capab; enum dpp_netrole e_netrole; diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 9dff7c653..9ae33d59a 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2325,10 +2325,10 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, goto fail; wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); - /* ke = HKDF(I-nonce, "dpp reconfig key", M.x) */ + /* ke = HKDF(C-nonce, "dpp reconfig key", M.x) */ - /* HKDF-Extract(I-nonce, M.x) */ - if (dpp_hmac(curve->hash_len, auth->i_nonce, curve->nonce_len, + /* HKDF-Extract(C-nonce, M.x) */ + if (dpp_hmac(curve->hash_len, auth->c_nonce, curve->nonce_len, Mx, curve->prime_len, prk) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); @@ -2338,7 +2338,7 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, "dpp reconfig key", auth->ke, curve->hash_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, - "DPP: ke = HKDF(I-nonce, \"dpp reconfig key\", M.x)", + "DPP: ke = HKDF(C-nonce, \"dpp reconfig key\", M.x)", auth->ke, curve->hash_len); res = 0; @@ -2420,10 +2420,10 @@ int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); - /* ke = HKDF(I-nonce, "dpp reconfig key", M.x) */ + /* ke = HKDF(C-nonce, "dpp reconfig key", M.x) */ - /* HKDF-Extract(I-nonce, M.x) */ - if (dpp_hmac(curve->hash_len, auth->i_nonce, curve->nonce_len, + /* HKDF-Extract(C-nonce, M.x) */ + if (dpp_hmac(curve->hash_len, auth->c_nonce, curve->nonce_len, Mx, curve->prime_len, prk) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); @@ -2433,7 +2433,7 @@ int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, "dpp reconfig key", auth->ke, curve->hash_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, - "DPP: ke = HKDF(I-nonce, \"dpp reconfig key\", M.x)", + "DPP: ke = HKDF(C-nonce, \"dpp reconfig key\", M.x)", auth->ke, curve->hash_len); res = 0; diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index a361131db..13324a047 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -158,10 +158,10 @@ static struct wpabuf * dpp_reconfig_build_req(struct dpp_authentication *auth) wpabuf_put_le16(msg, os_strlen(auth->conf->connector)); wpabuf_put_str(msg, auth->conf->connector); - /* I-nonce */ - wpabuf_put_le16(msg, DPP_ATTR_I_NONCE); + /* C-nonce */ + wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE); wpabuf_put_le16(msg, auth->curve->nonce_len); - wpabuf_put_data(msg, auth->i_nonce, auth->curve->nonce_len); + wpabuf_put_data(msg, auth->c_nonce, auth->curve->nonce_len); wpa_hexdump_buf(MSG_DEBUG, "DPP: Reconfig Authentication Request frame attributes", @@ -295,8 +295,8 @@ dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, if (dpp_configurator_build_own_connector(conf, curve) < 0) goto fail; - if (random_get_bytes(auth->i_nonce, auth->curve->nonce_len)) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); + if (random_get_bytes(auth->c_nonce, auth->curve->nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate C-nonce"); goto fail; } @@ -331,15 +331,15 @@ static int dpp_reconfig_build_resp(struct dpp_authentication *auth, if (!clear) goto fail; - /* I-nonce (wrapped) */ - wpabuf_put_le16(clear, DPP_ATTR_I_NONCE); + /* C-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE); wpabuf_put_le16(clear, auth->curve->nonce_len); - wpabuf_put_data(clear, auth->i_nonce, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len); - /* R-nonce (wrapped) */ - wpabuf_put_le16(clear, DPP_ATTR_R_NONCE); + /* E-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); wpabuf_put_le16(clear, auth->curve->nonce_len); - wpabuf_put_data(clear, auth->r_nonce, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->e_nonce, auth->curve->nonce_len); /* Connection Status (wrapped) */ wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS); @@ -392,7 +392,7 @@ static int dpp_reconfig_build_resp(struct dpp_authentication *auth, len[1] = attr_end - attr_start; wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - /* Wrapped Data: {I-nonce, R-nonce, Connection Status}ke */ + /* Wrapped Data: {C-nonce, E-nonce, Connection Status}ke */ wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); @@ -430,8 +430,8 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, const u8 *attr_start, size_t attr_len) { struct dpp_authentication *auth = NULL; - const u8 *trans_id, *version, *i_connector, *i_nonce; - u16 trans_id_len, version_len, i_connector_len, i_nonce_len; + const u8 *trans_id, *version, *i_connector, *c_nonce; + u16 trans_id_len, version_len, i_connector_len, c_nonce_len; struct dpp_signed_connector_info info; enum dpp_status_error res; struct json_token *root = NULL, *own_root = NULL, *token; @@ -465,14 +465,14 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, wpa_hexdump_ascii(MSG_DEBUG, "DPP: I-Connector", i_connector, i_connector_len); - i_nonce = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len > DPP_MAX_NONCE_LEN) { + c_nonce = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); + if (!c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) { wpa_printf(MSG_DEBUG, - "DPP: Missing or invalid I-Nonce attribute"); + "DPP: Missing or invalid C-nonce attribute"); goto fail; } - wpa_hexdump(MSG_DEBUG, "DPP: I-Nonce", i_nonce, i_nonce_len); + wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); res = dpp_check_signed_connector(&info, csign_key, csign_key_len, i_connector, i_connector_len); @@ -519,25 +519,25 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", auth->peer_version); - os_memcpy(auth->i_nonce, i_nonce, i_nonce_len); + os_memcpy(auth->c_nonce, c_nonce, c_nonce_len); if (dpp_reconfig_derive_ke_responder(auth, net_access_key, net_access_key_len, token) < 0) goto fail; - if (i_nonce_len != auth->curve->nonce_len) { + if (c_nonce_len != auth->curve->nonce_len) { wpa_printf(MSG_DEBUG, - "DPP: Unexpected I-nonce length %u (curve nonce len %zu)", - i_nonce_len, auth->curve->nonce_len); + "DPP: Unexpected C-nonce length %u (curve nonce len %zu)", + c_nonce_len, auth->curve->nonce_len); goto fail; } - if (random_get_bytes(auth->r_nonce, auth->curve->nonce_len)) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce"); + if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); goto fail; } - wpa_hexdump_key(MSG_DEBUG, "DPP: R-nonce", - auth->r_nonce, auth->curve->nonce_len); + wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce", + auth->e_nonce, auth->curve->nonce_len); /* Build Connection Status object */ /* TODO: Get appropriate result value */ @@ -590,15 +590,15 @@ dpp_reconfig_build_conf(struct dpp_authentication *auth) wpabuf_put_le16(clear, 1); wpabuf_put_u8(clear, auth->peer_version); - /* I-nonce (wrapped) */ - wpabuf_put_le16(clear, DPP_ATTR_I_NONCE); + /* C-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE); wpabuf_put_le16(clear, auth->curve->nonce_len); - wpabuf_put_data(clear, auth->i_nonce, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len); - /* R-nonce (wrapped) */ - wpabuf_put_le16(clear, DPP_ATTR_R_NONCE); + /* E-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); wpabuf_put_le16(clear, auth->curve->nonce_len); - wpabuf_put_data(clear, auth->r_nonce, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->e_nonce, auth->curve->nonce_len); /* Reconfig-Flags (wrapped) */ flags = DPP_CONFIG_REPLACEKEY; @@ -659,9 +659,9 @@ dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len) { const u8 *trans_id, *version, *r_connector, *r_proto, *wrapped_data, - *i_nonce, *r_nonce, *conn_status; + *c_nonce, *e_nonce, *conn_status; u16 trans_id_len, version_len, r_connector_len, r_proto_len, - wrapped_data_len, i_nonce_len, r_nonce_len, conn_status_len; + wrapped_data_len, c_nonce_len, e_nonce_len, conn_status_len; struct wpabuf *conf = NULL; char *signed_connector = NULL; struct dpp_signed_connector_info info; @@ -787,23 +787,23 @@ dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, goto fail; } - i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len != auth->curve->nonce_len || - os_memcmp(i_nonce, auth->i_nonce, i_nonce_len) != 0) { - dpp_auth_fail(auth, "Missing or invalid I-nonce"); + c_nonce = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); + if (!c_nonce || c_nonce_len != auth->curve->nonce_len || + os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid C-nonce"); goto fail; } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); - r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, - &r_nonce_len); - if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "Missing or invalid R-nonce"); + e_nonce = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len); + if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid E-nonce"); goto fail; } - wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); - os_memcpy(auth->r_nonce, r_nonce, r_nonce_len); + wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len); + os_memcpy(auth->e_nonce, e_nonce, e_nonce_len); conn_status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONN_STATUS, &conn_status_len); @@ -843,10 +843,10 @@ fail: int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len) { - const u8 *trans_id, *version, *wrapped_data, *i_nonce, *r_nonce, + const u8 *trans_id, *version, *wrapped_data, *c_nonce, *e_nonce, *reconfig_flags, *status; - u16 trans_id_len, version_len, wrapped_data_len, i_nonce_len, - r_nonce_len, reconfig_flags_len, status_len; + u16 trans_id_len, version_len, wrapped_data_len, c_nonce_len, + e_nonce_len, reconfig_flags_len, status_len; const u8 *addr[2]; size_t len[2]; u8 *unwrapped = NULL; @@ -925,23 +925,23 @@ int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, goto fail; } - i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len != auth->curve->nonce_len || - os_memcmp(i_nonce, auth->i_nonce, i_nonce_len) != 0) { - dpp_auth_fail(auth, "Missing or invalid I-nonce"); + c_nonce = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); + if (!c_nonce || c_nonce_len != auth->curve->nonce_len || + os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid C-nonce"); goto fail; } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); - r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, - &r_nonce_len); - if (!r_nonce || r_nonce_len != auth->curve->nonce_len || - os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) { - dpp_auth_fail(auth, "Missing or invalid R-nonce"); + e_nonce = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len); + if (!e_nonce || e_nonce_len != auth->curve->nonce_len || + os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid E-nonce"); goto fail; } - wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); + wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len); reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_RECONFIG_FLAGS, From 4ae5e459dd9ffa314be9e199c9efb639d54e905e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 9 Sep 2020 23:15:37 +0300 Subject: [PATCH 0858/1105] DPP2: Move E-nonce to be outside wrapped data in Reconfig Auth Resp This was changed in the protocol design to allow ke derivation to use E-nonce, so update implementation to match. Signed-off-by: Jouni Malinen --- src/common/dpp_reconfig.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 13324a047..225bac5e5 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -325,7 +325,7 @@ static int dpp_reconfig_build_resp(struct dpp_authentication *auth, int res = -1; /* Build DPP Reconfig Authentication Response frame attributes */ - clear_len = 2 * (4 + auth->curve->nonce_len) + + clear_len = 4 + auth->curve->nonce_len + 4 + wpabuf_len(conn_status); clear = wpabuf_alloc(clear_len); if (!clear) @@ -336,11 +336,6 @@ static int dpp_reconfig_build_resp(struct dpp_authentication *auth, wpabuf_put_le16(clear, auth->curve->nonce_len); wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len); - /* E-nonce (wrapped) */ - wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); - wpabuf_put_le16(clear, auth->curve->nonce_len); - wpabuf_put_data(clear, auth->e_nonce, auth->curve->nonce_len); - /* Connection Status (wrapped) */ wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS); wpabuf_put_le16(clear, wpabuf_len(conn_status)); @@ -352,6 +347,7 @@ static int dpp_reconfig_build_resp(struct dpp_authentication *auth, attr_len = 4 + 1 + 4 + 1 + 4 + os_strlen(own_connector) + + 4 + auth->curve->nonce_len + 4 + wpabuf_len(pr) + 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_RESP, attr_len); @@ -375,6 +371,11 @@ static int dpp_reconfig_build_resp(struct dpp_authentication *auth, wpabuf_put_le16(msg, os_strlen(own_connector)); wpabuf_put_str(msg, own_connector); + /* E-nonce */ + wpabuf_put_le16(msg, DPP_ATTR_ENROLLEE_NONCE); + wpabuf_put_le16(msg, auth->curve->nonce_len); + wpabuf_put_data(msg, auth->e_nonce, auth->curve->nonce_len); + /* Responder Protocol Key (Pr) */ wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); wpabuf_put_le16(msg, wpabuf_len(pr)); @@ -719,6 +720,15 @@ dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, wpa_hexdump_ascii(MSG_DEBUG, "DPP: R-Connector", r_connector, r_connector_len); + e_nonce = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len); + if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid E-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len); + os_memcpy(auth->e_nonce, e_nonce, e_nonce_len); + r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, &r_proto_len); if (!r_proto) { @@ -796,15 +806,6 @@ dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, } wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); - e_nonce = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len); - if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "Missing or invalid E-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len); - os_memcpy(auth->e_nonce, e_nonce, e_nonce_len); - conn_status = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_CONN_STATUS, &conn_status_len); if (!conn_status) { From 10c3e58b276f4ccfb1a48ad5c94f6fa843e9d8e2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 9 Sep 2020 23:33:58 +0300 Subject: [PATCH 0859/1105] DPP2: Include E-nonce in reconfig ke derivation This was changed in the protocol design to include nonce from both devices, so update implementation to match. Signed-off-by: Jouni Malinen --- src/common/dpp_crypto.c | 30 ++++++++++++++++++++++-------- src/common/dpp_reconfig.c | 7 ------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 9ae33d59a..5938ed6a7 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -19,6 +19,7 @@ #include "utils/json.h" #include "common/ieee802_11_defs.h" #include "crypto/crypto.h" +#include "crypto/random.h" #include "crypto/sha384.h" #include "crypto/sha512.h" #include "dpp.h" @@ -2269,6 +2270,7 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, u8 prk[DPP_MAX_HASH_LEN]; const struct dpp_curve_params *curve; int res = -1; + u8 nonces[2 * DPP_MAX_NONCE_LEN]; own_key = dpp_set_keypair(&auth->curve, net_access_key, net_access_key_len); @@ -2293,6 +2295,13 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, if (!auth->own_protocol_key) goto fail; + if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce", + auth->e_nonce, auth->curve->nonce_len); + /* M = { cR + pR } * CI */ cR = EVP_PKEY_get0_EC_KEY(own_key); pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); @@ -2325,10 +2334,12 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, goto fail; wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); - /* ke = HKDF(C-nonce, "dpp reconfig key", M.x) */ + /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ - /* HKDF-Extract(C-nonce, M.x) */ - if (dpp_hmac(curve->hash_len, auth->c_nonce, curve->nonce_len, + /* HKDF-Extract(C-nonce | E-nonce, M.x) */ + os_memcpy(nonces, auth->c_nonce, curve->nonce_len); + os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); + if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, Mx, curve->prime_len, prk) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); @@ -2338,7 +2349,7 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, "dpp reconfig key", auth->ke, curve->hash_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, - "DPP: ke = HKDF(C-nonce, \"dpp reconfig key\", M.x)", + "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", auth->ke, curve->hash_len); res = 0; @@ -2375,6 +2386,7 @@ int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, u8 prk[DPP_MAX_HASH_LEN]; int res = -1; const struct dpp_curve_params *curve; + u8 nonces[2 * DPP_MAX_NONCE_LEN]; pr = dpp_set_pubkey_point(auth->conf->connector_key, r_proto, r_proto_len); @@ -2420,10 +2432,12 @@ int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); - /* ke = HKDF(C-nonce, "dpp reconfig key", M.x) */ + /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ - /* HKDF-Extract(C-nonce, M.x) */ - if (dpp_hmac(curve->hash_len, auth->c_nonce, curve->nonce_len, + /* HKDF-Extract(C-nonce | E-nonce, M.x) */ + os_memcpy(nonces, auth->c_nonce, curve->nonce_len); + os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); + if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, Mx, curve->prime_len, prk) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); @@ -2433,7 +2447,7 @@ int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, "dpp reconfig key", auth->ke, curve->hash_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, - "DPP: ke = HKDF(C-nonce, \"dpp reconfig key\", M.x)", + "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", auth->ke, curve->hash_len); res = 0; diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index 225bac5e5..f9d01d841 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -533,13 +533,6 @@ dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, goto fail; } - if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); - goto fail; - } - wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce", - auth->e_nonce, auth->curve->nonce_len); - /* Build Connection Status object */ /* TODO: Get appropriate result value */ /* TODO: ssid64 and channelList */ From 5ecb45a41c116ba57ed6a4fafd703f2b670fa3f6 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Thu, 3 Sep 2020 00:25:28 +0530 Subject: [PATCH 0860/1105] OCV: Use more granular error codes for OCI validation failures Enhance the return values of ocv_verify_tx_params with enum to indicate different OCI verification failures to caller. Signed-off-by: Veerendranath Jakkam --- src/ap/ieee802_11.c | 3 ++- src/ap/ieee802_11_shared.c | 3 ++- src/ap/wnm_ap.c | 2 +- src/ap/wpa_auth.c | 6 ++++-- src/ap/wpa_auth_ft.c | 3 ++- src/common/ocv.c | 23 ++++++++++++----------- src/common/ocv.h | 13 ++++++++++--- src/rsn_supp/wpa.c | 6 +++--- src/rsn_supp/wpa_ft.c | 2 +- wpa_supplicant/mesh_mpm.c | 2 +- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wnm_sta.c | 2 +- 12 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index c98e77103..13431d567 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3563,7 +3563,8 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, return WLAN_STATUS_UNSPECIFIED_FAILURE; if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { + tx_chanwidth, tx_seg1_idx) != + OCI_SUCCESS) { wpa_printf(MSG_WARNING, "FILS: OCV failed: %s", ocv_errorstr); wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index 79ed450e2..17003d506 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -275,7 +275,8 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, return; if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { + tx_chanwidth, tx_seg1_idx) != + OCI_SUCCESS) { wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" MACSTR " frame=saquery%s error=%s", MAC2STR(sa), diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 248f5a1cf..be817978e 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -326,7 +326,7 @@ static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd, if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { + ci.seg1_idx) != OCI_SUCCESS) { wpa_msg(hapd, MSG_WARNING, "WNM: OCV failed: %s", ocv_errorstr); return; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 9e6c0cad3..a5b1953f6 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3051,7 +3051,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) return; if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { + tx_chanwidth, tx_seg1_idx) != + OCI_SUCCESS) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, "OCV failed: %s", ocv_errorstr); if (wpa_auth->conf.msg_ctx) @@ -3913,7 +3914,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) return; if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { + tx_chanwidth, tx_seg1_idx) != + OCI_SUCCESS) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, "OCV failed: %s", ocv_errorstr); if (wpa_auth->conf.msg_ctx) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 9caac194e..5cd7037e9 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -3519,7 +3519,8 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_UNSPECIFIED_FAILURE; if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { + tx_chanwidth, tx_seg1_idx) != + OCI_SUCCESS) { wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); if (sm->wpa_auth->conf.msg_ctx) wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, diff --git a/src/common/ocv.c b/src/common/ocv.c index 6c35117a7..4bc2749a7 100644 --- a/src/common/ocv.c +++ b/src/common/ocv.c @@ -95,23 +95,24 @@ int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos) } -int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, - struct wpa_channel_info *ci, int tx_chanwidth, - int tx_seg1_idx) +enum oci_verify_result +ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, + struct wpa_channel_info *ci, int tx_chanwidth, + int tx_seg1_idx) { struct oci_info oci; if (!oci_ie) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), "did not receive mandatory OCI"); - return -1; + return OCI_NOT_FOUND; } if (oci_ie_len != 3) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), "received OCI of unexpected length (%d)", (int) oci_ie_len); - return -1; + return OCI_INVALID_LENGTH; } os_memset(&oci, 0, sizeof(oci)); @@ -121,7 +122,7 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, if (ocv_derive_all_parameters(&oci) != 0) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), "unable to interpret received OCI"); - return -1; + return OCI_PARSE_ERROR; } /* Primary frequency used to send frames to STA must match the STA's */ @@ -129,7 +130,7 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), "primary channel mismatch in received OCI (we use %d but receiver is using %d)", ci->frequency, oci.freq); - return -1; + return OCI_PRIMARY_FREQ_MISMATCH; } /* We shouldn't transmit with a higher bandwidth than the STA supports @@ -138,7 +139,7 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), "channel bandwidth mismatch in received OCI (we use %d but receiver only supports %d)", tx_chanwidth, oci.chanwidth); - return -1; + return OCI_CHANNEL_WIDTH_MISMATCH; } /* @@ -152,7 +153,7 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), "secondary channel mismatch in received OCI (we use %d but receiver is using %d)", ci->sec_channel, oci.sec_channel); - return -1; + return OCI_SECONDARY_FREQ_MISMATCH; } /* @@ -165,8 +166,8 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), "frequency segment 1 mismatch in received OCI (we use %d but receiver is using %d)", tx_seg1_idx, oci.seg1_idx); - return -1; + return OCI_SEG_1_INDEX_MISMATCH; } - return 0; + return OCI_SUCCESS; } diff --git a/src/common/ocv.h b/src/common/ocv.h index 6379d9d06..7fa4522c1 100644 --- a/src/common/ocv.h +++ b/src/common/ocv.h @@ -27,14 +27,21 @@ struct oci_info { #define OCV_OCI_EXTENDED_LEN (3 + OCV_OCI_LEN) #define OCV_OCI_KDE_LEN (2 + RSN_SELECTOR_LEN + OCV_OCI_LEN) +enum oci_verify_result { + OCI_SUCCESS, OCI_NOT_FOUND, OCI_INVALID_LENGTH, OCI_PARSE_ERROR, + OCI_PRIMARY_FREQ_MISMATCH, OCI_CHANNEL_WIDTH_MISMATCH, + OCI_SECONDARY_FREQ_MISMATCH, OCI_SEG_1_INDEX_MISMATCH +}; + extern char ocv_errorstr[256]; int ocv_derive_all_parameters(struct oci_info *oci); int ocv_insert_oci(struct wpa_channel_info *ci, u8 **argpos); int ocv_insert_oci_kde(struct wpa_channel_info *ci, u8 **argpos); int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos); -int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, - struct wpa_channel_info *ci, int tx_chanwidth, - int tx_seg1_idx); +enum oci_verify_result +ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, + struct wpa_channel_info *ci, int tx_chanwidth, + int tx_seg1_idx); #endif /* OCV_H */ diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index b41e6e427..f3d324a67 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1717,7 +1717,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { + ci.seg1_idx) != OCI_SUCCESS) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" MACSTR " frame=eapol-key-m3 error=%s", MAC2STR(sm->bssid), ocv_errorstr); @@ -1865,7 +1865,7 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { + ci.seg1_idx) != OCI_SUCCESS) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" MACSTR " frame=eapol-key-g1 error=%s", MAC2STR(sm->bssid), ocv_errorstr); @@ -4799,7 +4799,7 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { + ci.seg1_idx) != OCI_SUCCESS) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" MACSTR " frame=fils-assoc error=%s", MAC2STR(sm->bssid), ocv_errorstr); diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index bcaf42fe6..bf73376b6 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -1167,7 +1167,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { + ci.seg1_idx) != OCI_SUCCESS) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" MACSTR " frame=ft-assoc error=%s", MAC2STR(sm->bssid), ocv_errorstr); diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 3abbe09d0..4547eea88 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -1292,7 +1292,7 @@ void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != - 0) { + OCI_SUCCESS) { wpa_printf(MSG_WARNING, "MPM: OCV failed: %s", ocv_errorstr); return; diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 2faaff930..7fec1cd8d 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -2915,7 +2915,7 @@ void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { + ci.seg1_idx) != OCI_SUCCESS) { wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR " frame=saquery%s error=%s", MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ? diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index d0c9f0f45..19f1eca8a 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -383,7 +383,7 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s, if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { + ci.seg1_idx) != OCI_SUCCESS) { wpa_msg(wpa_s, MSG_WARNING, "WNM: OCV failed: %s", ocv_errorstr); return; From a71b100c3bf306016b91d3baf3ae48c6bb8720fc Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 2 Sep 2020 17:25:15 +0530 Subject: [PATCH 0861/1105] OCV: Allow connecting MFP incapable OCV STA when OCV is disabled in AP Skip check to mandate MFP capability for OCV enabled STA when OCV is disabled in AP. This is to improve interoperability with STAs in which OCV capability is advertised incorrectly without advertising MFP when OCV is disabled in AP. Signed-off-by: Veerendranath Jakkam --- src/ap/wpa_auth_ie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index a7e6354a5..3a16997cf 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -808,7 +808,7 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_SAE */ #ifdef CONFIG_OCV - if ((data.capabilities & WPA_CAPABILITY_OCVC) && + if (wpa_auth->conf.ocv && (data.capabilities & WPA_CAPABILITY_OCVC) && !(data.capabilities & WPA_CAPABILITY_MFPC)) { wpa_printf(MSG_DEBUG, "Management frame protection required with OCV, but client did not enable it"); From 41f81890571c06e15d2c5a6f1f98d29e6c5a5822 Mon Sep 17 00:00:00 2001 From: Shaakir Mohamed Date: Tue, 8 Sep 2020 14:08:38 -0700 Subject: [PATCH 0862/1105] SAE-PK: Add support to skip sae_pk password check for testing purposes Add support to skip sae_pk password check under compile flag CONFIG_TESTING_OPTIONS which allows AP to be configured with sae_pk enabled but a password that is invalid for sae_pk. Signed-off-by: Shaakir Mohamed --- hostapd/config_file.c | 8 +++++++- src/ap/ap_config.c | 10 +++++++++- src/ap/ap_config.h | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 1861b5203..542c8cd0d 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2245,7 +2245,11 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val) } #ifdef CONFIG_SAE_PK - if (pw->pk && !sae_pk_valid_password(pw->password)) { + if (pw->pk && +#ifdef CONFIG_TESTING_OPTIONS + !bss->sae_pk_password_check_skip && +#endif /* CONFIG_TESTING_OPTIONS */ + !sae_pk_valid_password(pw->password)) { wpa_printf(MSG_INFO, "Invalid SAE password for a SAE-PK sae_password entry"); goto fail; @@ -4137,6 +4141,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->sae_commit_status = atoi(pos); } else if (os_strcmp(buf, "sae_pk_omit") == 0) { bss->sae_pk_omit = atoi(pos); + } else if (os_strcmp(buf, "sae_pk_password_check_skip") == 0) { + bss->sae_pk_password_check_skip = atoi(pos); } else if (os_strcmp(buf, "sae_commit_override") == 0) { wpabuf_free(bss->sae_commit_override); bss->sae_commit_override = wpabuf_parse_bin(pos); diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 769f7fab6..04535a163 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -1126,12 +1126,20 @@ static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss) bool res = false; if (bss->ssid.wpa_passphrase && +#ifdef CONFIG_TESTING_OPTIONS + !bss->sae_pk_password_check_skip && +#endif /* CONFIG_TESTING_OPTIONS */ sae_pk_valid_password(bss->ssid.wpa_passphrase)) res = true; for (pw = bss->sae_passwords; pw; pw = pw->next) { - if (!pw->pk && sae_pk_valid_password(pw->password)) + if (!pw->pk && +#ifdef CONFIG_TESTING_OPTIONS + !bss->sae_pk_password_check_skip && +#endif /* CONFIG_TESTING_OPTIONS */ + sae_pk_valid_password(pw->password)) return true; + if (bss->ssid.wpa_passphrase && res && pw->pk && os_strcmp(bss->ssid.wpa_passphrase, pw->password) == 0) res = false; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index b705c378f..bada04c3e 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -671,6 +671,7 @@ struct hostapd_bss_config { int sae_reflection_attack; int sae_commit_status; int sae_pk_omit; + int sae_pk_password_check_skip; struct wpabuf *sae_commit_override; struct wpabuf *rsne_override_eapol; struct wpabuf *rsnxe_override_eapol; From db599dbe998431fdd0a22b4221cff02f862688ef Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 11 Sep 2020 15:53:56 +0300 Subject: [PATCH 0863/1105] tests: SAE-PK with invalid password on AP Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae_pk.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/hwsim/test_sae_pk.py b/tests/hwsim/test_sae_pk.py index b425b9083..3bbc62ecd 100644 --- a/tests/hwsim/test_sae_pk.py +++ b/tests/hwsim/test_sae_pk.py @@ -429,3 +429,34 @@ def test_sae_pk_and_psk_invalid_password(dev, apdev): res = hapd.request("ENABLE") if "FAIL" not in res: raise Exception("Invalid configuration accepted") + +def test_sae_pk_invalid_pw(dev, apdev): + """SAE-PK with invalid password on AP""" + check_sae_pk_capab(dev[0]) + dev[0].set("sae_groups", "") + + params = hostapd.wpa2_params(ssid=SAE_PK_SSID) + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params["sae_pk_password_check_skip"] = "1" + invalid_pw = "r6cr+6ksa+56og" + params['sae_password'] = ['%s|pk=%s:%s' % (invalid_pw, SAE_PK_SEC3_M, + SAE_PK_19_PK)] + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect(SAE_PK_SSID, sae_password=invalid_pw, + key_mgmt="SAE", ieee80211w="2", scan_freq="2412") + dev[0].request("REMOVE_NETWORK *") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW, + key_mgmt="SAE", ieee80211w="2", scan_freq="2412", + wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) + if ev is None: + raise Exception("No result for the connection attempt") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection with invalid SAE-PK password") + dev[0].request("DISCONNECT") From 8a6a2894d17df4e133e84c5b44fa51268bc43517 Mon Sep 17 00:00:00 2001 From: Hu Wang Date: Thu, 17 Sep 2020 20:40:01 +0800 Subject: [PATCH 0864/1105] Add new QCA vendor attributes to get thermal level Add new QCA vendor attributes to get thermal level from the driver. The driver may return thermal level when userpace requests, or send a thermal event when thermal level changes. Signed-off-by: Hu Wang --- src/common/qca-vendor.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index aae56f935..e64270b26 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -6808,8 +6808,9 @@ enum qca_wlan_vendor_attr_wake_stats { /** * enum qca_wlan_vendor_thermal_level - Defines various thermal levels - * configured by userspace to the driver/firmware. The values will be - * encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL attribute. + * configured by userspace to the driver/firmware. + * The values can be encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL or + * QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL attribute. * The driver/firmware takes actions requested by userspace such as throttling * wifi TX etc. in order to mitigate high temperature. * @@ -6843,8 +6844,9 @@ enum qca_wlan_vendor_attr_thermal_cmd { */ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1, /* Userspace uses this attribute to configure thermal level to the - * driver/firmware. Used in request, u32 attribute, possible values - * are defined in enum qca_wlan_vendor_thermal_level. + * driver/firmware, or get thermal level from the driver/firmware. + * Used in request or response, u32 attribute, + * possible values are defined in enum qca_wlan_vendor_thermal_level. */ QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL = 2, /* Userspace uses this attribute to configure the time in which the @@ -6882,6 +6884,9 @@ enum qca_wlan_vendor_attr_thermal_cmd { * resume action. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL: Configure thermal level to * the driver/firmware. + * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL: Request to get the current + * thermal level from the driver/firmware. The driver should respond with a + * thermal level defined in enum qca_wlan_vendor_thermal_level. */ enum qca_wlan_vendor_attr_thermal_cmd_type { QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS, @@ -6889,6 +6894,7 @@ enum qca_wlan_vendor_attr_thermal_cmd_type { QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL, + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL, }; /** @@ -6971,6 +6977,11 @@ enum qca_wlan_vendor_attr_thermal_event { * NLA_FLAG attribute. */ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE, + /* Thermal level from the driver. + * u32 attribute. Possible values are defined in + * enum qca_wlan_vendor_thermal_level. + */ + QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST, From fd4a58ccdc37f7f81e39e29ca1da36894df1b58f Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Mon, 21 Sep 2020 14:52:22 +0530 Subject: [PATCH 0865/1105] Additional attributes to QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL Add additional attributes to enum qca_vendor_attr_roam_control to control the roam behavior through QCA_NL80211_VENDOR_SUBCMD_ROAM and QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index e64270b26..340f6117e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -4042,6 +4042,30 @@ enum qca_vendor_attr_scan_freq_list_scheme { QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_AFTER_LAST - 1, }; +/** + * enum qca_roam_scan_scheme: Scan scheme + * + * @QCA_ROAM_SCAN_SCHEME_NO_SCAN: No frequencies specified to scan. + * Indicates the driver to not scan on a Roam Trigger scenario, but + * disconnect. E.g., on a BTM request from the AP the driver/firmware shall + * disconnect from the current connected AP by notifying a failure + * code in the BTM response. + * + * @QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN: Indicates the driver/firmware to + * trigger partial frequency scans. These frequencies are the ones learned + * or maintained by the driver based on the probability of finding the + * BSSIDs in the ESS for which the roaming is triggered. + * + * @QCA_ROAM_SCAN_SCHEME_FULL_SCAN: Indicates the driver/firmware to + * trigger the scan on all the valid frequencies to find better + * candidates to roam. + */ +enum qca_roam_scan_scheme { + QCA_ROAM_SCAN_SCHEME_NO_SCAN = 0, + QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN = 1, + QCA_ROAM_SCAN_SCHEME_FULL_SCAN = 2, +}; + /* * enum qca_vendor_roam_triggers: Bitmap of roaming triggers * @@ -4233,6 +4257,27 @@ enum qca_vendor_attr_roam_candidate_selection_criteria { * * Clears the selection criteria configured in the driver when specified * with clear command. + * + * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME: Unsigned 32-bit value. + * Represents value of the scan frequency scheme from enum + * qca_roam_scan_scheme. + * It's an optional attribute. If this attribute is not configured, the + * driver shall proceed with default behavior. + * + * @QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD: Signed 32-bit value in dBm, + * signifying the RSSI threshold of the current connected AP, indicating + * the driver to trigger roam only when the current connected AP's RSSI + * is less than this threshold. + * + * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD: Signed 32-bit value in dBm, + * signifying the RSSI threshold of the candidate AP, indicating + * the driver to trigger roam only to the candidate AP with RSSI + * better than this threshold. + * + * @QCA_ATTR_ROAM_CONTROL_USER_REASON: Unsigned 32-bit value. Represents the + * user defined reason code to be sent to the AP in response to AP's + * request to trigger the roam if the roaming cannot be triggered. + * Applies to all the scenarios of AP assisted roaming (e.g., BTM). */ enum qca_vendor_attr_roam_control { QCA_ATTR_ROAM_CONTROL_ENABLE = 1, @@ -4243,6 +4288,10 @@ enum qca_vendor_attr_roam_control { QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD = 6, QCA_ATTR_ROAM_CONTROL_TRIGGERS = 7, QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA = 8, + QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME = 9, + QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD = 10, + QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11, + QCA_ATTR_ROAM_CONTROL_USER_REASON = 12, /* keep last */ QCA_ATTR_ROAM_CONTROL_AFTER_LAST, From a92660a00e102df6dd1a6500c758407a730f7b8e Mon Sep 17 00:00:00 2001 From: Kiran Kumar Lokere Date: Thu, 10 Sep 2020 20:40:02 -0700 Subject: [PATCH 0866/1105] Work around Supported Operating Classes element issues for 6 GHz IEEE Std 802.11 specifies that the Operating Classes field terminates immediately before the OneHundredAndThirty Delimiter (i.e., an octet with value 130). Move the operating class value 130 last in the global op_class array so that it gets added as the last entry into the Supported Operating Clases element and the 6 GHz operating class is parsed in that element by implementation that stop at the assumed OneHundredAndThirty Delimiter. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index c0c569bc6..9c536cc5f 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1872,7 +1872,6 @@ const struct oper_class_map global_op_class[] = { */ { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP }, /* @@ -1884,6 +1883,12 @@ const struct oper_class_map global_op_class[] = { { HOSTAPD_MODE_IEEE80211AD, 181, 9, 13, 1, BW4320, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP }, + + /* Keep the operating class 130 as the last entry as a workaround for + * the OneHundredAndThirty Delimiter value used in the Supported + * Operating Classes element to indicate the end of the Operating + * Classes field. */ + { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP }, { -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP } }; From e3ba0c4cd230424de1c05d90b28dca56af1fb953 Mon Sep 17 00:00:00 2001 From: Rohan Date: Fri, 14 Aug 2020 19:06:15 +0530 Subject: [PATCH 0867/1105] Do not start SA Query procedure without keys The AP mode condition for initiating the SA Query procedure when receiving a new (Re)Association Request frame used only association state and MFP negotiation result without checking that the key exchange has been completed. This can give rise to a corner case where the SA Query procedure may get started after open association but before the 4-way handshake has been completed, resulting in open SA query frames over the air. Fix this by adding station authorized check in hostapd_notif_assoc() and check_assoc_ies(). Signed-off-by: Rohan --- src/ap/drv_callbacks.c | 10 ++++++---- src/ap/ieee802_11.c | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 9faac0ddc..a8b339f58 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -388,13 +388,15 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, goto fail; } - if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP) && + if ((sta->flags & + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) == + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED) && !sta->sa_query_timed_out && sta->sa_query_count > 0) ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP) && + if ((sta->flags & + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) == + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED) && !sta->sa_query_timed_out && (sta->auth_alg != WLAN_AUTH_FT)) { /* diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 13431d567..e3a9cbee9 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3328,13 +3328,15 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, resp = wpa_res_to_status_code(res); if (resp != WLAN_STATUS_SUCCESS) return resp; - if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP) && + if ((sta->flags & + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) == + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED) && !sta->sa_query_timed_out && sta->sa_query_count > 0) ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP) && + if ((sta->flags & + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) == + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED) && !sta->sa_query_timed_out && (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { /* From 7e20502f7adc5a067eb41b261348d39190de9e3c Mon Sep 17 00:00:00 2001 From: Karthikeyan Kathirvel Date: Mon, 20 Jul 2020 22:22:01 +0530 Subject: [PATCH 0868/1105] hostapd: Resolved compiler uninitialized warning Resolved the below warning ../src/ap/ieee802_11.c:4535:25: warning: 'reply_res' may be used uninitialized in this function [-Wmaybe-uninitialized] if (sta && ((reply_res != WLAN_STATUS_SUCCESS && ^ Since reply_res is been assigned inside an if condition and so compiler treats reply_res as uninitalized variable Initialize reply_res with WLAN_STATUS_UNSPECIFIED_FAILURE. Fixes: 5344af7d22ac ("FT: Discard ReassocReq with mismatching RSNXE Used value") Signed-off-by: Karthikeyan Kathirvel --- src/ap/ieee802_11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index e3a9cbee9..bff8bac25 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4148,7 +4148,7 @@ static void handle_assoc(struct hostapd_data *hapd, { u16 capab_info, listen_interval, seq_ctrl, fc; int resp = WLAN_STATUS_SUCCESS; - u16 reply_res; + u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE; const u8 *pos; int left, i; struct sta_info *sta; From cab139ebc2e8950fececa29991ffd01b3f921aae Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 22 Sep 2020 23:31:20 +0300 Subject: [PATCH 0869/1105] Fix a typo in a comment Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index bff8bac25..568ecacb0 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4528,7 +4528,7 @@ static void handle_assoc(struct hostapd_data *hapd, os_free(tmp); /* - * Remove the station in case tranmission of a success response fails + * Remove the station in case transmission of a success response fails * (the STA was added associated to the driver) or if the station was * previously added unassociated. */ From 90e478aa0a1c2af5f12a09f1e77a640c850e3c13 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 23 Sep 2020 23:06:55 +0300 Subject: [PATCH 0870/1105] DPP2: Use the PFS fallback if multiple key_mgmt values are enabled Previously this fallback from PFS enabled to disabled (and back to enabled) was used only if the local network profile used key_mgmt=DPP, i.e., did not enable another other AKM. That leaves out some valid cases since the local network profile could actually enable both DPP and SAE. Extend this check to accept cases DPP AKM is enabled and it was selected for the connection even if there other enabled AKMs. Signed-off-by: Jouni Malinen --- wpa_supplicant/events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 80b803f5c..15c572f11 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4494,7 +4494,9 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, * WLAN_STATUS_AKMP_NOT_VALID is addressed in the same manner as an * interoperability workaround with older hostapd implementation. */ if (DPP_VERSION > 1 && wpa_s->current_ssid && - wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP && + (wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP || + ((wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_DPP) && + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP)) && wpa_s->current_ssid->dpp_pfs == 0 && (data->assoc_reject.status_code == WLAN_STATUS_ASSOC_DENIED_UNSPEC || From 440a5e235b7e0782e01286740e0412f1ef8aba8d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 23 Sep 2020 23:09:32 +0300 Subject: [PATCH 0871/1105] tests: DPP PFS fallback with SAE enabled Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 0f7d19fde..21847cb24 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5391,7 +5391,7 @@ def test_dpp_chirp_ap(dev, apdev): timeout=20) update_hapd_config(hapd) -def start_dpp_pfs_ap(apdev, pfs): +def start_dpp_pfs_ap(apdev, pfs, sae=False): params = {"ssid": "dpp", "wpa": "2", "wpa_key_mgmt": "DPP", @@ -5401,18 +5401,24 @@ def start_dpp_pfs_ap(apdev, pfs): "dpp_connector": params1_ap_connector, "dpp_csign": params1_csign, "dpp_netaccesskey": params1_ap_netaccesskey} + if sae: + params["wpa_key_mgmt"] = "DPP SAE" + params["sae_password"] = "sae-password" try: hapd = hostapd.add_ap(apdev, params) except: raise HwsimSkip("DPP not supported") return hapd -def run_dpp_pfs_sta(dev, pfs, fail=False, pfs_expected=None): - dev.connect("dpp", key_mgmt="DPP", scan_freq="2412", +def run_dpp_pfs_sta(dev, pfs, fail=False, pfs_expected=None, sae=False): + key_mgmt = "DPP SAE" if sae else "DPP" + psk = "sae-password" if sae else None + dev.connect("dpp", key_mgmt=key_mgmt, scan_freq="2412", ieee80211w="2", dpp_pfs=str(pfs), dpp_csign=params1_csign, dpp_connector=params1_sta_connector, dpp_netaccesskey=params1_sta_netaccesskey, + psk=psk, wait_connect=not fail) if fail: for i in range(2): @@ -5467,6 +5473,28 @@ def test_dpp_pfs_connect_cmd(dev, apdev): run_dpp_pfs_sta(wpas, 1, pfs_expected=True) run_dpp_pfs_sta(wpas, 2, pfs_expected=False) +def test_dpp_pfs_connect_cmd_ap_2(dev, apdev): + """DPP PFS and cfg80211 connect command (PFS not allowed by AP)""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + check_dpp_capab(wpas) + hapd = start_dpp_pfs_ap(apdev[0], 2) + run_dpp_pfs_sta(wpas, 0, pfs_expected=False) + run_dpp_pfs_sta(wpas, 1, fail=True) + run_dpp_pfs_sta(wpas, 2, pfs_expected=False) + +def test_dpp_pfs_connect_cmd_ap_2_sae(dev, apdev): + """DPP PFS and cfg80211 connect command (PFS not allowed by AP; SAE enabled)""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + check_dpp_capab(wpas) + if "SAE" not in wpas.get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + hapd = start_dpp_pfs_ap(apdev[0], 2, sae=True) + run_dpp_pfs_sta(wpas, 0, pfs_expected=False, sae=True) + run_dpp_pfs_sta(wpas, 1, fail=True, sae=True) + run_dpp_pfs_sta(wpas, 2, pfs_expected=False, sae=True) + def test_dpp_pfs_ap_0_sta_ver1(dev, apdev): """DPP PFS AP default with version 1 STA""" check_dpp_capab(dev[0]) From 8175c2654b42f071962783efd37f20a8c4fa21d4 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Mon, 21 Sep 2020 13:12:11 +0530 Subject: [PATCH 0872/1105] Add test configuration attr to start/stop transmitting FD frames Define QCA vendor attribute QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX to dynamically start/stop transmitting FILS discovery frames. Signed-off-by: Veerendranath Jakkam --- src/common/qca-vendor.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 340f6117e..af6822020 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7644,6 +7644,16 @@ enum qca_wlan_vendor_attr_wifi_test_config { */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT = 43, + /* 8-bit unsigned value to configure the driver/firmware to start or + * stop transmitting FILS discovery frames. + * 0 - Stop transmitting FILS discovery frames + * 1 - Start transmitting FILS discovery frames + * This attribute is used to configure the testbed device. + * This attribute can be configured only in AP mode and the + * configuration is valid until AP restart. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX = 44, + /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX = From 13feeaa10432bd548c544477ab59f31ff96ebf82 Mon Sep 17 00:00:00 2001 From: Rajasekaran Kalidoss Date: Tue, 22 Sep 2020 10:52:42 +0530 Subject: [PATCH 0873/1105] Add a new status code to represent an already suspended TWT session The firmware sends a new status code to indicate an already suspended TWT session. Update the status code enum to represent this state. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index af6822020..d42d31fa4 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -8048,6 +8048,8 @@ enum qca_wlan_vendor_attr_twt_setup { * @QCA_WLAN_VENDOR_TWT_STATUS_DENIED: AP did not accept the request * @QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR: Adding TWT dialog failed due to an * unknown reason + * @QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED: TWT session already in + * suspend state */ enum qca_wlan_vendor_twt_status { QCA_WLAN_VENDOR_TWT_STATUS_OK = 0, @@ -8063,6 +8065,7 @@ enum qca_wlan_vendor_twt_status { QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE = 10, QCA_WLAN_VENDOR_TWT_STATUS_DENIED = 11, QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR = 12, + QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED = 13, }; /** From 04824147432f4d856d0e56e33f4c58c09a5b64bb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 30 Sep 2020 00:19:53 +0300 Subject: [PATCH 0874/1105] wlantest: Fix EAPOL-Key Key Data padding removal The case where a single 0xdd octet without any 0x00 octets is used as padding was addressed incorrectly and that ended up truncating one octet of the actual plaintext version of the Key Data value. Fix this by removing the unnecessary change to the p pointer before calculating the new length since p is already pointing to one past the last octet of the full plaintext. Signed-off-by: Jouni Malinen --- wlantest/rx_eapol.c | 1 - 1 file changed, 1 deletion(-) diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index 44388fdda..1e5d66735 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -725,7 +725,6 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, if (p && p > decrypted && p + 1 == decrypted + decrypted_len && *p == 0xdd) { /* Remove padding */ - p--; plain_len = p - decrypted; } From fa63284af5baa19309f03376c74e49e672537ab5 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Fri, 25 Sep 2020 21:15:46 +0530 Subject: [PATCH 0875/1105] Add additional roam triggers to qca_vendor_roam_triggers Introduce QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS that represents the triggers for which the scan scheme from enum qca_roam_scan_scheme has to be applied. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index d42d31fa4..41724876f 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -4086,6 +4086,18 @@ enum qca_roam_scan_scheme { * when BTM Request frame is received from the connected AP. * @QCA_ROAM_TRIGGER_REASON_BSS_LOAD: Set if the roam has to be triggered * when the channel utilization is goes above the configured threshold. + * @QCA_ROAM_TRIGGER_REASON_USER_TRIGGER: Set if the roam has to be triggered + * based on the request from the user (space). + * @QCA_ROAM_TRIGGER_REASON_DEAUTH: Set if the roam has to be triggered when + * device receives Deauthentication/Disassociation frame from connected AP. + * @QCA_ROAM_TRIGGER_REASON_IDLE: Set if the roam has to be triggered when the + * device is in idle state (no TX/RX) and suspend mode, if the current RSSI + * is determined to be a poor one. + * @QCA_ROAM_TRIGGER_REASON_TX_FAILURES: Set if the roam has to be triggered + * based on continuous TX Data frame failures to the connected AP. + * @QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN: Set if the roam has to be triggered + * based on the scan results obtained from an external scan (not triggered + * to aim roaming). * * Set the corresponding roam trigger reason bit to consider it for roam * trigger. @@ -4101,6 +4113,11 @@ enum qca_vendor_roam_triggers { QCA_ROAM_TRIGGER_REASON_DENSE = 1 << 5, QCA_ROAM_TRIGGER_REASON_BTM = 1 << 6, QCA_ROAM_TRIGGER_REASON_BSS_LOAD = 1 << 7, + QCA_ROAM_TRIGGER_REASON_USER_TRIGGER = 1 << 8, + QCA_ROAM_TRIGGER_REASON_DEAUTH = 1 << 9, + QCA_ROAM_TRIGGER_REASON_IDLE = 1 << 10, + QCA_ROAM_TRIGGER_REASON_TX_FAILURES = 1 << 11, + QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN = 1 << 12, }; /** @@ -4278,6 +4295,19 @@ enum qca_vendor_attr_roam_candidate_selection_criteria { * user defined reason code to be sent to the AP in response to AP's * request to trigger the roam if the roaming cannot be triggered. * Applies to all the scenarios of AP assisted roaming (e.g., BTM). + * + * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS: Unsigned 32-bit value. + * Carries a bitmap of the roam triggers specified in + * enum qca_vendor_roam_triggers. + * Represents the roam triggers for which the specific scan scheme from + * enum qca_roam_scan_scheme has to be applied. + * It's an optional attribute. If this attribute is not configured, but + * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is specified, the scan scheme + * specified through QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is applicable for + * all the roams. + * If both QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME and + * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS are not specified, the + * driver shall proceed with the default behavior. */ enum qca_vendor_attr_roam_control { QCA_ATTR_ROAM_CONTROL_ENABLE = 1, @@ -4292,6 +4322,7 @@ enum qca_vendor_attr_roam_control { QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD = 10, QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11, QCA_ATTR_ROAM_CONTROL_USER_REASON = 12, + QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS = 13, /* keep last */ QCA_ATTR_ROAM_CONTROL_AFTER_LAST, From e8a1e6a4a132dd099f5e10c8f99bb32e2dfdce0e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 30 Sep 2020 10:14:33 +0300 Subject: [PATCH 0876/1105] P2P: Fix a typo in a comment Signed-off-by: Jouni Malinen --- wpa_supplicant/p2p_supplicant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index e94bffe52..93dd93d34 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -522,7 +522,7 @@ static int wpas_p2p_disconnect_safely(struct wpa_supplicant *wpa_s, /* * The calling wpa_s instance is going to be removed. Do that * from an eloop callback to keep the instance available until - * the caller has returned. This my be needed, e.g., to provide + * the caller has returned. This may be needed, e.g., to provide * control interface responses on the per-interface socket. */ if (eloop_register_timeout(0, 0, run_wpas_p2p_disconnect, From ac882374a595ba31a04f374f227755c938a7b4c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 1 Oct 2020 09:35:58 +0300 Subject: [PATCH 0877/1105] SAE: Fix error path handling for SSWU crypto_bignum_init_set() might fail in case of memory allocation failures. These two cases within sswu() did not handle that properly, i.e., a memory allocation failure could have resulted in dereferencing a NULL pointer. Check the return value before proceeding to fix this. Fixes: aeb022f8e51e ("SAE: Implement hash-to-element PT/PWE crypto routines") Signed-off-by: Jouni Malinen --- src/common/sae.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/common/sae.c b/src/common/sae.c index 72b5f3fab..057e1ce3b 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -713,6 +713,8 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group, goto fail; const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin); x1 = crypto_bignum_init_set(bin, prime_len); + if (!x1) + goto fail; debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len); /* gx1 = x1^3 + a * x1 + b */ @@ -753,6 +755,8 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group, goto fail; const_time_select_bin(is_qr, bin1, bin2, prime_len, bin); v = crypto_bignum_init_set(bin, prime_len); + if (!v) + goto fail; debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len); /* x = CSEL(l, x1, x2) */ From 760d10cdea4d0c0e1a694e83b94b5dd0f71b7dc3 Mon Sep 17 00:00:00 2001 From: Sreeramya Soratkal Date: Tue, 18 Aug 2020 21:46:12 +0530 Subject: [PATCH 0878/1105] P2P: Include channels 149 to 161 for operating classes 128 and 130 With the configuration defined in the global_op_class array, the channels starting from 149 in the operating classes 128 and 130 were not considered for P2P channel setup due to the non-continuous incrementation of channel indexes. The other channels in these operating classes were considered. Handle the channels from 149 to 161 in the operating classes 128 and 130 for P2P channel setup by handling this jump in the channel number incrementation. Signed-off-by: Sreeramya Soratkal --- wpa_supplicant/p2p_supplicant.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 93dd93d34..e26e8051d 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3737,6 +3737,13 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, wpa_s->global->p2p_24ghz_social_channels = 1; for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { enum chan_allowed res; + + /* Check for non-continuous jump in channel index + * incrementation */ + if ((o->op_class == 128 || o->op_class == 130) && + ch < 149 && ch + o->inc > 149) + ch = 149; + res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw); if (res == ALLOWED) { if (reg == NULL) { From 57536a567821c2833ca8e64e313070054224b1a6 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 25 Sep 2020 18:09:00 +0530 Subject: [PATCH 0879/1105] P2P: Fix P2P interface remuval through wpa_supplicant_remove_iface() wpa_supplicant_remove_iface() removes the P2P management interface from the global interfaces list before calling wpa_supplicant_deinit_iface(). When wpas_p2p_group_remove() is called from wpa_supplicant_deinit_iface(), the P2P group created on the calling wpa_s was not getting cleared as the calling wpa_s is not in the list of global->ifaces. This results in the P2P management interface being removed without disconnecting the p2p_group created on it. This could result in an illegal access of freed memory, e.g., when a pending eloop task wpas_p2p_reconsider_moving_go() was triggered with the leftover ctx pointer to the removed P2P interface instance. Fix this by disconnecting the P2P group created on interface to be deinitialized before deinitializing the interface. Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/p2p_supplicant.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index e26e8051d..36fb05557 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -5870,6 +5870,8 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname) if (os_strcmp(ifname, "*") == 0) { struct wpa_supplicant *prev; + bool calling_wpa_s_group_removed = false; + wpa_s = global->ifaces; while (wpa_s) { prev = wpa_s; @@ -5877,9 +5879,23 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname) if (prev->p2p_group_interface != NOT_P2P_GROUP_INTERFACE || (prev->current_ssid && - prev->current_ssid->p2p_group)) + prev->current_ssid->p2p_group)) { wpas_p2p_disconnect_safely(prev, calling_wpa_s); + if (prev == calling_wpa_s) + calling_wpa_s_group_removed = true; + } } + + if (!calling_wpa_s_group_removed && + (calling_wpa_s->p2p_group_interface != + NOT_P2P_GROUP_INTERFACE || + (calling_wpa_s->current_ssid && + calling_wpa_s->current_ssid->p2p_group))) { + wpa_printf(MSG_DEBUG, "Remove calling_wpa_s P2P group"); + wpas_p2p_disconnect_safely(calling_wpa_s, + calling_wpa_s); + } + return 0; } From 43ef227e90b34aac9c1c363832fe93d46f32e221 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 1 Oct 2020 15:44:19 +0300 Subject: [PATCH 0880/1105] P2P: Make use wpas_p2p_reconsider_moving_go timeout gets canceled The per-interface P2P data freeing function did not cover this eloop timeout that could potentially have been registered. Explicitly cancel this timeout to make sure no references to freed memory can remain in such a case. Signed-off-by: Jouni Malinen --- wpa_supplicant/p2p_supplicant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 36fb05557..1fbe15a5b 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -4776,6 +4776,7 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL); wpas_p2p_remove_pending_group_interface(wpa_s); eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL); + eloop_cancel_timeout(wpas_p2p_reconsider_moving_go, wpa_s, NULL); wpas_p2p_listen_work_done(wpa_s); if (wpa_s->p2p_send_action_work) { os_free(wpa_s->p2p_send_action_work->ctx); From ce637df76c76f50504de29f1364af03749a8bba4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 1 Oct 2020 15:45:34 +0300 Subject: [PATCH 0881/1105] tests: P2P autonomous GO and interface being removed Signed-off-by: Jouni Malinen --- tests/hwsim/test_p2p_autogo.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/hwsim/test_p2p_autogo.py b/tests/hwsim/test_p2p_autogo.py index f0e861e2f..91d68eaf2 100644 --- a/tests/hwsim/test_p2p_autogo.py +++ b/tests/hwsim/test_p2p_autogo.py @@ -922,3 +922,15 @@ def run_autogo_interworking(dev): dev[0].remove_group() if '6b03110203' not in bss['ie']: raise Exception("Interworking element not seen") + +def test_autogo_remove_iface(dev): + """P2P autonomous GO and interface being removed""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5") + wpas.global_request("SET p2p_no_group_iface 1") + wpas.set("p2p_group_idle", "1") + autogo(wpas) + wpas.global_request("P2P_SET disallow_freq 5000") + time.sleep(0.1) + wpas.global_request("INTERFACE_REMOVE " + wpas.ifname) + time.sleep(1) From a7f55f7f68f1d4cd55f391caa1968f619870a2b4 Mon Sep 17 00:00:00 2001 From: Disha Das Date: Tue, 6 Oct 2020 17:37:01 +0530 Subject: [PATCH 0882/1105] WPS: Enable SA Query checks for WPS AP Initiate SA Query for a WPS+MFP AP. STA flag checks for MFP added for Association Request frames that use WPS IE without RSNE. This is needed to avoid giving an opportunity to skip the protection against disconnections when WPS is enabled. Signed-off-by: Disha Das --- src/ap/drv_callbacks.c | 59 +++++++++++++++++++++++++++--------------- src/ap/ieee802_11.c | 52 ++++++++++++++++++++++--------------- 2 files changed, 69 insertions(+), 42 deletions(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index a8b339f58..9af5445e2 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -105,6 +105,32 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd, #endif /* CONFIG_FILS */ +static bool check_sa_query_need(struct hostapd_data *hapd, struct sta_info *sta) +{ + if ((sta->flags & + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) != + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) + return false; + + if (!sta->sa_query_timed_out && sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + + if (!sta->sa_query_timed_out && (sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA Query timeout + * has not been reached. Reject the association attempt + * temporarily and start SA Query, if one is not pending. + */ + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + return true; + } + + return false; +} + + int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, const u8 *req_ies, size_t req_ies_len, int reassoc) { @@ -293,6 +319,17 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { struct wpabuf *wps; + if (check_sa_query_need(hapd, sta)) { + status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; + + p = hostapd_eid_assoc_comeback_time(hapd, sta, + p); + + hostapd_sta_assoc(hapd, addr, reassoc, status, + buf, p - buf); + return 0; + } + sta->flags |= WLAN_STA_WPS; wps = ieee802_11_vendor_ie_concat(ie, ielen, WPS_IE_VENDOR_TYPE); @@ -388,27 +425,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, goto fail; } - if ((sta->flags & - (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED) && - !sta->sa_query_timed_out && - sta->sa_query_count > 0) - ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & - (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED) && - !sta->sa_query_timed_out && - (sta->auth_alg != WLAN_AUTH_FT)) { - /* - * STA has already been associated with MFP and SA - * Query timeout has not been reached. Reject the - * association attempt temporarily and start SA Query, - * if one is not pending. - */ - - if (sta->sa_query_count == 0) - ap_sta_start_sa_query(hapd, sta); - + if (check_sa_query_need(hapd, sta)) { status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; p = hostapd_eid_assoc_comeback_time(hapd, sta, p); diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 568ecacb0..78c1b8c8c 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3152,6 +3152,34 @@ end: #endif /* CONFIG_OWE */ +static bool check_sa_query(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc) +{ + if ((sta->flags & + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) != + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) + return false; + + if (!sta->sa_query_timed_out && sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + + if (!sta->sa_query_timed_out && + (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA Query timeout + * has not been reached. Reject the association attempt + * temporarily and start SA Query, if one is not pending. + */ + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + return true; + } + + return false; +} + + static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, const u8 *ies, size_t ies_len, int reassoc) { @@ -3275,6 +3303,8 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->conf->wps_state && elems.wps_ie) { wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association " "Request - assume WPS is used"); + if (check_sa_query(hapd, sta, reassoc)) + return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; sta->flags |= WLAN_STA_WPS; wpabuf_free(sta->wps_ie); sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, @@ -3328,29 +3358,9 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, resp = wpa_res_to_status_code(res); if (resp != WLAN_STATUS_SUCCESS) return resp; - if ((sta->flags & - (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED) && - !sta->sa_query_timed_out && - sta->sa_query_count > 0) - ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & - (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED) && - !sta->sa_query_timed_out && - (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { - /* - * STA has already been associated with MFP and SA - * Query timeout has not been reached. Reject the - * association attempt temporarily and start SA Query, - * if one is not pending. - */ - - if (sta->sa_query_count == 0) - ap_sta_start_sa_query(hapd, sta); + if (check_sa_query(hapd, sta, reassoc)) return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; - } if (wpa_auth_uses_mfp(sta->wpa_sm)) sta->flags |= WLAN_STA_MFP; From de250a1984e4650656d9cd0ea4ddb668d4dcc2ed Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 6 Oct 2020 22:46:26 +0300 Subject: [PATCH 0883/1105] tests: WPA2-PSK AP with PMF association comeback (WPS) Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_pmf.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index e0a6225db..6c2a58ac4 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -279,6 +279,34 @@ def test_ap_pmf_assoc_comeback2(dev, apdev): dev[0].p2p_interface_addr()) < 1: raise Exception("AP did not use reassociation comeback request") +@remote_compatible +def test_ap_pmf_assoc_comeback_wps(dev, apdev): + """WPA2-PSK AP with PMF association comeback (WPS)""" + ssid = "assoc-comeback" + appin = "12345670" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["eap_server"] = "1" + params["wps_state"] = "2" + params["ap_pin"] = appin + hapd = hostapd.add_ap(apdev[0], params) + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + dev[0].connect(ssid, psk="12345678", ieee80211w="1", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412") + hapd.set("ext_mgmt_frame_handling", "1") + dev[0].request("DISCONNECT") + dev[0].wait_disconnected(timeout=10) + hapd.set("ext_mgmt_frame_handling", "0") + dev[0].wps_reg(apdev[0]['bssid'], appin) + if wt.get_sta_counter("assocresp_comeback", apdev[0]['bssid'], + dev[0].p2p_interface_addr()) < 1: + raise Exception("AP did not use association comeback request") + def test_ap_pmf_ap_dropping_sa(dev, apdev): """WPA2-PSK PMF AP dropping SA""" ssid = "pmf" From 5c6c0d569acac768c79fe0874d314462b96daf64 Mon Sep 17 00:00:00 2001 From: Disha Das Date: Fri, 11 Sep 2020 09:58:40 +0530 Subject: [PATCH 0884/1105] DPP: Fix GAS fragmentation for DPP Config Response from hostapd The Query Response Length field was missing from GAS Initial Response and GAS Comeback Response frames in the DPP specific code path from hostaps GAS server. This resulted in invalid frames being used when the DPP Config Response needed fragmentation. Fix this by adding the Query Response Length fields into these frames. Signed-off-by: Disha Das --- src/ap/gas_serv.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c index 9567e202a..90f15778b 100644 --- a/src/ap/gas_serv.c +++ b/src/ap/gas_serv.c @@ -1555,11 +1555,14 @@ void gas_serv_req_dpp_processing(struct hostapd_data *hapd, di->prot = prot; di->sd_resp = buf; di->sd_resp_pos = 0; + di->dpp = 1; tx_buf = gas_build_initial_resp( dialog_token, WLAN_STATUS_SUCCESS, - comeback_delay, 10); - if (tx_buf) + comeback_delay, 10 + 2); + if (tx_buf) { gas_serv_write_dpp_adv_proto(tx_buf); + wpabuf_put_le16(tx_buf, 0); + } } } else { wpa_printf(MSG_DEBUG, @@ -1782,9 +1785,10 @@ static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd, tx_buf = gas_build_comeback_resp(dialog_token, WLAN_STATUS_SUCCESS, dialog->sd_frag_id, more, 0, - 10 + frag_len); + 10 + 2 + frag_len); if (tx_buf) { gas_serv_write_dpp_adv_proto(tx_buf); + wpabuf_put_le16(tx_buf, frag_len); wpabuf_put_buf(tx_buf, buf); } } else From d049aeb0c611efdfe3c18338c8dc3003324c8217 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 6 Oct 2020 23:37:17 +0300 Subject: [PATCH 0885/1105] tests: DPP with hostapd as configurator requiring fragmentation Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 21847cb24..f54dbdbcb 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -2563,6 +2563,30 @@ def test_dpp_hostapd_configurator_responder(dev, apdev): wait_auth_success(hapd, dev[0], configurator=hapd, enrollee=dev[0], stop_initiator=True) +def test_dpp_hostapd_configurator_fragmentation(dev, apdev): + """DPP with hostapd as configurator/initiator requiring fragmentation""" + check_dpp_capab(dev[0]) + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured", + "channel": "1"}) + check_dpp_capab(hapd) + conf_id = hapd.dpp_configurator_add() + id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True) + uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + id1 = hapd.dpp_qr_code(uri0) + res = hapd.request("DPP_BOOTSTRAP_INFO %d" % id1) + if "FAIL" in res: + raise Exception("DPP_BOOTSTRAP_INFO failed") + if "type=QRCODE" not in res: + raise Exception("DPP_BOOTSTRAP_INFO did not report correct type") + if "mac_addr=" + dev[0].own_addr() not in res: + raise Exception("DPP_BOOTSTRAP_INFO did not report correct mac_addr") + dev[0].dpp_listen(2412) + conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' ' + hapd.set("dpp_config_obj_override", conf) + hapd.dpp_auth_init(peer=id1, configurator=conf_id, conf="sta-dpp") + wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0], + stop_responder=True) + def test_dpp_own_config(dev, apdev): """DPP configurator signing own connector""" try: From 8e5739c3ac31723d65444c9fbc7d29adc3dec974 Mon Sep 17 00:00:00 2001 From: Disha Das Date: Fri, 11 Sep 2020 10:13:52 +0530 Subject: [PATCH 0886/1105] DPP2: Check channel 6 validity before adding it to chirp channel list Check if the 2.4 GHz channel 6 is in the list of available channels advertised by the driver before adding in to the chirping frequency list. This fixes issues, e.g., with a 5 GHz only interface. Signed-off-by: Disha Das --- wpa_supplicant/dpp_supplicant.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 28404b8d7..023895072 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3449,6 +3449,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, struct hostapd_hw_modes *mode; int c; struct wpa_bss *bss; + bool chan6; if (!bi && !wpa_s->dpp_reconfig_ssid) return; @@ -3466,7 +3467,22 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, } /* Preferred chirping channels */ - int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437); + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, + HOSTAPD_MODE_IEEE80211G, 0); + chan6 = mode == NULL; + if (mode) { + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if ((chan->flag & HOSTAPD_CHAN_DISABLED) || + chan->freq != 2437) + continue; + chan6 = true; + break; + } + } + if (chan6) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437); mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, HOSTAPD_MODE_IEEE80211A, 0); From 88d3f43bd33723e47339df25b8d3a80e87e39fa9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 7 Oct 2020 01:04:48 +0300 Subject: [PATCH 0887/1105] DPP2: Replace OneAsymmetricKey version number (v2 to v1) DPP tech spec was modified to use v1(0) instead of v2(1) for the OneAsymmetricKey in the Configurator backup structure to match the description in RFC 5958 Section 2 which indicates v2 to be used when any items tagged as version 2 are included. No such items are actually included in this case, so v1 should be used instead. Change OneAsymmetricKey generation to use v1(0) instead of v2(1) and parsing to accept either version to be used. This is not backwards compatible with the earlier implementation which requires v2(1) when parsing the received value. Signed-off-by: Jouni Malinen --- src/common/dpp_backup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c index e12bc6d7c..67ca1a5d2 100644 --- a/src/common/dpp_backup.c +++ b/src/common/dpp_backup.c @@ -189,7 +189,7 @@ static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth) if (!key) goto fail; - asn1_put_integer(key, 1); /* version = v2(1) */ + asn1_put_integer(key, 0); /* version = v1(0) */ /* PrivateKeyAlgorithmIdentifier */ wpabuf_put_buf(key, alg); @@ -908,7 +908,7 @@ dpp_parse_one_asymmetric_key(const u8 *buf, size_t len) /* Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) */ if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) goto fail; - if (val != 1) { + if (val != 0 && val != 1) { wpa_printf(MSG_DEBUG, "DPP: Unsupported DPPAsymmetricKeyPackage version %d", val); From aa704020a3b8fd7ef101d4ff576de31d9ffd3ca6 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 1 Oct 2020 17:52:28 +0200 Subject: [PATCH 0888/1105] DBus: Update dont_quote[] with ignore_broadcast_ssid parameter ignore_broadcast_ssid is supported when using with the config file. But it generates an error if you try to set it via the DBus interface. Signed-off-by: Yegor Yefremov --- wpa_supplicant/dbus/dbus_new_handlers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index d1f9607c6..34abab752 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -139,6 +139,7 @@ static const char * const dont_quote[] = { "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", "bssid", "scan_freq", "freq_list", "scan_ssid", "bssid_hint", "bssid_blacklist", "bssid_whitelist", "group_mgmt", + "ignore_broadcast_ssid", #ifdef CONFIG_MESH "mesh_basic_rates", #endif /* CONFIG_MESH */ From a8f304228d8782e23d7ec38a2e3bd889c4aa9c59 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Fri, 2 Oct 2020 08:21:53 +0200 Subject: [PATCH 0889/1105] Document the missing ignore_broadcast_ssid network profile parameter Copy parameter description from hostapd.conf. Signed-off-by: Yegor Yefremov --- wpa_supplicant/wpa_supplicant.conf | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 125083414..c10dd73ea 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -843,6 +843,16 @@ fast_reauth=1 # bssid: BSSID (optional); if set, this network block is used only when # associating with the AP using the configured BSSID # +# ignore_broadcast_ssid: SSID broadcast behavior +# Send empty SSID in beacons and ignore probe request frames that do not +# specify full SSID, i.e., require stations to know SSID. +# default: disabled (0) +# 1 = send empty (length=0) SSID in beacon and ignore probe request for +# broadcast SSID +# 2 = clear SSID (ASCII 0), but keep the original length (this may be required +# with some clients that do not support empty SSID) and ignore probe +# requests for broadcast SSID +# # priority: priority group (integer) # By default, all networks will get same priority group (0). If some of the # networks are more desirable, this field can be used to change the order in From cf3d260c39a9efeb61f92e892e202fda7fa9a94b Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Wed, 16 Sep 2020 21:51:40 +0000 Subject: [PATCH 0890/1105] DPP2: Fix hostapd crash setting global configurator params on chirp RX When a Presence Announcement frame is received, a check is done to ensure an ongoing auth is not in progress (!hapd->dpp_auth). A new DPP auth is then initialized, however, when setting global configurator params for it, the hapd->dpp_auth pointer is used which was earlier confirmed as NULL, causing a crash in dpp_set_configurator params when the pointer is dereferenced. This only occurs when there are global DPP configurator params to be set and the peer has no overriding configurator params. If no global DPP configurator params exist, the call to dpp_set_configurator exits early and the problem is not observed. Fix by using the newly init'ed DPP auth structure for setting global DPP configurator params. Signed-off-by: Andrew Beltrano --- src/ap/dpp_hostapd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 15aa82b85..2a28239e1 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1249,8 +1249,8 @@ hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src, 0); if (!auth) return; - hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); - if (dpp_set_configurator(hapd->dpp_auth, + hostapd_dpp_set_testing_options(hapd, auth); + if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) { dpp_auth_deinit(auth); return; From 8b667bfa14d8e31b1e225bbe47aca987202ab9f2 Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Mon, 21 Sep 2020 13:48:32 +0000 Subject: [PATCH 0891/1105] DPP2: Presence Announcement notification Define a control event with bootstrap id, frame source, frequency, and chirp hash for receipt of Presence Announcement (chirp) frames. Signed-off-by: Andrew Beltrano --- src/common/dpp.c | 14 ++++++++++++++ src/common/dpp.h | 2 ++ src/common/wpa_ctrl.h | 1 + 3 files changed, 17 insertions(+) diff --git a/src/common/dpp.c b/src/common/dpp.c index 3922edb63..552d7626c 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -4317,6 +4317,7 @@ void dpp_global_deinit(struct dpp_global *dpp) #ifdef CONFIG_DPP2 + struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi) { struct wpabuf *msg; @@ -4333,4 +4334,17 @@ struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi) "DPP: Presence Announcement frame attributes", msg); return msg; } + + +void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src, + unsigned int freq, const u8 *hash) +{ + char hex[SHA256_MAC_LEN * 2 + 1]; + + wpa_snprintf_hex(hex, sizeof(hex), hash, SHA256_MAC_LEN); + wpa_msg(msg_ctx, MSG_INFO, + DPP_EVENT_CHIRP_RX "id=%d src=" MACSTR " freq=%u hash=%s", + id, MAC2STR(src), freq, hex); +} + #endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp.h b/src/common/dpp.h index 011098f03..a39e87ed5 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -686,6 +686,8 @@ int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, struct dpp_authentication *auth)); struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); +void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src, + unsigned int freq, const u8 *hash); struct dpp_global_config { void *cb_ctx; diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 4e42c890f..52888d730 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -202,6 +202,7 @@ extern "C" { #define DPP_EVENT_MUD_URL "DPP-MUD-URL " #define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT " #define DPP_EVENT_CSR "DPP-CSR " +#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX " /* MESH events */ #define MESH_GROUP_STARTED "MESH-GROUP-STARTED " From 980c4da413e97dbb653a579cafc251e262f65fd4 Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Mon, 21 Sep 2020 13:49:37 +0000 Subject: [PATCH 0892/1105] DPP2: Presence Announcement notification in AP Generate a control interface event upon receipt of DPP Presence Announcement frames. This allows external programs to instrument hostapd with bootstrapping information on-demand. Signed-off-by: Andrew Beltrano --- src/ap/dpp_hostapd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 2a28239e1..6772a8748 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -1228,6 +1228,9 @@ hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src, r_bootstrap, r_bootstrap_len); peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp, r_bootstrap); + dpp_notify_chirp_received(hapd->msg_ctx, + peer_bi ? (int) peer_bi->id : -1, + src, freq, r_bootstrap); if (!peer_bi) { if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, src, hdr, buf, len, freq, NULL, From 0e8d569d4735377abef5c4d676aee04759f458f6 Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Mon, 21 Sep 2020 13:50:31 +0000 Subject: [PATCH 0893/1105] DPP2: Presence Announcement notification in STA Generate a control interface event upon receipt of DPP Presence Announcement frames. This allows external programs to instrument wpa_supplicant with bootstrapping information on-demand. Signed-off-by: Andrew Beltrano --- wpa_supplicant/dpp_supplicant.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 023895072..1008207b2 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1978,6 +1978,8 @@ wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src, wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", r_bootstrap, r_bootstrap_len); peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap); + dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src, + freq, r_bootstrap); if (!peer_bi) { wpa_printf(MSG_DEBUG, "DPP: No matching bootstrapping information found"); From fe27c464fd4badc4d04ee26cfbca537e485c1cba Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 7 Oct 2020 21:31:46 +0300 Subject: [PATCH 0894/1105] tests: DPP-CHIRP-RX reception Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index f54dbdbcb..2d343d36e 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5329,6 +5329,13 @@ def test_dpp_chirp(dev, apdev): dpp_cc = True if chan1 != 5 or chan6 != 5 or chan11 != 1: raise Exception("Unexpected number of presence announcements sent: %d %d %d" % (chan1, chan6, chan11)) + ev = hapd.wait_event(["DPP-CHIRP-RX"], timeout=1) + if ev is None: + raise Exception("No chirp received on the AP") + if "freq=2462" not in ev: + raise Exception("Chirp reception reported on unexpected channel: " + ev) + if "src=" + dev[0].own_addr() not in ev: + raise Exception("Unexpected chirp source reported: " + ev) @long_duration_test def test_dpp_chirp_listen(dev, apdev): From d48a3a676821f16b6a4acd0474fcda74e7fb13d6 Mon Sep 17 00:00:00 2001 From: Shaakir Mohamed Date: Fri, 2 Oct 2020 17:14:21 -0700 Subject: [PATCH 0895/1105] FT: Modify status code in FT Reassoc frame for invalid OCI channel info Modify status code in FT Reassociation Response frame from WLAN_STATUS_UNSPECIFIED_FAILURE to WLAN_STATUS_INVALID_FTE when replying to an invalid OCI channel info (subelement of FTE) in FT Reassociation Request frame. Signed-off-by: Shaakir Mohamed --- src/ap/wpa_auth_ft.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 5cd7037e9..94a688ed9 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -3527,7 +3527,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, OCV_FAILURE "addr=" MACSTR " frame=ft-reassoc-req error=%s", MAC2STR(sm->addr), ocv_errorstr); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + return WLAN_STATUS_INVALID_FTIE; } } #endif /* CONFIG_OCV */ From debf3e21658adf7da74f2b128dc611557bd6224f Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 7 Oct 2020 12:51:58 +0530 Subject: [PATCH 0896/1105] OCV: Work around for misbehaving STAs that indicate OCVC=1 without OCI Some legacy stations copy previously reserved RSN capability bits, including OCVC, in (Re)Association Request frames from the AP's RSNE but do not indicate MFP capability and/or do not send OCI in RSN handshakes. This is causing connection failures with such erroneous STAs. To improve interoperability with such legacy STAs allow a workaround OCV mode to be enabled to ignore OCVC=1 from the STA if it does not follow OCV requirements in the first protected exchange. This covers cases where a STA claims to have OCV capability, but it does not negotiate use of management frame protection or does not include OCI in EAPOL Key msg 2/4, FT Reassociation Request frame, or FILS (Re)Association Reqest. The previous behavior with ocv=1 is maintained, i.e., misbehaving STAs are not allowed to connect. When the new workaround mode is enabled with ocv=2, the AP considers STA as OCV capable on below criteria - STA indicates both OCV and MFP capability - STA sends OCI during connection attempt in a protected frame Enabling this workaround mode reduced OCV protection to some extend since it allows misbehavior to go through. As such, this should be enabled only if interoperability with misbehaving STAs is needed. Signed-off-by: Veerendranath Jakkam --- hostapd/hostapd.conf | 13 +++++++++++++ src/ap/ieee802_11.c | 13 ++++++++++--- src/ap/wpa_auth.c | 12 +++++++++--- src/ap/wpa_auth_ft.c | 12 +++++++++--- src/ap/wpa_auth_i.h | 3 ++- src/ap/wpa_auth_ie.c | 22 +++++++++++++++++----- 6 files changed, 60 insertions(+), 15 deletions(-) diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 25b4e4927..29717d2c6 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1732,6 +1732,19 @@ own_ip_addr=127.0.0.1 # Enabling this automatically also enables ieee80211w, if not yet enabled. # 0 = disabled (default) # 1 = enabled +# 2 = enabled in workaround mode - Allow STA that claims OCV capability to +# connect even if the STA doesn't send OCI or negotiate PMF. This +# workaround is to improve interoperability with legacy STAs which are +# wrongly copying reserved bits of RSN capabilities from the AP's +# RSNE into (Re)Association Request frames. When this configuration is +# enabled, the AP considers STA is OCV capable only when the STA indicates +# MFP capability in (Re)Association Request frames and sends OCI in +# EAPOL-Key msg 2/4/FT Reassociation Request frame/FILS (Re)Association +# Request frame; otherwise, the AP disables OCV for the current connection +# with the STA. Enabling this workaround mode reduced OCV protection to +# some extend since it allows misbehavior to go through. As such, this +# should be enabled only if interoperability with misbehaving STAs is +# needed. #ocv=1 # disable_pmksa_caching: Disable PMKSA caching diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 78c1b8c8c..a1a27f102 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3561,6 +3561,7 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, struct wpa_channel_info ci; int tx_chanwidth; int tx_seg1_idx; + enum oci_verify_result res; if (hostapd_drv_channel_info(hapd, &ci) != 0) { wpa_printf(MSG_WARNING, @@ -3574,9 +3575,15 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, &tx_seg1_idx) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; - if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != - OCI_SUCCESS) { + res = ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, + tx_chanwidth, tx_seg1_idx); + if (wpa_auth_uses_ocv(sta->wpa_sm) == 2 && + res == OCI_NOT_FOUND) { + /* Work around misbehaving STAs */ + wpa_printf(MSG_INFO, + "FILS: Disable OCV with a STA that does not send OCI"); + wpa_auth_set_ocv(sta->wpa_sm, 0); + } else if (res != OCI_SUCCESS) { wpa_printf(MSG_WARNING, "FILS: OCV failed: %s", ocv_errorstr); wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index a5b1953f6..9d74bfcd7 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3037,6 +3037,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) struct wpa_channel_info ci; int tx_chanwidth; int tx_seg1_idx; + enum oci_verify_result res; if (wpa_channel_info(wpa_auth, &ci) != 0) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, @@ -3050,9 +3051,14 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) &tx_seg1_idx) < 0) return; - if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != - OCI_SUCCESS) { + res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, + tx_chanwidth, tx_seg1_idx); + if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) { + /* Work around misbehaving STAs */ + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "Disable OCV with a STA that does not send OCI"); + wpa_auth_set_ocv(sm, 0); + } else if (res != OCI_SUCCESS) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, "OCV failed: %s", ocv_errorstr); if (wpa_auth->conf.msg_ctx) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 94a688ed9..5aa363eca 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -3505,6 +3505,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, struct wpa_channel_info ci; int tx_chanwidth; int tx_seg1_idx; + enum oci_verify_result res; if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { wpa_printf(MSG_WARNING, @@ -3518,9 +3519,14 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, &tx_seg1_idx) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; - if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != - OCI_SUCCESS) { + res = ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, + tx_chanwidth, tx_seg1_idx); + if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) { + /* Work around misbehaving STAs */ + wpa_printf(MSG_INFO, + "Disable OCV with a STA that does not send OCI"); + wpa_auth_set_ocv(sm, 0); + } else if (res != OCI_SUCCESS) { wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); if (sm->wpa_auth->conf.msg_ctx) wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index ba08ac257..a6dc1a591 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -95,8 +95,9 @@ struct wpa_state_machine { #endif /* CONFIG_IEEE80211R_AP */ unsigned int is_wnmsleep:1; unsigned int pmkid_set:1; + #ifdef CONFIG_OCV - unsigned int ocv_enabled:1; + int ocv_enabled; #endif /* CONFIG_OCV */ u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 3a16997cf..3704fc05e 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -810,12 +810,24 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_OCV if (wpa_auth->conf.ocv && (data.capabilities & WPA_CAPABILITY_OCVC) && !(data.capabilities & WPA_CAPABILITY_MFPC)) { - wpa_printf(MSG_DEBUG, - "Management frame protection required with OCV, but client did not enable it"); - return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + /* Some legacy MFP incapable STAs wrongly copy OCVC bit from + * AP RSN capabilities. To improve interoperability with such + * legacy STAs allow connection without enabling OCV when the + * workaround mode (ocv=2) is enabled. + */ + if (wpa_auth->conf.ocv == 2) { + wpa_printf(MSG_DEBUG, + "Allow connecting MFP incapable and OCV capable STA without enabling OCV"); + wpa_auth_set_ocv(sm, 0); + } else { + wpa_printf(MSG_DEBUG, + "Management frame protection required with OCV, but client did not enable it"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } + } else { + wpa_auth_set_ocv(sm, (data.capabilities & WPA_CAPABILITY_OCVC) ? + wpa_auth->conf.ocv : 0); } - wpa_auth_set_ocv(sm, wpa_auth->conf.ocv && - (data.capabilities & WPA_CAPABILITY_OCVC)); #endif /* CONFIG_OCV */ if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || From fd9fe8bc12907b31dabce4e82551dfb0e8622f44 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Oct 2020 23:07:43 +0300 Subject: [PATCH 0897/1105] tests: OCV and missing PMF or OCI Signed-off-by: Jouni Malinen --- tests/hwsim/test_ocv.py | 73 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py index fc939ff33..802e67887 100644 --- a/tests/hwsim/test_ocv.py +++ b/tests/hwsim/test_ocv.py @@ -1040,3 +1040,76 @@ def test_wpa2_ocv_ap_override_saquery_resp(dev, apdev): if "OK" not in dev[0].request("UNPROT_DEAUTH"): raise Exception("Triggering SA Query from the STA failed") check_ocv_failure(dev[0], "SA Query Response", "saqueryresp", bssid) + +@remote_compatible +def test_wpa2_ocv_no_pmf(dev, apdev): + """OCV on 2.4 GHz and no PMF on STA""" + params = {"channel": "1", + "ieee80211w": "1", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + ie = "301a0100000fac040100000fac040100000fac0200400000000fac06" + if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie): + raise Exception("Could not set TEST_ASSOC_IE") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0", + ieee80211w="0", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-ASSOC-REJECT"], + timeout=10) + dev[0].request("DISCONNECT") + if ev is None: + raise Exception("No connection result seen") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + if "status_code=31" not in ev: + raise Exception("Unexpected status code: " + ev) + +@remote_compatible +def test_wpa2_ocv_no_pmf_workaround(dev, apdev): + """OCV on 2.4 GHz and no PMF on STA with workaround""" + params = {"channel": "1", + "ieee80211w": "1", + "ocv": "2"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + ie = "301a0100000fac040100000fac040100000fac0200400000000fac06" + if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie): + raise Exception("Could not set TEST_ASSOC_IE") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0", + ieee80211w="0") + +@remote_compatible +def test_wpa2_ocv_no_oci(dev, apdev): + """OCV on 2.4 GHz and no OCI from STA""" + params = {"channel": "1", + "ieee80211w": "1", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + ie = "301a0100000fac040100000fac040100000fac0280400000000fac06" + if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie): + raise Exception("Could not set TEST_ASSOC_IE") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0", + ieee80211w="1", wait_connect=False) + ev = hapd.wait_event(["OCV-FAILURE"], timeout=10) + if ev is None: + raise Exception("No OCV failure reported") + if "frame=eapol-key-m2 error=did not receive mandatory OCI" not in ev: + raise Exception("Unexpected error: " + ev) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "WPA: 4-Way Handshake failed"], timeout=10) + dev[0].request("DISCONNECT") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + if ev is None: + raise Exception("4-way handshake failure not reported") + +@remote_compatible +def test_wpa2_ocv_no_oci_workaround(dev, apdev): + """OCV on 2.4 GHz and no OCI from STA with workaround""" + params = {"channel": "1", + "ieee80211w": "1", + "ocv": "2"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + ie = "301a0100000fac040100000fac040100000fac0280400000000fac06" + if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie): + raise Exception("Could not set TEST_ASSOC_IE") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0", + ieee80211w="1") From 14318ccff5665641ffc6ae550bdb491bbd87b6c1 Mon Sep 17 00:00:00 2001 From: Sreeramya Soratkal Date: Thu, 8 Oct 2020 17:35:43 +0530 Subject: [PATCH 0898/1105] P2P: Add configuration support to disable P2P in 6 GHz band Add a new configuration parameter p2p_6ghz_disable=1 to disable P2P operation in the 6 GHz band. This avoids additional delays caused by scanning 6 GHz channels in p2p_find and p2p_join operations in the cases where user doesn't want P2P connection in the 6 GHz band. Signed-off-by: Sreeramya Soratkal --- wpa_supplicant/config.c | 1 + wpa_supplicant/config.h | 2 ++ wpa_supplicant/config_file.c | 4 +++ wpa_supplicant/p2p_supplicant.c | 64 +++++++++++++++++++++++++++++++-- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 0b4a66ad7..154687d30 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4998,6 +4998,7 @@ static const struct global_parse_data global_fields[] = { { INT(p2p_device_random_mac_addr), 0 }, { FUNC(p2p_device_persistent_mac_addr), 0 }, { INT(p2p_interface_random_mac_addr), 0 }, + { INT(p2p_6ghz_disable), 0 }, #endif /* CONFIG_P2P */ { FUNC(country), CFG_CHANGED_COUNTRY }, { INT(bss_max_count), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index a385da528..3c38e1e57 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -779,6 +779,8 @@ struct wpa_config { int p2p_ignore_shared_freq; int p2p_optimize_listen_chan; + int p2p_6ghz_disable; + struct wpabuf *wps_vendor_ext_m1; #define MAX_WPS_VENDOR_EXT 10 diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 1ca254813..da3b8a958 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1333,6 +1333,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->p2p_go_freq_change_policy != DEFAULT_P2P_GO_FREQ_MOVE) fprintf(f, "p2p_go_freq_change_policy=%u\n", config->p2p_go_freq_change_policy); + + if (config->p2p_6ghz_disable) + fprintf(f, "p2p_6ghz_disable=%d\n", config->p2p_6ghz_disable); + if (WPA_GET_BE32(config->ip_addr_go)) fprintf(f, "ip_addr_go=%u.%u.%u.%u\n", config->ip_addr_go[0], config->ip_addr_go[1], diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 1fbe15a5b..479fa2fad 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -291,6 +291,41 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, } +static int wpas_p2p_add_scan_freq_list(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode band, + struct wpa_driver_scan_params *params) +{ + struct hostapd_hw_modes *mode; + int num_chans = 0; + int *freqs, i; + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, 0); + if (!mode) + return -1; + + if (params->freqs) { + while (params->freqs[num_chans]) + num_chans++; + } + + freqs = os_realloc(params->freqs, + (num_chans + mode->num_channels + 1) * sizeof(int)); + if (!freqs) + return -1; + + params->freqs = freqs; + + for (i = 0; i < mode->num_channels; i++) { + if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) + continue; + params->freqs[num_chans++] = mode->channels[i].freq; + } + params->freqs[num_chans] = 0; + + return 0; +} + + static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit) { struct wpa_supplicant *wpa_s = work->wpa_s; @@ -312,6 +347,15 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit) "Request driver to clear scan cache due to local BSS flush"); params->only_new_results = 1; } + + if (wpa_s->conf->p2p_6ghz_disable && !params->freqs) { + wpa_printf(MSG_DEBUG, + "P2P: 6 GHz disabled - update the scan frequency list"); + wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211G, + params); + wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211A, + params); + } ret = wpa_drv_scan(wpa_s, params); if (ret == 0) wpa_s->curr_scan_cookie = params->scan_cookie; @@ -3726,7 +3770,9 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, u8 ch; struct p2p_reg_class *reg = NULL, *cli_reg = NULL; - if (o->p2p == NO_P2P_SUPP) + if (o->p2p == NO_P2P_SUPP || + (is_6ghz_op_class(o->op_class) && + wpa_s->conf->p2p_6ghz_disable)) continue; mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode, @@ -3804,7 +3850,9 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s, const struct oper_class_map *o = &global_op_class[op]; u8 ch; - if (o->p2p == NO_P2P_SUPP) + if (o->p2p == NO_P2P_SUPP || + (is_6ghz_op_class(o->op_class) && + wpa_s->conf->p2p_6ghz_disable)) continue; for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { @@ -5275,6 +5323,13 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, if (freq > 0) { freqs[0] = freq; params.freqs = freqs; + } else if (wpa_s->conf->p2p_6ghz_disable) { + wpa_printf(MSG_DEBUG, + "P2P: 6 GHz disabled - update the scan frequency list"); + wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211G, + ¶ms); + wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211A, + ¶ms); } ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); @@ -5305,6 +5360,8 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, * the new scan results become available. */ ret = wpa_drv_scan(wpa_s, ¶ms); + if (wpa_s->conf->p2p_6ghz_disable && params.freqs != freqs) + os_free(params.freqs); if (!ret) { os_get_reltime(&wpa_s->scan_trigger_time); wpa_s->scan_res_handler = wpas_p2p_scan_res_join; @@ -5645,6 +5702,9 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, return -1; } + if (is_6ghz_freq(freq) && wpa_s->conf->p2p_6ghz_disable) + return -2; + os_free(wpa_s->global->add_psk); wpa_s->global->add_psk = NULL; From e7b27637a5f669ef8b29525334eeb253ebf2daed Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 8 Oct 2020 23:29:50 +0300 Subject: [PATCH 0899/1105] tests: P2P with 6 GHz disabled Signed-off-by: Jouni Malinen --- tests/hwsim/test_p2p_channel.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/hwsim/test_p2p_channel.py b/tests/hwsim/test_p2p_channel.py index ad1d712d6..87a1a24a7 100644 --- a/tests/hwsim/test_p2p_channel.py +++ b/tests/hwsim/test_p2p_channel.py @@ -1366,3 +1366,15 @@ def test_p2p_channel_drv_pref_autogo(dev): res_go = autogo(dev[0]) if res_go['freq'] != "2417": raise Exception("Unexpected operating frequency: " + res_go['freq']) + +def test_p2p_channel_disable_6ghz(dev): + """P2P with 6 GHz disabled""" + try: + dev[0].global_request("SET p2p_6ghz_disable 1") + dev[1].p2p_listen() + dev[0].discover_peer(dev[1].p2p_dev_addr(), social=False) + + autogo(dev[1]) + connect_cli(dev[1], dev[0]) + finally: + dev[0].global_request("SET p2p_6ghz_disable 0") From ac6595f2816bc021ab4a0c7a215f0d1c559f8026 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:26:52 +0200 Subject: [PATCH 0900/1105] tests: remote: Sort tests correctly Problem appeared after introducing python3 support. Signed-off-by: Janusz Dziedzic --- tests/remote/run-tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py index 95c8ab65d..e26e3483a 100755 --- a/tests/remote/run-tests.py +++ b/tests/remote/run-tests.py @@ -231,7 +231,7 @@ def main(): # sort the list test_names.sort() - tests.sort() + tests.sort(key=lambda t: t.__name__) # print help if requested_tests[0] == "help" and len(requested_hwsim_tests) == 0: From fed855d5dd01bb92d651b91f4f9fb49b0c4d66dd Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:26:53 +0200 Subject: [PATCH 0901/1105] tests: remote host stderr workaround In case we are using ssh MUX (which speed up a lot test execution) with remotehost we could hit cases where ssh will hang up. This depends on different ssh versions and remotehost implementation. stderr as a tmpfile fixes this problem. Signed-off-by: Janusz Dziedzic --- tests/hwsim/remotehost.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py index 8e121538a..b87b58936 100644 --- a/tests/hwsim/remotehost.py +++ b/tests/hwsim/remotehost.py @@ -7,6 +7,7 @@ import logging import subprocess import threading +import tempfile logger = logging.getLogger() @@ -17,12 +18,15 @@ def remote_compatible(func): def execute_thread(command, reply): cmd = ' '.join(command) logger.debug("thread run: " + cmd) + err = tempfile.TemporaryFile() try: status = 0 - buf = subprocess.check_output(command, stderr=subprocess.STDOUT).decode() + buf = subprocess.check_output(command, stderr=err).decode() except subprocess.CalledProcessError as e: status = e.returncode - buf = e.output + err.seek(0) + buf = err.read() + err.close() logger.debug("thread cmd: " + cmd) logger.debug("thread exit status: " + str(status)) @@ -46,12 +50,15 @@ class Host(): def local_execute(self, command): logger.debug("execute: " + str(command)) + err = tempfile.TemporaryFile() try: status = 0 - buf = subprocess.check_output(command, stderr=subprocess.STDOUT) + buf = subprocess.check_output(command, stderr=err) except subprocess.CalledProcessError as e: status = e.returncode - buf = e.output + err.seek(0) + buf = err.read() + err.close() logger.debug("status: " + str(status)) logger.debug("buf: " + str(buf)) @@ -64,12 +71,15 @@ class Host(): cmd = ["ssh", self.user + "@" + self.host, ' '.join(command)] _cmd = self.name + " execute: " + ' '.join(cmd) logger.debug(_cmd) + err = tempfile.TemporaryFile() try: status = 0 - buf = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + buf = subprocess.check_output(cmd, stderr=err) except subprocess.CalledProcessError as e: status = e.returncode - buf = e.output + err.seek(0) + buf = err.read() + err.close() logger.debug(self.name + " status: " + str(status)) logger.debug(self.name + " buf: " + str(buf)) From 14d28a655a214c2040a523148e531d170a34015b Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:26:54 +0200 Subject: [PATCH 0902/1105] tests: remotehost add execute_stop() Before we have to kill an application we start in the thread - in most cases using killall and sometimes kill other applicantions, e.g., tcpdump, iper, iperf3, tshark. With this patch we are able to stop/kill a single application/thread instead, based on the pid file. Signed-off-by: Janusz Dziedzic --- tests/hwsim/remotehost.py | 60 +++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py index b87b58936..a1ef1f34b 100644 --- a/tests/hwsim/remotehost.py +++ b/tests/hwsim/remotehost.py @@ -8,6 +8,7 @@ import logging import subprocess import threading import tempfile +import os logger = logging.getLogger() @@ -34,6 +35,17 @@ def execute_thread(command, reply): reply.append(status) reply.append(buf) +def gen_reaper_file(conf): + fd, filename = tempfile.mkstemp(dir='/tmp', prefix=conf + '-') + f = os.fdopen(fd, 'w') + + f.write("#!/bin/sh\n") + f.write("name=\"$(basename $0)\"\n") + f.write("echo $$ > /tmp/$name.pid\n") + f.write("exec \"$@\"\n"); + + return filename; + class Host(): def __init__(self, host=None, ifname=None, port=None, name="", user="root"): self.host = host @@ -86,17 +98,55 @@ class Host(): return status, buf.decode() # async execute - def execute_run(self, command, res): - if self.host is None: - cmd = command + def execute_run(self, command, res, use_reaper=True): + if use_reaper: + filename = gen_reaper_file("reaper") + self.send_file(filename, filename) + self.execute(["chmod", "755", filename]) + _command = [filename] + command else: - cmd = ["ssh", self.user + "@" + self.host, ' '.join(command)] + filename = "" + _command = command + + if self.host is None: + cmd = _command + else: + cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)] _cmd = self.name + " execute_run: " + ' '.join(cmd) logger.debug(_cmd) - t = threading.Thread(target=execute_thread, args=(cmd, res)) + t = threading.Thread(target=execute_thread, name=filename, args=(cmd, res)) t.start() return t + def execute_stop(self, t): + if t.name.find("reaper") == -1: + raise Exception("use_reaper required") + + pid_file = t.name + ".pid" + + if t.isAlive(): + cmd = ["kill `cat " + pid_file + "`"] + self.execute(cmd) + + # try again + self.wait_execute_complete(t, 5) + if t.isAlive(): + cmd = ["kill `cat " + pid_file + "`"] + self.execute(cmd) + + # try with -9 + self.wait_execute_complete(t, 5) + if t.isAlive(): + cmd = ["kill -9 `cat " + pid_file + "`"] + self.execute(cmd) + + self.wait_execute_complete(t, 5) + if t.isAlive(): + raise Exception("thread still alive") + + self.execute(["rm", pid_file]) + self.execute(["rm", t.name]) + def wait_execute_complete(self, t, wait=None): if wait == None: wait_str = "infinite" From adf6cfb0ab6f33de504dead51004afa3baf5493a Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:26:55 +0200 Subject: [PATCH 0903/1105] tests: remote: monitor use execute_stop() Stop the single thread instead of killing all monitor apps. Signed-off-by: Janusz Dziedzic --- tests/remote/monitor.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/remote/monitor.py b/tests/remote/monitor.py index 47b5e3bbd..96dbc6564 100644 --- a/tests/remote/monitor.py +++ b/tests/remote/monitor.py @@ -107,10 +107,7 @@ def stop(host): if host.thread is None: return - host.execute(["killall", "-s", "INT", "tshark"]) - host.wait_execute_complete(host.thread, 5) - if host.thread.isAlive(): - raise Exception("tshark still alive") + host.execute_stop(host.thread) host.thread = None # Add monitor to existing interface From 925dea791a4e066ca643a6c9d5e13adff90c5de2 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:26:56 +0200 Subject: [PATCH 0904/1105] tests: remote: Stop wpa_supplicant/hostapd using pidfile Instead of killall, use pidfile. Signed-off-by: Janusz Dziedzic --- tests/remote/rutils.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/remote/rutils.py b/tests/remote/rutils.py index 0acef42d1..e80901b50 100644 --- a/tests/remote/rutils.py +++ b/tests/remote/rutils.py @@ -117,7 +117,8 @@ def run_hostapd(host, setup_params): if log_file: host.add_log(log_file) - status, buf = host.execute([setup_params['hostapd'], "-B", "-ddt", "-g", "udp:" + host.port, log]) + pidfile = setup_params['log_dir'] + "hostapd_" + host.ifname + "_" + setup_params['tc_name'] + ".pid" + status, buf = host.execute([setup_params['hostapd'], "-B", "-ddt", "-g", "udp:" + host.port, "-P", pidfile, log]) if status != 0: raise Exception("Could not run hostapd: " + buf) @@ -134,15 +135,18 @@ def run_wpasupplicant(host, setup_params): if log_file: host.add_log(log_file) - status, buf = host.execute([setup_params['wpa_supplicant'], "-B", "-ddt", "-g", "udp:" + host.port, log]) + pidfile = setup_params['log_dir'] + "wpa_supplicant_" + host.ifname + "_" + setup_params['tc_name'] + ".pid" + status, buf = host.execute([setup_params['wpa_supplicant'], "-B", "-ddt", "-g", "udp:" + host.port, "-P", pidfile, log]) if status != 0: raise Exception("Could not run wpa_supplicant: " + buf) def kill_wpasupplicant(host, setup_params): - host.execute(['killall', setup_params['wpa_supplicant']]) + pidfile = setup_params['log_dir'] + "wpa_supplicant_" + host.ifname + "_" + setup_params['tc_name'] + ".pid" + host.execute(["kill `cat " + pidfile + "`"]) def kill_hostapd(host, setup_params): - host.execute(['killall', setup_params['hostapd']]) + pidfile = setup_params['log_dir'] + "hostapd_" + host.ifname + "_" + setup_params['tc_name'] + ".pid" + host.execute(["kill `cat " + pidfile + "`"]) def get_ap_params(channel="1", bw="HT20", country="US", security="open", ht_capab=None, vht_capab=None): ssid = "test_" + channel + "_" + security + "_" + bw From 777afa9f075bbcd51d3201dc8f5c7fd49082b6f2 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:26:57 +0200 Subject: [PATCH 0905/1105] tests: remote: Unblock rfkill on monitor Unblock wifi rfkill before setup/run monitor. Signed-off-by: Janusz Dziedzic --- tests/remote/monitor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/remote/monitor.py b/tests/remote/monitor.py index 96dbc6564..a97eaf928 100644 --- a/tests/remote/monitor.py +++ b/tests/remote/monitor.py @@ -63,6 +63,7 @@ def setup(host, monitor_params): logger.debug(traceback.format_exc()) break host.execute(["ifconfig", iface, " down"]) + host.execute(["rfkill", "unblock", "wifi"]) host.execute(["iw", iface, "set type monitor"]) host.execute(["ifconfig", iface, "up"]) status, buf = host.execute(["iw", iface, "set", "freq", param['freq'], From 8456b9e7db3766e38de9a0c6174cdc337abdfabe Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:26:58 +0200 Subject: [PATCH 0906/1105] tests: remote: Allow passing of parameters with devname Allow parameters to be passed together with the device name. For example, -m mon1:1,20,1,0 Signed-off-by: Janusz Dziedzic --- tests/remote/config.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/remote/config.py b/tests/remote/config.py index 5a6b728ac..1ac362ead 100644 --- a/tests/remote/config.py +++ b/tests/remote/config.py @@ -69,6 +69,8 @@ def get_devices(filename="cfg.py"): def get_device(devices, name=None, flags=None, lock=False): if name is None and flags is None: raise Exception("Failed to get device") + word = name.split(":") + name = word[0] for device in devices: if device['name'] == name: return device From c203897a88c0c7ee0e616abd25f3a6cd415dd2a4 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:26:59 +0200 Subject: [PATCH 0907/1105] tests: remote: Allow passing of parameters with monitor interface This is mainly for standalone monitor in case we know and would like to setup specific monitor configuration. -m monitor:,, , :... For example: -m monitor:1,40,3,0 -m e4300:1,40,3,0:11,40,9,0 This also supports monitor with multiple interfaces (one pcap). Signed-off-by: Janusz Dziedzic --- tests/hwsim/remotehost.py | 1 + tests/remote/monitor.py | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py index a1ef1f34b..dec1ad5a8 100644 --- a/tests/hwsim/remotehost.py +++ b/tests/hwsim/remotehost.py @@ -57,6 +57,7 @@ class Host(): self.ifname = ifname self.port = port self.dev = None + self.monitor_params = [] if self.name == "" and host != None: self.name = host diff --git a/tests/remote/monitor.py b/tests/remote/monitor.py index a97eaf928..5bd801c61 100644 --- a/tests/remote/monitor.py +++ b/tests/remote/monitor.py @@ -26,7 +26,8 @@ def create(devices, setup_params, refs, duts, monitors): mons.append(monitor) for mon in mons: - dev = config.get_device(devices, mon) + word = mon.split(":") + dev = config.get_device(devices, word[0]) if dev is None: continue @@ -35,6 +36,15 @@ def create(devices, setup_params, refs, duts, monitors): port=dev['port'], name=dev['name']) + for iface_param in word[1:]: + params = iface_param.split(",") + if len(params) > 3: + monitor_param = { "freq" : rutils.c2f(params[0]), + "bw" : params[1], + "center_freq1" : rutils.c2f(params[2]), + "center_freq2" : rutils.c2f(params[3]) } + host.monitor_params.append(monitor_param) + try: host.execute(["iw", "reg", "set", setup_params['country']]) rutils.setup_hw_host(host, setup_params, True) @@ -49,11 +59,15 @@ def destroy(devices, hosts): stop(host) for monitor in host.monitors: host.execute(["ifconfig", monitor, "down"]) + host.monitor_params = [] -def setup(host, monitor_params): +def setup(host, monitor_params=None): if host is None: return + if monitor_params == None: + monitor_params = host.monitor_params + ifaces = re.split('; | |, ', host.ifname) count = 0 for param in monitor_params: From 48e4680daec455a3b1ff0bbf37f392348ee5df2d Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 26 Sep 2020 13:27:00 +0200 Subject: [PATCH 0908/1105] tests: remote: Add run_monitor test case This is useful to run monitor quickly: ./run-tests.py -t run_monitor -m mon:36,20,36,0:1,20,1,0 In such example we will get one PCAP for 36/20 and 1/20. After execution, PCAP file is in the log directory, e.g.: ./logs/2019_11_11_13_36_24/run_monitor_mon_wlp3s0_wlp5s0.pcap Signed-off-by: Janusz Dziedzic --- tests/remote/test_monitor.py | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/remote/test_monitor.py diff --git a/tests/remote/test_monitor.py b/tests/remote/test_monitor.py new file mode 100644 index 000000000..c8b88d4be --- /dev/null +++ b/tests/remote/test_monitor.py @@ -0,0 +1,52 @@ +# Monitor support +# +# This software may be distributed under the terms of the BSD license. +# See README for more details. + +import remotehost +import config +import rutils +import monitor +import time +import os + +import logging +logger = logging.getLogger() + +def run_monitor(devices, setup_params, refs, duts, monitors, seconds=None): + try: + air_monitor = [] + output = "\n\tPCAP files:\n" + # setup log dir + local_log_dir = setup_params['local_log_dir'] + + # add/run monitors if requested + air_monitors = monitor.create(devices, setup_params, refs, duts, + monitors) + for air_monitor in air_monitors: + monitor.setup(air_monitor) + monitor.run(air_monitor, setup_params) + logger.warning(air_monitor.name + " - monitor started ...") + + if seconds != None: + time.sleep(int(seconds)) + else: + input("\tPress Enter to end capturing...") + + # destroy monitor / get pcap + monitor.destroy(devices, air_monitors) + for air_monitor in air_monitors: + for log in air_monitor.logs: + head, tail = os.path.split(log) + output = output + "\t" + local_log_dir + "/" + tail + "\n" + air_monitor.get_logs(local_log_dir) + return output + except: + for air_monitor in air_monitors: + monitor.destroy(devices, air_monitors) + air_monitor.get_logs(local_log_dir) + raise + +def test_run_monitor(devices, setup_params, refs, duts, monitors): + """TC run standalone monitor""" + return run_monitor(devices, setup_params, refs, duts, monitors) From 1c58317f56e312576b6872440f125f794e45f991 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 30 Sep 2020 18:34:36 +0200 Subject: [PATCH 0909/1105] D-Bus: Allow changing an interface bridge via D-Bus D-Bus clients can call CreateInterface() once and use the resulting Interface object to connect multiple times to different networks. However, if the network interface gets added to a bridge, clients currently have to remove the Interface object and create a new one. Improve this by supporting the change of the BridgeIfname property of an existing Interface object. Signed-off-by: Beniamino Galvani --- src/rsn_supp/tdls.c | 5 +++ wpa_supplicant/dbus/dbus_new.c | 2 +- wpa_supplicant/dbus/dbus_new_handlers.c | 37 ++++++++++++++++ wpa_supplicant/dbus/dbus_new_handlers.h | 1 + wpa_supplicant/wpa_supplicant.c | 59 +++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 2 + 6 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 7b47e3ac5..eff8cd829 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -2807,6 +2807,11 @@ int wpa_tdls_init(struct wpa_sm *sm) if (sm == NULL) return -1; + if (sm->l2_tdls) { + l2_packet_deinit(sm->l2_tdls); + sm->l2_tdls = NULL; + } + sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname : sm->ifname, sm->own_addr, diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 793a881ef..ab7628f87 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -3613,7 +3613,7 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { }, { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", wpas_dbus_getter_bridge_ifname, - NULL, + wpas_dbus_setter_bridge_ifname, NULL }, { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 34abab752..2cfc87fa8 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -3635,6 +3635,43 @@ dbus_bool_t wpas_dbus_getter_bridge_ifname( } +dbus_bool_t wpas_dbus_setter_bridge_ifname( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + const char *bridge_ifname = NULL; + const char *msg; + int r; + + if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, + &bridge_ifname)) + return FALSE; + + r = wpa_supplicant_update_bridge_ifname(wpa_s, bridge_ifname); + if (r != 0) { + switch (r) { + case -EINVAL: + msg = "invalid interface name"; + break; + case -EBUSY: + msg = "interface is busy"; + break; + case -EIO: + msg = "socket error"; + break; + default: + msg = "unknown error"; + break; + } + dbus_set_error_const(error, DBUS_ERROR_FAILED, msg); + return FALSE; + } + + return TRUE; +} + + /** * wpas_dbus_getter_config_file - Get interface configuration file path * @iter: Pointer to incoming dbus message iter diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index afa26efed..d528c0816 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -167,6 +167,7 @@ DECLARE_ACCESSOR(wpas_dbus_setter_scan_interval); DECLARE_ACCESSOR(wpas_dbus_getter_ifname); DECLARE_ACCESSOR(wpas_dbus_getter_driver); DECLARE_ACCESSOR(wpas_dbus_getter_bridge_ifname); +DECLARE_ACCESSOR(wpas_dbus_setter_bridge_ifname); DECLARE_ACCESSOR(wpas_dbus_getter_config_file); DECLARE_ACCESSOR(wpas_dbus_getter_current_bss); DECLARE_ACCESSOR(wpas_dbus_getter_current_network); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 39e92fb68..a7e9e459e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4906,6 +4906,65 @@ static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr, } +int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s, + const char *bridge_ifname) +{ + if (wpa_s->wpa_state > WPA_SCANNING) + return -EBUSY; + + if (bridge_ifname && + os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname)) + return -EINVAL; + + if (!bridge_ifname) + bridge_ifname = ""; + + if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0) + return 0; + + if (wpa_s->l2_br) { + l2_packet_deinit(wpa_s->l2_br); + wpa_s->l2_br = NULL; + } + + os_strlcpy(wpa_s->bridge_ifname, bridge_ifname, + sizeof(wpa_s->bridge_ifname)); + + if (wpa_s->bridge_ifname[0]) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Receiving packets from bridge interface '%s'", + wpa_s->bridge_ifname); + wpa_s->l2_br = l2_packet_init_bridge( + wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr, + ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1); + if (!wpa_s->l2_br) { + wpa_msg(wpa_s, MSG_ERROR, + "Failed to open l2_packet connection for the bridge interface '%s'", + wpa_s->bridge_ifname); + goto fail; + } + } + +#ifdef CONFIG_TDLS + if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa)) + goto fail; +#endif /* CONFIG_TDLS */ + + return 0; +fail: + wpa_s->bridge_ifname[0] = 0; + if (wpa_s->l2_br) { + l2_packet_deinit(wpa_s->l2_br); + wpa_s->l2_br = NULL; + } +#ifdef CONFIG_TDLS + if (!wpa_s->p2p_mgmt) + wpa_tdls_init(wpa_s->wpa); +#endif /* CONFIG_TDLS */ + return -EIO; +} + + /** * wpa_supplicant_driver_init - Initialize driver interface parameters * @wpa_s: Pointer to wpa_supplicant data diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 31a9b7427..eac3491cc 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1351,6 +1351,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s); const char * wpa_supplicant_state_txt(enum wpa_states state); int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s); int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s); +int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s, + const char *bridge_ifname); int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, u8 *wpa_ie, size_t *wpa_ie_len); From a87173b1d1eb74973cc2b761e005d248d1c8aad7 Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Wed, 15 Jul 2020 17:17:40 -0700 Subject: [PATCH 0910/1105] D-Bus: Skip property update actions when wpa_config_set() returns 1 When network properties are updated via dbus, wpa_config_set() is used to update the property in the wpa_ssid struct. If it returns 1, the property was not changed and there's no need to perform any of the update actions. Signed-off-by: Matthew Wang --- wpa_supplicant/dbus/dbus_new_handlers.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 2cfc87fa8..1c3f33367 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -268,8 +268,11 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, } else goto error; - if (wpa_config_set(ssid, entry.key, value, 0) < 0) + ret = wpa_config_set(ssid, entry.key, value, 0); + if (ret < 0) goto error; + if (ret == 1) + goto skip_update; if (os_strcmp(entry.key, "bssid") != 0 && os_strcmp(entry.key, "priority") != 0) @@ -291,6 +294,7 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, else if (os_strcmp(entry.key, "priority") == 0) wpa_config_update_prio_list(wpa_s->conf); + skip_update: os_free(value); value = NULL; wpa_dbus_dict_entry_clear(&entry); From 922fa099721903b106a7bc1ccd1ffe8c4a7bce69 Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Wed, 15 Jul 2020 17:17:41 -0700 Subject: [PATCH 0911/1105] Global parser functions to return 1 when property unchanged Currently, wpa_config_set(), the function that sets wpa_supplicant per-network properties, returns 1 when a property it attempts to set is unchanged. Its global parallel, wpa_config_process_global(), doesn't do this even though much of the code is very similar. Change this, and several of the parser functions, to resemble the per-network parser and setter functions. Signed-off-by: Matthew Wang --- src/utils/wpabuf.h | 15 ++++++ wpa_supplicant/config.c | 63 +++++++++++++++++++++++-- wpa_supplicant/ctrl_iface.c | 2 + wpa_supplicant/dbus/dbus_new_handlers.c | 7 +-- 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/utils/wpabuf.h b/src/utils/wpabuf.h index 01da41b32..b2a54b22f 100644 --- a/src/utils/wpabuf.h +++ b/src/utils/wpabuf.h @@ -70,6 +70,21 @@ static inline size_t wpabuf_tailroom(const struct wpabuf *buf) return buf->size - buf->used; } +/** + * wpabuf_cmp - Check if two buffers contain the same data + * @a: wpabuf buffer + * @b: wpabuf buffer + * Returns: 0 if the two buffers contain the same data and non-zero otherwise + */ +static inline int wpabuf_cmp(const struct wpabuf *a, const struct wpabuf *b) +{ + if (!a && !b) + return 0; + if (a && b && wpabuf_size(a) == wpabuf_size(b)) + return os_memcmp(a->buf, b->buf, wpabuf_size(a)); + return -1; +} + /** * wpabuf_head - Get pointer to the head of the buffer data * @buf: wpabuf buffer diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 154687d30..0cbd09c86 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4360,13 +4360,31 @@ void wpa_config_debug_dump_networks(struct wpa_config *config) #endif /* CONFIG_NO_STDOUT_DEBUG */ +/** + * Structure for global configuration parsing. This data is used to implement a + * generic parser for the global interface configuration. The table of variables + * is defined below in this file (global_fields[]). + */ struct global_parse_data { + /* Configuration variable name */ char *name; + + /* Parser function for this variable. The parser functions return 0 or 1 + * to indicate success. Value 0 indicates that the parameter value may + * have changed while value 1 means that the value did not change. + * Error cases (failure to parse the string) are indicated by returning + * -1. */ int (*parser)(const struct global_parse_data *data, struct wpa_config *config, int line, const char *value); + + /* Getter function to print the variable in text format to buf. */ int (*get)(const char *name, struct wpa_config *config, long offset, char *buf, size_t buflen, int pretty_print); + + /* Variable specific parameters for the parser. */ void *param1, *param2, *param3; + + /* Indicates which configuration variable has changed. */ unsigned int changed_flag; }; @@ -4377,6 +4395,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data, { int val, *dst; char *end; + bool same; dst = (int *) (((u8 *) config) + (long) data->param1); val = strtol(pos, &end, 0); @@ -4385,6 +4404,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data, line, pos); return -1; } + same = *dst == val; *dst = val; wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); @@ -4405,7 +4425,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data, return -1; } - return 0; + return same; } @@ -4413,7 +4433,7 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data, struct wpa_config *config, int line, const char *pos) { - size_t len; + size_t len, prev_len; char **dst, *tmp; len = os_strlen(pos); @@ -4437,11 +4457,22 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data, return -1; } + dst = (char **) (((u8 *) config) + (long) data->param1); + if (*dst) + prev_len = os_strlen(*dst); + else + prev_len = 0; + + /* No change to the previously configured value */ + if ((!(*dst) && !pos) || + (*dst && pos && prev_len == len && + os_memcmp(*dst, pos, len) == 0)) + return 1; + tmp = os_strdup(pos); if (tmp == NULL) return -1; - dst = (char **) (((u8 *) config) + (long) data->param1); os_free(*dst); *dst = tmp; wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); @@ -4482,6 +4513,10 @@ static int wpa_global_config_parse_bin(const struct global_parse_data *data, return -1; dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1); + if (wpabuf_cmp(*dst, tmp) == 0) { + wpabuf_free(tmp); + return 1; + } wpabuf_free(*dst); *dst = tmp; wpa_printf(MSG_DEBUG, "%s", data->name); @@ -4523,6 +4558,8 @@ static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, return -1; dst = (u32 *) (((u8 *) config) + (long) data->param1); + if (os_memcmp(dst, &addr.u.v4.s_addr, 4) == 0) + return 1; os_memcpy(dst, &addr.u.v4.s_addr, 4); wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name, WPA_GET_BE32((u8 *) dst)); @@ -4540,6 +4577,8 @@ static int wpa_config_process_country(const struct global_parse_data *data, wpa_printf(MSG_DEBUG, "Invalid country set"); return -1; } + if (pos[0] == config->country[0] && pos[1] == config->country[1]) + return 1; config->country[0] = pos[0]; config->country[1] = pos[1]; wpa_printf(MSG_DEBUG, "country='%c%c'", @@ -5159,6 +5198,19 @@ const char * wpa_config_get_global_field_name(unsigned int i, int *no_var) } +/** + * wpa_config_process_global - Set a variable in global configuration + * @config: Pointer to global configuration data + * @pos: Name and value in the format "{name}={value}" + * @line: Line number in configuration file or 0 if not used + * Returns: 0 on success with a possible change in value, 1 on success with no + * change to previously configured value, or -1 on failure + * + * This function can be used to set global configuration variables based on + * both the configuration file and management interface input. The value + * parameter must be in the same format as the text-based configuration file is + * using. For example, strings are using double quotation marks. + */ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) { size_t i; @@ -5171,11 +5223,14 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) pos[flen] != '=') continue; - if (field->parser(field, config, line, pos + flen + 1)) { + ret = field->parser(field, config, line, pos + flen + 1); + if (ret < 0) { wpa_printf(MSG_ERROR, "Line %d: failed to " "parse '%s'.", line, pos); ret = -1; } + if (ret == 1) + break; if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN) config->wps_nfc_pw_from_config = 1; config->changed_parameters |= field->changed_flag; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 5048ee83e..127b5fe0b 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -898,6 +898,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = wpa_config_process_global(wpa_s->conf, cmd, -1); if (ret == 0) wpa_supplicant_update_config(wpa_s); + else if (ret == 1) + ret = 0; } return ret; diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 1c3f33367..defb9d405 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -3983,14 +3983,15 @@ dbus_bool_t wpas_dbus_setter_iface_global( return FALSE; } - if (wpa_config_process_global(wpa_s->conf, buf, -1)) { + ret = wpa_config_process_global(wpa_s->conf, buf, -1); + if (ret < 0) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Failed to set interface property %s", property_desc->dbus_property); return FALSE; + } else if (ret == 0) { + wpa_supplicant_update_config(wpa_s); } - - wpa_supplicant_update_config(wpa_s); return TRUE; } From 4756ecabcfd08bb99968c0c738b7879e7e0211f5 Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Wed, 15 Jul 2020 17:17:42 -0700 Subject: [PATCH 0912/1105] Allow bgscan parameters to be reconfigured Teach wpa_supplicant to {de,}initialize bgscans when bgscan parameters are set after initial connection. Signed-off-by: Matthew Wang --- wpa_supplicant/config.c | 2 +- wpa_supplicant/config.h | 1 + wpa_supplicant/ctrl_iface.c | 14 ++++++++ wpa_supplicant/dbus/dbus_new_handlers.c | 17 +++++++++ wpa_supplicant/wpa_supplicant.c | 48 +++++++++++++++++-------- wpa_supplicant/wpa_supplicant_i.h | 1 + 6 files changed, 67 insertions(+), 16 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 0cbd09c86..b828b599f 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4963,7 +4963,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(eapol_version, 1, 2), 0 }, #endif /* CONFIG_MACSEC */ { INT(ap_scan), 0 }, - { FUNC(bgscan), 0 }, + { FUNC(bgscan), CFG_CHANGED_BGSCAN }, #ifdef CONFIG_MESH { INT(user_mpm), 0 }, { INT_RANGE(max_peer_links, 0, 255), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 3c38e1e57..2a2ad8722 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -376,6 +376,7 @@ struct wpa_cred { #define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17) #define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18) #define CFG_CHANGED_DISABLE_BTM BIT(19) +#define CFG_CHANGED_BGSCAN BIT(20) /** * struct wpa_config - wpa_supplicant configuration data diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 127b5fe0b..7df7ba0d1 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -3547,6 +3547,20 @@ static int wpa_supplicant_ctrl_iface_update_network( if (ret == 1) return 0; /* No change to the previously configured value */ +#ifdef CONFIG_BGSCAN + if (os_strcmp(name, "bgscan") == 0) { + /* + * Reset the bgscan parameters for the current network and + * return. There's no need to flush caches for bgscan parameter + * changes. + */ + if (wpa_s->current_ssid == ssid && + wpa_s->wpa_state == WPA_COMPLETED) + wpa_supplicant_reset_bgscan(wpa_s); + return 0; + } +#endif /* CONFIG_BGSCAN */ + if (os_strcmp(name, "bssid") != 0 && os_strcmp(name, "bssid_hint") != 0 && os_strcmp(name, "priority") != 0) { diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index defb9d405..53e869488 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -274,6 +274,23 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, if (ret == 1) goto skip_update; +#ifdef CONFIG_BGSCAN + if (os_strcmp(entry.key, "bgscan") == 0) { + /* + * Reset the bgscan parameters for the current network + * and continue. There's no need to flush caches for + * bgscan parameter changes. + */ + if (wpa_s->current_ssid == ssid && + wpa_s->wpa_state == WPA_COMPLETED) + wpa_supplicant_reset_bgscan(wpa_s); + os_free(value); + value = NULL; + wpa_dbus_dict_entry_clear(&entry); + continue; + } +#endif /* CONFIG_BGSCAN */ + if (os_strcmp(entry.key, "bssid") != 0 && os_strcmp(entry.key, "priority") != 0) wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index a7e9e459e..cb243f2f8 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -803,7 +803,22 @@ const char * wpa_supplicant_state_txt(enum wpa_states state) #ifdef CONFIG_BGSCAN -static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s) +static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->bgscan_ssid) { + bgscan_deinit(wpa_s); + wpa_s->bgscan_ssid = NULL; + } +} + + +/** + * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID. + * @wpa_s: Pointer to the wpa_supplicant data + * + * Stop, start, or reconfigure the scan parameters depending on the method. + */ +void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s) { const char *name; @@ -811,12 +826,12 @@ static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s) name = wpa_s->current_ssid->bgscan; else name = wpa_s->conf->bgscan; - if (name == NULL || name[0] == '\0') + if (!name || name[0] == '\0') { + wpa_supplicant_stop_bgscan(wpa_s); return; + } if (wpas_driver_bss_selection(wpa_s)) return; - if (wpa_s->current_ssid == wpa_s->bgscan_ssid) - return; #ifdef CONFIG_P2P if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) return; @@ -846,15 +861,6 @@ static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s) wpa_s->bgscan_ssid = NULL; } - -static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->bgscan_ssid != NULL) { - bgscan_deinit(wpa_s); - wpa_s->bgscan_ssid = NULL; - } -} - #endif /* CONFIG_BGSCAN */ @@ -1011,8 +1017,8 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_s->wpa_state = state; #ifdef CONFIG_BGSCAN - if (state == WPA_COMPLETED) - wpa_supplicant_start_bgscan(wpa_s); + if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid) + wpa_supplicant_reset_bgscan(wpa_s); else if (state < WPA_ASSOCIATED) wpa_supplicant_stop_bgscan(wpa_s); #endif /* CONFIG_BGSCAN */ @@ -7255,6 +7261,18 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s) if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM) wpa_supplicant_set_default_scan_ies(wpa_s); +#ifdef CONFIG_BGSCAN + /* + * We default to global bgscan parameters only when per-network bgscan + * parameters aren't set. Only bother resetting bgscan parameters if + * this is the case. + */ + if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) && + wpa_s->current_ssid && !wpa_s->current_ssid->bgscan && + wpa_s->wpa_state == WPA_COMPLETED) + wpa_supplicant_reset_bgscan(wpa_s); +#endif /* CONFIG_BGSCAN */ + #ifdef CONFIG_WPS wpas_wps_update_config(wpa_s); #endif /* CONFIG_WPS */ diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index eac3491cc..5d99fcccd 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1465,6 +1465,7 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s, void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s); void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s); void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx); +void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s); /* MBO functions */ From b2a1424659b162818ddc31bf9b96d9347bb08e44 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 9 Oct 2020 16:41:16 +0300 Subject: [PATCH 0913/1105] tests: Empty network profile parameters will be valid Remove this part of the dbus_network test case since it would be causing failures after wpa_supplicant is modified to accept empty strings through D-Bus. Signed-off-by: Jouni Malinen --- tests/hwsim/test_dbus.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py index e9d6b9e39..7b3d4bee5 100644 --- a/tests/hwsim/test_dbus.py +++ b/tests/hwsim/test_dbus.py @@ -1812,8 +1812,7 @@ def test_dbus_network(dev, apdev): tests = [dbus.Dictionary({'psk': "1234567"}, signature='sv'), dbus.Dictionary({'identity': dbus.ByteArray()}, signature='sv'), - dbus.Dictionary({'identity': dbus.Byte(1)}, signature='sv'), - dbus.Dictionary({'identity': ""}, signature='sv')] + dbus.Dictionary({'identity': dbus.Byte(1)}, signature='sv')] for args in tests: try: iface.AddNetwork(args) From 41d20df7f319c5ce251569923a87c9476b4dc1ba Mon Sep 17 00:00:00 2001 From: Matthew Wang Date: Wed, 15 Jul 2020 17:17:43 -0700 Subject: [PATCH 0914/1105] D-Bus: Allow empty string in dbus network properties This is needed for clearing previously set parameters in a similar manner that was already available through the control interface SET_NETWORK command. Signed-off-by: Matthew Wang --- wpa_supplicant/dbus/dbus_new_handlers.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 53e869488..66a0e2152 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -230,8 +230,6 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, } else if (entry.type == DBUS_TYPE_STRING) { if (should_quote_opt(entry.key)) { size = os_strlen(entry.str_value); - if (size == 0) - goto error; size += 3; value = os_zalloc(size); From fb0c693d5f173c0e93c0adbb3396b3b0350bc6c8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 9 Oct 2020 15:48:54 +0300 Subject: [PATCH 0915/1105] tests: bgscan parameter update Signed-off-by: Jouni Malinen --- tests/hwsim/test_bgscan.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/hwsim/test_bgscan.py b/tests/hwsim/test_bgscan.py index 5951f82e0..e3c1790ba 100644 --- a/tests/hwsim/test_bgscan.py +++ b/tests/hwsim/test_bgscan.py @@ -302,3 +302,14 @@ def test_bgscan_unknown_module(dev, apdev): hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"}) dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412", bgscan="unknown:-20:2") + +def test_bgscan_reconfig(dev, apdev): + """bgscan parameter update""" + hostapd.add_ap(apdev[0], {"ssid": "bgscan"}) + hostapd.add_ap(apdev[1], {"ssid": "bgscan"}) + + id = dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412", + bgscan="simple:1:-20:2") + dev[0].set_network_quoted(id, "bgscan", "simple:1:-45:2") + dev[0].set_network_quoted(id, "bgscan", "learn:1:-20:2") + dev[0].set_network_quoted(id, "bgscan", "") From 8776551bf8f9c3dcbccc96b5ff7043317eb78fb4 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 21 Jul 2020 11:53:55 +0100 Subject: [PATCH 0916/1105] BSD: don't log SIOCG80211 errors during interface setup Unless debugging. wpa_supplicant will log it failed to initialized the driver for the interface anyway so this just silences some noise for users. Signed-off-by: Roy Marples --- src/drivers/driver_bsd.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c index 5adee13a2..a29d2c801 100644 --- a/src/drivers/driver_bsd.c +++ b/src/drivers/driver_bsd.c @@ -137,7 +137,9 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, ireq->i_data = arg; if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, " + int level = drv->if_removed ? MSG_DEBUG : MSG_ERROR; + + wpa_printf(level, "ioctl[SIOCG80211, op=%u, " "arg_len=%u]: %s", op, arg_len, strerror(errno)); return -1; } @@ -1468,6 +1470,9 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) drv->global = priv; os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); + /* Set the interface as removed until proven to work. */ + drv->if_removed = 1; + if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", __func__, strerror(errno)); @@ -1495,6 +1500,9 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) if (bsd_get_iface_flags(drv) < 0) goto fail; + /* Proven to work, lets go! */ + drv->if_removed = 0; + drv->opmode = get80211opmode(drv); dl_list_add(&drv->global->ifaces, &drv->list); From 83fa0a1004c75822de2d60854a833f13055ee017 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 21 Jul 2020 13:17:41 +0100 Subject: [PATCH 0917/1105] op_classes: Don't report an error when there are none to add Instead, log a diagnostic so that noise to the user is reduced. This is expected behavior with driver interfaces that do not report supported operating modes/classes. Signed-off-by: Roy Marples --- wpa_supplicant/op_classes.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c index bd97fee54..91e15e799 100644 --- a/wpa_supplicant/op_classes.c +++ b/wpa_supplicant/op_classes.c @@ -412,9 +412,13 @@ size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, } *ie_len = wpabuf_len(buf) - 2; - if (*ie_len < 2 || wpabuf_len(buf) > len) { + if (*ie_len < 2) { + wpa_printf(MSG_DEBUG, + "No supported operating classes IE to add"); + res = 0; + } else if (wpabuf_len(buf) > len) { wpa_printf(MSG_ERROR, - "Failed to add supported operating classes IE"); + "Supported operating classes IE exceeds maximum buffer length"); res = 0; } else { os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf)); From e8b85c078e7339422c14ba09a64c01dc142f8516 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Tue, 21 Jul 2020 14:25:26 +0100 Subject: [PATCH 0918/1105] iface match: Unspecified matched interfaces should not log driver fails If there is no matching interface given, but interface matching is enabled, all interfaces on the system will try to be initialized. Non wireless interfaces will fail and the loopback device will be one of these, so just log a diagnostic rather than an error. Signed-off-by: Roy Marples --- wpa_supplicant/events.c | 2 -- wpa_supplicant/wpa_supplicant.c | 19 +++++++++++++++---- wpa_supplicant/wpa_supplicant_i.h | 12 ++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 15c572f11..7b7802c46 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -5472,8 +5472,6 @@ void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event, return; wpa_s = wpa_supplicant_add_iface(ctx, wpa_i, NULL); os_free(wpa_i); - if (wpa_s) - wpa_s->matched = 1; } #endif /* CONFIG_MATCH_IFACE */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index cb243f2f8..a52b9a9e1 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6154,6 +6154,8 @@ next_driver: wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname); if (wpa_s->drv_priv == NULL) { const char *pos; + int level = MSG_ERROR; + pos = driver ? os_strchr(driver, ',') : NULL; if (pos) { wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize " @@ -6161,8 +6163,12 @@ next_driver: driver = pos + 1; goto next_driver; } - wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver " - "interface"); + +#ifdef CONFIG_MATCH_IFACE + if (wpa_s->matched == WPA_IFACE_MATCHED_NULL) + level = MSG_DEBUG; +#endif /* CONFIG_MATCH_IFACE */ + wpa_msg(wpa_s, level, "Failed to initialize driver interface"); return -1; } if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) { @@ -6307,6 +6313,9 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, return -1; } os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname)); +#ifdef CONFIG_MATCH_IFACE + wpa_s->matched = iface->matched; +#endif /* CONFIG_MATCH_IFACE */ if (iface->bridge_ifname) { if (os_strlen(iface->bridge_ifname) >= @@ -6698,6 +6707,10 @@ struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global, if (!iface) return NULL; *iface = *miface; + if (!miface->ifname) + iface->matched = WPA_IFACE_MATCHED_NULL; + else + iface->matched = WPA_IFACE_MATCHED; iface->ifname = ifname; return iface; } @@ -6732,8 +6745,6 @@ static int wpa_supplicant_match_existing(struct wpa_global *global) if (iface) { wpa_s = wpa_supplicant_add_iface(global, iface, NULL); os_free(iface); - if (wpa_s) - wpa_s->matched = 1; } } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 5d99fcccd..e8778bbf9 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -121,6 +121,18 @@ struct wpa_interface { * interface that is not a network interface. */ int p2p_mgmt; + +#ifdef CONFIG_MATCH_IFACE + /** + * matched - Interface was matched rather than specified + * + */ + enum { + WPA_IFACE_NOT_MATCHED, + WPA_IFACE_MATCHED_NULL, + WPA_IFACE_MATCHED + } matched; +#endif /* CONFIG_MATCH_IFACE */ }; /** From a28d127b1a994a8d25e51c69686d8db9e9fcdf62 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Tue, 25 Aug 2020 08:48:06 -0700 Subject: [PATCH 0919/1105] AP: Reflect status code in SAE reflection attack test When testing SAE reflection, the incoming commit may have the H2E status code (126) or SAE-PK (127), but the test code in the AP was always sending back status code 0. The STA would then reject the commit response due to expecting H2E/SAE-PK status code. Just reflect the incoming status code so the commit can be rejected based on the SAE contents regardless of which variant of SAE was used. Signed-off-by: Thomas Pedersen --- src/ap/ieee802_11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index a1a27f102..292393224 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1241,6 +1241,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack"); pos = mgmt->u.auth.variable; end = ((const u8 *) mgmt) + len; + resp = status_code; send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE, auth_transaction, resp, pos, end - pos, "auth-sae-reflection-attack"); From 21cc50a43442b8f5540d71bfed8c1baf83f1dbc5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:47 +0200 Subject: [PATCH 0920/1105] HS 2.0 server: Add a .gitignore file Signed-off-by: Johannes Berg --- hs20/server/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 hs20/server/.gitignore diff --git a/hs20/server/.gitignore b/hs20/server/.gitignore new file mode 100644 index 000000000..fecb096c1 --- /dev/null +++ b/hs20/server/.gitignore @@ -0,0 +1 @@ +hs20_spp_server From a41a29192e5d196444fc8859100762b04ff0d1c2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:48 +0200 Subject: [PATCH 0921/1105] build: Pull common fragments into a build.rules file Some things are used by most of the binaries, pull them into a common rule fragment that we can use properly. Signed-off-by: Johannes Berg --- eap_example/Makefile | 31 +------------------- hostapd/Makefile | 34 ++------------------- hs20/client/Makefile | 30 ++----------------- hs20/server/Makefile | 14 ++------- radius_example/Makefile | 14 +-------- src/build.rules | 43 +++++++++++++++++++++++++++ tests/Makefile | 20 +++---------- wlantest/Makefile | 35 +--------------------- wpa_supplicant/Makefile | 65 +++++++++++------------------------------ 9 files changed, 74 insertions(+), 212 deletions(-) create mode 100644 src/build.rules diff --git a/eap_example/Makefile b/eap_example/Makefile index 0cc19bd53..e5f3b3471 100644 --- a/eap_example/Makefile +++ b/eap_example/Makefile @@ -1,19 +1,6 @@ ALL=eap_example -all: $(ALL) - -ifndef CC -CC=gcc -endif - -ifndef RANLIB -RANLIB=ranlib -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - +include ../src/build.rules CFLAGS += -I. CFLAGS += -I../src @@ -95,22 +82,6 @@ OBJS_server += ../src/eap_server/eap_server_tls_common.o CFLAGS += -DEAP_SERVER -ifndef LDO -LDO=$(CC) -endif - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - - OBJS_lib=$(OBJS_both) $(OBJS_peer) $(OBJS_server) OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o diff --git a/hostapd/Makefile b/hostapd/Makefile index 1400002a9..5c830fb44 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -1,10 +1,7 @@ -ifndef CC -CC=gcc -endif +ALL=hostapd hostapd_cli +VERIFY=verify_config -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../src/build.rules ifdef LIBS # If LIBS is set with some global build system defaults, clone those for @@ -1264,31 +1261,6 @@ ifdef CONFIG_NO_TKIP CFLAGS += -DCONFIG_NO_TKIP endif -ALL=hostapd hostapd_cli - -all: verify_config $(ALL) - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true -endif - -ifdef CONFIG_CODE_COVERAGE -%.o: %.c - @$(E) " CC " $< - $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<) -else -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< -endif - verify_config: @if [ ! -r .config ]; then \ echo 'Building hostapd requires a configuration file'; \ diff --git a/hs20/client/Makefile b/hs20/client/Makefile index cc2af03f4..70fb73598 100644 --- a/hs20/client/Makefile +++ b/hs20/client/Makefile @@ -1,28 +1,6 @@ -all: hs20-osu-client +ALL=hs20-osu-client -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifeq ($(QUIET), 1) -Q=@ -E=true -else -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../../src/build.rules CFLAGS += -I../../src/utils CFLAGS += -I../../src/common @@ -97,10 +75,6 @@ hs20-osu-client: $(OBJS) $(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS) @$(E) " LD " $@ -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - clean: rm -f core *~ *.o *.d hs20-osu-client rm -f ../../src/utils/*.o diff --git a/hs20/server/Makefile b/hs20/server/Makefile index 9b7372796..9ec7e4491 100644 --- a/hs20/server/Makefile +++ b/hs20/server/Makefile @@ -1,16 +1,6 @@ -all: hs20_spp_server +ALL=hs20_spp_server -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../../src/build.rules CFLAGS += -I../../src CFLAGS += -I../../src/utils diff --git a/radius_example/Makefile b/radius_example/Makefile index 883e2f2da..75cb3caeb 100644 --- a/radius_example/Makefile +++ b/radius_example/Makefile @@ -1,18 +1,6 @@ ALL=radius_example -all: $(ALL) - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../src/build.rules CFLAGS += -I. CFLAGS += -I../src diff --git a/src/build.rules b/src/build.rules new file mode 100644 index 000000000..f1ce7748e --- /dev/null +++ b/src/build.rules @@ -0,0 +1,43 @@ +.PHONY: all +all: $(VERIFY) $(ALL) $(EXTRA_TARGETS) + +ifndef CC +CC=gcc +endif + +ifndef RANLIB +RANLIB=ranlib +endif + +ifndef LDO +LDO=$(CC) +endif + +ifndef CFLAGS +CFLAGS = -MMD -O2 -Wall -g +endif + +Q=@ +E=echo +ifeq ($(V), 1) +Q= +E=true +endif +ifeq ($(QUIET), 1) +Q=@ +E=true +endif + +ifeq ($(Q),@) +MAKEFLAGS += --no-print-directory +endif + +ifdef CONFIG_CODE_COVERAGE +%.o: %.c + @$(E) " CC " $< + $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<) +else +%.o: %.c + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + @$(E) " CC " $< +endif diff --git a/tests/Makefile b/tests/Makefile index 0817c9a27..119ed7a2a 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,9 +1,9 @@ -TESTS=test-base64 test-md4 test-milenage \ +ALL=test-base64 test-md4 test-milenage \ test-rsa-sig-ver \ test-sha1 \ test-sha256 test-aes test-asn1 test-x509v3 test-list test-rc4 -all: $(TESTS) +include ../src/build.rules ifdef LIBFUZZER CC=clang @@ -14,18 +14,6 @@ LDFLAGS += -fsanitize=fuzzer,address,signed-integer-overflow,unsigned-integer-ov TEST_FUZZ=y endif -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - ifdef TEST_FUZZ CFLAGS += -DCONFIG_NO_RANDOM_POOL CFLAGS += -DTEST_FUZZ @@ -152,7 +140,7 @@ test-x509v3: test-x509v3.o $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -run-tests: $(TESTS) +run-tests: $(ALL) ./test-aes ./test-list ./test-md4 @@ -165,7 +153,7 @@ run-tests: $(TESTS) clean: $(MAKE) -C ../src clean - rm -f $(TESTS) *~ *.o *.d + rm -f $(ALL) *~ *.o *.d rm -f test-eapol rm -f test-https rm -f test-json diff --git a/wlantest/Makefile b/wlantest/Makefile index 22ea646c0..0324fa548 100644 --- a/wlantest/Makefile +++ b/wlantest/Makefile @@ -1,22 +1,9 @@ ALL=wlantest wlantest_cli test_vectors -all: $(ALL) +include ../src/build.rules UNAME := $(shell uname -s) -ifndef CC -CC=gcc -endif - -ifndef RANLIB -RANLIB=ranlib -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - - CFLAGS += -I. CFLAGS += -I../src CFLAGS += -I../src/utils @@ -26,26 +13,6 @@ ifneq ($(UNAME),Darwin) LIBS += -lrt endif -ifndef LDO -LDO=$(CC) -endif - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - - OWN_LIBS += ../src/utils/libutils.a OWN_LIBS += ../src/crypto/libcrypto.a diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index a01a32982..13d938168 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1,11 +1,24 @@ -ifndef CC -CC=gcc +BINALL=wpa_supplicant wpa_cli + +ifndef CONFIG_NO_WPA_PASSPHRASE +BINALL += wpa_passphrase endif -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g +ALL = $(BINALL) +ALL += systemd/wpa_supplicant.service +ALL += systemd/wpa_supplicant@.service +ALL += systemd/wpa_supplicant-nl80211@.service +ALL += systemd/wpa_supplicant-wired@.service +ALL += dbus/fi.w1.wpa_supplicant1.service +ifdef CONFIG_BUILD_WPA_CLIENT_SO +ALL += libwpa_client.so endif +VERIFY=verify_config +EXTRA_TARGETS=dynamic_eap_methods + +include ../src/build.rules + ifdef LIBS # If LIBS is set with some global build system defaults, clone those for # LIBS_c and LIBS_p to cover wpa_passphrase and wpa_cli as well. @@ -44,25 +57,6 @@ CONFIG_WPS_TESTING=y CONFIG_TDLS_TESTING=y endif -BINALL=wpa_supplicant wpa_cli - -ifndef CONFIG_NO_WPA_PASSPHRASE -BINALL += wpa_passphrase -endif - -ALL = $(BINALL) -ALL += systemd/wpa_supplicant.service -ALL += systemd/wpa_supplicant@.service -ALL += systemd/wpa_supplicant-nl80211@.service -ALL += systemd/wpa_supplicant-wired@.service -ALL += dbus/fi.w1.wpa_supplicant1.service -ifdef CONFIG_BUILD_WPA_CLIENT_SO -ALL += libwpa_client.so -endif - - -all: verify_config $(ALL) dynamic_eap_methods - verify_config: @if [ ! -r .config ]; then \ echo 'Building wpa_supplicant requires a configuration file'; \ @@ -1867,21 +1861,6 @@ ifdef CONFIG_NO_TKIP CFLAGS += -DCONFIG_NO_TKIP endif -ifndef LDO -LDO=$(CC) -endif - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true -endif - dynamic_eap_methods: $(EAPDYN) ../src/drivers/build.wpa_supplicant: @@ -1980,16 +1959,6 @@ eap_eke.so: ../src/eap_peer/eap_eke.c ../src/eap_common/eap_eke_common.c $(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \ -D$(*F:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init -ifdef CONFIG_CODE_COVERAGE -%.o: %.c - @$(E) " CC " $< - $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<) -else -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< -endif - %.service: %.service.in $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@ @$(E) " sed" $< From 3ff115db6f56e30916d02a6692501e592b6efb29 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:49 +0200 Subject: [PATCH 0922/1105] build: Disable built-in rules This makes things faster and easier to debug. Signed-off-by: Johannes Berg --- src/build.rules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/build.rules b/src/build.rules index f1ce7748e..5edfea1df 100644 --- a/src/build.rules +++ b/src/build.rules @@ -1,6 +1,9 @@ .PHONY: all all: $(VERIFY) $(ALL) $(EXTRA_TARGETS) +# disable built-in rules +.SUFFIXES: + ifndef CC CC=gcc endif From 06a6adb54e99a0bb809da701b57a12ed4216a120 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:50 +0200 Subject: [PATCH 0923/1105] build: Use build.rules in lib.rules Use the new build.rules in lib.rules and also unify the clean targets to lib.rules. Signed-off-by: Johannes Berg --- src/ap/Makefile | 6 ++---- src/common/Makefile | 6 ++---- src/crypto/Makefile | 7 ++----- src/eap_common/Makefile | 6 ++---- src/eap_peer/Makefile | 6 ++---- src/eap_server/Makefile | 6 ++---- src/eapol_auth/Makefile | 6 ++---- src/eapol_supp/Makefile | 6 ++---- src/l2_packet/Makefile | 6 ++---- src/lib.rules | 26 ++++---------------------- src/p2p/Makefile | 6 ++---- src/radius/Makefile | 7 ++----- src/rsn_supp/Makefile | 6 ++---- src/tls/Makefile | 7 ++----- src/utils/Makefile | 7 ++----- src/wps/Makefile | 6 ++---- 16 files changed, 34 insertions(+), 86 deletions(-) diff --git a/src/ap/Makefile b/src/ap/Makefile index 54e48a0dd..805181d00 100644 --- a/src/ap/Makefile +++ b/src/ap/Makefile @@ -1,12 +1,10 @@ -all: libap.a +ALL=libap.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libap.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules CFLAGS += -DHOSTAPD CFLAGS += -DNEED_AP_MLME diff --git a/src/common/Makefile b/src/common/Makefile index ccb280e90..eeb69f0d4 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,12 +1,10 @@ -all: libcommon.a +ALL=libcommon.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libcommon.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules CFLAGS += -DCONFIG_IEEE80211R CFLAGS += -DCONFIG_HS20 diff --git a/src/crypto/Makefile b/src/crypto/Makefile index c40e95566..94eac66fa 100644 --- a/src/crypto/Makefile +++ b/src/crypto/Makefile @@ -1,14 +1,11 @@ -all: libcrypto.a +ALL=libcrypto.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libcrypto.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules - CFLAGS += -DCONFIG_CRYPTO_INTERNAL CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER diff --git a/src/eap_common/Makefile b/src/eap_common/Makefile index f00b438c6..7d6777bab 100644 --- a/src/eap_common/Makefile +++ b/src/eap_common/Makefile @@ -1,12 +1,10 @@ -all: libeap_common.a +ALL=libeap_common.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libeap_common.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules LIB_OBJS= \ chap.o \ diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile index 6531ccd5d..282b89696 100644 --- a/src/eap_peer/Makefile +++ b/src/eap_peer/Makefile @@ -1,7 +1,6 @@ -all: libeap_peer.a +ALL=libeap_peer.a -clean: - rm -f *~ *.o *.so *.d *.gcno *.gcda *.gcov libeap_peer.a +include ../lib.rules install: if ls *.so >/dev/null 2>&1; then \ @@ -9,7 +8,6 @@ install: cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ ; fi -include ../lib.rules CFLAGS += -DIEEE8021X_EAPOL diff --git a/src/eap_server/Makefile b/src/eap_server/Makefile index 1172b7246..4ece9aa67 100644 --- a/src/eap_server/Makefile +++ b/src/eap_server/Makefile @@ -1,12 +1,10 @@ -all: libeap_server.a +ALL=libeap_server.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libeap_server.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules CFLAGS += -DCONFIG_HS20 diff --git a/src/eapol_auth/Makefile b/src/eapol_auth/Makefile index 7b927a127..0175a19d9 100644 --- a/src/eapol_auth/Makefile +++ b/src/eapol_auth/Makefile @@ -1,12 +1,10 @@ -all: libeapol_auth.a +ALL=libeapol_auth.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libeapol_auth.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules LIB_OBJS = eapol_auth_sm.o eapol_auth_dump.o diff --git a/src/eapol_supp/Makefile b/src/eapol_supp/Makefile index 80db9d486..c98280b46 100644 --- a/src/eapol_supp/Makefile +++ b/src/eapol_supp/Makefile @@ -1,12 +1,10 @@ -all: libeapol_supp.a +ALL=libeapol_supp.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libeapol_supp.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules CFLAGS += -DIEEE8021X_EAPOL diff --git a/src/l2_packet/Makefile b/src/l2_packet/Makefile index 47925b790..20f229511 100644 --- a/src/l2_packet/Makefile +++ b/src/l2_packet/Makefile @@ -1,12 +1,10 @@ -all: libl2_packet.a +ALL=libl2_packet.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libl2_packet.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules LIB_OBJS = l2_packet_linux.o diff --git a/src/lib.rules b/src/lib.rules index a46315442..81b895967 100644 --- a/src/lib.rules +++ b/src/lib.rules @@ -1,10 +1,5 @@ -ifndef CC -CC=gcc -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +LIB_RULES := $(lastword $(MAKEFILE_LIST)) +include $(dir $(LIB_RULES))build.rules ifdef TEST_FUZZ CFLAGS += -DCONFIG_NO_RANDOM_POOL @@ -14,18 +9,5 @@ endif CFLAGS += $(FUZZ_CFLAGS) CFLAGS += -I.. -I../utils - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< +clean: + $(Q)rm -f *~ *.o *.d *.gcno *.gcda *.gcov $(ALL) diff --git a/src/p2p/Makefile b/src/p2p/Makefile index 5587fcf28..174cf6f6f 100644 --- a/src/p2p/Makefile +++ b/src/p2p/Makefile @@ -1,12 +1,10 @@ -all: libp2p.a +ALL=libp2p.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libp2p.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules CFLAGS += -DCONFIG_WIFI_DISPLAY CFLAGS += -DCONFIG_WPS_NFC diff --git a/src/radius/Makefile b/src/radius/Makefile index 3ad4751df..dbe9a9a9f 100644 --- a/src/radius/Makefile +++ b/src/radius/Makefile @@ -1,14 +1,11 @@ -all: libradius.a +ALL=libradius.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libradius.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules - CFLAGS += -DCONFIG_IPV6 LIB_OBJS= \ diff --git a/src/rsn_supp/Makefile b/src/rsn_supp/Makefile index eea0efba9..255cb73a7 100644 --- a/src/rsn_supp/Makefile +++ b/src/rsn_supp/Makefile @@ -1,12 +1,10 @@ -all: librsn_supp.a +ALL=librsn_supp.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov librsn_supp.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules CFLAGS += -DCONFIG_IEEE80211R CFLAGS += -DCONFIG_TDLS diff --git a/src/tls/Makefile b/src/tls/Makefile index 52a890a15..0a36cf9e4 100644 --- a/src/tls/Makefile +++ b/src/tls/Makefile @@ -1,14 +1,11 @@ -all: libtls.a +ALL=libtls.a -clean: - rm -f *~ *.o *.d libtls.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules - CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH CFLAGS += -DCONFIG_CRYPTO_INTERNAL CFLAGS += -DCONFIG_TLSV11 diff --git a/src/utils/Makefile b/src/utils/Makefile index 1ee2bee67..29fb1295d 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1,14 +1,11 @@ -all: libutils.a +ALL=libutils.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libutils.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules - #CFLAGS += -DWPA_TRACE CFLAGS += -DCONFIG_IPV6 CFLAGS += -DCONFIG_DEBUG_FILE diff --git a/src/wps/Makefile b/src/wps/Makefile index 4806fe8da..811b62977 100644 --- a/src/wps/Makefile +++ b/src/wps/Makefile @@ -1,12 +1,10 @@ -all: libwps.a +ALL=libwps.a -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libwps.a +include ../lib.rules install: @echo Nothing to be made. -include ../lib.rules CFLAGS += -DCONFIG_P2P CFLAGS += -DCONFIG_WPS_OOB From 0430bc8267b42d1fe26cb4f5f8385ec8c8c2a5b4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:51 +0200 Subject: [PATCH 0924/1105] build: Add a common-clean target Clean up in a more common fashion as well, initially for ../src/. Also add $(Q) to the clean target in src/ Signed-off-by: Johannes Berg --- eap_example/Makefile | 5 ++--- hostapd/Makefile | 5 ++--- hs20/client/Makefile | 4 ++-- hs20/server/Makefile | 4 ++-- radius_example/Makefile | 5 ++--- src/Makefile | 4 ++-- src/build.rules | 8 ++++++++ tests/Makefile | 5 ++--- wlantest/Makefile | 5 ++--- wpa_supplicant/Makefile | 4 ++-- 10 files changed, 26 insertions(+), 23 deletions(-) diff --git a/eap_example/Makefile b/eap_example/Makefile index e5f3b3471..ecef3c976 100644 --- a/eap_example/Makefile +++ b/eap_example/Makefile @@ -116,8 +116,7 @@ endif eap_example: $(OBJS_ex) $(LIBEAP) $(LDO) $(LDFLAGS) -o eap_example $(OBJS_ex) -L. -leap $(LIBS) -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o *.d libeap.a libeap.so $(ALL) +clean: common-clean + rm -f core *~ *.o *.d libeap.a libeap.so -include $(OBJS:%.o=%.d) diff --git a/hostapd/Makefile b/hostapd/Makefile index 5c830fb44..2e15c8911 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -1362,9 +1362,8 @@ lcov-html: lcov -c -d .. > lcov.info genhtml lcov.info --output-directory lcov-html -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw +clean: common-clean + rm -f core *~ *.o nt_password_hash hlr_auc_gw rm -f sae_pk_gen rm -f *.d *.gcno *.gcda *.gcov rm -f lcov.info diff --git a/hs20/client/Makefile b/hs20/client/Makefile index 70fb73598..cbb1105e1 100644 --- a/hs20/client/Makefile +++ b/hs20/client/Makefile @@ -75,8 +75,8 @@ hs20-osu-client: $(OBJS) $(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS) @$(E) " LD " $@ -clean: - rm -f core *~ *.o *.d hs20-osu-client +clean: common-clean + rm -f core *~ *.o *.d rm -f ../../src/utils/*.o rm -f ../../src/utils/*.d rm -f ../../src/common/*.o diff --git a/hs20/server/Makefile b/hs20/server/Makefile index 9ec7e4491..24b81cd8a 100644 --- a/hs20/server/Makefile +++ b/hs20/server/Makefile @@ -36,8 +36,8 @@ OBJS += ../../src/utils/xml_libxml2.o hs20_spp_server: $(OBJS) $(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS) -clean: - rm -f core *~ *.o *.d hs20_spp_server +clean: common-clean + rm -f core *~ *.o *.d rm -f ../../src/utils/*.o rm -f ../../src/utils/*.d rm -f ../../src/crypto/*.o diff --git a/radius_example/Makefile b/radius_example/Makefile index 75cb3caeb..3492ac70f 100644 --- a/radius_example/Makefile +++ b/radius_example/Makefile @@ -27,8 +27,7 @@ OBJS_ex = radius_example.o radius_example: $(OBJS_ex) $(LIBS) $(LDO) $(LDFLAGS) -o radius_example $(OBJS_ex) $(LIBS) $(LLIBS) -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o *.d $(ALL) +clean: common-clean + rm -f core *~ *.o *.d -include $(OBJS:%.o=%.d) diff --git a/src/Makefile b/src/Makefile index c9e84c11d..6eb7f2acb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,8 +5,8 @@ all: for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done clean: - for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done - rm -f *~ + $(Q)for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done + $(Q)rm -f *~ install: for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done diff --git a/src/build.rules b/src/build.rules index 5edfea1df..18e23ea53 100644 --- a/src/build.rules +++ b/src/build.rules @@ -4,6 +4,9 @@ all: $(VERIFY) $(ALL) $(EXTRA_TARGETS) # disable built-in rules .SUFFIXES: +ROOTDIR := $(dir $(lastword $(MAKEFILE_LIST))) +ROOTDIR := $(dir $(ROOTDIR:%/=%)) + ifndef CC CC=gcc endif @@ -44,3 +47,8 @@ else $(Q)$(CC) -c -o $@ $(CFLAGS) $< @$(E) " CC " $< endif + +.PHONY: common-clean +common-clean: + $(Q)$(MAKE) -C $(ROOTDIR)/src clean + $(Q)rm -f $(ALL) diff --git a/tests/Makefile b/tests/Makefile index 119ed7a2a..4d9f2e0ab 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -151,9 +151,8 @@ run-tests: $(ALL) @echo @echo All tests completed successfully. -clean: - $(MAKE) -C ../src clean - rm -f $(ALL) *~ *.o *.d +clean: common-clean + rm -f *~ *.o *.d rm -f test-eapol rm -f test-https rm -f test-json diff --git a/wlantest/Makefile b/wlantest/Makefile index 0324fa548..fee80f6f4 100644 --- a/wlantest/Makefile +++ b/wlantest/Makefile @@ -81,8 +81,7 @@ wlantest_cli: $(OBJS_cli) $(OWN_LIBS) test_vectors: $(TOBJS) $(OWN_LIBS) $(LDO) $(LDFLAGS) -o test_vectors $(TOBJS) $(OWN_LIBS) $(LIBS) -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o *.d $(ALL) +clean: common-clean + rm -f core *~ *.o *.d -include $(OBJS:%.o=%.d) diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 13d938168..b18755bd7 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -2004,11 +2004,11 @@ lcov-html: wpa_supplicant.gcda lcov -c -d .. > lcov.info genhtml lcov.info --output-directory lcov-html -clean: +clean: common-clean $(MAKE) -C ../src clean $(MAKE) -C dbus clean rm -f core *~ *.o *.d *.gcno *.gcda *.gcov - rm -f eap_*.so $(ALL) $(WINALL) eapol_test preauth_test + rm -f eap_*.so $(WINALL) eapol_test preauth_test rm -f wpa_priv rm -f nfc_pw_token rm -f lcov.info From 0464d5d5d6a5287f4ca5d75f4e9d7abac17bd0ea Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:52 +0200 Subject: [PATCH 0925/1105] build: Move config file handling into build.rules This will make it easier to split out the handling in a proper way, and handle common cflags/dependencies. Signed-off-by: Johannes Berg --- hostapd/Makefile | 13 +------------ src/build.rules | 23 ++++++++++++++++++++++- wpa_supplicant/Makefile | 13 +------------ 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/hostapd/Makefile b/hostapd/Makefile index 2e15c8911..ac83730e9 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -1,5 +1,5 @@ ALL=hostapd hostapd_cli -VERIFY=verify_config +CONFIG_FILE = .config include ../src/build.rules @@ -27,8 +27,6 @@ CFLAGS += -I$(abspath ../src/utils) export BINDIR ?= /usr/local/bin/ --include .config - ifndef CONFIG_NO_GITVER # Add VERSION_STR postfix for builds from a git repository ifeq ($(wildcard ../.git),../.git) @@ -1261,15 +1259,6 @@ ifdef CONFIG_NO_TKIP CFLAGS += -DCONFIG_NO_TKIP endif -verify_config: - @if [ ! -r .config ]; then \ - echo 'Building hostapd requires a configuration file'; \ - echo '(.config). See README for more instructions. You can'; \ - echo 'run "cp defconfig .config" to create an example'; \ - echo 'configuration.'; \ - exit 1; \ - fi - $(DESTDIR)$(BINDIR)/%: % install -D $(<) $(@) diff --git a/src/build.rules b/src/build.rules index 18e23ea53..486fea658 100644 --- a/src/build.rules +++ b/src/build.rules @@ -1,5 +1,5 @@ .PHONY: all -all: $(VERIFY) $(ALL) $(EXTRA_TARGETS) +all: _all # disable built-in rules .SUFFIXES: @@ -23,6 +23,27 @@ ifndef CFLAGS CFLAGS = -MMD -O2 -Wall -g endif +ifneq ($(CONFIG_FILE),) +-include $(CONFIG_FILE) + +.PHONY: verify_config +verify_config: + @if [ ! -r $(CONFIG_FILE) ]; then \ + echo 'Building $(firstword $(ALL)) requires a configuration file'; \ + echo '(.config). See README for more instructions. You can'; \ + echo 'run "cp defconfig .config" to create an example'; \ + echo 'configuration.'; \ + exit 1; \ + fi +VERIFY := verify_config +else +VERIFY := +endif + +# default target +.PHONY: _all +_all: $(VERIFY) $(ALL) $(EXTRA_TARGETS) + Q=@ E=echo ifeq ($(V), 1) diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index b18755bd7..8645d908f 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -14,9 +14,9 @@ ifdef CONFIG_BUILD_WPA_CLIENT_SO ALL += libwpa_client.so endif -VERIFY=verify_config EXTRA_TARGETS=dynamic_eap_methods +CONFIG_FILE=.config include ../src/build.rules ifdef LIBS @@ -39,8 +39,6 @@ CFLAGS += $(EXTRA_CFLAGS) CFLAGS += -I$(abspath ../src) CFLAGS += -I$(abspath ../src/utils) --include .config - ifndef CONFIG_NO_GITVER # Add VERSION_STR postfix for builds from a git repository ifeq ($(wildcard ../.git),../.git) @@ -57,15 +55,6 @@ CONFIG_WPS_TESTING=y CONFIG_TDLS_TESTING=y endif -verify_config: - @if [ ! -r .config ]; then \ - echo 'Building wpa_supplicant requires a configuration file'; \ - echo '(.config). See README for more instructions. You can'; \ - echo 'run "cp defconfig .config" to create an example'; \ - echo 'configuration.'; \ - exit 1; \ - fi - mkconfig: @if [ -f .config ]; then \ echo '.config exists - did not replace it'; \ From 722138cd253f32f66d5da9f7e5a8a57a6448a16d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:53 +0200 Subject: [PATCH 0926/1105] build: Put object files into build/ folder Instead of building in the source tree, put most object files into the build/ folder at the root, and put each thing that's being built into a separate folder. This then allows us to build hostapd and wpa_supplicant (or other combinations) without "make clean" inbetween. For the tests keep the objects in place for now (and to do that, add the build rule) so that we don't have to rewrite all of that with $(call BUILDOBJS,...) which is just noise there. Signed-off-by: Johannes Berg --- .gitignore | 1 + eap_example/Makefile | 18 +++++++++++------- hostapd/Makefile | 22 +++++++++++++++++----- hs20/client/Makefile | 14 +++----------- hs20/server/Makefile | 10 +++------- radius_example/Makefile | 5 +++-- src/ap/Makefile | 4 ++-- src/build.rules | 34 +++++++++++++++++++++++++--------- src/common/Makefile | 4 ++-- src/crypto/Makefile | 4 ++-- src/eap_common/Makefile | 4 ++-- src/eap_peer/Makefile | 4 ++-- src/eap_server/Makefile | 4 ++-- src/eapol_auth/Makefile | 4 ++-- src/eapol_supp/Makefile | 4 ++-- src/l2_packet/Makefile | 4 ++-- src/objs.mk | 3 +++ src/p2p/Makefile | 4 ++-- src/radius/Makefile | 4 ++-- src/rsn_supp/Makefile | 4 ++-- src/tls/Makefile | 4 ++-- src/utils/Makefile | 4 ++-- src/wps/Makefile | 4 ++-- tests/Makefile | 7 +++++++ wlantest/Makefile | 10 +++++++--- wpa_supplicant/Makefile | 34 ++++++++++++++++++++++++++-------- 26 files changed, 136 insertions(+), 82 deletions(-) create mode 100644 src/objs.mk diff --git a/.gitignore b/.gitignore index e057b54ea..52a77fc01 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ wlantest/wlantest wlantest/wlantest_cli **/parallel-vm.log tags +build/ diff --git a/eap_example/Makefile b/eap_example/Makefile index ecef3c976..7660b8ddd 100644 --- a/eap_example/Makefile +++ b/eap_example/Makefile @@ -7,9 +7,9 @@ CFLAGS += -I../src CFLAGS += -I../src/utils -OBJS_both += ../src/utils/libutils.a -OBJS_both += ../src/crypto/libcrypto.a -OBJS_both += ../src/tls/libtls.a +EAP_LIBS += ../src/utils/libutils.a +EAP_LIBS += ../src/crypto/libcrypto.a +EAP_LIBS += ../src/tls/libtls.a OBJS_both += ../src/eap_common/eap_peap_common.o OBJS_both += ../src/eap_common/eap_psk_common.o @@ -83,8 +83,12 @@ CFLAGS += -DEAP_SERVER OBJS_lib=$(OBJS_both) $(OBJS_peer) $(OBJS_server) +_OBJS_VAR := OBJS_lib +include ../src/objs.mk OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o +_OBJS_VAR := OBJS_ex +include ../src/objs.mk ../src/utils/libutils.a: @@ -99,8 +103,8 @@ OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o ifneq ($(CONFIG_SOLIB), yes) LIBEAP = libeap.a -libeap.a: $(OBJS_lib) - $(AR) crT libeap.a $(OBJS_lib) +libeap.a: $(EAP_LIBS) $(OBJS_lib) + $(AR) crT libeap.a $^ $(RANLIB) libeap.a else @@ -108,8 +112,8 @@ CFLAGS += -fPIC -DPIC LDFLAGS += -shared LIBEAP = libeap.so -libeap.so: $(OBJS_lib) - $(LDO) $(LDFLAGS) $(OBJS_lib) -o $(LIBEAP) +libeap.so: $(EAP_LIBS) $(OBJS_lib) + $(LDO) $(LDFLAGS) $^ -o $(LIBEAP) endif diff --git a/hostapd/Makefile b/hostapd/Makefile index ac83730e9..f07acdf24 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -1272,6 +1272,9 @@ install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL)) BCHECK=../src/drivers/build.hostapd +_OBJS_VAR := OBJS +include ../src/objs.mk + hostapd: $(BCHECK) $(OBJS) $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS) @$(E) " LD " $@ @@ -1279,6 +1282,10 @@ hostapd: $(BCHECK) $(OBJS) ifdef CONFIG_WPA_TRACE OBJS_c += ../src/utils/trace.o endif + +_OBJS_VAR := OBJS_c +include ../src/objs.mk + hostapd_cli: $(OBJS_c) $(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c) @$(E) " LD " $@ @@ -1335,6 +1342,13 @@ SOBJS += ../src/crypto/sha256-kdf.o SOBJS += ../src/crypto/sha384-kdf.o SOBJS += ../src/crypto/sha512-kdf.o +_OBJS_VAR := NOBJS +include ../src/objs.mk +_OBJS_VAR := HOBJS +include ../src/objs.mk +_OBJS_VAR := SOBJS +include ../src/objs.mk + nt_password_hash: $(NOBJS) $(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n) @$(E) " LD " $@ @@ -1347,15 +1361,13 @@ sae_pk_gen: $(SOBJS) $(Q)$(CC) $(LDFLAGS) -o sae_pk_gen $(SOBJS) $(LIBS_s) @$(E) " LD " $@ +.PHONY: lcov-html lcov-html: - lcov -c -d .. > lcov.info + lcov -c -d $(BUILDDIR) > lcov.info genhtml lcov.info --output-directory lcov-html clean: common-clean - rm -f core *~ *.o nt_password_hash hlr_auc_gw + rm -f core *~ nt_password_hash hlr_auc_gw rm -f sae_pk_gen - rm -f *.d *.gcno *.gcda *.gcov rm -f lcov.info rm -rf lcov-html - --include $(OBJS:%.o=%.d) diff --git a/hs20/client/Makefile b/hs20/client/Makefile index cbb1105e1..4dcfe2d3b 100644 --- a/hs20/client/Makefile +++ b/hs20/client/Makefile @@ -71,19 +71,11 @@ CFLAGS += -DEAP_TLS_OPENSSL OBJS += ../../src/crypto/tls_openssl_ocsp.o LIBS += -lssl -lcrypto +_OBJS_VAR := OBJS +include ../../src/objs.mk hs20-osu-client: $(OBJS) $(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS) @$(E) " LD " $@ clean: common-clean - rm -f core *~ *.o *.d - rm -f ../../src/utils/*.o - rm -f ../../src/utils/*.d - rm -f ../../src/common/*.o - rm -f ../../src/common/*.d - rm -f ../../src/crypto/*.o - rm -f ../../src/crypto/*.d - rm -f ../../src/wps/*.o - rm -f ../../src/wps/*.d - --include $(OBJS:%.o=%.d) + rm -f core *~ diff --git a/hs20/server/Makefile b/hs20/server/Makefile index 24b81cd8a..0cab6d6b0 100644 --- a/hs20/server/Makefile +++ b/hs20/server/Makefile @@ -33,14 +33,10 @@ CFLAGS += $(shell xml2-config --cflags) LIBS += $(shell xml2-config --libs) OBJS += ../../src/utils/xml_libxml2.o +_OBJS_VAR := OBJS +include ../../src/objs.mk hs20_spp_server: $(OBJS) $(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS) clean: common-clean - rm -f core *~ *.o *.d - rm -f ../../src/utils/*.o - rm -f ../../src/utils/*.d - rm -f ../../src/crypto/*.o - rm -f ../../src/crypto/*.d - --include $(OBJS:%.o=%.d) + rm -f core *~ diff --git a/radius_example/Makefile b/radius_example/Makefile index 3492ac70f..f0e4e535a 100644 --- a/radius_example/Makefile +++ b/radius_example/Makefile @@ -24,10 +24,11 @@ LLIBS = -lrt OBJS_ex = radius_example.o +_OBJS_VAR := OBJS_ex +include ../src/objs.mk + radius_example: $(OBJS_ex) $(LIBS) $(LDO) $(LDFLAGS) -o radius_example $(OBJS_ex) $(LIBS) $(LLIBS) clean: common-clean rm -f core *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/src/ap/Makefile b/src/ap/Makefile index 805181d00..425b12340 100644 --- a/src/ap/Makefile +++ b/src/ap/Makefile @@ -65,7 +65,7 @@ LIB_OBJS= \ wps_hostapd.o \ x_snoop.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libap.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/build.rules b/src/build.rules index 486fea658..4b04eca58 100644 --- a/src/build.rules +++ b/src/build.rules @@ -4,8 +4,13 @@ all: _all # disable built-in rules .SUFFIXES: +# setup some variables ROOTDIR := $(dir $(lastword $(MAKEFILE_LIST))) -ROOTDIR := $(dir $(ROOTDIR:%/=%)) +ROOTDIR := $(dir $(ROOTDIR:%../src/=%))../ +BUILDDIR := $(ROOTDIR)build +_PROJ := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) +ABSROOT := $(abspath $(ROOTDIR)) +_PROJ := $(_PROJ:$(ABSROOT)/%=%) ifndef CC CC=gcc @@ -26,6 +31,9 @@ endif ifneq ($(CONFIG_FILE),) -include $(CONFIG_FILE) +# export for sub-makefiles +export CONFIG_CODE_COVERAGE + .PHONY: verify_config verify_config: @if [ ! -r $(CONFIG_FILE) ]; then \ @@ -44,6 +52,10 @@ endif .PHONY: _all _all: $(VERIFY) $(ALL) $(EXTRA_TARGETS) +# continue setup +COVSUFFIX := $(if $(CONFIG_CODE_COVERAGE),-cov,) +PROJ := $(_PROJ)$(COVSUFFIX) + Q=@ E=echo ifeq ($(V), 1) @@ -59,17 +71,21 @@ ifeq ($(Q),@) MAKEFLAGS += --no-print-directory endif -ifdef CONFIG_CODE_COVERAGE -%.o: %.c - @$(E) " CC " $< - $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<) -else -%.o: %.c +_DIRS := $(BUILDDIR)/$(PROJ) +.PHONY: _make_dirs +_make_dirs: + @mkdir -p $(_DIRS) + +$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c | _make_dirs $(Q)$(CC) -c -o $@ $(CFLAGS) $< @$(E) " CC " $< -endif +$(BUILDDIR)/$(PROJ)/%.o: %.c | _make_dirs + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + @$(E) " CC " $< + +BUILDOBJ = $(patsubst %,$(BUILDDIR)/$(PROJ)/%,$(patsubst $(ROOTDIR)%,%,$(1))) .PHONY: common-clean common-clean: $(Q)$(MAKE) -C $(ROOTDIR)/src clean - $(Q)rm -f $(ALL) + $(Q)rm -rf $(ALL) $(BUILDDIR)/$(PROJ) diff --git a/src/common/Makefile b/src/common/Makefile index eeb69f0d4..4cd48d9fd 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -19,7 +19,7 @@ LIB_OBJS= \ sae.o \ wpa_common.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libcommon.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/crypto/Makefile b/src/crypto/Makefile index 94eac66fa..3af5406ea 100644 --- a/src/crypto/Makefile +++ b/src/crypto/Makefile @@ -66,7 +66,7 @@ LIB_OBJS += random.o endif +_OBJS_VAR := LIB_OBJS +include ../objs.mk libcrypto.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/eap_common/Makefile b/src/eap_common/Makefile index 7d6777bab..49fbbde02 100644 --- a/src/eap_common/Makefile +++ b/src/eap_common/Makefile @@ -23,7 +23,7 @@ LIB_OBJS= \ eap_wsc_common.o \ ikev2_common.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libeap_common.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile index 282b89696..36439b788 100644 --- a/src/eap_peer/Makefile +++ b/src/eap_peer/Makefile @@ -15,7 +15,7 @@ LIB_OBJS= \ eap.o \ eap_methods.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libeap_peer.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/eap_server/Makefile b/src/eap_server/Makefile index 4ece9aa67..946ac195e 100644 --- a/src/eap_server/Makefile +++ b/src/eap_server/Makefile @@ -13,7 +13,7 @@ LIB_OBJS= \ eap_server_identity.o \ eap_server_methods.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libeap_server.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/eapol_auth/Makefile b/src/eapol_auth/Makefile index 0175a19d9..777979ce7 100644 --- a/src/eapol_auth/Makefile +++ b/src/eapol_auth/Makefile @@ -8,7 +8,7 @@ install: LIB_OBJS = eapol_auth_sm.o eapol_auth_dump.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libeapol_auth.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/eapol_supp/Makefile b/src/eapol_supp/Makefile index c98280b46..265e5f25c 100644 --- a/src/eapol_supp/Makefile +++ b/src/eapol_supp/Makefile @@ -10,7 +10,7 @@ CFLAGS += -DIEEE8021X_EAPOL LIB_OBJS = eapol_supp_sm.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libeapol_supp.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/l2_packet/Makefile b/src/l2_packet/Makefile index 20f229511..ab8c86ecc 100644 --- a/src/l2_packet/Makefile +++ b/src/l2_packet/Makefile @@ -8,7 +8,7 @@ install: LIB_OBJS = l2_packet_linux.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libl2_packet.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/objs.mk b/src/objs.mk new file mode 100644 index 000000000..df9fb17a1 --- /dev/null +++ b/src/objs.mk @@ -0,0 +1,3 @@ +$(_OBJS_VAR) := $(call BUILDOBJ,$($(_OBJS_VAR))) +-include $($(_OBJS_VAR):%.o=%.d) +_DIRS += $(dir $($(_OBJS_VAR))) diff --git a/src/p2p/Makefile b/src/p2p/Makefile index 174cf6f6f..c6b406661 100644 --- a/src/p2p/Makefile +++ b/src/p2p/Makefile @@ -21,7 +21,7 @@ LIB_OBJS= \ p2p_sd.o \ p2p_utils.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libp2p.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/radius/Makefile b/src/radius/Makefile index dbe9a9a9f..83096f0c7 100644 --- a/src/radius/Makefile +++ b/src/radius/Makefile @@ -14,7 +14,7 @@ LIB_OBJS= \ radius_das.o \ radius_server.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libradius.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/rsn_supp/Makefile b/src/rsn_supp/Makefile index 255cb73a7..43288e3fd 100644 --- a/src/rsn_supp/Makefile +++ b/src/rsn_supp/Makefile @@ -19,7 +19,7 @@ LIB_OBJS= \ wpa.o \ wpa_ie.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk librsn_supp.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/tls/Makefile b/src/tls/Makefile index 0a36cf9e4..3fac5ee8c 100644 --- a/src/tls/Makefile +++ b/src/tls/Makefile @@ -31,7 +31,7 @@ LIB_OBJS= \ x509v3.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libtls.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/utils/Makefile b/src/utils/Makefile index 29fb1295d..7be05101f 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -34,7 +34,7 @@ LIB_OBJS += edit.o #LIB_OBJS += pcsc_funcs.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libutils.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/src/wps/Makefile b/src/wps/Makefile index 811b62977..ed928ef41 100644 --- a/src/wps/Makefile +++ b/src/wps/Makefile @@ -33,7 +33,7 @@ LIB_OBJS= \ wps_upnp_ssdp.o \ wps_upnp_web.o +_OBJS_VAR := LIB_OBJS +include ../objs.mk libwps.a: $(LIB_OBJS) $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) diff --git a/tests/Makefile b/tests/Makefile index 4d9f2e0ab..4a07a5dc5 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -5,6 +5,13 @@ ALL=test-base64 test-md4 test-milenage \ include ../src/build.rules +# for now, keep building in this folder, otherwise we need to +# put each object for each test into a separate variable and +# then do the objs.mk dance for it ... +%.o: %.c + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + @$(E) " CC " $< + ifdef LIBFUZZER CC=clang CFLAGS = -MMD -O2 -Wall -g diff --git a/wlantest/Makefile b/wlantest/Makefile index fee80f6f4..410c309d4 100644 --- a/wlantest/Makefile +++ b/wlantest/Makefile @@ -71,6 +71,12 @@ TOBJS += gcmp.o OBJS_cli = wlantest_cli.o +_OBJS_VAR := OBJS +include ../src/objs.mk +_OBJS_VAR := TOBJS +include ../src/objs.mk +_OBJS_VAR := OBJS_cli +include ../src/objs.mk wlantest: $(OBJS) $(OWN_LIBS) $(LDO) $(LDFLAGS) -o wlantest $(OBJS) $(OWN_LIBS) $(LIBS) @@ -82,6 +88,4 @@ test_vectors: $(TOBJS) $(OWN_LIBS) $(LDO) $(LDFLAGS) -o test_vectors $(TOBJS) $(OWN_LIBS) $(LIBS) clean: common-clean - rm -f core *~ *.o *.d - --include $(OBJS:%.o=%.d) + rm -f core *~ diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 8645d908f..9f81addd8 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1860,28 +1860,40 @@ dynamic_eap_methods: $(EAPDYN) BCHECK=../src/drivers/build.wpa_supplicant +_OBJS_VAR := OBJS_priv +include ../src/objs.mk wpa_priv: $(BCHECK) $(OBJS_priv) $(Q)$(LDO) $(LDFLAGS) -o wpa_priv $(OBJS_priv) $(LIBS) @$(E) " LD " $@ $(OBJS_c) $(OBJS_t) $(OBJS_t2) $(OBJS) $(BCHECK) $(EXTRA_progs): .config +_OBJS_VAR := OBJS +include ../src/objs.mk wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) @$(E) " LD " $@ +_OBJS_VAR := OBJS_t +include ../src/objs.mk eapol_test: $(OBJS_t) $(Q)$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS) @$(E) " LD " $@ +_OBJS_VAR := OBJS_t2 +include ../src/objs.mk preauth_test: $(OBJS_t2) $(Q)$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS) @$(E) " LD " $@ +_OBJS_VAR := OBJS_p +include ../src/objs.mk wpa_passphrase: $(OBJS_p) $(Q)$(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p) $(LIBS) @$(E) " LD " $@ +_OBJS_VAR := OBJS_c +include ../src/objs.mk wpa_cli: $(OBJS_c) $(Q)$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c) @$(E) " LD " $@ @@ -1895,6 +1907,8 @@ LIBCTRLSO += ../src/utils/os_$(CONFIG_OS).c LIBCTRLSO += ../src/utils/common.c LIBCTRLSO += ../src/utils/wpa_debug.c +_OBJS_VAR := LIBCTRL +include ../src/objs.mk libwpa_client.a: $(LIBCTRL) $(Q)rm -f $@ $(Q)$(AR) crs $@ $? @@ -1904,14 +1918,19 @@ libwpa_client.so: $(LIBCTRLSO) @$(E) " CC $@ ($^)" $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -fPIC $^ -libwpa_test1: libwpa_test.o libwpa_client.a - $(Q)$(LDO) $(LDFLAGS) -o libwpa_test1 libwpa_test.o libwpa_client.a $(LIBS_c) +OBJS_wpatest := libwpa_test.o +_OBJS_VAR := OBJS_wpatest +include ../src/objs.mk +libwpa_test1: $(OBJS_wpatest) libwpa_client.a + $(Q)$(LDO) $(LDFLAGS) -o libwpa_test1 $(OBJS_wpatest) libwpa_client.a $(LIBS_c) @$(E) " LD " $@ -libwpa_test2: libwpa_test.o libwpa_client.so - $(Q)$(LDO) $(LDFLAGS) -o libwpa_test2 libwpa_test.o -L. -lwpa_client $(LIBS_c) +libwpa_test2: $(OBJS_wpatest) libwpa_client.so + $(Q)$(LDO) $(LDFLAGS) -o libwpa_test2 $(OBJS_wpatest) -L. -lwpa_client $(LIBS_c) @$(E) " LD " $@ +_OBJS_VAR := OBJS_nfc +include ../src/objs.mk nfc_pw_token: $(OBJS_nfc) $(Q)$(LDO) $(LDFLAGS) -o nfc_pw_token $(OBJS_nfc) $(LIBS) @$(E) " LD " $@ @@ -1989,8 +2008,9 @@ FIPSLD=$(FIPSDIR)/bin/fipsld fips: $(MAKE) CC=$(FIPSLD) FIPSLD_CC="$(CC)" -lcov-html: wpa_supplicant.gcda - lcov -c -d .. > lcov.info +.PHONY: lcov-html +lcov-html: $(call BUILDOBJ,wpa_supplicant.gcda) + lcov -c -d $(BUILDDIR) > lcov.info genhtml lcov.info --output-directory lcov-html clean: common-clean @@ -2005,5 +2025,3 @@ clean: common-clean rm -f libwpa_client.a rm -f libwpa_client.so rm -f libwpa_test1 libwpa_test2 - --include $(OBJS:%.o=%.d) From 6acda53222d78dafc69863a920c2f5885f462f04 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:54 +0200 Subject: [PATCH 0927/1105] build: Add .config file to dependencies If the .config file changes, basically everything needs to be rebuilt since we don't try to detect which symbols changed or such. Now that the .config file handling is in the common build system, make everything depend on it if there's one. Signed-off-by: Johannes Berg --- src/build.rules | 4 ++-- wpa_supplicant/Makefile | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/build.rules b/src/build.rules index 4b04eca58..bdcae6551 100644 --- a/src/build.rules +++ b/src/build.rules @@ -76,10 +76,10 @@ _DIRS := $(BUILDDIR)/$(PROJ) _make_dirs: @mkdir -p $(_DIRS) -$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c | _make_dirs +$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs $(Q)$(CC) -c -o $@ $(CFLAGS) $< @$(E) " CC " $< -$(BUILDDIR)/$(PROJ)/%.o: %.c | _make_dirs +$(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs $(Q)$(CC) -c -o $@ $(CFLAGS) $< @$(E) " CC " $< diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 9f81addd8..c858f43b5 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1866,8 +1866,6 @@ wpa_priv: $(BCHECK) $(OBJS_priv) $(Q)$(LDO) $(LDFLAGS) -o wpa_priv $(OBJS_priv) $(LIBS) @$(E) " LD " $@ -$(OBJS_c) $(OBJS_t) $(OBJS_t2) $(OBJS) $(BCHECK) $(EXTRA_progs): .config - _OBJS_VAR := OBJS include ../src/objs.mk wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) From ad6e4a5c595982b708f381faad55b2bc591918b0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:55 +0200 Subject: [PATCH 0928/1105] build: Remove hostapd vs. wpa_supplicant build checks These are no longer needed now. Note that this was never actually sufficient since src/drivers/ isn't the only thing shared, and thus a cross-build detection didn't work in all cases. Signed-off-by: Johannes Berg --- hostapd/Makefile | 10 +--------- wpa_supplicant/Makefile | 8 -------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/hostapd/Makefile b/hostapd/Makefile index f07acdf24..555e05f4a 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -1264,18 +1264,10 @@ $(DESTDIR)$(BINDIR)/%: % install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL)) -../src/drivers/build.hostapd: - @if [ -f ../src/drivers/build.wpa_supplicant ]; then \ - $(MAKE) -C ../src/drivers clean; \ - fi - @touch ../src/drivers/build.hostapd - -BCHECK=../src/drivers/build.hostapd - _OBJS_VAR := OBJS include ../src/objs.mk -hostapd: $(BCHECK) $(OBJS) +hostapd: $(OBJS) $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS) @$(E) " LD " $@ diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index c858f43b5..9adadf141 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1852,14 +1852,6 @@ endif dynamic_eap_methods: $(EAPDYN) -../src/drivers/build.wpa_supplicant: - @if [ -f ../src/drivers/build.hostapd ]; then \ - $(MAKE) -C ../src/drivers clean; \ - fi - @touch ../src/drivers/build.wpa_supplicant - -BCHECK=../src/drivers/build.wpa_supplicant - _OBJS_VAR := OBJS_priv include ../src/objs.mk wpa_priv: $(BCHECK) $(OBJS_priv) From e150641f78ff2dc20f2c35bb55fb18c4f5f93eac Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:56 +0200 Subject: [PATCH 0929/1105] tests: Rewrite .gitignore file The file was already outdated again, so rewrite it to ignore anything but c, h and sh files that start with "test-". Signed-off-by: Johannes Berg --- tests/.gitignore | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/tests/.gitignore b/tests/.gitignore index 7bbf25cca..f3c8ac941 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,16 +1,3 @@ -test-aes -test-asn1 -test-base64 -test-https -test-https_server -test-list -test-md4 -test-md5 -test-milenage -test-ms_funcs -test-printf -test-rc4 -test-sha1 -test-sha256 -test-x509 -test-x509v3 +test-* +!test-*.[ch] +!test-*.sh From b3313939b7c147047d4e8d1d08e2f5680da91878 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:49:58 +0200 Subject: [PATCH 0930/1105] tests: Use new build system for the tests I had previously kept that building in the sources, but we can also change that. Signed-off-by: Johannes Berg --- tests/Makefile | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 4a07a5dc5..c8ba3f21c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -5,13 +5,6 @@ ALL=test-base64 test-md4 test-milenage \ include ../src/build.rules -# for now, keep building in this folder, otherwise we need to -# put each object for each test into a separate variable and -# then do the objs.mk dance for it ... -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - ifdef LIBFUZZER CC=clang CFLAGS = -MMD -O2 -Wall -g @@ -98,52 +91,52 @@ LLIBS += -lrt $(MAKE) -C ../src/rsn_supp -test-aes: test-aes.o $(LIBS) +test-aes: $(call BUILDOBJ,test-aes.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-asn1: test-asn1.o $(LIBS) +test-asn1: $(call BUILDOBJ,test-asn1.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-base64: test-base64.o $(LIBS) +test-base64: $(call BUILDOBJ,test-base64.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-eapol: test-eapol.o $(LIBS) +test-eapol: $(call BUILDOBJ,test-eapol.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-https: test-https.o $(LIBS) +test-https: $(call BUILDOBJ,test-https.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-https_server: test-https_server.o $(LIBS) +test-https_server: $(call BUILDOBJ,test-https_server.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-json: test-json.o $(LIBS) +test-json: $(call BUILDOBJ,test-json.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-list: test-list.o $(LIBS) +test-list: $(call BUILDOBJ,test-list.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-md4: test-md4.o $(LIBS) +test-md4: $(call BUILDOBJ,test-md4.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-milenage: test-milenage.o $(LIBS) +test-milenage: $(call BUILDOBJ,test-milenage.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-rc4: test-rc4.o $(LIBS) +test-rc4: $(call BUILDOBJ,test-rc4.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-rsa-sig-ver: test-rsa-sig-ver.o $(LIBS) +test-rsa-sig-ver: $(call BUILDOBJ,test-rsa-sig-ver.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-sha1: test-sha1.o $(LIBS) +test-sha1: $(call BUILDOBJ,test-sha1.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-sha256: test-sha256.o $(LIBS) +test-sha256: $(call BUILDOBJ,test-sha256.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-tls: test-tls.o $(LIBS) +test-tls: $(call BUILDOBJ,test-tls.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-x509v3: test-x509v3.o $(LIBS) +test-x509v3: $(call BUILDOBJ,test-x509v3.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) @@ -159,12 +152,10 @@ run-tests: $(ALL) @echo All tests completed successfully. clean: common-clean - rm -f *~ *.o *.d + rm -f *~ rm -f test-eapol rm -f test-https rm -f test-json rm -f test-tls rm -f test_x509v3_nist.out.* rm -f test_x509v3_nist2.out.* - --include $(OBJS:%.o=%.d) From ce963433bd9316eaf825ba5d20d84404adf786e1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:50:00 +0200 Subject: [PATCH 0931/1105] build: Allow overriding BUILDDIR from command line You can now specify BUILDDIR= on the make command line, e.g., in order to put that into a tmpfs or similar. Signed-off-by: Johannes Berg --- src/build.rules | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/build.rules b/src/build.rules index bdcae6551..32f45ae1e 100644 --- a/src/build.rules +++ b/src/build.rules @@ -7,7 +7,8 @@ all: _all # setup some variables ROOTDIR := $(dir $(lastword $(MAKEFILE_LIST))) ROOTDIR := $(dir $(ROOTDIR:%../src/=%))../ -BUILDDIR := $(ROOTDIR)build +BUILDDIR ?= $(abspath $(ROOTDIR)build) +BUILDDIR := $(BUILDDIR:%/=%) _PROJ := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) ABSROOT := $(abspath $(ROOTDIR)) _PROJ := $(_PROJ:$(ABSROOT)/%=%) From dcc5288e5b300bfaac826e437bee26f0d75b6b38 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 18 Sep 2020 11:50:01 +0200 Subject: [PATCH 0932/1105] gitignore: Add various things Signed-off-by: Johannes Berg --- tests/fuzzing/ap-mgmt/.gitignore | 1 + tests/fuzzing/asn1/.gitignore | 1 + tests/fuzzing/dpp-uri/.gitignore | 1 + tests/fuzzing/eap-aka-peer/.gitignore | 1 + tests/fuzzing/eap-mschapv2-peer/.gitignore | 1 + tests/fuzzing/eap-sim-peer/.gitignore | 1 + tests/fuzzing/eapol-key-auth/.gitignore | 1 + tests/fuzzing/eapol-key-supp/.gitignore | 1 + tests/fuzzing/eapol-supp/.gitignore | 1 + tests/fuzzing/json/.gitignore | 1 + tests/fuzzing/p2p/.gitignore | 1 + tests/fuzzing/sae/.gitignore | 1 + tests/fuzzing/tls-client/.gitignore | 1 + tests/fuzzing/tls-server/.gitignore | 1 + tests/fuzzing/wnm/.gitignore | 1 + tests/fuzzing/x509/.gitignore | 1 + tests/p2p-fuzzer/.gitignore | 1 + wpa_supplicant/doc/docbook/.gitignore | 1 + wpa_supplicant/wpa_gui-qt4/icons/.gitignore | 2 ++ 19 files changed, 20 insertions(+) create mode 100644 tests/fuzzing/ap-mgmt/.gitignore create mode 100644 tests/fuzzing/asn1/.gitignore create mode 100644 tests/fuzzing/dpp-uri/.gitignore create mode 100644 tests/fuzzing/eap-aka-peer/.gitignore create mode 100644 tests/fuzzing/eap-mschapv2-peer/.gitignore create mode 100644 tests/fuzzing/eap-sim-peer/.gitignore create mode 100644 tests/fuzzing/eapol-key-auth/.gitignore create mode 100644 tests/fuzzing/eapol-key-supp/.gitignore create mode 100644 tests/fuzzing/eapol-supp/.gitignore create mode 100644 tests/fuzzing/json/.gitignore create mode 100644 tests/fuzzing/p2p/.gitignore create mode 100644 tests/fuzzing/sae/.gitignore create mode 100644 tests/fuzzing/tls-client/.gitignore create mode 100644 tests/fuzzing/tls-server/.gitignore create mode 100644 tests/fuzzing/wnm/.gitignore create mode 100644 tests/fuzzing/x509/.gitignore create mode 100644 tests/p2p-fuzzer/.gitignore create mode 100644 wpa_supplicant/wpa_gui-qt4/icons/.gitignore diff --git a/tests/fuzzing/ap-mgmt/.gitignore b/tests/fuzzing/ap-mgmt/.gitignore new file mode 100644 index 000000000..8d79d3c80 --- /dev/null +++ b/tests/fuzzing/ap-mgmt/.gitignore @@ -0,0 +1 @@ +ap-mgmt diff --git a/tests/fuzzing/asn1/.gitignore b/tests/fuzzing/asn1/.gitignore new file mode 100644 index 000000000..69d0e5c72 --- /dev/null +++ b/tests/fuzzing/asn1/.gitignore @@ -0,0 +1 @@ +asn1 diff --git a/tests/fuzzing/dpp-uri/.gitignore b/tests/fuzzing/dpp-uri/.gitignore new file mode 100644 index 000000000..6dd276499 --- /dev/null +++ b/tests/fuzzing/dpp-uri/.gitignore @@ -0,0 +1 @@ +dpp-uri diff --git a/tests/fuzzing/eap-aka-peer/.gitignore b/tests/fuzzing/eap-aka-peer/.gitignore new file mode 100644 index 000000000..d11f75fe3 --- /dev/null +++ b/tests/fuzzing/eap-aka-peer/.gitignore @@ -0,0 +1 @@ +eap-aka-peer diff --git a/tests/fuzzing/eap-mschapv2-peer/.gitignore b/tests/fuzzing/eap-mschapv2-peer/.gitignore new file mode 100644 index 000000000..3368b213c --- /dev/null +++ b/tests/fuzzing/eap-mschapv2-peer/.gitignore @@ -0,0 +1 @@ +eap-mschapv2-peer diff --git a/tests/fuzzing/eap-sim-peer/.gitignore b/tests/fuzzing/eap-sim-peer/.gitignore new file mode 100644 index 000000000..ea94e26e2 --- /dev/null +++ b/tests/fuzzing/eap-sim-peer/.gitignore @@ -0,0 +1 @@ +eap-sim-peer diff --git a/tests/fuzzing/eapol-key-auth/.gitignore b/tests/fuzzing/eapol-key-auth/.gitignore new file mode 100644 index 000000000..f693f2cd0 --- /dev/null +++ b/tests/fuzzing/eapol-key-auth/.gitignore @@ -0,0 +1 @@ +eapol-key-auth diff --git a/tests/fuzzing/eapol-key-supp/.gitignore b/tests/fuzzing/eapol-key-supp/.gitignore new file mode 100644 index 000000000..dcbbbdb02 --- /dev/null +++ b/tests/fuzzing/eapol-key-supp/.gitignore @@ -0,0 +1 @@ +eapol-key-supp diff --git a/tests/fuzzing/eapol-supp/.gitignore b/tests/fuzzing/eapol-supp/.gitignore new file mode 100644 index 000000000..e370093d8 --- /dev/null +++ b/tests/fuzzing/eapol-supp/.gitignore @@ -0,0 +1 @@ +eapol-supp diff --git a/tests/fuzzing/json/.gitignore b/tests/fuzzing/json/.gitignore new file mode 100644 index 000000000..3c840093b --- /dev/null +++ b/tests/fuzzing/json/.gitignore @@ -0,0 +1 @@ +json diff --git a/tests/fuzzing/p2p/.gitignore b/tests/fuzzing/p2p/.gitignore new file mode 100644 index 000000000..8bea15da4 --- /dev/null +++ b/tests/fuzzing/p2p/.gitignore @@ -0,0 +1 @@ +p2p diff --git a/tests/fuzzing/sae/.gitignore b/tests/fuzzing/sae/.gitignore new file mode 100644 index 000000000..1bb959165 --- /dev/null +++ b/tests/fuzzing/sae/.gitignore @@ -0,0 +1 @@ +sae diff --git a/tests/fuzzing/tls-client/.gitignore b/tests/fuzzing/tls-client/.gitignore new file mode 100644 index 000000000..b41f93681 --- /dev/null +++ b/tests/fuzzing/tls-client/.gitignore @@ -0,0 +1 @@ +tls-client diff --git a/tests/fuzzing/tls-server/.gitignore b/tests/fuzzing/tls-server/.gitignore new file mode 100644 index 000000000..341256f57 --- /dev/null +++ b/tests/fuzzing/tls-server/.gitignore @@ -0,0 +1 @@ +tls-server diff --git a/tests/fuzzing/wnm/.gitignore b/tests/fuzzing/wnm/.gitignore new file mode 100644 index 000000000..0e1d383dc --- /dev/null +++ b/tests/fuzzing/wnm/.gitignore @@ -0,0 +1 @@ +wnm diff --git a/tests/fuzzing/x509/.gitignore b/tests/fuzzing/x509/.gitignore new file mode 100644 index 000000000..490a5d71f --- /dev/null +++ b/tests/fuzzing/x509/.gitignore @@ -0,0 +1 @@ +x509 diff --git a/tests/p2p-fuzzer/.gitignore b/tests/p2p-fuzzer/.gitignore new file mode 100644 index 000000000..ee9420df0 --- /dev/null +++ b/tests/p2p-fuzzer/.gitignore @@ -0,0 +1 @@ +p2p-fuzzer diff --git a/wpa_supplicant/doc/docbook/.gitignore b/wpa_supplicant/doc/docbook/.gitignore index 8c3945c52..dac35c5a5 100644 --- a/wpa_supplicant/doc/docbook/.gitignore +++ b/wpa_supplicant/doc/docbook/.gitignore @@ -1,5 +1,6 @@ manpage.links manpage.refs +manpage.log *.8 *.5 *.html diff --git a/wpa_supplicant/wpa_gui-qt4/icons/.gitignore b/wpa_supplicant/wpa_gui-qt4/icons/.gitignore new file mode 100644 index 000000000..8d772cc93 --- /dev/null +++ b/wpa_supplicant/wpa_gui-qt4/icons/.gitignore @@ -0,0 +1,2 @@ +hicolor +pixmaps From 6d6310701b2b9e3ee5dcf06b3b393074072bc225 Mon Sep 17 00:00:00 2001 From: Yogesh Kulkarni Date: Wed, 10 Jun 2020 01:02:40 +0530 Subject: [PATCH 0933/1105] Fix STA mode default TXOP Limit values for AC_VI and AC_VO commit f4e3860f ("Fix AP mode default TXOP Limit values for AC_VI and AC_VO") corrects the default values of txop_limit from 93/46 to 94/47 for AP. STA would also need the same change. Signed-off-by: Yogesh Kulkarni Signed-off-by: Cathy Luo Signed-off-by: Ganapathi Bhat --- wpa_supplicant/config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index b828b599f..8e79cab20 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4264,9 +4264,9 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, const struct hostapd_wmm_ac_params ac_be = { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ - { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 }; + { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 }; const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ - { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 }; + { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 }; const struct hostapd_tx_queue_params txq_bk = { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; const struct hostapd_tx_queue_params txq_be = From 5653301409b7d8fcc76b4052032f5534bff51e9e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Oct 2020 18:33:57 +0300 Subject: [PATCH 0934/1105] tests: Prepare ap_blacklist_all for implementation change The blacklist design will be modified in the following commits and that would result in this validation step based on the older implementation starting to fail. Remove this check to avoid such testing failures. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_roam.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/hwsim/test_ap_roam.py b/tests/hwsim/test_ap_roam.py index 50b4c7248..fca3b57c5 100644 --- a/tests/hwsim/test_ap_roam.py +++ b/tests/hwsim/test_ap_roam.py @@ -44,8 +44,7 @@ def test_ap_blacklist_all(dev, apdev, params): if not dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10): raise Exception("AP 1 didn't reject us") blacklist = get_blacklist(dev[0]) - if len(blacklist) != 2: - raise Exception("Unexpected blacklist: %s" % blacklist) + logger.info("blacklist: " + str(blacklist)) dev[0].request("REMOVE_NETWORK all") dev[0].dump_monitor() From 2fd35d98575dd251653b9470f75409f6c8af3ff1 Mon Sep 17 00:00:00 2001 From: Kevin Lund Date: Thu, 11 Jun 2020 14:11:15 -0700 Subject: [PATCH 0935/1105] wpa_supplicant: Track consecutive connection failures Within wpas_connection_failed(), the 'count' value of wpa_blacklist is erroneously used as a tally of the number times the device has failed to associate to a given BSSID without making a successful connection. This is not accurate because there are a variety of ways a BSS can be added to the blacklist beyond failed association such as interference or deauthentication. This 'count' is lost whenever the blacklist is cleared, so the wpa_supplicant stores an additional value 'extra_blacklist_count' which helps persist the 'count' through clears. These count values are used to determine how long to wait to rescan after a failed connection attempt. While this logic was already slightly wrong, it would have been completely broken by the upcoming change which adds time-based blacklisting functionality. With the upcoming change, 'count' values are not cleared on association, and thus do not necessarily even approximate the "consecutive connection failures" which they were being used for. This change seeks to remove this unnecessary overloading of the blacklist 'count' by directly tracking consecutive connection failures within the wpa_supplicant struct, independent of the blacklist. This new 'consecutive_conn_failures' is iterated with every connection failure and cleared when any successful connection is made. This change also removes the now unused 'extra_blacklist_count' value. Signed-off-by: Kevin Lund Signed-off-by: Brian Norris --- wpa_supplicant/blacklist.c | 5 ----- wpa_supplicant/ctrl_iface.c | 3 ++- wpa_supplicant/wpa_supplicant.c | 28 ++++++++++++---------------- wpa_supplicant/wpa_supplicant_i.h | 13 ++----------- wpa_supplicant/wps_supplicant.c | 2 +- 5 files changed, 17 insertions(+), 34 deletions(-) diff --git a/wpa_supplicant/blacklist.c b/wpa_supplicant/blacklist.c index e53dc38b3..2e01e7fea 100644 --- a/wpa_supplicant/blacklist.c +++ b/wpa_supplicant/blacklist.c @@ -123,19 +123,14 @@ int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid) void wpa_blacklist_clear(struct wpa_supplicant *wpa_s) { struct wpa_blacklist *e, *prev; - int max_count = 0; e = wpa_s->blacklist; wpa_s->blacklist = NULL; while (e) { - if (e->count > max_count) - max_count = e->count; prev = e; e = e->next; wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " "blacklist (clear)", MAC2STR(prev->bssid)); os_free(prev); } - - wpa_s->extra_blacklist_count += max_count; } diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 7df7ba0d1..1bb18bdd1 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8418,9 +8418,10 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->set_sta_uapsd = 0; wpa_s->sta_uapsd = 0; + wpa_s->consecutive_conn_failures = 0; + wpa_drv_radio_disable(wpa_s, 0); wpa_blacklist_clear(wpa_s); - wpa_s->extra_blacklist_count = 0; wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all"); wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all"); wpa_config_flush_blobs(wpa_s->conf); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index a52b9a9e1..29c5d34e7 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -985,7 +985,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ wpas_clear_temp_disabled(wpa_s, ssid, 1); wpa_blacklist_clear(wpa_s); - wpa_s->extra_blacklist_count = 0; + wpa_s->consecutive_conn_failures = 0; wpa_s->new_connection = 0; wpa_drv_set_operstate(wpa_s, 1); #ifndef IEEE8021X_EAPOL @@ -7373,10 +7373,6 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) /* * Add the failed BSSID into the blacklist and speed up next scan * attempt if there could be other APs that could accept association. - * The current blacklist count indicates how many times we have tried - * connecting to this AP and multiple attempts mean that other APs are - * either not available or has already been tried, so that we can start - * increasing the delay here to avoid constant scanning. */ count = wpa_blacklist_add(wpa_s, bssid); if (count == 1 && wpa_s->current_bss) { @@ -7401,19 +7397,19 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) } } - /* - * Add previous failure count in case the temporary blacklist was - * cleared due to no other BSSes being available. - */ - count += wpa_s->extra_blacklist_count; + wpa_s->consecutive_conn_failures++; - if (count > 3 && wpa_s->current_ssid) { + if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) { wpa_printf(MSG_DEBUG, "Continuous association failures - " "consider temporary network disabling"); wpas_auth_failed(wpa_s, "CONN_FAILED"); } - - switch (count) { + /* + * Multiple consecutive connection failures mean that other APs are + * either not available or have already been tried, so we can start + * increasing the delay here to avoid constant scanning. + */ + switch (wpa_s->consecutive_conn_failures) { case 1: timeout = 100; break; @@ -7431,8 +7427,9 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) break; } - wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d " - "ms", count, timeout); + wpa_dbg(wpa_s, MSG_DEBUG, + "Consecutive connection failures: %d --> request scan in %d ms", + wpa_s->consecutive_conn_failures, timeout); /* * TODO: if more than one possible AP is available in scan results, @@ -7796,7 +7793,6 @@ void wpas_request_connection(struct wpa_supplicant *wpa_s) wpa_s->normal_scans = 0; wpa_s->scan_req = NORMAL_SCAN_REQ; wpa_supplicant_reinit_autoscan(wpa_s); - wpa_s->extra_blacklist_count = 0; wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_s->last_owe_group = 0; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index e8778bbf9..2df45c62c 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -666,17 +666,8 @@ struct wpa_supplicant { struct wpa_blacklist *blacklist; - /** - * extra_blacklist_count - Sum of blacklist counts after last connection - * - * This variable is used to maintain a count of temporary blacklisting - * failures (maximum number for any BSS) over blacklist clear - * operations. This is needed for figuring out whether there has been - * failures prior to the last blacklist clear operation which happens - * whenever no other not-blacklisted BSS candidates are available. This - * gets cleared whenever a connection has been established successfully. - */ - int extra_blacklist_count; + /* Number of connection failures since last successful connection */ + unsigned int consecutive_conn_failures; /** * scan_req - Type of the scan request diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index b7680f088..613fe2b6a 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -720,7 +720,7 @@ static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s) wpas_notify_wps_event_success(wpa_s); if (wpa_s->current_ssid) wpas_clear_temp_disabled(wpa_s, wpa_s->current_ssid, 1); - wpa_s->extra_blacklist_count = 0; + wpa_s->consecutive_conn_failures = 0; /* * Enable the networks disabled during wpas_wps_reassoc after 10 From d530110028f0c343085c1c605d80f5d0da55c274 Mon Sep 17 00:00:00 2001 From: Kevin Lund Date: Thu, 11 Jun 2020 14:11:16 -0700 Subject: [PATCH 0936/1105] wpa_supplicant: Implement time-based blacklisting wpa_supplicant keeps a blacklist of BSSs in order to prevent repeated associations to problematic APs*. Currently, this blacklist is completely cleared whenever we successfully connect to any AP. This causes problematic behavior when in the presence of both a bad AP and a good AP. The device can repeatedly attempt to roam to the bad AP because it is clearing the blacklist every time it connects to the good AP. This results in the connection constantly ping-ponging between the APs, leaving the user stuck without connection. Instead of clearing the blacklist, implement timeout functionality which allows association attempts to blacklisted APs after some time has passed. Each time a BSS would be added to the blacklist, increase the duration of this timeout exponentially, up to a cap of 1800 seconds. This means that the device will no longer be able to immediately attempt to roam back to a bad AP whenever it successfully connects to any other AP. Other details: The algorithm for building up the blacklist count and timeout duration on a given AP has been designed to be minimally obtrusive. Starting with a fresh blacklist, the device may attempt to connect to a problematic AP no more than 6 times in any ~45 minute period. Once an AP has reached a blacklist count >= 6, the device may attempt to connect to it no more than once every 30 minutes. The goal of these limits is to find an ideal balance between minimizing connection attempts to bad APs while still trying them out occasionally to see if the problems have stopped. The only exception to the above limits is that the blacklist is still completely cleared whenever there are no APs available in a scan. This means that if all nearby APs have been blacklisted, all APs will be completely exonerated regardless of their blacklist counts or how close their blacklist entries are to expiring. When all nearby APs have been blacklisted we know that every nearby AP is in some way problematic. Once we know that every AP is causing problems, it doesn't really make sense to sort them beyond that because the blacklist count and timeout duration don't necessarily reflect the degree to which an AP is problematic (i.e. they can be manipulated by external factors such as the user physically moving around). Instead, its best to restart the blacklist and let the normal roaming algorithm take over to maximize our chance of getting the best possible connection quality. As stated above, the time-based blacklisting algorithm is designed to be minimally obtrusive to user experience, so occasionally restarting the process is not too impactful on the user. *problematic AP: rejects new clients, frequently de-auths clients, very poor connection quality, etc. Signed-off-by: Kevin Lund Signed-off-by: Brian Norris --- wpa_supplicant/blacklist.c | 47 +++++++++++++++++++++++++++++---- wpa_supplicant/blacklist.h | 8 ++++++ wpa_supplicant/events.c | 24 ++++++++--------- wpa_supplicant/wpa_supplicant.c | 3 +-- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/wpa_supplicant/blacklist.c b/wpa_supplicant/blacklist.c index 2e01e7fea..c88a69acd 100644 --- a/wpa_supplicant/blacklist.c +++ b/wpa_supplicant/blacklist.c @@ -56,16 +56,29 @@ struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid) { struct wpa_blacklist *e; + struct os_reltime now; if (wpa_s == NULL || bssid == NULL) return -1; e = wpa_blacklist_get(wpa_s, bssid); + os_get_reltime(&now); if (e) { + e->blacklist_start = now; e->count++; - wpa_printf(MSG_DEBUG, "BSSID " MACSTR " blacklist count " - "incremented to %d", - MAC2STR(bssid), e->count); + if (e->count > 5) + e->timeout_secs = 1800; + else if (e->count == 5) + e->timeout_secs = 600; + else if (e->count == 4) + e->timeout_secs = 120; + else if (e->count == 3) + e->timeout_secs = 60; + else + e->timeout_secs = 10; + wpa_printf(MSG_INFO, "BSSID " MACSTR + " blacklist count incremented to %d, blacklisting for %d seconds", + MAC2STR(bssid), e->count, e->timeout_secs); return e->count; } @@ -74,10 +87,13 @@ int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid) return -1; os_memcpy(e->bssid, bssid, ETH_ALEN); e->count = 1; + e->timeout_secs = 10; + e->blacklist_start = now; e->next = wpa_s->blacklist; wpa_s->blacklist = e; - wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR " into blacklist", - MAC2STR(bssid)); + wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR + " into blacklist, blacklisting for %d seconds", + MAC2STR(bssid), e->timeout_secs); return e->count; } @@ -116,6 +132,27 @@ int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid) } +/** + * wpa_blacklist_is_blacklisted - Check the blacklist status of a BSS + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID to be checked + * Returns: count if BSS is currently considered to be blacklisted, 0 otherwise + */ +int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid) +{ + struct wpa_blacklist *e; + struct os_reltime now; + + e = wpa_blacklist_get(wpa_s, bssid); + if (!e) + return 0; + os_get_reltime(&now); + if (os_reltime_expired(&now, &e->blacklist_start, e->timeout_secs)) + return 0; + return e->count; +} + + /** * wpa_blacklist_clear - Clear the blacklist of all entries * @wpa_s: Pointer to wpa_supplicant data diff --git a/wpa_supplicant/blacklist.h b/wpa_supplicant/blacklist.h index ae06986f3..54ca6a37f 100644 --- a/wpa_supplicant/blacklist.h +++ b/wpa_supplicant/blacklist.h @@ -13,12 +13,20 @@ struct wpa_blacklist { struct wpa_blacklist *next; u8 bssid[ETH_ALEN]; int count; + /* Time of most recent blacklist event. */ + struct os_reltime blacklist_start; + /* + * Number of seconds after blacklist_start that the entry will be + * considered blacklisted. + */ + int timeout_secs; }; struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid); +int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid); void wpa_blacklist_clear(struct wpa_supplicant *wpa_s); #endif /* BLACKLIST_H */ diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 7b7802c46..1b46a9715 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1085,7 +1085,7 @@ static int disabled_freq(struct wpa_supplicant *wpa_s, int freq) static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, const u8 *match_ssid, size_t match_ssid_len, - struct wpa_bss *bss, struct wpa_blacklist *e, + struct wpa_bss *bss, int blacklist_count, bool debug_print); @@ -1099,7 +1099,7 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s, struct wpa_bss *bss; dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { - struct wpa_blacklist *e; + int count; const u8 *ie; u8 rsnxe_capa = 0; @@ -1117,9 +1117,9 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s, if (bss->est_throughput < 2000) return false; - e = wpa_blacklist_get(wpa_s, bss->bssid); + count = wpa_blacklist_is_blacklisted(wpa_s, bss->bssid); if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len, - bss, e, 0)) + bss, count, 0)) return true; } @@ -1130,7 +1130,7 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s, static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, const u8 *match_ssid, size_t match_ssid_len, - struct wpa_bss *bss, struct wpa_blacklist *e, + struct wpa_bss *bss, int blacklist_count, bool debug_print) { int res; @@ -1178,7 +1178,7 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, } #ifdef CONFIG_WPS - if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) { + if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && blacklist_count) { if (debug_print) wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted (WPS)"); @@ -1472,12 +1472,12 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int only_first_ssid, int debug_print) { u8 wpa_ie_len, rsn_ie_len; - struct wpa_blacklist *e; const u8 *ie; struct wpa_ssid *ssid; int osen; const u8 *match_ssid; size_t match_ssid_len; + int blacklist_count; ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie_len = ie ? ie[1] : 0; @@ -1503,8 +1503,8 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, osen ? " osen=1" : ""); } - e = wpa_blacklist_get(wpa_s, bss->bssid); - if (e) { + blacklist_count = wpa_blacklist_is_blacklisted(wpa_s, bss->bssid); + if (blacklist_count) { int limit = 1; if (wpa_supplicant_enabled_networks(wpa_s) == 1) { /* @@ -1517,11 +1517,11 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, */ limit = 0; } - if (e->count > limit) { + if (blacklist_count > limit) { if (debug_print) { wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted (count=%d limit=%d)", - e->count, limit); + blacklist_count, limit); } return NULL; } @@ -1557,7 +1557,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) { if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len, - bss, e, debug_print)) + bss, blacklist_count, debug_print)) return ssid; } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 29c5d34e7..30fb04786 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -984,7 +984,6 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, fils_hlp_sent ? " FILS_HLP_SENT" : ""); #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ wpas_clear_temp_disabled(wpa_s, ssid, 1); - wpa_blacklist_clear(wpa_s); wpa_s->consecutive_conn_failures = 0; wpa_s->new_connection = 0; wpa_drv_set_operstate(wpa_s, 1); @@ -7324,7 +7323,7 @@ static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s) continue; if (bss->ssid_len == cbss->ssid_len && os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 && - wpa_blacklist_get(wpa_s, bss->bssid) == NULL) { + !wpa_blacklist_is_blacklisted(wpa_s, bss->bssid)) { add_freq(freqs, &num_freqs, bss->freq); if (num_freqs == max_freqs) break; From 164b8dd8e4be8a563cf18a1cdc2929a552dbfc34 Mon Sep 17 00:00:00 2001 From: Kevin Lund Date: Thu, 11 Jun 2020 14:11:17 -0700 Subject: [PATCH 0937/1105] wpa_supplicant: Add wpa_blacklist_update() This change adds the function wpa_blacklist_update(), which goes through all blacklist entries and deletes them if their blacklist expired over an hour ago. The purpose of this is to remove stale entries from the blacklist which likely do not reflect the current condition of device's network surroundings. This function is called whenever the blacklist is polled, meaning that the caller always gets an up-to-date reflection of the blacklist. Another solution to clearing the blacklist that was considered was to slowly reduce the counts of blacklist entries over time, and delete them if the counts dropped below 0. We decided to go with the current solution instead because an AP's "problematic" status is really a binary thing: either the AP is no longer problematic, or it's still causing us problems. So if we see any more problems within a reasonable amount of time, it makes sense to just keep the blacklist where it was since the AP is likely still undergoing the same issue. If we go a significant amount of time (semi-arbitrarily chosen as 1 hour) without any issues with an AP, it's reasonable to behave as if the AP is no longer undergoing the same issue. If we see more problems at a later time, we can start the blacklisting process fresh again, treating this as a brand new issue. Signed-off-by: Kevin Lund Signed-off-by: Brian Norris --- wpa_supplicant/blacklist.c | 41 ++++++++++++++++++++++++++++++++++++++ wpa_supplicant/blacklist.h | 1 + 2 files changed, 42 insertions(+) diff --git a/wpa_supplicant/blacklist.c b/wpa_supplicant/blacklist.c index c88a69acd..fa2ad11ee 100644 --- a/wpa_supplicant/blacklist.c +++ b/wpa_supplicant/blacklist.c @@ -26,6 +26,8 @@ struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, if (wpa_s == NULL || bssid == NULL) return NULL; + wpa_blacklist_update(wpa_s); + e = wpa_s->blacklist; while (e) { if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) @@ -171,3 +173,42 @@ void wpa_blacklist_clear(struct wpa_supplicant *wpa_s) os_free(prev); } } + + +/** + * wpa_blacklist_update - Update the entries in the blacklist, + * deleting entries that have been expired for over an hour. + * @wpa_s: Pointer to wpa_supplicant data + */ +void wpa_blacklist_update(struct wpa_supplicant *wpa_s) +{ + struct wpa_blacklist *e, *prev = NULL; + struct os_reltime now; + + if (!wpa_s) + return; + + e = wpa_s->blacklist; + os_get_reltime(&now); + while (e) { + if (os_reltime_expired(&now, &e->blacklist_start, + e->timeout_secs + 3600)) { + struct wpa_blacklist *to_delete = e; + + if (prev) { + prev->next = e->next; + e = prev->next; + } else { + wpa_s->blacklist = e->next; + e = wpa_s->blacklist; + } + wpa_printf(MSG_INFO, "Removed BSSID " MACSTR + " from blacklist (expired)", + MAC2STR(to_delete->bssid)); + os_free(to_delete); + } else { + prev = e; + e = e->next; + } + } +} diff --git a/wpa_supplicant/blacklist.h b/wpa_supplicant/blacklist.h index 54ca6a37f..a1c60d5e6 100644 --- a/wpa_supplicant/blacklist.h +++ b/wpa_supplicant/blacklist.h @@ -28,5 +28,6 @@ int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid); void wpa_blacklist_clear(struct wpa_supplicant *wpa_s); +void wpa_blacklist_update(struct wpa_supplicant *wpa_s); #endif /* BLACKLIST_H */ From bbbb3c04ef735bdb75f4554dc2bb4a5e937dd09c Mon Sep 17 00:00:00 2001 From: Kevin Lund Date: Thu, 11 Jun 2020 14:11:18 -0700 Subject: [PATCH 0938/1105] wpa_supplicant: Add new blacklist tests This change adds some barebones tests for new blacklisting functionality to wpas_module_tests.c. The tests ensure some basic functionality for the functions wpa_blacklist_is_blacklisted() and wpa_blacklist_update(). Signed-off-by: Kevin Lund Signed-off-by: Brian Norris --- wpa_supplicant/wpas_module_tests.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/wpa_supplicant/wpas_module_tests.c b/wpa_supplicant/wpas_module_tests.c index 4e37591be..1c136f782 100644 --- a/wpa_supplicant/wpas_module_tests.c +++ b/wpa_supplicant/wpas_module_tests.c @@ -59,6 +59,23 @@ static int wpas_blacklist_module_tests(void) wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0) goto fail; + wpa_blacklist_clear(&wpa_s); + + if (wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 || + wpa_blacklist_add(&wpa_s, (u8 *) "222222") < 0 || + wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0 || + wpa_blacklist_add(&wpa_s, (u8 *) "444444") < 0 || + !wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111") || + wpa_blacklist_del(&wpa_s, (u8 *) "111111") < 0 || + wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111") || + wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0) + goto fail; + + wpa_blacklist_update(&wpa_s); + + if (!wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111")) + goto fail; + ret = 0; fail: wpa_blacklist_clear(&wpa_s); From cff545720ecd41f9fb56752bf22ef8fde0e237e1 Mon Sep 17 00:00:00 2001 From: Kevin Lund Date: Thu, 11 Jun 2020 14:11:19 -0700 Subject: [PATCH 0939/1105] wpa_supplicant: Clear blacklist when SSID configs change If the stored configurations for an SSID have changed, we can no longer trust the current blacklist state of that SSID, since the updated configs could change the behavior of the network. E.g., the BSS could be blacklisted due to a bad password, and the config could be updated to store the correct password. In this case, keeping the BSS in the blacklist will prevent the user from connecting to the BSS after the correct password has been updated. Add the value was_changed_recently to the wpa_ssid struct. Update this value every time a config is changed through wpa_set_config(). Check this value in wpa_blacklist_get() to clear the blacklist whenever the configs of current_ssid have changed. This solution was chosen over simply clearing the blacklist whenever configs change because the user should be able to change configs on an inactive SSID without affecting the blacklist for the currently active SSID. This way, the blacklist won't be cleared until the user attempts to connect to the inactive network again. Furthermore, the blacklist is stored per-BSSID while configs are stored per-SSID, so we don't have the option to just clear out certain blacklist entries that would be affected by the configs. Finally, the function wpa_supplicant_reload_configuration() causes the configs to be reloaded from scratch, so after a call to this function all bets are off as to the relevance of our current blacklist state. Thus, we clear the entire blacklist within this function. Signed-off-by: Kevin Lund Signed-off-by: Brian Norris --- wpa_supplicant/blacklist.c | 7 +++++++ wpa_supplicant/config.c | 1 + wpa_supplicant/config_ssid.h | 9 +++++++++ wpa_supplicant/wpa_supplicant.c | 1 + 4 files changed, 18 insertions(+) diff --git a/wpa_supplicant/blacklist.c b/wpa_supplicant/blacklist.c index fa2ad11ee..2f326444b 100644 --- a/wpa_supplicant/blacklist.c +++ b/wpa_supplicant/blacklist.c @@ -26,6 +26,13 @@ struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, if (wpa_s == NULL || bssid == NULL) return NULL; + if (wpa_s->current_ssid && + wpa_s->current_ssid->was_recently_reconfigured) { + wpa_blacklist_clear(wpa_s); + wpa_s->current_ssid->was_recently_reconfigured = false; + return NULL; + } + wpa_blacklist_update(wpa_s); e = wpa_s->blacklist; diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 8e79cab20..e3c12d8b3 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -3142,6 +3142,7 @@ int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, } ret = -1; } + ssid->was_recently_reconfigured = true; return ret; } diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 2c08c0218..ff9cdf4f6 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -1137,6 +1137,15 @@ struct wpa_ssid { * 2 = disable SAE-PK (allow SAE authentication only without SAE-PK) */ enum sae_pk_mode sae_pk; + + /** + * was_recently_reconfigured - Whether this SSID config has been changed + * recently + * + * This is an internally used variable, i.e., not used in external + * configuration. + */ + bool was_recently_reconfigured; }; #endif /* CONFIG_SSID_H */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 30fb04786..3404f7d01 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1189,6 +1189,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } + wpa_blacklist_clear(wpa_s); wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed"); return 0; } From 5b0ba21a0357f993cad99f684d59f620ab0748cd Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Sat, 10 Oct 2020 08:10:58 +0200 Subject: [PATCH 0940/1105] doc: Fix typos Signed-off-by: Yegor Yefremov --- doc/dbus.doxygen | 4 ++-- doc/doxygen.conf | 2 +- doc/driver_wrapper.doxygen | 2 +- doc/p2p.doxygen | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen index a2e5de262..08488ad4c 100644 --- a/doc/dbus.doxygen +++ b/doc/dbus.doxygen @@ -891,7 +891,7 @@ fi.w1.wpa_supplicant1.CreateInterface.
  • Hessid - s - (read/write)

    -

    Homogenous ESS identifier

    +

    Homogeneous ESS identifier

  • @@ -2037,7 +2037,7 @@ scan results. KeyMgmtasKey management suite. Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "wpa-eap-suite-b", "wpa-eap-suite-b-192", "wpa-fils-sha256", "wpa-fils-sha384", "wpa-ft-fils-sha256", "wpa-ft-fils-sha384", "sae", "ft-sae", "wpa-none" PairwiseasPairwise cipher suites. Possible array elements: "ccmp", "tkip" GroupsGroup cipher suite. Possible values are: "ccmp", "tkip", "wep104", "wep40" - MgmtGroupsMangement frames cipher suite. Possible values are: "aes128cmac" + MgmtGroupsManagement frames cipher suite. Possible values are: "aes128cmac"
  • diff --git a/doc/doxygen.conf b/doc/doxygen.conf index cf2879010..3f0117393 100644 --- a/doc/doxygen.conf +++ b/doc/doxygen.conf @@ -278,7 +278,7 @@ TYPEDEF_HIDES_STRUCT = NO # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. +# causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the diff --git a/doc/driver_wrapper.doxygen b/doc/driver_wrapper.doxygen index a3b470a2e..66211b3ab 100644 --- a/doc/driver_wrapper.doxygen +++ b/doc/driver_wrapper.doxygen @@ -156,7 +156,7 @@ ap_scan=1: - wpa_supplicant requests scan with SIOCSIWSCAN - driver reports scan complete with wireless event SIOCGIWSCAN - wpa_supplicant reads scan results with SIOCGIWSCAN (multiple call if - a larget buffer is needed) + a larger buffer is needed) - wpa_supplicant decides which AP to use based on scan results - wpa_supplicant configures driver to associate with the selected BSS (SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWFREQ, diff --git a/doc/p2p.doxygen b/doc/p2p.doxygen index f46d1b80a..d4d86e3ed 100644 --- a/doc/p2p.doxygen +++ b/doc/p2p.doxygen @@ -283,7 +283,7 @@ service discovery. The user of the P2P module is responsible for providing P2P specific Service Request TLV(s) for queries and Service Response TLV(s) for responses. -\subsection p2p_sd_query Quering services of peers +\subsection p2p_sd_query Querying services of peers Service discovery is implemented by processing pending queries as a part of the device discovery phase. \ref p2p_sd_request() function is used From 6e757bba8a6d21155ff17bde0e9f2746277e6b20 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Oct 2020 17:48:59 +0300 Subject: [PATCH 0941/1105] Use consistent spelling of "homogeneous" The 'H' in HESSID was originally spelled "homogenous" in IEEE Std 802.11-2016 abbreviations and acronyms list, but that was changed in REVmd to the significantly more common spelling "homonegeneous". Update this older version to match the new spelling to be consistent throughout the repository. Signed-off-by: Jouni Malinen --- wpa_supplicant/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 2a2ad8722..cd9830939 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -977,7 +977,7 @@ struct wpa_config { int go_venue_type; /** - * hessid - Homogenous ESS identifier + * hessid - Homogeneous ESS identifier * * If this is set (any octet is non-zero), scans will be used to * request response only from BSSes belonging to the specified From 17d6ba4c9ea17da5b45a4cb97c1c9c55dcbd678e Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 23 Jun 2020 10:39:02 -0700 Subject: [PATCH 0942/1105] DBus: Add "Roam" command support Add D-Bus interface for ROAM command, imitating the existing wpa_cli command. Chromium OS has been carrying a form of this patch for a very long time. I've cleaned it up a bit and documented it. Signed-off-by: Brian Norris --- doc/dbus.doxygen | 18 +++++++++ wpa_supplicant/dbus/dbus_new.c | 8 ++++ wpa_supplicant/dbus/dbus_new_handlers.c | 49 +++++++++++++++++++++++++ wpa_supplicant/dbus/dbus_new_handlers.h | 3 ++ 4 files changed, 78 insertions(+) diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen index 08488ad4c..06e53b98c 100644 --- a/doc/dbus.doxygen +++ b/doc/dbus.doxygen @@ -322,6 +322,24 @@ fi.w1.wpa_supplicant1.CreateInterface.
  • +
  • +

    Roam ( s : addr ) --> nothing

    +

    Initiate a roam to another BSS within the current ESS.

    +

    Possible errors

    +
    +
    fi.w1.wpa_supplicant1.InvalidArgs
    +
    Missing address argument.
    +
    fi.w1.wpa_supplicant1.InvalidArgs
    +
    Invalid hardware address format.
    +
    fi.w1.wpa_supplicant1.InvalidArgs
    +
    Target BSS not found.
    +
    fi.w1.wpa_supplicant1.NotConnected
    +
    Interface is not connected to any network.
    +
    fi.w1.wpa_supplicant1.UnknownError
    +
    Scan processing was not included in the build.
    +
    +
  • +
  • AddBlob ( s : name, ay : data ) --> nothing

    Adds a blob to the interface.

    diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index ab7628f87..6dcd948ad 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -3212,6 +3212,14 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { END_ARGS } }, + { "Roam", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_roam, + { + { "addr", "s", ARG_IN }, + END_ARGS + } + }, + #ifndef CONFIG_NO_CONFIG_BLOBS { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, (WPADBusMethodHandler) wpas_dbus_handler_add_blob, diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 66a0e2152..489d89a8d 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1976,6 +1976,55 @@ out: } +/** + * wpas_dbus_handler_roam - Initiate a roam to another BSS within the ESS + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NULL on success or dbus error on failure + * + * Handler function for "Roam" method call of network interface. + */ +DBusMessage * wpas_dbus_handler_roam(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ +#ifdef CONFIG_NO_SCAN_PROCESSING + return wpas_dbus_error_unknown_error(message, + "scan processing not included"); +#else /* CONFIG_NO_SCAN_PROCESSING */ + u8 bssid[ETH_ALEN]; + struct wpa_bss *bss; + struct wpa_ssid *ssid = wpa_s->current_ssid; + char *addr; + + if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &addr, + DBUS_TYPE_INVALID)) + return wpas_dbus_error_invalid_args(message, NULL); + + if (hwaddr_aton(addr, bssid)) + return wpas_dbus_error_invalid_args( + message, "Invalid hardware address format"); + + wpa_printf(MSG_DEBUG, "dbus: Roam " MACSTR, MAC2STR(bssid)); + + if (!ssid) + return dbus_message_new_error( + message, WPAS_DBUS_ERROR_NOT_CONNECTED, + "This interface is not connected"); + + bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); + if (!bss) { + wpa_printf(MSG_DEBUG, "dbus: Roam: Target BSS not found"); + return wpas_dbus_error_invalid_args( + message, "Target BSS not found"); + } + + wpa_s->reassociate = 1; + wpa_supplicant_connect(wpa_s, bss, ssid); + + return NULL; +#endif /* CONFIG_NO_SCAN_PROCESSING */ +} + #ifndef CONFIG_NO_CONFIG_BLOBS /** diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index d528c0816..c36383f05 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -117,6 +117,9 @@ DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message, DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_roam(DBusMessage *message, + struct wpa_supplicant *wpa_s); + DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message, struct wpa_supplicant *wpa_s); From 48aebcc31bad1f18c87f670c8a1d76dcf0b3b747 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 10 Oct 2020 20:15:34 +0300 Subject: [PATCH 0943/1105] tests: D-Bus Roam Signed-off-by: Jouni Malinen --- tests/hwsim/test_dbus.py | 68 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py index 7b3d4bee5..65ebe7da7 100644 --- a/tests/hwsim/test_dbus.py +++ b/tests/hwsim/test_dbus.py @@ -5920,3 +5920,71 @@ def test_dbus_mesh(dev, apdev): with TestDbusMesh(bus) as t: if not t.success(): raise Exception("Expected signals not seen") + +def test_dbus_roam(dev, apdev): + """D-Bus Roam""" + (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) + iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) + + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + hapd = hostapd.add_ap(apdev[0], params) + hapd2 = hostapd.add_ap(apdev[1], params) + bssid = apdev[0]['bssid'] + dev[0].scan_for_bss(bssid, freq=2412) + bssid2 = apdev[1]['bssid'] + dev[0].scan_for_bss(bssid2, freq=2412) + + class TestDbusConnect(TestDbus): + def __init__(self, bus): + TestDbus.__init__(self, bus) + self.state = 0 + + def __enter__(self): + gobject.timeout_add(1, self.run_connect) + gobject.timeout_add(15000, self.timeout) + self.add_signal(self.propertiesChanged, WPAS_DBUS_IFACE, + "PropertiesChanged") + self.loop.run() + return self + + def propertiesChanged(self, properties): + logger.debug("propertiesChanged: %s" % str(properties)) + if 'State' in properties and properties['State'] == "completed": + if self.state == 0: + self.state = 1 + cur = properties["CurrentBSS"] + bss_obj = bus.get_object(WPAS_DBUS_SERVICE, cur) + res = bss_obj.Get(WPAS_DBUS_BSS, 'BSSID', + dbus_interface=dbus.PROPERTIES_IFACE) + bssid_str = '' + for item in res: + if len(bssid_str) > 0: + bssid_str += ':' + bssid_str += '%02x' % item + dst = bssid if bssid_str == bssid2 else bssid2 + iface.Roam(dst) + elif self.state == 1: + if "RoamComplete" in properties and \ + properties["RoamComplete"]: + self.state = 2 + self.loop.quit() + + def run_connect(self, *args): + logger.debug("run_connect") + args = dbus.Dictionary({'ssid': ssid, + 'key_mgmt': 'WPA-PSK', + 'psk': passphrase, + 'scan_freq': 2412}, + signature='sv') + self.netw = iface.AddNetwork(args) + iface.SelectNetwork(self.netw) + return False + + def success(self): + return self.state == 2 + + with TestDbusConnect(bus) as t: + if not t.success(): + raise Exception("Expected signals not seen") From 566ea1b7ce7853894c1d11a0f35979607ba9a729 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Fri, 12 Jun 2020 16:49:44 +0200 Subject: [PATCH 0944/1105] mesh: Set correct address for mesh default broadcast/multicast keys wpa_drv_set_key() was called with a NULL address for IGTK and MGTK before this patch. The nl80211 driver will then not add the NL80211_KEY_DEFAULT_TYPE_MULTICAST flag for the key, which wrongly marks this key also as a default unicast key in the Linux kernel. With SAE this is no real problem in practice, as a pairwise key will be negotiated in mesh mode, before the first data frame gets send. When using IEEE 802.1X in a mesh network in the future, this gets a problem, as Linux now will encrypt EAPOL frames with the default key, which is also marked for unicast usage without this patch. Signed-off-by: Markus Theil --- wpa_supplicant/mesh_rsn.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c index f19bfbfc6..834c7a1cc 100644 --- a/wpa_supplicant/mesh_rsn.c +++ b/wpa_supplicant/mesh_rsn.c @@ -195,7 +195,8 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr, wpa_hexdump_key(MSG_DEBUG, "mesh: Own TX IGTK", rsn->igtk, rsn->igtk_len); wpa_drv_set_key(rsn->wpa_s, - wpa_cipher_to_alg(rsn->mgmt_group_cipher), NULL, + wpa_cipher_to_alg(rsn->mgmt_group_cipher), + broadcast_ether_addr, rsn->igtk_key_id, 1, seq, sizeof(seq), rsn->igtk, rsn->igtk_len, KEY_FLAG_GROUP_TX_DEFAULT); @@ -204,7 +205,8 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr, /* group privacy / data frames */ wpa_hexdump_key(MSG_DEBUG, "mesh: Own TX MGTK", rsn->mgtk, rsn->mgtk_len); - wpa_drv_set_key(rsn->wpa_s, wpa_cipher_to_alg(rsn->group_cipher), NULL, + wpa_drv_set_key(rsn->wpa_s, wpa_cipher_to_alg(rsn->group_cipher), + broadcast_ether_addr, rsn->mgtk_key_id, 1, seq, sizeof(seq), rsn->mgtk, rsn->mgtk_len, KEY_FLAG_GROUP_TX_DEFAULT); From c0b88d12913900d8ead231bdd320dd40c2f76254 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Tue, 25 Aug 2020 08:29:02 +0200 Subject: [PATCH 0945/1105] P2P: Limit P2P_DEVICE name to appropriate ifname size Otherwise the WPA_IF_P2P_DEVICE cannot be created if the base ifname is long enough. As this is not a netdev device, it is acceptable if the name is not completely unique. As such, simply insert a NUL byte at the appropriate place. Signed-off-by: Benjamin Berg --- wpa_supplicant/p2p_supplicant.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 479fa2fad..64ba34450 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3984,6 +3984,10 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s, wpa_s->ifname); if (os_snprintf_error(sizeof(ifname), ret)) return -1; + /* Cut length at the maximum size. Note that we don't need to ensure + * collision free names here as the created interface is not a netdev. + */ + ifname[IFNAMSIZ - 1] = '\0'; force_name[0] = '\0'; wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE; ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, NULL, NULL, From 2818e9ca903e52bb9a41921ec664d3a2e8572688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Georg=20M=C3=BCller?= Date: Thu, 18 Jun 2020 16:39:12 +0200 Subject: [PATCH 0946/1105] wpa_supplicant: Do not retry scan if operation is not supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using NetworkManager to set up an access point, there seems to be a race condition which can lead to a new log message every second. The following message appears in AP mode: CTRL-EVENT-SCAN-FAILED ret=-95 retry=1 Normally, this log message only appears once. But then (and only then) the race is triggered and they appear every second, the following log messages are also present: Reject scan trigger since one is already pending Failed to initiate AP scan This patch just disables the retry for requests where the operation is not supported anyway. Signed-off-by: Georg Müller --- wpa_supplicant/scan.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 7415eae9f..b9e4162c8 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -237,6 +237,10 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) if (wpa_s->disconnected) retry = 0; + /* do not retry if operation is not supported */ + if (ret == -EOPNOTSUPP) + retry = 0; + wpa_supplicant_notify_scanning(wpa_s, 0); wpas_notify_scan_done(wpa_s, 0); if (wpa_s->wpa_state == WPA_SCANNING) From 4dbba548ae5b3a5ebf6ca7400666a2180c691d13 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 25 Jun 2020 13:22:01 -0700 Subject: [PATCH 0947/1105] tests: Skip busctl tests when not available Signed-off-by: Brian Norris --- tests/hwsim/test_dbus.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py index 65ebe7da7..4958048ae 100644 --- a/tests/hwsim/test_dbus.py +++ b/tests/hwsim/test_dbus.py @@ -9,6 +9,7 @@ import logging logger = logging.getLogger() import subprocess import time +import shutil import struct import sys @@ -5354,6 +5355,8 @@ def test_dbus_introspect(dev, apdev): raise Exception("Unexpected Introspect response") def run_busctl(service, obj): + if not shutil.which("busctl"): + raise HwsimSkip("No busctl available") logger.info("busctl introspect %s %s" % (service, obj)) cmd = subprocess.Popen(['busctl', 'introspect', service, obj], stdout=subprocess.PIPE, From 4b0bf0ec6efe6015aa6a9792ce1fb65bdc7f7548 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Thu, 25 Jun 2020 13:22:02 -0700 Subject: [PATCH 0948/1105] tests: run-tests: Do not use sudo if already root Among other things, sudo can disrupt environment variables that a caller provides. Signed-off-by: Brian Norris --- tests/hwsim/run-all.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/run-all.sh b/tests/hwsim/run-all.sh index 495c9fa74..ee48cd058 100755 --- a/tests/hwsim/run-all.sh +++ b/tests/hwsim/run-all.sh @@ -122,7 +122,13 @@ if ! ./start.sh $VM $VALGRIND $TRACE channels=$NUM_CH; then exit 1 fi -sudo ./run-tests.py -D --logdir "$LOGDIR" $TRACE_ARGS -q $DB $RUN_TEST_ARGS || errors=1 +# Only use sudo if not already root. +if [ "$(id -u)" != 0 ]; then + SUDO=sudo +else + SUDO= +fi +${SUDO} ./run-tests.py -D --logdir "$LOGDIR" $TRACE_ARGS -q $DB $RUN_TEST_ARGS || errors=1 ./stop.sh From 07aac648a16e8df72463bbaa6f6ee7821d4eb7ed Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 19 Aug 2020 19:09:34 -0700 Subject: [PATCH 0949/1105] tests: dbus: Add test for RemoveAllNetworks while connected This likely passes today (at least without ASAN), but without the next commit, it trips up a use-after-free bug, which ASAN can catch. So consider this a regression test. Signed-off-by: Brian Norris --- tests/hwsim/test_dbus.py | 100 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py index 4958048ae..1143802c6 100644 --- a/tests/hwsim/test_dbus.py +++ b/tests/hwsim/test_dbus.py @@ -1380,6 +1380,106 @@ def test_dbus_connect(dev, apdev): if not t.success(): raise Exception("Expected signals not seen") +def test_dbus_remove_connected(dev, apdev): + """D-Bus RemoveAllNetworks while connected""" + (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) + iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) + + ssid = "test-open" + hapd = hostapd.add_ap(apdev[0], {"ssid": ssid}) + + class TestDbusConnect(TestDbus): + def __init__(self, bus): + TestDbus.__init__(self, bus) + self.network_added = False + self.network_selected = False + self.network_removed = False + self.state = 0 + + def __enter__(self): + gobject.timeout_add(1, self.run_connect) + gobject.timeout_add(15000, self.timeout) + self.add_signal(self.networkAdded, WPAS_DBUS_IFACE, "NetworkAdded") + self.add_signal(self.networkRemoved, WPAS_DBUS_IFACE, + "NetworkRemoved") + self.add_signal(self.networkSelected, WPAS_DBUS_IFACE, + "NetworkSelected") + self.add_signal(self.propertiesChanged, WPAS_DBUS_IFACE, + "PropertiesChanged") + self.loop.run() + return self + + def networkAdded(self, network, properties): + logger.debug("networkAdded: %s" % str(network)) + logger.debug(str(properties)) + self.network_added = True + + def networkRemoved(self, network): + logger.debug("networkRemoved: %s" % str(network)) + self.network_removed = True + + def networkSelected(self, network): + logger.debug("networkSelected: %s" % str(network)) + self.network_selected = True + + def propertiesChanged(self, properties): + logger.debug("propertiesChanged: %s" % str(properties)) + if 'State' in properties and properties['State'] == "completed": + if self.state == 0: + self.state = 1 + iface.Disconnect() + elif self.state == 2: + self.state = 3 + iface.Disconnect() + elif self.state == 4: + self.state = 5 + iface.Reattach() + elif self.state == 5: + self.state = 6 + iface.Disconnect() + elif self.state == 7: + self.state = 8 + res = iface.SignalPoll() + logger.debug("SignalPoll: " + str(res)) + if 'frequency' not in res or res['frequency'] != 2412: + self.state = -1 + logger.info("Unexpected SignalPoll result") + iface.RemoveAllNetworks() + if 'State' in properties and properties['State'] == "disconnected": + if self.state == 1: + self.state = 2 + iface.SelectNetwork(self.netw) + elif self.state == 3: + self.state = 4 + iface.Reassociate() + elif self.state == 6: + self.state = 7 + iface.Reconnect() + elif self.state == 8: + self.state = 9 + self.loop.quit() + + def run_connect(self, *args): + logger.debug("run_connect") + args = dbus.Dictionary({'ssid': ssid, + 'key_mgmt': 'NONE', + 'scan_freq': 2412}, + signature='sv') + self.netw = iface.AddNetwork(args) + iface.SelectNetwork(self.netw) + return False + + def success(self): + if not self.network_added or \ + not self.network_removed or \ + not self.network_selected: + return False + return self.state == 9 + + with TestDbusConnect(bus) as t: + if not t.success(): + raise Exception("Expected signals not seen") + def test_dbus_connect_psk_mem(dev, apdev): """D-Bus AddNetwork and connect with memory-only PSK""" (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) From 4b96fafcd8688f4222cf065038ab406f7083d86d Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 19 Aug 2020 19:09:35 -0700 Subject: [PATCH 0950/1105] D-Bus: Share 'remove all networks' with CLI The D-Bus implementation of RemoveAllNetworks differs wildly from the CLI implementation. Let's share the implementations. This resolves use-after-free bugs I noticed, where we continue to use the 'wpa_s->current_ssid' wpa_ssid object after freeing it, because we didn't bother to disconnect from (and set to NULL) current_ssid before freeing it. Signed-off-by: Brian Norris --- wpa_supplicant/ctrl_iface.c | 28 +-------------- wpa_supplicant/dbus/dbus_new_handlers.c | 24 +------------ wpa_supplicant/wpa_supplicant.c | 46 +++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 1 + 4 files changed, 49 insertions(+), 50 deletions(-) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 1bb18bdd1..76a3ed618 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -3480,38 +3480,12 @@ static int wpa_supplicant_ctrl_iface_remove_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; - struct wpa_ssid *ssid; int result; /* cmd: "" or "all" */ if (os_strcmp(cmd, "all") == 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); - if (wpa_s->sched_scanning) - wpa_supplicant_cancel_sched_scan(wpa_s); - - eapol_sm_invalidate_cached_session(wpa_s->eapol); - if (wpa_s->current_ssid) { -#ifdef CONFIG_SME - wpa_s->sme.prev_bssid_set = 0; -#endif /* CONFIG_SME */ - wpa_sm_set_config(wpa_s->wpa, NULL); - eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); - if (wpa_s->wpa_state >= WPA_AUTHENTICATING) - wpa_s->own_disconnect_req = 1; - wpa_supplicant_deauthenticate( - wpa_s, WLAN_REASON_DEAUTH_LEAVING); - } - ssid = wpa_s->conf->ssid; - while (ssid) { - struct wpa_ssid *remove_ssid = ssid; - id = ssid->id; - ssid = ssid->next; - if (wpa_s->last_ssid == remove_ssid) - wpa_s->last_ssid = NULL; - wpas_notify_network_removed(wpa_s, remove_ssid); - wpa_config_remove_network(wpa_s->conf, id); - } - return 0; + return wpa_supplicant_remove_all_networks(wpa_s); } id = atoi(cmd); diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 489d89a8d..86f85605a 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1817,25 +1817,6 @@ out: } -static void remove_network(void *arg, struct wpa_ssid *ssid) -{ - struct wpa_supplicant *wpa_s = arg; - - wpas_notify_network_removed(wpa_s, ssid); - - if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) { - wpa_printf(MSG_ERROR, - "%s[dbus]: error occurred when removing network %d", - __func__, ssid->id); - return; - } - - if (ssid == wpa_s->current_ssid) - wpa_supplicant_deauthenticate(wpa_s, - WLAN_REASON_DEAUTH_LEAVING); -} - - /** * wpas_dbus_handler_remove_all_networks - Remove all configured networks * @message: Pointer to incoming dbus message @@ -1847,11 +1828,8 @@ static void remove_network(void *arg, struct wpa_ssid *ssid) DBusMessage * wpas_dbus_handler_remove_all_networks( DBusMessage *message, struct wpa_supplicant *wpa_s) { - if (wpa_s->sched_scanning) - wpa_supplicant_cancel_sched_scan(wpa_s); - /* NB: could check for failure and return an error */ - wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s); + wpa_supplicant_remove_all_networks(wpa_s); return NULL; } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 3404f7d01..01ba032f4 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4122,6 +4122,52 @@ int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id) } +/** + * wpa_supplicant_remove_all_networks - Remove all configured networks + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: 0 on success (errors are currently ignored) + * + * This function performs the following operations: + * 1. Remove all networks. + * 2. Send network removal notifications. + * 3. Update internal state machines. + * 4. Stop any running sched scans. + */ +int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid; + + if (wpa_s->sched_scanning) + wpa_supplicant_cancel_sched_scan(wpa_s); + + eapol_sm_invalidate_cached_session(wpa_s->eapol); + if (wpa_s->current_ssid) { +#ifdef CONFIG_SME + wpa_s->sme.prev_bssid_set = 0; +#endif /* CONFIG_SME */ + wpa_sm_set_config(wpa_s->wpa, NULL); + eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) + wpa_s->own_disconnect_req = 1; + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + } + ssid = wpa_s->conf->ssid; + while (ssid) { + struct wpa_ssid *remove_ssid = ssid; + int id; + + id = ssid->id; + ssid = ssid->next; + if (wpa_s->last_ssid == remove_ssid) + wpa_s->last_ssid = NULL; + wpas_notify_network_removed(wpa_s, remove_ssid); + wpa_config_remove_network(wpa_s->conf, id); + } + return 0; +} + + /** * wpa_supplicant_enable_network - Mark a configured network as enabled * @wpa_s: wpa_supplicant structure for a network interface diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 2df45c62c..ffaacf948 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1381,6 +1381,7 @@ void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s); struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s); int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id); +int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s); void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s, From 52a1b28345123c374fd0127cbce623c41a760730 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 27 Aug 2020 15:59:40 -0700 Subject: [PATCH 0951/1105] nl80211: Unbreak mode processing due to presence of S1G band If kernel advertises a band with channels < 2.4 GHz hostapd/wpa_supplicant gets confused and assumes this is an IEEE 802.11b, corrupting the real IEEE 802.11b band info. Signed-off-by: Thomas Pedersen --- src/drivers/driver_nl80211_capa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 46f61fdbf..625fe5d0b 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1946,7 +1946,10 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, for (m = 0; m < *num_modes; m++) { if (!modes[m].num_channels) continue; - if (modes[m].channels[0].freq < 4000) { + if (modes[m].channels[0].freq < 2000) { + modes[m].num_channels = 0; + continue; + } else if (modes[m].channels[0].freq < 4000) { modes[m].mode = HOSTAPD_MODE_IEEE80211B; for (i = 0; i < modes[m].num_rates; i++) { if (modes[m].rates[i] > 200) { From 58c18bcf86db8053719fd19ec43c1ad754d76d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Sat, 10 Oct 2020 19:45:29 +0200 Subject: [PATCH 0952/1105] hostapd: Fix error message for radius_accept_attr config option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Error message contained wrong config option. Signed-off-by: Pali Rohár --- hostapd/config_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 542c8cd0d..ce32f3c04 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -341,7 +341,7 @@ static int hostapd_config_read_eap_user(const char *fname, struct hostapd_radius_attr *attr, *a; attr = hostapd_parse_radius_attr(buf + 19); if (attr == NULL) { - wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s", + wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s", buf + 19); user = NULL; /* already in the BSS list */ goto failed; From a49f628845a3d87ca6f1b5c438d6e4868e42d487 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 4 Aug 2020 11:48:23 +0200 Subject: [PATCH 0953/1105] wolfSSL: Fix wrong types in tls_wolfssl.c wolfSSL_X509_get_ext_d2i() returns STACK_OF(GENERAL_NAME)* for ALT_NAMES_OID therefore wolfSSL_sk_value needs to expect a WOLFSSL_GENERAL_NAME*. In addition, explicitly check for NULL return from wolfSSL_sk_value(). Signed-off-by: Juliusz Sosinowicz --- src/crypto/tls_wolfssl.c | 47 +++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c index 11e658220..b8a7665fd 100644 --- a/src/crypto/tls_wolfssl.c +++ b/src/crypto/tls_wolfssl.c @@ -19,6 +19,7 @@ #include #include #include +#include #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) #define HAVE_AESGCM @@ -576,7 +577,7 @@ static int tls_connection_private_key(void *tls_ctx, static int tls_match_alt_subject_component(WOLFSSL_X509 *cert, int type, const char *value, size_t len) { - WOLFSSL_ASN1_OBJECT *gen; + WOLFSSL_GENERAL_NAME *gen; void *ext; int found = 0; int i; @@ -585,14 +586,15 @@ static int tls_match_alt_subject_component(WOLFSSL_X509 *cert, int type, for (i = 0; ext && i < wolfSSL_sk_num(ext); i++) { gen = wolfSSL_sk_value(ext, i); - if (gen->type != type) + if (!gen || gen->type != type) continue; - if (os_strlen((char *) gen->obj) == len && - os_memcmp(value, gen->obj, len) == 0) + if ((size_t) wolfSSL_ASN1_STRING_length(gen->d.ia5) == len && + os_memcmp(value, wolfSSL_ASN1_STRING_data(gen->d.ia5), + len) == 0) found++; } - wolfSSL_sk_ASN1_OBJECT_free(ext); + wolfSSL_sk_GENERAL_NAME_free(ext); return found; } @@ -676,7 +678,7 @@ static int domain_suffix_match(const char *val, size_t len, const char *match, static int tls_match_suffix_helper(WOLFSSL_X509 *cert, const char *match, size_t match_len, int full) { - WOLFSSL_ASN1_OBJECT *gen; + WOLFSSL_GENERAL_NAME *gen; void *ext; int i; int j; @@ -690,21 +692,23 @@ static int tls_match_suffix_helper(WOLFSSL_X509 *cert, const char *match, for (j = 0; ext && j < wolfSSL_sk_num(ext); j++) { gen = wolfSSL_sk_value(ext, j); - if (gen->type != ASN_DNS_TYPE) + if (!gen || gen->type != ASN_DNS_TYPE) continue; dns_name++; wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName", - gen->obj, os_strlen((char *)gen->obj)); - if (domain_suffix_match((const char *) gen->obj, - os_strlen((char *) gen->obj), match, - match_len, full) == 1) { + wolfSSL_ASN1_STRING_data(gen->d.ia5), + wolfSSL_ASN1_STRING_length(gen->d.ia5)); + if (domain_suffix_match( + (const char *) wolfSSL_ASN1_STRING_data(gen->d.ia5), + wolfSSL_ASN1_STRING_length(gen->d.ia5), match, + match_len, full) == 1) { wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found", full ? "Match" : "Suffix match"); wolfSSL_sk_ASN1_OBJECT_free(ext); return 1; } } - wolfSSL_sk_ASN1_OBJECT_free(ext); + wolfSSL_sk_GENERAL_NAME_free(ext); if (dns_name) { wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched"); @@ -858,7 +862,7 @@ static void wolfssl_tls_cert_event(struct tls_connection *conn, struct tls_context *context = conn->context; char *alt_subject[TLS_MAX_ALT_SUBJECT]; int alt, num_alt_subject = 0; - WOLFSSL_ASN1_OBJECT *gen; + WOLFSSL_GENERAL_NAME *gen; void *ext; int i; #ifdef CONFIG_SHA256 @@ -899,12 +903,14 @@ static void wolfssl_tls_cert_event(struct tls_connection *conn, if (num_alt_subject == TLS_MAX_ALT_SUBJECT) break; gen = wolfSSL_sk_value((void *) ext, i); - if (gen->type != GEN_EMAIL && - gen->type != GEN_DNS && - gen->type != GEN_URI) + if (!gen || + (gen->type != GEN_EMAIL && + gen->type != GEN_DNS && + gen->type != GEN_URI)) continue; - pos = os_malloc(10 + os_strlen((char *) gen->obj) + 1); + pos = os_malloc(10 + wolfSSL_ASN1_STRING_length(gen->d.ia5) + + 1); if (!pos) break; alt_subject[num_alt_subject++] = pos; @@ -924,11 +930,12 @@ static void wolfssl_tls_cert_event(struct tls_connection *conn, break; } - os_memcpy(pos, gen->obj, os_strlen((char *)gen->obj)); - pos += os_strlen((char *)gen->obj); + os_memcpy(pos, wolfSSL_ASN1_STRING_data(gen->d.ia5), + wolfSSL_ASN1_STRING_length(gen->d.ia5)); + pos += wolfSSL_ASN1_STRING_length(gen->d.ia5); *pos = '\0'; } - wolfSSL_sk_ASN1_OBJECT_free(ext); + wolfSSL_sk_GENERAL_NAME_free(ext); for (alt = 0; alt < num_alt_subject; alt++) ev.peer_cert.altsubject[alt] = alt_subject[alt]; From 00b5e99b652597855d65befd047589e62f9584df Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2020 09:58:57 +0200 Subject: [PATCH 0954/1105] build: Use the new build system for fuzz tests Signed-off-by: Johannes Berg --- src/build.rules | 4 ++++ tests/fuzzing/ap-mgmt/Makefile | 14 +++++++------ tests/fuzzing/asn1/Makefile | 14 +++++++------ tests/fuzzing/dpp-uri/Makefile | 12 ++++++----- tests/fuzzing/eap-aka-peer/Makefile | 14 +++++++------ tests/fuzzing/eap-mschapv2-peer/Makefile | 14 +++++++------ tests/fuzzing/eap-sim-peer/Makefile | 14 +++++++------ tests/fuzzing/eapol-key-auth/Makefile | 14 +++++++------ tests/fuzzing/eapol-key-supp/Makefile | 14 +++++++------ tests/fuzzing/eapol-supp/Makefile | 14 +++++++------ tests/fuzzing/json/Makefile | 15 +++++++------- tests/fuzzing/p2p/Makefile | 14 +++++++------ tests/fuzzing/rules.include | 26 +++--------------------- tests/fuzzing/sae/Makefile | 14 +++++++------ tests/fuzzing/tls-client/Makefile | 15 +++++++------- tests/fuzzing/tls-server/Makefile | 15 +++++++------- tests/fuzzing/wnm/Makefile | 15 +++++++------- tests/fuzzing/x509/Makefile | 15 +++++++------- 18 files changed, 134 insertions(+), 123 deletions(-) diff --git a/src/build.rules b/src/build.rules index 32f45ae1e..5960ba841 100644 --- a/src/build.rules +++ b/src/build.rules @@ -83,6 +83,10 @@ $(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs $(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs $(Q)$(CC) -c -o $@ $(CFLAGS) $< @$(E) " CC " $< +# for the fuzzing tests +$(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FILE) | _make_dirs + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + @$(E) " CC " $< BUILDOBJ = $(patsubst %,$(BUILDDIR)/$(PROJ)/%,$(patsubst $(ROOTDIR)%,%,$(1))) diff --git a/tests/fuzzing/ap-mgmt/Makefile b/tests/fuzzing/ap-mgmt/Makefile index 192ae723e..159c7c3f8 100644 --- a/tests/fuzzing/ap-mgmt/Makefile +++ b/tests/fuzzing/ap-mgmt/Makefile @@ -1,4 +1,4 @@ -all: ap-mgmt +ALL=ap-mgmt include ../rules.include CFLAGS += -DCONFIG_WNM @@ -26,11 +26,13 @@ ELIBS += $(SRC)/tls/libtls.a OBJS += $(SRC)/drivers/driver_common.o -ap-mgmt: ap-mgmt.o $(OBJS) $(LIBS) +OBJS += ap-mgmt.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +ap-mgmt: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f ap-mgmt *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/asn1/Makefile b/tests/fuzzing/asn1/Makefile index 428625934..fb8fbed68 100644 --- a/tests/fuzzing/asn1/Makefile +++ b/tests/fuzzing/asn1/Makefile @@ -1,4 +1,4 @@ -all: asn1 +ALL=asn1 include ../rules.include OBJS += $(SRC)/utils/common.o @@ -7,12 +7,14 @@ OBJS += $(SRC)/utils/wpa_debug.o OBJS += $(SRC)/utils/wpabuf.o OBJS += $(SRC)/tls/asn1.o -asn1: asn1.o $(OBJS) $(LIBS) +OBJS += asn1.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +asn1: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: +clean: common-clean $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean rm -f asn1 *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index 07bfac06c..aca8f02ad 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -28,11 +28,13 @@ OBJS += $(SRC)/common/dpp_pkex.o OBJS += $(SRC)/common/dpp_reconfig.o OBJS += $(SRC)/common/dpp_tcp.o -dpp-uri: dpp-uri.o $(OBJS) $(LIBS) +OBJS += dpp-uri.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +dpp-uri: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f dpp-uri *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eap-aka-peer/Makefile b/tests/fuzzing/eap-aka-peer/Makefile index d1a4cd372..bd960caa7 100644 --- a/tests/fuzzing/eap-aka-peer/Makefile +++ b/tests/fuzzing/eap-aka-peer/Makefile @@ -1,4 +1,4 @@ -all: eap-aka-peer +ALL=eap-aka-peer include ../rules.include CFLAGS += -DIEEE8021X_EAPOL @@ -10,12 +10,14 @@ OBJS += $(SRC)/eap_common/eap_common.o LIBS += $(SRC)/crypto/libcrypto.a LIBS += $(SRC)/utils/libutils.a -eap-aka-peer: eap-aka-peer.o $(OBJS) $(LIBS) +OBJS += eap-aka-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +eap-aka-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eap-aka-peer *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eap-mschapv2-peer/Makefile b/tests/fuzzing/eap-mschapv2-peer/Makefile index 801e0af81..953855c85 100644 --- a/tests/fuzzing/eap-mschapv2-peer/Makefile +++ b/tests/fuzzing/eap-mschapv2-peer/Makefile @@ -1,4 +1,4 @@ -all: eap-mschapv2-peer +ALL=eap-mschapv2-peer include ../rules.include CFLAGS += -DIEEE8021X_EAPOL @@ -9,12 +9,14 @@ OBJS += $(SRC)/eap_common/eap_common.o LIBS += $(SRC)/crypto/libcrypto.a LIBS += $(SRC)/utils/libutils.a -eap-mschapv2-peer: eap-mschapv2-peer.o $(OBJS) $(LIBS) +OBJS += eap-mschapv2-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +eap-mschapv2-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eap-mschapv2-peer *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eap-sim-peer/Makefile b/tests/fuzzing/eap-sim-peer/Makefile index 302717e95..9292ccb79 100644 --- a/tests/fuzzing/eap-sim-peer/Makefile +++ b/tests/fuzzing/eap-sim-peer/Makefile @@ -1,4 +1,4 @@ -all: eap-sim-peer +ALL=eap-sim-peer include ../rules.include CFLAGS += -DIEEE8021X_EAPOL @@ -10,12 +10,14 @@ OBJS += $(SRC)/eap_common/eap_common.o LIBS += $(SRC)/crypto/libcrypto.a LIBS += $(SRC)/utils/libutils.a -eap-sim-peer: eap-sim-peer.o $(OBJS) $(LIBS) +OBJS += eap-sim-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +eap-sim-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eap-sim-peer *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eapol-key-auth/Makefile b/tests/fuzzing/eapol-key-auth/Makefile index bd2b27566..bdc731ff4 100644 --- a/tests/fuzzing/eapol-key-auth/Makefile +++ b/tests/fuzzing/eapol-key-auth/Makefile @@ -1,4 +1,4 @@ -all: eapol-key-auth +ALL=eapol-key-auth include ../rules.include CFLAGS += -DCONFIG_IEEE80211R_AP @@ -19,11 +19,13 @@ LIBS += $(SRC)/radius/libradius.a OBJS += $(SRC)/drivers/driver_common.o -eapol-key-auth: eapol-key-auth.o $(OBJS) $(LIBS) +OBJS += eapol-key-auth.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +eapol-key-auth: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eapol-key-auth *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eapol-key-supp/Makefile b/tests/fuzzing/eapol-key-supp/Makefile index afe566584..29e419b7c 100644 --- a/tests/fuzzing/eapol-key-supp/Makefile +++ b/tests/fuzzing/eapol-key-supp/Makefile @@ -1,4 +1,4 @@ -all: eapol-key-supp +ALL=eapol-key-supp include ../rules.include CFLAGS += -DCONFIG_IEEE80211R_AP @@ -15,11 +15,13 @@ LIBS += $(SRC)/eap_common/libeap_common.a LIBS += $(SRC)/l2_packet/libl2_packet.a LIBS += $(SRC)/utils/libutils.a -eapol-key-supp: eapol-key-supp.o $(OBJS) $(LIBS) +OBJS += eapol-key-supp.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +eapol-key-supp: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eapol-key-supp *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eapol-supp/Makefile b/tests/fuzzing/eapol-supp/Makefile index 41a505d37..27e631148 100644 --- a/tests/fuzzing/eapol-supp/Makefile +++ b/tests/fuzzing/eapol-supp/Makefile @@ -1,4 +1,4 @@ -all: eapol-supp +ALL=eapol-supp include ../rules.include CFLAGS += -DIEEE8021X_EAPOL @@ -13,11 +13,13 @@ LIBS += $(SRC)/eap_common/libeap_common.a LIBS += $(SRC)/l2_packet/libl2_packet.a LIBS += $(SRC)/utils/libutils.a -eapol-supp: eapol-supp.o $(OBJS) $(LIBS) +OBJS += eapol-supp.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +eapol-supp: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eapol-supp *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/json/Makefile b/tests/fuzzing/json/Makefile index ffa0c5a99..8de19293e 100644 --- a/tests/fuzzing/json/Makefile +++ b/tests/fuzzing/json/Makefile @@ -1,4 +1,4 @@ -all: json +ALL=json include ../rules.include OBJS += $(SRC)/utils/base64.o @@ -8,12 +8,13 @@ OBJS += $(SRC)/utils/os_unix.o OBJS += $(SRC)/utils/wpa_debug.o OBJS += $(SRC)/utils/wpabuf.o -json: json.o $(OBJS) $(LIBS) +OBJS += json.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +json: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f json *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/p2p/Makefile b/tests/fuzzing/p2p/Makefile index c088e32d0..ef31a7505 100644 --- a/tests/fuzzing/p2p/Makefile +++ b/tests/fuzzing/p2p/Makefile @@ -1,4 +1,4 @@ -all: p2p +ALL=p2p include ../rules.include LIBS += $(SRC)/utils/libutils.a @@ -8,11 +8,13 @@ LIBS += $(SRC)/p2p/libp2p.a LIBS += $(SRC)/tls/libtls.a LIBS += $(SRC)/wps/libwps.a -p2p: p2p.o $(OBJS) $(LIBS) +OBJS += p2p.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +p2p: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f p2p *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/rules.include b/tests/fuzzing/rules.include index a3b0ee0aa..b2e8a81ea 100644 --- a/tests/fuzzing/rules.include +++ b/tests/fuzzing/rules.include @@ -1,3 +1,6 @@ +FUZZ_RULES := $(lastword $(MAKEFILE_LIST)) +include $(dir $(FUZZ_RULES))../../src/build.rules + FUZZ_CFLAGS = ifdef LIBFUZZER @@ -18,14 +21,6 @@ CFLAGS += -DTEST_LIBFUZZER LDFLAGS += $(FUZZ_FLAGS) endif -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - WPAS_SRC=../../../wpa_supplicant SRC=../../../src @@ -76,18 +71,3 @@ $(SRC)/utils/libutils.a: $(SRC)/wps/libwps.a: $(MAKE) -C $(SRC)/wps - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< diff --git a/tests/fuzzing/sae/Makefile b/tests/fuzzing/sae/Makefile index 5b86c2f43..ee7257afe 100644 --- a/tests/fuzzing/sae/Makefile +++ b/tests/fuzzing/sae/Makefile @@ -1,4 +1,4 @@ -all: sae +ALL=sae include ../rules.include CFLAGS += -DCONFIG_SHA256 @@ -13,11 +13,13 @@ OBJS += $(SRC)/crypto/sha256-prf.o OBJS += $(SRC)/crypto/sha256-kdf.o OBJS += $(SRC)/common/dragonfly.o -sae: sae.o $(OBJS) $(LIBS) +OBJS += sae.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +sae: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f sae *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/tls-client/Makefile b/tests/fuzzing/tls-client/Makefile index e91125ec1..7d5e8d536 100644 --- a/tests/fuzzing/tls-client/Makefile +++ b/tests/fuzzing/tls-client/Makefile @@ -1,4 +1,4 @@ -all: tls-client +ALL=tls-client include ../rules.include LIBS += $(SRC)/common/libcommon.a @@ -14,12 +14,13 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a -tls-client: tls-client.o $(OBJS) $(LIBS) +OBJS += tls-client.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +tls-client: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f tls-client *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/tls-server/Makefile b/tests/fuzzing/tls-server/Makefile index dbb53e5a4..45304328e 100644 --- a/tests/fuzzing/tls-server/Makefile +++ b/tests/fuzzing/tls-server/Makefile @@ -1,4 +1,4 @@ -all: tls-server +ALL=tls-server include ../rules.include LIBS += $(SRC)/common/libcommon.a @@ -14,12 +14,13 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a -tls-server: tls-server.o $(OBJS) $(LIBS) +OBJS += tls-server.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +tls-server: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f tls-server *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/wnm/Makefile b/tests/fuzzing/wnm/Makefile index b8d33ac04..f27dd341b 100644 --- a/tests/fuzzing/wnm/Makefile +++ b/tests/fuzzing/wnm/Makefile @@ -1,4 +1,4 @@ -all: wnm +ALL=wnm include ../rules.include CFLAGS += -DCONFIG_WNM @@ -42,12 +42,13 @@ OBJS += $(WPAS_SRC)/wpas_glue.o OBJS += $(SRC)/drivers/driver_common.o OBJS += $(SRC)/drivers/drivers.o -wnm: wnm.o $(OBJS) $(LIBS) +OBJS += wnm.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +wnm: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f wnm *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/x509/Makefile b/tests/fuzzing/x509/Makefile index d7f751a9d..7fff15a3a 100644 --- a/tests/fuzzing/x509/Makefile +++ b/tests/fuzzing/x509/Makefile @@ -1,4 +1,4 @@ -all: x509 +ALL=x509 include ../rules.include LIBS += $(SRC)/common/libcommon.a @@ -9,12 +9,13 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a -x509: x509.o $(OBJS) $(LIBS) +OBJS += x509.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +x509: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f x509 *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) From 87098d3324e018fd05c1729998052603391a4e71 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2020 09:58:58 +0200 Subject: [PATCH 0955/1105] build: Put archive files into build/ folder too This is something I hadn't previously done, but there are cases where it's needed, e.g., building 'wlantest' and then one of the tests/fuzzing/*/ projects, they use a different configuration (fuzzing vs. not fuzzing). Perhaps more importantly, this gets rid of the last thing that was dumped into the source directories, apart from the binaries themselves. Note that due to the use of thin archives, this required building with absolute paths. Signed-off-by: Johannes Berg --- eap_example/Makefile | 11 +----- radius_example/Makefile | 12 ++---- src/ap/Makefile | 4 +- src/build.rules | 13 +++++- src/common/Makefile | 4 +- src/crypto/Makefile | 4 +- src/eap_common/Makefile | 4 +- src/eap_peer/Makefile | 4 +- src/eap_server/Makefile | 4 +- src/eapol_auth/Makefile | 4 +- src/eapol_supp/Makefile | 4 +- src/l2_packet/Makefile | 4 +- src/objs.mk | 2 +- src/p2p/Makefile | 4 +- src/radius/Makefile | 4 +- src/rsn_supp/Makefile | 4 +- src/tls/Makefile | 4 +- src/utils/Makefile | 4 +- src/wps/Makefile | 4 +- tests/Makefile | 50 ++++-------------------- tests/fuzzing/ap-mgmt/Makefile | 6 +++ tests/fuzzing/asn1/Makefile | 3 ++ tests/fuzzing/dpp-uri/Makefile | 3 ++ tests/fuzzing/eap-aka-peer/Makefile | 3 ++ tests/fuzzing/eap-mschapv2-peer/Makefile | 3 ++ tests/fuzzing/eap-sim-peer/Makefile | 3 ++ tests/fuzzing/eapol-key-auth/Makefile | 3 ++ tests/fuzzing/eapol-key-supp/Makefile | 3 ++ tests/fuzzing/eapol-supp/Makefile | 3 ++ tests/fuzzing/json/Makefile | 3 ++ tests/fuzzing/p2p/Makefile | 3 ++ tests/fuzzing/rules.include | 46 +--------------------- tests/fuzzing/sae/Makefile | 3 ++ tests/fuzzing/tls-client/Makefile | 6 +++ tests/fuzzing/tls-server/Makefile | 6 +++ tests/fuzzing/wnm/Makefile | 6 +++ tests/fuzzing/x509/Makefile | 6 +++ wlantest/Makefile | 9 +---- 38 files changed, 121 insertions(+), 145 deletions(-) diff --git a/eap_example/Makefile b/eap_example/Makefile index 7660b8ddd..691466f03 100644 --- a/eap_example/Makefile +++ b/eap_example/Makefile @@ -90,15 +90,8 @@ OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o _OBJS_VAR := OBJS_ex include ../src/objs.mk - -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - -../src/tls/libtls.a: - $(MAKE) -C ../src/tls +_OBJS_VAR := EAP_LIBS +include ../src/objs.mk ifneq ($(CONFIG_SOLIB), yes) diff --git a/radius_example/Makefile b/radius_example/Makefile index f0e4e535a..d58a82c34 100644 --- a/radius_example/Makefile +++ b/radius_example/Makefile @@ -11,15 +11,6 @@ LIBS += ../src/crypto/libcrypto.a LIBS += ../src/utils/libutils.a LLIBS = -lrt -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - -../src/radius/libradius.a: - $(MAKE) -C ../src/radius - #CLAGS += -DCONFIG_IPV6 OBJS_ex = radius_example.o @@ -27,6 +18,9 @@ OBJS_ex = radius_example.o _OBJS_VAR := OBJS_ex include ../src/objs.mk +_OBJS_VAR := LIBS +include ../src/objs.mk + radius_example: $(OBJS_ex) $(LIBS) $(LDO) $(LDFLAGS) -o radius_example $(OBJS_ex) $(LIBS) $(LLIBS) diff --git a/src/ap/Makefile b/src/ap/Makefile index 425b12340..09d54924c 100644 --- a/src/ap/Makefile +++ b/src/ap/Makefile @@ -1,4 +1,4 @@ -ALL=libap.a +ALL=$(OUT)libap.a include ../lib.rules @@ -67,5 +67,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libap.a: $(LIB_OBJS) +$(OUT)libap.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/build.rules b/src/build.rules index 5960ba841..ec1cd66ce 100644 --- a/src/build.rules +++ b/src/build.rules @@ -9,9 +9,14 @@ ROOTDIR := $(dir $(lastword $(MAKEFILE_LIST))) ROOTDIR := $(dir $(ROOTDIR:%../src/=%))../ BUILDDIR ?= $(abspath $(ROOTDIR)build) BUILDDIR := $(BUILDDIR:%/=%) -_PROJ := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) ABSROOT := $(abspath $(ROOTDIR)) +ifeq ($(origin OUT),command line) +_PROJ := $(OUT:%/=%) +_PROJ := $(_PROJ:$(BUILDDIR)/%=%) +else +_PROJ := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) _PROJ := $(_PROJ:$(ABSROOT)/%=%) +endif ifndef CC CC=gcc @@ -88,9 +93,13 @@ $(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FI $(Q)$(CC) -c -o $@ $(CFLAGS) $< @$(E) " CC " $< +# libraries - they know how to build themselves +$(BUILDDIR)/$(PROJ)/%.a: $(CONFIG_FILE) + $(Q)mkdir -p $(BUILDDIR)/$(PROJ)/$(dir $(@:$(BUILDDIR)/$(PROJ)/%=%)) + $(Q)$(MAKE) -C $(ROOTDIR)$(dir $(@:$(BUILDDIR)/$(PROJ)/%=%)) OUT=$(abspath $(dir $@))/ + BUILDOBJ = $(patsubst %,$(BUILDDIR)/$(PROJ)/%,$(patsubst $(ROOTDIR)%,%,$(1))) .PHONY: common-clean common-clean: - $(Q)$(MAKE) -C $(ROOTDIR)/src clean $(Q)rm -rf $(ALL) $(BUILDDIR)/$(PROJ) diff --git a/src/common/Makefile b/src/common/Makefile index 4cd48d9fd..19573ebd3 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,4 +1,4 @@ -ALL=libcommon.a +ALL=$(OUT)libcommon.a include ../lib.rules @@ -21,5 +21,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libcommon.a: $(LIB_OBJS) +$(OUT)libcommon.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/crypto/Makefile b/src/crypto/Makefile index 3af5406ea..b8accd81c 100644 --- a/src/crypto/Makefile +++ b/src/crypto/Makefile @@ -1,4 +1,4 @@ -ALL=libcrypto.a +ALL=$(OUT)libcrypto.a include ../lib.rules @@ -68,5 +68,5 @@ endif _OBJS_VAR := LIB_OBJS include ../objs.mk -libcrypto.a: $(LIB_OBJS) +$(OUT)libcrypto.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/eap_common/Makefile b/src/eap_common/Makefile index 49fbbde02..b50a4b731 100644 --- a/src/eap_common/Makefile +++ b/src/eap_common/Makefile @@ -1,4 +1,4 @@ -ALL=libeap_common.a +ALL=$(OUT)libeap_common.a include ../lib.rules @@ -25,5 +25,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libeap_common.a: $(LIB_OBJS) +$(OUT)libeap_common.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile index 36439b788..d7a0372ad 100644 --- a/src/eap_peer/Makefile +++ b/src/eap_peer/Makefile @@ -1,4 +1,4 @@ -ALL=libeap_peer.a +ALL=$(OUT)libeap_peer.a include ../lib.rules @@ -17,5 +17,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libeap_peer.a: $(LIB_OBJS) +$(OUT)libeap_peer.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/eap_server/Makefile b/src/eap_server/Makefile index 946ac195e..b4261ec39 100644 --- a/src/eap_server/Makefile +++ b/src/eap_server/Makefile @@ -1,4 +1,4 @@ -ALL=libeap_server.a +ALL=$(OUT)libeap_server.a include ../lib.rules @@ -15,5 +15,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libeap_server.a: $(LIB_OBJS) +$(OUT)libeap_server.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/eapol_auth/Makefile b/src/eapol_auth/Makefile index 777979ce7..aa597eda4 100644 --- a/src/eapol_auth/Makefile +++ b/src/eapol_auth/Makefile @@ -1,4 +1,4 @@ -ALL=libeapol_auth.a +ALL=$(OUT)libeapol_auth.a include ../lib.rules @@ -10,5 +10,5 @@ LIB_OBJS = eapol_auth_sm.o eapol_auth_dump.o _OBJS_VAR := LIB_OBJS include ../objs.mk -libeapol_auth.a: $(LIB_OBJS) +$(OUT)libeapol_auth.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/eapol_supp/Makefile b/src/eapol_supp/Makefile index 265e5f25c..453e49e6b 100644 --- a/src/eapol_supp/Makefile +++ b/src/eapol_supp/Makefile @@ -1,4 +1,4 @@ -ALL=libeapol_supp.a +ALL=$(OUT)libeapol_supp.a include ../lib.rules @@ -12,5 +12,5 @@ LIB_OBJS = eapol_supp_sm.o _OBJS_VAR := LIB_OBJS include ../objs.mk -libeapol_supp.a: $(LIB_OBJS) +$(OUT)libeapol_supp.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/l2_packet/Makefile b/src/l2_packet/Makefile index ab8c86ecc..870d652bc 100644 --- a/src/l2_packet/Makefile +++ b/src/l2_packet/Makefile @@ -1,4 +1,4 @@ -ALL=libl2_packet.a +ALL=$(OUT)libl2_packet.a include ../lib.rules @@ -10,5 +10,5 @@ LIB_OBJS = l2_packet_linux.o _OBJS_VAR := LIB_OBJS include ../objs.mk -libl2_packet.a: $(LIB_OBJS) +$(OUT)libl2_packet.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/objs.mk b/src/objs.mk index df9fb17a1..54e42e699 100644 --- a/src/objs.mk +++ b/src/objs.mk @@ -1,3 +1,3 @@ $(_OBJS_VAR) := $(call BUILDOBJ,$($(_OBJS_VAR))) --include $($(_OBJS_VAR):%.o=%.d) +-include $($($(_OBJS_VAR):%.o=%.d):%.a=%.d) _DIRS += $(dir $($(_OBJS_VAR))) diff --git a/src/p2p/Makefile b/src/p2p/Makefile index c6b406661..00e1908f0 100644 --- a/src/p2p/Makefile +++ b/src/p2p/Makefile @@ -1,4 +1,4 @@ -ALL=libp2p.a +ALL=$(OUT)libp2p.a include ../lib.rules @@ -23,5 +23,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libp2p.a: $(LIB_OBJS) +$(OUT)libp2p.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/radius/Makefile b/src/radius/Makefile index 83096f0c7..5cefa390f 100644 --- a/src/radius/Makefile +++ b/src/radius/Makefile @@ -1,4 +1,4 @@ -ALL=libradius.a +ALL=$(OUT)libradius.a include ../lib.rules @@ -16,5 +16,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libradius.a: $(LIB_OBJS) +$(OUT)libradius.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/rsn_supp/Makefile b/src/rsn_supp/Makefile index 43288e3fd..f5f5cad17 100644 --- a/src/rsn_supp/Makefile +++ b/src/rsn_supp/Makefile @@ -1,4 +1,4 @@ -ALL=librsn_supp.a +ALL=$(OUT)librsn_supp.a include ../lib.rules @@ -21,5 +21,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -librsn_supp.a: $(LIB_OBJS) +$(OUT)librsn_supp.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/tls/Makefile b/src/tls/Makefile index 3fac5ee8c..5483345e5 100644 --- a/src/tls/Makefile +++ b/src/tls/Makefile @@ -1,4 +1,4 @@ -ALL=libtls.a +ALL=$(OUT)libtls.a include ../lib.rules @@ -33,5 +33,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libtls.a: $(LIB_OBJS) +$(OUT)libtls.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/utils/Makefile b/src/utils/Makefile index 7be05101f..91aba3846 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1,4 +1,4 @@ -ALL=libutils.a +ALL=$(OUT)libutils.a include ../lib.rules @@ -36,5 +36,5 @@ LIB_OBJS += edit.o _OBJS_VAR := LIB_OBJS include ../objs.mk -libutils.a: $(LIB_OBJS) +$(OUT)libutils.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/src/wps/Makefile b/src/wps/Makefile index ed928ef41..791069527 100644 --- a/src/wps/Makefile +++ b/src/wps/Makefile @@ -1,4 +1,4 @@ -ALL=libwps.a +ALL=$(OUT)libwps.a include ../lib.rules @@ -35,5 +35,5 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -libwps.a: $(LIB_OBJS) +$(OUT)libwps.a: $(LIB_OBJS) $(AR) crT $@ $? diff --git a/tests/Makefile b/tests/Makefile index c8ba3f21c..72fb8ee4f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -42,55 +42,19 @@ DLIBS = ../src/crypto/libcrypto.a \ ../src/rsn_supp/librsn_supp.a \ ../src/tls/libtls.a +_OBJS_VAR := LLIBS +include ../src/objs.mk +_OBJS_VAR := SLIBS +include ../src/objs.mk +_OBJS_VAR := DLIBS +include ../src/objs.mk + LIBS = $(SLIBS) $(DLIBS) LLIBS = -Wl,--start-group $(DLIBS) -Wl,--end-group $(SLIBS) # glibc < 2.17 needs -lrt for clock_gettime() LLIBS += -lrt -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/common/libcommon.a: - $(MAKE) -C ../src/common - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - -../src/tls/libtls.a: - $(MAKE) -C ../src/tls - -../src/ap/libap.a: - $(MAKE) -C ../src/ap - -../src/radius/libradius.a: - $(MAKE) -C ../src/radius - -../src/l2_packet/libl2_packet.a: - $(MAKE) -C ../src/l2_packet - -../src/wps/libwps.a: - $(MAKE) -C ../src/wps - -../src/eap_peer/libeap_peer.a: - $(MAKE) -C ../src/eap_peer - -../src/eap_server/libeap_server.a: - $(MAKE) -C ../src/eap_server - -../src/eap_common/libeap_common.a: - $(MAKE) -C ../src/eap_common - -../src/eapol_auth/libeapol_auth.a: - $(MAKE) -C ../src/eapol_auth - -../src/eapol_supp/libeapol_supp.a: - $(MAKE) -C ../src/eapol_supp - -../src/rsn_supp/librsn_supp.a: - $(MAKE) -C ../src/rsn_supp - - test-aes: $(call BUILDOBJ,test-aes.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) diff --git a/tests/fuzzing/ap-mgmt/Makefile b/tests/fuzzing/ap-mgmt/Makefile index 159c7c3f8..74b6a02da 100644 --- a/tests/fuzzing/ap-mgmt/Makefile +++ b/tests/fuzzing/ap-mgmt/Makefile @@ -31,6 +31,12 @@ OBJS += ap-mgmt.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + ap-mgmt: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) diff --git a/tests/fuzzing/asn1/Makefile b/tests/fuzzing/asn1/Makefile index fb8fbed68..274641a40 100644 --- a/tests/fuzzing/asn1/Makefile +++ b/tests/fuzzing/asn1/Makefile @@ -12,6 +12,9 @@ OBJS += asn1.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + asn1: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile index aca8f02ad..1c1bab631 100644 --- a/tests/fuzzing/dpp-uri/Makefile +++ b/tests/fuzzing/dpp-uri/Makefile @@ -33,6 +33,9 @@ OBJS += dpp-uri.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + dpp-uri: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto diff --git a/tests/fuzzing/eap-aka-peer/Makefile b/tests/fuzzing/eap-aka-peer/Makefile index bd960caa7..c964f186d 100644 --- a/tests/fuzzing/eap-aka-peer/Makefile +++ b/tests/fuzzing/eap-aka-peer/Makefile @@ -15,6 +15,9 @@ OBJS += eap-aka-peer.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + eap-aka-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ diff --git a/tests/fuzzing/eap-mschapv2-peer/Makefile b/tests/fuzzing/eap-mschapv2-peer/Makefile index 953855c85..7290e90c6 100644 --- a/tests/fuzzing/eap-mschapv2-peer/Makefile +++ b/tests/fuzzing/eap-mschapv2-peer/Makefile @@ -14,6 +14,9 @@ OBJS += eap-mschapv2-peer.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + eap-mschapv2-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ diff --git a/tests/fuzzing/eap-sim-peer/Makefile b/tests/fuzzing/eap-sim-peer/Makefile index 9292ccb79..9e728e4f4 100644 --- a/tests/fuzzing/eap-sim-peer/Makefile +++ b/tests/fuzzing/eap-sim-peer/Makefile @@ -15,6 +15,9 @@ OBJS += eap-sim-peer.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + eap-sim-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ diff --git a/tests/fuzzing/eapol-key-auth/Makefile b/tests/fuzzing/eapol-key-auth/Makefile index bdc731ff4..bd15b91f2 100644 --- a/tests/fuzzing/eapol-key-auth/Makefile +++ b/tests/fuzzing/eapol-key-auth/Makefile @@ -24,6 +24,9 @@ OBJS += eapol-key-auth.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + eapol-key-auth: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group diff --git a/tests/fuzzing/eapol-key-supp/Makefile b/tests/fuzzing/eapol-key-supp/Makefile index 29e419b7c..949e2efe9 100644 --- a/tests/fuzzing/eapol-key-supp/Makefile +++ b/tests/fuzzing/eapol-key-supp/Makefile @@ -20,6 +20,9 @@ OBJS += eapol-key-supp.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + eapol-key-supp: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group diff --git a/tests/fuzzing/eapol-supp/Makefile b/tests/fuzzing/eapol-supp/Makefile index 27e631148..ea32346b2 100644 --- a/tests/fuzzing/eapol-supp/Makefile +++ b/tests/fuzzing/eapol-supp/Makefile @@ -18,6 +18,9 @@ OBJS += eapol-supp.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + eapol-supp: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group diff --git a/tests/fuzzing/json/Makefile b/tests/fuzzing/json/Makefile index 8de19293e..9dd51a5f2 100644 --- a/tests/fuzzing/json/Makefile +++ b/tests/fuzzing/json/Makefile @@ -13,6 +13,9 @@ OBJS += json.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + json: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) diff --git a/tests/fuzzing/p2p/Makefile b/tests/fuzzing/p2p/Makefile index ef31a7505..acac9d38f 100644 --- a/tests/fuzzing/p2p/Makefile +++ b/tests/fuzzing/p2p/Makefile @@ -13,6 +13,9 @@ OBJS += p2p.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + p2p: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) diff --git a/tests/fuzzing/rules.include b/tests/fuzzing/rules.include index b2e8a81ea..e2cf577af 100644 --- a/tests/fuzzing/rules.include +++ b/tests/fuzzing/rules.include @@ -27,47 +27,5 @@ SRC=../../../src CFLAGS += -I$(SRC) -I$(SRC)/utils -I$(WPAS_SRC) OBJS += ../fuzzer-common.o -$(SRC)/ap/libap.a: - $(MAKE) -C $(SRC)/ap TEST_FUZZ=y - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto TEST_FUZZ=y - -$(SRC)/eapol_auth/libeapol_auth.a: - $(MAKE) -C $(SRC)/eapol_auth - -$(SRC)/eapol_supp/libeapol_supp.a: - $(MAKE) -C $(SRC)/eapol_supp - -$(SRC)/eap_common/libeap_common.a: - $(MAKE) -C $(SRC)/eap_common - -$(SRC)/eap_peer/libeap_peer.a: - $(MAKE) -C $(SRC)/eap_peer - -$(SRC)/eap_server/libeap_server.a: - $(MAKE) -C $(SRC)/eap_server - -$(SRC)/l2_packet/libl2_packet.a: - $(MAKE) -C $(SRC)/l2_packet - -$(SRC)/p2p/libp2p.a: - $(MAKE) -C $(SRC)/p2p - -$(SRC)/radius/libradius.a: - $(MAKE) -C $(SRC)/radius - -$(SRC)/rsn_supp/librsn_supp.a: - $(MAKE) -C $(SRC)/rsn_supp TEST_FUZZ=y - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls TEST_FUZZ=y - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils TEST_FUZZ=y - -$(SRC)/wps/libwps.a: - $(MAKE) -C $(SRC)/wps +# for the lib builds +export TEST_FUZZ=y diff --git a/tests/fuzzing/sae/Makefile b/tests/fuzzing/sae/Makefile index ee7257afe..ee4b0c0b6 100644 --- a/tests/fuzzing/sae/Makefile +++ b/tests/fuzzing/sae/Makefile @@ -18,6 +18,9 @@ OBJS += sae.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + sae: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto diff --git a/tests/fuzzing/tls-client/Makefile b/tests/fuzzing/tls-client/Makefile index 7d5e8d536..84cfa0431 100644 --- a/tests/fuzzing/tls-client/Makefile +++ b/tests/fuzzing/tls-client/Makefile @@ -19,6 +19,12 @@ OBJS += tls-client.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + tls-client: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) diff --git a/tests/fuzzing/tls-server/Makefile b/tests/fuzzing/tls-server/Makefile index 45304328e..8e2400310 100644 --- a/tests/fuzzing/tls-server/Makefile +++ b/tests/fuzzing/tls-server/Makefile @@ -19,6 +19,12 @@ OBJS += tls-server.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + tls-server: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) diff --git a/tests/fuzzing/wnm/Makefile b/tests/fuzzing/wnm/Makefile index f27dd341b..73eab5387 100644 --- a/tests/fuzzing/wnm/Makefile +++ b/tests/fuzzing/wnm/Makefile @@ -47,6 +47,12 @@ OBJS += wnm.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + wnm: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) diff --git a/tests/fuzzing/x509/Makefile b/tests/fuzzing/x509/Makefile index 7fff15a3a..306473c3d 100644 --- a/tests/fuzzing/x509/Makefile +++ b/tests/fuzzing/x509/Makefile @@ -14,6 +14,12 @@ OBJS += x509.o _OBJS_VAR := OBJS include ../../../src/objs.mk +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + x509: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) diff --git a/wlantest/Makefile b/wlantest/Makefile index 410c309d4..602375112 100644 --- a/wlantest/Makefile +++ b/wlantest/Makefile @@ -62,13 +62,6 @@ TOBJS += bip.o TOBJS += gcmp.o -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - - OBJS_cli = wlantest_cli.o _OBJS_VAR := OBJS @@ -77,6 +70,8 @@ _OBJS_VAR := TOBJS include ../src/objs.mk _OBJS_VAR := OBJS_cli include ../src/objs.mk +_OBJS_VAR := OWN_LIBS +include ../src/objs.mk wlantest: $(OBJS) $(OWN_LIBS) $(LDO) $(LDFLAGS) -o wlantest $(OBJS) $(OWN_LIBS) $(LIBS) From ae0b90dfa4f2db5992269a9335df1fc156e55b24 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Fri, 26 Jun 2020 16:20:43 +0200 Subject: [PATCH 0956/1105] mesh: Allow channel switch command Signed-off-by: Markus Theil --- wpa_supplicant/ap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 2accf92cd..de3027dd7 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -1418,10 +1418,17 @@ int ap_switch_channel(struct wpa_supplicant *wpa_s, struct csa_settings *settings) { #ifdef NEED_AP_MLME - if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) + struct hostapd_iface *iface = NULL; + + if (wpa_s->ap_iface) + iface = wpa_s->ap_iface; + else if (wpa_s->ifmsh) + iface = wpa_s->ifmsh; + + if (!iface || !iface->bss[0]) return -1; - return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings); + return hostapd_switch_channel(iface->bss[0], settings); #else /* NEED_AP_MLME */ return -1; #endif /* NEED_AP_MLME */ From 283eee8eede8519e574300a7348f2fecdd2a1bb6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2020 10:06:14 +0200 Subject: [PATCH 0957/1105] gitignore: Clean up a bit Now that we no longer leave build artifacts outside the build folder, we can clean up the gitignore a bit. Also move more things to per-folder files that we mostly had already anyway. Signed-off-by: Johannes Berg --- .gitignore | 28 ---------------------------- hostapd/.gitignore | 5 +++++ src/crypto/.gitignore | 1 - src/drivers/.gitignore | 2 -- src/radius/.gitignore | 1 - src/tls/.gitignore | 1 - src/utils/.gitignore | 1 - wlantest/.gitignore | 4 ++++ wpa_supplicant/.gitignore | 14 ++++++++++++++ 9 files changed, 23 insertions(+), 34 deletions(-) create mode 100644 hostapd/.gitignore delete mode 100644 src/crypto/.gitignore delete mode 100644 src/drivers/.gitignore delete mode 100644 src/radius/.gitignore delete mode 100644 src/tls/.gitignore delete mode 100644 src/utils/.gitignore create mode 100644 wlantest/.gitignore diff --git a/.gitignore b/.gitignore index 52a77fc01..debae2d23 100644 --- a/.gitignore +++ b/.gitignore @@ -1,37 +1,9 @@ -*.a -*.o -*.d -*.gcno -*.gcda -*.gcov *.pyc *~ -.config tests/hwsim/logs tests/remote/logs wpaspy/build -wpa_supplicant/eapol_test -wpa_supplicant/nfc_pw_token -wpa_supplicant/preauth_test -wpa_supplicant/wpa_cli -wpa_supplicant/wpa_passphrase -wpa_supplicant/wpa_supplicant -wpa_supplicant/wpa_priv -wpa_supplicant/wpa_gui/Makefile -wpa_supplicant/wpa_gui/wpa_gui -wpa_supplicant/wpa_gui-qt4/Makefile -wpa_supplicant/wpa_gui-qt4/wpa_gui -wpa_supplicant/libwpa_test1 -wpa_supplicant/libwpa_test2 -hostapd/hostapd -hostapd/hostapd_cli -hostapd/hlr_auc_gw -hostapd/nt_password_hash mac80211_hwsim/tools/hwsim_test -wlantest/libwlantest.a -wlantest/test_vectors -wlantest/wlantest -wlantest/wlantest_cli **/parallel-vm.log tags build/ diff --git a/hostapd/.gitignore b/hostapd/.gitignore new file mode 100644 index 000000000..857f3dc41 --- /dev/null +++ b/hostapd/.gitignore @@ -0,0 +1,5 @@ +.config +hostapd +hostapd_cli +hlr_auc_gw +nt_password_hash diff --git a/src/crypto/.gitignore b/src/crypto/.gitignore deleted file mode 100644 index ee606048c..000000000 --- a/src/crypto/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libcrypto.a diff --git a/src/drivers/.gitignore b/src/drivers/.gitignore deleted file mode 100644 index 1d9e0e661..000000000 --- a/src/drivers/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build.wpa_supplicant -build.hostapd diff --git a/src/radius/.gitignore b/src/radius/.gitignore deleted file mode 100644 index a89a1f927..000000000 --- a/src/radius/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libradius.a diff --git a/src/tls/.gitignore b/src/tls/.gitignore deleted file mode 100644 index d43242d73..000000000 --- a/src/tls/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libtls.a diff --git a/src/utils/.gitignore b/src/utils/.gitignore deleted file mode 100644 index 833734f88..000000000 --- a/src/utils/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libutils.a diff --git a/wlantest/.gitignore b/wlantest/.gitignore new file mode 100644 index 000000000..7ffabe601 --- /dev/null +++ b/wlantest/.gitignore @@ -0,0 +1,4 @@ +libwlantest.a +test_vectors +wlantest +wlantest_cli diff --git a/wpa_supplicant/.gitignore b/wpa_supplicant/.gitignore index 0e3ad1b06..ff741201e 100644 --- a/wpa_supplicant/.gitignore +++ b/wpa_supplicant/.gitignore @@ -1 +1,15 @@ +.config *.service +eapol_test +nfc_pw_token +preauth_test +wpa_cli +wpa_passphrase +wpa_supplicant +wpa_priv +wpa_gui/Makefile +wpa_gui/wpa_gui +wpa_gui-qt4/Makefile +wpa_gui-qt4/wpa_gui +libwpa_test1 +libwpa_test2 From 45a1bfd956786c066b8e96f794d873e9d2b913f2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 11 Oct 2020 19:36:18 +0300 Subject: [PATCH 0958/1105] gitignore: Remove obsolete mac80211_hwsim entry That directory was removed last year, so no need to try to ignore the build result from there anymore. Signed-off-by: Jouni Malinen --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index debae2d23..b064303ce 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ tests/hwsim/logs tests/remote/logs wpaspy/build -mac80211_hwsim/tools/hwsim_test **/parallel-vm.log tags build/ From 27fb429e9558ca7f15941fd17048fa789937ee77 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2020 10:20:51 +0200 Subject: [PATCH 0959/1105] wpaspy: Allow building with python3 Add the necessary modified module registration code to allow building wpaspy with python3. Also clean up the wpaspy_close() function to not poke into the python version specific details. Signed-off-by: Johannes Berg --- wpaspy/Makefile | 1 + wpaspy/wpaspy.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/wpaspy/Makefile b/wpaspy/Makefile index bc920e0cc..6f720a9fe 100644 --- a/wpaspy/Makefile +++ b/wpaspy/Makefile @@ -2,6 +2,7 @@ all: build SRC=wpaspy.c +.PHONY: build build: $(SRC) setup.py python setup.py build diff --git a/wpaspy/wpaspy.c b/wpaspy/wpaspy.c index 278089b48..4d4c2a495 100644 --- a/wpaspy/wpaspy.c +++ b/wpaspy/wpaspy.c @@ -44,8 +44,7 @@ static void wpaspy_close(struct wpaspy_obj *self) self->ctrl = NULL; } - if (self->ob_type) - self->ob_type->tp_free((PyObject *) self); + PyObject_Del(self); } @@ -193,6 +192,7 @@ static PyTypeObject wpaspy_ctrl = { }; +#if PY_MAJOR_VERSION < 3 static PyMethodDef module_methods[] = { { NULL, NULL, 0, NULL } }; @@ -212,3 +212,34 @@ PyMODINIT_FUNC initwpaspy(void) PyModule_AddObject(mod, "Ctrl", (PyObject *) &wpaspy_ctrl); PyModule_AddObject(mod, "error", wpaspy_error); } +#else +static struct PyModuleDef wpaspy_def = { + PyModuleDef_HEAD_INIT, + "wpaspy", +}; + + +PyMODINIT_FUNC initwpaspy(void) +{ + PyObject *mod; + + mod = PyModule_Create(&wpaspy_def); + if (!mod) + return NULL; + + wpaspy_error = PyErr_NewException("wpaspy.error", NULL, NULL); + + Py_INCREF(&wpaspy_ctrl); + Py_INCREF(wpaspy_error); + + if (PyModule_AddObject(mod, "Ctrl", (PyObject *) &wpaspy_ctrl) < 0 || + PyModule_AddObject(mod, "error", wpaspy_error) < 0) { + Py_DECREF(&wpaspy_ctrl); + Py_DECREF(wpaspy_error); + Py_DECREF(mod); + mod = NULL; + } + + return mod; +} +#endif From e7c11ad24990598e71105270f7627d57a431b508 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2020 11:01:03 +0200 Subject: [PATCH 0960/1105] tests: build.sh: Remove 'make clean' steps Since the build artifacts are now landing in distinct directories, we don't need to 'make clean' and save some rebuild time. Signed-off-by: Johannes Berg --- tests/hwsim/build.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/hwsim/build.sh b/tests/hwsim/build.sh index 165d808fd..d8a78d705 100755 --- a/tests/hwsim/build.sh +++ b/tests/hwsim/build.sh @@ -28,17 +28,14 @@ done echo "Building TNC testing tools" cd tnc -make clean > /dev/null make QUIET=1 -j8 echo "Building wlantest" cd ../../../wlantest -make clean > /dev/null make QUIET=1 -j8 > /dev/null echo "Building hs20-osu-client" cd ../hs20/client/ -make clean > /dev/null 2>&1 make QUIET=1 CONFIG_NO_BROWSER=1 echo "Building hostapd" @@ -55,7 +52,6 @@ if [ $use_lcov -eq 1 ]; then fi fi -make clean > /dev/null make QUIET=1 -j8 hostapd hostapd_cli hlr_auc_gw echo "Building wpa_supplicant" @@ -72,7 +68,6 @@ if [ $use_lcov -eq 1 ]; then fi fi -make clean > /dev/null if [ -z $FIPSLD_CC ]; then export FIPSLD_CC=gcc fi From 5c7a048e451bed3bf34824e4d1be2b90689fdb9e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2020 11:04:38 +0200 Subject: [PATCH 0961/1105] tests: build.sh: Avoid copying .config if identical If the .config file is already identical, avoid copying it even if -f was specified; this improves build time if nothing has changed. Signed-off-by: Johannes Berg --- tests/hwsim/build.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/build.sh b/tests/hwsim/build.sh index d8a78d705..2a3dd706e 100755 --- a/tests/hwsim/build.sh +++ b/tests/hwsim/build.sh @@ -41,7 +41,9 @@ make QUIET=1 CONFIG_NO_BROWSER=1 echo "Building hostapd" cd ../../hostapd if [ ! -e .config -o $force_config -eq 1 ]; then - cp ../tests/hwsim/example-hostapd.config .config + if ! cmp ../tests/hwsim/example-hostapd.config .config >/dev/null 2>&1 ; then + cp ../tests/hwsim/example-hostapd.config .config + fi fi if [ $use_lcov -eq 1 ]; then @@ -57,7 +59,9 @@ make QUIET=1 -j8 hostapd hostapd_cli hlr_auc_gw echo "Building wpa_supplicant" cd ../wpa_supplicant if [ ! -e .config -o $force_config -eq 1 ]; then - cp ../tests/hwsim/example-wpa_supplicant.config .config + if ! cmp ../tests/hwsim/example-wpa_supplicant.config .config >/dev/null 2>&1 ; then + cp ../tests/hwsim/example-wpa_supplicant.config .config + fi fi if [ $use_lcov -eq 1 ]; then From 7e4ed93d3654752c818c5cf08d0686a0f7846f00 Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Mon, 14 Sep 2020 22:42:55 +0000 Subject: [PATCH 0962/1105] wpa_cli: Add dpp_bootstrap_set command Expose DPP_BOOTSTRAP_SET through wpa_cli command dpp_bootstrap_set Signed-off-by: Andrew Beltrano --- wpa_supplicant/wpa_cli.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index f5b02f662..5c7f5eef3 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -2994,6 +2994,13 @@ static int wpa_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc, } +static int wpa_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv); +} + + static int wpa_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -3764,6 +3771,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "dpp_bootstrap_info", wpa_cli_cmd_dpp_bootstrap_info, NULL, cli_cmd_flag_none, " = show DPP bootstrap information" }, + { "dpp_bootstrap_set", wpa_cli_cmd_dpp_bootstrap_set, NULL, + cli_cmd_flag_none, + " [conf=..] [ssid=] [ssid_charset=#] [psk=] [pass=] [configurator=] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" }, { "dpp_auth_init", wpa_cli_cmd_dpp_auth_init, NULL, cli_cmd_flag_none, "peer= [own=] = initiate DPP bootstrapping" }, { "dpp_listen", wpa_cli_cmd_dpp_listen, NULL, cli_cmd_flag_none, From 1a0169695b94787dbf33d4c726e32138eebe439d Mon Sep 17 00:00:00 2001 From: Andrew Beltrano Date: Mon, 14 Sep 2020 22:42:59 +0000 Subject: [PATCH 0963/1105] hostapd_cli: Add dpp_bootstrap_set command Expose DPP_BOOTSTRAP_SET through hostapd_cli command dpp_bootstrap_set Signed-off-by: Andrew Beltrano --- hostapd/hostapd_cli.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 440664e9b..01dcfe823 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -1402,6 +1402,13 @@ static int hostapd_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc, } +static int hostapd_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv); +} + + static int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1650,6 +1657,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { " = get DPP bootstrap URI" }, { "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL, " = show DPP bootstrap information" }, + { "dpp_bootstrap_set", hostapd_cli_cmd_dpp_bootstrap_set, NULL, + " [conf=..] [ssid=] [ssid_charset=#] [psk=] [pass=] [configurator=] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" }, { "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL, "peer= [own=] = initiate DPP bootstrapping" }, { "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL, From 0e9f62e5140dd202e435b713e85a31efb8bc9d52 Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Wed, 2 Sep 2020 16:50:11 +0800 Subject: [PATCH 0964/1105] P2P: Fallback to GO negotiation after running out of GO scan attempts We found a problem that p2p_fallback_to_go_neg is not handled correctly after running out of GO scan attempts. When autojoin is enabled and a group is found in old scan results, supplicant would try to scan the group several times. If the group is still not found, it reports group formation failure while p2p_fallback_to_go_neg is enabled already. If p2p_fallback_to_go_neg is enabled, it should fallback to GO negotiation, but not report group formation failure after running out of GO scan attempts. Signed-off-by: Jimmy Chen --- wpa_supplicant/p2p_supplicant.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 64ba34450..78798151f 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -4977,6 +4977,15 @@ static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s) MAC2STR(wpa_s->pending_join_dev_addr)); return; } + if (wpa_s->p2p_fallback_to_go_neg) { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Join operation failed - fall back to GO Negotiation"); + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, + P2P_EVENT_FALLBACK_TO_GO_NEG + "reason=join-failed"); + wpas_p2p_fallback_to_go_neg(wpa_s, 0); + return; + } wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_GROUP_FORMATION_FAILURE); wpas_notify_p2p_group_formation_failure(wpa_s, ""); From cb3b7093676adcb10a391fc16422f5b030b5ffb7 Mon Sep 17 00:00:00 2001 From: Jimmy Chen Date: Wed, 26 Aug 2020 18:55:45 +0800 Subject: [PATCH 0965/1105] P2P: Set ap_configured_cb during group reform process We found that if REMOVE-AND-REFORM occurs before a group is started, it would not send out GROUP-STARTED-EVENT after AP is enabled. In the remove-and-reform process, ap_configured_cb is cleared. If a group is not started, p2p_go_configured() will not be called after completing AP setup. Fix this by preserving the callback parameters. Signed-off-by: Jimmy Chen --- wpa_supplicant/p2p_supplicant.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 78798151f..4c083f865 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -9463,6 +9463,8 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s) { struct p2p_go_neg_results params; struct wpa_ssid *current_ssid = wpa_s->current_ssid; + void (*ap_configured_cb)(void *ctx, void *data); + void *ap_configured_cb_ctx, *ap_configured_cb_data; wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_REMOVE_AND_REFORM_GROUP); @@ -9472,6 +9474,13 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s) /* Stop the AP functionality */ /* TODO: Should do this in a way that does not indicated to possible * P2P Clients in the group that the group is terminated. */ + /* If this action occurs before a group is started, the callback should + * be preserved, or GROUP-STARTED event would be lost. If this action + * occurs after a group is started, these pointers are all NULL and + * harmless. */ + ap_configured_cb = wpa_s->ap_configured_cb; + ap_configured_cb_ctx = wpa_s->ap_configured_cb_ctx; + ap_configured_cb_data = wpa_s->ap_configured_cb_data; wpa_supplicant_ap_deinit(wpa_s); /* Reselect the GO frequency */ @@ -9495,6 +9504,11 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s) return; } + /* Restore preserved callback parameters */ + wpa_s->ap_configured_cb = ap_configured_cb; + wpa_s->ap_configured_cb_ctx = ap_configured_cb_ctx; + wpa_s->ap_configured_cb_data = ap_configured_cb_data; + /* Update the frequency */ current_ssid->frequency = params.freq; wpa_s->connect_without_scan = current_ssid; From e3b47cdf86e8f8ebafd1b3c4fd631e5b18a811c3 Mon Sep 17 00:00:00 2001 From: Wystan Schmidt Date: Fri, 24 Jul 2020 15:29:39 -0600 Subject: [PATCH 0966/1105] DPP2: Add DPP_CHIRP commands to hostapd_cli and wpa_cli Add the DPP control interface chirp commands to the CLIs for greater visibility and ease of use. Signed-off-by: Wystan Schmidt --- hostapd/hostapd_cli.c | 23 +++++++++++++++++++++++ wpa_supplicant/wpa_cli.c | 25 +++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 01dcfe823..363ae0ee7 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -1471,6 +1471,23 @@ static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, return hostapd_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv); } + +#ifdef CONFIG_DPP2 + +static int hostapd_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return hostapd_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv); +} + + +static int hostapd_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP"); +} + +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ @@ -1679,6 +1696,12 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { "add PKEX code" }, { "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL, "*| = remove DPP pkex information" }, +#ifdef CONFIG_DPP2 + { "dpp_chirp", hostapd_cli_cmd_dpp_chirp, NULL, + "own= iter= = start DPP chirp" }, + { "dpp_stop_chirp", hostapd_cli_cmd_dpp_stop_chirp, NULL, + "= stop DPP chirp" }, +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ { "accept_acl", hostapd_cli_cmd_accept_macacl, NULL, "=Add/Delete/Show/Clear accept MAC ACL" }, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 5c7f5eef3..51c9642e9 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -3063,6 +3063,23 @@ static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, return wpa_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv); } + +#ifdef CONFIG_DPP2 + +static int wpa_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP"); +} + +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ @@ -3799,6 +3816,14 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "dpp_pkex_remove", wpa_cli_cmd_dpp_pkex_remove, NULL, cli_cmd_flag_none, "*| = remove DPP pkex information" }, +#ifdef CONFIG_DPP2 + { "dpp_chirp", wpa_cli_cmd_dpp_chirp, NULL, + cli_cmd_flag_none, + "own= iter= = start DPP chirp" }, + { "dpp_stop_chirp", wpa_cli_cmd_dpp_stop_chirp, NULL, + cli_cmd_flag_none, + "= stop DPP chirp" }, +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ { "all_bss", wpa_cli_cmd_all_bss, NULL, cli_cmd_flag_none, "= list all BSS entries (scan results)" }, From 79db311e89d8f662300e3bd62c7386428fb0a430 Mon Sep 17 00:00:00 2001 From: Ze Gan Date: Thu, 2 Jul 2020 12:16:52 +0800 Subject: [PATCH 0967/1105] macsec_linux: Fix receive-lowest-PN setting Setting of the PN for the receive SA failed because the SCI wasn't provided. Fix this by adding the needed attribute to the command. Signed-off-by: Ze Gan --- src/drivers/driver_macsec_linux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/driver_macsec_linux.c b/src/drivers/driver_macsec_linux.c index 36a0757fe..3dba13ce7 100644 --- a/src/drivers/driver_macsec_linux.c +++ b/src/drivers/driver_macsec_linux.c @@ -712,6 +712,9 @@ static int macsec_drv_set_receive_lowest_pn(void *priv, struct receive_sa *sa) if (!msg) return ret; + if (nla_put_rxsc_config(msg, mka_sci_u64(&sa->sc->sci))) + goto nla_put_failure; + nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG); if (!nest) goto nla_put_failure; From 154b18d950588c463806ac5b80ade189ea8eb9e7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 11 Oct 2020 21:24:34 +0200 Subject: [PATCH 0968/1105] build: Fix dependency file inclusion The objs.mk include changes for archive files broke things completely and none of the dependency files (*.d) ever got included, as the expansion there ended up empty. Clearly, my mistake, I should've tested that better. As we don't need the %.a files in the list there use filter-out to remove them, rather than what I had lazily wanted to do, which was trying to read %.d files for them. The filter-out actually works, and avoids looking up files that can never exist in the first place. Fixes: 87098d3324e0 ("build: Put archive files into build/ folder too") Signed-off-by: Johannes Berg --- src/objs.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objs.mk b/src/objs.mk index 54e42e699..a3040b21b 100644 --- a/src/objs.mk +++ b/src/objs.mk @@ -1,3 +1,3 @@ $(_OBJS_VAR) := $(call BUILDOBJ,$($(_OBJS_VAR))) --include $($($(_OBJS_VAR):%.o=%.d):%.a=%.d) +-include $(filter-out %.a,$($(_OBJS_VAR):%.o=%.d)) _DIRS += $(dir $($(_OBJS_VAR))) From ee03056a621f13dd1384ecc8656d85bc58481bac Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Mon, 29 Jun 2020 08:23:01 +0900 Subject: [PATCH 0969/1105] tests: Fix mesh_secure_ocv_mix_legacy false negative by using common finalizer mesh_secure_ocv_mix_legacy might fail with this message: --------------- wlan0: Country code not reset back to 00: is AZ wlan0: Country code cleared back to 00 --------------- This patch fixes the issue. Signed-off-by: Masashi Honma --- tests/hwsim/test_wpas_mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 3c918184f..8298d482d 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -406,7 +406,7 @@ def set_reg(dev, country): def clear_reg_setting(dev): dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) + clear_regdom_dev(dev) dev[0].flush_scan_cache() dev[1].flush_scan_cache() From 0bea288fbe9cdbae411ed6b3cb3e450c9d6f5ae1 Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Mon, 29 Jun 2020 08:23:02 +0900 Subject: [PATCH 0970/1105] tests: Fix wpas_mesh_open_5ghz false negative by using common finalizer wpas_mesh_open_5ghz might fail with this message: --------------- wlan0: Country code not reset back to 00: is US wlan0: Country code cleared back to 00 --------------- This patch fixes the issue. Signed-off-by: Masashi Honma --- tests/hwsim/test_wpas_mesh.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 8298d482d..6e32ce67e 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -906,11 +906,7 @@ def test_wpas_mesh_open_5ghz(dev, apdev): try: _test_wpas_mesh_open_5ghz(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_wpas_mesh_open_5ghz(dev, apdev): check_mesh_support(dev[0]) From 5eea042220138acd930eaf4504d6936153d2ed90 Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Mon, 29 Jun 2020 08:23:03 +0900 Subject: [PATCH 0971/1105] tests: Fix wpas_mesh_open_ht40 false negative by using common finalizer wpas_mesh_open_ht40 might fail with this message: --------------- wlan0: Country code not reset back to 00: is US wlan0: Country code cleared back to 00 --------------- This patch fixes the issue. Signed-off-by: Masashi Honma --- tests/hwsim/test_wpas_mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 6e32ce67e..8082e46f2 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -988,7 +988,7 @@ def test_wpas_mesh_open_ht40(dev, apdev): dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) dev[2].request("MESH_GROUP_REMOVE " + dev[2].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) + clear_regdom_dev(dev) dev[0].flush_scan_cache() dev[1].flush_scan_cache() dev[2].flush_scan_cache() From 91de752d17bae55e20fe2ddc1949d17212fc67d0 Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Mon, 29 Jun 2020 08:23:04 +0900 Subject: [PATCH 0972/1105] tests: Fix wpas_mesh_open_vht40 false negative by using common finalizer wpas_mesh_open_vht40 might fail with this message: --------------- wlan0: Country code not reset back to 00: is US wlan0: Country code cleared back to 00 --------------- This patch fixes the issue. Signed-off-by: Masashi Honma --- tests/hwsim/test_wpas_mesh.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 8082e46f2..4472eb68b 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -1033,11 +1033,7 @@ def test_wpas_mesh_open_vht40(dev, apdev): try: _test_wpas_mesh_open_vht40(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_wpas_mesh_open_vht40(dev, apdev): check_mesh_support(dev[0]) From 54830a244558a36d8804bb0c47d94fda8fec6777 Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Mon, 29 Jun 2020 08:23:05 +0900 Subject: [PATCH 0973/1105] tests: Fix wpas_mesh_open_vht20 false negative by using common finalizer wpas_mesh_open_vht20 might fails with this message: --------------- wlan0: Country code not reset back to 00: is US wlan0: Country code cleared back to 00 --------------- This patch fixes the issue. Signed-off-by: Masashi Honma --- tests/hwsim/test_wpas_mesh.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 4472eb68b..78b0b33cb 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -1081,11 +1081,7 @@ def test_wpas_mesh_open_vht20(dev, apdev): try: _test_wpas_mesh_open_vht20(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_wpas_mesh_open_vht20(dev, apdev): check_mesh_support(dev[0]) From fd59cc8924eab95e71733283d0be9e6a026d70bb Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Mon, 29 Jun 2020 08:23:06 +0900 Subject: [PATCH 0974/1105] tests: Fix wpas_mesh_open_vht_80p80 false negative by using common finalizer wpas_mesh_open_vht_80p80 might fail with this message: --------------- wlan0: Country code not reset back to 00: is US wlan0: Country code cleared back to 00 --------------- This patch fixes the issue. Signed-off-by: Masashi Honma --- tests/hwsim/test_wpas_mesh.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 78b0b33cb..b10a5d1f5 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -1121,11 +1121,7 @@ def test_wpas_mesh_open_vht_80p80(dev, apdev): try: _test_wpas_mesh_open_vht_80p80(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_wpas_mesh_open_vht_80p80(dev, apdev): check_mesh_support(dev[0]) From 267d619798d7f9d022fe05e2335d24b701971889 Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Mon, 29 Jun 2020 08:23:07 +0900 Subject: [PATCH 0975/1105] tests: Fix mesh_open_vht_160 false negative by using common finalizer mesh_open_vht_160 might fail with this message: --------------- wlan0: Country code not reset back to 00: is ZA wlan0: Country code cleared back to 00 --------------- This patch fixes the issue. Signed-off-by: Masashi Honma --- tests/hwsim/test_wpas_mesh.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index b10a5d1f5..64e3cc66d 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -1165,11 +1165,7 @@ def test_mesh_open_vht_160(dev, apdev): try: _test_mesh_open_vht_160(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_mesh_open_vht_160(dev, apdev): check_mesh_support(dev[0]) From 6c41d43f1abd1685c0a11fe435e8834602baa442 Mon Sep 17 00:00:00 2001 From: Udhayakumar Mahendiran Date: Mon, 12 Oct 2020 16:45:29 +0530 Subject: [PATCH 0976/1105] mesh: Stop SAE auth timer when mesh node is removed Not doing this could cause wpa_supplicant to crash. Signed-off-by: Udhayakumar Mahendiran --- wpa_supplicant/mesh_mpm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 4547eea88..b6a5e8857 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -540,6 +540,7 @@ static int mesh_mpm_plink_close(struct hostapd_data *hapd, struct sta_info *sta, wpa_printf(MSG_DEBUG, "MPM closing plink sta=" MACSTR, MAC2STR(sta->addr)); eloop_cancel_timeout(plink_timer, wpa_s, sta); + eloop_cancel_timeout(mesh_auth_timer, wpa_s, sta); return 0; } From ac1447ae9db84993e092524ae6eb9b362f11442a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 Oct 2020 11:30:53 +0200 Subject: [PATCH 0977/1105] build: Rebuild libs all the time When files change that go into a static library such as libutils.a, then libutils.a doesn't get rebuilt from, e.g., wlantest because the top-level Makefile just calls the library make if the library doesn't exist yet. Change that by making the library depend on a phony target (cannot make it itself phony due to the pattern) so that the build will always recurse into the library build, and check there if the library needs to be rebuilt. While at it, remove the (actually unnecessary) mkdir so it doesn't get done each and every time you do 'make'. Signed-off-by: Johannes Berg --- src/build.rules | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/build.rules b/src/build.rules index ec1cd66ce..acda88472 100644 --- a/src/build.rules +++ b/src/build.rules @@ -94,8 +94,12 @@ $(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FI @$(E) " CC " $< # libraries - they know how to build themselves -$(BUILDDIR)/$(PROJ)/%.a: $(CONFIG_FILE) - $(Q)mkdir -p $(BUILDDIR)/$(PROJ)/$(dir $(@:$(BUILDDIR)/$(PROJ)/%=%)) +# (lib_phony so we recurse all the time) +.PHONY: lib_phony +lib_phony: +# nothing + +$(BUILDDIR)/$(PROJ)/%.a: $(CONFIG_FILE) lib_phony $(Q)$(MAKE) -C $(ROOTDIR)$(dir $(@:$(BUILDDIR)/$(PROJ)/%=%)) OUT=$(abspath $(dir $@))/ BUILDOBJ = $(patsubst %,$(BUILDDIR)/$(PROJ)/%,$(patsubst $(ROOTDIR)%,%,$(1))) From f4b3d14e9724934c2511f844cb5e0660862c3ae2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 Oct 2020 12:14:04 +0200 Subject: [PATCH 0978/1105] build: Make a common library build Derive the library name from the directory name, and let each library Makefile only declare the objects that are needed. This reduces duplicate code for the ar call. While at it, also pretty-print that call. Signed-off-by: Johannes Berg --- src/ap/Makefile | 4 ---- src/common/Makefile | 4 ---- src/crypto/Makefile | 4 ---- src/eap_common/Makefile | 4 ---- src/eap_peer/Makefile | 4 ---- src/eap_server/Makefile | 4 ---- src/eapol_auth/Makefile | 4 ---- src/eapol_supp/Makefile | 4 ---- src/l2_packet/Makefile | 4 ---- src/lib.rules | 8 ++++++++ src/p2p/Makefile | 4 ---- src/radius/Makefile | 4 ---- src/rsn_supp/Makefile | 4 ---- src/tls/Makefile | 4 ---- src/utils/Makefile | 4 ---- src/wps/Makefile | 4 ---- 16 files changed, 8 insertions(+), 60 deletions(-) diff --git a/src/ap/Makefile b/src/ap/Makefile index 09d54924c..9d67fb58b 100644 --- a/src/ap/Makefile +++ b/src/ap/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libap.a - include ../lib.rules install: @@ -67,5 +65,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libap.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/common/Makefile b/src/common/Makefile index 19573ebd3..a731c9230 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libcommon.a - include ../lib.rules install: @@ -21,5 +19,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libcommon.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/crypto/Makefile b/src/crypto/Makefile index b8accd81c..b0e13bd1d 100644 --- a/src/crypto/Makefile +++ b/src/crypto/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libcrypto.a - include ../lib.rules install: @@ -68,5 +66,3 @@ endif _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libcrypto.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/eap_common/Makefile b/src/eap_common/Makefile index b50a4b731..c85d01de7 100644 --- a/src/eap_common/Makefile +++ b/src/eap_common/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libeap_common.a - include ../lib.rules install: @@ -25,5 +23,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libeap_common.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile index d7a0372ad..1ce905d8c 100644 --- a/src/eap_peer/Makefile +++ b/src/eap_peer/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libeap_peer.a - include ../lib.rules install: @@ -17,5 +15,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libeap_peer.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/eap_server/Makefile b/src/eap_server/Makefile index b4261ec39..c68565c07 100644 --- a/src/eap_server/Makefile +++ b/src/eap_server/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libeap_server.a - include ../lib.rules install: @@ -15,5 +13,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libeap_server.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/eapol_auth/Makefile b/src/eapol_auth/Makefile index aa597eda4..328e18f50 100644 --- a/src/eapol_auth/Makefile +++ b/src/eapol_auth/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libeapol_auth.a - include ../lib.rules install: @@ -10,5 +8,3 @@ LIB_OBJS = eapol_auth_sm.o eapol_auth_dump.o _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libeapol_auth.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/eapol_supp/Makefile b/src/eapol_supp/Makefile index 453e49e6b..108e66c4c 100644 --- a/src/eapol_supp/Makefile +++ b/src/eapol_supp/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libeapol_supp.a - include ../lib.rules install: @@ -12,5 +10,3 @@ LIB_OBJS = eapol_supp_sm.o _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libeapol_supp.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/l2_packet/Makefile b/src/l2_packet/Makefile index 870d652bc..5c69413f3 100644 --- a/src/l2_packet/Makefile +++ b/src/l2_packet/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libl2_packet.a - include ../lib.rules install: @@ -10,5 +8,3 @@ LIB_OBJS = l2_packet_linux.o _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libl2_packet.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/lib.rules b/src/lib.rules index 81b895967..99b7bd026 100644 --- a/src/lib.rules +++ b/src/lib.rules @@ -1,3 +1,6 @@ +_LIBMK := $(lastword $(wordlist 1,$(shell expr $(words $(MAKEFILE_LIST)) - 1),$(MAKEFILE_LIST))) +_LIBNAME := $(notdir $(patsubst %/,%,$(dir $(abspath $(_LIBMK))))) +ALL := $(OUT)lib$(_LIBNAME).a LIB_RULES := $(lastword $(MAKEFILE_LIST)) include $(dir $(LIB_RULES))build.rules @@ -9,5 +12,10 @@ endif CFLAGS += $(FUZZ_CFLAGS) CFLAGS += -I.. -I../utils +.SECONDEXPANSION: +$(ALL): $$(LIB_OBJS) + @$(E) " AR $(notdir $@)" + $(Q)$(AR) crT $@ $? + clean: $(Q)rm -f *~ *.o *.d *.gcno *.gcda *.gcov $(ALL) diff --git a/src/p2p/Makefile b/src/p2p/Makefile index 00e1908f0..0289dec5e 100644 --- a/src/p2p/Makefile +++ b/src/p2p/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libp2p.a - include ../lib.rules install: @@ -23,5 +21,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libp2p.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/radius/Makefile b/src/radius/Makefile index 5cefa390f..8d25400e9 100644 --- a/src/radius/Makefile +++ b/src/radius/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libradius.a - include ../lib.rules install: @@ -16,5 +14,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libradius.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/rsn_supp/Makefile b/src/rsn_supp/Makefile index f5f5cad17..25accf795 100644 --- a/src/rsn_supp/Makefile +++ b/src/rsn_supp/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)librsn_supp.a - include ../lib.rules install: @@ -21,5 +19,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)librsn_supp.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/tls/Makefile b/src/tls/Makefile index 5483345e5..0e79902ef 100644 --- a/src/tls/Makefile +++ b/src/tls/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libtls.a - include ../lib.rules install: @@ -33,5 +31,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libtls.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/utils/Makefile b/src/utils/Makefile index 91aba3846..fc7f4323d 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libutils.a - include ../lib.rules install: @@ -36,5 +34,3 @@ LIB_OBJS += edit.o _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libutils.a: $(LIB_OBJS) - $(AR) crT $@ $? diff --git a/src/wps/Makefile b/src/wps/Makefile index 791069527..d7660fdd4 100644 --- a/src/wps/Makefile +++ b/src/wps/Makefile @@ -1,5 +1,3 @@ -ALL=$(OUT)libwps.a - include ../lib.rules install: @@ -35,5 +33,3 @@ LIB_OBJS= \ _OBJS_VAR := LIB_OBJS include ../objs.mk -$(OUT)libwps.a: $(LIB_OBJS) - $(AR) crT $@ $? From 1d0d8888af17ef834b70a5835ff5157121ae77e1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 Oct 2020 12:14:05 +0200 Subject: [PATCH 0979/1105] build: Make more library things common We don't really need to duplicate more of this, so just move the lib.rules include to the end and do more of the stuff that's common anyway there. Signed-off-by: Johannes Berg --- src/ap/Makefile | 9 +-------- src/common/Makefile | 9 +-------- src/crypto/Makefile | 10 +--------- src/eap_common/Makefile | 9 +-------- src/eap_peer/Makefile | 6 +----- src/eap_server/Makefile | 9 +-------- src/eapol_auth/Makefile | 10 +--------- src/eapol_supp/Makefile | 9 +-------- src/l2_packet/Makefile | 9 +-------- src/lib.rules | 9 +++++++-- src/p2p/Makefile | 9 +-------- src/radius/Makefile | 9 +-------- src/rsn_supp/Makefile | 9 +-------- src/tls/Makefile | 10 +--------- src/utils/Makefile | 9 +-------- src/wps/Makefile | 9 +-------- 16 files changed, 22 insertions(+), 122 deletions(-) diff --git a/src/ap/Makefile b/src/ap/Makefile index 9d67fb58b..a1e9b7c44 100644 --- a/src/ap/Makefile +++ b/src/ap/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DHOSTAPD CFLAGS += -DNEED_AP_MLME CFLAGS += -DCONFIG_ETH_P_OUI @@ -63,5 +57,4 @@ LIB_OBJS= \ wps_hostapd.o \ x_snoop.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/common/Makefile b/src/common/Makefile index a731c9230..59ba6c5e2 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DCONFIG_IEEE80211R CFLAGS += -DCONFIG_HS20 CFLAGS += -DCONFIG_SAE @@ -17,5 +11,4 @@ LIB_OBJS= \ sae.o \ wpa_common.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/crypto/Makefile b/src/crypto/Makefile index b0e13bd1d..ce0997091 100644 --- a/src/crypto/Makefile +++ b/src/crypto/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DCONFIG_CRYPTO_INTERNAL CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER @@ -63,6 +57,4 @@ ifndef TEST_FUZZ LIB_OBJS += random.o endif - -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/eap_common/Makefile b/src/eap_common/Makefile index c85d01de7..fd058a09a 100644 --- a/src/eap_common/Makefile +++ b/src/eap_common/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - LIB_OBJS= \ chap.o \ eap_common.o \ @@ -21,5 +15,4 @@ LIB_OBJS= \ eap_wsc_common.o \ ikev2_common.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile index 1ce905d8c..762c7a8eb 100644 --- a/src/eap_peer/Makefile +++ b/src/eap_peer/Makefile @@ -1,17 +1,13 @@ -include ../lib.rules - install: if ls *.so >/dev/null 2>&1; then \ install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \ cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ ; fi - CFLAGS += -DIEEE8021X_EAPOL LIB_OBJS= \ eap.o \ eap_methods.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/eap_server/Makefile b/src/eap_server/Makefile index c68565c07..cc9b76d61 100644 --- a/src/eap_server/Makefile +++ b/src/eap_server/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DCONFIG_HS20 LIB_OBJS= \ @@ -11,5 +5,4 @@ LIB_OBJS= \ eap_server_identity.o \ eap_server_methods.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/eapol_auth/Makefile b/src/eapol_auth/Makefile index 328e18f50..c82042f43 100644 --- a/src/eapol_auth/Makefile +++ b/src/eapol_auth/Makefile @@ -1,10 +1,2 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - LIB_OBJS = eapol_auth_sm.o eapol_auth_dump.o - -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/eapol_supp/Makefile b/src/eapol_supp/Makefile index 108e66c4c..67a11857b 100644 --- a/src/eapol_supp/Makefile +++ b/src/eapol_supp/Makefile @@ -1,12 +1,5 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DIEEE8021X_EAPOL LIB_OBJS = eapol_supp_sm.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/l2_packet/Makefile b/src/l2_packet/Makefile index 5c69413f3..c616626bd 100644 --- a/src/l2_packet/Makefile +++ b/src/l2_packet/Makefile @@ -1,10 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - LIB_OBJS = l2_packet_linux.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/lib.rules b/src/lib.rules index 99b7bd026..8182db8c7 100644 --- a/src/lib.rules +++ b/src/lib.rules @@ -12,10 +12,15 @@ endif CFLAGS += $(FUZZ_CFLAGS) CFLAGS += -I.. -I../utils -.SECONDEXPANSION: -$(ALL): $$(LIB_OBJS) +_OBJS_VAR := LIB_OBJS +include ../objs.mk + +$(ALL): $(LIB_OBJS) @$(E) " AR $(notdir $@)" $(Q)$(AR) crT $@ $? +install: + @echo Nothing to be made. + clean: $(Q)rm -f *~ *.o *.d *.gcno *.gcda *.gcov $(ALL) diff --git a/src/p2p/Makefile b/src/p2p/Makefile index 0289dec5e..4d1618006 100644 --- a/src/p2p/Makefile +++ b/src/p2p/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DCONFIG_WIFI_DISPLAY CFLAGS += -DCONFIG_WPS_NFC @@ -19,5 +13,4 @@ LIB_OBJS= \ p2p_sd.o \ p2p_utils.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/radius/Makefile b/src/radius/Makefile index 8d25400e9..8cfb33d35 100644 --- a/src/radius/Makefile +++ b/src/radius/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DCONFIG_IPV6 LIB_OBJS= \ @@ -12,5 +6,4 @@ LIB_OBJS= \ radius_das.o \ radius_server.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/rsn_supp/Makefile b/src/rsn_supp/Makefile index 25accf795..d14d736c1 100644 --- a/src/rsn_supp/Makefile +++ b/src/rsn_supp/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DCONFIG_IEEE80211R CFLAGS += -DCONFIG_TDLS CFLAGS += -DCONFIG_WNM @@ -17,5 +11,4 @@ LIB_OBJS= \ wpa.o \ wpa_ie.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/tls/Makefile b/src/tls/Makefile index 0e79902ef..c84fbe859 100644 --- a/src/tls/Makefile +++ b/src/tls/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH CFLAGS += -DCONFIG_CRYPTO_INTERNAL CFLAGS += -DCONFIG_TLSV11 @@ -28,6 +22,4 @@ LIB_OBJS= \ tlsv1_server_write.o \ x509v3.o - -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/utils/Makefile b/src/utils/Makefile index fc7f4323d..e8ad997ee 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - #CFLAGS += -DWPA_TRACE CFLAGS += -DCONFIG_IPV6 CFLAGS += -DCONFIG_DEBUG_FILE @@ -32,5 +26,4 @@ LIB_OBJS += edit.o #LIB_OBJS += pcsc_funcs.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules diff --git a/src/wps/Makefile b/src/wps/Makefile index d7660fdd4..cddc6865a 100644 --- a/src/wps/Makefile +++ b/src/wps/Makefile @@ -1,9 +1,3 @@ -include ../lib.rules - -install: - @echo Nothing to be made. - - CFLAGS += -DCONFIG_P2P CFLAGS += -DCONFIG_WPS_OOB CFLAGS += -DCONFIG_WPS_NFC @@ -31,5 +25,4 @@ LIB_OBJS= \ wps_upnp_ssdp.o \ wps_upnp_web.o -_OBJS_VAR := LIB_OBJS -include ../objs.mk +include ../lib.rules From ceab836a99081e940c92daeff7319c472b66ec1c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:00:52 +0300 Subject: [PATCH 0980/1105] tests: Remove obsolete p2p-fuzzer tests/fuzzing/p2p replaced this more than a year ago, so get rid of the now obsolete version. Signed-off-by: Jouni Malinen --- tests/p2p-fuzzer/.gitignore | 1 - tests/p2p-fuzzer/Makefile | 51 ------- tests/p2p-fuzzer/go-neg-req.dat | Bin 155 -> 0 bytes tests/p2p-fuzzer/invitation-req.dat | Bin 123 -> 0 bytes tests/p2p-fuzzer/p2p-fuzzer.c | 215 ---------------------------- tests/p2p-fuzzer/p2ps-pd-req.dat | Bin 189 -> 0 bytes tests/p2p-fuzzer/proberesp-go.dat | Bin 306 -> 0 bytes tests/p2p-fuzzer/proberesp.dat | Bin 209 -> 0 bytes 8 files changed, 267 deletions(-) delete mode 100644 tests/p2p-fuzzer/.gitignore delete mode 100644 tests/p2p-fuzzer/Makefile delete mode 100644 tests/p2p-fuzzer/go-neg-req.dat delete mode 100644 tests/p2p-fuzzer/invitation-req.dat delete mode 100644 tests/p2p-fuzzer/p2p-fuzzer.c delete mode 100644 tests/p2p-fuzzer/p2ps-pd-req.dat delete mode 100644 tests/p2p-fuzzer/proberesp-go.dat delete mode 100644 tests/p2p-fuzzer/proberesp.dat diff --git a/tests/p2p-fuzzer/.gitignore b/tests/p2p-fuzzer/.gitignore deleted file mode 100644 index ee9420df0..000000000 --- a/tests/p2p-fuzzer/.gitignore +++ /dev/null @@ -1 +0,0 @@ -p2p-fuzzer diff --git a/tests/p2p-fuzzer/Makefile b/tests/p2p-fuzzer/Makefile deleted file mode 100644 index 4f81ef158..000000000 --- a/tests/p2p-fuzzer/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -all: p2p-fuzzer - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -SRC=../../src - -CFLAGS += -I$(SRC) - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls - -$(SRC)/p2p/libp2p.a: - $(MAKE) -C $(SRC)/p2p - -$(SRC)/wps/libwps.a: - $(MAKE) -C $(SRC)/wps - -LIBS += $(SRC)/utils/libutils.a -LIBS += $(SRC)/common/libcommon.a -LIBS += $(SRC)/crypto/libcrypto.a -LIBS += $(SRC)/p2p/libp2p.a -LIBS += $(SRC)/tls/libtls.a -LIBS += $(SRC)/wps/libwps.a - -p2p-fuzzer: p2p-fuzzer.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) - -clean: - $(MAKE) -C $(SRC) clean - rm -f p2p-fuzzer *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/tests/p2p-fuzzer/go-neg-req.dat b/tests/p2p-fuzzer/go-neg-req.dat deleted file mode 100644 index ed06834d71a15feb902334f8d676fa828ced7269..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155 zcmcb>u!ez&fq{V$Ofo>(4h$@u0r|5y85r-zfoLWs22~CgMg}=nCWaIdHdcm+2$n!@ zPBy3}ZUKk@BNHiABJR Wfl)v}2&jcoz>|TE!CZ@hQ2_ufClN3J diff --git a/tests/p2p-fuzzer/invitation-req.dat b/tests/p2p-fuzzer/invitation-req.dat deleted file mode 100644 index 5991f3e6e3f9c8c162679aa64f570f8ae233af02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123 zcmcb>u!ez&fq{V$Ofo>(0Sqjh0r|5ynHld!f@oHd5+Ozg20>PahzOQICU!QcdTutb p03#DWKUBoUGsx9BM7KDCR~9NF$N|(10Rn;y94@J4naQaNjsRm%4lw`# diff --git a/tests/p2p-fuzzer/p2p-fuzzer.c b/tests/p2p-fuzzer/p2p-fuzzer.c deleted file mode 100644 index 8e9559294..000000000 --- a/tests/p2p-fuzzer/p2p-fuzzer.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * wpa_supplicant - P2P fuzzer - * Copyright (c) 2015, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "p2p/p2p.h" - - -static void debug_print(void *ctx, int level, const char *msg) -{ - wpa_printf(level, "P2P: %s", msg); -} - - -static void find_stopped(void *ctx) -{ -} - - -static int start_listen(void *ctx, unsigned int freq, - unsigned int duration, - const struct wpabuf *probe_resp_ie) -{ - return 0; -} - - -static void stop_listen(void *ctx) -{ -} - - -static void dev_found(void *ctx, const u8 *addr, - const struct p2p_peer_info *info, - int new_device) -{ -} - - -static void dev_lost(void *ctx, const u8 *dev_addr) -{ -} - - -static int send_action(void *ctx, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time, int *scheduled) -{ - *scheduled = 0; - return 0; -} - - -static void send_action_done(void *ctx) -{ -} - - -static void go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id, - u8 go_intent) -{ -} - - -static struct p2p_data * init_p2p(void) -{ - struct p2p_config p2p; - - os_memset(&p2p, 0, sizeof(p2p)); - p2p.max_peers = 100; - p2p.passphrase_len = 8; - p2p.channels.reg_classes = 1; - p2p.channels.reg_class[0].reg_class = 81; - p2p.channels.reg_class[0].channel[0] = 1; - p2p.channels.reg_class[0].channel[1] = 2; - p2p.channels.reg_class[0].channels = 2; - p2p.debug_print = debug_print; - p2p.find_stopped = find_stopped; - p2p.start_listen = start_listen; - p2p.stop_listen = stop_listen; - p2p.dev_found = dev_found; - p2p.dev_lost = dev_lost; - p2p.send_action = send_action; - p2p.send_action_done = send_action_done; - p2p.go_neg_req_rx = go_neg_req_rx; - - return p2p_init(&p2p); -} - - -struct arg_ctx { - struct p2p_data *p2p; - const char *fname; -}; - - -static void test_send_proberesp(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - struct os_reltime rx_time; - - wpa_printf(MSG_INFO, "p2p-fuzzer: Send proberesp '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - return; - } - - wpa_hexdump(MSG_MSGDUMP, "fuzzer - IEs", data, len); - - os_memset(&rx_time, 0, sizeof(rx_time)); - p2p_scan_res_handler(ctx->p2p, (u8 *) "\x02\x00\x00\x00\x01\x00", 2412, - &rx_time, 0, (u8 *) data, len); - p2p_scan_res_handled(ctx->p2p); - - os_free(data); - eloop_terminate(); -} - - -static void test_send_action(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - struct os_reltime rx_time; - struct ieee80211_mgmt *mgmt; - - wpa_printf(MSG_INFO, "p2p-fuzzer: Send action '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - return; - } - if (len < IEEE80211_HDRLEN + 1) - goto out; - - wpa_hexdump(MSG_MSGDUMP, "fuzzer - action", data, len); - - mgmt = (struct ieee80211_mgmt *) data; - os_memset(&rx_time, 0, sizeof(rx_time)); - p2p_rx_action(ctx->p2p, mgmt->da, mgmt->sa, mgmt->bssid, - mgmt->u.action.category, - (u8 *) data + IEEE80211_HDRLEN + 1, - len - IEEE80211_HDRLEN - 1, 2412); - -out: - os_free(data); - eloop_terminate(); -} - - -int main(int argc, char *argv[]) -{ - struct p2p_data *p2p; - struct arg_ctx ctx; - - /* TODO: probreq and wpas_p2p_probe_req_rx() */ - - if (argc < 3) { - printf("usage: %s \n", argv[0]); - return -1; - } - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - p2p = init_p2p(); - if (!p2p) { - wpa_printf(MSG_ERROR, "P2P init failed"); - return -1; - } - - ctx.p2p = p2p; - ctx.fname = argv[2]; - - if (os_strcmp(argv[1], "proberesp") == 0) { - eloop_register_timeout(0, 0, test_send_proberesp, &ctx, NULL); - } else if (os_strcmp(argv[1], "action") == 0) { - eloop_register_timeout(0, 0, test_send_action, &ctx, NULL); - } else { - wpa_printf(MSG_ERROR, "Unsupported test type '%s'", argv[1]); - return -1; - } - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - - p2p_deinit(p2p); - eloop_destroy(); - os_program_deinit(); - - return 0; -} diff --git a/tests/p2p-fuzzer/p2ps-pd-req.dat b/tests/p2p-fuzzer/p2ps-pd-req.dat deleted file mode 100644 index 7e1b6d91dead97241613c030b0ab5b02d5ae2858..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 189 zcmcb>u!ez&0R%uKBb4pHz`_}jKZ}!{@oqneW@2Jc)#8YXA`ff(#rksb!hT zsR~Z~{7`up&mdRl5ZzE0PBxehR)&ZOmOw^s0Wi(Y$i&RT%Er#Y$;B?A!+>sbu8n5t^a0!6PAunUPV8k;OoSk%57K4GR*<#KWK~Rl^|t|33p9 z0HtBTRt$*)69m%r94rhBOhAUiT?vMOPfU!A4Ghdn7#P%n*vUDTA<0OO;cg93hDE@O zfl)xfg@KVtz>$HGQ9uZ!O(2+o$THo(y~p=2}2?jBNkG;I3vs{wz)= VCI;0`URkhH85jiNCNLly0RTbSGMoSa diff --git a/tests/p2p-fuzzer/proberesp.dat b/tests/p2p-fuzzer/proberesp.dat deleted file mode 100644 index 8d997d1c5e1366e19c4b83169e037ec70a39373d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmZQzckv8zbq>*G~F9t>d0T%{FMgeOEMg{?Q27z#$ zANnW5!-8jvZ9Ttf#_Ep(iVTbj0?Hsl1w=T3h!6%21}G2^WZ-Z~Ez3+!Rd5pEU|=%z z5b$JRV=&hOs=KQhkUxu)iHSj#fmfD+38;gSK@hH!0a+{WrKxN`7feu4U Date: Mon, 12 Oct 2020 21:04:46 +0300 Subject: [PATCH 0981/1105] tests: Remove obsolete wnm-fuzzer tests/fuzzing/wnm replaced this more than a year ago, so get rid of the now obsolete version. Signed-off-by: Jouni Malinen --- tests/wnm-fuzzer/Makefile | 94 -------------------------- tests/wnm-fuzzer/bss-tm-req.dat | Bin 31 -> 0 bytes tests/wnm-fuzzer/wnm-fuzzer.c | 116 -------------------------------- tests/wnm-fuzzer/wnm-notif.dat | Bin 56 -> 0 bytes 4 files changed, 210 deletions(-) delete mode 100644 tests/wnm-fuzzer/Makefile delete mode 100644 tests/wnm-fuzzer/bss-tm-req.dat delete mode 100644 tests/wnm-fuzzer/wnm-fuzzer.c delete mode 100644 tests/wnm-fuzzer/wnm-notif.dat diff --git a/tests/wnm-fuzzer/Makefile b/tests/wnm-fuzzer/Makefile deleted file mode 100644 index 482a1ad63..000000000 --- a/tests/wnm-fuzzer/Makefile +++ /dev/null @@ -1,94 +0,0 @@ -all: wnm-fuzzer - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -SRC=../../src - -CFLAGS += -I$(SRC) -CFLAGS += -DCONFIG_WNM -CFLAGS += -DCONFIG_INTERWORKING -CFLAGS += -DCONFIG_GAS -CFLAGS += -DCONFIG_HS20 -CFLAGS += -DIEEE8021X_EAPOL - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls - -$(SRC)/rsn_supp/librsn_supp.a: - $(MAKE) -C $(SRC)/rsn_supp - -$(SRC)/eapol_supp/libeapol_supp.a: - $(MAKE) -C $(SRC)/eapol_supp - -$(SRC)/eap_peer/libeap_peer.a: - $(MAKE) -C $(SRC)/eap_peer - -$(SRC)/eap_common/libeap_common.a: - $(MAKE) -C $(SRC)/eap_common - -$(SRC)/l2_packet/libl2_packet.a: - $(MAKE) -C $(SRC)/l2_packet - -LIBS += $(SRC)/common/libcommon.a -LIBS += $(SRC)/crypto/libcrypto.a -LIBS += $(SRC)/tls/libtls.a -LIBS += $(SRC)/rsn_supp/librsn_supp.a -LIBS += $(SRC)/eapol_supp/libeapol_supp.a -LIBS += $(SRC)/eap_peer/libeap_peer.a -LIBS += $(SRC)/eap_common/libeap_common.a -LIBS += $(SRC)/l2_packet/libl2_packet.a -LIBS += $(SRC)/utils/libutils.a - -ELIBS += $(SRC)/crypto/libcrypto.a -ELIBS += $(SRC)/tls/libtls.a - -CFLAGS += -I$(SRC)/utils -OBJS += ../../wpa_supplicant/wnm_sta.o -OBJS += ../../wpa_supplicant/bss.o -OBJS += ../../wpa_supplicant/scan.o -OBJS += ../../wpa_supplicant/notify.o -OBJS += ../../wpa_supplicant/wpa_supplicant.o -OBJS += ../../wpa_supplicant/config.o -OBJS += ../../wpa_supplicant/config_file.o -OBJS += ../../wpa_supplicant/blacklist.o -OBJS += ../../wpa_supplicant/events.o -OBJS += ../../wpa_supplicant/wpas_glue.o -OBJS += ../../wpa_supplicant/wmm_ac.o -OBJS += ../../wpa_supplicant/eap_register.o -OBJS += ../../wpa_supplicant/gas_query.o -OBJS += ../../wpa_supplicant/offchannel.o -OBJS += ../../wpa_supplicant/interworking.o -OBJS += ../../wpa_supplicant/hs20_supplicant.o -OBJS += ../../wpa_supplicant/rrm.o -OBJS += ../../wpa_supplicant/op_classes.o -OBJS += $(SRC)/drivers/drivers.o -OBJS += $(SRC)/drivers/driver_common.o - -wnm-fuzzer: wnm-fuzzer.o $(OBJS) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) - -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C ../../wpa_supplicant clean - rm -f wnm-fuzzer *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/tests/wnm-fuzzer/bss-tm-req.dat b/tests/wnm-fuzzer/bss-tm-req.dat deleted file mode 100644 index 14510bb3ad11f70bd8277a5cc4828e0021f97281..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31 ccmcb>V8zJ900JPA8A=*3aIrJ8a4|3d03#v+XaE2J diff --git a/tests/wnm-fuzzer/wnm-fuzzer.c b/tests/wnm-fuzzer/wnm-fuzzer.c deleted file mode 100644 index 2517b5c85..000000000 --- a/tests/wnm-fuzzer/wnm-fuzzer.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * wpa_supplicant - WNM fuzzer - * Copyright (c) 2015-2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "rsn_supp/wpa.h" -#include "rsn_supp/wpa_i.h" -#include "../../wpa_supplicant/wpa_supplicant_i.h" -#include "../../wpa_supplicant/bss.h" -#include "../../wpa_supplicant/wnm_sta.h" -#include "../../wpa_supplicant/config.h" - - -struct arg_ctx { - const char *fname; - struct wpa_supplicant wpa_s; - struct wpa_bss bss; - struct wpa_driver_ops driver; - struct wpa_sm wpa; - struct wpa_config conf; -}; - - -static void test_send_wnm(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - struct ieee80211_mgmt *mgmt; - - wpa_printf(MSG_INFO, "wnm-fuzzer: Send '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - goto out; - } - - wpa_hexdump(MSG_MSGDUMP, "fuzzer - WNM", data, len); - - mgmt = (struct ieee80211_mgmt *) data; - ieee802_11_rx_wnm_action(&ctx->wpa_s, mgmt, len); - -out: - os_free(data); - eloop_terminate(); -} - - -static int init_wpa(struct arg_ctx *ctx) -{ - ctx->wpa_s.wpa_state = WPA_COMPLETED; - os_memcpy(ctx->wpa_s.bssid, "\x02\x00\x00\x00\x03\x00", ETH_ALEN); - ctx->wpa_s.current_bss = &ctx->bss; - ctx->wpa_s.driver = &ctx->driver; - ctx->wpa_s.wpa = &ctx->wpa; - ctx->wpa_s.conf = &ctx->conf; - - return 0; -} - - -static void deinit_wpa(struct arg_ctx *ctx) -{ - wnm_deallocate_memory(&ctx->wpa_s); -} - - -int main(int argc, char *argv[]) -{ - struct arg_ctx ctx; - int ret = -1; - - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - os_memset(&ctx, 0, sizeof(ctx)); - ctx.fname = argv[1]; - if (init_wpa(&ctx)) - goto fail; - - eloop_register_timeout(0, 0, test_send_wnm, &ctx, NULL); - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - deinit_wpa(&ctx); - - ret = 0; -fail: - eloop_destroy(); - os_program_deinit(); - - return ret; -} diff --git a/tests/wnm-fuzzer/wnm-notif.dat b/tests/wnm-fuzzer/wnm-notif.dat deleted file mode 100644 index c234d3ad5b69b08d0a4caa217475d1d91391b24c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56 zcmcb>V8zJ900JPA8A=8)a7i&T-jxc-pT!`OQBqP+Y^ATCT9KGrkdvyHoS&=D2ms%~ B3q}9{ From e974fad9c5cf5259d35ce24f72b4959532486340 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:06:58 +0300 Subject: [PATCH 0982/1105] tests: Remove obsolete eapol-fuzzer tests/fuzzing/eapol-supp replaced this more than a year ago, so get rid of the now obsolete version. Signed-off-by: Jouni Malinen --- tests/eapol-fuzzer/Makefile | 64 ------- tests/eapol-fuzzer/eap-req-identity.dat | Bin 9 -> 0 bytes tests/eapol-fuzzer/eap-req-sim.dat | Bin 24 -> 0 bytes tests/eapol-fuzzer/eapol-fuzzer.c | 215 ------------------------ tests/eapol-fuzzer/eapol-key-m1.dat | Bin 99 -> 0 bytes 5 files changed, 279 deletions(-) delete mode 100644 tests/eapol-fuzzer/Makefile delete mode 100644 tests/eapol-fuzzer/eap-req-identity.dat delete mode 100644 tests/eapol-fuzzer/eap-req-sim.dat delete mode 100644 tests/eapol-fuzzer/eapol-fuzzer.c delete mode 100644 tests/eapol-fuzzer/eapol-key-m1.dat diff --git a/tests/eapol-fuzzer/Makefile b/tests/eapol-fuzzer/Makefile deleted file mode 100644 index b7fff6ee3..000000000 --- a/tests/eapol-fuzzer/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -all: eapol-fuzzer - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -SRC=../../src - -CFLAGS += -I$(SRC) -CFLAGS += -DIEEE8021X_EAPOL - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls - -$(SRC)/rsn_supp/librsn_supp.a: - $(MAKE) -C $(SRC)/rsn_supp - -$(SRC)/eapol_supp/libeapol_supp.a: - $(MAKE) -C $(SRC)/eapol_supp - -$(SRC)/eap_peer/libeap_peer.a: - $(MAKE) -C $(SRC)/eap_peer - -$(SRC)/eap_common/libeap_common.a: - $(MAKE) -C $(SRC)/eap_common - -$(SRC)/l2_packet/libl2_packet.a: - $(MAKE) -C $(SRC)/l2_packet - -LIBS += $(SRC)/common/libcommon.a -LIBS += $(SRC)/crypto/libcrypto.a -LIBS += $(SRC)/tls/libtls.a -LIBS += $(SRC)/rsn_supp/librsn_supp.a -LIBS += $(SRC)/eapol_supp/libeapol_supp.a -LIBS += $(SRC)/eap_peer/libeap_peer.a -LIBS += $(SRC)/eap_common/libeap_common.a -LIBS += $(SRC)/l2_packet/libl2_packet.a -LIBS += $(SRC)/utils/libutils.a - -eapol-fuzzer: eapol-fuzzer.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group - -clean: - $(MAKE) -C $(SRC) clean - rm -f eapol-fuzzer *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/tests/eapol-fuzzer/eap-req-identity.dat b/tests/eapol-fuzzer/eap-req-identity.dat deleted file mode 100644 index 768b277541670eb92839d143fba898e1b0264896..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9 OcmZQ#U|?l51Y!UI4FEs@ diff --git a/tests/eapol-fuzzer/eap-req-sim.dat b/tests/eapol-fuzzer/eap-req-sim.dat deleted file mode 100644 index eb854aae01fd3ee860b0adfdf84b990653be7bec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 dcmZQ#U=U$6Vh|DHVqoB9WMJTDVqjtb(f|qi0Gt2- diff --git a/tests/eapol-fuzzer/eapol-fuzzer.c b/tests/eapol-fuzzer/eapol-fuzzer.c deleted file mode 100644 index b54614991..000000000 --- a/tests/eapol-fuzzer/eapol-fuzzer.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * wpa_supplicant - EAPOL fuzzer - * Copyright (c) 2015, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "eapol_supp/eapol_supp_sm.h" -#include "rsn_supp/wpa.h" -#include "rsn_supp/wpa_i.h" - - -struct arg_ctx { - const char *fname; - struct wpa_sm *wpa; - struct eapol_sm *eapol; -}; - - -static void test_send_eapol(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - u8 src[ETH_ALEN] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 }; - u8 wpa_ie[200]; - size_t wpa_ie_len; - - wpa_printf(MSG_INFO, "eapol-fuzzer: Send '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - goto out; - } - - wpa_hexdump(MSG_MSGDUMP, "fuzzer - EAPOL", data, len); - - eapol_sm_notify_portEnabled(ctx->eapol, TRUE); - - wpa_sm_set_param(ctx->wpa, WPA_PARAM_PROTO, WPA_PROTO_RSN); - wpa_sm_set_param(ctx->wpa, WPA_PARAM_RSN_ENABLED, 1); - wpa_sm_set_param(ctx->wpa, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); - wpa_sm_set_param(ctx->wpa, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); - wpa_sm_set_param(ctx->wpa, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); - - wpa_ie_len = sizeof(wpa_ie); - wpa_sm_set_assoc_wpa_ie_default(ctx->wpa, wpa_ie, &wpa_ie_len); - - if (eapol_sm_rx_eapol(ctx->eapol, src, (u8 *) data, len) <= 0) - wpa_sm_rx_eapol(ctx->wpa, src, (u8 *) data, len); - -out: - os_free(data); - eloop_terminate(); -} - - -static void * get_network_ctx(void *arg) -{ - return (void *) 1; -} - - -static void set_state(void *arg, enum wpa_states state) -{ -} - - -static void deauthenticate(void *arg, u16 reason_code) -{ -} - - -static u8 * alloc_eapol(void *arg, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - struct ieee802_1x_hdr *hdr; - - *msg_len = sizeof(*hdr) + data_len; - hdr = os_malloc(*msg_len); - if (hdr == NULL) - return NULL; - - hdr->version = 2; - hdr->type = type; - hdr->length = host_to_be16(data_len); - - if (data) - os_memcpy(hdr + 1, data, data_len); - else - os_memset(hdr + 1, 0, data_len); - - if (data_pos) - *data_pos = hdr + 1; - - return (u8 *) hdr; -} - - -static int ether_send(void *arg, const u8 *dest, u16 proto, - const u8 *buf, size_t len) -{ - return 0; -} - - -static int get_bssid(void *ctx, u8 *bssid) -{ - return -1; -} - - -static int eapol_send(void *ctx, int type, const u8 *buf, size_t len) -{ - return 0; -} - - -static int init_wpa(struct arg_ctx *arg) -{ - struct wpa_sm_ctx *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); - return -1; - } - - ctx->ctx = arg; - ctx->msg_ctx = arg; - ctx->get_network_ctx = get_network_ctx; - ctx->set_state = set_state; - ctx->deauthenticate = deauthenticate; - ctx->alloc_eapol = alloc_eapol; - ctx->ether_send = ether_send; - ctx->get_bssid = get_bssid; - - arg->wpa = wpa_sm_init(ctx); - if (!arg->wpa) - return -1; - arg->wpa->pmk_len = PMK_LEN; - return 0; -} - - -static int init_eapol(struct arg_ctx *arg) -{ - struct eapol_ctx *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context."); - return -1; - } - - ctx->ctx = arg; - ctx->msg_ctx = arg; - ctx->eapol_send = eapol_send; - - arg->eapol = eapol_sm_init(ctx); - return arg->eapol ? 0 : -1; -} - - -int main(int argc, char *argv[]) -{ - struct arg_ctx ctx; - int ret = -1; - - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - os_memset(&ctx, 0, sizeof(ctx)); - ctx.fname = argv[1]; - if (init_wpa(&ctx) || init_eapol(&ctx)) - goto fail; - - eloop_register_timeout(0, 0, test_send_eapol, &ctx, NULL); - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - - ret = 0; -fail: - if (ctx.wpa) - wpa_sm_deinit(ctx.wpa); - if (ctx.eapol) - eapol_sm_deinit(ctx.eapol); - - eloop_destroy(); - os_program_deinit(); - - return ret; -} diff --git a/tests/eapol-fuzzer/eapol-key-m1.dat b/tests/eapol-fuzzer/eapol-key-m1.dat deleted file mode 100644 index 937721c5013d93f83cb601c59f54b436c1f5f9f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99 zcmZQ#W{78E=wc9HfB?qnhYkJj>lEI7kYqLMkBD#2<$llEC-ww%e)#VfayIMkN2ody FC;%3B6Kwzh From b1e91a53e438357d2b671d2293a91baa3bb09375 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:10:01 +0300 Subject: [PATCH 0983/1105] tests: Remove obsolete ap-mgmt-fuzzer tests/fuzzing/ap-mgmt replaced this more than a year ago, so get rid of the now obsolete version. Signed-off-by: Jouni Malinen --- tests/ap-mgmt-fuzzer/.gitignore | 1 - tests/ap-mgmt-fuzzer/Makefile | 82 ----------- tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c | 194 -------------------------- tests/ap-mgmt-fuzzer/auth.dat | Bin 30 -> 0 bytes tests/ap-mgmt-fuzzer/multi.dat | Bin 246 -> 0 bytes tests/ap-mgmt-fuzzer/probe-req.dat | Bin 83 -> 0 bytes 6 files changed, 277 deletions(-) delete mode 100644 tests/ap-mgmt-fuzzer/.gitignore delete mode 100644 tests/ap-mgmt-fuzzer/Makefile delete mode 100644 tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c delete mode 100644 tests/ap-mgmt-fuzzer/auth.dat delete mode 100644 tests/ap-mgmt-fuzzer/multi.dat delete mode 100644 tests/ap-mgmt-fuzzer/probe-req.dat diff --git a/tests/ap-mgmt-fuzzer/.gitignore b/tests/ap-mgmt-fuzzer/.gitignore deleted file mode 100644 index 70db3e15d..000000000 --- a/tests/ap-mgmt-fuzzer/.gitignore +++ /dev/null @@ -1 +0,0 @@ -ap-mgmt-fuzzer diff --git a/tests/ap-mgmt-fuzzer/Makefile b/tests/ap-mgmt-fuzzer/Makefile deleted file mode 100644 index 1e06767c4..000000000 --- a/tests/ap-mgmt-fuzzer/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -all: ap-mgmt-fuzzer - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -SRC=../../src - -CFLAGS += -I$(SRC) -CFLAGS += -I$(SRC)/utils -CFLAGS += -DCONFIG_WNM -CFLAGS += -DCONFIG_INTERWORKING -CFLAGS += -DCONFIG_GAS -CFLAGS += -DCONFIG_HS20 -CFLAGS += -DIEEE8021X_EAPOL -CFLAGS += -DNEED_AP_MLME -CFLAGS += -DCONFIG_AIRTIME_POLICY - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls - -$(SRC)/wps/libwps.a: - $(MAKE) -C $(SRC)/wps - -$(SRC)/eap_common/libeap_common.a: - $(MAKE) -C $(SRC)/eap_common - -$(SRC)/eap_server/libeap_server.a: - $(MAKE) -C $(SRC)/eap_server - -$(SRC)/l2_packet/libl2_packet.a: - $(MAKE) -C $(SRC)/l2_packet - -$(SRC)/eapol_auth/libeapol_auth.a: - $(MAKE) -C $(SRC)/eapol_auth - -$(SRC)/ap/libap.a: - $(MAKE) -C $(SRC)/ap - -$(SRC)/radius/libradius.a: - $(MAKE) -C $(SRC)/radius - -LIBS += $(SRC)/common/libcommon.a -LIBS += $(SRC)/crypto/libcrypto.a -LIBS += $(SRC)/tls/libtls.a -LIBS += $(SRC)/wps/libwps.a -LIBS += $(SRC)/eap_server/libeap_server.a -LIBS += $(SRC)/eap_common/libeap_common.a -LIBS += $(SRC)/l2_packet/libl2_packet.a -LIBS += $(SRC)/ap/libap.a -LIBS += $(SRC)/eapol_auth/libeapol_auth.a -LIBS += $(SRC)/radius/libradius.a -LIBS += $(SRC)/utils/libutils.a - -ELIBS += $(SRC)/crypto/libcrypto.a -ELIBS += $(SRC)/tls/libtls.a - -ap-mgmt-fuzzer: ap-mgmt-fuzzer.o $(OBJS) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) - -clean: - $(MAKE) -C $(SRC) clean - rm -f ap-mgmt-fuzzer *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c b/tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c deleted file mode 100644 index 9d61b6bcc..000000000 --- a/tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * hostapd - Management frame fuzzer - * Copyright (c) 2015, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "ap/hostapd.h" -#include "ap/hw_features.h" -#include "ap/ieee802_11.h" -#include "ap/sta_info.h" -#include "ap/ap_list.h" - - -const struct wpa_driver_ops *const wpa_drivers[] = -{ - NULL -}; - - -struct arg_ctx { - const char *fname; - struct hostapd_iface iface; - struct hostapd_data hapd; - struct wpa_driver_ops driver; - struct hostapd_config iconf; - struct hostapd_bss_config conf; - int multi_frame; -}; - - -static void test_send_mgmt(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - struct hostapd_frame_info fi; - - wpa_printf(MSG_INFO, "ap-mgmt-fuzzer: Send '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - goto out; - } - - os_memset(&fi, 0, sizeof(fi)); - if (ctx->multi_frame) { - u8 *pos, *end; - - pos = (u8 *) data; - end = pos + len; - - while (end - pos > 2) { - u16 flen; - - flen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < flen) - break; - wpa_hexdump(MSG_MSGDUMP, "fuzzer - frame", pos, flen); - ieee802_11_mgmt(&ctx->hapd, pos, flen, &fi); - pos += flen; - } - } else { - wpa_hexdump(MSG_MSGDUMP, "fuzzer - WNM", data, len); - ieee802_11_mgmt(&ctx->hapd, (u8 *) data, len, &fi); - } - -out: - os_free(data); - eloop_terminate(); -} - - -static struct hostapd_hw_modes * gen_modes(void) -{ - struct hostapd_hw_modes *mode; - struct hostapd_channel_data *chan; - - mode = os_zalloc(sizeof(struct hostapd_hw_modes)); - if (!mode) - return NULL; - - mode->mode = HOSTAPD_MODE_IEEE80211G; - chan = os_zalloc(sizeof(struct hostapd_channel_data)); - if (!chan) { - os_free(mode); - return NULL; - } - chan->chan = 1; - chan->freq = 2412; - mode->channels = chan; - mode->num_channels = 1; - - mode->rates = os_zalloc(sizeof(int)); - if (!mode->rates) { - os_free(chan); - os_free(mode); - return NULL; - } - mode->rates[0] = 10; - mode->num_rates = 1; - - return mode; -} - - -static int init_hapd(struct arg_ctx *ctx) -{ - struct hostapd_data *hapd = &ctx->hapd; - struct sta_info *sta; - struct hostapd_bss_config *bss; - - hapd->driver = &ctx->driver; - os_memcpy(hapd->own_addr, "\x02\x00\x00\x00\x03\x00", ETH_ALEN); - hapd->iface = &ctx->iface; - hapd->iface->conf = hostapd_config_defaults(); - if (!hapd->iface->conf) - return -1; - hapd->iface->hw_features = gen_modes(); - hapd->iface->num_hw_features = 1; - hapd->iface->current_mode = hapd->iface->hw_features; - hapd->iconf = hapd->iface->conf; - hapd->iconf->hw_mode = HOSTAPD_MODE_IEEE80211G; - hapd->iconf->channel = 1; - bss = hapd->conf = hapd->iconf->bss[0]; - hostapd_config_defaults_bss(hapd->conf); - os_memcpy(bss->ssid.ssid, "test", 4); - bss->ssid.ssid_len = 4; - bss->ssid.ssid_set = 1; - - sta = ap_sta_add(hapd, (u8 *) "\x02\x00\x00\x00\x00\x00"); - if (sta) - sta->flags |= WLAN_STA_ASSOC | WLAN_STA_WMM; - - return 0; -} - - -int main(int argc, char *argv[]) -{ - struct arg_ctx ctx; - int ret = -1; - - if (argc < 2) { - printf("usage: %s [-m] \n", argv[0]); - return -1; - } - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - os_memset(&ctx, 0, sizeof(ctx)); - if (argc >= 3 && os_strcmp(argv[1], "-m") == 0) { - ctx.multi_frame = 1; - ctx.fname = argv[2]; - } else { - ctx.fname = argv[1]; - } - if (init_hapd(&ctx)) - goto fail; - - eloop_register_timeout(0, 0, test_send_mgmt, &ctx, NULL); - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - hostapd_free_stas(&ctx.hapd); - hostapd_free_hw_features(ctx.hapd.iface->hw_features, - ctx.hapd.iface->num_hw_features); - - ret = 0; -fail: - hostapd_config_free(ctx.hapd.iconf); - ap_list_deinit(&ctx.iface); - eloop_destroy(); - os_program_deinit(); - - return ret; -} diff --git a/tests/ap-mgmt-fuzzer/auth.dat b/tests/ap-mgmt-fuzzer/auth.dat deleted file mode 100644 index 0eb36e5aab3db9f6b754475269029b0b2299a9da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30 ccmdnMV8zJ9z`(%F03sQ{Br}5mki`hZ033}02><{9 diff --git a/tests/ap-mgmt-fuzzer/multi.dat b/tests/ap-mgmt-fuzzer/multi.dat deleted file mode 100644 index 29d074e0c4142b61e5bdd36d34bfd0393772d89e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmZPwc3@y&_zwn5Ko*P*Vli?sv2cs=2uY|Iu^4zHPi&}NdNy2l7#?97=wYK zo`Z#fiwP*;z#zAQ!HN-N95VyNPzYN9C<4}y%z#y1fkBalm4Sh!B(=B%-Ev(i8{9T? bfo*mG+RS*Dogv^86UZ8=3s@})06GEyltUk) diff --git a/tests/ap-mgmt-fuzzer/probe-req.dat b/tests/ap-mgmt-fuzzer/probe-req.dat deleted file mode 100644 index a5fba77adc59cd10b1022d9a72d6ef97c83b8392..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 83 zcmZ=@U|{$U224N}j16Kjaxk%Qi}46as2H&rcqHU7GcxK*6$wcH{|}Od07e*tfuWv* Lg@KC+DBu79BqI^~ From 95cbbf44f0e9b0df96f7482e5daaf1fa4bb47c97 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:13:08 +0300 Subject: [PATCH 0984/1105] tests: Remove obsolete json fuzzer tests/fuzzing/json replaced this more than a year ago, so get rid of the now obsolete version. Signed-off-by: Jouni Malinen --- tests/Makefile | 4 --- tests/test-json.c | 64 ----------------------------------------------- 2 files changed, 68 deletions(-) delete mode 100644 tests/test-json.c diff --git a/tests/Makefile b/tests/Makefile index 72fb8ee4f..558194c1e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -73,9 +73,6 @@ test-https: $(call BUILDOBJ,test-https.o) $(LIBS) test-https_server: $(call BUILDOBJ,test-https_server.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-json: $(call BUILDOBJ,test-json.o) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) - test-list: $(call BUILDOBJ,test-list.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) @@ -119,7 +116,6 @@ clean: common-clean rm -f *~ rm -f test-eapol rm -f test-https - rm -f test-json rm -f test-tls rm -f test_x509v3_nist.out.* rm -f test_x509v3_nist2.out.* diff --git a/tests/test-json.c b/tests/test-json.c deleted file mode 100644 index b33a79214..000000000 --- a/tests/test-json.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * JSON parser - test program - * Copyright (c) 2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include "utils/common.h" -#include "utils/os.h" -#include "utils/json.h" -#include "utils/wpa_debug.h" - - -void run_test(const char *buf, size_t len) -{ - struct json_token *root; - char *txt; - size_t buflen = 10000; - - root = json_parse(buf, len); - if (!root) { - wpa_printf(MSG_DEBUG, "JSON parsing failed"); - return; - } - - txt = os_zalloc(buflen); - if (txt) { - json_print_tree(root, txt, buflen); - wpa_printf(MSG_DEBUG, "%s", txt); - os_free(txt); - } - json_free(root); -} - - -#ifdef TEST_LIBFUZZER -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - run_test((const char *) data, size); - return 0; -} -#else /* TEST_LIBFUZZER */ -int main(int argc, char *argv[]) -{ - char *buf; - size_t len; - - wpa_debug_level = 0; - - if (argc < 2) - return -1; - - buf = os_readfile(argv[1], &len); - if (!buf) - return -1; - - run_test(buf, len); - os_free(buf); - - return 0; -} -#endif /* TEST_LIBFUZZER */ From 8a43fcd18c7ba91d32b6552e102fc5632f822f17 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:17:45 +0300 Subject: [PATCH 0985/1105] tests: Remove obsolete EAPOL-Key fuzzer tests/fuzzing/eapol-key-{auth,supp} replaced this more than a year ago, so get rid of the now obsolete version. Signed-off-by: Jouni Malinen --- tests/Makefile | 4 - tests/test-eapol.c | 608 --------------------------------------------- 2 files changed, 612 deletions(-) delete mode 100644 tests/test-eapol.c diff --git a/tests/Makefile b/tests/Makefile index 558194c1e..1c8def0de 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -64,9 +64,6 @@ test-asn1: $(call BUILDOBJ,test-asn1.o) $(LIBS) test-base64: $(call BUILDOBJ,test-base64.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-eapol: $(call BUILDOBJ,test-eapol.o) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) - test-https: $(call BUILDOBJ,test-https.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) @@ -114,7 +111,6 @@ run-tests: $(ALL) clean: common-clean rm -f *~ - rm -f test-eapol rm -f test-https rm -f test-tls rm -f test_x509v3_nist.out.* diff --git a/tests/test-eapol.c b/tests/test-eapol.c deleted file mode 100644 index 944e4cfb9..000000000 --- a/tests/test-eapol.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Testing tool for EAPOL-Key Supplicant/Authenticator routines - * Copyright (c) 2006-2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "rsn_supp/wpa.h" -#include "ap/wpa_auth.h" - - -struct wpa { - enum { AUTH, SUPP } test_peer; - enum { READ, WRITE } test_oper; - FILE *f; - int wpa1; - - u8 auth_addr[ETH_ALEN]; - u8 supp_addr[ETH_ALEN]; - u8 psk[PMK_LEN]; - - /* from authenticator */ - u8 *auth_eapol; - size_t auth_eapol_len; - - /* from supplicant */ - u8 *supp_eapol; - size_t supp_eapol_len; - - struct wpa_sm *supp; - struct wpa_authenticator *auth_group; - struct wpa_state_machine *auth; - - u8 supp_ie[80]; - size_t supp_ie_len; - - int key_request_done; - int key_request_done1; - int auth_sent; -}; - - -const struct wpa_driver_ops *const wpa_drivers[] = { NULL }; - - -static int auth_read_msg(struct wpa *wpa); -static void supp_eapol_key_request(void *eloop_data, void *user_ctx); - - -static void usage(void) { - wpa_printf(MSG_INFO, - "usage: test-eapol "); - exit(-1); -} - - -static void write_msg(FILE *f, const u8 *msg, size_t msg_len) -{ - u8 len[2]; - - wpa_printf(MSG_DEBUG, "TEST: Write message to file (msg_len=%u)", - (unsigned int) msg_len); - WPA_PUT_BE16(len, msg_len); - fwrite(len, 2, 1, f); - fwrite(msg, msg_len, 1, f); -} - - -static u8 * read_msg(FILE *f, size_t *ret_len) -{ - u8 len[2]; - u16 msg_len; - u8 *msg; - - if (fread(len, 2, 1, f) != 1) { - wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); - eloop_terminate(); - return NULL; - } - msg_len = WPA_GET_BE16(len); - - msg = os_malloc(msg_len); - if (!msg) - return NULL; - if (msg_len > 0 && fread(msg, msg_len, 1, f) != 1) { - wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", - msg_len); - os_free(msg); - eloop_terminate(); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len); - - *ret_len = msg_len; - return msg; -} - - -static int supp_get_bssid(void *ctx, u8 *bssid) -{ - struct wpa *wpa = ctx; - wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); - os_memcpy(bssid, wpa->auth_addr, ETH_ALEN); - return 0; -} - - -static void supp_set_state(void *ctx, enum wpa_states state) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state); -} - - -static void auth_eapol_rx(void *eloop_data, void *user_ctx) -{ - struct wpa *wpa = eloop_data; - - wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame"); - wpa->auth_sent = 0; - wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol, - wpa->supp_eapol_len); - if (!wpa->auth_sent && wpa->test_peer == SUPP && - wpa->test_oper == READ) { - /* Speed up process by not going through retransmit timeout */ - wpa_printf(MSG_DEBUG, - "AUTH: No response was sent - process next message"); - auth_read_msg(wpa); - } - if (wpa->wpa1 && wpa->key_request_done && !wpa->key_request_done1) { - wpa->key_request_done1 = 1; - eloop_register_timeout(0, 0, supp_eapol_key_request, - wpa, NULL); - } - -} - - -static void supp_eapol_rx(void *eloop_data, void *user_ctx) -{ - struct wpa *wpa = eloop_data; - - wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame"); - wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol, - wpa->auth_eapol_len); -} - - -static int supp_read_msg(struct wpa *wpa) -{ - os_free(wpa->auth_eapol); - wpa->auth_eapol = read_msg(wpa->f, &wpa->auth_eapol_len); - if (!wpa->auth_eapol) - return -1; - eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL); - return 0; -} - - -static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, - size_t len) -{ - struct wpa *wpa = ctx; - - wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x " - "len=%lu)", - __func__, MAC2STR(dest), proto, (unsigned long) len); - - if (wpa->test_peer == SUPP && wpa->test_oper == WRITE) - write_msg(wpa->f, buf, len); - - if (wpa->test_peer == AUTH && wpa->test_oper == READ) - return supp_read_msg(wpa); - - os_free(wpa->supp_eapol); - wpa->supp_eapol = os_malloc(len); - if (!wpa->supp_eapol) - return -1; - os_memcpy(wpa->supp_eapol, buf, len); - wpa->supp_eapol_len = len; - eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL); - - return 0; -} - - -static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, - u16 data_len, size_t *msg_len, void **data_pos) -{ - struct ieee802_1x_hdr *hdr; - - wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", - __func__, type, data_len); - - *msg_len = sizeof(*hdr) + data_len; - hdr = os_malloc(*msg_len); - if (hdr == NULL) - return NULL; - - hdr->version = 2; - hdr->type = type; - hdr->length = host_to_be16(data_len); - - if (data) - os_memcpy(hdr + 1, data, data_len); - else - os_memset(hdr + 1, 0, data_len); - - if (data_pos) - *data_pos = hdr + 1; - - return (u8 *) hdr; -} - - -static int supp_get_beacon_ie(void *ctx) -{ - struct wpa *wpa = ctx; - const u8 *ie; - size_t ielen; - - wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); - - ie = wpa_auth_get_wpa_ie(wpa->auth_group, &ielen); - if (ie == NULL || ielen < 1) - return -1; - if (ie[0] == WLAN_EID_RSN) - return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]); - return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]); -} - - -static int supp_set_key(void *ctx, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " - "set_tx=%d)", - __func__, alg, MAC2STR(addr), key_idx, set_tx); - wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); - wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len); - return 0; -} - - -static int supp_mlme_setprotection(void *ctx, const u8 *addr, - int protection_type, int key_type) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d " - "key_type=%d)", - __func__, MAC2STR(addr), protection_type, key_type); - return 0; -} - - -static void supp_cancel_auth_timeout(void *ctx) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); -} - - -static void * supp_get_network_ctx(void *ctx) -{ - return (void *) 1; -} - - -static void supp_deauthenticate(void *ctx, u16 reason_code) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s(%d)", __func__, reason_code); -} - - -static enum wpa_states supp_get_state(void *ctx) -{ - return WPA_COMPLETED; -} - - -static int supp_init(struct wpa *wpa) -{ - struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); - - if (!ctx) - return -1; - - ctx->ctx = wpa; - ctx->msg_ctx = wpa; - ctx->set_state = supp_set_state; - ctx->get_bssid = supp_get_bssid; - ctx->ether_send = supp_ether_send; - ctx->get_beacon_ie = supp_get_beacon_ie; - ctx->alloc_eapol = supp_alloc_eapol; - ctx->set_key = supp_set_key; - ctx->mlme_setprotection = supp_mlme_setprotection; - ctx->cancel_auth_timeout = supp_cancel_auth_timeout; - ctx->get_network_ctx = supp_get_network_ctx; - ctx->deauthenticate = supp_deauthenticate; - ctx->get_state = supp_get_state; - wpa->supp = wpa_sm_init(ctx); - if (!wpa->supp) { - wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); - return -1; - } - - wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr); - if (wpa->wpa1) { - wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 0); - wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_WPA); - wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, - WPA_CIPHER_TKIP); - wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_TKIP); - wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, - WPA_KEY_MGMT_PSK); - } else { - wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1); - wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN); - wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, - WPA_CIPHER_CCMP); - wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); - wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, - WPA_KEY_MGMT_PSK); - wpa_sm_set_param(wpa->supp, WPA_PARAM_MFP, - MGMT_FRAME_PROTECTION_OPTIONAL); - } - wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN, NULL, NULL); - - wpa->supp_ie_len = sizeof(wpa->supp_ie); - if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie, - &wpa->supp_ie_len) < 0) { - wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()" - " failed"); - return -1; - } - - wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr); - - return 0; -} - - -static void auth_logger(void *ctx, const u8 *addr, logger_level level, - const char *txt) -{ - if (addr) - wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s", - MAC2STR(addr), txt); - else - wpa_printf(MSG_DEBUG, "AUTH: %s", txt); -} - - -static int auth_read_msg(struct wpa *wpa) -{ - os_free(wpa->supp_eapol); - wpa->supp_eapol = read_msg(wpa->f, &wpa->supp_eapol_len); - if (!wpa->supp_eapol) - return -1; - eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL); - return 0; -} - - -static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, - size_t data_len, int encrypt) -{ - struct wpa *wpa = ctx; - - wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu " - "encrypt=%d)", - __func__, MAC2STR(addr), (unsigned long) data_len, encrypt); - wpa->auth_sent = 1; - - if (wpa->test_peer == AUTH && wpa->test_oper == WRITE) - write_msg(wpa->f, data, data_len); - - if (wpa->test_peer == SUPP && wpa->test_oper == READ) - return auth_read_msg(wpa); - - os_free(wpa->auth_eapol); - wpa->auth_eapol = os_malloc(data_len); - if (!wpa->auth_eapol) - return -1; - os_memcpy(wpa->auth_eapol, data, data_len); - wpa->auth_eapol_len = data_len; - eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL); - - return 0; -} - - -static const u8 * auth_get_psk(void *ctx, const u8 *addr, - const u8 *p2p_dev_addr, const u8 *prev_psk, - size_t *psk_len, int *vlan_id) -{ - struct wpa *wpa = ctx; - - wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", - __func__, MAC2STR(addr), prev_psk); - if (vlan_id) - *vlan_id = 0; - if (psk_len) - *psk_len = PMK_LEN; - if (prev_psk) - return NULL; - return wpa->psk; -} - - -static void supp_eapol_key_request(void *eloop_data, void *user_ctx) -{ - struct wpa *wpa = eloop_data; - - wpa_printf(MSG_DEBUG, "SUPP: EAPOL-Key Request trigger"); - if (wpa->test_peer == SUPP && wpa->test_oper == READ) { - if (!eloop_is_timeout_registered(auth_eapol_rx, wpa, NULL)) - auth_read_msg(wpa); - } else { - wpa_sm_key_request(wpa->supp, 0, 1); - } -} - - -static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, - const u8 *addr, int idx, u8 *key, - size_t key_len) -{ - struct wpa *wpa = ctx; - - wpa_printf(MSG_DEBUG, "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d)", - __func__, vlan_id, alg, idx, (int) key_len); - if (addr) - wpa_printf(MSG_DEBUG, "AUTH: addr=" MACSTR, MAC2STR(addr)); - - if (alg != WPA_ALG_NONE && idx == 0 && key_len > 0 && - !wpa->key_request_done) { - wpa_printf(MSG_DEBUG, "Test EAPOL-Key Request"); - wpa->key_request_done = 1; - if (!wpa->wpa1) - eloop_register_timeout(0, 0, supp_eapol_key_request, - wpa, NULL); - } - - return 0; -} - - -static int auth_init_group(struct wpa *wpa) -{ - struct wpa_auth_config conf; - struct wpa_auth_callbacks cb; - - wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine"); - - os_memset(&conf, 0, sizeof(conf)); - if (wpa->wpa1) { - conf.wpa = 1; - conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; - conf.wpa_pairwise = WPA_CIPHER_TKIP; - conf.wpa_group = WPA_CIPHER_TKIP; - } else { - conf.wpa = 2; - conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; - conf.wpa_pairwise = WPA_CIPHER_CCMP; - conf.rsn_pairwise = WPA_CIPHER_CCMP; - conf.wpa_group = WPA_CIPHER_CCMP; - conf.ieee80211w = 2; - conf.group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; - } - conf.eapol_version = 2; - conf.wpa_group_update_count = 4; - conf.wpa_pairwise_update_count = 4; - - os_memset(&cb, 0, sizeof(cb)); - cb.logger = auth_logger; - cb.send_eapol = auth_send_eapol; - cb.get_psk = auth_get_psk; - cb.set_key = auth_set_key, - - wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &cb, wpa); - if (!wpa->auth_group) { - wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed"); - return -1; - } - - return 0; -} - - -static int auth_init(struct wpa *wpa) -{ - if (wpa->test_peer == AUTH && wpa->test_oper == READ) - return supp_read_msg(wpa); - - wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr, NULL); - if (!wpa->auth) { - wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed"); - return -1; - } - - if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, 2412, wpa->supp_ie, - wpa->supp_ie_len, NULL, 0, NULL, 0, NULL, 0) != - WPA_IE_OK) { - wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); - return -1; - } - - wpa_auth_sm_event(wpa->auth, WPA_ASSOC); - - wpa_auth_sta_associated(wpa->auth_group, wpa->auth); - - return 0; -} - - -static void deinit(struct wpa *wpa) -{ - wpa_auth_sta_deinit(wpa->auth); - wpa_sm_deinit(wpa->supp); - wpa_deinit(wpa->auth_group); - os_free(wpa->auth_eapol); - wpa->auth_eapol = NULL; - os_free(wpa->supp_eapol); - wpa->supp_eapol = NULL; -} - - -int main(int argc, char *argv[]) -{ - const char *file; - int ret; - struct wpa wpa; - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - os_memset(&wpa, 0, sizeof(wpa)); - - if (argc < 4) - usage(); - - if (os_strcmp(argv[1], "auth") == 0) { - wpa.test_peer = AUTH; - } else if (os_strcmp(argv[1], "auth1") == 0) { - wpa.test_peer = AUTH; - wpa.wpa1 = 1; - } else if (os_strcmp(argv[1], "supp") == 0) { - wpa.test_peer = SUPP; - } else if (os_strcmp(argv[1], "supp1") == 0) { - wpa.test_peer = SUPP; - wpa.wpa1 = 1; - } else { - usage(); - } - - if (os_strcmp(argv[2], "read") == 0) - wpa.test_oper = READ; - else if (os_strcmp(argv[2], "write") == 0) - wpa.test_oper = WRITE; - else - usage(); - - file = argv[3]; - - wpa.f = fopen(file, wpa.test_oper == READ ? "r" : "w"); - if (!wpa.f) - return -1; - - os_memset(wpa.auth_addr, 0x12, ETH_ALEN); - os_memset(wpa.supp_addr, 0x32, ETH_ALEN); - os_memset(wpa.psk, 0x44, PMK_LEN); - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - goto fail; - } - - if (auth_init_group(&wpa) < 0) - goto fail; - - if (supp_init(&wpa) < 0) - goto fail; - - if (auth_init(&wpa) < 0) - goto fail; - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - - ret = 0; -fail: - deinit(&wpa); - fclose(wpa.f); - - eloop_destroy(); - - os_program_deinit(); - - return ret; -} From 0db20eacaa8d6540d4d6f4547043a072c38f518c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:20:12 +0300 Subject: [PATCH 0986/1105] tests: Remove obsolete TLS fuzzer tests/fuzzing/tls-{client,server} replaced this more than a year ago, so get rid of the now obsolete version. Signed-off-by: Jouni Malinen --- tests/Makefile | 4 - tests/test-tls.c | 243 ----------------------------------------------- 2 files changed, 247 deletions(-) delete mode 100644 tests/test-tls.c diff --git a/tests/Makefile b/tests/Makefile index 1c8def0de..fed0a7411 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -91,9 +91,6 @@ test-sha1: $(call BUILDOBJ,test-sha1.o) $(LIBS) test-sha256: $(call BUILDOBJ,test-sha256.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-tls: $(call BUILDOBJ,test-tls.o) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) - test-x509v3: $(call BUILDOBJ,test-x509v3.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) @@ -112,6 +109,5 @@ run-tests: $(ALL) clean: common-clean rm -f *~ rm -f test-https - rm -f test-tls rm -f test_x509v3_nist.out.* rm -f test_x509v3_nist2.out.* diff --git a/tests/test-tls.c b/tests/test-tls.c deleted file mode 100644 index 9941fb5fa..000000000 --- a/tests/test-tls.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Testing tool for TLSv1 client/server routines - * Copyright (c) 2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/tls.h" - - -static void usage(void) { - wpa_printf(MSG_INFO, - "usage: test-tls "); - exit(-1); -} - - -static void write_msg(FILE *f, struct wpabuf *msg) -{ - u8 len[2]; - - wpa_printf(MSG_DEBUG, "TEST: Write message to file (msg_len=%u)", - (unsigned int) wpabuf_len(msg)); - WPA_PUT_BE16(len, wpabuf_len(msg)); - fwrite(len, 2, 1, f); - fwrite(wpabuf_head(msg), wpabuf_len(msg), 1, f); -} - - -static struct wpabuf * read_msg(FILE *f) -{ - u8 len[2]; - u16 msg_len; - struct wpabuf *msg; - - if (fread(len, 2, 1, f) != 1) { - wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); - return NULL; - } - msg_len = WPA_GET_BE16(len); - - msg = wpabuf_alloc(msg_len); - if (!msg) - return NULL; - if (msg_len > 0 && - fread(wpabuf_put(msg, msg_len), msg_len, 1, f) != 1) { - wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", - msg_len); - wpabuf_free(msg); - return NULL; - } - wpa_hexdump_buf(MSG_DEBUG, "TEST: Read message from file", msg); - - return msg; -} - - -int main(int argc, char *argv[]) -{ - struct tls_config conf; - void *tls_server, *tls_client; - struct tls_connection_params params; - struct tls_connection *conn_server = NULL, *conn_client = NULL; - int ret = -1; - struct wpabuf *in = NULL, *out = NULL, *appl; - enum { SERVER, CLIENT } test_peer; - enum { READ, WRITE } test_oper; - const char *file; - FILE *f; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (argc < 4) - usage(); - - if (os_strcmp(argv[1], "server") == 0) - test_peer = SERVER; - else if (os_strcmp(argv[1], "client") == 0) - test_peer = CLIENT; - else - usage(); - - if (os_strcmp(argv[2], "read") == 0) - test_oper = READ; - else if (os_strcmp(argv[2], "write") == 0) - test_oper = WRITE; - else - usage(); - - file = argv[3]; - - f = fopen(file, test_oper == READ ? "r" : "w"); - if (!f) - return -1; - - os_memset(&conf, 0, sizeof(conf)); - tls_server = tls_init(&conf); - tls_client = tls_init(&conf); - if (!tls_server || !tls_client) - goto fail; - - os_memset(¶ms, 0, sizeof(params)); - params.ca_cert = "hwsim/auth_serv/ca.pem"; - params.client_cert = "hwsim/auth_serv/server.pem"; - params.private_key = "hwsim/auth_serv/server.key"; - params.dh_file = "hwsim/auth_serv/dh.conf"; - - if (tls_global_set_params(tls_server, ¶ms)) { - wpa_printf(MSG_ERROR, "Failed to set TLS parameters"); - goto fail; - } - - conn_server = tls_connection_init(tls_server); - conn_client = tls_connection_init(tls_client); - if (!conn_server || !conn_client) - goto fail; - - in = NULL; - for (;;) { - appl = NULL; - if (test_peer == CLIENT && test_oper == READ) - out = read_msg(f); - else - out = tls_connection_handshake(tls_client, conn_client, - in, &appl); - wpabuf_free(in); - in = NULL; - if (!out) - goto fail; - if (test_peer == CLIENT && test_oper == WRITE && - wpabuf_len(out) > 0) - write_msg(f, out); - if (!(test_peer == CLIENT && test_oper == READ) && - tls_connection_get_failed(tls_client, conn_client)) { - wpa_printf(MSG_ERROR, "TLS handshake failed"); - goto fail; - } - if (((test_peer == CLIENT && test_oper == READ) || - tls_connection_established(tls_client, conn_client)) && - ((test_peer == SERVER && test_oper == READ) || - tls_connection_established(tls_server, conn_server))) - break; - - appl = NULL; - if (test_peer == SERVER && test_oper == READ) - in = read_msg(f); - else - in = tls_connection_server_handshake(tls_server, - conn_server, - out, &appl); - wpabuf_free(out); - out = NULL; - if (!in) - goto fail; - if (test_peer == SERVER && test_oper == WRITE) - write_msg(f, in); - if (!(test_peer == SERVER && test_oper == READ) && - tls_connection_get_failed(tls_server, conn_server)) { - wpa_printf(MSG_ERROR, "TLS handshake failed"); - goto fail; - } - if (((test_peer == CLIENT && test_oper == READ) || - tls_connection_established(tls_client, conn_client)) && - ((test_peer == SERVER && test_oper == READ) || - tls_connection_established(tls_server, conn_server))) - break; - } - - wpabuf_free(in); - in = wpabuf_alloc(100); - if (!in) - goto fail; - wpabuf_put_str(in, "PING"); - wpabuf_free(out); - if (test_peer == CLIENT && test_oper == READ) - out = read_msg(f); - else - out = tls_connection_encrypt(tls_client, conn_client, in); - wpabuf_free(in); - in = NULL; - if (!out) - goto fail; - if (test_peer == CLIENT && test_oper == WRITE) - write_msg(f, out); - - if (!(test_peer == SERVER && test_oper == READ)) { - in = tls_connection_decrypt(tls_server, conn_server, out); - wpabuf_free(out); - out = NULL; - if (!in) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "Server decrypted ApplData", in); - } - - wpabuf_free(in); - in = wpabuf_alloc(100); - if (!in) - goto fail; - wpabuf_put_str(in, "PONG"); - wpabuf_free(out); - if (test_peer == SERVER && test_oper == READ) - out = read_msg(f); - else - out = tls_connection_encrypt(tls_server, conn_server, in); - wpabuf_free(in); - in = NULL; - if (!out) - goto fail; - if (test_peer == SERVER && test_oper == WRITE) - write_msg(f, out); - - if (!(test_peer == CLIENT && test_oper == READ)) { - in = tls_connection_decrypt(tls_client, conn_client, out); - wpabuf_free(out); - out = NULL; - if (!in) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "Client decrypted ApplData", in); - } - - ret = 0; -fail: - if (tls_server) { - if (conn_server) - tls_connection_deinit(tls_server, conn_server); - tls_deinit(tls_server); - } - if (tls_client) { - if (conn_client) - tls_connection_deinit(tls_server, conn_client); - tls_deinit(tls_client); - } - wpabuf_free(in); - wpabuf_free(out); - fclose(f); - - return ret; -} From 0167a2d165bc92bd04feda4849a42b00c902af18 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:23:02 +0300 Subject: [PATCH 0987/1105] tests: Remove obsolete ASN.1 parser/fuzzer tests/fuzzing/asn1 replaced this more than a year ago, so get rid of the now obsolete version. Signed-off-by: Jouni Malinen --- tests/Makefile | 5 +- tests/test-asn1.c | 195 ---------------------------------------------- 2 files changed, 1 insertion(+), 199 deletions(-) delete mode 100644 tests/test-asn1.c diff --git a/tests/Makefile b/tests/Makefile index fed0a7411..ef1665aba 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,7 +1,7 @@ ALL=test-base64 test-md4 test-milenage \ test-rsa-sig-ver \ test-sha1 \ - test-sha256 test-aes test-asn1 test-x509v3 test-list test-rc4 + test-sha256 test-aes test-x509v3 test-list test-rc4 include ../src/build.rules @@ -58,9 +58,6 @@ LLIBS += -lrt test-aes: $(call BUILDOBJ,test-aes.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-asn1: $(call BUILDOBJ,test-asn1.o) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) - test-base64: $(call BUILDOBJ,test-base64.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) diff --git a/tests/test-asn1.c b/tests/test-asn1.c deleted file mode 100644 index c6957fd25..000000000 --- a/tests/test-asn1.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Testing tool for ASN.1 routines - * Copyright (c) 2006-2009, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "tls/asn1.h" - - -static const char * asn1_class_str(int class) -{ - switch (class) { - case ASN1_CLASS_UNIVERSAL: - return "Universal"; - case ASN1_CLASS_APPLICATION: - return "Application"; - case ASN1_CLASS_CONTEXT_SPECIFIC: - return "Context-specific"; - case ASN1_CLASS_PRIVATE: - return "Private"; - default: - return "?"; - } -} - - -int asn1_parse(const u8 *buf, size_t len, int level) -{ - const u8 *pos, *prev, *end; - char prefix[10], str[100]; - int _level; - struct asn1_hdr hdr; - struct asn1_oid oid; - u8 tmp; - - _level = level; - if ((size_t) _level > sizeof(prefix) - 1) - _level = sizeof(prefix) - 1; - memset(prefix, ' ', _level); - prefix[_level] = '\0'; - - pos = buf; - end = buf + len; - - while (pos < end) { - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - prev = pos; - pos = hdr.payload; - - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) " - "Tag %u Length %u", - prefix, hdr.class, asn1_class_str(hdr.class), - hdr.constructed, - hdr.constructed ? "Constructed" : "Primitive", - hdr.tag, hdr.length); - - if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && - hdr.constructed) { - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - } - - if (hdr.class != ASN1_CLASS_UNIVERSAL) - continue; - - switch (hdr.tag) { - case ASN1_TAG_EOC: - if (hdr.length) { - wpa_printf(MSG_DEBUG, "ASN.1: Non-zero " - "end-of-contents length (%u)", - hdr.length); - return -1; - } - wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix); - break; - case ASN1_TAG_BOOLEAN: - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "ASN.1: Unexpected " - "Boolean length (%u)", hdr.length); - return -1; - } - tmp = *pos++; - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s", - prefix, tmp ? "TRUE" : "FALSE"); - break; - case ASN1_TAG_INTEGER: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_BITSTRING: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_OCTETSTRING: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_NULL: - if (hdr.length) { - wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null " - "length (%u)", hdr.length); - return -1; - } - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix); - break; - case ASN1_TAG_OID: - if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) { - wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID"); - return -1; - } - asn1_oid_to_str(&oid, str, sizeof(str)); - wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str); - pos += hdr.length; - break; - case ANS1_TAG_RELATIVE_OID: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_SEQUENCE: - wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix); - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - break; - case ASN1_TAG_SET: - wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix); - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - break; - case ASN1_TAG_PRINTABLESTRING: - wpa_hexdump_ascii(MSG_MSGDUMP, - "ASN.1: PrintableString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_IA5STRING: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_UTCTIME: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_VISIBLESTRING: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString", - pos, hdr.length); - pos += hdr.length; - break; - default: - wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d", - hdr.tag); - return -1; - } - } - - return 0; -} - - -int main(int argc, char *argv[]) -{ - FILE *f; - u8 buf[3000]; - size_t len; - - wpa_debug_level = 0; - - f = fopen(argv[1], "rb"); - if (f == NULL) - return -1; - len = fread(buf, 1, sizeof(buf), f); - fclose(f); - - if (asn1_parse(buf, len, 0) < 0) - printf("Failed to parse DER ASN.1\n"); - - printf("\n\n"); - - return 0; -} From b746f28c00fd63dc698ae8df84864c7477f797bb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:35:26 +0300 Subject: [PATCH 0988/1105] tests: Remove unnecessary libraries from tests/test-*.c build These libraries are not needed anymore with the remaining tests/test-*.c tools. Signed-off-by: Jouni Malinen --- tests/Makefile | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index ef1665aba..47d1685c0 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -29,17 +29,6 @@ CFLAGS += -I../src/utils SLIBS = ../src/utils/libutils.a DLIBS = ../src/crypto/libcrypto.a \ - ../src/common/libcommon.a \ - ../src/ap/libap.a \ - ../src/eapol_auth/libeapol_auth.a \ - ../src/eapol_supp/libeapol_supp.a \ - ../src/eap_peer/libeap_peer.a \ - ../src/eap_server/libeap_server.a \ - ../src/eap_common/libeap_common.a \ - ../src/radius/libradius.a \ - ../src/l2_packet/libl2_packet.a \ - ../src/wps/libwps.a \ - ../src/rsn_supp/librsn_supp.a \ ../src/tls/libtls.a _OBJS_VAR := LLIBS From 05195189f1cb6073759ce256276d2f8ba51fdbd9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:37:25 +0300 Subject: [PATCH 0989/1105] tests: Build test-https and test-https_server as part of ALL Even though these are not part of run-tests, it is simpler to just build them like all other tests/test-* tools. Signed-off-by: Jouni Malinen --- tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index 47d1685c0..2d2343b64 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,6 +1,7 @@ ALL=test-base64 test-md4 test-milenage \ test-rsa-sig-ver \ test-sha1 \ + test-https test-https_server \ test-sha256 test-aes test-x509v3 test-list test-rc4 include ../src/build.rules @@ -94,6 +95,5 @@ run-tests: $(ALL) clean: common-clean rm -f *~ - rm -f test-https rm -f test_x509v3_nist.out.* rm -f test_x509v3_nist2.out.* From a964cb65a1528798c30af6aee538effc0c70d90b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 12 Oct 2020 21:40:08 +0300 Subject: [PATCH 0990/1105] tests: Silence compiler warnings from test-base64 Use typecasting to match the base64_{encode,decode}() function prototype for signed/unsigned char buffer. Signed-off-by: Jouni Malinen --- tests/test-base64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test-base64.c b/tests/test-base64.c index 980febf9e..99943f0db 100644 --- a/tests/test-base64.c +++ b/tests/test-base64.c @@ -26,9 +26,9 @@ int main(int argc, char *argv[]) return -1; if (strcmp(argv[1], "encode") == 0) - e = base64_encode(buf, len, &elen); + e = (unsigned char *) base64_encode(buf, len, &elen); else - e = base64_decode(buf, len, &elen); + e = base64_decode((const char *) buf, len, &elen); if (e == NULL) return -2; f = fopen(argv[3], "w"); From 1d14758450f8b90823ddd243bc315754fc3baa5e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Oct 2020 19:48:29 +0300 Subject: [PATCH 0991/1105] DPP: Make dpp_keygen_configurator() a static function This was not used anywhere outside dpp.c. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 2 +- src/common/dpp.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 552d7626c..d83c1a2d0 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -3413,7 +3413,7 @@ static int dpp_configurator_gen_kid(struct dpp_configurator *conf) } -struct dpp_configurator * +static struct dpp_configurator * dpp_keygen_configurator(const char *curve, const u8 *privkey, size_t privkey_len) { diff --git a/src/common/dpp.h b/src/common/dpp.h index a39e87ed5..7a0443471 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -583,9 +583,6 @@ const char * dpp_akm_selector_str(enum dpp_akm akm); int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, size_t buflen); void dpp_configurator_free(struct dpp_configurator *conf); -struct dpp_configurator * -dpp_keygen_configurator(const char *curve, const u8 *privkey, - size_t privkey_len); int dpp_configurator_own_config(struct dpp_authentication *auth, const char *curve, int ap); enum dpp_status_error From 9c1fbff074046362360e5206006da9c74f340835 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Oct 2020 19:59:29 +0300 Subject: [PATCH 0992/1105] DPP2: Generate a privacy protection key for Configurator Generate a new key for Configurator. This is either generated automatically for the specified curve or provided from external source with the new ppkey= argument similarly to the way c-sign-key was previously generated. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 30 ++++++++++++++++++++++++------ src/common/dpp.h | 1 + 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index d83c1a2d0..b3bbbf855 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -3355,6 +3355,7 @@ void dpp_configurator_free(struct dpp_configurator *conf) os_free(conf->kid); os_free(conf->connector); EVP_PKEY_free(conf->connector_key); + EVP_PKEY_free(conf->pp_key); os_free(conf); } @@ -3415,7 +3416,7 @@ static int dpp_configurator_gen_kid(struct dpp_configurator *conf) static struct dpp_configurator * dpp_keygen_configurator(const char *curve, const u8 *privkey, - size_t privkey_len) + size_t privkey_len, const u8 *pp_key, size_t pp_key_len) { struct dpp_configurator *conf; @@ -3435,7 +3436,12 @@ dpp_keygen_configurator(const char *curve, const u8 *privkey, privkey_len); else conf->csign = dpp_gen_keypair(conf->curve); - if (!conf->csign) + if (pp_key) + conf->pp_key = dpp_set_keypair(&conf->curve, pp_key, + pp_key_len); + else + conf->pp_key = dpp_gen_keypair(conf->curve); + if (!conf->csign || !conf->pp_key) goto fail; conf->own = 1; @@ -4122,14 +4128,15 @@ static unsigned int dpp_next_configurator_id(struct dpp_global *dpp) int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) { char *curve = NULL; - char *key = NULL; - u8 *privkey = NULL; - size_t privkey_len = 0; + char *key = NULL, *ppkey = NULL; + u8 *privkey = NULL, *pp_key = NULL; + size_t privkey_len = 0, pp_key_len = 0; int ret = -1; struct dpp_configurator *conf = NULL; curve = get_param(cmd, " curve="); key = get_param(cmd, " key="); + ppkey = get_param(cmd, " ppkey="); if (key) { privkey_len = os_strlen(key) / 2; @@ -4139,7 +4146,16 @@ int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) goto fail; } - conf = dpp_keygen_configurator(curve, privkey, privkey_len); + if (ppkey) { + pp_key_len = os_strlen(key) / 2; + pp_key = os_malloc(pp_key_len); + if (!pp_key || + hexstr2bin(ppkey, pp_key, pp_key_len) < 0) + goto fail; + } + + conf = dpp_keygen_configurator(curve, privkey, privkey_len, + pp_key, pp_key_len); if (!conf) goto fail; @@ -4150,7 +4166,9 @@ int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) fail: os_free(curve); str_clear_free(key); + str_clear_free(ppkey); bin_clear_free(privkey, privkey_len); + bin_clear_free(pp_key, pp_key_len); dpp_configurator_free(conf); return ret; } diff --git a/src/common/dpp.h b/src/common/dpp.h index 7a0443471..f6216522d 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -364,6 +364,7 @@ struct dpp_configurator { const struct dpp_curve_params *curve; char *connector; /* own Connector for reconfiguration */ EVP_PKEY *connector_key; + EVP_PKEY *pp_key; }; struct dpp_introduction { From 2a8c92887186f2b499c62a6e1cfacf95f4ce1665 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Oct 2020 20:16:58 +0300 Subject: [PATCH 0993/1105] DPP2: Add ppKey into Connector This provides the new privacy protection key to the Enrollee so that this can be used to protect E-id in Reconfig Announcement frames. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/common/dpp.c b/src/common/dpp.c index b3bbbf855..72ddd4e05 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1586,6 +1586,16 @@ skip_groups: wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK"); goto fail; } +#ifdef CONFIG_DPP2 + if (auth->peer_version >= 2 && auth->conf->pp_key) { + json_value_sep(buf); + if (dpp_build_jwk(buf, "ppKey", auth->conf->pp_key, NULL, + curve) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to build ppKey JWK"); + goto fail; + } + } +#endif /* CONFIG_DPP2 */ json_end_object(buf); json_end_object(buf); From a8ee2292bd8db7b1d733b1203f690bbe4ea4c72d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Oct 2020 20:24:56 +0300 Subject: [PATCH 0994/1105] DPP2: Parse ppKey from Connector This will be used to protect E-id in Reconfig Announcement frames. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 39 ++++++++++++++++++++++++++++++++++++--- src/common/dpp.h | 1 + 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 72ddd4e05..024423dd8 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -1285,6 +1285,7 @@ void dpp_auth_deinit(struct dpp_authentication *auth) wpabuf_free(conf->certs); wpabuf_free(conf->cacert); os_free(conf->server_name); + wpabuf_free(conf->pp_key); } #ifdef CONFIG_DPP2 dpp_free_asymmetric_key(auth->conf_key_pkg); @@ -2428,6 +2429,20 @@ static void dpp_copy_csign(struct dpp_config_obj *conf, EVP_PKEY *csign) } +static void dpp_copy_ppkey(struct dpp_config_obj *conf, EVP_PKEY *ppkey) +{ + unsigned char *der = NULL; + int der_len; + + der_len = i2d_PUBKEY(ppkey, &der); + if (der_len <= 0) + return; + wpabuf_free(conf->pp_key); + conf->pp_key = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); +} + + static void dpp_copy_netaccesskey(struct dpp_authentication *auth, struct dpp_config_obj *conf) { @@ -2463,10 +2478,10 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, struct json_token *cred) { struct dpp_signed_connector_info info; - struct json_token *token, *csign; + struct json_token *token, *csign, *ppkey; int ret = -1; - EVP_PKEY *csign_pub = NULL; - const struct dpp_curve_params *key_curve = NULL; + EVP_PKEY *csign_pub = NULL, *pp_pub = NULL; + const struct dpp_curve_params *key_curve = NULL, *pp_curve = NULL; const char *signed_connector; os_memset(&info, 0, sizeof(info)); @@ -2493,6 +2508,21 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, } dpp_debug_print_key("DPP: Received C-sign-key", csign_pub); + ppkey = json_get_member(cred, "ppKey"); + if (ppkey && ppkey->type == JSON_OBJECT) { + pp_pub = dpp_parse_jwk(ppkey, &pp_curve); + if (!pp_pub) { + wpa_printf(MSG_DEBUG, "DPP: Failed to parse ppKey JWK"); + goto fail; + } + dpp_debug_print_key("DPP: Received ppKey", pp_pub); + if (key_curve != pp_curve) { + wpa_printf(MSG_DEBUG, + "DPP: C-sign-key and ppKey do not use the same curve"); + goto fail; + } + } + token = json_get_member(cred, "signedConnector"); if (!token || token->type != JSON_STRING) { wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found"); @@ -2523,12 +2553,15 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, conf->connector = os_strdup(signed_connector); dpp_copy_csign(conf, csign_pub); + if (pp_pub) + dpp_copy_ppkey(conf, pp_pub); if (dpp_akm_dpp(conf->akm) || auth->peer_version >= 2) dpp_copy_netaccesskey(auth, conf); ret = 0; fail: EVP_PKEY_free(csign_pub); + EVP_PKEY_free(pp_pub); os_free(info.payload); return ret; } diff --git a/src/common/dpp.h b/src/common/dpp.h index f6216522d..4b270524a 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -326,6 +326,7 @@ struct dpp_authentication { struct wpabuf *certs; struct wpabuf *cacert; char *server_name; + struct wpabuf *pp_key; } conf_obj[DPP_MAX_CONF_OBJ]; unsigned int num_conf_obj; struct dpp_asymmetric_key *conf_key_pkg; From 37df40845ab4a0043f4dc90c2be0e05a7f462fce Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Oct 2020 20:29:27 +0300 Subject: [PATCH 0995/1105] DPP2: Copy received ppKey into wpa_supplicant network profile Store the received privacy protection key from Connector into wpa_supplicant network profile and indicate it through the control interface similarly to C-sign-key. Signed-off-by: Jouni Malinen --- src/common/wpa_ctrl.h | 1 + wpa_supplicant/config.c | 2 ++ wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 10 ++++++++++ wpa_supplicant/dpp_supplicant.c | 23 +++++++++++++++++++++++ 5 files changed, 37 insertions(+) diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 52888d730..acc2d6c4c 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -184,6 +184,7 @@ extern "C" { #define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK " #define DPP_EVENT_CONNECTOR "DPP-CONNECTOR " #define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY " +#define DPP_EVENT_PP_KEY "DPP-PP-KEY " #define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY " #define DPP_EVENT_SERVER_NAME "DPP-SERVER-NAME " #define DPP_EVENT_CERTBAG "DPP-CERTBAG " diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index e3c12d8b3..61761299b 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2573,6 +2573,7 @@ static const struct parse_data ssid_fields[] = { { STR_LEN(dpp_netaccesskey) }, { INT(dpp_netaccesskey_expiry) }, { STR_LEN(dpp_csign) }, + { STR_LEN(dpp_pp_key) }, { INT_RANGE(dpp_pfs, 0, 2) }, #endif /* CONFIG_DPP */ { INT_RANGE(owe_group, 0, 65535) }, @@ -2776,6 +2777,7 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) os_free(ssid->dpp_connector); bin_clear_free(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); os_free(ssid->dpp_csign); + os_free(ssid->dpp_pp_key); while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry, list))) { dl_list_del(&psk->list); diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index da3b8a958..c01557dac 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -928,6 +928,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(dpp_netaccesskey); INT(dpp_netaccesskey_expiry); STR(dpp_csign); + STR(dpp_pp_key); INT(dpp_pfs); #endif /* CONFIG_DPP */ INT(owe_group); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index ff9cdf4f6..b4fdc8a17 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -1023,6 +1023,16 @@ struct wpa_ssid { */ size_t dpp_csign_len; + /** + * dpp_pp_key - ppKey (Configurator privacy protection public key) + */ + u8 *dpp_pp_key; + + /** + * dpp_pp_key_len - ppKey length in octets + */ + size_t dpp_pp_key_len; + /** * dpp_pfs - DPP PFS * 0: allow PFS to be used or not used diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 1008207b2..8e9a37c8b 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -1192,6 +1192,15 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key); } + if (conf->pp_key) { + ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key)); + if (!ssid->dpp_pp_key) + goto fail; + os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key), + wpabuf_len(conf->pp_key)); + ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key); + } + if (auth->net_access_key) { ssid->dpp_netaccesskey = os_malloc(wpabuf_len(auth->net_access_key)); @@ -1429,6 +1438,20 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s, os_free(hex); } } + if (conf->pp_key) { + char *hex; + size_t hexlen; + + hexlen = 2 * wpabuf_len(conf->pp_key) + 1; + hex = os_malloc(hexlen); + if (hex) { + wpa_snprintf_hex(hex, hexlen, + wpabuf_head(conf->pp_key), + wpabuf_len(conf->pp_key)); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex); + os_free(hex); + } + } if (auth->net_access_key) { char *hex; size_t hexlen; From 99d7bf23486d4e456726a60dbda8201eb9fb5df2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Oct 2020 20:53:09 +0300 Subject: [PATCH 0996/1105] DPP2: Use the new privacy protection key to protect E-id on Enrollee Use ppKey instead of C-sign-key to encrypted E-id to E'-id into Reconfig Announcement frame on the Enrollee side. Signed-off-by: Jouni Malinen --- src/common/dpp.h | 4 +++- src/common/dpp_crypto.c | 33 +++++++++++++++++++++++---------- src/common/dpp_i.h | 1 + wpa_supplicant/dpp_supplicant.c | 4 +++- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/common/dpp.h b/src/common/dpp.h index 4b270524a..1774d6cfb 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -723,7 +723,9 @@ int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len); struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, - size_t csign_key_len); + size_t csign_key_len, + const u8 *pp_key, + size_t pp_key_len); int dpp_update_reconfig_id(struct dpp_reconfig_id *id); void dpp_free_reconfig_id(struct dpp_reconfig_id *id); diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 5938ed6a7..865215afe 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -3004,10 +3004,12 @@ fail: struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, - size_t csign_key_len) + size_t csign_key_len, + const u8 *pp_key, + size_t pp_key_len) { const unsigned char *p; - EVP_PKEY *csign = NULL; + EVP_PKEY *csign = NULL, *ppkey = NULL; struct dpp_reconfig_id *id = NULL; BN_CTX *ctx = NULL; BIGNUM *bn = NULL, *q = NULL; @@ -3020,6 +3022,13 @@ struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, if (!csign) goto fail; + if (!pp_key) + goto fail; + p = pp_key; + ppkey = d2i_PUBKEY(NULL, &p, pp_key_len); + if (!ppkey) + goto fail; + eckey = EVP_PKEY_get0_EC_KEY(csign); if (!eckey) goto fail; @@ -3047,9 +3056,12 @@ struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, e_id = NULL; id->csign = csign; csign = NULL; + id->pp_key = ppkey; + ppkey = NULL; fail: EC_POINT_free(e_id); EVP_PKEY_free(csign); + EVP_PKEY_free(ppkey); BN_clear_free(bn); BN_CTX_free(ctx); return id; @@ -3093,13 +3105,13 @@ int dpp_update_reconfig_id(struct dpp_reconfig_id *id) BIGNUM *bn = NULL, *q = NULL; EC_POINT *e_prime_id = NULL, *a_nonce = NULL; int ret = -1; - const EC_KEY *csign; - const EC_POINT *csign_point; + const EC_KEY *pp; + const EC_POINT *pp_point; - csign = EVP_PKEY_get0_EC_KEY(id->csign); - if (!csign) + pp = EVP_PKEY_get0_EC_KEY(id->pp_key); + if (!pp) goto fail; - csign_point = EC_KEY_get0_public_key(csign); + pp_point = EC_KEY_get0_public_key(pp); e_prime_id = EC_POINT_new(id->group); a_nonce = EC_POINT_new(id->group); ctx = BN_CTX_new(); @@ -3107,12 +3119,12 @@ int dpp_update_reconfig_id(struct dpp_reconfig_id *id) q = BN_new(); /* Generate random 0 <= a-nonce < q * A-NONCE = a-nonce * G - * E'-id = E-id + a-nonce * S_C */ - if (!csign_point || !e_prime_id || !a_nonce || !ctx || !bn || !q || + * E'-id = E-id + a-nonce * P_pk */ + if (!pp_point || !e_prime_id || !a_nonce || !ctx || !bn || !q || !EC_GROUP_get_order(id->group, q, ctx) || !BN_rand_range(bn, q) || /* bn = a-nonce */ !EC_POINT_mul(id->group, a_nonce, bn, NULL, NULL, ctx) || - !EC_POINT_mul(id->group, e_prime_id, NULL, csign_point, bn, ctx) || + !EC_POINT_mul(id->group, e_prime_id, NULL, pp_point, bn, ctx) || !EC_POINT_add(id->group, e_prime_id, id->e_id, e_prime_id, ctx)) goto fail; @@ -3145,6 +3157,7 @@ void dpp_free_reconfig_id(struct dpp_reconfig_id *id) EVP_PKEY_free(id->csign); EVP_PKEY_free(id->a_nonce); EVP_PKEY_free(id->e_prime_id); + EVP_PKEY_free(id->pp_key); os_free(id); } } diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index f2164c789..b875f2033 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -146,6 +146,7 @@ struct dpp_reconfig_id { EVP_PKEY *csign; EVP_PKEY *a_nonce; /* A-NONCE */ EVP_PKEY *e_prime_id; /* E'-id */ + EVP_PKEY *pp_key; }; /* dpp_tcp.c */ diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 8e9a37c8b..74514886a 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3730,7 +3730,9 @@ int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd) dpp_free_reconfig_id(wpa_s->dpp_reconfig_id); wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign, - ssid->dpp_csign_len); + ssid->dpp_csign_len, + ssid->dpp_pp_key, + ssid->dpp_pp_key_len); if (!wpa_s->dpp_reconfig_id) { wpa_printf(MSG_DEBUG, "DPP: Failed to generate E-id for reconfiguration"); From a0ccc4017fa76485cf26109decd2d22de19a6009 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Oct 2020 20:57:26 +0300 Subject: [PATCH 0997/1105] DPP2: Use ppKey to decrypt E'-id on Configurator Use the new privacy protection key to decrypt E'-id from Reconfig Announcement frames. Signed-off-by: Jouni Malinen --- src/common/dpp_crypto.c | 21 ++++++++++++--------- src/common/dpp_i.h | 2 +- src/common/dpp_reconfig.c | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 865215afe..7c4801531 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -3163,32 +3163,35 @@ void dpp_free_reconfig_id(struct dpp_reconfig_id *id) } -EC_POINT * dpp_decrypt_e_id(EVP_PKEY *csign, EVP_PKEY *a_nonce, +EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce, EVP_PKEY *e_prime_id) { - const EC_KEY *csign_ec, *a_nonce_ec, *e_prime_id_ec; - const BIGNUM *csign_bn; + const EC_KEY *pp_ec, *a_nonce_ec, *e_prime_id_ec; + const BIGNUM *pp_bn; const EC_GROUP *group; EC_POINT *e_id = NULL; const EC_POINT *a_nonce_point, *e_prime_id_point; BN_CTX *ctx = NULL; + if (!ppkey) + return NULL; + /* E-id = E'-id - s_C * A-NONCE */ - csign_ec = EVP_PKEY_get0_EC_KEY(csign); + pp_ec = EVP_PKEY_get0_EC_KEY(ppkey); a_nonce_ec = EVP_PKEY_get0_EC_KEY(a_nonce); e_prime_id_ec = EVP_PKEY_get0_EC_KEY(e_prime_id); - if (!csign_ec || !a_nonce_ec || !e_prime_id_ec) + if (!pp_ec || !a_nonce_ec || !e_prime_id_ec) return NULL; - csign_bn = EC_KEY_get0_private_key(csign_ec); - group = EC_KEY_get0_group(csign_ec); + pp_bn = EC_KEY_get0_private_key(pp_ec); + group = EC_KEY_get0_group(pp_ec); a_nonce_point = EC_KEY_get0_public_key(a_nonce_ec); e_prime_id_point = EC_KEY_get0_public_key(e_prime_id_ec); ctx = BN_CTX_new(); - if (!csign_bn || !group || !a_nonce_point || !e_prime_id_point || !ctx) + if (!pp_bn || !group || !a_nonce_point || !e_prime_id_point || !ctx) goto fail; e_id = EC_POINT_new(group); if (!e_id || - !EC_POINT_mul(group, e_id, NULL, a_nonce_point, csign_bn, ctx) || + !EC_POINT_mul(group, e_id, NULL, a_nonce_point, pp_bn, ctx) || !EC_POINT_invert(group, e_id, ctx) || !EC_POINT_add(group, e_id, e_prime_id_point, e_id, ctx)) { EC_POINT_clear_free(e_id); diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index b875f2033..af12467a5 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -133,7 +133,7 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, const u8 *r_proto, u16 r_proto_len, struct json_token *net_access_key); -EC_POINT * dpp_decrypt_e_id(EVP_PKEY *csign, EVP_PKEY *a_nonce, +EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce, EVP_PKEY *e_prime_id); char * dpp_sign_connector(struct dpp_configurator *conf, const struct wpabuf *dppcon); diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c index f9d01d841..c4a027363 100644 --- a/src/common/dpp_reconfig.c +++ b/src/common/dpp_reconfig.c @@ -264,7 +264,7 @@ dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, return NULL; } dpp_debug_print_key("E'-id", e_prime_id); - e_id = dpp_decrypt_e_id(conf->csign, a_nonce, e_prime_id); + e_id = dpp_decrypt_e_id(conf->pp_key, a_nonce, e_prime_id); EVP_PKEY_free(a_nonce); EVP_PKEY_free(e_prime_id); if (!e_id) { From 0f07230eb9684080adfd711531be075fa157f00d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Oct 2020 23:11:40 +0300 Subject: [PATCH 0998/1105] DPP2: Add privacyProtectionKey into Configurator backup/restore This allows the privacyProtectionKey to be transferred to a new Configurator similarly to the way c-sign-key is transferred. Signed-off-by: Jouni Malinen --- src/common/dpp.c | 20 ++++++++++-- src/common/dpp.h | 1 + src/common/dpp_backup.c | 72 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 024423dd8..0bda85fe7 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -4275,12 +4275,12 @@ int dpp_configurator_from_backup(struct dpp_global *dpp, struct dpp_asymmetric_key *key) { struct dpp_configurator *conf; - const EC_KEY *eckey; - const EC_GROUP *group; + const EC_KEY *eckey, *eckey_pp; + const EC_GROUP *group, *group_pp; int nid; const struct dpp_curve_params *curve; - if (!key->csign) + if (!key->csign || !key->pp_key) return -1; eckey = EVP_PKEY_get0_EC_KEY(key->csign); if (!eckey) @@ -4294,6 +4294,18 @@ int dpp_configurator_from_backup(struct dpp_global *dpp, wpa_printf(MSG_INFO, "DPP: Unsupported group in c-sign-key"); return -1; } + eckey_pp = EVP_PKEY_get0_EC_KEY(key->pp_key); + if (!eckey_pp) + return -1; + group_pp = EC_KEY_get0_group(eckey_pp); + if (!group_pp) + return -1; + if (EC_GROUP_get_curve_name(group) != + EC_GROUP_get_curve_name(group_pp)) { + wpa_printf(MSG_INFO, + "DPP: Mismatch in c-sign-key and ppKey groups"); + return -1; + } conf = os_zalloc(sizeof(*conf)); if (!conf) @@ -4301,6 +4313,8 @@ int dpp_configurator_from_backup(struct dpp_global *dpp, conf->curve = curve; conf->csign = key->csign; key->csign = NULL; + conf->pp_key = key->pp_key; + key->pp_key = NULL; conf->own = 1; if (dpp_configurator_gen_kid(conf) < 0) { dpp_configurator_free(conf); diff --git a/src/common/dpp.h b/src/common/dpp.h index 1774d6cfb..649c5ddde 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -235,6 +235,7 @@ struct dpp_configuration { struct dpp_asymmetric_key { struct dpp_asymmetric_key *next; EVP_PKEY *csign; + EVP_PKEY *pp_key; char *config_template; char *connector_template; }; diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c index 67ca1a5d2..3b81f0964 100644 --- a/src/common/dpp_backup.c +++ b/src/common/dpp_backup.c @@ -40,6 +40,7 @@ void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key) struct dpp_asymmetric_key *next = key->next; EVP_PKEY_free(key->csign); + EVP_PKEY_free(key->pp_key); str_clear_free(key->config_template); str_clear_free(key->connector_template); os_free(key); @@ -48,35 +49,62 @@ void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key) } -static struct wpabuf * dpp_build_conf_params(void) +static struct wpabuf * dpp_build_conf_params(struct dpp_configurator *conf) { - struct wpabuf *buf; + struct wpabuf *buf, *priv_key = NULL; size_t len; /* TODO: proper template values */ const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}"; const char *connector_template = NULL; + EC_KEY *eckey; + unsigned char *der = NULL; + int der_len; + + if (!conf->pp_key) + return NULL; + eckey = EVP_PKEY_get0_EC_KEY(conf->pp_key); + if (!eckey) + return NULL; + + EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len > 0) + priv_key = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + if (!priv_key) + goto fail; len = 100 + os_strlen(conf_template); if (connector_template) len += os_strlen(connector_template); + if (priv_key) + len += wpabuf_len(priv_key); buf = wpabuf_alloc(len); if (!buf) - return NULL; + goto fail; /* * DPPConfigurationParameters ::= SEQUENCE { + * privacyProtectionKey PrivateKey, * configurationTemplate UTF8String, * connectorTemplate UTF8String OPTIONAL} */ + /* PrivateKey ::= OCTET STRING */ + asn1_put_octet_string(buf, priv_key); + asn1_put_utf8string(buf, conf_template); if (connector_template) asn1_put_utf8string(buf, connector_template); + wpabuf_clear_free(priv_key); return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +fail: + wpabuf_clear_free(priv_key); + return NULL; } -static struct wpabuf * dpp_build_attribute(void) +static struct wpabuf * dpp_build_attribute(struct dpp_configurator *conf) { struct wpabuf *conf_params, *attr; @@ -88,7 +116,7 @@ static struct wpabuf * dpp_build_attribute(void) * type OBJECT IDENTIFIER, * values SET SIZE(1..MAX) OF Type */ - conf_params = dpp_build_conf_params(); + conf_params = dpp_build_conf_params(conf); conf_params = asn1_encaps(conf_params, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET); if (!conf_params) @@ -167,7 +195,7 @@ static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth) alg = dpp_build_key_alg(auth->conf->curve); /* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */ - attr = dpp_build_attribute(); + attr = dpp_build_attribute(auth->conf); attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET); if (!priv_key || !attr || !alg) goto fail; @@ -1059,6 +1087,7 @@ dpp_parse_one_asymmetric_key(const u8 *buf, size_t len) /* * DPPConfigurationParameters ::= SEQUENCE { + * privacyProtectionKey PrivateKey, * configurationTemplate UTF8String, * connectorTemplate UTF8String OPTIONAL} */ @@ -1075,6 +1104,37 @@ dpp_parse_one_asymmetric_key(const u8 *buf, size_t len) end = pos; pos = hdr.payload; + /* + * PrivateKey ::= OCTET STRING + * (Contains DER encoding of ECPrivateKey) + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_key(MSG_MSGDUMP, "DPP: privacyProtectionKey", + hdr.payload, hdr.length); + pos = hdr.payload + hdr.length; + eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length); + if (!eckey) { + wpa_printf(MSG_INFO, + "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + key->pp_key = EVP_PKEY_new(); + if (!key->pp_key || EVP_PKEY_assign_EC_KEY(key->pp_key, eckey) != 1) { + EC_KEY_free(eckey); + goto fail; + } + if (wpa_debug_show_keys) + dpp_debug_print_key("DPP: Received privacyProtectionKey", + key->pp_key); + if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_UTF8STRING) { From 7f8ac02e8524633d92941f7934440c19f1002616 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 13:53:17 +0200 Subject: [PATCH 0999/1105] HE/VHT: Fix frequency setup with HE enabled Some places in the code base were not using the wrappers like hostapd_set_oper_centr_freq_seg0_idx and friends. This could lead to errors, for example when joining 80 MHz mesh networks. Fix this, by enforcing usage of these wrappers. wpa_supplicant_conf_ap_ht() now checks for HE capability before dealing with VHT in order for these wrappers to work, as they first check HE support in the config. While doing these changes, I've noticed that the extra channel setup code for mesh networks in wpa_supplicant/mesh.c should not be necessary anymore and dropped it. wpa_supplicant_conf_ap_ht() should handle this setup already. Acked-by: John Crispin Signed-off-by: Markus Theil --- src/ap/dfs.c | 8 ++++---- wpa_supplicant/ap.c | 40 +++++++++++++++++++++++----------------- wpa_supplicant/mesh.c | 24 ------------------------ 3 files changed, 27 insertions(+), 45 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 3c078b9cb..f62da49a7 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -1028,7 +1028,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) unsigned int i; int err = 1; struct hostapd_hw_modes *cmode = iface->current_mode; - u8 current_vht_oper_chwidth = iface->conf->vht_oper_chwidth; + u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", __func__, iface->cac_started ? "yes" : "no", @@ -1089,8 +1089,8 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) "freq=%d chan=%d sec_chan=%d", channel->freq, channel->chan, secondary_channel); - new_vht_oper_chwidth = iface->conf->vht_oper_chwidth; - iface->conf->vht_oper_chwidth = current_vht_oper_chwidth; + new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); + hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth); /* Setup CSA request */ os_memset(&csa_settings, 0, sizeof(csa_settings)); @@ -1130,7 +1130,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) iface->freq = channel->freq; iface->conf->channel = channel->chan; iface->conf->secondary_channel = secondary_channel; - iface->conf->vht_oper_chwidth = new_vht_oper_chwidth; + hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth); hostapd_set_oper_centr_freq_seg0_idx(iface->conf, oper_centr_freq_seg0_idx); hostapd_set_oper_centr_freq_seg1_idx(iface->conf, diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index de3027dd7..895b62ae3 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -52,6 +52,7 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, #ifdef CONFIG_P2P u8 center_chan = 0; u8 channel = conf->channel; + u8 freq_seg_idx; #endif /* CONFIG_P2P */ if (!conf->secondary_channel) @@ -59,19 +60,21 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, /* Use the maximum oper channel width if it's given. */ if (ssid->max_oper_chwidth) - conf->vht_oper_chwidth = ssid->max_oper_chwidth; + hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth); ieee80211_freq_to_chan(ssid->vht_center_freq2, - &conf->vht_oper_centr_freq_seg1_idx); + &freq_seg_idx); + hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx); if (!ssid->p2p_group) { if (!ssid->vht_center_freq1 || - conf->vht_oper_chwidth == CHANWIDTH_USE_HT) + hostapd_get_oper_chwidth(conf) == CHANWIDTH_USE_HT) goto no_vht; ieee80211_freq_to_chan(ssid->vht_center_freq1, - &conf->vht_oper_centr_freq_seg0_idx); + &freq_seg_idx); + hostapd_set_oper_centr_freq_seg0_idx(conf, freq_seg_idx); wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP", - conf->vht_oper_centr_freq_seg0_idx); + hostapd_get_oper_centr_freq_seg0_idx(conf)); return; } @@ -96,14 +99,14 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is * not supported. */ - conf->vht_oper_chwidth = CHANWIDTH_160MHZ; + hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ); center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel); if (center_chan) { wpa_printf(MSG_DEBUG, "VHT center channel %u for auto-selected 160 MHz bandwidth", center_chan); } else { - conf->vht_oper_chwidth = CHANWIDTH_80MHZ; + hostapd_set_oper_chwidth(conf, CHANWIDTH_80MHZ); center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel); wpa_printf(MSG_DEBUG, @@ -115,9 +118,9 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, if (!center_chan) goto no_vht; - conf->vht_oper_centr_freq_seg0_idx = center_chan; + hostapd_set_oper_centr_freq_seg0_idx(conf, center_chan); wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO", - conf->vht_oper_centr_freq_seg0_idx); + hostapd_get_oper_centr_freq_seg0_idx(conf)); return; #endif /* CONFIG_P2P */ @@ -125,9 +128,9 @@ no_vht: wpa_printf(MSG_DEBUG, "No VHT higher bandwidth support for the selected channel %d", conf->channel); - conf->vht_oper_centr_freq_seg0_idx = - conf->channel + conf->secondary_channel * 2; - conf->vht_oper_chwidth = CHANWIDTH_USE_HT; + hostapd_set_oper_centr_freq_seg0_idx( + conf, conf->channel + conf->secondary_channel * 2); + hostapd_set_oper_chwidth(conf, CHANWIDTH_USE_HT); } @@ -231,16 +234,19 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, HT_CAP_INFO_TX_STBC | HT_CAP_INFO_MAX_AMSDU_SIZE); + /* check this before VHT, because setting oper chan + * width and friends is the same call for HE and VHT + * and checks if conf->ieee8021ax == 1 */ + if (mode->he_capab[wpas_mode_to_ieee80211_mode( + ssid->mode)].he_supported && + ssid->he) + conf->ieee80211ax = 1; + if (mode->vht_capab && ssid->vht) { conf->ieee80211ac = 1; conf->vht_capab |= mode->vht_capab; wpas_conf_ap_vht(wpa_s, ssid, conf, mode); } - - if (mode->he_capab[wpas_mode_to_ieee80211_mode( - ssid->mode)].he_supported && - ssid->he) - conf->ieee80211ax = 1; } } diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index c085466b1..8cacf28e1 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -333,30 +333,6 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, frequency); goto out_free; } - if (ssid->ht40) - conf->secondary_channel = ssid->ht40; - if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) { - if (ssid->max_oper_chwidth != DEFAULT_MAX_OPER_CHWIDTH) - conf->vht_oper_chwidth = ssid->max_oper_chwidth; - switch (conf->vht_oper_chwidth) { - case CHANWIDTH_80MHZ: - case CHANWIDTH_80P80MHZ: - ieee80211_freq_to_chan( - frequency, - &conf->vht_oper_centr_freq_seg0_idx); - conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2; - break; - case CHANWIDTH_160MHZ: - ieee80211_freq_to_chan( - frequency, - &conf->vht_oper_centr_freq_seg0_idx); - conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2; - conf->vht_oper_centr_freq_seg0_idx += 40 / 5; - break; - } - ieee80211_freq_to_chan(ssid->vht_center_freq2, - &conf->vht_oper_centr_freq_seg1_idx); - } if (ssid->mesh_basic_rates == NULL) { /* From 0be9c232a35c5fab719feadf01a6e58594696e0a Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 13:53:18 +0200 Subject: [PATCH 1000/1105] tests: Remove wpas_mesh_open_5ghz_coex This is in preparation for an implementation change that ends up contradicting the operations enforced in this test case for mesh coex. Signed-off-by: Markus Theil --- tests/hwsim/test_wpas_mesh.py | 50 ----------------------------------- 1 file changed, 50 deletions(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 64e3cc66d..b7f98468b 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -929,56 +929,6 @@ def _test_wpas_mesh_open_5ghz(dev, apdev): dev[0].dump_monitor() dev[1].dump_monitor() -def test_wpas_mesh_open_5ghz_coex(dev, apdev): - """Mesh network on 5 GHz band and 20/40 coex change""" - try: - _test_wpas_mesh_open_5ghz_coex(dev, apdev) - finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - set_world_reg(apdev0=apdev[0], dev0=dev[0]) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() - -def _test_wpas_mesh_open_5ghz_coex(dev, apdev): - check_mesh_support(dev[0]) - subprocess.call(['iw', 'reg', 'set', 'US']) - - # Start a 20 MHz BSS on channel 40 that would be the secondary channel of - # HT40+ mesh on channel 36. - params = {"ssid": "test-ht40", - "hw_mode": "a", - "channel": "40", - "country_code": "US"} - hapd = hostapd.add_ap(apdev[0], params) - bssid = hapd.own_addr() - - for i in range(2): - for j in range(5): - ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5) - if ev is None: - raise Exception("No regdom change event") - if "alpha2=US" in ev: - break - dev[i].scan_for_bss(bssid, freq=5200) - add_open_mesh_network(dev[i], freq="5180") - - check_mesh_joined_connected(dev) - - freq = dev[0].get_status_field("freq") - if freq != "5200": - raise Exception("Unexpected STATUS freq=" + freq) - sig = dev[0].request("SIGNAL_POLL").splitlines() - if "FREQUENCY=5200" not in sig: - raise Exception("Unexpected SIGNAL_POLL output: " + str(sig)) - - hapd.disable() - dev[0].mesh_group_remove() - dev[1].mesh_group_remove() - check_mesh_group_removed(dev[0]) - check_mesh_group_removed(dev[1]) - dev[0].dump_monitor() - dev[1].dump_monitor() def test_wpas_mesh_open_ht40(dev, apdev): """Mesh and HT40 support difference""" From 93da12fd9ff7596f057ddd3f0e67210960fe6a90 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 13:53:18 +0200 Subject: [PATCH 1001/1105] mesh: Fix channel init order, disable pri/sec channel switch wpa_supplicant_conf_ap_ht() has to happen before hostapd_setup_interface() in order for its configuration settings to have effect on interface configuration. Disable primary and secondary channel switch because of missing tie breaking rule/frames in mesh networks. A rather long comment about this issue is placed in mesh.c in the corresponding place. I was not able to reproduce the memory corruption during mesh_secure_ocv_mix_legacy, which lead to a revert of a similar patch in the past. Signed-off-by: Markus Theil --- wpa_supplicant/mesh.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 8cacf28e1..558d87ae2 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -363,6 +363,31 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, conf->basic_rates[rate_len] = -1; } + /* While it can enhance performance to switch the primary channel, which + * is also the secondary channel of another network at the same time), + * to the other primary channel, problems exist with this in mesh + * networks. + * + * Example with problems: + * - 3 mesh nodes M1-M3, freq (5200, 5180) + * - other node O1, e.g. AP mode, freq (5180, 5200), + * Locations: O1 M1 M2 M3 + * + * M3 can only send frames to M1 over M2, no direct connection is + * possible + * Start O1, M1 and M3 first, M1 or O1 will switch channels to align + * with* each other. M3 does not swap, because M1 or O1 cannot be + * reached. M2 is started afterwards and can either connect to M3 or M1 + * because of this primary secondary channel switch. + * + * Solutions: (1) central coordination -> not always possible + * (2) disable pri/sec channel switch in mesh networks + * + * In AP mode, when all nodes can work independently, this poses of + * course no problem, therefore disable it only in mesh mode. */ + conf->no_pri_sec_switch = 1; + wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf); + if (wpa_drv_init_mesh(wpa_s)) { wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver"); return -1; @@ -374,8 +399,6 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, return -1; } - wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf); - return 0; out_free: wpa_supplicant_mesh_deinit(wpa_s); From df6745e8c8c1312d41f3e7fd044f438408526a2b Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 13:53:19 +0200 Subject: [PATCH 1002/1105] wpa_supplicant: Handle HT40 and mode downgrade in AP mode Add some missing pieces to the interface configuration of AP/mesh mode in wpa_supplicant. - check for secondary channel and HT40 capability - try to downgrade to IEEE 802.11b if 802.11g is not available Especially with the HT40 check, this code now performs all settings, which the deleted/duplicated mesh code did. Signed-off-by: Markus Theil --- wpa_supplicant/ap.c | 52 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 895b62ae3..bac79b2e4 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -134,6 +134,24 @@ no_vht: } +static struct hostapd_hw_modes * +wpa_supplicant_find_hw_mode(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode hw_mode) +{ + struct hostapd_hw_modes *mode = NULL; + int i; + + for (i = 0; i < wpa_s->hw.num_modes; i++) { + if (wpa_s->hw.modes[i].mode == hw_mode) { + mode = &wpa_s->hw.modes[i]; + break; + } + } + + return mode; +} + + int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_config *conf) @@ -147,9 +165,6 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, return -1; } - /* TODO: enable HT40 if driver supports it; - * drop to 11b if driver does not support 11g */ - /* * Enable HT20 if the driver supports it, by setting conf->ieee80211n * and a mask of allowed capabilities within conf->ht_capab. @@ -158,17 +173,28 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, */ if (wpa_s->hw.modes) { struct hostapd_hw_modes *mode = NULL; - int i, no_ht = 0; + int no_ht = 0; wpa_printf(MSG_DEBUG, "Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)", ssid->frequency, conf->channel); - for (i = 0; i < wpa_s->hw.num_modes; i++) { - if (wpa_s->hw.modes[i].mode == conf->hw_mode) { - mode = &wpa_s->hw.modes[i]; - break; - } + mode = wpa_supplicant_find_hw_mode(wpa_s, conf->hw_mode); + + /* May drop to IEEE 802.11b if the driver does not support IEEE + * 802.11g */ + if (!mode && conf->hw_mode == HOSTAPD_MODE_IEEE80211G) { + conf->hw_mode = HOSTAPD_MODE_IEEE80211B; + wpa_printf(MSG_INFO, + "Try downgrade to IEEE 802.11b as 802.11g is not supported by the current hardware"); + mode = wpa_supplicant_find_hw_mode(wpa_s, + conf->hw_mode); + } + + if (!mode) { + wpa_printf(MSG_ERROR, + "No match between requested and supported hw modes found"); + return -1; } #ifdef CONFIG_HT_OVERRIDES @@ -193,6 +219,14 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET), ssid->ht40); conf->ieee80211n = 1; + + if (ssid->ht40 && + (mode->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) + conf->secondary_channel = ssid->ht40; + else + conf->secondary_channel = 0; + #ifdef CONFIG_P2P if (ssid->p2p_group && conf->hw_mode == HOSTAPD_MODE_IEEE80211A && From 5965c7da5d6d0b81ef32cd19d9f69efcd9e0aa5c Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 13:53:21 +0200 Subject: [PATCH 1003/1105] wpa_supplicant: Enable VHT and HE in default config parameters Enable VHT and HE as default config parameters in order for wpa_supplicant AP mode to use it, if hw support is given. Signed-off-by: Markus Theil --- wpa_supplicant/config.c | 2 ++ wpa_supplicant/config_file.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 61761299b..e8c4d05a4 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -3038,6 +3038,8 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS; ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; ssid->ht = 1; + ssid->vht = 1; + ssid->he = 1; #ifdef IEEE8021X_EAPOL ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index c01557dac..246644a33 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -876,9 +876,10 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1); INT(disabled); INT(mixed_cell); - INT(vht); + INT_DEF(vht, 1); INT_DEF(ht, 1); INT(ht40); + INT_DEF(he, 1); INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH); INT(vht_center_freq1); INT(vht_center_freq2); From a72599b319ab0e17ebdf3415b45d6deb405c3a84 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 13:53:22 +0200 Subject: [PATCH 1004/1105] hw_features: Better debug messages for some error cases Signed-off-by: Markus Theil --- src/common/hw_features_common.c | 36 ++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c index 1d9387f70..511e68f9e 100644 --- a/src/common/hw_features_common.c +++ b/src/common/hw_features_common.c @@ -540,13 +540,20 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, if (center_segment1 || (center_segment0 != 0 && 5000 + center_segment0 * 5 != data->center_freq1 && - 2407 + center_segment0 * 5 != data->center_freq1)) + 2407 + center_segment0 * 5 != data->center_freq1)) { + wpa_printf(MSG_ERROR, + "20/40 MHz: center segment 0 (=%d) and center freq 1 (=%d) not in sync", + center_segment0, data->center_freq1); return -1; + } break; case CHANWIDTH_80P80MHZ: if (center_segment1 == center_segment0 + 4 || - center_segment1 == center_segment0 - 4) + center_segment1 == center_segment0 - 4) { + wpa_printf(MSG_ERROR, + "80+80 MHz: center segment 1 only 20 MHz apart"); return -1; + } data->center_freq2 = 5000 + center_segment1 * 5; /* fall through */ case CHANWIDTH_80MHZ: @@ -555,8 +562,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, center_segment1) || (oper_chwidth == CHANWIDTH_80P80MHZ && !center_segment1) || - !sec_channel_offset) + !sec_channel_offset) { + wpa_printf(MSG_ERROR, + "80/80+80 MHz: center segment 1 wrong or no second channel offset"); return -1; + } if (!center_segment0) { if (channel <= 48) center_segment0 = 42; @@ -582,16 +592,25 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, center_segment0 == channel - 2 || center_segment0 == channel - 6) data->center_freq1 = 5000 + center_segment0 * 5; - else + else { + wpa_printf(MSG_ERROR, + "Wrong coupling between HT and VHT/HE channel setting"); return -1; + } } break; case CHANWIDTH_160MHZ: data->bandwidth = 160; - if (center_segment1) + if (center_segment1) { + wpa_printf(MSG_ERROR, + "160 MHz: center segment 1 should not be set"); return -1; - if (!sec_channel_offset) + } + if (!sec_channel_offset) { + wpa_printf(MSG_ERROR, + "160 MHz: second channel offset not set"); return -1; + } /* * Note: HT/VHT config and params are coupled. Check if * HT40 channel band is in VHT160 channel band configuration. @@ -605,8 +624,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, center_segment0 == channel - 10 || center_segment0 == channel - 14) data->center_freq1 = 5000 + center_segment0 * 5; - else + else { + wpa_printf(MSG_ERROR, + "160 MHz: HT40 channel band is not in 160 MHz band"); return -1; + } break; } From c3f37c35f0ef02bd88ce4faf25a466e52e7a64f8 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 13:53:23 +0200 Subject: [PATCH 1005/1105] DFS: Use helper functions for VHT/HE parameters This is needed to cover the HE-specific conf->he_oper_chwidth value in addition to conf->vht_oper_chwidth. Signed-off-by: Markus Theil --- src/ap/dfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index f62da49a7..f04a00af0 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -955,10 +955,13 @@ dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel, if (*skip_radar) { *skip_radar = 0; } else { - if (iface->conf->vht_oper_chwidth == CHANWIDTH_USE_HT) + int oper_chwidth; + + oper_chwidth = hostapd_get_oper_chwidth(iface->conf); + if (oper_chwidth == CHANWIDTH_USE_HT) break; *skip_radar = 1; - iface->conf->vht_oper_chwidth--; + hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1); } } From 39748963d76152e05cf8177306af11f4ffe6f434 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 14 Oct 2020 22:57:04 +0300 Subject: [PATCH 1006/1105] build: Fix libeap_peer.a build The install target at the beginning of src/eap_peer/Makefile was confusing make about the build rules for libeap_peer.a and overriding of the install target between src/eap_peer/Makefile and src/lib.rules was breaking installation of dynamic EAP peer *.so files. Fix this by lib.rules defining a default for the install target so that src/*/Makefile can override that and by moving the install target for eap_peer to the end of the Makefile. Signed-off-by: Jouni Malinen --- src/eap_peer/Makefile | 12 ++++++------ src/lib.rules | 5 ++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile index 762c7a8eb..bdbead6a6 100644 --- a/src/eap_peer/Makefile +++ b/src/eap_peer/Makefile @@ -1,9 +1,3 @@ -install: - if ls *.so >/dev/null 2>&1; then \ - install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \ - cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ - ; fi - CFLAGS += -DIEEE8021X_EAPOL LIB_OBJS= \ @@ -11,3 +5,9 @@ LIB_OBJS= \ eap_methods.o include ../lib.rules + +install: + if ls *.so >/dev/null 2>&1; then \ + install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \ + cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ + ; fi diff --git a/src/lib.rules b/src/lib.rules index 8182db8c7..59801c517 100644 --- a/src/lib.rules +++ b/src/lib.rules @@ -19,8 +19,11 @@ $(ALL): $(LIB_OBJS) @$(E) " AR $(notdir $@)" $(Q)$(AR) crT $@ $? -install: +install-default: @echo Nothing to be made. +%: %-default + @true + clean: $(Q)rm -f *~ *.o *.d *.gcno *.gcda *.gcov $(ALL) From cc3d6efa8b04af1590feac23b639b2c60dd68860 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Thu, 8 Oct 2020 17:47:19 +0530 Subject: [PATCH 1007/1105] Add QCA interface for driver to report various connect fail reason codes The connection process fails for several reasons and the status codes defined in IEEE Std 802.11 do not cover the locally generated reason codes. Add an attribute to QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor sub command which can be used by the driver/firmware to report various additional reason codes for connection failures. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 41724876f..eb6a2c149 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -9478,6 +9478,16 @@ enum qca_vendor_wlan_sta_guard_interval { * only. This represents number of Beacon frames received from this station with * the packet number less than or equal to the last received packet number when * beacon protection is enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE: u32, used in + * STA mode only. The driver uses this attribute to populate the connection + * failure reason codes and the values are defined in + * enum qca_sta_connect_fail_reason_codes. Userspace applications can send + * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command after receiving + * a connection failure indication from the driver. The driver shall not + * include this attribute in response to the + * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO command if there is no connection + * failure observed in the last attempted connection. */ enum qca_wlan_vendor_attr_get_sta_info { QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0, @@ -9523,6 +9533,7 @@ enum qca_wlan_vendor_attr_get_sta_info { QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT = 40, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT = 41, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT = 42, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE = 43, /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST, @@ -9972,4 +9983,32 @@ enum qca_wlan_vendor_attr_mbssid_tx_vdev_status { QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST - 1, }; +/** + * enum qca_sta_connect_fail_reason_codes - Defines values carried + * by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor + * attribute. + * @QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received + * for unicast Probe Request frame. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for + * auth request. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not + * received from AP. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send + * Association Request frame. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for + * Association Request frame. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response + * frame is not received from AP. + */ +enum qca_sta_connect_fail_reason_codes { + QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1, + QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2, + QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3, + QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7, +}; + #endif /* QCA_VENDOR_H */ From 0f7989d8af726b5f4ee3741a45545fe890c83366 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Tue, 13 Oct 2020 21:21:13 +0530 Subject: [PATCH 1008/1105] MSCS: Fix decapsulating subelements from MSCS descriptor Fix pointer sent for decapsulating subelements from MSCS descriptor IE while processing (re)association response frames. Fixes: af8ab3208d03 ("MSCS: Parse result of MSCS setup in (Re)Association Response frames") Signed-off-by: Jouni Malinen --- wpa_supplicant/robust_av.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c index 4ac1a2bb9..1280f5d96 100644 --- a/wpa_supplicant/robust_av.c +++ b/wpa_supplicant/robust_av.c @@ -142,10 +142,13 @@ void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, return; mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR); - if (!mscs_desc_ie || mscs_desc_ie[1] < 1) + if (!mscs_desc_ie || mscs_desc_ie[1] <= 8) return; - mscs_status = get_ie(mscs_desc_ie, mscs_desc_ie[1], + /* Subelements start after (ie_id(1) + ie_len(1) + ext_id(1) + + * request type(1) + upc(2) + stream timeout(4) =) 10. + */ + mscs_status = get_ie(&mscs_desc_ie[10], mscs_desc_ie[1] - 8, MCSC_SUBELEM_STATUS); if (!mscs_status || mscs_status[1] < 2) return; From 13256b8cf3ed3965207e7dcc83435b2a13114a0a Mon Sep 17 00:00:00 2001 From: Hu Wang Date: Wed, 29 Jul 2020 11:15:35 +0800 Subject: [PATCH 1009/1105] P2P: Stop old listen radio work before go to WAIT_PEER_IDLE state P2P goes to Listen state while waiting for the peer to become ready for GO Negotiation. If old listen radio work has not been completed, P2P fails to go to listen state. This could happen in cases where P2P Action frame transmission reused ongoing p2p-listen radio work. p2p0: Add radio work 'p2p-listen'@0x P2P-FIND-STOPPED p2p0: Starting radio work 'p2p-listen'@0x after 0.010644 second wait P2P: Use ongoing radio work for Action frame TX P2P: Use ongoing radio work for Action frame TX P2P: State CONNECT -> CONNECT P2P: State CONNECT -> WAIT_PEER_IDLE P2P: State WAIT_PEER_IDLE -> WAIT_PEER_CONNECT P2P: Reject start_listen since p2p_listen_work already exists P2P: Failed to start listen mode Signed-off-by: Jouni Malinen --- src/p2p/p2p.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index b7a5eae35..f9ca90301 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -3974,6 +3974,7 @@ static void p2p_timeout_wait_peer_idle(struct p2p_data *p2p) } p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation"); + p2p->cfg->stop_listen(p2p->cfg->cb_ctx); p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT); p2p_listen_in_find(p2p, 0); } From 4c66894fab44d2e81e4cc95a47ead465458beef3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 16 Oct 2020 09:21:25 +0200 Subject: [PATCH 1010/1105] eap_peer: Add .gitignore with *.so If wpa_supplicant is built with dynamic EAP methods, the *.so files land here. Add them to .gitignore. Signed-off-by: Johannes Berg --- src/eap_peer/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/eap_peer/.gitignore diff --git a/src/eap_peer/.gitignore b/src/eap_peer/.gitignore new file mode 100644 index 000000000..140f8cf80 --- /dev/null +++ b/src/eap_peer/.gitignore @@ -0,0 +1 @@ +*.so From d720de929f918807fe7e62dd01644d267d4bb888 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Thu, 15 Oct 2020 22:00:40 +0200 Subject: [PATCH 1011/1105] hostapd: Fix typos Signed-off-by: Yegor Yefremov --- hostapd/Android.mk | 2 +- hostapd/ChangeLog | 4 ++-- hostapd/Makefile | 2 +- hostapd/android.config | 2 +- hostapd/ctrl_iface.c | 2 +- hostapd/defconfig | 2 +- hostapd/hostapd.conf | 6 +++--- hostapd/hostapd_cli.c | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 6cfbe5c22..6c9561778 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -414,7 +414,7 @@ endif ifdef CONFIG_EAP_SIM_COMMON OBJS += src/eap_common/eap_sim_common.c # Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be -# replaced with another file implementating the interface specified in +# replaced with another file implementing the interface specified in # eap_sim_db.h. OBJS += src/eap_server/eap_sim_db.c NEED_FIPS186_2_PRF=y diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog index 6c4410e8e..34a8a0818 100644 --- a/hostapd/ChangeLog +++ b/hostapd/ChangeLog @@ -362,7 +362,7 @@ ChangeLog for hostapd * RADIUS server functionality - add minimal RADIUS accounting server support (hostapd-as-server); this is mainly to enable testing coverage with hwsim scripts - - allow authentication log to be written into SQLite databse + - allow authentication log to be written into SQLite database - added option for TLS protocol testing of an EAP peer by simulating various misbehaviors/known attacks - MAC ACL support for testing purposes @@ -668,7 +668,7 @@ ChangeLog for hostapd * fixed HT Capabilities IE with nl80211 drivers * moved generic AP functionality code into src/ap * WPS: handle Selected Registrar as union of info from all Registrars - * remove obsolte Prism54.org driver wrapper + * remove obsolete Prism54.org driver wrapper * added internal debugging mechanism with backtrace support and memory allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y) * EAP-FAST server: piggyback Phase 2 start with the end of Phase 1 diff --git a/hostapd/Makefile b/hostapd/Makefile index 555e05f4a..456fb184f 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -444,7 +444,7 @@ endif ifdef CONFIG_EAP_SIM_COMMON OBJS += ../src/eap_common/eap_sim_common.o # Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be -# replaced with another file implementating the interface specified in +# replaced with another file implementing the interface specified in # eap_sim_db.h. OBJS += ../src/eap_server/eap_sim_db.o NEED_FIPS186_2_PRF=y diff --git a/hostapd/android.config b/hostapd/android.config index 94a9bb47b..7bd792efe 100644 --- a/hostapd/android.config +++ b/hostapd/android.config @@ -184,7 +184,7 @@ CONFIG_AP=y #CONFIG_FST=y # Multiband Operation support -# These extentions facilitate efficient use of multiple frequency bands +# These extensions facilitate efficient use of multiple frequency bands # available to the AP and the devices that may associate with it. #CONFIG_MBO=y diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 5b71a7bc4..30fa47f2d 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1922,7 +1922,7 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) { wpa_printf(MSG_DEBUG, - "test data: RX - ignore unexpect IP header"); + "test data: RX - ignore unexpected IP header"); return; } diff --git a/hostapd/defconfig b/hostapd/defconfig index 64f03bd84..e9f5de775 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -351,7 +351,7 @@ CONFIG_IPV6=y #CONFIG_ACS=y # Multiband Operation support -# These extentions facilitate efficient use of multiple frequency bands +# These extensions facilitate efficient use of multiple frequency bands # available to the AP and the devices that may associate with it. #CONFIG_MBO=y diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 29717d2c6..bf89fbcda 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1202,7 +1202,7 @@ eap_server=0 # should be unique across all issuing servers. In theory, this is a variable # length field, but due to some existing implementations requiring A-ID to be # 16 octets in length, it is strongly recommended to use that length for the -# field to provid interoperability with deployed peer implementations. This +# field to provide interoperability with deployed peer implementations. This # field is configured in hex format. #eap_fast_a_id=101112131415161718191a1b1c1d1e1f @@ -1776,7 +1776,7 @@ own_ip_addr=127.0.0.1 # be followed by optional peer MAC address (dot11RSNAConfigPasswordPeerMac) and # by optional password identifier (dot11RSNAConfigPasswordIdentifier). In # addition, an optional VLAN ID specification can be used to bind the station -# to the specified VLAN whenver the specific SAE password entry is used. +# to the specified VLAN whenever the specific SAE password entry is used. # # If the peer MAC address is not included or is set to the wildcard address # (ff:ff:ff:ff:ff:ff), the entry is available for any station to use. If a @@ -2037,7 +2037,7 @@ own_ip_addr=127.0.0.1 #ft_psk_generate_local=0 ##### Neighbor table ########################################################## -# Maximum number of entries kept in AP table (either for neigbor table or for +# Maximum number of entries kept in AP table (either for neighbor table or for # detecting Overlapping Legacy BSS Condition). The oldest entry will be # removed when adding a new entry that would make the list grow over this # limit. Note! WFA certification for IEEE 802.11g requires that OLBC is diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 363ae0ee7..ad4398175 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -975,7 +975,7 @@ static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl) dir = opendir(ctrl_iface_dir); if (dir == NULL) { printf("Control interface directory '%s' could not be " - "openned.\n", ctrl_iface_dir); + "opened.\n", ctrl_iface_dir); return; } From 0747432efdf70fb1269bf6dc98cc2619132ad3ff Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 16 Oct 2020 12:42:23 +0300 Subject: [PATCH 1012/1105] Fix spelling of "unexpected" in messages Signed-off-by: Jouni Malinen --- tests/hwsim/test_rrm.py | 4 ++-- wpa_supplicant/ctrl_iface.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_rrm.py b/tests/hwsim/test_rrm.py index b9de82de5..73782c995 100644 --- a/tests/hwsim/test_rrm.py +++ b/tests/hwsim/test_rrm.py @@ -1116,7 +1116,7 @@ def test_rrm_beacon_req_table_bssid(dev, apdev): report = BeaconReport(binascii.unhexlify(fields[4])) logger.info("Received beacon report: " + str(report)) if "bssid=" + bssid2 not in str(report): - raise Exception("Report for unexpect BSS") + raise Exception("Report for unexpected BSS") ev = hapd.wait_event(["BEACON-RESP-RX"], timeout=0.1) if ev is not None: raise Exception("Unexpected beacon report response") @@ -1140,7 +1140,7 @@ def test_rrm_beacon_req_table_ssid(dev, apdev): report = BeaconReport(binascii.unhexlify(fields[4])) logger.info("Received beacon report: " + str(report)) if "bssid=" + bssid2 not in str(report): - raise Exception("Report for unexpect BSS") + raise Exception("Report for unexpected BSS") ev = hapd.wait_event(["BEACON-RESP-RX"], timeout=0.1) if ev is not None: raise Exception("Unexpected beacon report response") diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 76a3ed618..f5c65870e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -9342,7 +9342,7 @@ static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) { wpa_printf(MSG_DEBUG, - "test data: RX - ignore unexpect IP header"); + "test data: RX - ignore unexpected IP header"); return; } From d34b33451c83414d690661905f14cf585fb10ccd Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 14 Oct 2020 21:31:15 +0200 Subject: [PATCH 1013/1105] wpa_supplicant: Fix frequency config for VHT/HE cases Fix compilation without CONFIG_P2P and only set secondary channel seg idx if we use a mode supporting a sec channel for VHT/HE. Signed-off-by: Markus Theil --- wpa_supplicant/ap.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index bac79b2e4..a4892e788 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -52,8 +52,8 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, #ifdef CONFIG_P2P u8 center_chan = 0; u8 channel = conf->channel; - u8 freq_seg_idx; #endif /* CONFIG_P2P */ + u8 freq_seg_idx; if (!conf->secondary_channel) goto no_vht; @@ -62,24 +62,28 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, if (ssid->max_oper_chwidth) hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth); - ieee80211_freq_to_chan(ssid->vht_center_freq2, - &freq_seg_idx); - hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx); + if (hostapd_get_oper_chwidth(conf) == CHANWIDTH_80P80MHZ) { + ieee80211_freq_to_chan(ssid->vht_center_freq2, + &freq_seg_idx); + hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx); + } if (!ssid->p2p_group) { - if (!ssid->vht_center_freq1 || - hostapd_get_oper_chwidth(conf) == CHANWIDTH_USE_HT) + if (!ssid->vht_center_freq1) goto no_vht; ieee80211_freq_to_chan(ssid->vht_center_freq1, &freq_seg_idx); hostapd_set_oper_centr_freq_seg0_idx(conf, freq_seg_idx); - wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP", - hostapd_get_oper_centr_freq_seg0_idx(conf)); + + wpa_printf(MSG_DEBUG, + "VHT seg0 index %d and seg1 index %d for AP", + hostapd_get_oper_centr_freq_seg0_idx(conf), + hostapd_get_oper_centr_freq_seg1_idx(conf)); return; } #ifdef CONFIG_P2P - switch (conf->vht_oper_chwidth) { + switch (hostapd_get_oper_chwidth(conf)) { case CHANWIDTH_80MHZ: case CHANWIDTH_80P80MHZ: center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel); From d68c0dd4d42fc75ea90b729e907eb289b0f4a11b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 Oct 2020 11:42:21 +0200 Subject: [PATCH 1014/1105] build: lib.rules: Add common-clean During the build reshuffling, I missed this, so doing 'make clean' in a certain src/lib folder doesn't clean up everything anymore. Fix that. Signed-off-by: Johannes Berg --- src/lib.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rules b/src/lib.rules index 59801c517..947617b07 100644 --- a/src/lib.rules +++ b/src/lib.rules @@ -25,5 +25,5 @@ install-default: %: %-default @true -clean: +clean: common-clean $(Q)rm -f *~ *.o *.d *.gcno *.gcda *.gcov $(ALL) From e364a34c69fdd0ca3985af29dade24f5176564c6 Mon Sep 17 00:00:00 2001 From: Pooventhiran G Date: Sun, 18 Oct 2020 21:00:09 +0530 Subject: [PATCH 1015/1105] OpenSSL: Make openssl_debug_dump_certificate() more robust SSL_CTX_get0_certificate() returns NULL if no certificate is installed. While this should not be the case here due to the loop in openssl_debug_dump_certificate_chains() proceeding only if the SSL_CTX_set_current_cert() returns success, it is safer to make openssl_debug_dump_certificate() explicitly check against NULL before trying to dump details about the certificate. Signed-off-by: Pooventhiran G --- src/crypto/tls_openssl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index f7dfecbbf..ef872c50e 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -5323,6 +5323,9 @@ static void openssl_debug_dump_certificate(int i, X509 *cert) ASN1_INTEGER *ser; char serial_num[128]; + if (!cert) + return; + X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); ser = X509_get_serialNumber(cert); From ff7e0c1cf71170607a2aa8bb16284fbe2f314c32 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Mon, 19 Oct 2020 11:06:28 +0300 Subject: [PATCH 1016/1105] wpa_cli: Don't access uninitialized variables Don't print potentially uninitialized variables in wpa_ctrl_command_bss(). Some compilers and analyzers may warn about it. Signed-off-by: Andrei Otcheretianski --- wpa_supplicant/wpa_cli.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 51c9642e9..813e4b3cf 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -3085,7 +3085,8 @@ static int wpa_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc, static int wpa_ctrl_command_bss(struct wpa_ctrl *ctrl, const char *cmd) { - char buf[512], *pos, *bssid, *freq, *level, *flags, *ssid; + char buf[512], *pos, *bssid = NULL, *freq = NULL, *level = NULL, + *flags = NULL, *ssid = NULL; size_t len; int ret, id = -1; @@ -3126,7 +3127,9 @@ static int wpa_ctrl_command_bss(struct wpa_ctrl *ctrl, const char *cmd) *pos++ = '\0'; } if (id != -1) - printf("%s\t%s\t%s\t%s\t%s\n", bssid, freq, level, flags, ssid); + printf("%s\t%s\t%s\t%s\t%s\n", bssid ? bssid : "N/A", + freq ? freq : "N/A", level ? level : "N/A", + flags ? flags : "N/A", ssid ? ssid : "N/A"); return id; } From b4c7114cf54a83570140d58d591018a8812d26be Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Mon, 19 Oct 2020 11:06:29 +0300 Subject: [PATCH 1017/1105] wpa_supplicant: Remove unfeasible conditions in config parsing pos can't be NULL in wpa_global_config_parse_str(), so there is no point checking this, especially when pos was already dereferenced earlier. Remove the redundant conditions. Signed-off-by: Andrei Otcheretianski --- wpa_supplicant/config.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index e8c4d05a4..c5161544d 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -4469,9 +4469,7 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data, prev_len = 0; /* No change to the previously configured value */ - if ((!(*dst) && !pos) || - (*dst && pos && prev_len == len && - os_memcmp(*dst, pos, len) == 0)) + if (*dst && prev_len == len && os_memcmp(*dst, pos, len) == 0) return 1; tmp = os_strdup(pos); From 80662accb5e945a7ac285e023138a5f79798b417 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Mon, 19 Oct 2020 11:06:30 +0300 Subject: [PATCH 1018/1105] SAE: Don't use potentially uninitialized keys If SAE_CONFIG_PK is not defined and sae->pk isn't zero (which is possible as it is controlled by the commit message status code), sae_derive_keys() may end up deriving PMK and KCK from an uninitialized array. Fix that. Fixes: 6b9e99e571ee ("SAE-PK: Extend SAE functionality for AP validation") Fixes: 20ccf97b3dc1 ("SAE-PK: AP functionality") Signed-off-by: Andrei Otcheretianski --- src/common/sae.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/common/sae.c b/src/common/sae.c index 057e1ce3b..372905db0 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -1609,18 +1609,26 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) * octets). */ crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len); wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); - if (!sae->pk && - sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", + +#ifdef CONFIG_SAE_PK + if (sae->pk) { + if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys", + val, sae->tmp->order_len, + keys, 2 * hash_len + SAE_PMK_LEN) < 0) + goto fail; + } else { + if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", + val, sae->tmp->order_len, + keys, hash_len + SAE_PMK_LEN) < 0) + goto fail; + } +#else /* CONFIG_SAE_PK */ + if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", val, sae->tmp->order_len, keys, hash_len + SAE_PMK_LEN) < 0) goto fail; -#ifdef CONFIG_SAE_PK - if (sae->pk && - sae_kdf_hash(hash_len, keyseed, "SAE-PK keys", - val, sae->tmp->order_len, - keys, 2 * hash_len + SAE_PMK_LEN) < 0) - goto fail; -#endif /* CONFIG_SAE_PK */ +#endif /* !CONFIG_SAE_PK */ + forced_memzero(keyseed, sizeof(keyseed)); os_memcpy(sae->tmp->kck, keys, hash_len); sae->tmp->kck_len = hash_len; From 183e72ae1348fddbb2f90de23c8378cb7d6cba1d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 19 Oct 2020 23:35:00 +0300 Subject: [PATCH 1019/1105] SAE-PK: Do not accept SAE-PK status code when no PK is configured Make sae_status_success() more explicit by rejecting SAE-PK status code when the AP is not configured with PK. Fixes: 20ccf97b3dc1 ("SAE-PK: AP functionality") Signed-off-by: Jouni Malinen --- src/ap/ieee802_11.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 292393224..de715a04c 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1149,6 +1149,7 @@ static int sae_status_success(struct hostapd_data *hapd, u16 status_code) { int sae_pwe = hapd->conf->sae_pwe; int id_in_use; + bool sae_pk = false; id_in_use = hostapd_sae_pw_id_in_use(hapd->conf); if (id_in_use == 2 && sae_pwe != 3) @@ -1156,7 +1157,8 @@ static int sae_status_success(struct hostapd_data *hapd, u16 status_code) else if (id_in_use == 1 && sae_pwe == 0) sae_pwe = 2; #ifdef CONFIG_SAE_PK - if (sae_pwe == 0 && hostapd_sae_pk_in_use(hapd->conf)) + sae_pk = hostapd_sae_pk_in_use(hapd->conf); + if (sae_pwe == 0 && sae_pk) sae_pwe = 2; #endif /* CONFIG_SAE_PK */ @@ -1164,11 +1166,11 @@ static int sae_status_success(struct hostapd_data *hapd, u16 status_code) status_code == WLAN_STATUS_SUCCESS) || (sae_pwe == 1 && (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || - status_code == WLAN_STATUS_SAE_PK)) || + (sae_pk && status_code == WLAN_STATUS_SAE_PK))) || (sae_pwe == 2 && (status_code == WLAN_STATUS_SUCCESS || status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || - status_code == WLAN_STATUS_SAE_PK)); + (sae_pk && status_code == WLAN_STATUS_SAE_PK))); } From ac835ea0928d416a92bebbe7129ae295166b6ddc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 19 Oct 2020 23:57:11 +0300 Subject: [PATCH 1020/1105] tests: SAE status code handling Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index 3ab29be80..1c80b3946 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -1076,6 +1076,47 @@ def test_sae_proto_hostapd_ffc(dev, apdev): # Unexpected continuation of the connection attempt with confirm hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030002000000" + "0000" + "fd7b081ff4e8676f03612a4140eedcd3c179ab3a13b93863c6f7ca451340b9ae") +def sae_start_ap(apdev, sae_pwe): + params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") + params['wpa_key_mgmt'] = 'SAE' + params['sae_groups'] = "19" + params['sae_pwe'] = str(sae_pwe) + return hostapd.add_ap(apdev, params) + +def check_commit_status(hapd, use_status, expect_status): + hapd.set("ext_mgmt_frame_handling", "1") + bssid = hapd.own_addr().replace(':', '') + addr = "020000000000" + addr2 = "020000000001" + hdr = "b0003a01" + bssid + addr + bssid + "1000" + hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" + group = "1300" + scalar = "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + element_x = "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d" + element_y = "d3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8" + status = binascii.hexlify(struct.pack(' Date: Sun, 18 Oct 2020 19:28:23 +0200 Subject: [PATCH 1021/1105] wpa_supplicant: Fix typos Signed-off-by: Yegor Yefremov --- wpa_supplicant/ChangeLog | 10 +++++----- wpa_supplicant/README | 4 ++-- wpa_supplicant/README-HS20 | 2 +- wpa_supplicant/binder/binder.h | 2 +- wpa_supplicant/config.h | 2 +- wpa_supplicant/ctrl_iface.c | 2 +- wpa_supplicant/dbus/dbus_new.c | 4 ++-- wpa_supplicant/dbus/dbus_new_handlers.c | 2 +- wpa_supplicant/examples/p2p-action-udhcp.sh | 4 ++-- wpa_supplicant/examples/p2p-action.sh | 4 ++-- wpa_supplicant/examples/p2p/p2p_connect.py | 16 ++++++++-------- wpa_supplicant/examples/p2p/p2p_disconnect.py | 2 +- wpa_supplicant/examples/p2p/p2p_find.py | 2 +- wpa_supplicant/examples/p2p/p2p_flush.py | 2 +- wpa_supplicant/examples/p2p/p2p_group_add.py | 10 +++++----- wpa_supplicant/examples/p2p/p2p_invite.py | 10 +++++----- wpa_supplicant/examples/p2p/p2p_listen.py | 2 +- wpa_supplicant/examples/p2p/p2p_stop_find.py | 2 +- wpa_supplicant/examples/udhcpd-p2p.conf | 10 +++++----- wpa_supplicant/interworking.c | 2 +- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wmm_ac.c | 2 +- wpa_supplicant/wpa_supplicant.conf | 2 +- 23 files changed, 50 insertions(+), 50 deletions(-) diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog index f82e5e0ea..a06a93b22 100644 --- a/wpa_supplicant/ChangeLog +++ b/wpa_supplicant/ChangeLog @@ -533,7 +533,7 @@ ChangeLog for wpa_supplicant * fixed MSCHAP UTF-8 to UCS-2 conversion for three-byte encoding; this fixes password with include UTF-8 characters that use three-byte encoding EAP methods that use NtPasswordHash - * fixed couple of sequencies where radio work items could get stuck, + * fixed couple of sequences where radio work items could get stuck, e.g., when rfkill blocking happens during scanning or when scan-for-auth workaround is used * P2P enhancements/fixes @@ -627,7 +627,7 @@ ChangeLog for wpa_supplicant * added 'dup_network ' command; this can be used to clone the psk field without having toextract it from wpa_supplicant * fixed GSM authentication on USIM - * added support for usin epoll in eloop (CONFIG_ELOOP_EPOLL=y) + * added support for using epoll in eloop (CONFIG_ELOOP_EPOLL=y) * fixed some concurrent virtual interface cases with dedicated P2P management interface to not catch events from removed interface (this could result in the management interface getting disabled) @@ -1113,7 +1113,7 @@ ChangeLog for wpa_supplicant workarounds. - Add support for AuthorizedMACs attribute. * TDLS: - - Propogate TDLS related nl80211 capability flags from kernel and + - Propagate TDLS related nl80211 capability flags from kernel and add them as driver capability flags. If the driver doesn't support capabilities, assume TDLS is supported internally. When TDLS is explicitly not supported, disable all user facing TDLS operations. @@ -2221,7 +2221,7 @@ ChangeLog for wpa_supplicant * added support for EAP-SIM pseudonyms and fast re-authentication * added support for EAP-TLS/PEAP/TTLS fast re-authentication (TLS session resumption) - * added support for EAP-SIM with two challanges + * added support for EAP-SIM with two challenges (phase1="sim_min_num_chal=3" can be used to require three challenges) * added support for configuring DH/DSA parameters for an ephemeral DH key exchange (EAP-TLS/PEAP/TTLS) using new configuration parameters @@ -2332,7 +2332,7 @@ ChangeLog for wpa_supplicant ctrl_interface_group can be used to select which group gets access to the control interface; wpa_cli: by default, try to connect to the first interface available - in /var/run/wpa_supplicant; this path can be overriden with -p option + in /var/run/wpa_supplicant; this path can be overridden with -p option and an interface can be selected with -i option (i.e., in most common cases, wpa_cli does not need to get any arguments) * added support for LEAP diff --git a/wpa_supplicant/README b/wpa_supplicant/README index bbc86b137..391912e9b 100644 --- a/wpa_supplicant/README +++ b/wpa_supplicant/README @@ -383,7 +383,7 @@ cp wpa_cli wpa_supplicant /usr/local/bin You will need to make a configuration file, e.g., /etc/wpa_supplicant.conf, with network configuration for the networks you are going to use. Configuration file section below includes -explanation fo the configuration file format and includes various +explanation of the configuration file format and includes various examples. Once the configuration is ready, you can test whether the configuration work by first running wpa_supplicant with following command to start it on foreground with debugging enabled: @@ -778,7 +778,7 @@ wpa_cli commands disconnect = disconnect and wait for reassociate command before connecting scan = request new BSS scan scan_results = get latest scan results - get_capability = get capabilies + get_capability = get capabilities terminate = terminate wpa_supplicant quit = exit wpa_cli diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20 index 334287101..484e4cbf4 100644 --- a/wpa_supplicant/README-HS20 +++ b/wpa_supplicant/README-HS20 @@ -78,7 +78,7 @@ hs20=1 # Parameters for controlling scanning -# Homogenous ESS identifier +# Homogeneous ESS identifier # If this is set, scans will be used to request response only from BSSes # belonging to the specified Homogeneous ESS. This is used only if interworking # is enabled. diff --git a/wpa_supplicant/binder/binder.h b/wpa_supplicant/binder/binder.h index 019e3275c..6d7abb134 100644 --- a/wpa_supplicant/binder/binder.h +++ b/wpa_supplicant/binder/binder.h @@ -17,7 +17,7 @@ extern "C" { /** * This is the binder RPC interface entry point to the wpa_supplicant core. * This initializes the binder driver & BinderManager instance and then forwards - * all the notifcations from the supplicant core to the BinderManager. + * all the notifications from the supplicant core to the BinderManager. */ struct wpas_binder_priv; struct wpa_global; diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index cd9830939..648573de0 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -650,7 +650,7 @@ struct wpa_config { * This variable control whether wpa_supplicant is allow to re-write * its configuration with wpa_config_write(). If this is zero, * configuration data is only changed in memory and the external data - * is not overriden. If this is non-zero, wpa_supplicant will update + * is not overridden. If this is non-zero, wpa_supplicant will update * the configuration data (e.g., a file) whenever configuration is * changed. This update may replace the old configuration which can * remove comments from it in case of a text file configuration. diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index f5c65870e..56a6aaaad 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -10278,7 +10278,7 @@ static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s, char *cmd) { /* - * We do not check mesh interface existance because PMKSA should be + * We do not check mesh interface existence because PMKSA should be * stored before wpa_s->ifmsh creation to suppress commit message * creation. */ diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index 6dcd948ad..2c01943f7 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -1824,7 +1824,7 @@ void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s, * @sa: station addr (p2p i/f) of the peer * @dialog_token: service discovery request dialog token * @update_indic: service discovery request update indicator - * @tlvs: service discovery request genrated byte array of tlvs + * @tlvs: service discovery request generated byte array of tlvs * @tlvs_len: service discovery request tlvs length */ void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, @@ -1893,7 +1893,7 @@ void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, * @wpa_s: %wpa_supplicant network interface data * @sa: station addr (p2p i/f) of the peer * @update_indic: service discovery request update indicator - * @tlvs: service discovery request genrated byte array of tlvs + * @tlvs: service discovery request generated byte array of tlvs * @tlvs_len: service discovery request tlvs length */ void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 86f85605a..fa9a1a370 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -2568,7 +2568,7 @@ wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message, * wpas_dbus_handler_save_config - Save configuration to configuration file * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface - * Returns: NULL on Success, Otherwise errror message + * Returns: NULL on Success, Otherwise error message * * Handler function for "SaveConfig" method call of network interface. */ diff --git a/wpa_supplicant/examples/p2p-action-udhcp.sh b/wpa_supplicant/examples/p2p-action-udhcp.sh index d7d0e79b7..53d8b777c 100755 --- a/wpa_supplicant/examples/p2p-action-udhcp.sh +++ b/wpa_supplicant/examples/p2p-action-udhcp.sh @@ -50,7 +50,7 @@ fi if [ "$CMD" = "P2P-CROSS-CONNECT-ENABLE" ]; then GIFNAME=$3 UPLINK=$4 - # enable NAT/masquarade $GIFNAME -> $UPLINK + # enable NAT/masquerade $GIFNAME -> $UPLINK iptables -P FORWARD DROP iptables -t nat -A POSTROUTING -o $UPLINK -j MASQUERADE iptables -A FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT @@ -61,7 +61,7 @@ fi if [ "$CMD" = "P2P-CROSS-CONNECT-DISABLE" ]; then GIFNAME=$3 UPLINK=$4 - # disable NAT/masquarade $GIFNAME -> $UPLINK + # disable NAT/masquerade $GIFNAME -> $UPLINK sysctl net.ipv4.ip_forward=0 iptables -t nat -D POSTROUTING -o $UPLINK -j MASQUERADE iptables -D FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT diff --git a/wpa_supplicant/examples/p2p-action.sh b/wpa_supplicant/examples/p2p-action.sh index 797d43a00..6c27b27b7 100755 --- a/wpa_supplicant/examples/p2p-action.sh +++ b/wpa_supplicant/examples/p2p-action.sh @@ -77,7 +77,7 @@ fi if [ "$CMD" = "P2P-CROSS-CONNECT-ENABLE" ]; then GIFNAME=$3 UPLINK=$4 - # enable NAT/masquarade $GIFNAME -> $UPLINK + # enable NAT/masquerade $GIFNAME -> $UPLINK iptables -P FORWARD DROP iptables -t nat -A POSTROUTING -o $UPLINK -j MASQUERADE iptables -A FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT @@ -88,7 +88,7 @@ fi if [ "$CMD" = "P2P-CROSS-CONNECT-DISABLE" ]; then GIFNAME=$3 UPLINK=$4 - # disable NAT/masquarade $GIFNAME -> $UPLINK + # disable NAT/masquerade $GIFNAME -> $UPLINK sysctl net.ipv4.ip_forward=0 iptables -t nat -D POSTROUTING -o $UPLINK -j MASQUERADE iptables -D FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT diff --git a/wpa_supplicant/examples/p2p/p2p_connect.py b/wpa_supplicant/examples/p2p/p2p_connect.py index 2f62e9c94..bfb553341 100644 --- a/wpa_supplicant/examples/p2p/p2p_connect.py +++ b/wpa_supplicant/examples/p2p/p2p_connect.py @@ -71,7 +71,7 @@ class P2P_Connect(): global wpas_dbus_interfaces_interface global wpas_dbus_interfaces_p2pdevice - # Dictionary of Arguements + # Dictionary of Arguments global p2p_connect_arguements # Constructor @@ -146,9 +146,9 @@ class P2P_Connect(): signal_name="WpsFailed") - #Constructing all the arguements needed to connect + #Constructing all the arguments needed to connect def constructArguements(self): - # Adding required arguements + # Adding required arguments self.p2p_connect_arguements = {'wps_method':self.wps_method, 'peer':dbus.ObjectPath(self.path+'/Peers/'+self.addr)} @@ -198,7 +198,7 @@ class P2P_Connect(): usage() quit() - # Go_intent is optional for all arguements + # Go_intent is optional for all arguments if (self.go_intent != None): self.p2p_connect_arguements.update( {'go_intent':dbus.Int32(self.go_intent)}) @@ -239,7 +239,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): @@ -266,9 +266,9 @@ if __name__ == "__main__": else: assert False, "unhandled option" - # Required Arguements check + # Required Arguments check if (interface_name == None or wps_method == None or addr == None): - print("Error:\n Required arguements not specified") + print("Error:\n Required arguments not specified") usage() quit() @@ -289,7 +289,7 @@ if __name__ == "__main__": addr,pin,wps_method,go_intent) except: - print("Error:\n Invalid Arguements") + print("Error:\n Invalid Arguments") usage() quit() diff --git a/wpa_supplicant/examples/p2p/p2p_disconnect.py b/wpa_supplicant/examples/p2p/p2p_disconnect.py index 85b5a8b39..f04b98e66 100644 --- a/wpa_supplicant/examples/p2p/p2p_disconnect.py +++ b/wpa_supplicant/examples/p2p/p2p_disconnect.py @@ -125,7 +125,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/p2p/p2p_find.py b/wpa_supplicant/examples/p2p/p2p_find.py index e2df52896..412d81200 100644 --- a/wpa_supplicant/examples/p2p/p2p_find.py +++ b/wpa_supplicant/examples/p2p/p2p_find.py @@ -136,7 +136,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/p2p/p2p_flush.py b/wpa_supplicant/examples/p2p/p2p_flush.py index 42fc7a3e9..5cc3a0e18 100644 --- a/wpa_supplicant/examples/p2p/p2p_flush.py +++ b/wpa_supplicant/examples/p2p/p2p_flush.py @@ -125,7 +125,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/p2p/p2p_group_add.py b/wpa_supplicant/examples/p2p/p2p_group_add.py index 6d408218a..fbfc2382e 100644 --- a/wpa_supplicant/examples/p2p/p2p_group_add.py +++ b/wpa_supplicant/examples/p2p/p2p_group_add.py @@ -18,7 +18,7 @@ def usage(): print(" [-w ]") print("Options:") print(" -i = interface name") - print(" -p = persistant group = 0 (0=false, 1=true)") + print(" -p = persistent group = 0 (0=false, 1=true)") print(" -f = frequency") print(" -o = persistent group object path") print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1") @@ -57,7 +57,7 @@ class P2P_Group_Add (threading.Thread): global wpas_dbus_interfaces_interface global wpas_dbus_interfaces_p2pdevice - # Arguements + # Arguments global P2PDictionary # Constructor @@ -141,7 +141,7 @@ class P2P_Group_Add (threading.Thread): self.p2p_interface.GroupAdd(self.P2PDictionary) except: - print("Error:\n Could not preform group add") + print("Error:\n Could not perform group add") usage() os._exit(0) @@ -172,7 +172,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): @@ -213,7 +213,7 @@ if __name__ == "__main__": p2p_group_add_test = P2P_Group_Add(interface_name,wpas_dbus_interface, persistent,frequency,persistent_group_object) except: - print("Error:\n Invalid Arguements") + print("Error:\n Invalid Arguments") p2p_group_add_test.constructArguements() p2p_group_add_test.start() diff --git a/wpa_supplicant/examples/p2p/p2p_invite.py b/wpa_supplicant/examples/p2p/p2p_invite.py index 341dcd0a9..8944e11ed 100644 --- a/wpa_supplicant/examples/p2p/p2p_invite.py +++ b/wpa_supplicant/examples/p2p/p2p_invite.py @@ -25,7 +25,7 @@ def usage(): # Required Signals def InvitationResult(invite_result): - print("Inviation Result signal :") + print("Invitation Result signal :") status = invite_result['status'] print("status = ", status) if invite_result.has_key('BSSID'): @@ -55,7 +55,7 @@ class P2P_Invite (threading.Thread): global wpas_dbus_interfaces_interface global wpas_dbus_interfaces_p2pdevice - # Arguements + # Arguments global P2PDictionary # Constructor @@ -127,7 +127,7 @@ class P2P_Invite (threading.Thread): self.p2p_interface.Invite(self.P2PDictionary) except: - print("Error:\n Invalid Arguements") + print("Error:\n Invalid Arguments") usage() os._exit(0) @@ -154,7 +154,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): @@ -190,7 +190,7 @@ if __name__ == "__main__": P2P_Invite(interface_name,wpas_dbus_interface, addr,persistent_group_object) except: - print("Error:\n Invalid Arguements") + print("Error:\n Invalid Arguments") usage() os._exit(1) diff --git a/wpa_supplicant/examples/p2p/p2p_listen.py b/wpa_supplicant/examples/p2p/p2p_listen.py index b0837d9df..cbeda9ff4 100644 --- a/wpa_supplicant/examples/p2p/p2p_listen.py +++ b/wpa_supplicant/examples/p2p/p2p_listen.py @@ -126,7 +126,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/p2p/p2p_stop_find.py b/wpa_supplicant/examples/p2p/p2p_stop_find.py index bdb4c0e32..f36719645 100644 --- a/wpa_supplicant/examples/p2p/p2p_stop_find.py +++ b/wpa_supplicant/examples/p2p/p2p_stop_find.py @@ -130,7 +130,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/udhcpd-p2p.conf b/wpa_supplicant/examples/udhcpd-p2p.conf index df5909408..9916a166c 100644 --- a/wpa_supplicant/examples/udhcpd-p2p.conf +++ b/wpa_supplicant/examples/udhcpd-p2p.conf @@ -11,8 +11,8 @@ end 192.168.42.254 #default: 192.168.0.254 interface wlan2 #default: eth0 -# The maximim number of leases (includes addressesd reserved -# by OFFER's, DECLINE's, and ARP conficts +# The maximum number of leases (includes addressesd reserved +# by OFFER's, DECLINE's, and ARP conflicts #max_leases 254 #default: 254 @@ -52,12 +52,12 @@ interface wlan2 #default: eth0 # If a lease to be given is below this value, the full lease time is # instead used (seconds). -#min_lease 60 #defult: 60 +#min_lease 60 #default: 60 # The location of the leases file -#lease_file /var/lib/misc/udhcpd.leases #defualt: /var/lib/misc/udhcpd.leases +#lease_file /var/lib/misc/udhcpd.leases #default: /var/lib/misc/udhcpd.leases # The location of the pid file pidfile /var/run/udhcpd-wlan2.pid #default: /var/run/udhcpd.pid @@ -77,7 +77,7 @@ pidfile /var/run/udhcpd-wlan2.pid #default: /var/run/udhcpd.pid #boot_file /var/nfs_root #default: (none) -# The remainer of options are DHCP options and can be specifed with the +# The remainder of options are DHCP options and can be specified with the # keyword 'opt' or 'option'. If an option can take multiple items, such # as the dns option, they can be listed on the same line, or multiple # lines. The only option with a default is 'lease'. diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 00e1492c6..ce11491b9 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -2532,7 +2532,7 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) (selected_cred == NULL || cred_prio_cmp(selected_home_cred, selected_cred) >= 0)) { /* Prefer network operated by the Home SP */ - wpa_printf(MSG_DEBUG, "Interworking: Overrided selected with selected_home"); + wpa_printf(MSG_DEBUG, "Interworking: Overrode selected with selected_home"); selected = selected_home; selected_cred = selected_home_cred; } diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 7fec1cd8d..9b4eeb915 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -300,7 +300,7 @@ static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s, *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES; *pos++ = rrm_ie_len; - /* Set supported capabilites flags */ + /* Set supported capabilities flags */ if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION) *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT; diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c index 38800cc77..d0fdd55d3 100644 --- a/wpa_supplicant/wmm_ac.c +++ b/wpa_supplicant/wmm_ac.c @@ -400,7 +400,7 @@ static int wmm_ac_ts_req_is_valid(struct wpa_supplicant *wpa_s, req_ac = up_to_ac[params->user_priority]; - /* Requested accesss category must have acm */ + /* Requested access category must have acm */ if (!wpa_s->wmm_ac_assoc_info->ac_params[req_ac].acm) { wpa_printf(MSG_DEBUG, "WMM AC: AC %d is not ACM", req_ac); return 0; diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index c10dd73ea..46f78755d 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -526,7 +526,7 @@ fast_reauth=1 #go_venue_group=7 #go_venue_type=1 -# Homogenous ESS identifier +# Homogeneous ESS identifier # If this is set, scans will be used to request response only from BSSes # belonging to the specified Homogeneous ESS. This is used only if interworking # is enabled. From 5d988b4a5b5d9993cd22d731bda2f2f513fcc945 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 20 Oct 2020 00:19:44 +0300 Subject: [PATCH 1022/1105] Fix couple more typos Couple of similar cases that were not included in the previous commit. Signed-off-by: Jouni Malinen --- src/tls/rsa.c | 2 +- wpa_supplicant/examples/p2p/p2p_group_add.py | 4 ++-- wpa_supplicant/examples/udhcpd-p2p.conf | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/tls/rsa.c b/src/tls/rsa.c index 3525eb991..1b01f5843 100644 --- a/src/tls/rsa.c +++ b/src/tls/rsa.c @@ -285,7 +285,7 @@ int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, if (use_private) { /* - * Decrypt (or sign) using Chinese remainer theorem to speed + * Decrypt (or sign) using Chinese remainder theorem to speed * up calculation. This is equivalent to tmp = tmp^d mod n * (which would require more CPU to calculate directly). * diff --git a/wpa_supplicant/examples/p2p/p2p_group_add.py b/wpa_supplicant/examples/p2p/p2p_group_add.py index fbfc2382e..db6d60d80 100644 --- a/wpa_supplicant/examples/p2p/p2p_group_add.py +++ b/wpa_supplicant/examples/p2p/p2p_group_add.py @@ -120,7 +120,7 @@ class P2P_Group_Add (threading.Thread): signal_name="WpsFailed") # Sets up p2p_group_add dictionary - def constructArguements(self): + def constructArguments(self): self.P2PDictionary = {'persistent':self.persistent} if (self.frequency != None): @@ -215,7 +215,7 @@ if __name__ == "__main__": except: print("Error:\n Invalid Arguments") - p2p_group_add_test.constructArguements() + p2p_group_add_test.constructArguments() p2p_group_add_test.start() time.sleep(5) print("Error:\n Group formation timed out") diff --git a/wpa_supplicant/examples/udhcpd-p2p.conf b/wpa_supplicant/examples/udhcpd-p2p.conf index 9916a166c..f92cc619e 100644 --- a/wpa_supplicant/examples/udhcpd-p2p.conf +++ b/wpa_supplicant/examples/udhcpd-p2p.conf @@ -11,8 +11,8 @@ end 192.168.42.254 #default: 192.168.0.254 interface wlan2 #default: eth0 -# The maximum number of leases (includes addressesd reserved -# by OFFER's, DECLINE's, and ARP conflicts +# The maximum number of leases (includes addresses reserved +# by OFFER's, DECLINE's, and ARP conflicts) #max_leases 254 #default: 254 @@ -116,5 +116,3 @@ option lease 864000 # 10 days of seconds # Static leases map #static_lease 00:60:08:11:CE:4E 192.168.0.54 #static_lease 00:60:08:11:CE:3E 192.168.0.44 - - From d2190cdc65cfd66de35399469e9ad79d531dce97 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 21 Oct 2020 00:29:38 +0300 Subject: [PATCH 1023/1105] DPP2: Update the default port number for DPP-over-TCP IANA assigned the TCP port 8908 for DPP, so update the implementation to match the formal assignment. Signed-off-by: Jouni Malinen --- src/common/dpp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dpp.h b/src/common/dpp.h index 649c5ddde..2fd331b1a 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -35,7 +35,7 @@ extern int dpp_version_override; #endif /* CONFIG_TESTING_OPTIONS */ #define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */ -#define DPP_TCP_PORT 7871 +#define DPP_TCP_PORT 8908 enum dpp_public_action_frame_type { DPP_PA_AUTHENTICATION_REQ = 0, From 2d8a7cf3f551e427b940492499c4ec134b586b6b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 21 Oct 2020 00:31:01 +0300 Subject: [PATCH 1024/1105] tests: Update dpp_controller_rx_errors to use the assigned TCP port Signed-off-by: Jouni Malinen --- tests/hwsim/test_dpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 2d343d36e..ff0381430 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5001,7 +5001,7 @@ def run_dpp_controller_rx_errors(dev, apdev): if "OK" not in dev[0].request("DPP_CONTROLLER_START"): raise Exception("Could not start Controller") - addr = ("127.0.0.1", 7871) + addr = ("127.0.0.1", 8908) tests = [b"abc", b"abcd", From 45ae6ae8e1ba13123f901db41d3deb0305ab0016 Mon Sep 17 00:00:00 2001 From: Arun Kumar Khandavalli Date: Thu, 22 Oct 2020 21:24:41 +0530 Subject: [PATCH 1025/1105] Add additional vendor specific hang reason codes Add additional hang reason codes in enum qca_wlan_vendor_hang_reason to address potential internal failure cases. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index eb6a2c149..de4c8baa8 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -6222,6 +6222,12 @@ enum qca_wlan_vendor_hang_reason { * the FW on a specific VDEV. */ QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT = 22, + /* WMI sequence mismatch between WMI command and Tx completion */ + QCA_WLAN_HANG_WMI_BUF_SEQUENCE_MISMATCH = 23, + /* Write to Device HAL register failed */ + QCA_WLAN_HANG_REG_WRITE_FAILURE = 24, + /* No credit left to send the wow_wakeup_from_sleep to firmware */ + QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25, }; /** From 8f0ed71ffeae9b8c829055603c6bfe37982814bd Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Thu, 15 Oct 2020 19:08:45 +0530 Subject: [PATCH 1026/1105] Vendor specific feature capability for Adaptive 11r Add feature capability indication for Adaptive 11r for the drivers to advertize support for this. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index de4c8baa8..89736b16e 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -1445,6 +1445,15 @@ enum qca_wlan_vendor_acs_hw_mode { * %QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL and * %QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW attributes from * userspace. + * @QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R: Device supports Adaptive 11r. + * With Adaptive 11r feature, access points advertise the vendor + * specific IEs and MDE but do not include FT AKM in the RSNE. + * The Adaptive 11r supported stations are expected to identify + * such vendor specific IEs and connect to the AP in FT mode though + * the profile is configured in non-FT mode. + * The driver-based SME cases also need to have this support for + * Adaptive 11r to handle the connection and roaming scenarios. + * This flag indicates the support for the same to the user space. * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits */ enum qca_wlan_vendor_features { @@ -1460,6 +1469,7 @@ enum qca_wlan_vendor_features { QCA_WLAN_VENDOR_FEATURE_11AX = 9, QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT = 10, QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG = 11, + QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R = 12, NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */ }; From 9c39c1a6d3c246925e02571dfdf01d0a78082dd2 Mon Sep 17 00:00:00 2001 From: Sreeramya Soratkal Date: Thu, 24 Sep 2020 16:08:27 +0530 Subject: [PATCH 1027/1105] P2P: Include p2p_add_cli_chan parameter while cloning the configuration The dynamically created P2P group interface did not consider the channels that can be used by the P2P client during the P2P group formation. Copy the p2p_add_cli_chan parameter while cloning the configuration to the P2P group interface. This allows the dynamically created group interface case to form the group in the specific client-only channels when the device is a P2P client in the group. Signed-off-by: Sreeramya Soratkal --- wpa_supplicant/p2p_supplicant.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 4c083f865..330687b81 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2161,6 +2161,7 @@ do { \ d->go_internet = s->go_internet; d->go_venue_group = s->go_venue_group; d->go_venue_type = s->go_venue_type; + d->p2p_add_cli_chan = s->p2p_add_cli_chan; } From 106d67a93c2d3da2a8e25984ae7b0e17c85783cd Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 26 Oct 2020 22:34:07 +0200 Subject: [PATCH 1028/1105] nl80211: Filter out unsupported bands If the driver indicates capability for a band that hostapd/wpa_supplicant does not support, the struct hostapd_hw_modes array of bands got an empty entry for that with NUM_HOSTAPD_MODES as the mode. This resulted in various issues, e.g., with fst_hw_mode_to_band() hitting a WPA_ASSERT(0). Fix this by filtering out unsupported bands from the internal data structures. Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211_capa.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 625fe5d0b..227f665c7 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1963,6 +1963,22 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, modes[m].mode = HOSTAPD_MODE_IEEE80211A; } + /* Remove unsupported bands */ + m = 0; + while (m < *num_modes) { + if (modes[m].mode == NUM_HOSTAPD_MODES) { + wpa_printf(MSG_DEBUG, + "nl80211: Remove unsupported mode"); + os_free(modes[m].channels); + os_free(modes[m].rates); + os_memmove(&modes[m], &modes[m + 1], + sizeof(struct hostapd_hw_modes)); + (*num_modes)--; + continue; + } + m++; + } + /* If only 802.11g mode is included, use it to construct matching * 802.11b mode data. */ From c575904761b374e3738120580617c4a83a73e9f7 Mon Sep 17 00:00:00 2001 From: Sreeramya Soratkal Date: Mon, 12 Oct 2020 16:12:14 +0530 Subject: [PATCH 1029/1105] P2P: Consider BSS entry pending for P2P joining as a known BSS Consider the BSS entry that is pending for the P2P group join operation also as a known network along with the existing configured networks. This prevents removal of the BSS entry that is still in the process of P2P join operation from the BSS table when the number of entries exceed bss_max_count. Signed-off-by: Sreeramya Soratkal --- wpa_supplicant/bss.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 127f43e5e..17c5a4e98 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -351,10 +351,32 @@ static int wpa_bss_is_wps_candidate(struct wpa_supplicant *wpa_s, } +static bool is_p2p_pending_bss(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) +{ +#ifdef CONFIG_P2P + u8 addr[ETH_ALEN]; + + if (os_memcmp(bss->bssid, wpa_s->pending_join_iface_addr, + ETH_ALEN) == 0) + return true; + if (!is_zero_ether_addr(wpa_s->pending_join_dev_addr) && + p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, + addr) == 0 && + os_memcmp(addr, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0) + return true; +#endif /* CONFIG_P2P */ + return false; +} + + static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { struct wpa_ssid *ssid; + if (is_p2p_pending_bss(wpa_s, bss)) + return 1; + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { if (ssid->ssid == NULL || ssid->ssid_len == 0) continue; From 02289ab537e94d47f01156b672c697ce78cdbab0 Mon Sep 17 00:00:00 2001 From: Disha Das Date: Tue, 27 Oct 2020 13:09:31 +0530 Subject: [PATCH 1030/1105] DPP2: Explicitly check EC_KEY before dereferencing it In theory, the EVP_PKEY_get0_EC_KEY() could fail, so verify that it succeeds before using the pointer to get the group. Fixes: 65e94351dc4a ("DPP2: Reconfig Authentication Request processing and Response generation") Signed-off-by: Disha Das --- src/common/dpp_crypto.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 7c4801531..37c2b692b 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2305,13 +2305,15 @@ int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, /* M = { cR + pR } * CI */ cR = EVP_PKEY_get0_EC_KEY(own_key); pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); + if (!pR) + goto fail; group = EC_KEY_get0_group(pR); bnctx = BN_CTX_new(); sum = BN_new(); mx = BN_new(); q = BN_new(); m = EC_POINT_new(group); - if (!cR || !pR || !bnctx || !sum || !mx || !q || !m) + if (!cR || !bnctx || !sum || !mx || !q || !m) goto fail; cR_bn = EC_KEY_get0_private_key(cR); pR_bn = EC_KEY_get0_private_key(pR); From 0577e8e679c3c74daaf927713c201998a85d8c2b Mon Sep 17 00:00:00 2001 From: Pooventhiran G Date: Tue, 27 Oct 2020 11:54:21 +0530 Subject: [PATCH 1031/1105] nl80211: Check for proper nlmsg allocation in send_and_recv_msgs_owner() When nlmsg allocation fails, nl80211_drv_msg() returns NULL and the call to send_and_recv_msgs_owner() from nl80211_leave_ibss() could have ended up dereferencing a NULL pointer. Fix this by make send_and_recv_msgs_owner() more consistent with other send_and_recv*() cases that check msg == NULL internally. Fixes: 12ea7dee311b ("nl80211: Use nl80211 control port for receiving EAPOL frames") Signed-off-by: Pooventhiran G --- src/drivers/driver_nl80211.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 2ee34d11d..ffa0c467e 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -502,6 +502,9 @@ static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv, void *), void *ack_data) { + if (!msg) + return -ENOMEM; + /* Control port over nl80211 needs the flags and attributes below. * * The Linux kernel has initial checks for them (in nl80211.c) like: From 5e779873ed01d3c8ca974e1b0c5994ebe1ee61fd Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Fri, 16 Oct 2020 12:47:28 -0700 Subject: [PATCH 1032/1105] EAP-SIM peer: Send AT_IDENTITY first For EAP-SIM connections, reorder the order of the attributes in EAP-Response/SIM/Start message: Send AT_IDENTITY first, then AT_NONCE and AT_VERSION instead of AT_IDENTITY last. Even though there is no order requirements in the RFC, some implementations expect the order of the attributes to be exactly as described in the RFC figures. Peer Authenticator | | | +------------------------------+ | | Server does not have a | | | Subscriber identity available| | | When starting EAP-SIM | | +------------------------------+ | | | EAP-Request/SIM/Start | | (AT_ANY_ID_REQ, AT_VERSION_LIST) | |<------------------------------------------------| | | | | | EAP-Response/SIM/Start | | (AT_IDENTITY, AT_NONCE_MT, | | AT_SELECTED_VERSION) | |------------------------------------------------>| | | Signed-off-by: Hai Shalom --- src/eap_peer/eap_sim.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c index eaa1ad715..09866277d 100644 --- a/src/eap_peer/eap_sim.c +++ b/src/eap_peer/eap_sim.c @@ -520,6 +520,12 @@ static struct wpabuf * eap_sim_response_start(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); + if (identity) { + wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", + identity, identity_len); + eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, + identity, identity_len); + } if (!data->reauth) { wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", data->nonce_mt, EAP_SIM_NONCE_MT_LEN); @@ -531,13 +537,6 @@ static struct wpabuf * eap_sim_response_start(struct eap_sm *sm, data->selected_version, NULL, 0); } - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", - identity, identity_len); - eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, - identity, identity_len); - } - resp = eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0); if (resp) eap_sim_state(data, START_DONE); From 66bed14b22242bf4794b54b09ab342d4e1188f41 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 16 Sep 2020 13:58:22 +0530 Subject: [PATCH 1033/1105] 6 GHz: Fix opclasses mapping in ieee80211_freq_to_channel_ext() Previously only primary channel number used to calculate 6GHz operating class in ieee80211_freq_to_channel_ext() and it is always giving 131 operating class. Fix this by mapping operating class using chanwidth and sec_channel also. This is needed to avoid OCV failures on the 6 GHz band when the channel width is larger than 20 MHz. Signed-off-by: Veerendranath Jakkam --- src/common/ieee802_11_common.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 9c536cc5f..471db43c7 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1030,15 +1030,28 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, } if (freq > 5950 && freq <= 7115) { - int bw; - u8 idx = (freq - 5950) / 5; - - bw = center_idx_to_bw_6ghz(idx); - if (bw < 0) + if ((freq - 5950) % 5) return NUM_HOSTAPD_MODES; - *channel = idx; - *op_class = 131 + bw; + switch (chanwidth) { + case CHANWIDTH_80MHZ: + *op_class = 133; + break; + case CHANWIDTH_160MHZ: + *op_class = 134; + break; + case CHANWIDTH_80P80MHZ: + *op_class = 135; + break; + default: + if (sec_channel) + *op_class = 132; + else + *op_class = 131; + break; + } + + *channel = (freq - 5950) / 5; return HOSTAPD_MODE_IEEE80211A; } From 79e3f08d3c2749fb58bb07910306495331ee0198 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Wed, 16 Sep 2020 13:51:47 +0530 Subject: [PATCH 1034/1105] 6 GHz: Add support for missing 6 GHz operating classes Add support for missing 6 GHz operating classes as defined in IEEE P802.11ax/D7.0. This is needed to avoid OCV failures on the 6 GHz band when the channel width is larger than 20 MHz. Signed-off-by: Veerendranath Jakkam --- src/common/ieee802_11_common.c | 6 +++ src/common/ieee802_11_common.h | 4 +- src/common/ocv.c | 2 + wpa_supplicant/op_classes.c | 83 ++++++++++++++++++++++++++++++---- wpa_supplicant/rrm.c | 29 ++++++++---- 5 files changed, 102 insertions(+), 22 deletions(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 471db43c7..9b3782e26 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1886,6 +1886,11 @@ const struct oper_class_map global_op_class[] = { { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP }, /* * IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes. @@ -2199,6 +2204,7 @@ int oper_class_bw_to_int(const struct oper_class_map *map) switch (map->bw) { case BW20: return 20; + case BW40: case BW40PLUS: case BW40MINUS: return 40; diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 0ddba0692..0ae0fa4d1 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -232,8 +232,8 @@ struct oper_class_map { u8 min_chan; u8 max_chan; u8 inc; - enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80, BW4320, - BW6480, BW8640} bw; + enum { BW20, BW40PLUS, BW40MINUS, BW40, BW80, BW2160, BW160, BW80P80, + BW4320, BW6480, BW8640} bw; enum { P2P_SUPP, NO_P2P_SUPP } p2p; }; diff --git a/src/common/ocv.c b/src/common/ocv.c index 4bc2749a7..c9dc14fa6 100644 --- a/src/common/ocv.c +++ b/src/common/ocv.c @@ -45,6 +45,8 @@ int ocv_derive_all_parameters(struct oci_info *oci) oci->sec_channel = 1; else if (op_class_map->bw == BW40MINUS) oci->sec_channel = -1; + else if (op_class_map->bw == BW40) + oci->sec_channel = (((oci->channel - 1) / 4) % 2) ? -1 : 1; return 0; } diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c index 91e15e799..461ae5458 100644 --- a/wpa_supplicant/op_classes.c +++ b/wpa_supplicant/op_classes.c @@ -47,15 +47,15 @@ static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, } -static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel) +static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel, + const u8 *center_channels, size_t num_chan) { - u8 center_channels[] = { 42, 58, 106, 122, 138, 155 }; size_t i; if (mode->mode != HOSTAPD_MODE_IEEE80211A) return 0; - for (i = 0; i < ARRAY_SIZE(center_channels); i++) { + for (i = 0; i < num_chan; i++) { /* * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48), * so the center channel is 6 channels away from the start/end. @@ -75,8 +75,22 @@ static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, u8 center_chan; unsigned int i; unsigned int no_ir = 0; + const u8 *center_channels; + size_t num_chan; + const u8 center_channels_5ghz[] = { 42, 58, 106, 122, 138, 155 }; + const u8 center_channels_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, + 135, 151, 167, 183, 199, 215 }; - center_chan = get_center_80mhz(mode, channel); + if (is_6ghz_op_class(op_class)) { + center_channels = center_channels_6ghz; + num_chan = ARRAY_SIZE(center_channels_6ghz); + } else { + center_channels = center_channels_5ghz; + num_chan = ARRAY_SIZE(center_channels_5ghz); + } + + center_chan = get_center_80mhz(mode, channel, center_channels, + num_chan); if (!center_chan) return NOT_ALLOWED; @@ -106,15 +120,15 @@ static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, } -static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel) +static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel, + const u8 *center_channels, size_t num_chan) { - u8 center_channels[] = { 50, 114 }; unsigned int i; if (mode->mode != HOSTAPD_MODE_IEEE80211A) return 0; - for (i = 0; i < ARRAY_SIZE(center_channels); i++) { + for (i = 0; i < num_chan; i++) { /* * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64), * so the center channel is 14 channels away from the start/end. @@ -134,8 +148,21 @@ static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode, u8 center_chan; unsigned int i; unsigned int no_ir = 0; + const u8 *center_channels; + size_t num_chan; + const u8 center_channels_5ghz[] = { 50, 114 }; + const u8 center_channels_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 }; - center_chan = get_center_160mhz(mode, channel); + if (is_6ghz_op_class(op_class)) { + center_channels = center_channels_6ghz; + num_chan = ARRAY_SIZE(center_channels_6ghz); + } else { + center_channels = center_channels_5ghz; + num_chan = ARRAY_SIZE(center_channels_5ghz); + } + + center_chan = get_center_160mhz(mode, channel, center_channels, + num_chan); if (!center_chan) return NOT_ALLOWED; @@ -176,11 +203,12 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class, enum chan_allowed res, res2; res2 = res = allow_channel(mode, op_class, channel, &flag); - if (bw == BW40MINUS) { + if (bw == BW40MINUS || (bw == BW40 && (((channel - 1) / 4) % 2))) { if (!(flag & HOSTAPD_CHAN_HT40MINUS)) return NOT_ALLOWED; res2 = allow_channel(mode, op_class, channel - 4, NULL); - } else if (bw == BW40PLUS) { + } else if (bw == BW40PLUS || + (bw == BW40 && !(((channel - 1) / 4) % 2))) { if (!(flag & HOSTAPD_CHAN_HT40PLUS)) return NOT_ALLOWED; res2 = allow_channel(mode, op_class, channel + 4, NULL); @@ -343,6 +371,41 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s, return 0; } + if (op_class->op_class == 135) { + /* Need at least two 80 MHz segments which do not fall under the + * same 160 MHz segment to support 80+80 in 6 GHz. + */ + int first_seg = 0; + int curr_seg = 0; + + for (chan = op_class->min_chan; chan <= op_class->max_chan; + chan += op_class->inc) { + curr_seg++; + if (verify_channel(mode, op_class->op_class, chan, + op_class->bw) != NOT_ALLOWED) { + if (!first_seg) { + first_seg = curr_seg; + continue; + } + + /* Supported if at least two non-consecutive 80 + * MHz segments allowed. + */ + if ((curr_seg - first_seg) > 1) + return 1; + + /* Supported even if the 80 MHz segments are + * consecutive when they do not fall under the + * same 160 MHz segment. + */ + if ((first_seg % 2) == 0) + return 1; + } + } + + return 0; + } + found = 0; for (chan = op_class->min_chan; chan <= op_class->max_chan; chan += op_class->inc) { diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c index afc117275..f08726636 100644 --- a/wpa_supplicant/rrm.c +++ b/wpa_supplicant/rrm.c @@ -556,23 +556,32 @@ static int * wpas_add_channels(const struct oper_class_map *op, static int * wpas_op_class_freqs(const struct oper_class_map *op, struct hostapd_hw_modes *mode, int active) { - u8 channels_80mhz[] = { 42, 58, 106, 122, 138, 155 }; - u8 channels_160mhz[] = { 50, 114 }; + u8 channels_80mhz_5ghz[] = { 42, 58, 106, 122, 138, 155 }; + u8 channels_160mhz_5ghz[] = { 50, 114 }; + u8 channels_80mhz_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, 135, 151, + 167, 183, 199, 215 }; + u8 channels_160mhz_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 }; + const u8 *channels = NULL; + size_t num_chan = 0; + int is_6ghz = is_6ghz_op_class(op->op_class); /* * When adding all channels in the operating class, 80 + 80 MHz * operating classes are like 80 MHz channels because we add all valid * channels anyway. */ - if (op->bw == BW80 || op->bw == BW80P80) - return wpas_add_channels(op, mode, active, channels_80mhz, - ARRAY_SIZE(channels_80mhz)); + if (op->bw == BW80 || op->bw == BW80P80) { + channels = is_6ghz ? channels_80mhz_6ghz : channels_80mhz_5ghz; + num_chan = is_6ghz ? ARRAY_SIZE(channels_80mhz_6ghz) : + ARRAY_SIZE(channels_80mhz_5ghz); + } else if (op->bw == BW160) { + channels = is_6ghz ? channels_160mhz_6ghz : + channels_160mhz_5ghz; + num_chan = is_6ghz ? ARRAY_SIZE(channels_160mhz_6ghz) : + ARRAY_SIZE(channels_160mhz_5ghz); + } - if (op->bw == BW160) - return wpas_add_channels(op, mode, active, channels_160mhz, - ARRAY_SIZE(channels_160mhz)); - - return wpas_add_channels(op, mode, active, NULL, 0); + return wpas_add_channels(op, mode, active, channels, num_chan); } From 589bf1f7a962e006153125ba9bc2a2a7f21a0db6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Nov 2020 16:31:02 +0200 Subject: [PATCH 1035/1105] DPP2: Fix ppkey parsing DPP_CONFIGURATOR_ADD processing of the new ppkey parameter had a copy-paste error in determining the correct length of this parameter. Fix that by referencing the correct pointer. Fixes: 9c1fbff07404 ("DPP2: Generate a privacy protection key for Configurator") Signed-off-by: Jouni Malinen --- src/common/dpp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/dpp.c b/src/common/dpp.c index 0bda85fe7..3c8c7682d 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -4190,7 +4190,7 @@ int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) } if (ppkey) { - pp_key_len = os_strlen(key) / 2; + pp_key_len = os_strlen(ppkey) / 2; pp_key = os_malloc(pp_key_len); if (!pp_key || hexstr2bin(ppkey, pp_key, pp_key_len) < 0) From f724dd1bfd60eff27a395a00bae7ae32429856d6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Nov 2020 16:36:14 +0200 Subject: [PATCH 1036/1105] Remove unused variable update Commit e8b85c078e73 ("iface match: Unspecified matched interfaces should not log driver fails") removed the only use of the added interface wpa_s pointer, but left that pointer setting in place. Remove it to keep static analyzers happy. Signed-off-by: Jouni Malinen --- wpa_supplicant/wpa_supplicant.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 01ba032f4..fba6d0eaf 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -6789,7 +6789,7 @@ static int wpa_supplicant_match_existing(struct wpa_global *global) continue; iface = wpa_supplicant_match_iface(global, ifi->if_name); if (iface) { - wpa_s = wpa_supplicant_add_iface(global, iface, NULL); + wpa_supplicant_add_iface(global, iface, NULL); os_free(iface); } } From 3d490296bcdb6221e0e00b1c3ca3ca2f3ff444bf Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Nov 2020 16:52:01 +0200 Subject: [PATCH 1037/1105] DPP2: Fix error path handling in enterprise provisioning The allocated memory pointed by the pem pointer was freed on an error path without clearing the pointer to NULL before returning it from the function. This could have resulted in use of freed memory in an error case. Fix this by clearing the pointer so that the function returns NULL properly in the case of this error. Fixes: ace3723d9879 ("DPP2: Enterprise provisioning (Enrollee)") Signed-off-by: Jouni Malinen --- src/common/dpp_crypto.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 37c2b692b..c75fc7871 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -2868,6 +2868,7 @@ struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7) res = BIO_read(out, wpabuf_put(pem, 0), rlen); if (res <= 0) { wpabuf_free(pem); + pem = NULL; goto fail; } wpabuf_put(pem, res); From a86078c876130cf0cca8ef4275f8898a854877b3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Nov 2020 17:26:04 +0200 Subject: [PATCH 1038/1105] TDLS: Fix error path handling for TPK M1 send failures Local allocation error or failure to get a random number could have resulted in the peer entry getting freed and couple of the error path cases in callers could have tried to reference or delete the peer after that. Fix this by tracking the errors where the peer is freed. Signed-off-by: Jouni Malinen --- src/rsn_supp/tdls.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index eff8cd829..1fb28c5c5 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -1155,7 +1155,7 @@ skip_rsnie: rbuf = os_zalloc(buf_len + 1); if (rbuf == NULL) { wpa_tdls_peer_free(sm, peer); - return -1; + return -2; } pos = rbuf; @@ -1174,7 +1174,7 @@ skip_rsnie: "TDLS: Failed to get random data for initiator Nonce"); os_free(rbuf); wpa_tdls_peer_free(sm, peer); - return -1; + return -2; } peer->tk_set = 0; /* A new nonce results in a new TK */ wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake", @@ -1926,7 +1926,8 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, peer->initiator = 1; wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0); - wpa_tdls_send_tpk_m1(sm, peer); + if (wpa_tdls_send_tpk_m1(sm, peer) == -2) + goto error; } if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && @@ -2654,6 +2655,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) { struct wpa_tdls_peer *peer; int tdls_prohibited = sm->tdls_prohibited; + int res; if (sm->tdls_disabled || !sm->tdls_supported) return -1; @@ -2693,8 +2695,10 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) peer->tpk_in_progress = 1; - if (wpa_tdls_send_tpk_m1(sm, peer) < 0) { - wpa_tdls_disable_peer_link(sm, peer); + res = wpa_tdls_send_tpk_m1(sm, peer); + if (res < 0) { + if (res != -2) + wpa_tdls_disable_peer_link(sm, peer); return -1; } From 3b89dbaa7d44ea810e017ae0ff300fb639304c73 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Nov 2020 17:40:18 +0200 Subject: [PATCH 1039/1105] tests: TDLS with SAE Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_tdls.py | 51 ++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/tests/hwsim/test_ap_tdls.py b/tests/hwsim/test_ap_tdls.py index ea14a08b2..a2bf6d498 100644 --- a/tests/hwsim/test_ap_tdls.py +++ b/tests/hwsim/test_ap_tdls.py @@ -26,9 +26,13 @@ def connectivity(dev, hapd): hwsim_utils.test_connectivity(dev[0], hapd) hwsim_utils.test_connectivity(dev[1], hapd) -def connect_2sta(dev, ssid, hapd): - dev[0].connect(ssid, psk="12345678", scan_freq="2412") - dev[1].connect(ssid, psk="12345678", scan_freq="2412") +def connect_2sta(dev, ssid, hapd, sae=False): + key_mgmt = "SAE" if sae else "WPA-PSK" + ieee80211w = "2" if sae else "1" + dev[0].connect(ssid, key_mgmt=key_mgmt, psk="12345678", + ieee80211w=ieee80211w, scan_freq="2412") + dev[1].connect(ssid, key_mgmt=key_mgmt, psk="12345678", + ieee80211w=ieee80211w, scan_freq="2412") hapd.wait_sta() hapd.wait_sta() connectivity(dev, hapd) @@ -112,7 +116,7 @@ def check_connectivity(sta0, sta1, hapd): hwsim_utils.test_connectivity(sta0, hapd) hwsim_utils.test_connectivity(sta1, hapd) -def setup_tdls(sta0, sta1, hapd, reverse=False, expect_fail=False): +def setup_tdls(sta0, sta1, hapd, reverse=False, expect_fail=False, sae=False): logger.info("Setup TDLS") check_connectivity(sta0, sta1, hapd) bssid = hapd.own_addr() @@ -124,18 +128,20 @@ def setup_tdls(sta0, sta1, hapd, reverse=False, expect_fail=False): sta0.tdls_setup(addr1) time.sleep(1) if expect_fail: - tdls_check_ap(sta0, sta1, bssid, addr0, addr1) + if not sae: + tdls_check_ap(sta0, sta1, bssid, addr0, addr1) return if reverse: addr1 = sta0.p2p_interface_addr() addr0 = sta1.p2p_interface_addr() - conf = wt.get_tdls_counter("setup_conf_ok", bssid, addr0, addr1) - if conf == 0: - raise Exception("No TDLS Setup Confirm (success) seen") - tdls_check_dl(sta0, sta1, bssid, addr0, addr1) + if not sae: + conf = wt.get_tdls_counter("setup_conf_ok", bssid, addr0, addr1) + if conf == 0: + raise Exception("No TDLS Setup Confirm (success) seen") + tdls_check_dl(sta0, sta1, bssid, addr0, addr1) check_connectivity(sta0, sta1, hapd) -def teardown_tdls(sta0, sta1, hapd, responder=False, wildcard=False): +def teardown_tdls(sta0, sta1, hapd, responder=False, wildcard=False, sae=False): logger.info("Teardown TDLS") check_connectivity(sta0, sta1, hapd) bssid = hapd.own_addr() @@ -148,11 +154,12 @@ def teardown_tdls(sta0, sta1, hapd, responder=False, wildcard=False): else: sta0.tdls_teardown(addr1) time.sleep(1) - wt = Wlantest() - teardown = wt.get_tdls_counter("teardown", bssid, addr0, addr1) - if teardown == 0: - raise Exception("No TDLS Setup Teardown seen") - tdls_check_ap(sta0, sta1, bssid, addr0, addr1) + if not sae: + wt = Wlantest() + teardown = wt.get_tdls_counter("teardown", bssid, addr0, addr1) + if teardown == 0: + raise Exception("No TDLS Setup Teardown seen") + tdls_check_ap(sta0, sta1, bssid, addr0, addr1) check_connectivity(sta0, sta1, hapd) def check_tdls_link(sta0, sta1, connected=True): @@ -627,3 +634,17 @@ def _test_ap_open_tdls_external_control(dev, apdev): time.sleep(0.1) if connected: raise Exception("TDLS teardown did not complete") + +def test_ap_sae_tdls(dev, apdev): + """SAE AP and two stations using TDLS""" + check_sae_capab(dev[0]) + check_sae_capab(dev[1]) + params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + hapd = hostapd.add_ap(apdev[0], params) + wlantest_setup(hapd) + connect_2sta(dev, "test-wpa2-psk", hapd, sae=True) + setup_tdls(dev[0], dev[1], hapd, sae=True) + teardown_tdls(dev[0], dev[1], hapd, sae=True) + setup_tdls(dev[1], dev[0], hapd, sae=True) From c643c392874a7e41dc447cd29afe14a2934e2289 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Nov 2020 18:38:41 +0200 Subject: [PATCH 1040/1105] nl80211: Fix filtering of unsupported bands/modes The loop for removing unsupported bands was assuming there is always exactly one band/mode following the removed band. That was not at all correct, so fix this by dynamically determining how many (if any) bands need to be moved. Fixes: 106d67a93c2d ("nl80211: Filter out unsupported bands") Signed-off-by: Jouni Malinen --- src/drivers/driver_nl80211_capa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 227f665c7..287b8aa30 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1971,8 +1971,10 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, "nl80211: Remove unsupported mode"); os_free(modes[m].channels); os_free(modes[m].rates); - os_memmove(&modes[m], &modes[m + 1], - sizeof(struct hostapd_hw_modes)); + if (m + 1 < *num_modes) + os_memmove(&modes[m], &modes[m + 1], + sizeof(struct hostapd_hw_modes) * + (*num_modes - (m + 1))); (*num_modes)--; continue; } From a9fed5f5b5503f286c2ed34e5fc637776587bcdb Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 2 Nov 2020 18:46:35 +0200 Subject: [PATCH 1041/1105] Avoid undefined behavior with memcpy PMK/PSK update When SAE is used, the local pointer pmk may point to sm->PMK. Skip the memcpy operation in such a case since it is not really needed and use of overlapping memory buffers is undefined behavior for memcpy(). Signed-off-by: Jouni Malinen --- src/ap/wpa_auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 9d74bfcd7..82a97468d 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3145,7 +3145,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) sm->pending_1_of_4_timeout = 0; eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && sm->PMK != pmk) { /* PSK may have changed from the previous choice, so update * state machine data based on whatever PSK was selected here. */ From 05962099c3b88831a1815df8e542b38474b109be Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Nov 2020 19:45:36 +0200 Subject: [PATCH 1042/1105] TDLS: Fix error path for TPK M1 send failure in testing functionality The previous fix did not actually address this testing functionality case correctly. Clear the peer pointer to avoid double freeing. Fixes: a86078c87613 ("TDLS: Fix error path handling for TPK M1 send failures") Signed-off-by: Jouni Malinen --- src/rsn_supp/tdls.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 1fb28c5c5..7c4ef191c 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -1926,8 +1926,10 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, peer->initiator = 1; wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0); - if (wpa_tdls_send_tpk_m1(sm, peer) == -2) + if (wpa_tdls_send_tpk_m1(sm, peer) == -2) { + peer = NULL; goto error; + } } if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && From ec0d99c00e92505a1dff1c26516b8cb1cd389d87 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Nov 2020 19:56:39 +0200 Subject: [PATCH 1043/1105] HS 2.0: Clarify OSU Friendly Name length validation This extends the changes in commit 0570a3ea7d87 ("HS 2.0: Clarify OSU Provider list length validation") to cover the length field for the OSU Friendly Name value to try to get this easier for static analyzers to understand. Signed-off-by: Jouni Malinen --- wpa_supplicant/hs20_supplicant.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index 3bf777e6a..de350bbb4 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -901,14 +901,25 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, /* OSU Friendly Name Duples */ while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) { struct osu_lang_string *f; - if (1 + pos2[0] > pos - pos2 || pos2[0] < 3) { + u8 slen; + + slen = pos2[0]; + if (1 + slen > pos - pos2) { wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name"); break; } + if (slen < 3) { + wpa_printf(MSG_DEBUG, + "Invalid OSU Friendly Name (no room for language)"); + break; + } f = &prov->friendly_name[prov->friendly_name_count++]; - os_memcpy(f->lang, pos2 + 1, 3); - os_memcpy(f->text, pos2 + 1 + 3, pos2[0] - 3); - pos2 += 1 + pos2[0]; + pos2++; + os_memcpy(f->lang, pos2, 3); + pos2 += 3; + slen -= 3; + os_memcpy(f->text, pos2, slen); + pos2 += slen; } /* OSU Server URI */ From c42d41bf35cb205388adc0736e332057562f6f4b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Nov 2020 20:11:17 +0200 Subject: [PATCH 1044/1105] EAP-IKEv2: Try to make transform parser simpler to understand Use a local variable to try to make ikev2_parse_proposal() easier for static analyzers to understand. Bounds checking in the loop is really done by the ikev2_parse_transform() function, so the p->num_transforms value itself is of no importance for that part and even that was already implicitly limited in range. Signed-off-by: Jouni Malinen --- src/eap_peer/ikev2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/eap_peer/ikev2.c b/src/eap_peer/ikev2.c index 7bd97b1b9..c2e6c5df5 100644 --- a/src/eap_peer/ikev2.c +++ b/src/eap_peer/ikev2.c @@ -201,7 +201,8 @@ static int ikev2_parse_proposal(struct ikev2_proposal_data *prop, const u8 *pos, const u8 *end) { const u8 *pend, *ppos; - int proposal_len, i; + int proposal_len; + unsigned int i, num; const struct ikev2_proposal *p; if (end - pos < (int) sizeof(*p)) { @@ -269,12 +270,13 @@ static int ikev2_parse_proposal(struct ikev2_proposal_data *prop, return -1; } - if (p->num_transforms == 0) { + num = p->num_transforms; + if (num == 0 || num > 255) { wpa_printf(MSG_INFO, "IKEV2: At least one transform required"); return -1; } - for (i = 0; i < (int) p->num_transforms; i++) { + for (i = 0; i < num; i++) { int tlen = ikev2_parse_transform(prop, ppos, pend); if (tlen < 0) return -1; @@ -411,7 +413,7 @@ static int ikev2_process_kei(struct ikev2_responder_data *data, wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value", data->i_dh_public); - + return 0; } From f14df9b56a68dce69da61f56a084e2321c81e301 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Nov 2020 21:08:52 +0200 Subject: [PATCH 1045/1105] tests: Prepare for control interface message change Update ap_wpa2_psk_supp_proto_too_long_gtk_in_group_msg to accept upcoming change in the parsing validation step that catches the issue. Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_psk.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index e79380e90..c4a8b9e2e 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -2313,7 +2313,8 @@ def test_ap_wpa2_psk_supp_proto_too_long_gtk_in_group_msg(dev, apdev): key_info=0x13c2) counter += 1 send_eapol(dev[0], bssid, build_eapol(msg)) - ev = dev[0].wait_event(["WPA: Unsupported CCMP Group Cipher key length 33"]) + ev = dev[0].wait_event(["WPA: Unsupported CCMP Group Cipher key length 33", + "RSN: Too long GTK in GTK KDE (len=33)"]) if ev is None: raise Exception("Too long GTK KDE not reported") dev[0].wait_disconnected(timeout=1) From ec1f4f3c815e0c99b0b7dc1180ea49c88b4a19e2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Nov 2020 20:23:48 +0200 Subject: [PATCH 1046/1105] Make GTK length validation for RSN Group 1/2 easier to analyze This extends the changes in commit c397eff82894 ("Make GTK length validation easier to analyze") to cover the RSN case as well as the WPA. Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index f3d324a67..e07527ba5 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -1836,6 +1836,7 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, { int maxkeylen; struct wpa_eapol_ie_parse ie; + u16 gtk_len; wpa_hexdump_key(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); @@ -1851,7 +1852,20 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, "WPA: No GTK IE in Group Key msg 1/2"); return -1; } - maxkeylen = gd->gtk_len = ie.gtk_len - 2; + gtk_len = ie.gtk_len; + if (gtk_len < 2) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Invalid GTK KDE length (%u) in Group Key msg 1/2", + gtk_len); + return -1; + } + gtk_len -= 2; + if (gtk_len > sizeof(gd->gtk)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Too long GTK in GTK KDE (len=%u)", gtk_len); + return -1; + } + maxkeylen = gd->gtk_len = gtk_len; #ifdef CONFIG_OCV if (wpa_sm_ocv_enabled(sm)) { @@ -1875,22 +1889,16 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, #endif /* CONFIG_OCV */ if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, - gd->gtk_len, maxkeylen, + gtk_len, maxkeylen, &gd->key_rsc_len, &gd->alg)) return -1; wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in group key handshake", - ie.gtk, ie.gtk_len); + ie.gtk, 2 + gtk_len); gd->keyidx = ie.gtk[0] & 0x3; gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, !!(ie.gtk[0] & BIT(2))); - if (ie.gtk_len - 2 > sizeof(gd->gtk)) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: Too long GTK in GTK IE (len=%lu)", - (unsigned long) ie.gtk_len - 2); - return -1; - } - os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); + os_memcpy(gd->gtk, ie.gtk + 2, gtk_len); if (ieee80211w_set_keys(sm, &ie) < 0) wpa_msg(sm->ctx->msg_ctx, MSG_INFO, From 56a1df71e54dbc9d4ff807bbf89e13164caa9583 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 3 Nov 2020 20:36:15 +0200 Subject: [PATCH 1047/1105] BSS: Convert wpa_bss_get_vendor_ie() to use for_each_element_id() Use the common IE parsing routine in hope of trying to make the length checks easier for static analyzers. Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 17c5a4e98..97aa146c8 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -1154,18 +1154,15 @@ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie) */ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; - pos = (const u8 *) (bss + 1); - end = pos + bss->ie_len; + ies = (const u8 *) (bss + 1); - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, bss->ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; From aa06444f2c3704e0c531b65cc45ee9496a4d039e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 4 Nov 2020 19:39:08 +0200 Subject: [PATCH 1048/1105] dbus: Check eloop registration failure in add_watch handler Report failures at lower layer to the upper layer D-Bus handling of socket registration to allow failures to be addressed more cleanly. Signed-off-by: Jouni Malinen --- wpa_supplicant/dbus/dbus_common.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/wpa_supplicant/dbus/dbus_common.c b/wpa_supplicant/dbus/dbus_common.c index efa6c7b20..a727217fd 100644 --- a/wpa_supplicant/dbus/dbus_common.c +++ b/wpa_supplicant/dbus/dbus_common.c @@ -108,17 +108,18 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data) flags = dbus_watch_get_flags(watch); fd = dbus_watch_get_unix_fd(watch); - eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception, - priv, watch); + if (eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, + process_watch_exception, priv, watch) < 0) + return FALSE; - if (flags & DBUS_WATCH_READABLE) { - eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read, - priv, watch); - } - if (flags & DBUS_WATCH_WRITABLE) { - eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write, - priv, watch); - } + if ((flags & DBUS_WATCH_READABLE) && + eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read, + priv, watch) < 0) + return FALSE; + if ((flags & DBUS_WATCH_WRITABLE) && + eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write, + priv, watch) < 0) + return FALSE; dbus_watch_set_data(watch, priv, NULL); From f4de21a77afc113fe959133ca4e873235a754025 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 4 Nov 2020 19:50:34 +0200 Subject: [PATCH 1049/1105] BSS/scan: More conversions to for_each_element_id() Use the common IE parsing routine in hope of trying to make the length checks easier for static analyzers. In addition, try to make the *_vendor_ie_multi() cases easier to analyze as well even though they cannot use for_each_element_id(). Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 35 ++++++++++++++++------------- wpa_supplicant/scan.c | 52 +++++++++++++++++++++---------------------- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 97aa146c8..7b6ed773a 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -1184,22 +1184,20 @@ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; if (bss->beacon_ie_len == 0) return NULL; - pos = (const u8 *) (bss + 1); - pos += bss->ie_len; - end = pos + bss->beacon_ie_len; + ies = (const u8 *) (bss + 1); + ies += bss->ie_len; - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, + bss->beacon_ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1230,12 +1228,17 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, end = pos + bss->ie_len; while (end - pos > 1) { - if (2 + pos[1] > end - pos) + u8 ie, len; + + ie = pos[0]; + len = pos[1]; + if (len > end - pos - 2) break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); - pos += 2 + pos[1]; + pos += 2; + if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 && + vendor_type == WPA_GET_BE32(pos)) + wpabuf_put_data(buf, pos + 4, len - 4); + pos += len; } if (wpabuf_len(buf) == 0) { diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index b9e4162c8..78371d3ad 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1869,18 +1869,15 @@ const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; + ies = (const u8 *) (res + 1); - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, res->ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1902,22 +1899,20 @@ const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; if (res->beacon_ie_len == 0) return NULL; - pos = (const u8 *) (res + 1); - pos += res->ie_len; - end = pos + res->beacon_ie_len; + ies = (const u8 *) (res + 1); + ies += res->ie_len; - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, + res->beacon_ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1948,12 +1943,17 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, end = pos + res->ie_len; while (end - pos > 1) { - if (2 + pos[1] > end - pos) + u8 ie, len; + + ie = pos[0]; + len = pos[1]; + if (len > end - pos - 2) break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); - pos += 2 + pos[1]; + pos += 2; + if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 && + vendor_type == WPA_GET_BE32(pos)) + wpabuf_put_data(buf, pos + 4, len - 4); + pos += len; } if (wpabuf_len(buf) == 0) { From cd3aa54a3750ce1124020fa6b0b407ff066d2a43 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 28 Oct 2020 14:18:01 -0700 Subject: [PATCH 1050/1105] Add test configuration attr to enable/disable full bandwidth UL MU-MIMO Define a QCA vendor attribute QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO to enable/disable full bandwidth UL MU-MIMO subfield in the HE PHY capabilities information field for testing purposes. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 89736b16e..ca9c2d177 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7701,6 +7701,15 @@ enum qca_wlan_vendor_attr_wifi_test_config { */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX = 44, + /* 8-bit unsigned value to configure the driver/firmware to enable or + * disable full bandwidth UL MU-MIMO subfield in the HE PHY capabilities + * information field. + * 0 - Disable full bandwidth UL MU-MIMO subfield + * 1 - Enable full bandwidth UL MU-MIMO subfield + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO = 45, + /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX = From c2c46862280df428aa3c037be52f562c962c4c1d Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Tue, 27 Oct 2020 23:33:59 +0530 Subject: [PATCH 1051/1105] Set NLA_F_NESTED flag with NL80211_ATTR_VENDOR_DATA conditionally The newer kernel versions enforce strict netlink attribute policy validation and will cause cfg80211 to reject vendor commands with NL80211_ATTR_VENDOR_DATA if NLA_F_NESTED attribute is not set but if the vendor command is expecting nested data within NL80211_ATTR_VENDOR_DATA attribute. Most of the earlier instances were addressed by adding NLA_F_NESTED flag in nla_nest_start(). This commit addresses the remaining instance in which NL80211_ATTR_VENDOR_DATA is populated using data set by user through the control interface. Enhance the control interface VENDOR command to indicate whether the vendor subcommand uses nested attributes within NL80211_ATTR_VENDOR_DATA attribute or not. Set NLA_F_NESTED flag for existing QCA vendor commands which use nested attributes within the NL80211_ATTR_VENDOR_DATA attributes so that the old frameworks implementations for already existing commands work without any issues. Signed-off-by: Jouni Malinen --- hostapd/ctrl_iface.c | 19 +++++++++++++++---- hostapd/hostapd_cli.c | 9 +++++---- src/ap/ap_drv_ops.h | 3 ++- src/drivers/driver.h | 17 ++++++++++++++--- src/drivers/driver_nl80211.c | 36 +++++++++++++++++++++++++++++++++--- wpa_supplicant/ctrl_iface.c | 19 +++++++++++++++---- wpa_supplicant/driver_i.h | 6 ++++-- 7 files changed, 88 insertions(+), 21 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 30fa47f2d..e2ae0ad44 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2707,13 +2707,17 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) { int ret; - char *pos; + char *pos, *temp = NULL; u8 *data = NULL; unsigned int vendor_id, subcmd; + enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED; struct wpabuf *reply; size_t data_len = 0; - /* cmd: [] */ + /** + * cmd: [] + * [nested=<0|1>] + */ vendor_id = strtoul(cmd, &pos, 16); if (!isblank((unsigned char) *pos)) return -EINVAL; @@ -2723,7 +2727,9 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, if (*pos != '\0') { if (!isblank((unsigned char) *pos++)) return -EINVAL; - data_len = os_strlen(pos); + + temp = os_strchr(pos, ' '); + data_len = temp ? (size_t) (temp - pos) : os_strlen(pos); } if (data_len) { @@ -2740,6 +2746,11 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, } } + pos = os_strstr(cmd, "nested="); + if (pos) + nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED : + NESTED_ATTR_NOT_USED; + reply = wpabuf_alloc((buflen - 1) / 2); if (!reply) { os_free(data); @@ -2747,7 +2758,7 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, } ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, - reply); + nested_attr_flag, reply); if (ret == 0) ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index ad4398175..dac00e01a 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -1227,14 +1227,15 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) char cmd[256]; int res; - if (argc < 2 || argc > 3) { + if (argc < 2 || argc > 4) { printf("Invalid vendor command\n" - "usage: []\n"); + "usage: [] [nested=<0|1>]\n"); return -1; } - res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1], - argc == 3 ? argv[2] : ""); + res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s%s%s", argv[0], + argv[1], argc >= 3 ? argv[2] : "", + argc == 4 ? " " : "", argc == 4 ? argv[3] : ""); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long VENDOR command.\n"); return -1; diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 5738c1c97..cc7ea07a2 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -350,12 +350,13 @@ static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd, static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd, int vendor_id, int subcmd, const u8 *data, size_t data_len, + enum nested_attr nested_attr_flag, struct wpabuf *buf) { if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL) return -1; return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data, - data_len, buf); + data_len, nested_attr_flag, buf); } static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index e8defaba2..0019f54f9 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2432,6 +2432,13 @@ struct external_auth { const u8 *pmkid; }; +/* enum nested_attr - Used to specify if subcommand uses nested attributes */ +enum nested_attr { + NESTED_ATTR_NOT_USED = 0, + NESTED_ATTR_USED = 1, + NESTED_ATTR_UNSPECIFIED = 2, +}; + /** * struct wpa_driver_ops - Driver interface API definition * @@ -3717,6 +3724,8 @@ struct wpa_driver_ops { * @priv: Private driver interface data * @vendor_id: Vendor id * @subcmd: Vendor command id + * @nested_attr_flag: Specifies if vendor subcommand uses nested + * attributes or not * @data: Vendor command parameters (%NULL if no parameters) * @data_len: Data length * @buf: Return buffer (%NULL to ignore reply) @@ -3724,9 +3733,10 @@ struct wpa_driver_ops { * * This function handles vendor specific commands that are passed to * the driver/device. The command is identified by vendor id and - * command id. Parameters can be passed as argument to the command - * in the data buffer. Reply (if any) will be filled in the supplied - * return buffer. + * command id. The nested_attr_flag specifies whether the subcommand + * uses nested attributes or not. Parameters can be passed + * as argument to the command in the data buffer. Reply (if any) will be + * filled in the supplied return buffer. * * The exact driver behavior is driver interface and vendor specific. As * an example, this will be converted to a vendor specific cfg80211 @@ -3734,6 +3744,7 @@ struct wpa_driver_ops { */ int (*vendor_cmd)(void *priv, unsigned int vendor_id, unsigned int subcmd, const u8 *data, size_t data_len, + enum nested_attr nested_attr_flag, struct wpabuf *buf); /** diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index ffa0c467e..477443050 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -9704,14 +9704,35 @@ static int vendor_reply_handler(struct nl_msg *msg, void *arg) } +static bool is_cmd_with_nested_attrs(unsigned int vendor_id, + unsigned int subcmd) +{ + if (vendor_id != OUI_QCA) + return true; + + switch (subcmd) { + case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: + case QCA_NL80211_VENDOR_SUBCMD_STATS_EXT: + case QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI: + case QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY: + case QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS: + case QCA_NL80211_VENDOR_SUBCMD_NAN: + return false; + default: + return true; + } +} + + static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, unsigned int subcmd, const u8 *data, - size_t data_len, struct wpabuf *buf) + size_t data_len, enum nested_attr nested_attr, + struct wpabuf *buf) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; - int ret; + int ret, nla_flag; #ifdef CONFIG_TESTING_OPTIONS if (vendor_id == 0xffffffff) { @@ -9737,11 +9758,20 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, } #endif /* CONFIG_TESTING_OPTIONS */ + if (nested_attr == NESTED_ATTR_USED) + nla_flag = NLA_F_NESTED; + else if (nested_attr == NESTED_ATTR_UNSPECIFIED && + is_cmd_with_nested_attrs(vendor_id, subcmd)) + nla_flag = NLA_F_NESTED; + else + nla_flag = 0; + if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_VENDOR)) || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, vendor_id) || nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd) || (data && - nla_put(msg, NL80211_ATTR_VENDOR_DATA, data_len, data))) + nla_put(msg, nla_flag | NL80211_ATTR_VENDOR_DATA, + data_len, data))) goto fail; ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf, diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 56a6aaaad..aeea5ddbc 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8236,13 +8236,17 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { int ret; - char *pos; + char *pos, *temp = NULL; u8 *data = NULL; unsigned int vendor_id, subcmd; + enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED; struct wpabuf *reply; size_t data_len = 0; - /* cmd: [] */ + /** + * cmd: [] + * [nested=<0|1>] + */ vendor_id = strtoul(cmd, &pos, 16); if (!isblank((unsigned char) *pos)) return -EINVAL; @@ -8252,7 +8256,9 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, if (*pos != '\0') { if (!isblank((unsigned char) *pos++)) return -EINVAL; - data_len = os_strlen(pos); + + temp = os_strchr(pos, ' '); + data_len = temp ? (size_t) (temp - pos) : os_strlen(pos); } if (data_len) { @@ -8269,6 +8275,11 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, } } + pos = os_strstr(cmd, "nested="); + if (pos) + nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED : + NESTED_ATTR_NOT_USED; + reply = wpabuf_alloc((buflen - 1) / 2); if (!reply) { os_free(data); @@ -8276,7 +8287,7 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, } ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len, - reply); + nested_attr_flag, reply); if (ret == 0) ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index ba8cc552b..3a2828982 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -719,12 +719,14 @@ static inline int wpa_drv_wowlan(struct wpa_supplicant *wpa_s, static inline int wpa_drv_vendor_cmd(struct wpa_supplicant *wpa_s, int vendor_id, int subcmd, const u8 *data, - size_t data_len, struct wpabuf *buf) + size_t data_len, + enum nested_attr nested_attr_flag, + struct wpabuf *buf) { if (!wpa_s->driver->vendor_cmd) return -1; return wpa_s->driver->vendor_cmd(wpa_s->drv_priv, vendor_id, subcmd, - data, data_len, buf); + data, data_len, nested_attr_flag, buf); } static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed, From d0e0d2283eba89201ffeb9df81e18bd08833dc65 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Nov 2020 13:14:27 +0200 Subject: [PATCH 1052/1105] Sync with mac80211-next.git include/uapi/linux/nl80211.h This brings in nl80211 definitions as of 2020-11-11. Signed-off-by: Jouni Malinen --- src/drivers/nl80211_copy.h | 330 +++++++++++++++++++++++++++++++------ 1 file changed, 282 insertions(+), 48 deletions(-) diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index dad8c8f85..3e0d4a038 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -183,18 +183,27 @@ * * By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK flag drivers * can indicate they support offloading EAPOL handshakes for WPA/WPA2 - * preshared key authentication. In %NL80211_CMD_CONNECT the preshared - * key should be specified using %NL80211_ATTR_PMK. Drivers supporting - * this offload may reject the %NL80211_CMD_CONNECT when no preshared - * key material is provided, for example when that driver does not - * support setting the temporal keys through %CMD_NEW_KEY. + * preshared key authentication in station mode. In %NL80211_CMD_CONNECT + * the preshared key should be specified using %NL80211_ATTR_PMK. Drivers + * supporting this offload may reject the %NL80211_CMD_CONNECT when no + * preshared key material is provided, for example when that driver does + * not support setting the temporal keys through %NL80211_CMD_NEW_KEY. * * Similarly @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X flag can be * set by drivers indicating offload support of the PTK/GTK EAPOL - * handshakes during 802.1X authentication. In order to use the offload - * the %NL80211_CMD_CONNECT should have %NL80211_ATTR_WANT_1X_4WAY_HS - * attribute flag. Drivers supporting this offload may reject the - * %NL80211_CMD_CONNECT when the attribute flag is not present. + * handshakes during 802.1X authentication in station mode. In order to + * use the offload the %NL80211_CMD_CONNECT should have + * %NL80211_ATTR_WANT_1X_4WAY_HS attribute flag. Drivers supporting this + * offload may reject the %NL80211_CMD_CONNECT when the attribute flag is + * not present. + * + * By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK flag drivers + * can indicate they support offloading EAPOL handshakes for WPA/WPA2 + * preshared key authentication in AP mode. In %NL80211_CMD_START_AP + * the preshared key should be specified using %NL80211_ATTR_PMK. Drivers + * supporting this offload may reject the %NL80211_CMD_START_AP when no + * preshared key material is provided, for example when that driver does + * not support setting the temporal keys through %NL80211_CMD_NEW_KEY. * * For 802.1X the PMK or PMK-R0 are set by providing %NL80211_ATTR_PMK * using %NL80211_CMD_SET_PMK. For offloaded FT support also @@ -243,9 +252,13 @@ * DOC: SAE authentication offload * * By setting @NL80211_EXT_FEATURE_SAE_OFFLOAD flag drivers can indicate they - * support offloading SAE authentication for WPA3-Personal networks. In - * %NL80211_CMD_CONNECT the password for SAE should be specified using - * %NL80211_ATTR_SAE_PASSWORD. + * support offloading SAE authentication for WPA3-Personal networks in station + * mode. Similarly @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP flag can be set by + * drivers indicating the offload support in AP mode. + * + * The password for SAE should be specified using %NL80211_ATTR_SAE_PASSWORD in + * %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP for station and AP mode + * respectively. */ /** @@ -363,7 +376,7 @@ * @NL80211_CMD_SET_STATION: Set station attributes for station identified by * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. + * interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC * or, if no MAC address given, all stations, on the interface identified * by %NL80211_ATTR_IFINDEX. %NL80211_ATTR_MGMT_SUBTYPE and @@ -383,7 +396,7 @@ * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by * %NL80211_ATTR_MAC. * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. + * interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC * or, if no MAC address given, all mesh paths, on the interface identified * by %NL80211_ATTR_IFINDEX. @@ -638,13 +651,9 @@ * authentication/association or not receiving a response from the AP. * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as * well to remain backwards compatible. - * When establishing a security association, drivers that support 4 way - * handshake offload should send %NL80211_CMD_PORT_AUTHORIZED event when - * the 4 way handshake is completed successfully. * @NL80211_CMD_ROAM: Notification indicating the card/driver roamed by itself. - * When a security association was established with the new AP (e.g. if - * the FT protocol was used for roaming or the driver completed the 4 way - * handshake), this event should be followed by an + * When a security association was established on an 802.1X network using + * fast transition, this event should be followed by an * %NL80211_CMD_PORT_AUTHORIZED event. * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify * userspace that a connection was dropped by the AP or due to other @@ -748,7 +757,8 @@ * of any other interfaces, and other interfaces will again take * precedence when they are used. * - * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. + * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface + * (no longer supported). * * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform * multicast to unicast conversion. When enabled, all multicast packets @@ -794,7 +804,7 @@ * various triggers. These triggers can be configured through this * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For * more background information, see - * http://wireless.kernel.org/en/users/Documentation/WoWLAN. + * https://wireless.wiki.kernel.org/en/users/Documentation/WoWLAN. * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification * from the driver reporting the wakeup reason. In this case, the * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason @@ -934,7 +944,7 @@ * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules. * * @NL80211_CMD_CHANNEL_SWITCH: Perform a channel switch by announcing the - * the new channel information (Channel Switch Announcement - CSA) + * new channel information (Channel Switch Announcement - CSA) * in the beacon for some time (as defined in the * %NL80211_ATTR_CH_SWITCH_COUNT parameter) and then change to the * new channel. Userspace provides the new channel information (using @@ -1058,13 +1068,11 @@ * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously * configured PMK for the authenticator address identified by * %NL80211_ATTR_MAC. - * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way - * handshake was completed successfully by the driver. The BSSID is - * specified with %NL80211_ATTR_MAC. Drivers that support 4 way handshake - * offload should send this event after indicating 802.11 association with - * %NL80211_CMD_CONNECT or %NL80211_CMD_ROAM. If the 4 way handshake failed - * %NL80211_CMD_DISCONNECT should be indicated instead. - * + * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates an 802.1X FT roam was + * completed successfully. Drivers that support 4 way handshake offload + * should send this event after indicating 802.1X FT assocation with + * %NL80211_CMD_ROAM. If the 4 way handshake failed %NL80211_CMD_DISCONNECT + * should be indicated instead. * @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request * and RX notification. This command is used both as a request to transmit * a control port frame and as a notification that a control port frame @@ -1113,7 +1121,7 @@ * randomization may be enabled and configured by specifying the * %NL80211_ATTR_MAC and %NL80211_ATTR_MAC_MASK attributes. * If a timeout is requested, use the %NL80211_ATTR_TIMEOUT attribute. - * A u64 cookie for further %NL80211_ATTR_COOKIE use is is returned in + * A u64 cookie for further %NL80211_ATTR_COOKIE use is returned in * the netlink extended ack message. * * To cancel a measurement, close the socket that requested it. @@ -1511,7 +1519,7 @@ enum nl80211_commands { * rates as defined by IEEE 802.11 7.3.2.2 but without the length * restriction (at most %NL80211_MAX_SUPP_RATES). * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station - * to, or the AP interface the station was originally added to to. + * to, or the AP interface the station was originally added to. * @NL80211_ATTR_STA_INFO: information about a station, part of station info * given for %NL80211_CMD_GET_STATION, nested attribute containing * info as possible, see &enum nl80211_sta_info. @@ -1743,8 +1751,9 @@ enum nl80211_commands { * specify just a single bitrate, which is to be used for the beacon. * The driver must also specify support for this with the extended * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, - * NL80211_EXT_FEATURE_BEACON_RATE_HT and - * NL80211_EXT_FEATURE_BEACON_RATE_VHT. + * NL80211_EXT_FEATURE_BEACON_RATE_HT, + * NL80211_EXT_FEATURE_BEACON_RATE_VHT and + * NL80211_EXT_FEATURE_BEACON_RATE_HE. * * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. @@ -2073,10 +2082,10 @@ enum nl80211_commands { * operation). * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information * for the time while performing a channel switch. - * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel - * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). - * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel - * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). + * @NL80211_ATTR_CNTDWN_OFFS_BEACON: An array of offsets (u16) to the channel + * switch or color change counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). + * @NL80211_ATTR_CNTDWN_OFFS_PRESP: An array of offsets (u16) to the channel + * switch or color change counters in the probe response (%NL80211_ATTR_PROBE_RESP). * * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. * As specified in the &enum nl80211_rxmgmt_flags. @@ -2084,7 +2093,7 @@ enum nl80211_commands { * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels. * * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported - * supported operating classes. + * operating classes. * * @NL80211_ATTR_HANDLE_DFS: A flag indicating whether user space * controls DFS operation in IBSS mode. If the flag is included in @@ -2362,10 +2371,11 @@ enum nl80211_commands { * * @NL80211_ATTR_PMK: attribute for passing PMK key material. Used with * %NL80211_CMD_SET_PMKSA for the PMKSA identified by %NL80211_ATTR_PMKID. - * For %NL80211_CMD_CONNECT it is used to provide PSK for offloading 4-way - * handshake for WPA/WPA2-PSK networks. For 802.1X authentication it is - * used with %NL80211_CMD_SET_PMK. For offloaded FT support this attribute - * specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME is included as well. + * For %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP it is used to provide + * PSK for offloading 4-way handshake for WPA/WPA2-PSK networks. For 802.1X + * authentication it is used with %NL80211_CMD_SET_PMK. For offloaded FT + * support this attribute specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME + * is included as well. * * @NL80211_ATTR_SCHED_SCAN_MULTI: flag attribute which user-space shall use to * indicate that it supports multiple active scheduled scan requests. @@ -2395,7 +2405,7 @@ enum nl80211_commands { * nl80211_txq_stats) * @NL80211_ATTR_TXQ_LIMIT: Total packet limit for the TXQ queues for this phy. * The smaller of this and the memory limit is enforced. - * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory memory limit (in bytes) for the + * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory limit (in bytes) for the * TXQ queues for this phy. The smaller of this and the packet limit is * enforced. * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes @@ -2505,6 +2515,25 @@ enum nl80211_commands { * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from * association request when used with NL80211_CMD_NEW_STATION). * + * @NL80211_ATTR_FILS_DISCOVERY: Optional parameter to configure FILS + * discovery. It is a nested attribute, see + * &enum nl80211_fils_discovery_attributes. + * + * @NL80211_ATTR_UNSOL_BCAST_PROBE_RESP: Optional parameter to configure + * unsolicited broadcast probe response. It is a nested attribute, see + * &enum nl80211_unsol_bcast_probe_resp_attributes. + * + * @NL80211_ATTR_S1G_CAPABILITY: S1G Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * @NL80211_ATTR_S1G_CAPABILITY_MASK: S1G Capability Information element + * override mask. Used with NL80211_ATTR_S1G_CAPABILITY in + * NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT. + * + * @NL80211_ATTR_SAE_PWE: Indicates the mechanism(s) allowed for SAE PWE + * derivation in WPA3-Personal networks which are using SAE authentication. + * This is a u8 attribute that encapsulates one of the values from + * &enum nl80211_sae_pwe_mechanism. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2811,8 +2840,8 @@ enum nl80211_attrs { NL80211_ATTR_CH_SWITCH_COUNT, NL80211_ATTR_CH_SWITCH_BLOCK_TX, NL80211_ATTR_CSA_IES, - NL80211_ATTR_CSA_C_OFF_BEACON, - NL80211_ATTR_CSA_C_OFF_PRESP, + NL80211_ATTR_CNTDWN_OFFS_BEACON, + NL80211_ATTR_CNTDWN_OFFS_PRESP, NL80211_ATTR_RXMGMT_FLAGS, @@ -2987,6 +3016,15 @@ enum nl80211_attrs { NL80211_ATTR_HE_6GHZ_CAPABILITY, + NL80211_ATTR_FILS_DISCOVERY, + + NL80211_ATTR_UNSOL_BCAST_PROBE_RESP, + + NL80211_ATTR_S1G_CAPABILITY, + NL80211_ATTR_S1G_CAPABILITY_MASK, + + NL80211_ATTR_SAE_PWE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2999,6 +3037,8 @@ enum nl80211_attrs { #define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG #define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER #define NL80211_ATTR_SAE_DATA NL80211_ATTR_AUTH_DATA +#define NL80211_ATTR_CSA_C_OFF_BEACON NL80211_ATTR_CNTDWN_OFFS_BEACON +#define NL80211_ATTR_CSA_C_OFF_PRESP NL80211_ATTR_CNTDWN_OFFS_PRESP /* * Allow user space programs to use #ifdef on new attributes by defining them @@ -3176,6 +3216,18 @@ enum nl80211_he_gi { NL80211_RATE_INFO_HE_GI_3_2, }; +/** + * enum nl80211_he_ltf - HE long training field + * @NL80211_RATE_INFO_HE_1xLTF: 3.2 usec + * @NL80211_RATE_INFO_HE_2xLTF: 6.4 usec + * @NL80211_RATE_INFO_HE_4xLTF: 12.8 usec + */ +enum nl80211_he_ltf { + NL80211_RATE_INFO_HE_1XLTF, + NL80211_RATE_INFO_HE_2XLTF, + NL80211_RATE_INFO_HE_4XLTF, +}; + /** * enum nl80211_he_ru_alloc - HE RU allocation values * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation @@ -3370,6 +3422,8 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station * @NL80211_STA_INFO_ASSOC_AT_BOOTTIME: Timestamp (CLOCK_BOOTTIME, nanoseconds) * of STA's association + * @NL80211_STA_INFO_CONNECTED_TO_AS: set to true if STA has a path to a + * authentication server (u8, 0 or 1) * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -3417,6 +3471,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_AIRTIME_WEIGHT, NL80211_STA_INFO_AIRTIME_LINK_METRIC, NL80211_STA_INFO_ASSOC_AT_BOOTTIME, + NL80211_STA_INFO_CONNECTED_TO_AS, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -3712,6 +3767,16 @@ enum nl80211_wmm_rule { * @NL80211_FREQUENCY_ATTR_NO_HE: HE operation is not allowed on this channel * in current regulatory domain. * @NL80211_FREQUENCY_ATTR_OFFSET: frequency offset in KHz + * @NL80211_FREQUENCY_ATTR_1MHZ: 1 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_2MHZ: 2 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_4MHZ: 4 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_8MHZ: 8 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_16MHZ: 16 MHz operation is allowed + * on this channel in current regulatory domain. * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number * currently defined * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use @@ -3743,6 +3808,11 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_WMM, NL80211_FREQUENCY_ATTR_NO_HE, NL80211_FREQUENCY_ATTR_OFFSET, + NL80211_FREQUENCY_ATTR_1MHZ, + NL80211_FREQUENCY_ATTR_2MHZ, + NL80211_FREQUENCY_ATTR_4MHZ, + NL80211_FREQUENCY_ATTR_8MHZ, + NL80211_FREQUENCY_ATTR_16MHZ, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, @@ -4036,6 +4106,7 @@ enum nl80211_user_reg_hint_type { * receiving frames destined to the local BSS * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number * currently defined + * @NL80211_SURVEY_INFO_FREQUENCY_OFFSET: center frequency offset in KHz * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use */ enum nl80211_survey_info { @@ -4051,6 +4122,7 @@ enum nl80211_survey_info { NL80211_SURVEY_INFO_TIME_SCAN, NL80211_SURVEY_INFO_PAD, NL80211_SURVEY_INFO_TIME_BSS_RX, + NL80211_SURVEY_INFO_FREQUENCY_OFFSET, /* keep last */ __NL80211_SURVEY_INFO_AFTER_LAST, @@ -4236,6 +4308,16 @@ enum nl80211_mesh_power_mode { * field. If left unset then the mesh formation field will only * advertise such if there is an active root mesh path. * + * @NL80211_MESHCONF_NOLEARN: Try to avoid multi-hop path discovery (e.g. + * PREQ/PREP for HWMP) if the destination is a direct neighbor. Note that + * this might not be the optimal decision as a multi-hop route might be + * better. So if using this setting you will likely also want to disable + * dot11MeshForwarding and use another mesh routing protocol on top. + * + * @NL80211_MESHCONF_CONNECTED_TO_AS: If set to true then this mesh STA + * will advertise that it is connected to a authentication server + * in the mesh formation field. + * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use */ enum nl80211_meshconf_params { @@ -4269,6 +4351,8 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_AWAKE_WINDOW, NL80211_MESHCONF_PLINK_TIMEOUT, NL80211_MESHCONF_CONNECTED_TO_GATE, + NL80211_MESHCONF_NOLEARN, + NL80211_MESHCONF_CONNECTED_TO_AS, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, @@ -4437,6 +4521,11 @@ enum nl80211_key_mode { * attribute must be provided as well * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel + * @NL80211_CHAN_WIDTH_1: 1 MHz OFDM channel + * @NL80211_CHAN_WIDTH_2: 2 MHz OFDM channel + * @NL80211_CHAN_WIDTH_4: 4 MHz OFDM channel + * @NL80211_CHAN_WIDTH_8: 8 MHz OFDM channel + * @NL80211_CHAN_WIDTH_16: 16 MHz OFDM channel */ enum nl80211_chan_width { NL80211_CHAN_WIDTH_20_NOHT, @@ -4447,6 +4536,11 @@ enum nl80211_chan_width { NL80211_CHAN_WIDTH_160, NL80211_CHAN_WIDTH_5, NL80211_CHAN_WIDTH_10, + NL80211_CHAN_WIDTH_1, + NL80211_CHAN_WIDTH_2, + NL80211_CHAN_WIDTH_4, + NL80211_CHAN_WIDTH_8, + NL80211_CHAN_WIDTH_16, }; /** @@ -4457,11 +4551,15 @@ enum nl80211_chan_width { * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide + * @NL80211_BSS_CHAN_WIDTH_1: control channel is 1 MHz wide + * @NL80211_BSS_CHAN_WIDTH_2: control channel is 2 MHz wide */ enum nl80211_bss_scan_width { NL80211_BSS_CHAN_WIDTH_20, NL80211_BSS_CHAN_WIDTH_10, NL80211_BSS_CHAN_WIDTH_5, + NL80211_BSS_CHAN_WIDTH_1, + NL80211_BSS_CHAN_WIDTH_2, }; /** @@ -4702,6 +4800,10 @@ enum nl80211_key_attributes { * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection, * see &struct nl80211_txrate_vht * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi + * @NL80211_TXRATE_HE: HE rates allowed for TX rate selection, + * see &struct nl80211_txrate_he + * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us. + * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF. * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute */ @@ -4711,6 +4813,9 @@ enum nl80211_tx_rate_attributes { NL80211_TXRATE_HT, NL80211_TXRATE_VHT, NL80211_TXRATE_GI, + NL80211_TXRATE_HE, + NL80211_TXRATE_HE_GI, + NL80211_TXRATE_HE_LTF, /* keep last */ __NL80211_TXRATE_AFTER_LAST, @@ -4728,6 +4833,15 @@ struct nl80211_txrate_vht { __u16 mcs[NL80211_VHT_NSS_MAX]; }; +#define NL80211_HE_NSS_MAX 8 +/** + * struct nl80211_txrate_he - HE MCS/NSS txrate bitmap + * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.) + */ +struct nl80211_txrate_he { + __u16 mcs[NL80211_HE_NSS_MAX]; +}; + enum nl80211_txrate_gi { NL80211_TXRATE_DEFAULT_GI, NL80211_TXRATE_FORCE_SGI, @@ -4740,6 +4854,7 @@ enum nl80211_txrate_gi { * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) + * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace * since newer kernel versions may support more bands */ @@ -4748,6 +4863,7 @@ enum nl80211_band { NL80211_BAND_5GHZ, NL80211_BAND_60GHZ, NL80211_BAND_6GHZ, + NL80211_BAND_S1GHZ, NUM_NL80211_BANDS, }; @@ -5636,7 +5752,7 @@ enum nl80211_feature_flags { * enum nl80211_ext_feature_index - bit index of extended features. * @NL80211_EXT_FEATURE_VHT_IBSS: This driver supports IBSS with VHT datarates. * @NL80211_EXT_FEATURE_RRM: This driver supports RRM. When featured, user can - * can request to use RRM (see %NL80211_ATTR_USE_RRM) with + * request to use RRM (see %NL80211_ATTR_USE_RRM) with * %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set * the ASSOC_REQ_USE_RRM flag in the association request even if * NL80211_FEATURE_QUIET is not advertized. @@ -5773,6 +5889,25 @@ enum nl80211_feature_flags { * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS: The driver * can report tx status for control port over nl80211 tx operations. * + * @NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION: Driver supports Operating + * Channel Validation (OCV) when using driver's SME for RSNA handshakes. + * + * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK: Device wants to do 4-way + * handshake with PSK in AP mode (PSK is passed as part of the start AP + * command). + * + * @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP: Device wants to do SAE authentication + * in AP mode (SAE password is passed as part of the start AP command). + * + * @NL80211_EXT_FEATURE_FILS_DISCOVERY: Driver/device supports FILS discovery + * frames transmission + * + * @NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP: Driver/device supports + * unsolicited broadcast probe response transmission + * + * @NL80211_EXT_FEATURE_BEACON_RATE_HE: Driver supports beacon rate + * configuration (AP/mesh) with HE rates. + * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ @@ -5828,6 +5963,12 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT, NL80211_EXT_FEATURE_SCAN_FREQ_KHZ, NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS, + NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK, + NL80211_EXT_FEATURE_SAE_OFFLOAD_AP, + NL80211_EXT_FEATURE_FILS_DISCOVERY, + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP, + NL80211_EXT_FEATURE_BEACON_RATE_HE, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, @@ -5942,6 +6083,8 @@ enum nl80211_timeout_reason { * @NL80211_SCAN_FLAG_FREQ_KHZ: report scan results with * %NL80211_ATTR_SCAN_FREQ_KHZ. This also means * %NL80211_ATTR_SCAN_FREQUENCIES will not be included. + * @NL80211_SCAN_FLAG_COLOCATED_6GHZ: scan for colocated APs reported by + * 2.4/5 GHz APs */ enum nl80211_scan_flags { NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, @@ -5958,6 +6101,7 @@ enum nl80211_scan_flags { NL80211_SCAN_FLAG_RANDOM_SN = 1<<11, NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12, NL80211_SCAN_FLAG_FREQ_KHZ = 1<<13, + NL80211_SCAN_FLAG_COLOCATED_6GHZ = 1<<14, }; /** @@ -6045,7 +6189,7 @@ enum nl80211_dfs_state { }; /** - * enum enum nl80211_protocol_features - nl80211 protocol features + * enum nl80211_protocol_features - nl80211 protocol features * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting * wiphy dumps (if requested by the application with the attribute * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the @@ -6860,6 +7004,13 @@ enum nl80211_peer_measurement_ftm_resp { * * @NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET: the OBSS PD minimum tx power offset. * @NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET: the OBSS PD maximum tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET: the non-SRG OBSS PD maximum + * tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP: bitmap that indicates the BSS color + * values used by members of the SRG. + * @NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP: bitmap that indicates the partial + * BSSID values used by members of the SRG. + * @NL80211_HE_OBSS_PD_ATTR_SR_CTRL: The SR Control field of SRP element. * * @__NL80211_HE_OBSS_PD_ATTR_LAST: Internal * @NL80211_HE_OBSS_PD_ATTR_MAX: highest OBSS PD attribute. @@ -6869,6 +7020,10 @@ enum nl80211_obss_pd_attributes { NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, + NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET, + NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP, + NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP, + NL80211_HE_OBSS_PD_ATTR_SR_CTRL, /* keep last */ __NL80211_HE_OBSS_PD_ATTR_LAST, @@ -6922,4 +7077,83 @@ enum nl80211_iftype_akm_attributes { NL80211_IFTYPE_AKM_ATTR_MAX = __NL80211_IFTYPE_AKM_ATTR_LAST - 1, }; +/** + * enum nl80211_fils_discovery_attributes - FILS discovery configuration + * from IEEE Std 802.11ai-2016, Annex C.3 MIB detail. + * + * @__NL80211_FILS_DISCOVERY_ATTR_INVALID: Invalid + * + * @NL80211_FILS_DISCOVERY_ATTR_INT_MIN: Minimum packet interval (u32, TU). + * Allowed range: 0..10000 (TU = Time Unit) + * @NL80211_FILS_DISCOVERY_ATTR_INT_MAX: Maximum packet interval (u32, TU). + * Allowed range: 0..10000 (TU = Time Unit) + * @NL80211_FILS_DISCOVERY_ATTR_TMPL: Template data for FILS discovery action + * frame including the headers. + * + * @__NL80211_FILS_DISCOVERY_ATTR_LAST: Internal + * @NL80211_FILS_DISCOVERY_ATTR_MAX: highest attribute + */ +enum nl80211_fils_discovery_attributes { + __NL80211_FILS_DISCOVERY_ATTR_INVALID, + + NL80211_FILS_DISCOVERY_ATTR_INT_MIN, + NL80211_FILS_DISCOVERY_ATTR_INT_MAX, + NL80211_FILS_DISCOVERY_ATTR_TMPL, + + /* keep last */ + __NL80211_FILS_DISCOVERY_ATTR_LAST, + NL80211_FILS_DISCOVERY_ATTR_MAX = __NL80211_FILS_DISCOVERY_ATTR_LAST - 1 +}; + +/* + * FILS discovery template minimum length with action frame headers and + * mandatory fields. + */ +#define NL80211_FILS_DISCOVERY_TMPL_MIN_LEN 42 + +/** + * enum nl80211_unsol_bcast_probe_resp_attributes - Unsolicited broadcast probe + * response configuration. Applicable only in 6GHz. + * + * @__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INVALID: Invalid + * + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT: Maximum packet interval (u32, TU). + * Allowed range: 0..20 (TU = Time Unit). IEEE P802.11ax/D6.0 + * 26.17.2.3.2 (AP behavior for fast passive scanning). + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL: Unsolicited broadcast probe response + * frame template (binary). + * + * @__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST: Internal + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX: highest attribute + */ +enum nl80211_unsol_bcast_probe_resp_attributes { + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INVALID, + + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT, + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL, + + /* keep last */ + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST, + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX = + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST - 1 +}; + +/** + * enum nl80211_sae_pwe_mechanism - The mechanism(s) allowed for SAE PWE + * derivation. Applicable only when WPA3-Personal SAE authentication is + * used. + * + * @NL80211_SAE_PWE_UNSPECIFIED: not specified, used internally to indicate that + * attribute is not present from userspace. + * @NL80211_SAE_PWE_HUNT_AND_PECK: hunting-and-pecking loop only + * @NL80211_SAE_PWE_HASH_TO_ELEMENT: hash-to-element only + * @NL80211_SAE_PWE_BOTH: both hunting-and-pecking loop and hash-to-element + * can be used. + */ +enum nl80211_sae_pwe_mechanism { + NL80211_SAE_PWE_UNSPECIFIED, + NL80211_SAE_PWE_HUNT_AND_PECK, + NL80211_SAE_PWE_HASH_TO_ELEMENT, + NL80211_SAE_PWE_BOTH, +}; #endif /* __LINUX_NL80211_H */ From 1934ad9b23afb55dfcf8f5b241a49592b313b723 Mon Sep 17 00:00:00 2001 From: Nandha Kishore Easwaran Date: Wed, 11 Nov 2020 18:38:02 +0530 Subject: [PATCH 1053/1105] Add extra parameters to vendor command GPIO attribute Add extra parameters mux_config, drive, and init_enable to the GPIO config command. Signed-off-by: Nandha Kishore Easwaran --- src/common/qca-vendor.h | 69 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index ca9c2d177..d7e4dda4b 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2438,23 +2438,50 @@ enum qca_wlan_vendor_attr_sap_conditional_chan_switch { * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_OUTPUT. * - * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Required (u32) + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Optional (u32) * value to specify the GPIO pull type. Please refer to enum qca_gpio_pull_type * for the available values. * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is - * %QCA_WLAN_VENDOR_GPIO_CONFIG. + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. * - * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Required (u32) + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Optional (u32) * value to specify the GPIO interrupt mode. Please refer to enum * qca_gpio_interrupt_mode for the available values. * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is - * %QCA_WLAN_VENDOR_GPIO_CONFIG. + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. * - * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Required (u32) + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Optional (u32) * value to specify the GPIO direction. Please refer to enum qca_gpio_direction * for the available values. * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is - * %QCA_WLAN_VENDOR_GPIO_CONFIG. + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG: Optional (u32) + * Value to specify the mux config. Meaning of a given value is dependent + * on the target chipset and GPIO pin. Must be of the range 0-15. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to 0. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE: Optional (u32) + * Value to specify the drive, refer to enum qca_gpio_drive. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to QCA_WLAN_GPIO_DRIVE_2MA(0). + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG: Optional (flag) + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. When present this attribute signals that all + * other parameters for the given GPIO will be obtained from internal + * configuration. Only %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM must be + * specified to indicate the GPIO pin being configured. */ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0, @@ -2470,6 +2497,12 @@ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE = 5, /* Unsigned 32-bit attribute for GPIO direction to configure */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR = 6, + /* Unsigned 32-bit attribute for GPIO mux config */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG = 7, + /* Unsigned 32-bit attribute for GPIO drive */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE = 8, + /* Flag attribute for using internal GPIO configuration */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG = 9, /* keep last */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST, @@ -2544,6 +2577,30 @@ enum qca_gpio_interrupt_mode { QCA_WLAN_GPIO_INTMODE_MAX, }; +/** + * enum qca_gpio_drive - GPIO drive + * @QCA_WLAN_GPIO_DRIVE_2MA: drive 2MA + * @QCA_WLAN_GPIO_DRIVE_4MA: drive 4MA + * @QCA_WLAN_GPIO_DRIVE_6MA: drive 6MA + * @QCA_WLAN_GPIO_DRIVE_8MA: drive 8MA + * @QCA_WLAN_GPIO_DRIVE_10MA: drive 10MA + * @QCA_WLAN_GPIO_DRIVE_12MA: drive 12MA + * @QCA_WLAN_GPIO_DRIVE_14MA: drive 14MA + * @QCA_WLAN_GPIO_DRIVE_16MA: drive 16MA + * @QCA_WLAN_GPIO_DRIVE_MAX: invalid GPIO drive + */ +enum qca_gpio_drive { + QCA_WLAN_GPIO_DRIVE_2MA = 0, + QCA_WLAN_GPIO_DRIVE_4MA = 1, + QCA_WLAN_GPIO_DRIVE_6MA = 2, + QCA_WLAN_GPIO_DRIVE_8MA = 3, + QCA_WLAN_GPIO_DRIVE_10MA = 4, + QCA_WLAN_GPIO_DRIVE_12MA = 5, + QCA_WLAN_GPIO_DRIVE_14MA = 6, + QCA_WLAN_GPIO_DRIVE_16MA = 7, + QCA_WLAN_GPIO_DRIVE_MAX, +}; + /** * qca_wlan_set_qdepth_thresh_attr - Parameters for setting * MSDUQ depth threshold per peer per tid in the target From 7423fa6e8f59b39cbef48f74b11bd12b8bf57142 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Wed, 4 Nov 2020 21:39:38 +0530 Subject: [PATCH 1054/1105] Vendor feature capability to support concurrent sessions on Wi-Fi bands Introduces a vendor specific feature capability QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS to know if the device supports concurrent network sessions on different Wi-Fi bands. This feature capability is attributed to the hardware's capability to support the same (e.g., DBS). Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index d7e4dda4b..096757e41 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -1454,6 +1454,10 @@ enum qca_wlan_vendor_acs_hw_mode { * The driver-based SME cases also need to have this support for * Adaptive 11r to handle the connection and roaming scenarios. * This flag indicates the support for the same to the user space. + * @QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS: Device supports + * concurrent network sessions on different Wi-Fi bands. This feature + * capability is attributed to the hardware's capability to support + * the same (e.g., DBS). * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits */ enum qca_wlan_vendor_features { @@ -1470,6 +1474,7 @@ enum qca_wlan_vendor_features { QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT = 10, QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG = 11, QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R = 12, + QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS = 13, NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */ }; From 60c902f408ae4fdbf982e137f97162f5d540be69 Mon Sep 17 00:00:00 2001 From: "Vinita S. Maloo" Date: Thu, 15 Oct 2020 20:28:17 +0530 Subject: [PATCH 1055/1105] Add connect fail reason code from the driver to assoc reject event Add support to report a vendor specific connect fail reason code fetched from the driver to users by adding the reason code to the event CTRL-EVENT-ASSOC-REJECT. Fetch the connect fail reason code when the driver sends a failure connection result and append the reason code, if available, to assoc reject event. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 33 ++++++++++ src/drivers/driver_nl80211.h | 1 + src/drivers/driver_nl80211_capa.c | 3 + src/drivers/driver_nl80211_event.c | 99 ++++++++++++++++++++++++++++++ wpa_supplicant/events.c | 41 +++++++++++-- 5 files changed, 173 insertions(+), 4 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 0019f54f9..2f7f09a8a 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -5062,6 +5062,34 @@ struct freq_survey { #define SURVEY_HAS_CHAN_TIME_RX BIT(3) #define SURVEY_HAS_CHAN_TIME_TX BIT(4) +/** + * enum sta_connect_fail_reason_codes - STA connect failure reason code values + * @STA_CONNECT_FAIL_REASON_UNSPECIFIED: No reason code specified for + * connection failure. + * @STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received + * for unicast Probe Request frame. + * @STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request. + * @STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for + * auth request. + * @STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not + * received from AP. + * @STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send + * Association Request frame. + * @STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for + * Association Request frame. + * @STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response + * frame is not received from AP. + */ +enum sta_connect_fail_reason_codes { + STA_CONNECT_FAIL_REASON_UNSPECIFIED = 0, + STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1, + STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2, + STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3, + STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4, + STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5, + STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6, + STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7, +}; /** * union wpa_event_data - Additional data for wpa_supplicant_event() calls @@ -5463,6 +5491,11 @@ union wpa_event_data { * FILS ERP messages */ u16 fils_erp_next_seq_num; + + /** + * reason_code - Connection failure reason code from the driver + */ + enum sta_connect_fail_reason_codes reason_code; } assoc_reject; struct timeout_event { diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 017c025a0..4009545fa 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -174,6 +174,7 @@ struct wpa_driver_nl80211_data { unsigned int control_port_ap:1; unsigned int multicast_registrations:1; unsigned int no_rrm:1; + unsigned int get_sta_info_vendor_cmd_avail:1; u64 vendor_scan_cookie; u64 remain_on_chan_cookie; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 287b8aa30..6c2ab515e 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -994,6 +994,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: drv->add_sta_node_vendor_cmd_avail = 1; break; + case QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO: + drv->get_sta_info_vendor_cmd_avail = 1; + break; #endif /* CONFIG_DRIVER_NL80211_QCA */ } } diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index ce95e9cd3..f75f7b3ae 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -296,6 +296,94 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, } +#ifdef CONFIG_DRIVER_NL80211_QCA + +static int qca_drv_connect_fail_reason_code_handler(struct nl_msg *msg, + void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct nlattr *tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + u32 *reason_code = arg; + + *reason_code = 0; + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_VENDOR_DATA]) { + wpa_printf(MSG_ERROR, "%s: Vendor data not found", __func__); + return NL_SKIP; + } + + nla_parse(tb_sta_info, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX, + nla_data(tb[NL80211_ATTR_VENDOR_DATA]), + nla_len(tb[NL80211_ATTR_VENDOR_DATA]), NULL); + + if (!tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE]) { + wpa_printf(MSG_INFO, "%s: Vendor attr not found", __func__); + return NL_SKIP; + } + + *reason_code = nla_get_u32(tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE]); + + return NL_SKIP; +} + + +static enum qca_sta_connect_fail_reason_codes +drv_get_connect_fail_reason_code(struct wpa_driver_nl80211_data *drv) +{ + enum qca_sta_connect_fail_reason_codes reason_code; + struct nl_msg *msg; + int ret; + + msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR); + if (!msg || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, + QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO)) { + nlmsg_free(msg); + return 0; + } + + ret = send_and_recv_msgs(drv, msg, + qca_drv_connect_fail_reason_code_handler, + &reason_code, NULL, NULL); + if (ret) + wpa_printf(MSG_DEBUG, + "nl80211: Get connect fail reason_code failed: ret=%d (%s)", + ret, strerror(-ret)); + + return reason_code; +} + + +static enum sta_connect_fail_reason_codes +convert_connect_fail_reason_codes(enum qca_sta_connect_fail_reason_codes + reason_code) +{ + switch (reason_code) { + case QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: + return STA_CONNECT_FAIL_REASON_NO_BSS_FOUND; + case QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: + return STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL; + case QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: + return STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED; + case QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: + return STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED; + case QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: + return STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL; + case QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: + return STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED; + case QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: + return STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED; + default: + return STA_CONNECT_FAIL_REASON_UNSPECIFIED; + } +} + +#endif /* CONFIG_DRIVER_NL80211_QCA */ + + static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, enum nl80211_commands cmd, struct nlattr *status, struct nlattr *addr, struct nlattr *req_ie, @@ -385,6 +473,17 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, if (fils_erp_next_seq_num) event.assoc_reject.fils_erp_next_seq_num = nla_get_u16(fils_erp_next_seq_num); + +#ifdef CONFIG_DRIVER_NL80211_QCA + if (drv->get_sta_info_vendor_cmd_avail) { + enum qca_sta_connect_fail_reason_codes reason_code; + + reason_code = drv_get_connect_fail_reason_code(drv); + event.assoc_reject.reason_code = + convert_connect_fail_reason_codes(reason_code); + } +#endif /* CONFIG_DRIVER_NL80211_QCA */ + wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event); return; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 1b46a9715..b53746b70 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -4425,6 +4425,31 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s, } +static const char * connect_fail_reason(enum sta_connect_fail_reason_codes code) +{ + switch (code) { + case STA_CONNECT_FAIL_REASON_UNSPECIFIED: + return ""; + case STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: + return "no_bss_found"; + case STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: + return "auth_tx_fail"; + case STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: + return "auth_no_ack_received"; + case STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: + return "auth_no_resp_received"; + case STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: + return "assoc_req_tx_fail"; + case STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: + return "assoc_no_ack_received"; + case STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: + return "assoc_no_resp_received"; + default: + return "unknown_reason"; + } +} + + static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { @@ -4444,21 +4469,29 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, if (data->assoc_reject.bssid) wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT - "bssid=" MACSTR " status_code=%u%s%s%s", + "bssid=" MACSTR " status_code=%u%s%s%s%s%s", MAC2STR(data->assoc_reject.bssid), data->assoc_reject.status_code, data->assoc_reject.timed_out ? " timeout" : "", data->assoc_reject.timeout_reason ? "=" : "", data->assoc_reject.timeout_reason ? - data->assoc_reject.timeout_reason : ""); + data->assoc_reject.timeout_reason : "", + data->assoc_reject.reason_code != + STA_CONNECT_FAIL_REASON_UNSPECIFIED ? + " qca_driver_reason=" : "", + connect_fail_reason(data->assoc_reject.reason_code)); else wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT - "status_code=%u%s%s%s", + "status_code=%u%s%s%s%s%s", data->assoc_reject.status_code, data->assoc_reject.timed_out ? " timeout" : "", data->assoc_reject.timeout_reason ? "=" : "", data->assoc_reject.timeout_reason ? - data->assoc_reject.timeout_reason : ""); + data->assoc_reject.timeout_reason : "", + data->assoc_reject.reason_code != + STA_CONNECT_FAIL_REASON_UNSPECIFIED ? + " qca_driver_reason=" : "", + connect_fail_reason(data->assoc_reject.reason_code)); wpa_s->assoc_status_code = data->assoc_reject.status_code; wpas_notify_assoc_status_code(wpa_s); From 2ffd3bb4b6dfd497fa1fb228b2cb4c6dafe37735 Mon Sep 17 00:00:00 2001 From: Sreeramya Soratkal Date: Thu, 29 Oct 2020 19:15:47 +0530 Subject: [PATCH 1056/1105] P2P: Include p2p_6ghz_disable in global configuration Previously, the configuration to disable the 6 GHz band remained local to the P2P interface. With this there is a possibility of 6 GHz channels being included in the channel list when the channel list needs to be updated if the state changes on one of the interfaces. Include the configuration to disable the 6 GHz band for P2P as a global configuration value to prevent the inclusion of 6 GHz channels in the channel list for P2P when the channel list needs to be updated during the state change in one of the interfaces. Signed-off-by: Sreeramya Soratkal --- src/p2p/p2p.c | 8 ++++++++ src/p2p/p2p.h | 7 +++++++ wpa_supplicant/p2p_supplicant.c | 13 ++++++++----- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index f9ca90301..6b92a6d23 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -2913,6 +2913,14 @@ void p2p_group_formation_failed(struct p2p_data *p2p) } +bool is_p2p_6ghz_disabled(struct p2p_data *p2p) +{ + if (p2p) + return p2p->cfg->p2p_6ghz_disable; + return false; +} + + struct p2p_data * p2p_init(const struct p2p_config *cfg) { struct p2p_data *p2p; diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 2dae6c6ec..ed8beab19 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -500,6 +500,11 @@ struct p2p_config { */ struct p2p_channel *pref_chan; + /** + * p2p_6ghz_disable - Disable 6GHz for P2P operations + */ + bool p2p_6ghz_disable; + /** * pri_dev_type - Primary Device Type (see WPS) */ @@ -2100,6 +2105,8 @@ void p2p_update_channel_list(struct p2p_data *p2p, const struct p2p_channels *chan, const struct p2p_channels *cli_chan); +bool is_p2p_6ghz_disabled(struct p2p_data *p2p); + /** * p2p_set_best_channels - Update best channel information * @p2p: P2P module context from p2p_init() diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 330687b81..75e62a9e9 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3752,7 +3752,8 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s, static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, struct p2p_channels *chan, - struct p2p_channels *cli_chan) + struct p2p_channels *cli_chan, + bool p2p_disable_6ghz) { struct hostapd_hw_modes *mode; int cla, op, cli_cla; @@ -3772,8 +3773,7 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, struct p2p_reg_class *reg = NULL, *cli_reg = NULL; if (o->p2p == NO_P2P_SUPP || - (is_6ghz_op_class(o->op_class) && - wpa_s->conf->p2p_6ghz_disable)) + (is_6ghz_op_class(o->op_class) && p2p_disable_6ghz)) continue; mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode, @@ -4669,6 +4669,7 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb; p2p.p2ps_group_capability = p2ps_group_capability; p2p.get_pref_freq_list = wpas_p2p_get_pref_freq_list; + p2p.p2p_6ghz_disable = wpa_s->conf->p2p_6ghz_disable; os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); @@ -4682,7 +4683,8 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.config_methods = wpa_s->wps->config_methods; } - if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) { + if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels, + p2p.p2p_6ghz_disable)) { wpa_printf(MSG_ERROR, "P2P: Failed to configure supported channel list"); return -1; @@ -8018,7 +8020,8 @@ void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s, os_memset(&chan, 0, sizeof(chan)); os_memset(&cli_chan, 0, sizeof(cli_chan)); - if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan)) { + if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan, + is_p2p_6ghz_disabled(wpa_s->global->p2p))) { wpa_printf(MSG_ERROR, "P2P: Failed to update supported " "channel list"); return; From 2576f27e04259c4434733070ed12d21dcd767d36 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna Date: Mon, 16 Nov 2020 12:31:34 +0530 Subject: [PATCH 1057/1105] P2P: Disable P2P in the 6 GHz band for now P2P usage in the 6 GHz band is not standardized yet by WFA. Disable P2P operations in the 6 GHz band to avoid potential interop issues with existing P2P devices in production. P2P operations in the 6 GHz band can be reenabled later after defining standard ways to address potential interop issues with existing P2P devices. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 9b3782e26..8bdeeb5a4 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -1885,7 +1885,7 @@ const struct oper_class_map global_op_class[] = { */ { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, NO_P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP }, From fdf114641fded544ffc4d9a90d214181abdfec92 Mon Sep 17 00:00:00 2001 From: Rohan Dutta Date: Sat, 7 Nov 2020 19:23:24 +0530 Subject: [PATCH 1058/1105] nl80211: Send the sae_pwe value to the driver Use NL80211_ATTR_SAE_PWE attribute to indicate the sae_pwe value to the driver during the NL80211_CMD_START_AP and NL80211_CMD_CONNECT in WPA3-Personal networks which are using SAE authentication. Signed-off-by: Rohan Dutta --- src/ap/beacon.c | 3 +++ src/drivers/driver.h | 16 ++++++++++++++ src/drivers/driver_nl80211.c | 38 +++++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant.c | 4 ++++ 4 files changed, 61 insertions(+) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index b3b33b7fa..6d5bb7106 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1507,6 +1507,9 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd) IEEE80211_MODE_AP); #endif /* CONFIG_IEEE80211AX */ hapd->reenable_beacon = 0; +#ifdef CONFIG_SAE + params.sae_pwe = hapd->conf->sae_pwe; +#endif /* CONFIG_SAE */ if (cmode && hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq, diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 2f7f09a8a..722e428f1 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1189,6 +1189,14 @@ struct wpa_driver_associate_params { * fils_erp_rrk_len - Length of fils_erp_rrk in bytes */ size_t fils_erp_rrk_len; + + /** + * sae_pwe - SAE mechanism for PWE derivation + * 0 = hunting-and-pecking loop only + * 1 = hash-to-element only + * 2 = both hunting-and-pecking loop and hash-to-element enabled + */ + int sae_pwe; }; enum hide_ssid { @@ -1508,6 +1516,14 @@ struct wpa_driver_ap_params { * twt_responder - Whether Target Wait Time responder is enabled */ int twt_responder; + + /** + * sae_pwe - SAE mechanism for PWE derivation + * 0 = hunting-and-pecking loop only + * 1 = hash-to-element only + * 2 = both hunting-and-pecking loop and hash-to-element enabled + */ + int sae_pwe; }; struct wpa_driver_mesh_bss_params { diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 477443050..94bf98210 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4304,6 +4304,30 @@ static int nl80211_set_multicast_to_unicast(struct i802_bss *bss, } +#ifdef CONFIG_SAE +static int nl80211_put_sae_pwe(struct nl_msg *msg, int pwe) +{ + u8 sae_pwe; + + wpa_printf(MSG_DEBUG, "nl802111: sae_pwe=%d", pwe); + if (pwe == 0) + sae_pwe = NL80211_SAE_PWE_HUNT_AND_PECK; + else if (pwe == 1) + sae_pwe = NL80211_SAE_PWE_HASH_TO_ELEMENT; + else if (pwe == 2) + sae_pwe = NL80211_SAE_PWE_BOTH; + else if (pwe == 3) + return 0; /* special test mode */ + else + return -1; + if (nla_put_u8(msg, NL80211_ATTR_SAE_PWE, sae_pwe)) + return -1; + + return 0; +} +#endif /* CONFIG_SAE */ + + static int wpa_driver_nl80211_set_ap(void *priv, struct wpa_driver_ap_params *params) { @@ -4564,6 +4588,13 @@ static int wpa_driver_nl80211_set_ap(void *priv, } #endif /* CONFIG_IEEE80211AX */ +#ifdef CONFIG_SAE + if (((params->key_mgmt_suites & WPA_KEY_MGMT_SAE) || + (params->key_mgmt_suites & WPA_KEY_MGMT_FT_SAE)) && + nl80211_put_sae_pwe(msg, params->sae_pwe) < 0) + goto fail; +#endif /* CONFIG_SAE */ + ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1, NULL, NULL, NULL, NULL); if (ret) { @@ -6114,6 +6145,13 @@ static int wpa_driver_nl80211_try_connect( nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_OPTIONAL)) goto fail; +#ifdef CONFIG_SAE + if ((params->key_mgmt_suite == WPA_KEY_MGMT_SAE || + params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE) && + nl80211_put_sae_pwe(msg, params->sae_pwe) < 0) + goto fail; +#endif /* CONFIG_SAE */ + algs = 0; if (params->auth_alg & WPA_AUTH_ALG_OPEN) algs++; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index fba6d0eaf..ba7c23fa9 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3831,6 +3831,10 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_s->current_ssid) params.prev_bssid = prev_bssid; +#ifdef CONFIG_SAE + params.sae_pwe = wpa_s->conf->sae_pwe; +#endif /* CONFIG_SAE */ + ret = wpa_drv_associate(wpa_s, ¶ms); os_free(wpa_ie); if (ret < 0) { From 2a7023ba6f4ef318f52efbd52c9f54459c06d6cb Mon Sep 17 00:00:00 2001 From: Hai Shalom Date: Mon, 2 Nov 2020 18:14:11 -0800 Subject: [PATCH 1059/1105] Change list arguments to const where possible Change struct dl_list pointer argument to const in list functions that do not manipulate the list: dl_list_len() and dl_list_empty(). Signed-off-by: Hai Shalom --- src/utils/list.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/list.h b/src/utils/list.h index 85aa5e39c..5298c2626 100644 --- a/src/utils/list.h +++ b/src/utils/list.h @@ -46,12 +46,12 @@ static inline void dl_list_del(struct dl_list *item) item->prev = NULL; } -static inline int dl_list_empty(struct dl_list *list) +static inline int dl_list_empty(const struct dl_list *list) { return list->next == list; } -static inline unsigned int dl_list_len(struct dl_list *list) +static inline unsigned int dl_list_len(const struct dl_list *list) { struct dl_list *item; int count = 0; From 5027f34a331646a5dbb4cf97a9e3b633abacf534 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Nov 2020 15:36:59 +0200 Subject: [PATCH 1060/1105] tests: Fix test description strings for couple of SAE cases Remove the extraneous closing parenthesis. Signed-off-by: Jouni Malinen --- tests/hwsim/test_sae.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index 1c80b3946..9276e513e 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -1710,7 +1710,7 @@ def test_sae_password_id_only(dev, apdev): key_mgmt="SAE", scan_freq="2412") def test_sae_password_id_pwe_looping(dev, apdev): - """SAE and password identifier with forced PWE looping)""" + """SAE and password identifier with forced PWE looping""" check_sae_capab(dev[0]) params = hostapd.wpa2_params(ssid="test-sae") params['wpa_key_mgmt'] = 'SAE' @@ -1728,7 +1728,7 @@ def test_sae_password_id_pwe_looping(dev, apdev): dev[0].set("sae_pwe", "0") def test_sae_password_id_pwe_check_ap(dev, apdev): - """SAE and password identifier with STA using unexpected PWE derivation)""" + """SAE and password identifier with STA using unexpected PWE derivation""" check_sae_capab(dev[0]) params = hostapd.wpa2_params(ssid="test-sae") params['wpa_key_mgmt'] = 'SAE' @@ -1749,7 +1749,7 @@ def test_sae_password_id_pwe_check_ap(dev, apdev): dev[0].set("sae_pwe", "0") def test_sae_password_id_pwe_check_sta(dev, apdev): - """SAE and password identifier with AP using unexpected PWE derivation)""" + """SAE and password identifier with AP using unexpected PWE derivation""" check_sae_capab(dev[0]) params = hostapd.wpa2_params(ssid="test-sae") params['wpa_key_mgmt'] = 'SAE' From dba4f7a54509ee261a8dfd29ae5b87e9b8f3f7c2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Nov 2020 15:52:22 +0200 Subject: [PATCH 1061/1105] Mark wpa_bss_get_fils_cache_id() argument const This function does not modify the BSS entry. Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 2 +- wpa_supplicant/bss.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 7b6ed773a..7e420485f 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -1359,7 +1359,7 @@ int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates) #ifdef CONFIG_FILS -const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss) +const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss) { const u8 *ie; diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 071676174..e49858d19 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -148,7 +148,7 @@ int wpa_bss_get_max_rate(const struct wpa_bss *bss); int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates); struct wpa_bss_anqp * wpa_bss_anqp_alloc(void); int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss); -const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss); +const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss); int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab); static inline int bss_is_dmg(const struct wpa_bss *bss) From 95edd81441bf80b1560ff04d3506d3490d9c1429 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Nov 2020 16:00:21 +0200 Subject: [PATCH 1062/1105] BSS: Add wpa_bss_get_ie_ext() wrapper This removes need from the callers to know the struct wpa_bss details for the location of the memory area for storing the IEs. Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 15 +++++++++++++++ wpa_supplicant/bss.h | 1 + wpa_supplicant/ctrl_iface.c | 3 +-- wpa_supplicant/wpa_supplicant.c | 4 ++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 7e420485f..c64ddbced 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -1143,6 +1143,21 @@ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie) } +/** + * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry + * @bss: BSS table entry + * @ext: Information element extension identifier (WLAN_EID_EXT_*) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the BSS + * entry. + */ +const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext) +{ + return get_ie_ext((const u8 *) (bss + 1), bss->ie_len, ext); +} + + /** * wpa_bss_get_vendor_ie - Fetch a vendor information element from a BSS entry * @bss: BSS table entry diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index e49858d19..b3d574eee 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -137,6 +137,7 @@ struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id); struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, unsigned int idf, unsigned int idl); const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); +const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext); const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, u32 vendor_type); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index aeea5ddbc..fcae260b9 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -3030,8 +3030,7 @@ static int wpa_supplicant_ctrl_iface_scan_result( if (bss_is_dmg(bss)) { const char *s; - if (get_ie_ext((const u8 *) (bss + 1), bss->ie_len, - WLAN_EID_EXT_EDMG_OPERATION)) { + if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) { ret = os_snprintf(pos, end - pos, "[EDMG]"); if (os_snprintf_error(end - pos, ret)) return -1; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ba7c23fa9..b51e31785 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3640,8 +3640,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) } if (bss && ssid->enable_edmg) - edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len, - WLAN_EID_EXT_EDMG_OPERATION); + edmg_ie_oper = wpa_bss_get_ie_ext(bss, + WLAN_EID_EXT_EDMG_OPERATION); else edmg_ie_oper = NULL; From be7ee264f65498f616a87e1b439ae0190de0dda3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Nov 2020 16:21:56 +0200 Subject: [PATCH 1063/1105] BSS: Use wrapper function for getting a pointer to the IE buffer This makes it easier to change the internal struct wpa_bss design for storing the variable length IE buffers. Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 19 +++++++++---------- wpa_supplicant/bss.h | 5 +++++ wpa_supplicant/ctrl_iface.c | 13 +++++++------ wpa_supplicant/events.c | 4 ++-- wpa_supplicant/op_classes.c | 5 +++-- wpa_supplicant/p2p_supplicant.c | 6 +++--- wpa_supplicant/rrm.c | 10 +++++----- wpa_supplicant/wpa_supplicant.c | 3 +-- 8 files changed, 35 insertions(+), 30 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index c64ddbced..93ef6fe14 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -361,8 +361,7 @@ static bool is_p2p_pending_bss(struct wpa_supplicant *wpa_s, ETH_ALEN) == 0) return true; if (!is_zero_ether_addr(wpa_s->pending_join_dev_addr) && - p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, - addr) == 0 && + p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) == 0 && os_memcmp(addr, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0) return true; #endif /* CONFIG_P2P */ @@ -568,7 +567,7 @@ static u32 wpa_bss_compare_res(const struct wpa_bss *old, changes |= WPA_BSS_MODE_CHANGED_FLAG; if (old->ie_len == new_res->ie_len && - os_memcmp(old + 1, new_res + 1, old->ie_len) == 0) + os_memcmp(wpa_bss_ie_ptr(old), new_res + 1, old->ie_len) == 0) return changes; changes |= WPA_BSS_IES_CHANGED_FLAG; @@ -1075,7 +1074,7 @@ struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, *found = NULL; dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) { u8 addr[ETH_ALEN]; - if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, + if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) != 0 || os_memcmp(addr, dev_addr, ETH_ALEN) != 0) continue; @@ -1139,7 +1138,7 @@ struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, */ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie) { - return get_ie((const u8 *) (bss + 1), bss->ie_len, ie); + return get_ie(wpa_bss_ie_ptr(bss), bss->ie_len, ie); } @@ -1154,7 +1153,7 @@ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie) */ const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext) { - return get_ie_ext((const u8 *) (bss + 1), bss->ie_len, ext); + return get_ie_ext(wpa_bss_ie_ptr(bss), bss->ie_len, ext); } @@ -1172,7 +1171,7 @@ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) const u8 *ies; const struct element *elem; - ies = (const u8 *) (bss + 1); + ies = wpa_bss_ie_ptr(bss); for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, bss->ie_len) { if (elem->datalen >= 4 && @@ -1205,7 +1204,7 @@ const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, if (bss->beacon_ie_len == 0) return NULL; - ies = (const u8 *) (bss + 1); + ies = wpa_bss_ie_ptr(bss); ies += bss->ie_len; for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, @@ -1239,7 +1238,7 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, if (buf == NULL) return NULL; - pos = (const u8 *) (bss + 1); + pos = wpa_bss_ie_ptr(bss); end = pos + bss->ie_len; while (end - pos > 1) { @@ -1288,7 +1287,7 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss, if (buf == NULL) return NULL; - pos = (const u8 *) (bss + 1); + pos = wpa_bss_ie_ptr(bss); pos += bss->ie_len; end = pos + bss->beacon_ie_len; diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index b3d574eee..a918bc356 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -113,6 +113,11 @@ struct wpa_bss { /* followed by beacon_ie_len octets of IEs */ }; +static inline const u8 * wpa_bss_ie_ptr(const struct wpa_bss *bss) +{ + return (const u8 *) (bss + 1); +} + void wpa_bss_update_start(struct wpa_supplicant *wpa_s); void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s, struct wpa_scan_res *res, diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index fcae260b9..1f9172332 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5022,7 +5022,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, return 0; pos += ret; - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); for (i = 0; i < bss->ie_len; i++) { ret = os_snprintf(pos, end - pos, "%02x", *ie++); if (os_snprintf_error(end - pos, ret)) @@ -5189,7 +5189,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #ifdef CONFIG_WPS if (mask & WPA_BSS_MASK_WPS_SCAN) { - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); if (ret >= end - pos) return 0; @@ -5200,7 +5200,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #ifdef CONFIG_P2P if (mask & WPA_BSS_MASK_P2P_SCAN) { - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); if (ret >= end - pos) return 0; @@ -5212,7 +5212,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #ifdef CONFIG_WIFI_DISPLAY if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { struct wpabuf *wfd; - ie = (const u8 *) (bss + 1); + + ie = wpa_bss_ie_ptr(bss); wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, WFD_IE_VENDOR_TYPE); if (wfd) { @@ -5290,7 +5291,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #ifdef CONFIG_MESH if (mask & WPA_BSS_MASK_MESH_SCAN) { - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end); if (ret >= end - pos) return 0; @@ -5337,7 +5338,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, return 0; pos += ret; - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); ie += bss->ie_len; for (i = 0; i < bss->beacon_ie_len; i++) { ret = os_snprintf(pos, end - pos, "%02x", *ie++); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index b53746b70..89e6e7306 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1852,7 +1852,7 @@ wpas_get_est_throughput_from_bss_snr(const struct wpa_supplicant *wpa_s, const struct wpa_bss *bss, int snr) { int rate = wpa_bss_get_max_rate(bss); - const u8 *ies = (const void *) (bss + 1); + const u8 *ies = wpa_bss_ie_ptr(bss); size_t ie_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; return wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr); @@ -3029,7 +3029,7 @@ static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s, if (!bss) return; - ieprb = (const u8 *) (bss + 1); + ieprb = wpa_bss_ie_ptr(bss); iebcn = ieprb + bss->ie_len; if (!wpas_fst_update_mbie(wpa_s, ieprb, bss->ie_len)) diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c index 461ae5458..b4c0c8a0b 100644 --- a/wpa_supplicant/op_classes.c +++ b/wpa_supplicant/op_classes.c @@ -424,12 +424,13 @@ static int wpas_sta_secondary_channel_offset(struct wpa_bss *bss, u8 *current, u8 *channel) { - u8 *ies, phy_type; + const u8 *ies; + u8 phy_type; size_t ies_len; if (!bss) return -1; - ies = (u8 *) (bss + 1); + ies = wpa_bss_ie_ptr(bss); ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; return wpas_get_op_chan_phy(bss->freq, ies, ies_len, current, channel, &phy_type); diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 75e62a9e9..9bcce8c6c 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1107,9 +1107,9 @@ static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s, "group is persistent - BSS " MACSTR " did not include P2P IE", MAC2STR(bssid)); wpa_hexdump(MSG_DEBUG, "P2P: Probe Response IEs", - (u8 *) (bss + 1), bss->ie_len); + wpa_bss_ie_ptr(bss), bss->ie_len); wpa_hexdump(MSG_DEBUG, "P2P: Beacon IEs", - ((u8 *) bss + 1) + bss->ie_len, + wpa_bss_ie_ptr(bss) + bss->ie_len, bss->beacon_ie_len); return 0; } @@ -5200,7 +5200,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency " "from BSS table: %d MHz (SSID %s)", freq, wpa_ssid_txt(bss->ssid, bss->ssid_len)); - if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, + if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, dev_addr) == 0 && os_memcmp(wpa_s->pending_join_dev_addr, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0 && diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c index f08726636..a9c7b90fd 100644 --- a/wpa_supplicant/rrm.c +++ b/wpa_supplicant/rrm.c @@ -775,10 +775,10 @@ int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, static int wpas_beacon_rep_add_frame_body(struct bitfield *eids, enum beacon_report_detail detail, struct wpa_bss *bss, u8 *buf, - size_t buf_len, u8 **ies_buf, + size_t buf_len, const u8 **ies_buf, size_t *ie_len, int add_fixed) { - u8 *ies = *ies_buf; + const u8 *ies = *ies_buf; size_t ies_len = *ie_len; u8 *pos = buf; int rem_len; @@ -860,7 +860,7 @@ static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data, struct wpa_bss *bss, struct wpabuf **wpa_buf, struct rrm_measurement_beacon_report *rep, - u8 **ie, size_t *ie_len, u8 idx) + const u8 **ie, size_t *ie_len, u8 idx) { int ret; u8 *buf, *pos; @@ -927,8 +927,8 @@ static int wpas_add_beacon_rep(struct wpa_supplicant *wpa_s, u64 start, u64 parent_tsf) { struct beacon_rep_data *data = &wpa_s->beacon_rep_data; - u8 *ies = (u8 *) (bss + 1); - u8 *pos = ies; + const u8 *ies = wpa_bss_ie_ptr(bss); + const u8 *pos = ies; size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; struct rrm_measurement_beacon_report rep; u8 idx = 0; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index b51e31785..5cf45b4ff 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2276,8 +2276,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, #ifdef CONFIG_TDLS if (bss) - wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1), - bss->ie_len); + wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len); #endif /* CONFIG_TDLS */ #ifdef CONFIG_MBO From 454ebb504c7efd604ef482b6c8f71aed132e754d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Nov 2020 16:25:17 +0200 Subject: [PATCH 1064/1105] BSS: Use variable length array for IEs at the end of struct wpa_bss Replace the previously used design "(u8 *) (bss + 1)" with a variable length array at the end of struct wpa_bss bss->ies[] in hopes of making this easier to understand for static analyzers. Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.c | 6 +++--- wpa_supplicant/bss.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 93ef6fe14..e9c2f822c 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -464,7 +464,7 @@ static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s, bss->ssid_len = ssid_len; bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; - os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); + os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len); wpa_bss_set_hessid(bss); if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count && @@ -691,7 +691,7 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #endif /* CONFIG_P2P */ if (bss->ie_len + bss->beacon_ie_len >= res->ie_len + res->beacon_ie_len) { - os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); + os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len); bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; } else { @@ -712,7 +712,7 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, wpa_s->current_bss = nbss; wpa_bss_update_pending_connect(wpa_s, bss, nbss); bss = nbss; - os_memcpy(bss + 1, res + 1, + os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len); bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index a918bc356..c68a3e576 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -111,11 +111,12 @@ struct wpa_bss { size_t beacon_ie_len; /* followed by ie_len octets of IEs */ /* followed by beacon_ie_len octets of IEs */ + u8 ies[]; }; static inline const u8 * wpa_bss_ie_ptr(const struct wpa_bss *bss) { - return (const u8 *) (bss + 1); + return bss->ies; } void wpa_bss_update_start(struct wpa_supplicant *wpa_s); From 90ca804e479b5013b0b410dc4d2c6bce6e1d0797 Mon Sep 17 00:00:00 2001 From: Srinivas Girigowda Date: Wed, 28 Oct 2020 14:42:50 -0700 Subject: [PATCH 1065/1105] Add vendor attributes for TWT nudge request TWT nudge is a combination of suspend and resume in a single request. Add TWT nudge operation and QCA vendor attributes to support the TWT nudge request. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 096757e41..cd7f6f9a3 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7801,6 +7801,12 @@ enum qca_wlan_vendor_attr_wifi_test_config { * @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are * configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_resume. Valid only after the TWT session is setup. + * + * @QCA_WLAN_TWT_NUDGE: Suspend and resume the TWT session. TWT nudge is a + * combination of suspend and resume in a single request. Required parameters + * are configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the + * enum qca_wlan_vendor_attr_twt_nudge. Valid only after the TWT session is + * setup. */ enum qca_wlan_twt_operation { QCA_WLAN_TWT_SET = 0, @@ -7808,6 +7814,7 @@ enum qca_wlan_twt_operation { QCA_WLAN_TWT_TERMINATE = 2, QCA_WLAN_TWT_SUSPEND = 3, QCA_WLAN_TWT_RESUME = 4, + QCA_WLAN_TWT_NUDGE = 5, }; /** @@ -8082,6 +8089,7 @@ enum qca_wlan_vendor_attr_nan_params { * 2. TWT TERMINATE Response * 3. TWT SUSPEND Response * 4. TWT RESUME Response + * 5. TWT NUDGE Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE: Required (u8) * This field is applicable for TWT response only. @@ -8231,6 +8239,44 @@ enum qca_wlan_vendor_attr_twt_resume { QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST - 1, }; +/** + * enum qca_wlan_vendor_attr_twt_nudge - Represents attributes for + * TWT (Target Wake Time) nudge request. TWT nudge is a combination of suspend + * and resume in a single request. These attributes are sent as part of + * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID: Required (u8) + * Flow ID is the unique identifier for each TWT session. This attribute + * represents the respective TWT session to suspend and resume. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME: Required (u32) + * This attribute is used as the SP offset which is the offset from + * TSF after which the wake happens. The units are in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE: Required (u32) + * This attribute represents the next TWT subfield size. + * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits, + * and 4 for 64 bits. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer to which TWT Suspend and Resume is + * being sent. This is used in AP mode to represent the respective + * client and is a required parameter. In STA mode, this is an optional + * parameter. + */ +enum qca_wlan_vendor_attr_twt_nudge { + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID = 1, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME = 2, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE = 3, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR = 4, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX = + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST - 1, +}; + /** * enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by * the TWT responder From 1c77f3d3f9a34200649c165508566b910a940683 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 23 Nov 2020 20:32:26 +0200 Subject: [PATCH 1066/1105] Indicate whether additional ANQP elements were protected Store information on whether extra ANQP elements were received using the protection alternative (protected GAS during an association using PMF) and make this available through the control interface BSS command. For example: anqp[277]= protected-anqp-info[277]=1 Signed-off-by: Jouni Malinen --- wpa_supplicant/bss.h | 1 + wpa_supplicant/ctrl_iface.c | 8 ++++++++ wpa_supplicant/interworking.c | 12 ++++++++---- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index c68a3e576..7cb1745db 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -23,6 +23,7 @@ struct wpa_scan_res; struct wpa_bss_anqp_elem { struct dl_list list; u16 infoid; + bool protected; /* received in a protected GAS response */ struct wpabuf *payload; }; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 1f9172332..8306950a5 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5285,6 +5285,14 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, os_snprintf(title, sizeof(title), "anqp[%u]", elem->infoid); pos = anqp_add_hex(pos, end, title, elem->payload); + if (elem->protected) { + ret = os_snprintf(pos, end - pos, + "protected-anqp-info[%u]=1\n", + elem->infoid); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } } } #endif /* CONFIG_INTERWORKING */ diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index ce11491b9..5f9d1dced 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -2831,7 +2831,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, int freq, static void anqp_add_extra(struct wpa_supplicant *wpa_s, struct wpa_bss_anqp *anqp, u16 info_id, - const u8 *data, size_t slen) + const u8 *data, size_t slen, bool protected) { struct wpa_bss_anqp_elem *tmp, *elem = NULL; @@ -2856,6 +2856,7 @@ static void anqp_add_extra(struct wpa_supplicant *wpa_s, wpabuf_free(elem->payload); } + elem->protected = protected; elem->payload = wpabuf_alloc_copy(data, slen); if (!elem->payload) { dl_list_del(&elem->list); @@ -2898,6 +2899,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, const u8 *pos = data; struct wpa_bss_anqp *anqp = NULL; u8 type; + bool protected; if (bss) anqp = bss->anqp; @@ -2998,9 +3000,10 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, case ANQP_VENUE_URL: wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL", MAC2STR(sa)); - anqp_add_extra(wpa_s, anqp, info_id, pos, slen); + protected = pmf_in_use(wpa_s, sa); + anqp_add_extra(wpa_s, anqp, info_id, pos, slen, protected); - if (!pmf_in_use(wpa_s, sa)) { + if (!protected) { wpa_printf(MSG_DEBUG, "ANQP: Ignore Venue URL since PMF was not enabled"); break; @@ -3052,7 +3055,8 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, default: wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Unsupported ANQP Info ID %u", info_id); - anqp_add_extra(wpa_s, anqp, info_id, data, slen); + anqp_add_extra(wpa_s, anqp, info_id, data, slen, + pmf_in_use(wpa_s, sa)); break; } } From ff7cae34447c939d15a70bdcbcc17d89b37f2d2f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 23 Nov 2020 20:35:00 +0200 Subject: [PATCH 1067/1105] tests: ANQP protection indication Signed-off-by: Jouni Malinen --- tests/hwsim/test_gas.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/hwsim/test_gas.py b/tests/hwsim/test_gas.py index 5d60779e9..cb4a1a8d6 100644 --- a/tests/hwsim/test_gas.py +++ b/tests/hwsim/test_gas.py @@ -1670,6 +1670,11 @@ def test_gas_anqp_venue_url(dev, apdev): if not bss['anqp_capability_list'].startswith(binascii.hexlify(ids).decode()): raise Exception("Unexpected Capability List ANQP-element value: " + bss['anqp_capability_list']) + if "anqp[277]" not in bss: + raise Exception("Venue-URL ANQP info not available") + if "protected-anqp-info[277]" in bss: + raise Exception("Unexpected Venue-URL protection info") + def test_gas_anqp_venue_url2(dev, apdev): """GAS/ANQP and Venue URL (hostapd venue_url)""" venue_group = 1 @@ -1775,6 +1780,14 @@ def test_gas_anqp_venue_url_pmf(dev, apdev): if "2 " + url2 not in ev: raise Exception("Unexpected Venue URL information (2): " + ev) + bss = dev[0].get_bss(bssid) + if "anqp[277]" not in bss: + raise Exception("Venue-URL ANQP info not available") + if "protected-anqp-info[277]" not in bss: + raise Exception("Venue-URL protection info not available") + if bss["protected-anqp-info[277]"] != "1": + raise Exception("Venue-URL was not indicated to be protected") + def test_gas_anqp_capab_list(dev, apdev): """GAS/ANQP and Capability List ANQP-element""" params = {"ssid": "gas/anqp", From 5b782ff620002c21f193034ab911e6524b31785a Mon Sep 17 00:00:00 2001 From: Arun Kumar Khandavalli Date: Fri, 20 Nov 2020 17:16:11 +0530 Subject: [PATCH 1068/1105] Add bus failure reason code to vendor indication Add bus failure hang reason code in enum qca_wlan_vendor_hang_reason. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index cd7f6f9a3..d4c1da7e8 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -6300,6 +6300,8 @@ enum qca_wlan_vendor_hang_reason { QCA_WLAN_HANG_REG_WRITE_FAILURE = 24, /* No credit left to send the wow_wakeup_from_sleep to firmware */ QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25, + /* Bus failure */ + QCA_WLAN_HANG_BUS_FAILURE = 26, }; /** From ed24bad1d98d50f94e024f71093cdbd76cc0d872 Mon Sep 17 00:00:00 2001 From: Sreeramya Soratkal Date: Wed, 18 Nov 2020 16:21:29 +0530 Subject: [PATCH 1069/1105] AP: Check driver support while auto-selecting bandwidth for AP/P2P GO If the maximum operating channel width for AP/P2P GO is not specified, it is auto-selected during configuration. While selecting the channel width, if VHT is supported and 160 MHz channels are available, 160 MHz channel width is preferred to 80 MHz. During the selection of the channel width, the corresponding driver capabilities were not checked. As a result, the AP/P2P GO configuration was set to use the available 160 MHz channels even if the driver did not have capability to support the 160 MHz channel width causing failure to start the AP/P2P GO. Fix this by checking the driver support for the 160 MHz channel width while selecting the channel width for AP/P2P GO. Signed-off-by: Sreeramya Soratkal --- wpa_supplicant/ap.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index a4892e788..ac88a7dc9 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -44,6 +44,27 @@ static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); #endif /* CONFIG_WPS */ +static bool is_chanwidth160_supported(struct hostapd_hw_modes *mode, + struct hostapd_config *conf) +{ +#ifdef CONFIG_IEEE80211AX + if (conf->ieee80211ax) { + struct he_capabilities *he_cap; + + he_cap = &mode->he_capab[IEEE80211_MODE_AP]; + if (he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + (HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G | + HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)) + return true; + } +#endif /* CONFIG_IEEE80211AX */ + if (mode->vht_capab & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | + VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) + return true; + return false; +} + + static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_config *conf, @@ -105,7 +126,7 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, */ hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ); center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel); - if (center_chan) { + if (center_chan && is_chanwidth160_supported(mode, conf)) { wpa_printf(MSG_DEBUG, "VHT center channel %u for auto-selected 160 MHz bandwidth", center_chan); From 0ea870324e0697c17958e67f88b692ce985d2cd2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 23 Nov 2020 21:02:03 +0200 Subject: [PATCH 1070/1105] tests: Use helper functions for PSK ext EAPOL-Key processing Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_psk.py | 100 ++++++++++--------------------------- 1 file changed, 26 insertions(+), 74 deletions(-) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index c4a8b9e2e..9bc141453 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -668,30 +668,34 @@ def test_ap_wpa2_ext_add_to_bridge(dev, apdev): hostapd.cmd_execute(apdev[0], ['brctl', 'delif', br_ifname, ifname]) hostapd.cmd_execute(apdev[0], ['brctl', 'delbr', br_ifname]) -def test_ap_wpa2_psk_ext(dev, apdev): - """WPA2-PSK AP using external EAPOL I/O""" - bssid = apdev[0]['bssid'] +def setup_psk_ext(dev, apdev, wpa_ptk_rekey=None): ssid = "test-wpa2-psk" passphrase = 'qwertyuiop' psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' params = hostapd.wpa2_params(ssid=ssid) params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) + if wpa_ptk_rekey: + params['wpa_ptk_rekey'] = wpa_ptk_rekey + hapd = hostapd.add_ap(apdev, params) hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) - addr = dev[0].p2p_interface_addr() + dev.request("SET ext_eapol_frame_io 1") + dev.connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) + return hapd + +def ext_4way_hs(hapd, dev): + bssid = hapd.own_addr() + addr = dev.own_addr() while True: ev = hapd.wait_event(["EAPOL-TX", "AP-STA-CONNECTED"], timeout=15) if ev is None: raise Exception("Timeout on EAPOL-TX from hostapd") if "AP-STA-CONNECTED" in ev: - dev[0].wait_connected(timeout=15) + dev.wait_connected(timeout=15) break - res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2]) + res = dev.request("EAPOL_RX " + bssid + " " + ev.split(' ')[2]) if "OK" not in res: raise Exception("EAPOL_RX to wpa_supplicant failed") - ev = dev[0].wait_event(["EAPOL-TX", "CTRL-EVENT-CONNECTED"], timeout=15) + ev = dev.wait_event(["EAPOL-TX", "CTRL-EVENT-CONNECTED"], timeout=15) if ev is None: raise Exception("Timeout on EAPOL-TX from wpa_supplicant") if "CTRL-EVENT-CONNECTED" in ev: @@ -700,18 +704,15 @@ def test_ap_wpa2_psk_ext(dev, apdev): if "OK" not in res: raise Exception("EAPOL_RX to hostapd failed") +def test_ap_wpa2_psk_ext(dev, apdev): + """WPA2-PSK AP using external EAPOL I/O""" + hapd = setup_psk_ext(dev[0], apdev[0]) + ext_4way_hs(hapd, dev[0]) + def test_ap_wpa2_psk_ext_retry_msg_3(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -769,16 +770,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3(dev, apdev): def test_ap_wpa2_psk_ext_retry_msg_3b(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4 (b)""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -844,16 +837,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3b(dev, apdev): def test_ap_wpa2_psk_ext_retry_msg_3c(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4 (c)""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -936,16 +921,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3c(dev, apdev): def test_ap_wpa2_psk_ext_retry_msg_3d(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4 (d)""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -1031,16 +1008,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3d(dev, apdev): def test_ap_wpa2_psk_ext_retry_msg_3e(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4 (e)""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -1137,17 +1106,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3e(dev, apdev): def test_ap_wpa2_psk_ext_delayed_ptk_rekey(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and delayed PTK rekey exchange""" + hapd = setup_psk_ext(dev[0], apdev[0], wpa_ptk_rekey="3") bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - params['wpa_ptk_rekey'] = '3' - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -2700,16 +2660,8 @@ def test_ap_wpa2_psk_ifdown(dev, apdev): def test_ap_wpa2_psk_drop_first_msg_4(dev, apdev): """WPA2-PSK and first EAPOL-Key msg 4/4 dropped""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].own_addr() # EAPOL-Key msg 1/4 From 1759a8e3f36a40b20e7c7df06c6d1afc5d1c30c7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 23 Nov 2020 21:28:19 +0200 Subject: [PATCH 1071/1105] tests: WPA2-PSK and supplicant receiving unexpected EAPOL-Key frames Signed-off-by: Jouni Malinen --- tests/hwsim/test_ap_psk.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index 9bc141453..db10377a4 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -685,6 +685,8 @@ def setup_psk_ext(dev, apdev, wpa_ptk_rekey=None): def ext_4way_hs(hapd, dev): bssid = hapd.own_addr() addr = dev.own_addr() + first = None + last = None while True: ev = hapd.wait_event(["EAPOL-TX", "AP-STA-CONNECTED"], timeout=15) if ev is None: @@ -692,6 +694,9 @@ def ext_4way_hs(hapd, dev): if "AP-STA-CONNECTED" in ev: dev.wait_connected(timeout=15) break + if not first: + first = ev.split(' ')[2] + last = ev.split(' ')[2] res = dev.request("EAPOL_RX " + bssid + " " + ev.split(' ')[2]) if "OK" not in res: raise Exception("EAPOL_RX to wpa_supplicant failed") @@ -703,12 +708,41 @@ def ext_4way_hs(hapd, dev): res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2]) if "OK" not in res: raise Exception("EAPOL_RX to hostapd failed") + return first, last def test_ap_wpa2_psk_ext(dev, apdev): """WPA2-PSK AP using external EAPOL I/O""" hapd = setup_psk_ext(dev[0], apdev[0]) ext_4way_hs(hapd, dev[0]) +def test_ap_wpa2_psk_unexpected(dev, apdev): + """WPA2-PSK and supplicant receiving unexpected EAPOL-Key frames""" + hapd = setup_psk_ext(dev[0], apdev[0]) + first, last = ext_4way_hs(hapd, dev[0]) + + # Not associated - Delay processing of received EAPOL frame (state=COMPLETED + # bssid=02:00:00:00:03:00) + other = "02:11:22:33:44:55" + res = dev[0].request("EAPOL_RX " + other + " " + first) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + # WPA: EAPOL-Key Replay Counter did not increase - dropping packet + bssid = hapd.own_addr() + res = dev[0].request("EAPOL_RX " + bssid + " " + last) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + # WPA: Invalid EAPOL-Key MIC - dropping packet + msg = last[0:18] + '01' + last[20:] + res = dev[0].request("EAPOL_RX " + bssid + " " + msg) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=12) + if ev is not None: + raise Exception("Unexpected disconnection") + def test_ap_wpa2_psk_ext_retry_msg_3(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4""" hapd = setup_psk_ext(dev[0], apdev[0]) From 3c9abc7858ee27a3adb56f14ceb6a916fbe24114 Mon Sep 17 00:00:00 2001 From: Sachin Ahuja Date: Mon, 23 Nov 2020 16:57:40 +0530 Subject: [PATCH 1072/1105] QCA vendor attributes to configure TX and RX NSS Define QCA vendor attributes to dynamically configure TX NSS and RX NSS to be used with QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION commands. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index d4c1da7e8..96b3b0526 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -2300,6 +2300,10 @@ enum qca_wlan_vendor_attr_config { * frame. The updated NSS value after the connection shall not be * greater than the one negotiated during the connection. Any such * higher value configuration shall be returned with a failure. + * Only symmetric NSS configuration (such as 2X2 or 1X1) can be done + * using this attribute. QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS and + * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attributes shall be used to + * configure the asymmetric NSS configuration (such as 1X2). */ QCA_WLAN_VENDOR_ATTR_CONFIG_NSS = 70, /* 8-bit unsigned value to trigger Optimized Power Management: @@ -2348,6 +2352,46 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL = 76, + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of spatial streams used for transmitting the data. When + * configured in the disconnected state, the configured value will + * be considered for the following connection attempt. + * If the NSS is updated after the connection, the updated NSS value + * is notified to the peer using the Operating Mode Notification/Spatial + * Multiplexing Power Save frame. + * The TX NSS value configured after the connection shall not be greater + * than the value negotiated during the connection. Any such higher + * value configuration shall be treated as invalid configuration by + * the driver. This attribute shall be configured along with + * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute to define the symmetric + * configuration (such as 2X2 or 1X1) or the asymmetric + * configuration (such as 1X2). + * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along + * with this QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute the driver + * will update the TX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS = 77, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of spatial streams used for receiving the data. When + * configured in the disconnected state, the configured value will + * be considered for the following connection attempt. + * If the NSS is updated after the connection, the updated NSS value + * is notified to the peer using the Operating Mode Notification/Spatial + * Multiplexing Power Save frame. + * The RX NSS value configured after the connection shall not be greater + * than the value negotiated during the connection. Any such higher + * value configuration shall be treated as invalid configuration by + * the driver. This attribute shall be configured along with + * QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute to define the symmetric + * configuration (such as 2X2 or 1X1) or the asymmetric + * configuration (such as 1X2). + * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along + * with this QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute the driver + * will update the RX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78, + /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = From f1df4fbfc7ad3d8c18a8c9fe5c71628f2ed09bb7 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Tue, 30 Jun 2020 14:18:56 +0200 Subject: [PATCH 1073/1105] mesh: Use setup completion callback to complete mesh join Mesh join function is the last function to be called during mesh join process, but it's been called a bit earlier than it's supposed to be, so that some mesh parameter values such as VHT capabilities were not applied correct when mesh join is in process. Moreover, the current design of mesh join that is called directly after mesh initialization isn't suitable for DFS channels to use, since mesh join process should be paused until DFS CAC is done and resumed after it's done. The callback will be called by hostapd_setup_interface_complete_sync(). There is a possibility that completing mesh init fails, so add error handling codes for that. Signed-off-by: Peter Oh --- src/ap/hostapd.c | 11 ++++++++++- wpa_supplicant/mesh.c | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index b37f49f9a..38212305e 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -434,6 +434,8 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd) #ifdef CONFIG_MESH wpabuf_free(hapd->mesh_pending_auth); hapd->mesh_pending_auth = NULL; + /* handling setup failure is already done */ + hapd->setup_complete_cb = NULL; #endif /* CONFIG_MESH */ hostapd_clean_rrm(hapd); @@ -2156,6 +2158,13 @@ dfs_offload: if (hapd->setup_complete_cb) hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); +#ifdef CONFIG_MESH + if (delay_apply_cfg && !iface->mconf) { + wpa_printf(MSG_ERROR, "Error while completing mesh init"); + goto fail; + } +#endif /* CONFIG_MESH */ + wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", iface->bss[0]->conf->iface); if (iface->interfaces && iface->interfaces->terminate_on_error > 0) @@ -2299,7 +2308,7 @@ int hostapd_setup_interface(struct hostapd_iface *iface) ret = setup_interface(iface); if (ret) { wpa_printf(MSG_ERROR, "%s: Unable to setup interface.", - iface->bss[0]->conf->iface); + iface->conf ? iface->conf->bss[0]->iface : "N/A"); return -1; } diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 558d87ae2..66f8311f1 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -244,6 +244,14 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) } +static void wpas_mesh_complete_cb(void *arg) +{ + struct wpa_supplicant *wpa_s = arg; + + wpas_mesh_complete(wpa_s); +} + + static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_freq_params *freq) @@ -267,6 +275,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, if (!ifmsh) return -ENOMEM; + ifmsh->owner = wpa_s; ifmsh->drv_flags = wpa_s->drv_flags; ifmsh->drv_flags2 = wpa_s->drv_flags2; ifmsh->num_bss = 1; @@ -285,6 +294,8 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, bss->drv_priv = wpa_s->drv_priv; bss->iface = ifmsh; bss->mesh_sta_free_cb = mesh_mpm_free_sta; + bss->setup_complete_cb = wpas_mesh_complete_cb; + bss->setup_complete_cb_ctx = wpa_s; frequency = ssid->frequency; if (frequency != freq->freq && frequency == freq->freq + freq->sec_channel_offset * 20) { @@ -525,7 +536,6 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, goto out; } - ret = wpas_mesh_complete(wpa_s); out: return ret; } From e3608040c4ebf7c5a5d6b6fd4ca2a4d2143df4cc Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Tue, 30 Jun 2020 14:18:57 +0200 Subject: [PATCH 1074/1105] mesh: Update ssid->frequency as pri/sec channels switch ssid->frequency is one of the variables used to get the channel number from a given frequency. Leaving it as unchanged when pri/sec channel switch will cause picking up a wrong channel number after applying the secondary channel offset for HT40 and leads to failing interface bring-up. Signed-off-by: Peter Oh --- wpa_supplicant/mesh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 66f8311f1..b8fafa5db 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -301,6 +301,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, frequency == freq->freq + freq->sec_channel_offset * 20) { wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched"); frequency = freq->freq; + ssid->frequency = frequency; } wpa_s->assoc_freq = frequency; wpa_s->current_ssid = ssid; From 8725909789555e549d92b1f8f582fa63adb390a5 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Tue, 30 Jun 2020 14:18:59 +0200 Subject: [PATCH 1075/1105] nl80211: Do not set offchanok on DFS channels in non-ETSI for mesh mac80211 does not allow mgmt tx to use off channel on DFS channels in non-ETSI domain, because it will invalidate CAC result on current operating channel. (mac80211 commit: 34373d12f3cbb74960a73431138ef619d857996f) Hence don't set offchanok for mgmt tx in case of DFS channels in non-ETSI. Signed-off-by: Peter Oh --- src/drivers/driver_nl80211.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 94bf98210..60d3557df 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -7950,6 +7950,28 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, os_memset(bss->rand_addr, 0, ETH_ALEN); } +#ifdef CONFIG_MESH + if (is_mesh_interface(drv->nlmode)) { + struct hostapd_hw_modes *modes; + u16 num_modes, flags; + u8 dfs_domain; + int i; + + modes = nl80211_get_hw_feature_data(bss, &num_modes, + &flags, &dfs_domain); + if (dfs_domain != HOSTAPD_DFS_REGION_ETSI && + ieee80211_is_dfs(bss->freq, modes, num_modes)) + offchanok = 0; + if (modes) { + for (i = 0; i < num_modes; i++) { + os_free(modes[i].channels); + os_free(modes[i].rates); + } + os_free(modes); + } + } +#endif /* CONFIG_MESH */ + if (is_ap_interface(drv->nlmode) && (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || (int) freq == bss->freq || drv->device_ap_sme || From a27faf2c9a0c07f6a74420824b941cdc91c33b45 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Tue, 30 Jun 2020 14:19:00 +0200 Subject: [PATCH 1076/1105] mesh: Fix channel switch error during CAC Mesh interface would have used its channel parameters that were configured during initialization even after channel switch due to DFS radar detection during CAC which could result in a channel switch error. Fix the error by updating the channel parameters when channel has been changed from the initial one. Signed-off-by: Peter Oh --- wpa_supplicant/mesh.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index b8fafa5db..ab816b9c9 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -13,6 +13,7 @@ #include "utils/uuid.h" #include "common/ieee802_11_defs.h" #include "common/wpa_ctrl.h" +#include "common/hw_features_common.h" #include "ap/sta_info.h" #include "ap/hostapd.h" #include "ap/ieee802_11.h" @@ -207,6 +208,43 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) return -1; } + /* + * Update channel configuration if the channel has changed since the + * initial setting, i.e., due to DFS radar detection during CAC. + */ + if (ifmsh->freq != params->freq.freq) { + struct he_capabilities *he_capab = NULL; + + wpa_s->assoc_freq = ifmsh->freq; + ssid->frequency = ifmsh->freq; + + if (ifmsh->current_mode) + he_capab = &ifmsh->current_mode->he_capab[ + IEEE80211_MODE_MESH]; + + if (hostapd_set_freq_params( + ¶ms->freq, + ifmsh->conf->hw_mode, + ifmsh->freq, + ifmsh->conf->channel, + ifmsh->conf->enable_edmg, + ifmsh->conf->edmg_channel, + ifmsh->conf->ieee80211n, + ifmsh->conf->ieee80211ac, + ifmsh->conf->ieee80211ax, + ifmsh->conf->secondary_channel, + hostapd_get_oper_chwidth(ifmsh->conf), + hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf), + hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf), + ifmsh->conf->vht_capab, + he_capab)) { + wpa_printf(MSG_ERROR, + "Error updating mesh frequency params"); + wpa_supplicant_mesh_deinit(wpa_s); + return -1; + } + } + if (ifmsh->mconf->security != MESH_CONF_SEC_NONE && wpas_mesh_init_rsn(wpa_s)) { wpa_printf(MSG_ERROR, From 12ae3e3dba0e0826a4b181e1e5f1f9fd8708845c Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Tue, 30 Jun 2020 14:19:01 +0200 Subject: [PATCH 1077/1105] mesh: Inform kernel driver about DFS handler in userspace The kernel requires indication of DFS handler residing in user space (NL80211_ATTR_HANDLE_DFS) to enable DFS channels. Signed-off-by: Peter Oh --- src/drivers/driver.h | 1 + src/drivers/driver_nl80211.c | 3 +++ wpa_supplicant/mesh.c | 1 + 3 files changed, 5 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 722e428f1..58a7bd776 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1559,6 +1559,7 @@ struct wpa_driver_mesh_join_params { #define WPA_DRIVER_MESH_FLAG_SAE_AUTH 0x00000004 #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008 unsigned int flags; + bool handle_dfs; }; struct wpa_driver_set_key_params { diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 60d3557df..8ba1bf72f 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -10247,6 +10247,9 @@ static int nl80211_join_mesh(struct i802_bss *bss, wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags); + if (params->handle_dfs && nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS)) + goto fail; + container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP); if (!container) goto fail; diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index ab816b9c9..80de01c8e 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -361,6 +361,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, conf->country[0] = wpa_s->conf->country[0]; conf->country[1] = wpa_s->conf->country[1]; conf->country[2] = ' '; + wpa_s->mesh_params->handle_dfs = true; } bss->iconf = conf; From 06161d4f108905d10c63060c82973ad70a844247 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 14:19:05 +0200 Subject: [PATCH 1078/1105] mesh: Fix mesh_oom test Only change freq params, if ifmsh->freq is set initially, which only happens if hostapd_get_hw_features in setup_interface2 succeeds. Signed-off-by: Markus Theil --- wpa_supplicant/mesh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 80de01c8e..19813aa0d 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -212,7 +212,7 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) * Update channel configuration if the channel has changed since the * initial setting, i.e., due to DFS radar detection during CAC. */ - if (ifmsh->freq != params->freq.freq) { + if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) { struct he_capabilities *he_capab = NULL; wpa_s->assoc_freq = ifmsh->freq; From 0896c442dcd5477ac8c49036c089f728f703df88 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 14:19:02 +0200 Subject: [PATCH 1079/1105] mesh: Fix for mesh init/deinit Send mesh group started notification after join completion callback is called. Implement outstanding TODO, to leave the mesh network on deinit. Signed-off-by: Markus Theil --- wpa_supplicant/mesh.c | 32 ++++++++++++++++++++------------ wpa_supplicant/mesh.h | 6 ++++-- wpa_supplicant/wpa_supplicant.c | 8 ++------ 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 19813aa0d..1acc8f965 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -30,20 +30,20 @@ static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s) { - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh); + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true); wpa_s->ifmsh = NULL; wpa_s->current_ssid = NULL; os_free(wpa_s->mesh_rsn); wpa_s->mesh_rsn = NULL; os_free(wpa_s->mesh_params); wpa_s->mesh_params = NULL; - /* TODO: leave mesh (stop beacon). This will happen on link down - * anyway, so it's not urgent */ + wpa_supplicant_leave_mesh(wpa_s, false); } void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, - struct hostapd_iface *ifmsh) + struct hostapd_iface *ifmsh, + bool also_clear_hostapd) { if (!ifmsh) return; @@ -64,8 +64,10 @@ void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, } /* take care of shared data */ - hostapd_interface_deinit(ifmsh); - hostapd_interface_free(ifmsh); + if (also_clear_hostapd) { + hostapd_interface_deinit(ifmsh); + hostapd_interface_free(ifmsh); + } } @@ -249,8 +251,7 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) wpas_mesh_init_rsn(wpa_s)) { wpa_printf(MSG_ERROR, "mesh: RSN initialization failed - deinit mesh"); - wpa_supplicant_mesh_deinit(wpa_s); - wpa_drv_leave_mesh(wpa_s); + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, false); return -1; } @@ -275,9 +276,15 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) /* hostapd sets the interface down until we associate */ wpa_drv_set_operstate(wpa_s, 1); - if (!ret) + if (!ret) { wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len), + ssid->id); + wpas_notify_mesh_group_started(wpa_s, ssid); + } + return ret; } @@ -571,7 +578,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, wpa_s->mesh_params = params; if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) { wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh"); - wpa_drv_leave_mesh(wpa_s); + wpa_supplicant_leave_mesh(wpa_s, true); ret = -1; goto out; } @@ -581,14 +588,15 @@ out: } -int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s) +int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, bool need_deinit) { int ret = 0; wpa_msg(wpa_s, MSG_INFO, "leaving mesh"); /* Need to send peering close messages first */ - wpa_supplicant_mesh_deinit(wpa_s); + if (need_deinit) + wpa_supplicant_mesh_deinit(wpa_s); ret = wpa_drv_leave_mesh(wpa_s); if (ret) diff --git a/wpa_supplicant/mesh.h b/wpa_supplicant/mesh.h index 7317083c9..a429e5e27 100644 --- a/wpa_supplicant/mesh.h +++ b/wpa_supplicant/mesh.h @@ -11,9 +11,11 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); -int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s); +int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, + bool need_deinit); void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, - struct hostapd_iface *ifmsh); + struct hostapd_iface *ifmsh, + bool also_clear_hostapd); int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end); int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname, diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 5cf45b4ff..ddd43e5d2 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2249,10 +2249,6 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, return; } wpa_s->current_bss = bss; - wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len), - ssid->id); - wpas_notify_mesh_group_started(wpa_s, ssid); #else /* CONFIG_MESH */ wpa_msg(wpa_s, MSG_ERROR, "mesh mode support not included in the build"); @@ -3990,7 +3986,7 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, wpa_s->ifname); wpas_notify_mesh_group_removed(wpa_s, mconf->meshid, mconf->meshid_len, reason_code); - wpa_supplicant_leave_mesh(wpa_s); + wpa_supplicant_leave_mesh(wpa_s, true); } #endif /* CONFIG_MESH */ @@ -6717,7 +6713,7 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, #ifdef CONFIG_MESH if (wpa_s->ifmsh) { - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh); + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true); wpa_s->ifmsh = NULL; } #endif /* CONFIG_MESH */ From 7c2cad969a67453c35422cc6ad1d2803dc27adc1 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 14:19:03 +0200 Subject: [PATCH 1080/1105] mesh: Fix DFS deinit/init The hostapd DFS code deinitializes and initializes the AP interface, if a clean channel switch is not possible. In this case the AP code paths would deinit the driver, for example nl80211, without wpa_supplicant code paths getting notice of this. Therefore add callbacks for wpa_supplicant mesh methods, which are called on init/deinit of the AP BSS. These callbacks are then used to handle the reset in the mesh code. Signed-off-by: Markus Theil --- src/ap/dfs.c | 7 +++- src/ap/hostapd.c | 15 +++++-- src/ap/hostapd.h | 6 +++ wpa_supplicant/mesh.c | 94 ++++++++++++++++++++++++++++++++++++++----- 4 files changed, 107 insertions(+), 15 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index f04a00af0..15ef50bce 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -1032,6 +1032,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) int err = 1; struct hostapd_hw_modes *cmode = iface->current_mode; u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); + int ieee80211_mode = IEEE80211_MODE_AP; wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", __func__, iface->cac_started ? "yes" : "no", @@ -1099,6 +1100,10 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) os_memset(&csa_settings, 0, sizeof(csa_settings)); csa_settings.cs_count = 5; csa_settings.block_tx = 1; +#ifdef CONFIG_MESH + if (iface->mconf) + ieee80211_mode = IEEE80211_MODE_MESH; +#endif /* CONFIG_MESH */ err = hostapd_set_freq_params(&csa_settings.freq_params, iface->conf->hw_mode, channel->freq, @@ -1113,7 +1118,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx, cmode->vht_capab, - &cmode->he_capab[IEEE80211_MODE_AP]); + &cmode->he_capab[ieee80211_mode]); if (err) { wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 38212305e..1de032930 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -354,7 +354,7 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) #endif /* CONFIG_WEP */ -static void hostapd_free_hapd_data(struct hostapd_data *hapd) +void hostapd_free_hapd_data(struct hostapd_data *hapd) { os_free(hapd->probereq_cb); hapd->probereq_cb = NULL; @@ -498,7 +498,7 @@ static void sta_track_deinit(struct hostapd_iface *iface) } -static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) +void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) { wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); #ifdef NEED_AP_MLME @@ -626,7 +626,7 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) } -static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd) +void hostapd_bss_deinit_no_free(struct hostapd_data *hapd) { hostapd_free_stas(hapd); hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); @@ -2690,6 +2690,12 @@ int hostapd_enable_iface(struct hostapd_iface *hapd_iface) { size_t j; + if (!hapd_iface) + return -1; + + if (hapd_iface->enable_iface_cb) + return hapd_iface->enable_iface_cb(hapd_iface); + if (hapd_iface->bss[0]->drv_priv != NULL) { wpa_printf(MSG_ERROR, "Interface %s already enabled", hapd_iface->conf->bss[0]->iface); @@ -2751,6 +2757,9 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface) if (hapd_iface == NULL) return -1; + if (hapd_iface->disable_iface_cb) + return hapd_iface->disable_iface_cb(hapd_iface); + if (hapd_iface->bss[0]->drv_priv == NULL) { wpa_printf(MSG_INFO, "Interface %s already disabled", hapd_iface->conf->bss[0]->iface); diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index b70d13fba..4ce31416d 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -589,6 +589,9 @@ struct hostapd_iface { /* Previous WMM element information */ struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM]; + + int (*enable_iface_cb)(struct hostapd_iface *iface); + int (*disable_iface_cb)(struct hostapd_iface *iface); }; /* hostapd.c */ @@ -617,6 +620,9 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface); int hostapd_enable_iface(struct hostapd_iface *hapd_iface); int hostapd_reload_iface(struct hostapd_iface *hapd_iface); int hostapd_disable_iface(struct hostapd_iface *hapd_iface); +void hostapd_bss_deinit_no_free(struct hostapd_data *hapd); +void hostapd_free_hapd_data(struct hostapd_data *hapd); +void hostapd_cleanup_iface_partial(struct hostapd_iface *iface); int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf); int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf); void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator); diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 1acc8f965..336ae69d0 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -28,15 +28,22 @@ #include "mesh.h" -static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s) +static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s, + bool also_clear_hostapd) { - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true); - wpa_s->ifmsh = NULL; - wpa_s->current_ssid = NULL; + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, + also_clear_hostapd); + + if (also_clear_hostapd) { + wpa_s->ifmsh = NULL; + wpa_s->current_ssid = NULL; + os_free(wpa_s->mesh_params); + wpa_s->mesh_params = NULL; + } + os_free(wpa_s->mesh_rsn); wpa_s->mesh_rsn = NULL; - os_free(wpa_s->mesh_params); - wpa_s->mesh_params = NULL; + wpa_supplicant_leave_mesh(wpa_s, false); } @@ -242,7 +249,7 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) he_capab)) { wpa_printf(MSG_ERROR, "Error updating mesh frequency params"); - wpa_supplicant_mesh_deinit(wpa_s); + wpa_supplicant_mesh_deinit(wpa_s, true); return -1; } } @@ -251,7 +258,7 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) wpas_mesh_init_rsn(wpa_s)) { wpa_printf(MSG_ERROR, "mesh: RSN initialization failed - deinit mesh"); - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, false); + wpa_supplicant_mesh_deinit(wpa_s, false); return -1; } @@ -297,6 +304,69 @@ static void wpas_mesh_complete_cb(void *arg) } +static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh) +{ + struct wpa_supplicant *wpa_s = ifmsh->owner; + struct hostapd_data *bss; + + ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid); + + bss = ifmsh->bss[0]; + bss->msg_ctx = wpa_s; + os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN); + bss->driver = wpa_s->driver; + bss->drv_priv = wpa_s->drv_priv; + bss->iface = ifmsh; + bss->mesh_sta_free_cb = mesh_mpm_free_sta; + bss->setup_complete_cb = wpas_mesh_complete_cb; + bss->setup_complete_cb_ctx = wpa_s; + + bss->conf->start_disabled = 1; + bss->conf->mesh = MESH_ENABLED; + bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity; + + if (wpa_drv_init_mesh(wpa_s)) { + wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver"); + return -1; + } + + if (hostapd_setup_interface(ifmsh)) { + wpa_printf(MSG_ERROR, + "Failed to initialize hostapd interface for mesh"); + return -1; + } + + return 0; +} + + +static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh) +{ + struct wpa_supplicant *wpa_s = ifmsh->owner; + size_t j; + + wpa_supplicant_mesh_deinit(wpa_s, false); + +#ifdef NEED_AP_MLME + for (j = 0; j < ifmsh->num_bss; j++) + hostapd_cleanup_cs_params(ifmsh->bss[j]); +#endif /* NEED_AP_MLME */ + + /* Same as hostapd_interface_deinit() without deinitializing control + * interface */ + for (j = 0; j < ifmsh->num_bss; j++) { + struct hostapd_data *hapd = ifmsh->bss[j]; + + hostapd_bss_deinit_no_free(hapd); + hostapd_free_hapd_data(hapd); + } + + hostapd_cleanup_iface_partial(ifmsh); + + return 0; +} + + static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_freq_params *freq) @@ -324,6 +394,8 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, ifmsh->drv_flags = wpa_s->drv_flags; ifmsh->drv_flags2 = wpa_s->drv_flags2; ifmsh->num_bss = 1; + ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb; + ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb; ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, sizeof(struct hostapd_data *)); if (!ifmsh->bss) @@ -459,7 +531,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, return 0; out_free: - wpa_supplicant_mesh_deinit(wpa_s); + wpa_supplicant_mesh_deinit(wpa_s, true); return -ENOMEM; } @@ -507,7 +579,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, goto out; } - wpa_supplicant_mesh_deinit(wpa_s); + wpa_supplicant_mesh_deinit(wpa_s, true); wpa_s->pairwise_cipher = WPA_CIPHER_NONE; wpa_s->group_cipher = WPA_CIPHER_NONE; @@ -596,7 +668,7 @@ int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, bool need_deinit) /* Need to send peering close messages first */ if (need_deinit) - wpa_supplicant_mesh_deinit(wpa_s); + wpa_supplicant_mesh_deinit(wpa_s, true); ret = wpa_drv_leave_mesh(wpa_s); if (ret) From 3806ad73e120da81912d8201bfbf247f926657fe Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 14:19:04 +0200 Subject: [PATCH 1081/1105] tests: DFS test for mesh Add a test which uses a DFS channel, waits for CAC afterwards successful mesh join and then triggers a radar event and checks if the mesh comes up again on the same device. Signed-off-by: Markus Theil --- tests/hwsim/test_wpas_mesh.py | 57 +++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index b7f98468b..75bc02146 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -80,8 +80,24 @@ def check_mesh_scan(dev, params, other_started=False, beacon_int=0): if '[MESH]' not in bss['flags']: raise Exception("BSS output did not include MESH flag") -def check_mesh_group_added(dev): - ev = dev.wait_event(["MESH-GROUP-STARTED"]) +def check_dfs_started(dev, timeout=10): + ev = dev.wait_event(["DFS-CAC-START"], timeout=timeout) + if ev is None: + raise Exception("Test exception: CAC did not start") + +def check_dfs_finished(dev, timeout=70): + ev = dev.wait_event(["DFS-CAC-COMPLETED"], timeout=timeout) + if ev is None: + raise Exception("Test exception: CAC did not finish") + +def check_mesh_radar_handling_finished(dev, timeout=75): + ev = dev.wait_event(["CTRL-EVENT-CHANNEL-SWITCH", "MESH-GROUP-STARTED"], + timeout=timeout) + if ev is None: + raise Exception("Test exception: Couldn't join mesh") + +def check_mesh_group_added(dev, timeout=10): + ev = dev.wait_event(["MESH-GROUP-STARTED"], timeout=timeout) if ev is None: raise Exception("Test exception: Couldn't join mesh") @@ -91,6 +107,10 @@ def check_mesh_group_removed(dev): if ev is None: raise Exception("Test exception: Couldn't leave mesh") +def check_regdom_change(dev, timeout=10): + ev = dev.wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=timeout) + if ev is None: + raise Exception("Test exception: No regdom change happened.") def check_mesh_peer_connected(dev, timeout=10): ev = dev.wait_event(["MESH-PEER-CONNECTED"], timeout=timeout) @@ -167,6 +187,39 @@ def test_wpas_mesh_group_remove(dev): check_mesh_group_removed(dev[0]) dev[0].mesh_group_remove() +def dfs_simulate_radar(dev): + logger.info("Trigger a simulated radar event") + phyname = dev.get_driver_status_field("phyname") + radar_file = '/sys/kernel/debug/ieee80211/' + phyname + '/hwsim/dfs_simulate_radar' + with open(radar_file, 'w') as f: + f.write('1') + +@long_duration_test +def test_mesh_peer_connected_dfs(dev): + """Mesh peer connected (DFS)""" + dev[0].set("country", "DE") + dev[1].set("country", "DE") + + check_regdom_change(dev[0]) + check_regdom_change(dev[1]) + + check_mesh_support(dev[0]) + add_open_mesh_network(dev[0], freq="5500", beacon_int=160) + add_open_mesh_network(dev[1], freq="5500", beacon_int=160) + check_dfs_started(dev[0]) + check_dfs_finished(dev[0]) + check_mesh_joined_connected(dev, timeout0=10) + + dfs_simulate_radar(dev[0]) + + check_mesh_radar_handling_finished(dev[0], timeout=75) + + dev[0].set("country", "00") + dev[1].set("country", "00") + + check_regdom_change(dev[0]) + check_regdom_change(dev[1]) + def test_wpas_mesh_peer_connected(dev): """wpa_supplicant MESH peer connected""" check_mesh_support(dev[0]) From 89ad24379d4a1c1decdb8ee693ffc50fcc5b4c1a Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 14:19:06 +0200 Subject: [PATCH 1082/1105] mesh: Move mesh frequency setting to its own function Signed-off-by: Markus Theil --- wpa_supplicant/mesh.c | 62 ++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 336ae69d0..df204478b 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -204,6 +204,40 @@ static int wpas_mesh_init_rsn(struct wpa_supplicant *wpa_s) } +static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s) +{ + struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params; + struct hostapd_iface *ifmsh = wpa_s->ifmsh; + struct he_capabilities *he_capab = NULL; + + if (ifmsh->current_mode) + he_capab = &ifmsh->current_mode->he_capab[IEEE80211_MODE_MESH]; + + if (hostapd_set_freq_params( + ¶ms->freq, + ifmsh->conf->hw_mode, + ifmsh->freq, + ifmsh->conf->channel, + ifmsh->conf->enable_edmg, + ifmsh->conf->edmg_channel, + ifmsh->conf->ieee80211n, + ifmsh->conf->ieee80211ac, + ifmsh->conf->ieee80211ax, + ifmsh->conf->secondary_channel, + hostapd_get_oper_chwidth(ifmsh->conf), + hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf), + hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf), + ifmsh->conf->vht_capab, + he_capab)) { + wpa_printf(MSG_ERROR, "Error updating mesh frequency params"); + wpa_supplicant_mesh_deinit(wpa_s, true); + return -1; + } + + return 0; +} + + static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) { struct hostapd_iface *ifmsh = wpa_s->ifmsh; @@ -222,36 +256,10 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) * initial setting, i.e., due to DFS radar detection during CAC. */ if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) { - struct he_capabilities *he_capab = NULL; - wpa_s->assoc_freq = ifmsh->freq; ssid->frequency = ifmsh->freq; - - if (ifmsh->current_mode) - he_capab = &ifmsh->current_mode->he_capab[ - IEEE80211_MODE_MESH]; - - if (hostapd_set_freq_params( - ¶ms->freq, - ifmsh->conf->hw_mode, - ifmsh->freq, - ifmsh->conf->channel, - ifmsh->conf->enable_edmg, - ifmsh->conf->edmg_channel, - ifmsh->conf->ieee80211n, - ifmsh->conf->ieee80211ac, - ifmsh->conf->ieee80211ax, - ifmsh->conf->secondary_channel, - hostapd_get_oper_chwidth(ifmsh->conf), - hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf), - hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf), - ifmsh->conf->vht_capab, - he_capab)) { - wpa_printf(MSG_ERROR, - "Error updating mesh frequency params"); - wpa_supplicant_mesh_deinit(wpa_s, true); + if (wpas_mesh_update_freq_params(wpa_s) < 0) return -1; - } } if (ifmsh->mconf->security != MESH_CONF_SEC_NONE && From eee0d242bb8ec56fa93367ba4b39d7086aac12e2 Mon Sep 17 00:00:00 2001 From: Shay Bar Date: Tue, 30 Jun 2020 17:23:46 +0300 Subject: [PATCH 1083/1105] hostapd: Add ability to disable HT/VHT/HE per BSS Add the ability to disable HT/VHT/HE for specific BSS from hostapd.conf. - Add disable_11ax boolean to hostapd_bss_config. - Change disable_11n and disable_11ac to bool in hostapd_bss_config. - Add configuration option to set these disable_11* parameters (which were previously used only automatically based on incompatible security parameters to disable HT/VHT). Signed-off-by: Shay Bar --- hostapd/config_file.c | 6 ++++++ hostapd/hostapd.conf | 9 +++++++++ src/ap/ap_config.c | 10 +++++----- src/ap/ap_config.h | 5 +++-- src/ap/beacon.c | 12 ++++++------ src/ap/ctrl_iface_ap.c | 5 +++-- src/ap/ieee802_11.c | 4 ++-- src/ap/ieee802_11_he.c | 2 ++ src/ap/neighbor_db.c | 2 +- 9 files changed, 37 insertions(+), 18 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index ce32f3c04..af2445563 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4569,6 +4569,12 @@ static int hostapd_config_fill(struct hostapd_config *conf, } bss->mka_psk_set |= MKA_PSK_SET_CKN; #endif /* CONFIG_MACSEC */ + } else if (os_strcmp(buf, "disable_11n") == 0) { + bss->disable_11n = !!atoi(pos); + } else if (os_strcmp(buf, "disable_11ac") == 0) { + bss->disable_11ac = !!atoi(pos); + } else if (os_strcmp(buf, "disable_11ax") == 0) { + bss->disable_11ax = !!atoi(pos); } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index bf89fbcda..21f7b1e13 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -580,6 +580,9 @@ wmm_ac_vo_acm=0 # Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band. #ieee80211n=1 +# disable_11n: Boolean (0/1) to disable HT for a specific BSS +#disable_11n=0 + # ht_capab: HT capabilities (list of flags) # LDPC coding capability: [LDPC] = supported # Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary @@ -632,6 +635,9 @@ wmm_ac_vo_acm=0 # Note: hw_mode=a is used to specify that 5 GHz band is used with VHT. #ieee80211ac=1 +# disable_11ac: Boolean (0/1) to disable VHT for a specific BSS +#disable_11ac=0 + # vht_capab: VHT capabilities (list of flags) # # vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454] @@ -786,6 +792,9 @@ wmm_ac_vo_acm=0 # 1 = enabled #ieee80211ax=1 +# disable_11ax: Boolean (0/1) to disable HE for a specific BSS +#disable_11ax=0 + #he_su_beamformer: HE single user beamformer support # 0 = not supported (default) # 1 = supported diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 04535a163..f82468ac8 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -1229,7 +1229,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, if (full_config && conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " "allowed, disabling HT capabilities"); } @@ -1237,7 +1237,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, #ifdef CONFIG_WEP if (full_config && conf->ieee80211n && bss->ssid.security_policy == SECURITY_STATIC_WEP) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " "allowed, disabling HT capabilities"); } @@ -1248,7 +1248,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " "requires CCMP/GCMP to be enabled, disabling HT " "capabilities"); @@ -1258,7 +1258,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, #ifdef CONFIG_WEP if (full_config && conf->ieee80211ac && bss->ssid.security_policy == SECURITY_STATIC_WEP) { - bss->disable_11ac = 1; + bss->disable_11ac = true; wpa_printf(MSG_ERROR, "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities"); } @@ -1269,7 +1269,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) { - bss->disable_11ac = 1; + bss->disable_11ac = true; wpa_printf(MSG_ERROR, "VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities"); } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index bada04c3e..b6937cbc0 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -531,8 +531,9 @@ struct hostapd_bss_config { #define TDLS_PROHIBIT BIT(0) #define TDLS_PROHIBIT_CHAN_SWITCH BIT(1) int tdls; - int disable_11n; - int disable_11ac; + bool disable_11n; + bool disable_11ac; + bool disable_11ax; /* IEEE 802.11v */ int time_advertisement; diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 6d5bb7106..807fe0ff9 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -458,7 +458,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, } #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { buflen += 3 + sizeof(struct ieee80211_he_capabilities) + 3 + sizeof(struct ieee80211_he_operation) + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + @@ -564,14 +564,14 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || - hapd->iconf->ieee80211ax) + (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax)) pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); pos = hostapd_eid_fils_indic(hapd, pos, 0); pos = hostapd_get_rsnxe(hapd, pos, epos - pos); #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP); pos = hostapd_eid_he_operation(hapd, pos); pos = hostapd_eid_spatial_reuse(hapd, pos); @@ -1163,7 +1163,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { tail_len += 3 + sizeof(struct ieee80211_he_capabilities) + 3 + sizeof(struct ieee80211_he_operation) + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + @@ -1288,14 +1288,14 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || - hapd->iconf->ieee80211ax) + (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax)) tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0); tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos); #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { tailpos = hostapd_eid_he_capab(hapd, tailpos, IEEE80211_MODE_AP); tailpos = hostapd_eid_he_operation(hapd, tailpos); diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index ef53a8254..b3d6d62e4 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -748,7 +748,8 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, iface->conf->ieee80211n && !hapd->conf->disable_11n, iface->conf->ieee80211ac && !hapd->conf->disable_11ac, - iface->conf->ieee80211ax, + iface->conf->ieee80211ax && + !hapd->conf->disable_11ax, iface->conf->beacon_int, hapd->conf->dtim_period); if (os_snprintf_error(buflen - len, ret)) @@ -756,7 +757,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, len += ret; #ifdef CONFIG_IEEE80211AX - if (iface->conf->ieee80211ax) { + if (iface->conf->ieee80211ax && !hapd->conf->disable_11ax) { ret = os_snprintf(buf + len, buflen - len, "he_oper_chwidth=%d\n" "he_oper_centr_freq_seg0_idx=%d\n" diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index de715a04c..114d1f574 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -3254,7 +3254,7 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP, elems.he_capabilities, elems.he_capabilities_len); @@ -3870,7 +3870,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP); p = hostapd_eid_he_operation(hapd, p); p = hostapd_eid_spatial_reuse(hapd, p); diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 85b714090..dad68ac43 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -419,6 +419,7 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, size_t he_capab_len) { if (!he_capab || !hapd->iconf->ieee80211ax || + hapd->conf->disable_11ax || !check_valid_he_mcs(hapd, he_capab, opmode) || ieee80211_invalid_he_cap_size(he_capab, he_capab_len) || he_capab_len > sizeof(struct ieee80211_he_capabilities)) { @@ -448,6 +449,7 @@ u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta, const u8 *he_6ghz_capab) { if (!he_6ghz_capab || !hapd->iconf->ieee80211ax || + hapd->conf->disable_11ax || !is_6ghz_op_class(hapd->iconf->op_class)) { sta->flags &= ~WLAN_STA_6GHZ; os_free(sta->he_6ghz_capab); diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c index 01bf88623..2bbe31859 100644 --- a/src/ap/neighbor_db.c +++ b/src/ap/neighbor_db.c @@ -220,7 +220,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd) u16 capab = hostapd_own_capab_info(hapd); int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n; int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac; - int he = hapd->iconf->ieee80211ax; + int he = hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax; struct wpa_ssid_value ssid; u8 channel, op_class; u8 center_freq1_idx = 0, center_freq2_idx = 0; From 4683b72183c5435e16b905b1494f509aeb921d60 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Sat, 4 Jul 2020 10:12:21 +0200 Subject: [PATCH 1084/1105] DFS: Enter DFS state if no available channel is found Previously hostapd would not stop transmitting when a DFS event was detected and no available channel to switch to was available. Disable and re-enable the interface to enter DFS state. This way, TX does not happen until the kernel notifies hostapd about the NOP expiring. Signed-off-by: David Bauer --- src/ap/dfs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ap/dfs.c b/src/ap/dfs.c index 15ef50bce..84db7f28d 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -1070,8 +1070,16 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) &oper_centr_freq_seg0_idx, &oper_centr_freq_seg1_idx, &skip_radar); - if (!channel) - return err; + if (!channel) { + /* + * Toggle interface state to enter DFS state + * until NOP is finished. + */ + hostapd_disable_iface(iface); + hostapd_enable_iface(iface); + return 0; + } + if (!skip_radar) { iface->freq = channel->freq; iface->conf->channel = channel->chan; From 67d5328b3c52c605d630a7e0742575510333efe3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 2 Dec 2020 16:47:28 +0200 Subject: [PATCH 1085/1105] tests: DFS and no available channel after radar detection Signed-off-by: Jouni Malinen --- tests/hwsim/test_dfs.py | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/hwsim/test_dfs.py b/tests/hwsim/test_dfs.py index 3efe6bb2d..f1a1494bc 100644 --- a/tests/hwsim/test_dfs.py +++ b/tests/hwsim/test_dfs.py @@ -652,3 +652,45 @@ def test_dfs_chan_switch(dev, apdev): hwsim_utils.test_connectivity(dev[0], hapd) finally: clear_regdom(hapd, dev) + +@long_duration_test +def test_dfs_no_available_channel(dev, apdev): + """DFS and no available channel after radar detection""" + try: + hapd = None + hapd = start_dfs_ap(apdev[0], chanlist="56") + + ev = hapd.wait_event(["AP-ENABLED"], timeout=70) + if not ev: + raise Exception("AP2 setup timed out") + + dfs_simulate_radar(hapd) + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5260 ht_enabled=1 chan_offset=0 chan_width=1" not in ev: + raise Exception("Unexpected DFS radar detection freq from AP") + + ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5) + if "freq=5280 chan=56" not in ev: + raise Exception("Unexpected DFS new freq: " + ev) + ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) + if "freq=5280" not in ev: + raise Exception("Unexpected channel: " + ev) + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5280" not in ev: + raise Exception("Unexpected DFS freq result") + ev = hapd.wait_event(["AP-ENABLED"], timeout=5) + if not ev: + raise Exception("AP setup timed out") + + dfs_simulate_radar(hapd) + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5280 ht_enabled=1 chan_offset=0 chan_width=1" not in ev: + raise Exception("Unexpected DFS radar detection freq from AP [2]") + + ev = hapd.wait_event(["AP-DISABLED"], timeout=10) + if ev is None: + raise Exception("AP was not disabled") + finally: + clear_regdom(hapd, dev) From f2a01014019a07868618c7c8489164b3019c0203 Mon Sep 17 00:00:00 2001 From: Frederik Juul Date: Thu, 23 Jul 2020 08:39:41 +0000 Subject: [PATCH 1086/1105] wpa_supplicant: Initial connection speedup Add initial_freq_list to wpa_supplicant configuration. This option allows wpa_supplicant to scan a smaller list of frequencies when it starts. This in turn allows for a faster connection to an already known network. This limit applies only for the initial scan operation and does not restrict other channels from being used in consecutive scans. Tests have shown this to reduce the amount of time for connecting to a network from roughly 3 seconds to roughly 0.1 second. Signed-off-by: Frederik Juul --- wpa_supplicant/config.c | 22 ++++++++++++++++++++++ wpa_supplicant/config.h | 13 +++++++++++++ wpa_supplicant/config_file.c | 9 +++++++++ wpa_supplicant/scan.c | 7 ++++++- 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index c5161544d..0aa92a28c 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2890,6 +2890,7 @@ void wpa_config_free(struct wpa_config *config) os_free(config->p2p_no_go_freq.range); os_free(config->autoscan); os_free(config->freq_list); + os_free(config->initial_freq_list); wpabuf_free(config->wps_nfc_dh_pubkey); wpabuf_free(config->wps_nfc_dh_privkey); wpabuf_free(config->wps_nfc_dev_pw); @@ -4547,6 +4548,26 @@ static int wpa_config_process_freq_list(const struct global_parse_data *data, } +static int +wpa_config_process_initial_freq_list(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *value) +{ + int *freqs; + + freqs = wpa_config_parse_int_array(value); + if (!freqs) + return -1; + if (freqs[0] == 0) { + os_free(freqs); + freqs = NULL; + } + os_free(config->initial_freq_list); + config->initial_freq_list = freqs; + return 0; +} + + #ifdef CONFIG_P2P static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, struct wpa_config *config, int line, @@ -5082,6 +5103,7 @@ static const struct global_parse_data global_fields[] = { { FUNC(ap_vendor_elements), 0 }, { INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, { FUNC(freq_list), 0 }, + { FUNC(initial_freq_list), 0}, { INT(scan_cur_freq), 0 }, { INT(sched_scan_interval), 0 }, { INT(sched_scan_start_delay), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 648573de0..d128cd9bf 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -916,6 +916,19 @@ struct wpa_config { */ int *freq_list; + /** + * initial_freq_list - like freq_list but for initial scan + * + * This is an optional zero-terminated array of frequencies in + * megahertz (MHz) to allow for narrowing scanning range when + * the application is started. + * + * This can be used to speed up initial connection time if the + * channel is known ahead of time, without limiting the scanned + * frequencies during normal use. + */ + int *initial_freq_list; + /** * scan_cur_freq - Whether to scan only the current channel * diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 246644a33..cb04a78a2 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1475,6 +1475,15 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) } fprintf(f, "\n"); } + if (config->initial_freq_list && config->initial_freq_list[0]) { + int i; + fprintf(f, "initial_freq_list="); + for (i = 0; config->initial_freq_list[i]; i++) { + fprintf(f, "%s%d", i > 0 ? " " : "", + config->initial_freq_list[i]); + } + fprintf(f, "\n"); + } if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 78371d3ad..9ac658151 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1201,7 +1201,12 @@ ssid_list_set: wpa_setband_scan_freqs(wpa_s, ¶ms); /* See if user specified frequencies. If so, scan only those. */ - if (wpa_s->conf->freq_list && !params.freqs) { + if (wpa_s->last_scan_req == INITIAL_SCAN_REQ && + wpa_s->conf->initial_freq_list && !params.freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Optimize scan based on conf->initial_freq_list"); + int_array_concat(¶ms.freqs, wpa_s->conf->initial_freq_list); + } else if (wpa_s->conf->freq_list && !params.freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on conf->freq_list"); int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); From d83eaa351e950e11d14e856acf35acf1567c9656 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 12 Aug 2020 18:55:31 +0200 Subject: [PATCH 1087/1105] Add option to ignore Probe Request frames when RSSI is too low Add a new hostapd configuration parameters rssi_ignore_probe_request to ignore Probe Request frames received with too low RSSI. Signed-off-by: John Crispin --- hostapd/config_file.c | 2 ++ hostapd/hostapd.conf | 4 ++++ src/ap/ap_config.h | 1 + src/ap/beacon.c | 4 ++++ 4 files changed, 11 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index af2445563..b3dc8f81a 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4450,6 +4450,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->rssi_reject_assoc_rssi = atoi(pos); } else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) { conf->rssi_reject_assoc_timeout = atoi(pos); + } else if (os_strcmp(buf, "rssi_ignore_probe_request") == 0) { + conf->rssi_ignore_probe_request = atoi(pos); } else if (os_strcmp(buf, "pbss") == 0) { bss->pbss = atoi(pos); } else if (os_strcmp(buf, "transition_disable") == 0) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 21f7b1e13..3ac64a75e 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -2735,6 +2735,10 @@ own_ip_addr=127.0.0.1 # threshold (range: 0..255, default=30). #rssi_reject_assoc_timeout=30 +# Ignore Probe Request frames if RSSI is below given threshold (in dBm) +# Allowed range: -60 to -90 dBm; default = 0 (rejection disabled) +#rssi_ignore_probe_request=-75 + ##### Fast Session Transfer (FST) support ##################################### # # The options in this section are only available when the build configuration diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index b6937cbc0..f7a344e0e 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -1039,6 +1039,7 @@ struct hostapd_config { int rssi_reject_assoc_rssi; int rssi_reject_assoc_timeout; + int rssi_ignore_probe_request; #ifdef CONFIG_AIRTIME_POLICY enum { diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 807fe0ff9..47b260e81 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -818,6 +818,10 @@ void handle_probe_req(struct hostapd_data *hapd, size_t csa_offs_len; struct radius_sta rad_info; + if (hapd->iconf->rssi_ignore_probe_request && ssi_signal && + ssi_signal < hapd->iconf->rssi_ignore_probe_request) + return; + if (len < IEEE80211_HDRLEN) return; ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN; From 95cff14c6f7e1f53f16701fad40eb69ae1156919 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 27 Aug 2020 15:58:55 -0700 Subject: [PATCH 1088/1105] tests: Fix p2p_autogo_pref_chan_not_in_regulatory Sweden now allows channel 149 in the updated wireless-regdb. Choose Japan for the negative test instead. Signed-off-by: Thomas Pedersen --- tests/hwsim/test_p2p_channel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_p2p_channel.py b/tests/hwsim/test_p2p_channel.py index 87a1a24a7..7bbc958b9 100644 --- a/tests/hwsim/test_p2p_channel.py +++ b/tests/hwsim/test_p2p_channel.py @@ -603,7 +603,7 @@ def test_p2p_autogo_pref_chan_not_in_regulatory(dev, apdev): raise Exception("Unexpected number of network blocks: " + str(netw)) id = netw[0]['id'] - set_country("SE", dev[0]) + set_country("JP", dev[0]) res = autogo(dev[0], persistent=id) if res['freq'] == "5745": raise Exception("Unexpected channel selected(2): " + res['freq']) From 0dcfdd5e47a1bef0746f1ad95270887753e1bb58 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 4 Dec 2020 11:43:45 +0200 Subject: [PATCH 1089/1105] tests: Skip test cases properly if tshark is not available Instead of trying to process empty results, mark the test case as skipped if tshark is not available. Signed-off-by: Jouni Malinen --- tests/hwsim/tshark.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/hwsim/tshark.py b/tests/hwsim/tshark.py index d6a57f0a3..32cdf4701 100644 --- a/tests/hwsim/tshark.py +++ b/tests/hwsim/tshark.py @@ -12,6 +12,8 @@ import subprocess import logging logger = logging.getLogger() +from utils import * + class UnknownFieldsException(Exception): def __init__(self, fields): Exception.__init__(self, "unknown tshark fields %s" % ','.join(fields)) @@ -41,6 +43,8 @@ def _run_tshark(filename, filter, display=None, wait=True): stderr=subprocess.PIPE) except Exception as e: logger.info("Could run run tshark check: " + str(e)) + if "No such file or directory: 'tshark'" in str(e): + raise HwsimSkip("No tshark available") cmd = None return None @@ -111,6 +115,8 @@ def run_tshark_json(filename, filter): stderr=subprocess.PIPE) except Exception as e: logger.info("Could run run tshark: " + str(e)) + if "No such file or directory: 'tshark'" in str(e): + raise HwsimSkip("No tshark available") return None output = cmd.communicate() out = output[0].decode() From 348447c4869744fb4ccdb8b90aaae4b10374f2b7 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 4 Dec 2020 11:49:04 +0200 Subject: [PATCH 1090/1105] tests: Determine number of parallel make jobs automatically Use nproc (if available) instead of the hardcoded 8 parallel make jobs. Signed-off-by: Jouni Malinen --- tests/hwsim/build.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/hwsim/build.sh b/tests/hwsim/build.sh index 2a3dd706e..cb4700166 100755 --- a/tests/hwsim/build.sh +++ b/tests/hwsim/build.sh @@ -26,13 +26,18 @@ while [ "$1" != "" ]; do esac done +JOBS=`nproc` +if [ -z "$ABC" ]; then + JOBS=8 +fi + echo "Building TNC testing tools" cd tnc -make QUIET=1 -j8 +make QUIET=1 -j$JOBS echo "Building wlantest" cd ../../../wlantest -make QUIET=1 -j8 > /dev/null +make QUIET=1 -j$JOBS > /dev/null echo "Building hs20-osu-client" cd ../hs20/client/ @@ -54,7 +59,7 @@ if [ $use_lcov -eq 1 ]; then fi fi -make QUIET=1 -j8 hostapd hostapd_cli hlr_auc_gw +make QUIET=1 -j$JOBS hostapd hostapd_cli hlr_auc_gw echo "Building wpa_supplicant" cd ../wpa_supplicant @@ -75,4 +80,4 @@ fi if [ -z $FIPSLD_CC ]; then export FIPSLD_CC=gcc fi -make QUIET=1 -j8 +make QUIET=1 -j$JOBS From eac2b6563523ed617240805ae002e7c4fbcb5c69 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Thu, 22 Oct 2020 18:01:37 +0300 Subject: [PATCH 1091/1105] tests: Skip dpp_enterprise_tcp tests without OpenSSL Skip these tests if OpenSSL wasn't loaded, instead of crashing. Signed-off-by: Andrei Otcheretianski --- tests/hwsim/test_dpp.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index ff0381430..5a9d1eeae 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -5967,6 +5967,9 @@ def test_dpp_enterprise_reject(dev, apdev, params): def test_dpp_enterprise_tcp(dev, apdev, params): """DPP over TCP for enterprise provisioning""" + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + try: run_dpp_enterprise_tcp(dev, apdev, params) finally: @@ -6054,6 +6057,9 @@ def run_dpp_enterprise_tcp_end(params, dev, wt): def test_dpp_enterprise_tcp2(dev, apdev, params): """DPP over TCP for enterprise provisioning (Controller initiating)""" + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + try: run_dpp_enterprise_tcp2(dev, apdev, params) finally: From be96f4e8d25aca15a634b8927de3f7d779f45d05 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Thu, 22 Oct 2020 11:20:32 -0700 Subject: [PATCH 1092/1105] wlantest: Allow missing RSNE in S1G beacon S1G beacons save a few bytes by not requiring the RSNE in beacon if RSN BSS is configured. Handle this in wlantest by only clearing RSNE from the BSS info if frame is a Probe Response frame. Signed-off-by: Thomas Pedersen --- src/common/ieee802_11_common.c | 5 +++++ src/common/ieee802_11_common.h | 1 + src/common/ieee802_11_defs.h | 3 +++ wlantest/bss.c | 8 ++++++-- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 8bdeeb5a4..531def458 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -566,6 +566,11 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->dils = pos; elems->dils_len = elen; break; + case WLAN_EID_S1G_CAPABILITIES: + if (elen < 15) + break; + elems->s1g_capab = pos; + break; case WLAN_EID_FRAGMENT: ieee802_11_parse_fragment(&elems->frag_ies, pos, elen); break; diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 0ae0fa4d1..473e00cfd 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -115,6 +115,7 @@ struct ieee802_11_elems { const u8 *short_ssid_list; const u8 *he_6ghz_band_cap; const u8 *sae_pk; + const u8 *s1g_capab; u8 ssid_len; u8 supp_rates_len; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 86d71c156..9518a7afe 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -443,7 +443,10 @@ #define WLAN_EID_DEVICE_LOCATION 204 #define WLAN_EID_WHITE_SPACE_MAP 205 #define WLAN_EID_FTM_PARAMETERS 206 +#define WLAN_EID_S1G_BCN_COMPAT 213 +#define WLAN_EID_S1G_CAPABILITIES 217 #define WLAN_EID_VENDOR_SPECIFIC 221 +#define WLAN_EID_S1G_OPERATION 232 #define WLAN_EID_CAG_NUMBER 237 #define WLAN_EID_AP_CSN 239 #define WLAN_EID_FILS_INDICATION 240 diff --git a/wlantest/bss.c b/wlantest/bss.c index 3208e65e4..92f4a5ebc 100644 --- a/wlantest/bss.c +++ b/wlantest/bss.c @@ -178,14 +178,18 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, elems->osen_len + 2); } - if (elems->rsn_ie == NULL) { + /* S1G does not include RSNE in beacon, so only clear it from + * Probe Response frames. Note this assumes short beacons were dropped + * due to missing SSID above. + */ + if (!elems->rsn_ie && (!elems->s1g_capab || beacon != 1)) { if (bss->rsnie[0]) { add_note(wt, MSG_INFO, "BSS " MACSTR " - RSN IE removed", MAC2STR(bss->bssid)); bss->rsnie[0] = 0; update = 1; } - } else { + } else if (elems->rsn_ie) { if (bss->rsnie[0] == 0 || os_memcmp(bss->rsnie, elems->rsn_ie - 2, elems->rsn_ie_len + 2) != 0) { From 11b3af3dad12e2975913f11f1572a0dc7b316e24 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 7 Nov 2020 11:49:14 +0100 Subject: [PATCH 1093/1105] tests: remotehost: Use correct name While we start thread use: - thread_run - therad_stop - thread_wait Signed-off-by: Janusz Dziedzic --- tests/hwsim/remotehost.py | 10 +++++----- tests/hwsim/wlantest.py | 4 ++-- tests/remote/monitor.py | 4 ++-- tests/remote/rutils.py | 14 +++++++------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py index dec1ad5a8..b4b837187 100644 --- a/tests/hwsim/remotehost.py +++ b/tests/hwsim/remotehost.py @@ -99,7 +99,7 @@ class Host(): return status, buf.decode() # async execute - def execute_run(self, command, res, use_reaper=True): + def thread_run(self, command, res, use_reaper=True): if use_reaper: filename = gen_reaper_file("reaper") self.send_file(filename, filename) @@ -113,13 +113,13 @@ class Host(): cmd = _command else: cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)] - _cmd = self.name + " execute_run: " + ' '.join(cmd) + _cmd = self.name + " thread_run: " + ' '.join(cmd) logger.debug(_cmd) t = threading.Thread(target=execute_thread, name=filename, args=(cmd, res)) t.start() return t - def execute_stop(self, t): + def thread_stop(self, t): if t.name.find("reaper") == -1: raise Exception("use_reaper required") @@ -148,13 +148,13 @@ class Host(): self.execute(["rm", pid_file]) self.execute(["rm", t.name]) - def wait_execute_complete(self, t, wait=None): + def thread_wait(self, t, wait=None): if wait == None: wait_str = "infinite" else: wait_str = str(wait) + "s" - logger.debug(self.name + " wait_execute_complete(" + wait_str + "): ") + logger.debug(self.name + " thread_wait(" + wait_str + "): ") if t.isAlive(): t.join(wait) diff --git a/tests/hwsim/wlantest.py b/tests/hwsim/wlantest.py index 6d4343b63..16765d27a 100644 --- a/tests/hwsim/wlantest.py +++ b/tests/hwsim/wlantest.py @@ -29,7 +29,7 @@ class Wlantest: return cls.remote_host.execute(["killall", "-9", "wlantest"]) - cls.remote_host.wait_execute_complete(cls.exe_thread, 5) + cls.remote_host.thread_wait(cls.exe_thread, 5) cls.exe_thread = None cls.exe_res = [] @@ -64,7 +64,7 @@ class Wlantest: pcap_file, log_file) cls.remote_host.add_log(log_file) cls.remote_host.add_log(pcap_file) - cls.exe_thread = cls.remote_host.execute_run(cmd.split(), cls.exe_res) + cls.exe_thread = cls.remote_host.thread_run(cmd.split(), cls.exe_res) # Give wlantest a chance to start working time.sleep(1) diff --git a/tests/remote/monitor.py b/tests/remote/monitor.py index 5bd801c61..0f77d500b 100644 --- a/tests/remote/monitor.py +++ b/tests/remote/monitor.py @@ -110,7 +110,7 @@ def run(host, setup_params): log = log_dir + tc_name + "_" + host.name + log_monitor + ".pcap" host.add_log(log) - thread = host.execute_run([tshark, "-w", log], monitor_res) + thread = host.thread_run([tshark, "-w", log], monitor_res) host.thread = thread @@ -122,7 +122,7 @@ def stop(host): if host.thread is None: return - host.execute_stop(host.thread) + host.thread_stop(host.thread) host.thread = None # Add monitor to existing interface diff --git a/tests/remote/rutils.py b/tests/remote/rutils.py index e80901b50..0585480a2 100644 --- a/tests/remote/rutils.py +++ b/tests/remote/rutils.py @@ -342,11 +342,11 @@ def ping_run(host, ip, result, ifname=None, addr_type="ipv4", deadline="5", qos= flush_arp_cache(host) - thread = host.execute_run(ping, result) + thread = host.thread_run(ping, result) return thread def ping_wait(host, thread, timeout=None): - host.wait_execute_complete(thread, timeout) + host.thread_wait(thread, timeout) if thread.isAlive(): raise Exception("ping thread still alive") @@ -496,23 +496,23 @@ def iperf_run(server, client, server_ip, client_res, server_res, flush_arp_cache(server) flush_arp_cache(client) - server_thread = server.execute_run(iperf_server, server_res) + server_thread = server.thread_run(iperf_server, server_res) time.sleep(1) - client_thread = client.execute_run(iperf_client, client_res) + client_thread = client.thread_run(iperf_client, client_res) return server_thread, client_thread def iperf_wait(server, client, server_thread, client_thread, timeout=None, iperf="iperf"): - client.wait_execute_complete(client_thread, timeout) + client.thread_wait(client_thread, timeout) if client_thread.isAlive(): raise Exception("iperf client thread still alive") - server.wait_execute_complete(server_thread, 5) + server.thread_wait(server_thread, 5) if server_thread.isAlive(): server.execute(["killall", "-s", "INT", iperf]) time.sleep(1) - server.wait_execute_complete(server_thread, 5) + server.thread_wait(server_thread, 5) if server_thread.isAlive(): raise Exception("iperf server thread still alive") From 3fd22b6ef40929b812d03dcf1b7c52eacd1974c9 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic Date: Sat, 7 Nov 2020 11:49:15 +0100 Subject: [PATCH 1094/1105] tests: remotehost: Introduce wait_event() Allow to run local/remote process like: - ubus listen - logread -f - tail -f - wpa_cli - hostapd_cli And next wait for specific event(s). Signed-off-by: Janusz Dziedzic --- tests/hwsim/remotehost.py | 80 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py index b4b837187..a5b85ac7d 100644 --- a/tests/hwsim/remotehost.py +++ b/tests/hwsim/remotehost.py @@ -147,6 +147,7 @@ class Host(): self.execute(["rm", pid_file]) self.execute(["rm", t.name]) + self.local_execute(["rm", t.name]) def thread_wait(self, t, wait=None): if wait == None: @@ -158,6 +159,85 @@ class Host(): if t.isAlive(): t.join(wait) + def pending(self, s, timeout=0): + [r, w, e] = select.select([s], [], [], timeout) + if r: + return True + return False + + def proc_run(self, command): + filename = gen_reaper_file("reaper") + self.send_file(filename, filename) + self.execute(["chmod", "755", filename]) + _command = [filename] + command + + if self.host: + cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)] + else: + cmd = _command + + _cmd = self.name + " proc_run: " + ' '.join(cmd) + logger.debug(_cmd) + err = tempfile.TemporaryFile() + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=err) + proc.reaper_file = filename + return proc + + def proc_wait_event(self, proc, events, timeout=10): + if not isinstance(events, list): + raise Exception("proc_wait_event() events not a list") + + logger.debug(self.name + " proc_wait_event: " + ' '.join(events) + " timeout: " + str(timeout)) + start = os.times()[4] + try: + while True: + while self.pending(proc.stdout): + line = proc.stdout.readline() + if not line: + return None + line = line.decode() + logger.debug(line.strip('\n')) + for event in events: + if event in line: + return line + now = os.times()[4] + remaining = start + timeout - now + if remaining <= 0: + break + if not self.pending(proc.stdout, timeout=remaining): + break + except: + pass + return None + + def proc_stop(self, proc): + if not proc: + return + + self.execute(["kill `cat " + proc.reaper_file + ".pid`"]) + self.execute(["rm", proc.reaper_file + ".pid"]) + self.execute(["rm", proc.reaper_file]) + self.local_execute(["rm", proc.reaper_file]) + proc.kill() + + def proc_dump(self, proc): + if not proc: + return "" + return proc.stdout.read() + + def execute_and_wait_event(self, command, events, timeout=10): + proc = None + ev = None + + try: + proc = self.proc_run(command) + ev = self.proc_wait_event(proc, events, timeout) + except: + pass + + self.proc_stop(proc) + return ev + def add_log(self, log_file): self.logs.append(log_file) From 297050b4600ed465ad174566a0f92df076397fd3 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Tue, 3 Nov 2020 09:54:16 +0200 Subject: [PATCH 1095/1105] nl80211: Report invalid signal and noise when info is unavailable When the driver sends a CQM RSSI threshold event, wpa_supplicant queries the driver for the signal and noise values. However, it is possible that by that time the station has already disconnected from the AP, so these values are no longer valid. In this case, indicate that these values are invalid by setting them to WPA_INVALID_NOISE. Previously a value of 0 would be reported, which may be confusing as this is a valid value. Since nl80211_get_link_signal() and nl80211_get_link_noise() already set invalid values for a case of failure, just use the value set by these functions even if they fail. Signed-off-by: Avraham Stern Signed-off-by: Andrei Otcheretianski Reviewed-by: Brian Norris --- src/drivers/driver_nl80211_event.c | 23 +++++++++++++++-------- wpa_supplicant/bss.h | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index f75f7b3ae..a3e2eee93 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1376,7 +1376,6 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; enum nl80211_cqm_rssi_threshold_event event; union wpa_event_data ed; - struct wpa_signal_info sig; int res; if (tb[NL80211_ATTR_CQM] == NULL || @@ -1443,19 +1442,27 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, return; } - res = nl80211_get_link_signal(drv, &sig); + /* + * nl80211_get_link_signal() and nl80211_get_link_noise() set default + * values in case querying the driver fails. + */ + res = nl80211_get_link_signal(drv, &ed.signal_change); if (res == 0) { - ed.signal_change.current_signal = sig.current_signal; - ed.signal_change.current_txrate = sig.current_txrate; wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d", - sig.current_signal, sig.current_txrate); + ed.signal_change.current_signal, + ed.signal_change.current_txrate); + } else { + wpa_printf(MSG_DEBUG, + "nl80211: Querying the driver for signal info failed"); } - res = nl80211_get_link_noise(drv, &sig); + res = nl80211_get_link_noise(drv, &ed.signal_change); if (res == 0) { - ed.signal_change.current_noise = sig.current_noise; wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm", - sig.current_noise); + ed.signal_change.current_noise); + } else { + wpa_printf(MSG_DEBUG, + "nl80211: Querying the driver for noise info failed"); } wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed); diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 7cb1745db..919bbe113 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -177,7 +177,7 @@ static inline int bss_is_pbss(struct wpa_bss *bss) static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level) { - if (bss != NULL && new_level < 0) + if (bss != NULL && new_level > -WPA_INVALID_NOISE && new_level < 0) bss->level = new_level; } From 0225301fde6a51cfa5dce49c253e4f3c2c36a79c Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Wed, 21 Oct 2020 17:59:53 +0200 Subject: [PATCH 1096/1105] wolfSSL: Client cert loading API fix Client cert loading API should check equality to SSL_SUCCESS for success. Signed-off-by: Juliusz Sosinowicz --- src/crypto/tls_wolfssl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c index b8a7665fd..ea8f7063b 100644 --- a/src/crypto/tls_wolfssl.c +++ b/src/crypto/tls_wolfssl.c @@ -469,7 +469,7 @@ static int tls_connection_client_cert(struct tls_connection *conn, if (client_cert_blob) { if (wolfSSL_use_certificate_chain_buffer_format( conn->ssl, client_cert_blob, blob_len, - SSL_FILETYPE_ASN1) < 0) { + SSL_FILETYPE_ASN1) != SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use client cert DER blob failed"); return -1; @@ -479,13 +479,13 @@ static int tls_connection_client_cert(struct tls_connection *conn, } if (client_cert) { - if (wolfSSL_use_certificate_chain_file(conn->ssl, - client_cert) < 0) { + if (wolfSSL_use_certificate_chain_file( + conn->ssl, client_cert) != SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use client cert PEM file failed"); if (wolfSSL_use_certificate_chain_file_format( conn->ssl, client_cert, - SSL_FILETYPE_ASN1) < 0) { + SSL_FILETYPE_ASN1) != SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use client cert DER file failed"); return -1; From d215f42538289c230c015550bc4efb4586c208b2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Oct 2020 14:04:01 +0200 Subject: [PATCH 1097/1105] tests: HE: Add a test for wifi generation on 2.4 GHz This was broken in the kernel in mac80211 for a while, until commit 780a8c9efc65 ("mac80211: do not disable HE if HT is missing on 2.4 GHz") fixed it. Add a test for wifi generation on 2.4 GHz in addition to the 5 GHz one. Signed-off-by: Johannes Berg --- tests/hwsim/test_he.py | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index 28123e853..d062f512c 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -154,27 +154,19 @@ def test_he80(dev, apdev): dev[0].request("DISCONNECT") clear_regdom(hapd, dev) -def test_he_wifi_generation(dev, apdev): +def _test_he_wifi_generation(dev, apdev, conf, scan_freq): """HE and wifi_generation""" try: hapd = None params = {"ssid": "he", "country_code": "FI", - "hw_mode": "a", - "channel": "36", - "ht_capab": "[HT40+]", "ieee80211n": "1", - "ieee80211ac": "1", - "ieee80211ax": "1", - "vht_oper_chwidth": "1", - "vht_capab": "[MAX-MPDU-11454]", - "vht_oper_centr_freq_seg0_idx": "42", - "he_oper_chwidth": "1", - "he_oper_centr_freq_seg0_idx": "42"} + "ieee80211ax": "1"} + params.update(conf) hapd = hostapd.add_ap(apdev[0], params) bssid = apdev[0]['bssid'] - dev[0].connect("he", key_mgmt="NONE", scan_freq="5180") + dev[0].connect("he", key_mgmt="NONE", scan_freq=scan_freq) status = dev[0].get_status() if 'wifi_generation' not in status: # For now, assume this is because of missing kernel support @@ -185,7 +177,7 @@ def test_he_wifi_generation(dev, apdev): wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") - wpas.connect("he", key_mgmt="NONE", scan_freq="5180") + wpas.connect("he", key_mgmt="NONE", scan_freq=scan_freq) status = wpas.get_status() if 'wifi_generation' not in status: # For now, assume this is because of missing kernel support @@ -202,6 +194,27 @@ def test_he_wifi_generation(dev, apdev): dev[0].request("DISCONNECT") clear_regdom(hapd, dev) +def test_he_wifi_generation(dev, apdev): + conf = { + "vht_oper_chwidth": "1", + "hw_mode": "a", + "channel": "36", + "ht_capab": "[HT40+]", + "vht_oper_centr_freq_seg0_idx": "42", + "he_oper_chwidth": "1", + "he_oper_centr_freq_seg0_idx": "42", + "vht_capab": "[MAX-MPDU-11454]", + "ieee80211ac": "1", + } + _test_he_wifi_generation(dev, apdev, conf, "5180") + +def test_he_wifi_generation_24(dev, apdev): + conf = { + "hw_mode": "g", + "channel": "1", + } + _test_he_wifi_generation(dev, apdev, conf, "2412") + def he80_test(apdev, dev, channel, ht_capab): clear_scan_cache(apdev) try: From bba926350a0e28fa181af7caee24a11619ad10fc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 4 Dec 2020 13:45:03 +0200 Subject: [PATCH 1098/1105] Fix gcc-10 build with -Werror=array-bounds and dl_list_for_each() The earlier workaround for UBSAN issues in commit 3b6b3ae58133 ("Modify dl_list_for_each() to not use unaligned access with WPA_TRACE") ended up using a construction in which the type cast to the containing structure was compared instead of the struct dl_list pointers. While that worked around the UBSAN issue, it resulted in a comparison that gcc-10 interprets as being out of bounds for struct dl_list (which it obviously is since this is to find the start of the containing structure). Revert that workaround and instead, mark the struct dl_list used within struct os_alloc_trace to have matching 16 octet alignment as the containing structure. This is also restoring consistent design for dl_list_for_each*(). Signed-off-by: Jouni Malinen --- src/utils/list.h | 4 ++-- src/utils/os_unix.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/list.h b/src/utils/list.h index 5298c2626..aa62c0881 100644 --- a/src/utils/list.h +++ b/src/utils/list.h @@ -76,8 +76,8 @@ static inline unsigned int dl_list_len(const struct dl_list *list) dl_list_entry((list)->prev, type, member)) #define dl_list_for_each(item, list, type, member) \ - for (item = dl_list_first((list), type, member); \ - item && item != dl_list_entry((list), type, member); \ + for (item = dl_list_entry((list)->next, type, member); \ + &item->member != (list); \ item = dl_list_entry(item->member.next, type, member)) #define dl_list_for_each_safe(item, n, list, type, member) \ diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c index 6f0c17756..1de37204d 100644 --- a/src/utils/os_unix.c +++ b/src/utils/os_unix.c @@ -39,7 +39,7 @@ static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list); struct os_alloc_trace { unsigned int magic; - struct dl_list list; + struct dl_list list __attribute__((aligned(16))); size_t len; WPA_TRACE_INFO } __attribute__((aligned(16))); From 2a37cda747afb03fe13fe27a61b6a5af39b52c53 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Fri, 20 Nov 2020 19:58:50 +0530 Subject: [PATCH 1099/1105] scan: Add a helper function to append supported freqs from a given band This functionality was repeated for couple of times. Use a shared helper function to avoid code duplication. Signed-off-by: Veerendranath Jakkam --- wpa_supplicant/p2p_supplicant.c | 51 ++++++--------------------------- wpa_supplicant/scan.c | 45 +++++++++++++++++------------ wpa_supplicant/scan.h | 3 ++ 3 files changed, 38 insertions(+), 61 deletions(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 9bcce8c6c..91ffbf6e2 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -291,41 +291,6 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, } -static int wpas_p2p_add_scan_freq_list(struct wpa_supplicant *wpa_s, - enum hostapd_hw_mode band, - struct wpa_driver_scan_params *params) -{ - struct hostapd_hw_modes *mode; - int num_chans = 0; - int *freqs, i; - - mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, 0); - if (!mode) - return -1; - - if (params->freqs) { - while (params->freqs[num_chans]) - num_chans++; - } - - freqs = os_realloc(params->freqs, - (num_chans + mode->num_channels + 1) * sizeof(int)); - if (!freqs) - return -1; - - params->freqs = freqs; - - for (i = 0; i < mode->num_channels; i++) { - if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) - continue; - params->freqs[num_chans++] = mode->channels[i].freq; - } - params->freqs[num_chans] = 0; - - return 0; -} - - static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit) { struct wpa_supplicant *wpa_s = work->wpa_s; @@ -351,10 +316,10 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit) if (wpa_s->conf->p2p_6ghz_disable && !params->freqs) { wpa_printf(MSG_DEBUG, "P2P: 6 GHz disabled - update the scan frequency list"); - wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211G, - params); - wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211A, - params); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params, + 0); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params, + 0); } ret = wpa_drv_scan(wpa_s, params); if (ret == 0) @@ -5342,10 +5307,10 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, } else if (wpa_s->conf->p2p_6ghz_disable) { wpa_printf(MSG_DEBUG, "P2P: 6 GHz disabled - update the scan frequency list"); - wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211G, - ¶ms); - wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211A, - ¶ms); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, ¶ms, + 0); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms, + 0); } ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 9ac658151..edf3ca800 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -670,30 +670,38 @@ static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s) #endif /* CONFIG_P2P */ -static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s, - enum hostapd_hw_mode band, - struct wpa_driver_scan_params *params, - int is_6ghz) +int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode band, + struct wpa_driver_scan_params *params, int is_6ghz) { /* Include only supported channels for the specified band */ struct hostapd_hw_modes *mode; - int count, i; + int num_chans = 0; + int *freqs, i; mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, is_6ghz); - if (mode == NULL) { - /* No channels supported in this band - use empty list */ - params->freqs = os_zalloc(sizeof(int)); - return; + if (!mode) + return -1; + + if (params->freqs) { + while (params->freqs[num_chans]) + num_chans++; } - params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); - if (params->freqs == NULL) - return; - for (count = 0, i = 0; i < mode->num_channels; i++) { + freqs = os_realloc(params->freqs, + (num_chans + mode->num_channels + 1) * sizeof(int)); + if (!freqs) + return -1; + + params->freqs = freqs; + for (i = 0; i < mode->num_channels; i++) { if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) continue; - params->freqs[count++] = mode->channels[i].freq; + params->freqs[num_chans++] = mode->channels[i].freq; } + params->freqs[num_chans] = 0; + + return 0; } @@ -704,12 +712,13 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s, return; /* unknown what channels the driver supports */ if (params->freqs) return; /* already using a limited channel set */ + if (wpa_s->setband == WPA_SETBAND_5G) - wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, - params, 0); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params, + 0); else if (wpa_s->setband == WPA_SETBAND_2G) - wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, - params, 0); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params, + 0); } diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h index c9ce2cecf..4dd3f8360 100644 --- a/wpa_supplicant/scan.h +++ b/wpa_supplicant/scan.h @@ -86,5 +86,8 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, const u8 *ies, size_t ies_len, int rate, int snr); void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s); +int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode band, + struct wpa_driver_scan_params *params, int is_6ghz); #endif /* SCAN_H */ From e4c815a77a1e85f35bc2391057bb1dd5d6865af9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 11 Dec 2020 19:54:47 +0200 Subject: [PATCH 1100/1105] tests: Update scan_fail to match implementation change The function name for adding frequency lists changed, so this test case needs a matching change to avoid failures. Signed-off-by: Jouni Malinen --- tests/hwsim/test_scan.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index 2e64ceec7..458887cd3 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -1137,7 +1137,7 @@ def test_scan_fail(dev, apdev): try: if "OK" not in dev[0].request("SET setband 2G"): raise Exception("SET setband failed") - with alloc_fail(dev[0], 1, "=wpa_setband_scan_freqs_list"): + with alloc_fail(dev[0], 1, "=wpa_add_scan_freqs_list"): # While the frequency list cannot be created due to memory # allocation failure, this scan is expected to be completed without # frequency filtering. From 7131fede3436b769eeceb928dd3be05a767ee9e7 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Thu, 6 Aug 2020 12:04:48 +0530 Subject: [PATCH 1101/1105] Extend the setband support for 6 GHz and band combinations Support possible band combinations of 2.4 GHz, 5 GHz, and 6 GHz with QCA_WLAN_VENDOR_ATTR_SETBAND_MASK attribute. Ensure backwards compatibility with old drivers that are using QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE attribute and supporting only 2.4 GHz and 5 GHz bands. Signed-off-by: Veerendranath Jakkam --- hostapd/ctrl_iface.c | 30 +++++++++++++-------- src/ap/ap_drv_ops.h | 4 +-- src/common/defs.h | 7 ++--- src/drivers/driver.h | 6 ++--- src/drivers/driver_nl80211.c | 45 +++++++++++++++++++------------ wpa_supplicant/ctrl_iface.c | 30 ++++++++++++++------- wpa_supplicant/driver_i.h | 4 +-- wpa_supplicant/scan.c | 7 +++-- wpa_supplicant/wpa_supplicant.c | 1 + wpa_supplicant/wpa_supplicant_i.h | 2 +- 10 files changed, 85 insertions(+), 51 deletions(-) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index e2ae0ad44..7af4f095a 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1347,21 +1347,29 @@ static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd) static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd, - const char *band) + const char *bands) { union wpa_event_data event; - enum set_band setband; + u32 setband_mask = WPA_SETBAND_AUTO; - if (os_strcmp(band, "AUTO") == 0) - setband = WPA_SETBAND_AUTO; - else if (os_strcmp(band, "5G") == 0) - setband = WPA_SETBAND_5G; - else if (os_strcmp(band, "2G") == 0) - setband = WPA_SETBAND_2G; - else - return -1; + /* + * For example: + * SET setband 2G,6G + * SET setband 5G + * SET setband AUTO + */ + if (!os_strstr(bands, "AUTO")) { + if (os_strstr(bands, "5G")) + setband_mask |= WPA_SETBAND_5G; + if (os_strstr(bands, "6G")) + setband_mask |= WPA_SETBAND_6G; + if (os_strstr(bands, "2G")) + setband_mask |= WPA_SETBAND_2G; + if (setband_mask == WPA_SETBAND_AUTO) + return -1; + } - if (hostapd_drv_set_band(hapd, setband) == 0) { + if (hostapd_drv_set_band(hapd, setband_mask) == 0) { os_memset(&event, 0, sizeof(event)); event.channel_list_changed.initiator = REGDOM_SET_BY_USER; event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index cc7ea07a2..0257c3a65 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -385,11 +385,11 @@ hostapd_drv_send_external_auth_status(struct hostapd_data *hapd, } static inline int -hostapd_drv_set_band(struct hostapd_data *hapd, enum set_band band) +hostapd_drv_set_band(struct hostapd_data *hapd, u32 band_mask) { if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band) return -1; - return hapd->driver->set_band(hapd->drv_priv, band); + return hapd->driver->set_band(hapd->drv_priv, band_mask); } #endif /* AP_DRV_OPS */ diff --git a/src/common/defs.h b/src/common/defs.h index bbe3120de..b01ab03b6 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -388,9 +388,10 @@ enum mesh_plink_state { }; enum set_band { - WPA_SETBAND_AUTO, - WPA_SETBAND_5G, - WPA_SETBAND_2G + WPA_SETBAND_AUTO = 0, + WPA_SETBAND_5G = BIT(0), + WPA_SETBAND_2G = BIT(1), + WPA_SETBAND_6G = BIT(2), }; enum wpa_radio_work_band { diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 58a7bd776..b0543e7b4 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -4277,12 +4277,12 @@ struct wpa_driver_ops { int (*do_acs)(void *priv, struct drv_acs_params *params); /** - * set_band - Notify driver of band selection + * set_band - Notify driver of band(s) selection * @priv: Private driver interface data - * @band: The selected band(s) + * @band_mask: The selected band(s) bit mask (from enum set_band) * Returns 0 on success, -1 on failure */ - int (*set_band)(void *priv, enum set_band band); + int (*set_band)(void *priv, u32 band_mask); /** * get_pref_freq_list - Get preferred frequency list for an interface diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 8ba1bf72f..448c404f3 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -10795,38 +10795,49 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params) } -static int nl80211_set_band(void *priv, enum set_band band) +static int nl80211_set_band(void *priv, u32 band_mask) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; struct nlattr *data; int ret; - enum qca_set_band qca_band; + enum qca_set_band qca_band_value; + u32 qca_band_mask = QCA_SETBAND_AUTO; - if (!drv->setband_vendor_cmd_avail) + if (!drv->setband_vendor_cmd_avail || + (band_mask > (WPA_SETBAND_2G | WPA_SETBAND_5G | WPA_SETBAND_6G))) return -1; - switch (band) { - case WPA_SETBAND_AUTO: - qca_band = QCA_SETBAND_AUTO; - break; - case WPA_SETBAND_5G: - qca_band = QCA_SETBAND_5G; - break; - case WPA_SETBAND_2G: - qca_band = QCA_SETBAND_2G; - break; - default: - return -1; - } + if (band_mask & WPA_SETBAND_5G) + qca_band_mask |= QCA_SETBAND_5G; + if (band_mask & WPA_SETBAND_2G) + qca_band_mask |= QCA_SETBAND_2G; + if (band_mask & WPA_SETBAND_6G) + qca_band_mask |= QCA_SETBAND_6G; + + /* + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE is a legacy interface hence make + * it suite to its values (AUTO/5G/2G) for backwards compatibility. + */ + qca_band_value = ((qca_band_mask & QCA_SETBAND_5G) && + (qca_band_mask & QCA_SETBAND_2G)) ? + QCA_SETBAND_AUTO : + qca_band_mask & ~QCA_SETBAND_6G; + + wpa_printf(MSG_DEBUG, + "nl80211: QCA_BAND_MASK = 0x%x, QCA_BAND_VALUE = %d", + qca_band_mask, qca_band_value); if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, QCA_NL80211_VENDOR_SUBCMD_SETBAND) || !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || - nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, qca_band)) { + nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, + qca_band_value) || + nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_MASK, + qca_band_mask)) { nlmsg_free(msg); return -ENOBUFS; } diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 8306950a5..7ce2a90e8 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -299,20 +299,30 @@ static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd) } -static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band) +static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands) { union wpa_event_data event; + u32 setband_mask = WPA_SETBAND_AUTO; - if (os_strcmp(band, "AUTO") == 0) - wpa_s->setband = WPA_SETBAND_AUTO; - else if (os_strcmp(band, "5G") == 0) - wpa_s->setband = WPA_SETBAND_5G; - else if (os_strcmp(band, "2G") == 0) - wpa_s->setband = WPA_SETBAND_2G; - else - return -1; + /* + * For example: + * SET setband 2G,6G + * SET setband 5G + * SET setband AUTO + */ + if (!os_strstr(bands, "AUTO")) { + if (os_strstr(bands, "5G")) + setband_mask |= WPA_SETBAND_5G; + if (os_strstr(bands, "6G")) + setband_mask |= WPA_SETBAND_6G; + if (os_strstr(bands, "2G")) + setband_mask |= WPA_SETBAND_2G; + if (setband_mask == WPA_SETBAND_AUTO) + return -1; + } - if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) { + wpa_s->setband_mask = setband_mask; + if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) { os_memset(&event, 0, sizeof(event)); event.channel_list_changed.initiator = REGDOM_SET_BY_USER; event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 3a2828982..237f4e085 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -954,11 +954,11 @@ static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s, #endif /* CONFIG_MACSEC */ static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s, - enum set_band band) + u32 band_mask) { if (!wpa_s->driver->set_band) return -1; - return wpa_s->driver->set_band(wpa_s->drv_priv, band); + return wpa_s->driver->set_band(wpa_s->drv_priv, band_mask); } static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index edf3ca800..5339b796b 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -713,12 +713,15 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s, if (params->freqs) return; /* already using a limited channel set */ - if (wpa_s->setband == WPA_SETBAND_5G) + if (wpa_s->setband_mask & WPA_SETBAND_5G) wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params, 0); - else if (wpa_s->setband == WPA_SETBAND_2G) + if (wpa_s->setband_mask & WPA_SETBAND_2G) wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params, 0); + if (wpa_s->setband_mask & WPA_SETBAND_6G) + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params, + 1); } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ddd43e5d2..5560197bd 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -5111,6 +5111,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent) wpa_s->parent = parent ? parent : wpa_s; wpa_s->p2pdev = wpa_s->parent; wpa_s->sched_scanning = 0; + wpa_s->setband_mask = WPA_SETBAND_AUTO; dl_list_init(&wpa_s->bss_tmp_disallowed); dl_list_init(&wpa_s->fils_hlp_req); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index ffaacf948..212cc37b6 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -594,7 +594,7 @@ struct wpa_supplicant { struct wpa_ssid_value *disallow_aps_ssid; size_t disallow_aps_ssid_count; - enum set_band setband; + u32 setband_mask; /* Preferred network for the next connection attempt */ struct wpa_ssid *next_ssid; From 9a411882bd2b7f71df89189ffa1bb80bb1e91382 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 11 Dec 2020 17:10:30 +0200 Subject: [PATCH 1102/1105] tests: setband with band combination Signed-off-by: Jouni Malinen --- tests/hwsim/test_scan.py | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/tests/hwsim/test_scan.py b/tests/hwsim/test_scan.py index 458887cd3..cbe8371b1 100644 --- a/tests/hwsim/test_scan.py +++ b/tests/hwsim/test_scan.py @@ -654,6 +654,10 @@ def test_scan_reqs_with_non_scan_radio_work(dev, apdev): def test_scan_setband(dev, apdev): """Band selection for scan operations""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5") + devs = [ dev[0], dev[1], dev[2], wpas ] + try: hapd = None hapd2 = None @@ -678,21 +682,26 @@ def test_scan_setband(dev, apdev): raise Exception("Failed to set setband") if "OK" not in dev[2].request("SET setband 2G"): raise Exception("Failed to set setband") + if "OK" not in wpas.request("SET setband 2G,5G"): + raise Exception("Failed to set setband") # Allow a retry to avoid reporting errors during heavy load for j in range(5): - for i in range(3): - dev[i].request("SCAN only_new=1") + for d in devs: + d.request("SCAN only_new=1") - for i in range(3): - ev = dev[i].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15) + for d in devs: + ev = d.wait_event(["CTRL-EVENT-SCAN-RESULTS"], 15) if ev is None: raise Exception("Scan timed out") res0 = dev[0].request("SCAN_RESULTS") res1 = dev[1].request("SCAN_RESULTS") res2 = dev[2].request("SCAN_RESULTS") - if bssid in res0 and bssid2 in res0 and bssid in res1 and bssid2 in res2: + res3 = wpas.request("SCAN_RESULTS") + if bssid in res0 and bssid2 in res0 and \ + bssid in res1 and bssid2 in res2 and \ + bssid in res3 and bssid2 in res3: break res = dev[0].request("SCAN_RESULTS") @@ -710,15 +719,19 @@ def test_scan_setband(dev, apdev): raise Exception("Missing scan result(2)") if bssid in res: raise Exception("Unexpected scan result(2)") + + res = wpas.request("SCAN_RESULTS") + if bssid not in res or bssid2 not in res: + raise Exception("Missing scan result(3)") finally: if hapd: hapd.request("DISABLE") if hapd2: hapd2.request("DISABLE") subprocess.call(['iw', 'reg', 'set', '00']) - for i in range(3): - dev[i].request("SET setband AUTO") - dev[i].flush_scan_cache() + for i in devs: + d.request("SET setband AUTO") + d.flush_scan_cache() @remote_compatible def test_scan_hidden_many(dev, apdev): From 6ead8b897fed9ba3f35e8d1ba632a6e8b0cc9c0f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 11 Dec 2020 17:18:09 +0200 Subject: [PATCH 1103/1105] Use bool for is_6ghz variables and functions Replace the implicit boolean checks that used int variables with use of a more explicit bool variable type. Signed-off-by: Jouni Malinen --- src/common/ieee802_11_common.c | 22 +++++++++++----------- src/common/ieee802_11_common.h | 6 +++--- wpa_supplicant/dpp_supplicant.c | 6 +++--- wpa_supplicant/op_classes.c | 4 ++-- wpa_supplicant/p2p_supplicant.c | 2 +- wpa_supplicant/rrm.c | 2 +- wpa_supplicant/scan.c | 2 +- wpa_supplicant/scan.h | 3 ++- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wpa_supplicant.c | 4 ++-- wpa_supplicant/wpa_supplicant_i.h | 2 +- 11 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 531def458..c90e04ce7 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -2245,44 +2245,44 @@ int center_idx_to_bw_6ghz(u8 idx) } -int is_6ghz_freq(int freq) +bool is_6ghz_freq(int freq) { if (freq < 5935 || freq > 7115) - return 0; + return false; if (freq == 5935) - return 1; + return true; if (center_idx_to_bw_6ghz((freq - 5950) / 5) < 0) - return 0; + return false; - return 1; + return true; } -int is_6ghz_op_class(u8 op_class) +bool is_6ghz_op_class(u8 op_class) { return op_class >= 131 && op_class <= 136; } -int is_6ghz_psc_frequency(int freq) +bool is_6ghz_psc_frequency(int freq) { int i; if (!is_6ghz_freq(freq) || freq == 5935) - return 0; + return false; if ((((freq - 5950) / 5) & 0x3) != 0x1) - return 0; + return false; i = (freq - 5950 + 55) % 80; if (i == 0) i = (freq - 5950 + 55) / 80; if (i >= 1 && i <= 15) - return 1; + return true; - return 0; + return false; } diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 473e00cfd..6bbe3b7a3 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -259,9 +259,9 @@ u8 country_to_global_op_class(const char *country, u8 op_class); const struct oper_class_map * get_oper_class(const char *country, u8 op_class); int oper_class_bw_to_int(const struct oper_class_map *map); int center_idx_to_bw_6ghz(u8 idx); -int is_6ghz_freq(int freq); -int is_6ghz_op_class(u8 op_class); -int is_6ghz_psc_frequency(int freq); +bool is_6ghz_freq(int freq); +bool is_6ghz_op_class(u8 op_class); +bool is_6ghz_psc_frequency(int freq); int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, size_t nei_rep_len); diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 74514886a..09355cf7f 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -3493,7 +3493,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, /* Preferred chirping channels */ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, - HOSTAPD_MODE_IEEE80211G, 0); + HOSTAPD_MODE_IEEE80211G, false); chan6 = mode == NULL; if (mode) { for (c = 0; c < mode->num_channels; c++) { @@ -3510,7 +3510,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437); mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, - HOSTAPD_MODE_IEEE80211A, 0); + HOSTAPD_MODE_IEEE80211A, false); if (mode) { int chan44 = 0, chan149 = 0; @@ -3532,7 +3532,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, } mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, - HOSTAPD_MODE_IEEE80211AD, 0); + HOSTAPD_MODE_IEEE80211AD, false); if (mode) { for (c = 0; c < mode->num_channels; c++) { struct hostapd_channel_data *chan = &mode->channels[c]; diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c index b4c0c8a0b..41b47cc62 100644 --- a/wpa_supplicant/op_classes.c +++ b/wpa_supplicant/op_classes.c @@ -22,10 +22,10 @@ static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, unsigned int *flags) { int i; - int is_6ghz = op_class >= 131 && op_class <= 136; + bool is_6ghz = op_class >= 131 && op_class <= 136; for (i = 0; i < mode->num_channels; i++) { - int chan_is_6ghz; + bool chan_is_6ghz; chan_is_6ghz = mode->channels[i].freq >= 5935 && mode->channels[i].freq <= 7115; diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 91ffbf6e2..867874dd9 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1921,7 +1921,7 @@ static int wpas_p2p_freq_to_edmg_channel(struct wpa_supplicant *wpa_s, return -1; hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, - HOSTAPD_MODE_IEEE80211AD, 0); + HOSTAPD_MODE_IEEE80211AD, false); if (!hwmode) { wpa_printf(MSG_ERROR, "Unsupported AP mode: HOSTAPD_MODE_IEEE80211AD"); diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c index a9c7b90fd..242496d0a 100644 --- a/wpa_supplicant/rrm.c +++ b/wpa_supplicant/rrm.c @@ -563,7 +563,7 @@ static int * wpas_op_class_freqs(const struct oper_class_map *op, u8 channels_160mhz_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 }; const u8 *channels = NULL; size_t num_chan = 0; - int is_6ghz = is_6ghz_op_class(op->op_class); + bool is_6ghz = is_6ghz_op_class(op->op_class); /* * When adding all channels in the operating class, 80 + 80 MHz diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 5339b796b..5d3016305 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -672,7 +672,7 @@ static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s) int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s, enum hostapd_hw_mode band, - struct wpa_driver_scan_params *params, int is_6ghz) + struct wpa_driver_scan_params *params, bool is_6ghz) { /* Include only supported channels for the specified band */ struct hostapd_hw_modes *mode; diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h index 4dd3f8360..8eb5c73e2 100644 --- a/wpa_supplicant/scan.h +++ b/wpa_supplicant/scan.h @@ -88,6 +88,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s); int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s, enum hostapd_hw_mode band, - struct wpa_driver_scan_params *params, int is_6ghz); + struct wpa_driver_scan_params *params, + bool is_6ghz); #endif /* SCAN_H */ diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 9b4eeb915..46963e92f 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -2462,7 +2462,7 @@ static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s, int start, end; mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, - HOSTAPD_MODE_IEEE80211G, 0); + HOSTAPD_MODE_IEEE80211G, false); if (mode == NULL) { /* No channels supported in this band - use empty list */ params->freqs = os_zalloc(sizeof(int)); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 5560197bd..fc0574e03 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3395,7 +3395,7 @@ get_supported_edmg(struct wpa_supplicant *wpa_s, if (hw_mode == NUM_HOSTAPD_MODES) goto fail; - mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0); + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false); if (!mode) goto fail; @@ -8055,7 +8055,7 @@ int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame, struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, u16 num_modes, enum hostapd_hw_mode mode, - int is_6ghz) + bool is_6ghz) { u16 i; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 212cc37b6..568e383b1 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1620,7 +1620,7 @@ int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd); struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, u16 num_modes, enum hostapd_hw_mode mode, - int is_6ghz); + bool is_6ghz); void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid, unsigned int sec, int rssi_threshold); From b709bb40fd101c399eeb801ec3f8a392f1e08fb8 Mon Sep 17 00:00:00 2001 From: Disha Das Date: Thu, 10 Dec 2020 11:35:32 +0530 Subject: [PATCH 1104/1105] DPP2: Add DPP_CONTROLLER commands to hostapd_cli and wpa_cli Add the DPP control interface DPP_CONTROLLER_START and DPP_CONTROLLER_STOP commands to the CLIs. Signed-off-by: Disha Das --- hostapd/hostapd_cli.c | 18 ++++++++++++++++++ wpa_supplicant/wpa_cli.c | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index dac00e01a..249e46699 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -1475,6 +1475,20 @@ static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, #ifdef CONFIG_DPP2 +static int hostapd_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return hostapd_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv); +} + + +static int hostapd_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP"); +} + + static int hostapd_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1698,6 +1712,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { { "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL, "*| = remove DPP pkex information" }, #ifdef CONFIG_DPP2 + { "dpp_controller_start", hostapd_cli_cmd_dpp_controller_start, NULL, + "[tcp_port=] [role=..] = start DPP controller" }, + { "dpp_controller_stop", hostapd_cli_cmd_dpp_controller_stop, NULL, + "= stop DPP controller" }, { "dpp_chirp", hostapd_cli_cmd_dpp_chirp, NULL, "own= iter= = start DPP chirp" }, { "dpp_stop_chirp", hostapd_cli_cmd_dpp_stop_chirp, NULL, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 813e4b3cf..9f2f903cc 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -3066,6 +3066,20 @@ static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, #ifdef CONFIG_DPP2 +static int wpa_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP"); +} + + static int wpa_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -3820,6 +3834,12 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { cli_cmd_flag_none, "*| = remove DPP pkex information" }, #ifdef CONFIG_DPP2 + { "dpp_controller_start", wpa_cli_cmd_dpp_controller_start, NULL, + cli_cmd_flag_none, + "[tcp_port=] [role=..] = start DPP controller" }, + { "dpp_controller_stop", wpa_cli_cmd_dpp_controller_stop, NULL, + cli_cmd_flag_none, + "= stop DPP controller" }, { "dpp_chirp", wpa_cli_cmd_dpp_chirp, NULL, cli_cmd_flag_none, "own= iter= = start DPP chirp" }, From a337c1d7c92a1085a0a6f692a30be30c3642d678 Mon Sep 17 00:00:00 2001 From: Sunil Dutt Date: Tue, 24 Nov 2020 23:41:11 +0530 Subject: [PATCH 1105/1105] New TWT operations and attributes to TWT Setup and Nudge Define the following additional TWT operations: QCA_WLAN_TWT_GET_STATS, QCA_WLAN_TWT_CLEAR_STATS, QCA_WLAN_TWT_GET_CAPABILITIES, QCA_WLAN_TWT_SETUP_READY_NOTIFY. Also define new attributes to qca_wlan_vendor_attr_twt_setup and qca_wlan_vendor_attr_twt_nudge. Signed-off-by: Jouni Malinen --- src/common/qca-vendor.h | 254 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 252 insertions(+), 2 deletions(-) diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 96b3b0526..28a93d7b8 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -7839,6 +7839,8 @@ enum qca_wlan_vendor_attr_wifi_test_config { * @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Required parameters are * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup. + * This terminate can either get triggered by the user space or can as well be + * a notification from the firmware if it initiates a terminate. * * @QCA_WLAN_TWT_SUSPEND: Suspend the TWT session. Required parameters are * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum @@ -7847,12 +7849,29 @@ enum qca_wlan_vendor_attr_wifi_test_config { * @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are * configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_resume. Valid only after the TWT session is setup. + * This can as well be a notification from the firmware on a QCA_WLAN_TWT_NUDGE + * request. * * @QCA_WLAN_TWT_NUDGE: Suspend and resume the TWT session. TWT nudge is a * combination of suspend and resume in a single request. Required parameters * are configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the * enum qca_wlan_vendor_attr_twt_nudge. Valid only after the TWT session is * setup. + * + * @QCA_WLAN_TWT_GET_STATS: Get the TWT session traffic statistics information. + * Refers the enum qca_wlan_vendor_attr_twt_stats. Valid only after the TWT + * session is setup. + * + * @QCA_WLAN_TWT_CLEAR_STATS: Clear TWT session traffic statistics information. + * Valid only after the TWT session is setup. + * + * @QCA_WLAN_TWT_GET_CAPABILITIES: Get TWT capabilities of this device and its + * peer. Refers the enum qca_wlan_vendor_attr_twt_capability. It's a synchronous + * operation, i.e., the capabilities are obtained in the corresponding + * vendor command reply to the user space. + * + * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmare is + * ready for a new TWT session setup after it issued a TWT teardown. */ enum qca_wlan_twt_operation { QCA_WLAN_TWT_SET = 0, @@ -7861,6 +7880,10 @@ enum qca_wlan_twt_operation { QCA_WLAN_TWT_SUSPEND = 3, QCA_WLAN_TWT_RESUME = 4, QCA_WLAN_TWT_NUDGE = 5, + QCA_WLAN_TWT_GET_STATS = 6, + QCA_WLAN_TWT_CLEAR_STATS = 7, + QCA_WLAN_TWT_GET_CAPABILITIES = 8, + QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9, }; /** @@ -7874,8 +7897,8 @@ enum qca_wlan_twt_operation { * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the * parameters configured for TWT. These parameters are represented by - * enum qca_wlan_vendor_attr_twt_setup or enum qca_wlan_vendor_attr_twt_resume - * based on the operation. + * enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume, + * or enum qca_wlan_vendor_attr_twt_stats based on the operation. */ enum qca_wlan_vendor_attr_config_twt { QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0, @@ -8035,6 +8058,19 @@ enum qca_wlan_vendor_attr_nan_params { QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST - 1 }; +/** + * qca_wlan_twt_setup_state: Represents the TWT session states. + * + * QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED: TWT session not established. + * QCA_WLAN_TWT_SETUP_STATE_ACTIVE: TWT session is active. + * QCA_WLAN_TWT_SETUP_STATE_SUSPEND: TWT session is in suspended state. + */ +enum qca_wlan_twt_setup_state { + QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED = 0, + QCA_WLAN_TWT_SETUP_STATE_ACTIVE = 1, + QCA_WLAN_TWT_SETUP_STATE_SUSPEND = 2, +}; + /** * enum qca_wlan_vendor_attr_twt_setup: Represents attributes for * TWT (Target Wake Time) setup request. These attributes are sent as part of @@ -8085,6 +8121,14 @@ enum qca_wlan_vendor_attr_nan_params { * 2. TWT GET Request and Response * 3. TWT TERMINATE Request and Response * 4. TWT SUSPEND Request and Response + * Flow ID values from 0 to 254 represent a single TWT session + * Flow ID value of 255 represents all TWT sessions for the following + * 1. TWT TERMINATE Request and Response + * 2. TWT SUSPEND Request and Response + * 4. TWT CLEAR STATISTICS request + * 5. TWT GET STATISTICS request and response + * If an invalid dialog ID is provided, status + * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8) * This attribute (exp) is used along with the mantissa to derive the @@ -8172,6 +8216,23 @@ enum qca_wlan_vendor_attr_nan_params { * 4. TWT SUSPEND Request * In STA mode, this is an optional parameter in request and response for * the above four TWT operations. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL: Optional (u32) + * Minimum tolerance limit of wake interval parameter in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL: Optional (u32) + * Maximum tolerance limit of wake interval parameter in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION: Optional (u32) + * Minimum tolerance limit of wake duration parameter in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION: Optional (u32) + * Maximum tolerance limit of wake duration parameter in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE: Optional (u32) + * TWT state for the given dialog id. The values for this are represented + * by enum qca_wlan_twt_setup_state. + * This is obtained through TWT GET operation. */ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0, @@ -8193,6 +8254,11 @@ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED = 14, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR = 15, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL = 16, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL = 17, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION = 18, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION = 19, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE = 20, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST, @@ -8222,6 +8288,16 @@ enum qca_wlan_vendor_attr_twt_setup { * unknown reason * @QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED: TWT session already in * suspend state + * @QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID: FW has dropped the frame due to + * invalid IE in the received TWT frame + * @QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE: Parameters received from + * the responder are not in the specified range + * @QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE: FW terminated the TWT + * session due to request from the responder. Used on the TWT_TERMINATE + * notification from the firmware. + * @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT + * session due to roaming. Used on the TWT_TERMINATE notification from the + * firmware. */ enum qca_wlan_vendor_twt_status { QCA_WLAN_VENDOR_TWT_STATUS_OK = 0, @@ -8238,6 +8314,10 @@ enum qca_wlan_vendor_twt_status { QCA_WLAN_VENDOR_TWT_STATUS_DENIED = 11, QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR = 12, QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED = 13, + QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID = 14, + QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15, + QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16, + QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17, }; /** @@ -8264,6 +8344,10 @@ enum qca_wlan_vendor_twt_status { * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID: Required (u8). * Flow ID is the unique identifier for each TWT session. This attribute * represents the respective TWT session to resume. + * Flow ID values from 0 to 254 represent a single TWT session + * Flow ID value of 255 represents all TWT sessions. + * If an invalid dialog id is provided, status + * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR: 6-byte MAC address * Represents the MAC address of the peer to which TWT Resume is @@ -8294,6 +8378,11 @@ enum qca_wlan_vendor_attr_twt_resume { * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID: Required (u8) * Flow ID is the unique identifier for each TWT session. This attribute * represents the respective TWT session to suspend and resume. + * Flow ID values from 0 to 254 represent a single TWT session + * Flow ID value of 255 represents all TWT sessions in TWT NUDGE request + * and response. + * If an invalid dialog id is provided, status + * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. * * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME: Required (u32) * This attribute is used as the SP offset which is the offset from @@ -8309,6 +8398,10 @@ enum qca_wlan_vendor_attr_twt_resume { * being sent. This is used in AP mode to represent the respective * client and is a required parameter. In STA mode, this is an optional * parameter. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF: Optional (u64) + * This field contains absolute TSF value of the time at which the TWT + * session will be resumed. */ enum qca_wlan_vendor_attr_twt_nudge { QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_INVALID = 0, @@ -8316,6 +8409,7 @@ enum qca_wlan_vendor_attr_twt_nudge { QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME = 2, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE = 3, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR = 4, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF = 5, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST, @@ -8323,6 +8417,162 @@ enum qca_wlan_vendor_attr_twt_nudge { QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST - 1, }; +/** + * enum qca_wlan_vendor_attr_twt_stats: Represents attributes for + * TWT (Target Wake Time) get statistics and clear statistics request. + * These attributes are sent as part of + * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID: Required (u8) + * Flow ID is the unique identifier for each TWT session. This attribute + * represents the respective TWT session for get and clear TWT statistics. + * Flow ID values from 0 to 254 represent a single TWT session + * Flow ID value of 255 represents all TWT sessions in + * 1) TWT GET STATISTICS request and response + * 2) TWT CLEAR STATISTICS request + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer for which TWT Statistics + * is required. + * In AP mode this is used to represent the respective + * client and is a required parameter for + * 1) TWT GET STATISTICS request and response + * 2) TWT CLEAR STATISTICS request and response + * In STA mode, this is an optional parameter. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION: Required (u32) + * This is the duration of the service period in microseconds. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION: Required (u32) + * Average of the actual wake duration observed so far. Unit is microseconds. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS: Required (u32) + * The number of TWT service periods elapsed so far. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION: Required (u32) + * This is the minimum value of the wake duration observed across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is + * microseconds. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION: Required (u32) + * This is the maximum value of wake duration observed across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is + * microseconds. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU: Required (u32) + * Average number of MPDUs transmitted successfully across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU: Required (u32) + * Average number of MPDUs received successfully across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE: Required (u32) + * Average number of bytes transmitted successfully across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE: Required (u32) + * Average number of bytes received successfully across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS: Required (u32) + * Status of the TWT GET STATISTICS request. + * This contains status values in enum qca_wlan_vendor_twt_status + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + */ +enum qca_wlan_vendor_attr_twt_stats { + QCA_WLAN_VENDOR_ATTR_TWT_STATS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID = 1, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR = 2, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION = 3, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION = 4, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS = 5, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION = 6, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION = 7, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU = 8, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU = 9, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE = 10, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE = 11, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS = 12, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX = + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST - 1, +}; + +/** + * qca_wlan_twt_get_capa - Represents the bitmap of TWT capabilities + * supported by the device and the peer. + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_GET_CAPABILITIES + * + * @QCA_WLAN_TWT_CAPA_REQUESTOR: TWT requestor support is advertised by + * TWT non-scheduling STA. This capability is advertised in the HE + * Capability/Extended Capabilities information element in the + * Association Request frame by the device. + * + * @QCA_WLAN_TWT_CAPA_RESPONDER: TWT responder support is advertised by + * the TWT scheduling AP. This capability is advertised in the Extended + * Capabilities/HE Capabilities information element. + * + * @QCA_WLAN_TWT_CAPA_BROADCAST: On the requestor side, this indicates support + * for the broadcast TWT functionality. On the responder side, this indicates + * support for the role of broadcast TWT scheduling functionality. This + * capability is advertised in the HE Capabilities information element. + * + * @QCA_WLAN_TWT_CAPA_TWT_FLEXIBLE: The device supports flexible TWT schedule. + * This capability is advertised in the HE Capabilities information element. + * + * @QCA_WLAN_TWT_CAPA_REQUIRED: The TWT Required is advertised by AP to indicate + * that it mandates the associated HE STAs to support TWT. This capability is + * advertised by AP in the HE Operation Parameters field of the HE Operation + * information element. + */ +enum qca_wlan_twt_capa { + QCA_WLAN_TWT_CAPA_REQUESTOR = BIT(0), + QCA_WLAN_TWT_CAPA_RESPONDER = BIT(1), + QCA_WLAN_TWT_CAPA_BROADCAST = BIT(2), + QCA_WLAN_TWT_CAPA_FLEXIBLE = BIT(3), + QCA_WLAN_TWT_CAPA_REQUIRED = BIT(4), +}; + +/** + * enum qca_wlan_vendor_attr_twt_capability - Represents attributes for TWT + * get capabilities request type. Used by QCA_WLAN_TWT_GET_CAPABILITIES TWT + * operation. + * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer for which the TWT capabilities + * are being queried. This is used in AP mode to represent the respective + * client. In STA mode, this is an optional parameter. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF: (u16). + * Self TWT capabilities. Carries a bitmap of TWT capabilities specified in + * enum qca_wlan_twt_capa. + * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER: (u16). + * Peer TWT capabilities. Carries a bitmap of TWT capabilities specified in + * enum qca_wlan_twt_capa. + */ +enum qca_wlan_vendor_attr_twt_capability { + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR = 1, + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF = 2, + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER = 3, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAX = + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST - 1, +}; + /** * enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by * the TWT responder