[wpa_supplicant] Cherry-pick security fixes (April 29, 2019)

09ab81b9e WPA: Clear authenticator keys for a STA on deinit/disconnection
7958223fd EAP-pwd: Use const_time_memcmp() for pwd_value >= prime comparison
8e14b030e SAE: Use const_time_memcmp() for pwd_value >= prime comparison
c3805fb62 Ignore channel switch event if AP interface is not yet ready
eb314e8af Verify that channel info is available in hostapd_hw_get_channel()
b9058266f Clear cached extended_capa pointers on hapd_deinit() call

Bug: 129344244
Test: Connect to SAE network
Test: Connect to EAP network
Test: Enable/disable SoftAP
Test: Regression test (Bug: 131703857)
Change-Id: Iac0d8a7972b905da0d0f0f7414f1eea910b8986b
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 8ddf754..952a3d5 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -787,6 +787,13 @@
 		       freq, ht, hapd->iconf->ch_switch_vht_config, offset,
 		       width, channel_width_to_string(width), cf1, cf2);
 
+	if (!hapd->iface->current_mode) {
+		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_WARNING,
+			       "ignore channel switch since the interface is not yet ready");
+		return;
+	}
+
 	hapd->iface->freq = freq;
 
 	channel = hostapd_hw_get_channel(hapd, freq);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 20c8e8f..0bd6892 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -2486,8 +2486,12 @@
 			wpa_printf(MSG_DEBUG, "%s:bss[%d]->drv_priv=%p",
 				   __func__, (int) j,
 				   hapd_iface->bss[j]->drv_priv);
-			if (hapd_iface->bss[j]->drv_priv == drv_priv)
+			if (hapd_iface->bss[j]->drv_priv == drv_priv) {
 				hapd_iface->bss[j]->drv_priv = NULL;
+				hapd_iface->extended_capa = NULL;
+				hapd_iface->extended_capa_mask = NULL;
+				hapd_iface->extended_capa_len = 0;
+			}
 		}
 	}
 }
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 9d3d990..8ac33bb 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -936,11 +936,16 @@
 	int i, channel;
 	struct hostapd_hw_modes *mode;
 
-	channel = hw_get_chan(hapd->iface->current_mode, freq);
-	if (channel)
-		return channel;
+	if (hapd->iface->current_mode) {
+		channel = hw_get_chan(hapd->iface->current_mode, freq);
+		if (channel)
+			return channel;
+	}
+
 	/* Check other available modes since the channel list for the current
 	 * mode did not include the specified frequency. */
+	if (!hapd->iface->hw_features)
+		return 0;
 	for (i = 0; i < hapd->iface->num_hw_features; i++) {
 		mode = &hapd->iface->hw_features[i];
 		channel = hw_get_chan(mode, freq);
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 616b205..e89a716 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -699,7 +699,7 @@
 #ifdef CONFIG_DPP2
 	wpabuf_clear_free(sm->dpp_z);
 #endif /* CONFIG_DPP2 */
-	os_free(sm);
+	bin_clear_free(sm, sizeof(*sm));
 }
 
 
@@ -1730,6 +1730,12 @@
 	case WPA_DEAUTH:
 	case WPA_DISASSOC:
 		sm->DeauthenticationRequest = TRUE;
+#ifdef CONFIG_IEEE80211R_AP
+		os_memset(sm->PMK, 0, sizeof(sm->PMK));
+		sm->pmk_len = 0;
+		os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
+		sm->xxkey_len = 0;
+#endif /* CONFIG_IEEE80211R_AP */
 		break;
 	case WPA_REAUTH:
 	case WPA_REAUTH_EAPOL:
diff --git a/src/common/sae.c b/src/common/sae.c
index 5a50294..0d56e55 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -317,7 +317,7 @@
 	wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
 			pwd_value, sae->tmp->prime_len);
 
-	if (os_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
+	if (const_time_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
 		return 0;
 
 	x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index 884150e..6ca2c8b 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -144,6 +144,7 @@
 	u8 qnr_bin[MAX_ECC_PRIME_LEN];
 	u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN];
 	u8 x_bin[MAX_ECC_PRIME_LEN];
+	u8 prime_bin[MAX_ECC_PRIME_LEN];
 	struct crypto_bignum *tmp1 = NULL, *tmp2 = NULL, *pm1 = NULL;
 	struct crypto_hash *hash;
 	unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr;
@@ -161,6 +162,11 @@
 	os_memset(x_bin, 0, sizeof(x_bin));
 
 	prime = crypto_ec_get_prime(grp->group);
+	primebitlen = crypto_ec_prime_len_bits(grp->group);
+	primebytelen = crypto_ec_prime_len(grp->group);
+	if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin),
+				 primebytelen) < 0)
+		return -1;
 	grp->pwe = crypto_ec_point_init(grp->group);
 	tmp1 = crypto_bignum_init();
 	pm1 = crypto_bignum_init();
@@ -170,8 +176,6 @@
 		goto fail;
 	}
 
-	primebitlen = crypto_ec_prime_len_bits(grp->group);
-	primebytelen = crypto_ec_prime_len(grp->group);
 	if ((prfbuf = os_malloc(primebytelen)) == NULL) {
 		wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf "
 			   "buffer");
@@ -237,6 +241,8 @@
 		if (primebitlen % 8)
 			buf_shift_right(prfbuf, primebytelen,
 					8 - primebitlen % 8);
+		if (const_time_memcmp(prfbuf, prime_bin, primebytelen) >= 0)
+			continue;
 
 		crypto_bignum_deinit(x_candidate, 1);
 		x_candidate = crypto_bignum_init_set(prfbuf, primebytelen);
@@ -246,9 +252,6 @@
 			goto fail;
 		}
 
-		if (crypto_bignum_cmp(x_candidate, prime) >= 0)
-			continue;
-
 		wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: x_candidate",
 				prfbuf, primebytelen);
 		const_time_select_bin(found, x_bin, prfbuf, primebytelen,