Accumulative patch from commit f8361e3d681e55efead2aac79fedf4b232d533fb

TDLS: Pass peer's VHT Capability information during sta_add
WPS: Clear sent_carrier to avoid errors in python script
WPS: Fix OOB Device Password use in PSK1,PSK1 derivation
WPS: Add AP mode NFC connection handover with wpa_supplicant/nfcpy
WPS NFC: Add connection handover support for ER
WPS: Add wps-er-config command for writing config token from ER

Change-Id: I8934dcffb9f66bd3a2f840b78d72c9dd6cecf61d
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index dfe77ad..e017972 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1612,6 +1612,7 @@
 int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd)
 {
 	struct wps_context *wps = hapd->wps;
+	struct wpabuf *pw;
 
 	if (wps == NULL)
 		return -1;
@@ -1626,7 +1627,16 @@
 	wps->ap_nfc_dev_pw_id = hapd->conf->wps_nfc_dev_pw_id;
 	wps->ap_nfc_dh_pubkey = wpabuf_dup(hapd->conf->wps_nfc_dh_pubkey);
 	wps->ap_nfc_dh_privkey = wpabuf_dup(hapd->conf->wps_nfc_dh_privkey);
-	wps->ap_nfc_dev_pw = wpabuf_dup(hapd->conf->wps_nfc_dev_pw);
+	pw = hapd->conf->wps_nfc_dev_pw;
+	wps->ap_nfc_dev_pw = wpabuf_alloc(
+		wpabuf_len(pw) * 2 + 1);
+	if (wps->ap_nfc_dev_pw) {
+		wpa_snprintf_hex_uppercase(
+			(char *) wpabuf_put(wps->ap_nfc_dev_pw,
+					    wpabuf_len(pw) * 2),
+			wpabuf_len(pw) * 2 + 1,
+			wpabuf_head(pw), wpabuf_len(pw));
+	}
 
 	if (!wps->ap_nfc_dh_pubkey || !wps->ap_nfc_dh_privkey ||
 	    !wps->ap_nfc_dev_pw) {
diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c
index f358156..81ad0ce 100644
--- a/src/eap_peer/eap_wsc.c
+++ b/src/eap_peer/eap_wsc.c
@@ -137,7 +137,6 @@
 	struct wps_context *wps;
 	struct wps_credential new_ap_settings;
 	int res;
-	u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN];
 	int nfc = 0;
 
 	wps = sm->wps;
@@ -186,14 +185,6 @@
 		while (*pos != '\0' && *pos != ' ')
 			pos++;
 		cfg.pin_len = pos - (const char *) cfg.pin;
-		if (cfg.pin_len >= WPS_OOB_DEVICE_PASSWORD_MIN_LEN * 2 &&
-		    cfg.pin_len <= WPS_OOB_DEVICE_PASSWORD_LEN * 2 &&
-		    hexstr2bin((const char *) cfg.pin, dev_pw,
-			       cfg.pin_len / 2) == 0) {
-			/* Convert OOB Device Password to binary */
-			cfg.pin = dev_pw;
-			cfg.pin_len /= 2;
-		}
 		if (cfg.pin_len == 6 &&
 		    os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) {
 			cfg.pin = NULL;
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 09adc19..09abdbb 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -122,6 +122,7 @@
 	size_t supp_rates_len;
 
 	struct ieee80211_ht_capabilities *ht_capabilities;
+	struct ieee80211_vht_capabilities *vht_capabilities;
 
 	u8 qos_info;
 
@@ -620,6 +621,8 @@
 	peer->sm_tmr.buf = NULL;
 	os_free(peer->ht_capabilities);
 	peer->ht_capabilities = NULL;
+	os_free(peer->vht_capabilities);
+	peer->vht_capabilities = NULL;
 	os_free(peer->ext_capab);
 	peer->ext_capab = NULL;
 	peer->rsnie_i_len = peer->rsnie_p_len = 0;
@@ -1370,6 +1373,34 @@
 }
 
 
+static int copy_peer_vht_capab(const struct wpa_eapol_ie_parse *kde,
+			      struct wpa_tdls_peer *peer)
+{
+	if (!kde->vht_capabilities ||
+	    kde->vht_capabilities_len <
+	    sizeof(struct ieee80211_vht_capabilities) ) {
+		wpa_printf(MSG_DEBUG, "TDLS: No supported vht capabilities "
+			   "received");
+		return 0;
+	}
+
+	if (!peer->vht_capabilities) {
+		peer->vht_capabilities =
+                        os_zalloc(sizeof(struct ieee80211_vht_capabilities));
+		if (peer->vht_capabilities == NULL)
+                        return -1;
+	}
+
+	os_memcpy(peer->vht_capabilities, kde->vht_capabilities,
+                  sizeof(struct ieee80211_vht_capabilities));
+	wpa_hexdump(MSG_DEBUG, "TDLS: Peer VHT capabilities",
+		    (u8 *) peer->vht_capabilities,
+		    sizeof(struct ieee80211_vht_capabilities));
+
+	return 0;
+}
+
+
 static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
 			       struct wpa_tdls_peer *peer)
 {
@@ -1466,6 +1497,9 @@
 	if (copy_peer_ht_capab(&kde, peer) < 0)
 		goto error;
 
+	if (copy_peer_vht_capab(&kde, peer) < 0)
+		goto error;
+
 	if (copy_peer_ext_capab(&kde, peer) < 0)
 		goto error;
 
@@ -1694,7 +1728,7 @@
 
 skip_rsn_check:
 	/* add the peer to the driver as a "setup in progress" peer */
-	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0,
+	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0,
 				NULL, 0);
 
 	wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
@@ -1738,8 +1772,9 @@
 	/* add supported rates, capabilities, and qos_info to the TDLS peer */
 	wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
 				peer->supp_rates, peer->supp_rates_len,
-				peer->ht_capabilities, peer->qos_info,
-				peer->ext_capab, peer->ext_capab_len);
+				peer->ht_capabilities, peer->vht_capabilities,
+				peer->qos_info, peer->ext_capab,
+				peer->ext_capab_len);
 
 	wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
 }
@@ -1838,6 +1873,9 @@
 	if (copy_peer_ht_capab(&kde, peer) < 0)
 		goto error;
 
+	if (copy_peer_vht_capab(&kde, peer) < 0)
+		goto error;
+
 	if (copy_peer_ext_capab(&kde, peer) < 0)
 		goto error;
 
@@ -2146,7 +2184,7 @@
 	peer->initiator = 1;
 
 	/* add the peer to the driver as a "setup in progress" peer */
-	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, 0,
+	wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0, NULL, NULL, 0,
 				NULL, 0);
 
 	if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 6679dda..dbb493e 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -60,6 +60,7 @@
 				u16 capability, const u8 *supp_rates,
 				size_t supp_rates_len,
 				const struct ieee80211_ht_capabilities *ht_capab,
+				const struct ieee80211_vht_capabilities *vht_capab,
 				u8 qosinfo, const u8 *ext_capab,
 				size_t ext_capab_len);
 #endif /* CONFIG_TDLS */
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 5dae5de..877e6de 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -285,14 +285,15 @@
 			u16 capability, const u8 *supp_rates,
 			size_t supp_rates_len,
 			const struct ieee80211_ht_capabilities *ht_capab,
+			const struct ieee80211_vht_capabilities *vht_capab,
 			u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
 {
 	if (sm->ctx->tdls_peer_addset)
 		return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
 						 capability, supp_rates,
 						 supp_rates_len, ht_capab,
-						 qosinfo, ext_capab,
-						 ext_capab_len);
+						 vht_capab, qosinfo,
+						 ext_capab, ext_capab_len);
 	return -1;
 }
 #endif /* CONFIG_TDLS */
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index 252737f..652197f 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -430,6 +430,9 @@
 		} else if (*pos == WLAN_EID_HT_CAP) {
 			ie->ht_capabilities = pos + 2;
 			ie->ht_capabilities_len = pos[1];
+		} else if (*pos == WLAN_EID_VHT_CAP) {
+			ie->vht_capabilities = pos + 2;
+			ie->vht_capabilities_len = pos[1];
 		} else if (*pos == WLAN_EID_QOS && pos[1] >= 1) {
 			ie->qosinfo = pos[2];
 		} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h
index b212711..82a5c08 100644
--- a/src/rsn_supp/wpa_ie.h
+++ b/src/rsn_supp/wpa_ie.h
@@ -51,6 +51,8 @@
 	size_t ext_supp_rates_len;
 	const u8 *ht_capabilities;
 	size_t ht_capabilities_len;
+	const u8 *vht_capabilities;
+	size_t vht_capabilities_len;
 	u8 qosinfo;
 };
 
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index f01e3b3..86ef022 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -32,7 +32,7 @@
 	struct dl_list list;
 	u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN];
 	u16 pw_id;
-	u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN];
+	u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1];
 	size_t dev_pw_len;
 };
 
@@ -3503,8 +3503,10 @@
 
 	os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
 	token->pw_id = pw_id;
-	os_memcpy(token->dev_pw, dev_pw, dev_pw_len);
-	token->dev_pw_len = dev_pw_len;
+	wpa_snprintf_hex_uppercase((char *) token->dev_pw,
+				   sizeof(token->dev_pw),
+				   dev_pw, dev_pw_len);
+	token->dev_pw_len = dev_pw_len * 2;
 
 	dl_list_add(&reg->nfc_pw_tokens, &token->list);