Cumulative patch from commit e376290c667e970d751acc916e0efe2ed16292ed

e376290 HS 2.0R2: Add update_identifier field to network
5bc2857 Fix some sparse warnings about u16 vs. le16
42619d6 Fix CTRL-EVENT-REGDOM-CHANGE event init= value
a520bf4 Mark function static
0cb79d3 dbus: Fix indentation level to match code logic
8f03ac9 Mark functions static
6891f0e Allow SCAN command to specify scan_ssid=1 SSIDs
18389ab WPS: Clear keys/PINs explicitly
b7175b4 Clear hostapd configuration keys explicitly
d1ecca6 HS 2.0 R2: Clear hs20-osu-client configuration keys explicitly
0a13e06 EAP server: Clear keying material on deinit
f534ee0 EAP peer: Clear keying material on deinit
19c48da Clear wpa_supplicant configuration keys explicitly
28bfa29 EAP-AKA: Remove unnecessary dead increment
62493df EAP-GPSK: Avoid dead increment by checking pos pointer
164a453 FT: Debug print extra response data
70bfc77 PCSC: Debug print extra response data
5dbbf36 Interworking: Remove unnecessary dead increment
a1e46f3 Check for no key_mgmt/proto/auth_alg entries in config writer
290ea6a Remove unnecessary tracking of first entry
d3fa2bb WFD: Explicit limit for subelement length (CID 68127)
745ef18 HS 2.0: Verify assoc_req_ie buffer size for indication elements
0233dca SAE: Use os_memcmp_const() for hash/password comparisons
34ef46c WEP shared key: Use os_memcmp_const() for hash/password comparisons
3e4b77c EAP-GTC: Use os_memcmp_const() for hash/password comparisons
a6eae3f EAP-MSCHAPv2: Use os_memcmp_const() for hash/password comparisons
30411b3 EAP-TTLS: Use os_memcmp_const() for hash/password comparisons
a564d9c EAP-MD5: Use os_memcmp_const() for hash/password comparisons
4685482 EAP-PSK: Use os_memcmp_const() for hash/password comparisons
cba0f86 EAP-PEAP: Use os_memcmp_const() for hash/password comparisons
7b1e745 EAP-LEAP: Use os_memcmp_const() for hash/password comparisons
8f92826 EAP-GPSK: Use os_memcmp_const() for hash/password comparisons
e1550d4 EAP-PAX: Use os_memcmp_const() for hash/password comparisons
c434503 EAP-FAST: Use os_memcmp_const() for hash/password comparisons
dddf7bb EAP-EKE: Use os_memcmp_const() for hash/password comparisons
dfb5608 EAP-SAKE: Use os_memcmp_const() for hash/password comparisons
05c79d6 EAP-SIM/AKA: Use os_memcmp_const() for hash/password comparisons
675ddad EAP-IKEv2: Use os_memcmp_const() for hash/password comparisons
2049a3c TLS: Use os_memcmp_const() for hash/password comparisons
a79aea5 Milenage: Use os_memcmp_const() for hash/password comparisons
05f916e AES-GCM: Use os_memcmp_const() for hash/password comparisons
87a5c93 AES-CCM: Use os_memcmp_const() for hash/password comparisons
7c24f53 EAPOL supplicant: Use os_memcmp_const() for hash/password comparisons
870834a RSN authenticator: Use os_memcmp_const() for hash/password comparisons
0d15b69 RSN supplicant: Use os_memcmp_const() for hash/password comparisons
72619ce MACsec: Use os_memcmp_const() for hash/password comparisons
c237195 RADIUS: Use os_memcmp_const() for hash/password comparisons
ce9c9bc WPS: Use os_memcmp_const() for hash/password comparisons
afc3c8b Add constant time memory comparison function os_memcmp_const
ee352f1 EAP-pwd: Add explicit total length limit
b2b8a4c EAP-SIM/AKA: Pass EAP type as argument to eap_sim_msg_finish()
f107d00 PeerKey: Clean up EAPOL-Key Key Data processing
010fc5f dbus: Clean up array-array-type property getter

Change-Id: I1dbe483be2678a7468e6955d70ea261f8e53b26d
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 86d6d72..8cd4a2f 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -286,7 +286,7 @@
 {
 #ifdef CONFIG_EXT_PASSWORD
 	if (os_strncmp(value, "ext:", 4) == 0) {
-		os_free(ssid->passphrase);
+		str_clear_free(ssid->passphrase);
 		ssid->passphrase = NULL;
 		ssid->psk_set = 0;
 		os_free(ssid->ext_psk);
@@ -322,7 +322,7 @@
 		    os_memcmp(ssid->passphrase, value, len) == 0)
 			return 0;
 		ssid->psk_set = 0;
-		os_free(ssid->passphrase);
+		str_clear_free(ssid->passphrase);
 		ssid->passphrase = dup_binstr(value, len);
 		if (ssid->passphrase == NULL)
 			return -1;
@@ -341,7 +341,7 @@
 		return -1;
 	}
 
-	os_free(ssid->passphrase);
+	str_clear_free(ssid->passphrase);
 	ssid->passphrase = NULL;
 
 	ssid->psk_set = 1;
@@ -435,7 +435,7 @@
 static char * wpa_config_write_proto(const struct parse_data *data,
 				     struct wpa_ssid *ssid)
 {
-	int first = 1, ret;
+	int ret;
 	char *buf, *pos, *end;
 
 	pos = buf = os_zalloc(20);
@@ -444,27 +444,32 @@
 	end = buf + 20;
 
 	if (ssid->proto & WPA_PROTO_WPA) {
-		ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " ");
+		ret = os_snprintf(pos, end - pos, "%sWPA",
+				  pos == buf ? "" : " ");
 		if (ret < 0 || ret >= end - pos)
 			return buf;
 		pos += ret;
-		first = 0;
 	}
 
 	if (ssid->proto & WPA_PROTO_RSN) {
-		ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " ");
+		ret = os_snprintf(pos, end - pos, "%sRSN",
+				  pos == buf ? "" : " ");
 		if (ret < 0 || ret >= end - pos)
 			return buf;
 		pos += ret;
-		first = 0;
 	}
 
 	if (ssid->proto & WPA_PROTO_OSEN) {
-		ret = os_snprintf(pos, end - pos, "%sOSEN", first ? "" : " ");
+		ret = os_snprintf(pos, end - pos, "%sOSEN",
+				  pos == buf ? "" : " ");
 		if (ret < 0 || ret >= end - pos)
 			return buf;
 		pos += ret;
-		first = 0;
+	}
+
+	if (pos == buf) {
+		os_free(buf);
+		buf = NULL;
 	}
 
 	return buf;
@@ -672,6 +677,11 @@
 	}
 #endif /* CONFIG_WPS */
 
+	if (pos == buf) {
+		os_free(buf);
+		buf = NULL;
+	}
+
 	return buf;
 }
 #endif /* NO_CONFIG_WRITE */
@@ -863,6 +873,11 @@
 		pos += ret;
 	}
 
+	if (pos == buf) {
+		os_free(buf);
+		buf = NULL;
+	}
+
 	return buf;
 }
 #endif /* NO_CONFIG_WRITE */
@@ -1115,7 +1130,7 @@
 
 	if (os_strcmp(value, "NULL") == 0) {
 		wpa_printf(MSG_DEBUG, "Unset configuration string 'password'");
-		os_free(ssid->eap.password);
+		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
 		ssid->eap.password = NULL;
 		ssid->eap.password_len = 0;
 		return 0;
@@ -1126,7 +1141,7 @@
 		char *name = os_strdup(value + 4);
 		if (name == NULL)
 			return -1;
-		os_free(ssid->eap.password);
+		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
 		ssid->eap.password = (u8 *) name;
 		ssid->eap.password_len = os_strlen(name);
 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1148,7 +1163,7 @@
 		wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name,
 				      (u8 *) tmp, res_len);
 
-		os_free(ssid->eap.password);
+		bin_clear_free(ssid->eap.password, ssid->eap.password_len);
 		ssid->eap.password = (u8 *) tmp;
 		ssid->eap.password_len = res_len;
 		ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1177,7 +1192,7 @@
 
 	wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16);
 
-	os_free(ssid->eap.password);
+	bin_clear_free(ssid->eap.password, ssid->eap.password_len);
 	ssid->eap.password = hash;
 	ssid->eap.password_len = 16;
 	ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH;
@@ -1247,7 +1262,7 @@
 			   line, (unsigned int) *len);
 	}
 	os_memcpy(key, buf, *len);
-	os_free(buf);
+	str_clear_free(buf);
 	res = os_snprintf(title, sizeof(title), "wep_key%d", idx);
 	if (res >= 0 && (size_t) res < sizeof(title))
 		wpa_hexdump_key(MSG_MSGDUMP, title, key, *len);
@@ -1736,6 +1751,9 @@
 #ifdef CONFIG_MACSEC
 	{ INT_RANGE(macsec_policy, 0, 1) },
 #endif /* CONFIG_MACSEC */
+#ifdef CONFIG_HS20
+	{ INT(update_identifier) },
+#endif /* CONFIG_HS20 */
 };
 
 #undef OFFSET
@@ -1845,14 +1863,14 @@
 static void eap_peer_config_free(struct eap_peer_config *eap)
 {
 	os_free(eap->eap_methods);
-	os_free(eap->identity);
+	bin_clear_free(eap->identity, eap->identity_len);
 	os_free(eap->anonymous_identity);
-	os_free(eap->password);
+	bin_clear_free(eap->password, eap->password_len);
 	os_free(eap->ca_cert);
 	os_free(eap->ca_path);
 	os_free(eap->client_cert);
 	os_free(eap->private_key);
-	os_free(eap->private_key_passwd);
+	str_clear_free(eap->private_key_passwd);
 	os_free(eap->dh_file);
 	os_free(eap->subject_match);
 	os_free(eap->altsubject_match);
@@ -1861,7 +1879,7 @@
 	os_free(eap->ca_path2);
 	os_free(eap->client_cert2);
 	os_free(eap->private_key2);
-	os_free(eap->private_key2_passwd);
+	str_clear_free(eap->private_key2_passwd);
 	os_free(eap->dh_file2);
 	os_free(eap->subject_match2);
 	os_free(eap->altsubject_match2);
@@ -1869,7 +1887,7 @@
 	os_free(eap->phase1);
 	os_free(eap->phase2);
 	os_free(eap->pcsc);
-	os_free(eap->pin);
+	str_clear_free(eap->pin);
 	os_free(eap->engine_id);
 	os_free(eap->key_id);
 	os_free(eap->cert_id);
@@ -1877,13 +1895,13 @@
 	os_free(eap->key2_id);
 	os_free(eap->cert2_id);
 	os_free(eap->ca_cert2_id);
-	os_free(eap->pin2);
+	str_clear_free(eap->pin2);
 	os_free(eap->engine2_id);
 	os_free(eap->otp);
 	os_free(eap->pending_req_otp);
 	os_free(eap->pac_file);
-	os_free(eap->new_password);
-	os_free(eap->external_sim_resp);
+	bin_clear_free(eap->new_password, eap->new_password_len);
+	str_clear_free(eap->external_sim_resp);
 }
 #endif /* IEEE8021X_EAPOL */
 
@@ -1900,7 +1918,8 @@
 	struct psk_list_entry *psk;
 
 	os_free(ssid->ssid);
-	os_free(ssid->passphrase);
+	os_memset(ssid->psk, 0, sizeof(ssid->psk));
+	str_clear_free(ssid->passphrase);
 	os_free(ssid->ext_psk);
 #ifdef IEEE8021X_EAPOL
 	eap_peer_config_free(&ssid->eap);
@@ -1927,14 +1946,14 @@
 	size_t i;
 
 	os_free(cred->realm);
-	os_free(cred->username);
-	os_free(cred->password);
+	str_clear_free(cred->username);
+	str_clear_free(cred->password);
 	os_free(cred->ca_cert);
 	os_free(cred->client_cert);
 	os_free(cred->private_key);
-	os_free(cred->private_key_passwd);
+	str_clear_free(cred->private_key_passwd);
 	os_free(cred->imsi);
-	os_free(cred->milenage);
+	str_clear_free(cred->milenage);
 	for (i = 0; i < cred->num_domain; i++)
 		os_free(cred->domain[i]);
 	os_free(cred->domain);
@@ -2004,7 +2023,7 @@
 	os_free(config->pkcs11_engine_path);
 	os_free(config->pkcs11_module_path);
 	os_free(config->pcsc_reader);
-	os_free(config->pcsc_pin);
+	str_clear_free(config->pcsc_pin);
 	os_free(config->driver_param);
 	os_free(config->device_name);
 	os_free(config->manufacturer);
@@ -2388,7 +2407,7 @@
 					wpa_printf(MSG_DEBUG, "Do not allow "
 						   "key_data field to be "
 						   "exposed");
-					os_free(res);
+					str_clear_free(res);
 					return os_strdup("*");
 				}
 
@@ -2534,7 +2553,7 @@
 
 	if (os_strcmp(var, "password") == 0 &&
 	    os_strncmp(value, "ext:", 4) == 0) {
-		os_free(cred->password);
+		str_clear_free(cred->password);
 		cred->password = os_strdup(value);
 		cred->ext_password = 1;
 		return 0;
@@ -2597,13 +2616,13 @@
 	}
 
 	if (os_strcmp(var, "username") == 0) {
-		os_free(cred->username);
+		str_clear_free(cred->username);
 		cred->username = val;
 		return 0;
 	}
 
 	if (os_strcmp(var, "password") == 0) {
-		os_free(cred->password);
+		str_clear_free(cred->password);
 		cred->password = val;
 		cred->ext_password = 0;
 		return 0;
@@ -2628,7 +2647,7 @@
 	}
 
 	if (os_strcmp(var, "private_key_passwd") == 0) {
-		os_free(cred->private_key_passwd);
+		str_clear_free(cred->private_key_passwd);
 		cred->private_key_passwd = val;
 		return 0;
 	}
@@ -2640,7 +2659,7 @@
 	}
 
 	if (os_strcmp(var, "milenage") == 0) {
-		os_free(cred->milenage);
+		str_clear_free(cred->milenage);
 		cred->milenage = val;
 		return 0;
 	}
@@ -2808,7 +2827,7 @@
 }
 
 
-char * alloc_int_str(int val)
+static char * alloc_int_str(int val)
 {
 	char *buf;
 
@@ -2820,7 +2839,7 @@
 }
 
 
-char * alloc_strdup(const char *str)
+static char * alloc_strdup(const char *str)
 {
 	if (str == NULL)
 		return NULL;
@@ -3192,7 +3211,7 @@
 {
 	if (blob) {
 		os_free(blob->name);
-		os_free(blob->data);
+		bin_clear_free(blob->data, blob->len);
 		os_free(blob);
 	}
 }
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index fd99218..98855d8 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -739,6 +739,9 @@
 #ifdef CONFIG_MACSEC
 	INT(macsec_policy);
 #endif /* CONFIG_MACSEC */
+#ifdef CONFIG_HS20
+	INT(update_identifier);
+#endif /* CONFIG_HS20 */
 
 #undef STR
 #undef INT
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 76b0632..ab474ff 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -647,6 +647,10 @@
 	 */
 	int macsec_policy;
 #endif /* CONFIG_MACSEC */
+
+#ifdef CONFIG_HS20
+	int update_identifier;
+#endif /* CONFIG_HS20 */
 };
 
 #endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c
index 00a1004..199f04f 100644
--- a/wpa_supplicant/config_winreg.c
+++ b/wpa_supplicant/config_winreg.c
@@ -930,6 +930,9 @@
 		  MGMT_FRAME_PROTECTION_DEFAULT);
 #endif /* CONFIG_IEEE80211W */
 	STR(id_str);
+#ifdef CONFIG_HS20
+	INT(update_identifier);
+#endif /* CONFIG_HS20 */
 
 #undef STR
 #undef INT
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index a509bfb..244fd2d 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5986,6 +5986,25 @@
 }
 
 
+static int scan_id_list_parse(struct wpa_supplicant *wpa_s, const char *value)
+{
+	const char *pos = value;
+
+	while (pos) {
+		if (*pos == ' ' || *pos == '\0')
+			break;
+		if (wpa_s->scan_id_count == MAX_SCAN_ID)
+			return -1;
+		wpa_s->scan_id[wpa_s->scan_id_count++] = atoi(pos);
+		pos = os_strchr(pos, ',');
+		if (pos)
+			pos++;
+	}
+
+	return 0;
+}
+
+
 static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params,
 			   char *reply, int reply_size, int *reply_len)
 {
@@ -5999,6 +6018,7 @@
 	wpa_s->manual_scan_passive = 0;
 	wpa_s->manual_scan_use_id = 0;
 	wpa_s->manual_scan_only_new = 0;
+	wpa_s->scan_id_count = 0;
 
 	if (params) {
 		if (os_strncasecmp(params, "TYPE=ONLY", 9) == 0)
@@ -6021,6 +6041,12 @@
 		pos = os_strstr(params, "only_new=1");
 		if (pos)
 			wpa_s->manual_scan_only_new = 1;
+
+		pos = os_strstr(params, "scan_id=");
+		if (pos && scan_id_list_parse(wpa_s, pos + 8) < 0) {
+			*reply_len = -1;
+			return;
+		}
 	} else {
 		os_free(wpa_s->manual_scan_freqs);
 		wpa_s->manual_scan_freqs = NULL;
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index f5efd8b..6dc5f76 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -512,7 +512,7 @@
 		return FALSE;
 	}
 
-	for (i = 0; i < array_len; i++) {
+	for (i = 0; i < array_len && array[i]; i++) {
 		wpa_dbus_dict_bin_array_add_element(&array_iter,
 						    wpabuf_head(array[i]),
 						    wpabuf_len(array[i]));
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
index a3b63bc..516551a 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_p2p.c
@@ -1455,7 +1455,7 @@
 						       void *user_data)
 {
 	struct wpabuf *vendor_extension[P2P_MAX_WPS_VENDOR_EXT];
-	int i, num;
+	unsigned int i, num = 0;
 	struct peer_handler_args *peer_args = user_data;
 	const struct p2p_peer_info *info;
 
@@ -1468,7 +1468,8 @@
 	}
 
 	/* Add WPS vendor extensions attribute */
-	for (i = 0, num = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
+	os_memset(vendor_extension, 0, sizeof(vendor_extension));
+	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
 		if (info->wps_vendor_ext[i] == NULL)
 			continue;
 		vendor_extension[num] = info->wps_vendor_ext[i];
@@ -2115,8 +2116,9 @@
 	struct wpa_supplicant *wpa_s = user_data;
 	struct hostapd_data *hapd;
 	struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
-	int num_vendor_ext = 0;
-	int i;
+	unsigned int i, num_vendor_ext = 0;
+
+	os_memset(vendor_ext, 0, sizeof(vendor_ext));
 
 	/* Verify correct role for this property */
 	if (wpas_get_p2p_role(wpa_s) == WPAS_P2P_ROLE_GO) {
diff --git a/wpa_supplicant/dbus/dbus_old_handlers.c b/wpa_supplicant/dbus/dbus_old_handlers.c
index 88e5254..048158f 100644
--- a/wpa_supplicant/dbus/dbus_old_handlers.c
+++ b/wpa_supplicant/dbus/dbus_old_handlers.c
@@ -428,7 +428,7 @@
 		if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
 						     (const char *) (ie + 2),
 						     ie[1]))
-		goto error;
+			goto error;
 	}
 
 	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index ad24d4e..2d0b827 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2760,7 +2760,7 @@
 	struct wpa_supplicant *ifs;
 
 	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
-		reg_init_str(info->type), reg_type_str(info->type),
+		reg_init_str(info->initiator), reg_type_str(info->type),
 		info->alpha2[0] ? " alpha2=" : "",
 		info->alpha2[0] ? info->alpha2 : "");
 
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index ab8b66b..257aa6d 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -109,7 +109,13 @@
 {
 	struct wpa_cred *cred;
 
-	if (ssid == NULL || ssid->parent_cred == NULL)
+	if (ssid == NULL)
+		return 0;
+
+	if (ssid->update_identifier)
+		return ssid->update_identifier;
+
+	if (ssid->parent_cred == NULL)
 		return 0;
 
 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index bbee951..45a8f69 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -796,8 +796,8 @@
 		*pos++ = imsi[4];
 		*pos++ = imsi[5];
 	}
-	pos += os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org",
-			   imsi[0], imsi[1], imsi[2]);
+	os_snprintf(pos, end - pos, ".mcc%c%c%c.3gppnetwork.org",
+		    imsi[0], imsi[1], imsi[2]);
 
 	return 0;
 }
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index a2b996f..b13713c 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -548,6 +548,47 @@
 }
 
 
+static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
+			       struct wpa_driver_scan_params *params,
+			       size_t max_ssids)
+{
+	unsigned int i;
+	struct wpa_ssid *ssid;
+
+	for (i = 0; i < wpa_s->scan_id_count; i++) {
+		unsigned int j;
+
+		ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]);
+		if (!ssid || !ssid->scan_ssid)
+			continue;
+
+		for (j = 0; j < params->num_ssids; j++) {
+			if (params->ssids[j].ssid_len == ssid->ssid_len &&
+			    params->ssids[j].ssid &&
+			    os_memcmp(params->ssids[j].ssid, ssid->ssid,
+				      ssid->ssid_len) == 0)
+				break;
+		}
+		if (j < params->num_ssids)
+			continue; /* already in the list */
+
+		if (params->num_ssids + 1 > max_ssids) {
+			wpa_printf(MSG_DEBUG,
+				   "Over max scan SSIDs for manual request");
+			break;
+		}
+
+		wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
+			   wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+		params->ssids[params->num_ssids].ssid = ssid->ssid;
+		params->ssids[params->num_ssids].ssid_len = ssid->ssid_len;
+		params->num_ssids++;
+	}
+
+	wpa_s->scan_id_count = 0;
+}
+
+
 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 {
 	struct wpa_supplicant *wpa_s = eloop_ctx;
@@ -758,6 +799,10 @@
 				ssid = wpa_s->conf->ssid;
 		}
 
+		if (wpa_s->scan_id_count &&
+		    wpa_s->last_scan_req == MANUAL_SCAN_REQ)
+			wpa_set_scan_ssids(wpa_s, &params, max_ssids);
+
 		for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) {
 			if (wpas_network_disabled(wpa_s, tssid))
 				continue;
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 1b04398..5188b9f 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -361,11 +361,17 @@
 		hs20 = wpabuf_alloc(20);
 		if (hs20) {
 			int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
+			size_t len;
+
 			wpas_hs20_add_indication(hs20, pps_mo_id);
-			os_memcpy(wpa_s->sme.assoc_req_ie +
-				  wpa_s->sme.assoc_req_ie_len,
-				  wpabuf_head(hs20), wpabuf_len(hs20));
-			wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
+			len = sizeof(wpa_s->sme.assoc_req_ie) -
+				wpa_s->sme.assoc_req_ie_len;
+			if (wpabuf_len(hs20) <= len) {
+				os_memcpy(wpa_s->sme.assoc_req_ie +
+					  wpa_s->sme.assoc_req_ie_len,
+					  wpabuf_head(hs20), wpabuf_len(hs20));
+				wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
+			}
 			wpabuf_free(hs20);
 		}
 	}
diff --git a/wpa_supplicant/wifi_display.c b/wpa_supplicant/wifi_display.c
index f0c4364..b6f9236 100644
--- a/wpa_supplicant/wifi_display.c
+++ b/wpa_supplicant/wifi_display.c
@@ -280,6 +280,16 @@
 			break; /* truncated subelement */
 
 		if (buf[i] == id) {
+			/*
+			 * Limit explicitly to an arbitrary length to avoid
+			 * unnecessarily large allocations. In practice, this
+			 * is limited to maximum frame length anyway, so the
+			 * maximum memory allocation here is not really that
+			 * large. Anyway, the Wi-Fi Display subelements that
+			 * are fetched with this function are even shorter.
+			 */
+			if (elen > 1000)
+				break;
 			subelem = os_zalloc(2 * elen + 1);
 			if (!subelem)
 				return NULL;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 28d763c..55570de 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1656,10 +1656,15 @@
 		hs20 = wpabuf_alloc(20);
 		if (hs20) {
 			int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
+			size_t len;
+
 			wpas_hs20_add_indication(hs20, pps_mo_id);
-			os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
-				  wpabuf_len(hs20));
-			wpa_ie_len += wpabuf_len(hs20);
+			len = sizeof(wpa_ie) - wpa_ie_len;
+			if (wpabuf_len(hs20) <= len) {
+				os_memcpy(wpa_ie + wpa_ie_len,
+					  wpabuf_head(hs20), wpabuf_len(hs20));
+				wpa_ie_len += wpabuf_len(hs20);
+			}
 			wpabuf_free(hs20);
 		}
 	}
@@ -2830,7 +2835,7 @@
 				 struct ieee80211_ht_capabilities *htcaps_mask,
 				 int disabled)
 {
-	u16 msk;
+	le16 msk;
 
 	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
 
@@ -2903,8 +2908,8 @@
 				int disabled)
 {
 	/* Masking these out disables HT40 */
-	u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
-			       HT_CAP_INFO_SHORT_GI40MHZ);
+	le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
+				HT_CAP_INFO_SHORT_GI40MHZ);
 
 	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
 
@@ -2925,8 +2930,8 @@
 			       int disabled)
 {
 	/* Masking these out disables SGI */
-	u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
-			       HT_CAP_INFO_SHORT_GI40MHZ);
+	le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
+				HT_CAP_INFO_SHORT_GI40MHZ);
 
 	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
 
@@ -2947,7 +2952,7 @@
 			       int disabled)
 {
 	/* Masking these out disables LDPC */
-	u16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
+	le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP);
 
 	wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled);
 
@@ -2988,7 +2993,7 @@
 	wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc);
 
 	if (ssid->ht40_intolerant) {
-		u16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
+		le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT);
 		htcaps->ht_capabilities_info |= bit;
 		htcaps_mask->ht_capabilities_info |= bit;
 	}
@@ -3150,8 +3155,8 @@
 }
 
 
-int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
-			     struct wpa_driver_capa *capa)
+static int wpas_set_wowlan_triggers(struct wpa_supplicant *wpa_s,
+				    struct wpa_driver_capa *capa)
 {
 	struct wowlan_triggers triggers;
 	char *start, *end, *buf;
@@ -4390,7 +4395,7 @@
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_EAP_PASSWORD:
-		os_free(eap->password);
+		bin_clear_free(eap->password, eap->password_len);
 		eap->password = (u8 *) os_strdup(value);
 		eap->password_len = os_strlen(value);
 		eap->pending_req_password = 0;
@@ -4398,7 +4403,7 @@
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
-		os_free(eap->new_password);
+		bin_clear_free(eap->new_password, eap->new_password_len);
 		eap->new_password = (u8 *) os_strdup(value);
 		eap->new_password_len = os_strlen(value);
 		eap->pending_req_new_password = 0;
@@ -4406,14 +4411,14 @@
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_EAP_PIN:
-		os_free(eap->pin);
+		str_clear_free(eap->pin);
 		eap->pin = os_strdup(value);
 		eap->pending_req_pin = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_EAP_OTP:
-		os_free(eap->otp);
+		bin_clear_free(eap->otp, eap->otp_len);
 		eap->otp = (u8 *) os_strdup(value);
 		eap->otp_len = os_strlen(value);
 		os_free(eap->pending_req_otp);
@@ -4421,14 +4426,14 @@
 		eap->pending_req_otp_len = 0;
 		break;
 	case WPA_CTRL_REQ_EAP_PASSPHRASE:
-		os_free(eap->private_key_passwd);
-		eap->private_key_passwd = (u8 *) os_strdup(value);
+		str_clear_free(eap->private_key_passwd);
+		eap->private_key_passwd = os_strdup(value);
 		eap->pending_req_passphrase = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;
 		break;
 	case WPA_CTRL_REQ_SIM:
-		os_free(eap->external_sim_resp);
+		str_clear_free(eap->external_sim_resp);
 		eap->external_sim_resp = os_strdup(value);
 		break;
 	default:
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 1cb4e16..8a9ca97 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -568,6 +568,9 @@
 	int normal_scans; /* normal scans run before sched_scan */
 	int scan_for_connection; /* whether the scan request was triggered for
 				  * finding a connection */
+#define MAX_SCAN_ID 16
+	int scan_id[MAX_SCAN_ID];
+	unsigned int scan_id_count;
 
 	unsigned int drv_flags;
 	unsigned int drv_enc;