Accumulative patch from commit f5f37d3a4fc2df2a24676b4f95afca15ed793cba

Author: Jouni Malinen <j@w1.fi>
Date:   Sun Nov 25 22:05:32 2012 +0200

   Fix REAUTHENTICATE command after PMKSA caching

   The current PMKSA cache entry needs to be clear to allow EAPOL
   reauthentication to be started in case this association used PMKSA
   caching.

 - Remove old WPS_OOB NCF
 - WPS: Add preliminary NFC connection handover support for Enrollee
 - WPS: Reenable the networks disabled during wpa_wpas_reassoc
 - P2P: Avoid multi-channel scans when they are not needed
 - P2P: Allow discoverable interval for p2p_find to be configured
 - P2P: Allow all channels with multi-channel concurrency
 - Bonjour changes
 - Remove disassociate
 - HS 2.0 changes
 - Add preliminary support for using SQLite for eap_user database
 - Add SAE support
 - Add disallow_aps parameter to disallow BSSIDs/SSIDs

Change-Id: I85358a05b39d46b8db49acdad667e771c580b05c
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/wps/ndef.c b/src/wps/ndef.c
index 7630ecb..a48a2d7 100644
--- a/src/wps/ndef.c
+++ b/src/wps/ndef.c
@@ -10,13 +10,13 @@
 #include "includes.h"
 #include "common.h"
 #include "wps/wps.h"
-#include "wps/wps_i.h"
 
 #define FLAG_MESSAGE_BEGIN (1 << 7)
 #define FLAG_MESSAGE_END (1 << 6)
 #define FLAG_CHUNK (1 << 5)
 #define FLAG_SHORT_RECORD (1 << 4)
 #define FLAG_ID_LENGTH_PRESENT (1 << 3)
+#define FLAG_TNF_NFC_FORUM (0x01)
 #define FLAG_TNF_RFC2046 (0x02)
 
 struct ndef_record {
@@ -168,3 +168,78 @@
 				 FLAG_TNF_RFC2046, wifi_handover_type,
 				 os_strlen(wifi_handover_type), NULL, 0, buf);
 }
+
+
+struct wpabuf * ndef_build_wifi_hr(void)
+{
+	struct wpabuf *rn, *cr, *ac_payload, *ac, *hr_payload, *hr;
+	struct wpabuf *carrier, *hc;
+
+	rn = wpabuf_alloc(2);
+	if (rn == NULL)
+		return NULL;
+	wpabuf_put_be16(rn, os_random() & 0xffff);
+
+	cr = ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_TNF_NFC_FORUM, "cr", 2,
+			       NULL, 0, rn);
+	wpabuf_free(rn);
+
+	if (cr == NULL)
+		return NULL;
+
+	ac_payload = wpabuf_alloc(4);
+	if (ac_payload == NULL) {
+		wpabuf_free(cr);
+		return NULL;
+	}
+	wpabuf_put_u8(ac_payload, 0x01); /* Carrier Flags: CRS=1 "active" */
+	wpabuf_put_u8(ac_payload, 0x01); /* Carrier Data Reference Length */
+	wpabuf_put_u8(ac_payload, '0'); /* Carrier Data Reference: "0" */
+	wpabuf_put_u8(ac_payload, 0); /* Aux Data Reference Count */
+
+	ac = ndef_build_record(FLAG_MESSAGE_END | FLAG_TNF_NFC_FORUM, "ac", 2,
+			       NULL, 0, ac_payload);
+	wpabuf_free(ac_payload);
+	if (ac == NULL) {
+		wpabuf_free(cr);
+		return NULL;
+	}
+
+	hr_payload = wpabuf_alloc(1 + wpabuf_len(cr) + wpabuf_len(ac));
+	if (hr_payload == NULL) {
+		wpabuf_free(cr);
+		wpabuf_free(ac);
+		return NULL;
+	}
+
+	wpabuf_put_u8(hr_payload, 0x12); /* Connection Handover Version 1.2 */
+	wpabuf_put_buf(hr_payload, cr);
+	wpabuf_put_buf(hr_payload, ac);
+	wpabuf_free(cr);
+	wpabuf_free(ac);
+
+	hr = ndef_build_record(FLAG_MESSAGE_BEGIN | FLAG_TNF_NFC_FORUM, "Hr", 2,
+			       NULL, 0, hr_payload);
+	wpabuf_free(hr_payload);
+	if (hr == NULL)
+		return NULL;
+
+	carrier = wpabuf_alloc(2 + os_strlen(wifi_handover_type));
+	if (carrier == NULL) {
+		wpabuf_free(hr);
+		return NULL;
+	}
+	wpabuf_put_u8(carrier, 0x02); /* Carrier Type Format */
+	wpabuf_put_u8(carrier, os_strlen(wifi_handover_type));
+	wpabuf_put_str(carrier, wifi_handover_type);
+
+	hc = ndef_build_record(FLAG_MESSAGE_END | FLAG_TNF_NFC_FORUM, "Hc", 2,
+			       "0", 1, carrier);
+	wpabuf_free(carrier);
+	if (hc == NULL) {
+		wpabuf_free(hr);
+		return NULL;
+	}
+
+	return wpabuf_concat(hr, hc);
+}
diff --git a/src/wps/wps.c b/src/wps/wps.c
index 4c2322d..2575705 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -45,8 +45,7 @@
 		os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN);
 	}
 	if (cfg->pin) {
-		data->dev_pw_id = data->wps->oob_dev_pw_id == 0 ?
-			cfg->dev_pw_id : data->wps->oob_dev_pw_id;
+		data->dev_pw_id = cfg->dev_pw_id;
 		data->dev_password = os_malloc(cfg->pin_len);
 		if (data->dev_password == NULL) {
 			os_free(data);
@@ -110,6 +109,7 @@
 		data->new_ap_settings =
 			os_malloc(sizeof(*data->new_ap_settings));
 		if (data->new_ap_settings == NULL) {
+			os_free(data->dev_password);
 			os_free(data);
 			return NULL;
 		}
diff --git a/src/wps/wps.h b/src/wps/wps.h
index c45b68c..c6b7099 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -42,6 +42,7 @@
  * @cred_attr: Unparsed Credential attribute data (used only in cred_cb());
  *	this may be %NULL, if not used
  * @cred_attr_len: Length of cred_attr in octets
+ * @ap_channel: AP channel
  */
 struct wps_credential {
 	u8 ssid[32];
@@ -54,6 +55,7 @@
 	u8 mac_addr[ETH_ALEN];
 	const u8 *cred_attr;
 	size_t cred_attr_len;
+	u16 ap_channel;
 };
 
 #define WPS_DEV_TYPE_LEN 8
@@ -101,17 +103,6 @@
 	int p2p;
 };
 
-struct oob_conf_data {
-	enum {
-		OOB_METHOD_UNKNOWN = 0,
-		OOB_METHOD_DEV_PWD_E,
-		OOB_METHOD_DEV_PWD_R,
-		OOB_METHOD_CRED,
-	} oob_method;
-	struct wpabuf *dev_password;
-	struct wpabuf *pubkey_hash;
-};
-
 /**
  * struct wps_config - WPS configuration for a single registration protocol run
  */
@@ -617,16 +608,6 @@
 	struct wps_device_data dev;
 
 	/**
-	 * oob_conf - OOB Config data
-	 */
-	struct oob_conf_data oob_conf;
-
-	/**
-	 * oob_dev_pw_id - OOB Device password id
-	 */
-	u16 oob_dev_pw_id;
-
-	/**
 	 * dh_ctx - Context data for Diffie-Hellman operation
 	 */
 	void *dh_ctx;
@@ -764,23 +745,6 @@
 	struct wpabuf *ap_nfc_dev_pw;
 };
 
-struct oob_device_data {
-	char *device_name;
-	char *device_path;
-	void * (*init_func)(struct wps_context *, struct oob_device_data *,
-			    int);
-	struct wpabuf * (*read_func)(void *);
-	int (*write_func)(void *, struct wpabuf *);
-	void (*deinit_func)(void *);
-};
-
-struct oob_nfc_device_data {
-	int (*init_func)(char *);
-	void * (*read_func)(size_t *);
-	int (*write_func)(void *, size_t);
-	void (*deinit_func)(void);
-};
-
 struct wps_registrar *
 wps_registrar_init(struct wps_context *wps,
 		   const struct wps_registrar_config *cfg);
@@ -819,11 +783,6 @@
 int wps_pin_str_valid(const char *pin);
 void wps_free_pending_msgs(struct upnp_pending_message *msgs);
 
-struct oob_device_data * wps_get_oob_device(char *device_type);
-struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name);
-int wps_get_oob_method(char *method);
-int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
-		    int registrar);
 struct wpabuf * wps_get_oob_cred(struct wps_context *wps);
 int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr);
 int wps_attr_text(struct wpabuf *data, char *buf, char *end);
@@ -858,6 +817,7 @@
 /* ndef.c */
 struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf);
 struct wpabuf * ndef_build_wifi(const struct wpabuf *buf);
+struct wpabuf * ndef_build_wifi_hr(void);
 
 #ifdef CONFIG_WPS_STRICT
 int wps_validate_beacon(const struct wpabuf *wps_ie);
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index 9be30b9..29aee8e 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -368,38 +368,6 @@
 
 	return 0;
 }
-
-
-int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps)
-{
-	u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN];
-
-	wpa_printf(MSG_DEBUG, "WPS:  * OOB Device Password");
-
-	if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) {
-		wpa_printf(MSG_ERROR, "WPS: device password id "
-			   "generation error");
-		return -1;
-	}
-	wps->oob_dev_pw_id |= 0x0010;
-
-	if (random_get_bytes(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) <
-	    0) {
-		wpa_printf(MSG_ERROR, "WPS: OOB device password "
-			   "generation error");
-		return -1;
-	}
-
-	wpa_snprintf_hex_uppercase(
-		wpabuf_put(wps->oob_conf.dev_password,
-			   wpabuf_size(wps->oob_conf.dev_password)),
-		wpabuf_size(wps->oob_conf.dev_password),
-		dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN);
-
-	return wps_build_oob_dev_pw(msg, wps->oob_dev_pw_id, wps->dh_pubkey,
-				    dev_password_bin,
-				    WPS_OOB_DEVICE_PASSWORD_LEN);
-}
 #endif /* CONFIG_WPS_OOB */
 
 
diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c
index 5aa9b00..3999b1b 100644
--- a/src/wps/wps_attr_parse.c
+++ b/src/wps/wps_attr_parse.c
@@ -542,6 +542,14 @@
 		if (wps_parse_vendor_ext(attr, pos, len) < 0)
 			return -1;
 		break;
+	case ATTR_AP_CHANNEL:
+		if (len != 2) {
+			wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
+				   "length %u", len);
+			return -1;
+		}
+		attr->ap_channel = pos;
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
 			   "len=%u", type, len);
diff --git a/src/wps/wps_attr_parse.h b/src/wps/wps_attr_parse.h
index 332e966..88e51a4 100644
--- a/src/wps/wps_attr_parse.h
+++ b/src/wps/wps_attr_parse.h
@@ -56,6 +56,7 @@
 	const u8 *settings_delay_time; /* 1 octet */
 	const u8 *network_key_shareable; /* 1 octet (Bool) */
 	const u8 *request_to_enroll; /* 1 octet (Bool) */
+	const u8 *ap_channel; /* 2 octets */
 
 	/* variable length fields */
 	const u8 *manufacturer;
diff --git a/src/wps/wps_attr_process.c b/src/wps/wps_attr_process.c
index d4c6e88..b81f106 100644
--- a/src/wps/wps_attr_process.c
+++ b/src/wps/wps_attr_process.c
@@ -258,6 +258,19 @@
 }
 
 
+static int wps_process_cred_ap_channel(struct wps_credential *cred,
+				       const u8 *ap_channel)
+{
+	if (ap_channel == NULL)
+		return 0; /* optional attribute */
+
+	cred->ap_channel = WPA_GET_BE16(ap_channel);
+	wpa_printf(MSG_DEBUG, "WPS: AP Channel: %u", cred->ap_channel);
+
+	return 0;
+}
+
+
 static int wps_workaround_cred_key(struct wps_credential *cred)
 {
 	if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) &&
@@ -303,7 +316,8 @@
 	    wps_process_cred_eap_identity(cred, attr->eap_identity,
 					  attr->eap_identity_len) ||
 	    wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) ||
-	    wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled))
+	    wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled) ||
+	    wps_process_cred_ap_channel(cred, attr->ap_channel))
 		return -1;
 
 	return wps_workaround_cred_key(cred);
diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
index 5a8817f..68d9f0a 100644
--- a/src/wps/wps_common.c
+++ b/src/wps/wps_common.c
@@ -375,84 +375,6 @@
 }
 
 
-static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps)
-{
-	struct wpabuf *data;
-
-	data = wpabuf_alloc(200);
-	if (data == NULL) {
-		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
-			   "device password attribute");
-		return NULL;
-	}
-
-	wpabuf_free(wps->oob_conf.dev_password);
-	wps->oob_conf.dev_password =
-		wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1);
-	if (wps->oob_conf.dev_password == NULL) {
-		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
-			   "device password");
-		wpabuf_free(data);
-		return NULL;
-	}
-
-	if (wps_build_version(data) ||
-	    wps_build_oob_dev_password(data, wps) ||
-	    wps_build_wfa_ext(data, 0, NULL, 0)) {
-		wpa_printf(MSG_ERROR, "WPS: Build OOB device password "
-			   "attribute error");
-		wpabuf_free(data);
-		return NULL;
-	}
-
-	return data;
-}
-
-
-static int wps_parse_oob_dev_pwd(struct wps_context *wps,
-				 struct wpabuf *data)
-{
-	struct oob_conf_data *oob_conf = &wps->oob_conf;
-	struct wps_parse_attr attr;
-	const u8 *pos;
-	size_t pw_len;
-
-	if (wps_parse_msg(data, &attr) < 0 ||
-	    attr.oob_dev_password == NULL) {
-		wpa_printf(MSG_ERROR, "WPS: OOB device password not found");
-		return -1;
-	}
-
-	pos = attr.oob_dev_password;
-
-	wpabuf_free(oob_conf->pubkey_hash);
-	oob_conf->pubkey_hash =
-		wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN);
-	if (oob_conf->pubkey_hash == NULL) {
-		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
-			   "public key hash");
-		return -1;
-	}
-	pos += WPS_OOB_PUBKEY_HASH_LEN;
-
-	wps->oob_dev_pw_id = WPA_GET_BE16(pos);
-	pos += sizeof(wps->oob_dev_pw_id);
-
-	pw_len = attr.oob_dev_password_len - WPS_OOB_PUBKEY_HASH_LEN - 2;
-	oob_conf->dev_password = wpabuf_alloc(pw_len * 2 + 1);
-	if (oob_conf->dev_password == NULL) {
-		wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB "
-			   "device password");
-		return -1;
-	}
-	wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password,
-					      pw_len * 2 + 1),
-				   pw_len * 2 + 1, pos, pw_len);
-
-	return 0;
-}
-
-
 int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr)
 {
 	struct wpabuf msg;
@@ -477,107 +399,6 @@
 }
 
 
-static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data)
-{
-	struct wps_parse_attr attr;
-
-	if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) {
-		wpa_printf(MSG_ERROR, "WPS: OOB credential not found");
-		return -1;
-	}
-
-	return wps_oob_use_cred(wps, &attr);
-}
-
-
-int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev,
-		    int registrar)
-{
-	struct wpabuf *data;
-	int ret, write_f, oob_method = wps->oob_conf.oob_method;
-	void *oob_priv;
-
-	write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar;
-
-	oob_priv = oob_dev->init_func(wps, oob_dev, registrar);
-	if (oob_priv == NULL) {
-		wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device");
-		return -1;
-	}
-
-	if (write_f) {
-		if (oob_method == OOB_METHOD_CRED)
-			data = wps_get_oob_cred(wps);
-		else
-			data = wps_get_oob_dev_pwd(wps);
-
-		ret = 0;
-		if (data == NULL || oob_dev->write_func(oob_priv, data) < 0)
-			ret = -1;
-	} else {
-		data = oob_dev->read_func(oob_priv);
-		if (data == NULL)
-			ret = -1;
-		else {
-			if (oob_method == OOB_METHOD_CRED)
-				ret = wps_parse_oob_cred(wps, data);
-			else
-				ret = wps_parse_oob_dev_pwd(wps, data);
-		}
-	}
-	wpabuf_free(data);
-	oob_dev->deinit_func(oob_priv);
-
-	if (ret < 0) {
-		wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data");
-		return -1;
-	}
-
-	return 0;
-}
-
-
-struct oob_device_data * wps_get_oob_device(char *device_type)
-{
-#ifdef CONFIG_WPS_UFD
-	if (os_strstr(device_type, "ufd") != NULL)
-		return &oob_ufd_device_data;
-#endif /* CONFIG_WPS_UFD */
-#ifdef CONFIG_WPS_NFC
-	if (os_strstr(device_type, "nfc") != NULL)
-		return &oob_nfc_device_data;
-#endif /* CONFIG_WPS_NFC */
-
-	return NULL;
-}
-
-
-#ifdef CONFIG_WPS_NFC
-struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name)
-{
-	if (device_name == NULL)
-		return NULL;
-#ifdef CONFIG_WPS_NFC_PN531
-	if (os_strstr(device_name, "pn531") != NULL)
-		return &oob_nfc_pn531_device_data;
-#endif /* CONFIG_WPS_NFC_PN531 */
-
-	return NULL;
-}
-#endif /* CONFIG_WPS_NFC */
-
-
-int wps_get_oob_method(char *method)
-{
-	if (os_strstr(method, "pin-e") != NULL)
-		return OOB_METHOD_DEV_PWD_E;
-	if (os_strstr(method, "pin-r") != NULL)
-		return OOB_METHOD_DEV_PWD_R;
-	if (os_strstr(method, "cred") != NULL)
-		return OOB_METHOD_CRED;
-	return OOB_METHOD_UNKNOWN;
-}
-
 #endif /* CONFIG_WPS_OOB */
 
 
@@ -657,15 +478,10 @@
 #ifdef CONFIG_WPS2
 		methods |= WPS_CONFIG_VIRT_DISPLAY;
 #endif /* CONFIG_WPS2 */
-#ifdef CONFIG_WPS_UFD
-		methods |= WPS_CONFIG_USBA;
-#endif /* CONFIG_WPS_UFD */
 #ifdef CONFIG_WPS_NFC
 		methods |= WPS_CONFIG_NFC_INTERFACE;
 #endif /* CONFIG_WPS_NFC */
 	} else {
-		if (os_strstr(str, "usba"))
-			methods |= WPS_CONFIG_USBA;
 		if (os_strstr(str, "ethernet"))
 			methods |= WPS_CONFIG_ETHERNET;
 		if (os_strstr(str, "label"))
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index 389aa84..837b941 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -523,23 +523,6 @@
 		return -1;
 	}
 
-#ifdef CONFIG_WPS_OOB
-	if (wps->dev_pw_id != DEV_PW_DEFAULT &&
-	    wps->wps->oob_conf.pubkey_hash) {
-		const u8 *addr[1];
-		u8 hash[WPS_HASH_LEN];
-
-		addr[0] = pk;
-		sha256_vector(1, addr, &pk_len, hash);
-		if (os_memcmp(hash,
-			      wpabuf_head(wps->wps->oob_conf.pubkey_hash),
-			      WPS_OOB_PUBKEY_HASH_LEN) != 0) {
-			wpa_printf(MSG_ERROR, "WPS: Public Key hash error");
-			return -1;
-		}
-	}
-#endif /* CONFIG_WPS_OOB */
-
 	wpabuf_free(wps->dh_pubkey_r);
 	wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len);
 	if (wps->dh_pubkey_r == NULL)
@@ -665,6 +648,7 @@
 {
 	struct wps_parse_attr attr;
 	struct wpabuf msg;
+	int ret = 0;
 
 	wpa_printf(MSG_DEBUG, "WPS: Received Credential");
 	os_memset(&wps->cred, 0, sizeof(wps->cred));
@@ -714,12 +698,12 @@
 	if (wps->wps->cred_cb) {
 		wps->cred.cred_attr = cred - 4;
 		wps->cred.cred_attr_len = cred_len + 4;
-		wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred);
+		ret = wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred);
 		wps->cred.cred_attr = NULL;
 		wps->cred.cred_attr_len = 0;
 	}
 
-	return 0;
+	return ret;
 }
 
 
diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h
index 86ad248..8110894 100644
--- a/src/wps/wps_i.h
+++ b/src/wps/wps_i.h
@@ -137,10 +137,6 @@
 void wps_pbc_overlap_event(struct wps_context *wps);
 void wps_pbc_timeout_event(struct wps_context *wps);
 
-extern struct oob_device_data oob_ufd_device_data;
-extern struct oob_device_data oob_nfc_device_data;
-extern struct oob_nfc_device_data oob_nfc_pn531_device_data;
-
 struct wpabuf * wps_build_wsc_ack(struct wps_data *wps);
 struct wpabuf * wps_build_wsc_nack(struct wps_data *wps);
 
@@ -169,7 +165,6 @@
 int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
 			 const struct wpabuf *pubkey, const u8 *dev_pw,
 			 size_t dev_pw_len);
-int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps);
 struct wpabuf * wps_ie_encapsulate(struct wpabuf *data);
 
 /* wps_attr_process.c */
diff --git a/src/wps/wps_nfc.c b/src/wps/wps_nfc.c
deleted file mode 100644
index 6804350..0000000
--- a/src/wps/wps_nfc.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * NFC routines for Wi-Fi Protected Setup
- * Copyright (c) 2009-2012, Masashi Honma <masashi.honma@gmail.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include "common.h"
-
-#include "wps/wps.h"
-#include "wps_i.h"
-
-
-struct wps_nfc_data {
-	struct oob_nfc_device_data *oob_nfc_dev;
-};
-
-
-static void * init_nfc(struct wps_context *wps,
-		       struct oob_device_data *oob_dev, int registrar)
-{
-	struct oob_nfc_device_data *oob_nfc_dev;
-	struct wps_nfc_data *data;
-
-	oob_nfc_dev = wps_get_oob_nfc_device(oob_dev->device_name);
-	if (oob_nfc_dev == NULL) {
-		wpa_printf(MSG_ERROR, "WPS (NFC): Unknown NFC device (%s)",
-			   oob_dev->device_name);
-		return NULL;
-	}
-
-	if (oob_nfc_dev->init_func(oob_dev->device_path) < 0)
-		return NULL;
-
-	data = os_zalloc(sizeof(*data));
-	if (data == NULL) {
-		wpa_printf(MSG_ERROR, "WPS (NFC): Failed to allocate "
-			   "nfc data area");
-		return NULL;
-	}
-	data->oob_nfc_dev = oob_nfc_dev;
-	return data;
-}
-
-
-static struct wpabuf * read_nfc(void *priv)
-{
-	struct wps_nfc_data *data = priv;
-	struct wpabuf *wifi, *buf;
-	char *raw_data;
-	size_t len;
-
-	raw_data = data->oob_nfc_dev->read_func(&len);
-	if (raw_data == NULL)
-		return NULL;
-
-	wifi = wpabuf_alloc_copy(raw_data, len);
-	os_free(raw_data);
-	if (wifi == NULL) {
-		wpa_printf(MSG_ERROR, "WPS (NFC): Failed to allocate "
-			   "nfc read area");
-		return NULL;
-	}
-
-	buf = ndef_parse_wifi(wifi);
-	wpabuf_free(wifi);
-	if (buf == NULL)
-		wpa_printf(MSG_ERROR, "WPS (NFC): Failed to unwrap");
-	return buf;
-}
-
-
-static int write_nfc(void *priv, struct wpabuf *buf)
-{
-	struct wps_nfc_data *data = priv;
-	struct wpabuf *wifi;
-	int ret;
-
-	wifi = ndef_build_wifi(buf);
-	if (wifi == NULL) {
-		wpa_printf(MSG_ERROR, "WPS (NFC): Failed to wrap");
-		return -1;
-	}
-
-	ret = data->oob_nfc_dev->write_func(wpabuf_mhead(wifi),
-					    wpabuf_len(wifi));
-	wpabuf_free(wifi);
-	return ret;
-}
-
-
-static void deinit_nfc(void *priv)
-{
-	struct wps_nfc_data *data = priv;
-
-	data->oob_nfc_dev->deinit_func();
-
-	os_free(data);
-}
-
-
-struct oob_device_data oob_nfc_device_data = {
-	.device_name	= NULL,
-	.device_path	= NULL,
-	.init_func	= init_nfc,
-	.read_func	= read_nfc,
-	.write_func	= write_nfc,
-	.deinit_func	= deinit_nfc,
-};
diff --git a/src/wps/wps_nfc_pn531.c b/src/wps/wps_nfc_pn531.c
deleted file mode 100644
index c2bf457..0000000
--- a/src/wps/wps_nfc_pn531.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * NFC PN531 routines for Wi-Fi Protected Setup
- * Copyright (c) 2009-2012, Masashi Honma <masashi.honma@gmail.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include "common.h"
-
-#include "wps/wps.h"
-#include "wps_i.h"
-
-#include "WpsNfcType.h"
-#include "WpsNfc.h"
-
-
-static int init_nfc_pn531(char *path)
-{
-	u32 ret;
-
-	ret = WpsNfcInit();
-	if (ret != WPS_NFCLIB_ERR_SUCCESS) {
-		wpa_printf(MSG_ERROR, "WPS (PN531): Failed to initialize "
-			   "NFC Library: 0x%08x", ret);
-		return -1;
-	}
-
-	ret = WpsNfcOpenDevice((int8 *) path);
-	if (ret != WPS_NFCLIB_ERR_SUCCESS) {
-		wpa_printf(MSG_ERROR, "WPS (PN531): Failed to open "
-			   "NFC Device(%s): 0x%08x", path, ret);
-		goto fail;
-	}
-
-	ret = WpsNfcTokenDiscovery();
-	if (ret != WPS_NFCLIB_ERR_SUCCESS) {
-		wpa_printf(MSG_ERROR, "WPS (PN531): Failed to discover "
-			   "token: 0x%08x", ret);
-		WpsNfcCloseDevice();
-		goto fail;
-	}
-
-	return 0;
-
-fail:
-	WpsNfcDeinit();
-	return -1;
-}
-
-
-static void * read_nfc_pn531(size_t *size)
-{
-	uint32 len;
-	u32 ret;
-	int8 *data;
-
-	ret = WpsNfcRawReadToken(&data, &len);
-	if (ret != WPS_NFCLIB_ERR_SUCCESS) {
-		wpa_printf(MSG_ERROR, "WPS (PN531): Failed to read: 0x%08x",
-			   ret);
-		return NULL;
-	}
-
-	*size = len;
-	return data;
-}
-
-
-static int write_nfc_pn531(void *data, size_t len)
-{
-	u32 ret;
-
-	ret = WpsNfcRawWriteToken(data, len);
-	if (ret != WPS_NFCLIB_ERR_SUCCESS) {
-		wpa_printf(MSG_ERROR, "WPS (PN531): Failed to write: 0x%08x",
-			   ret);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static void deinit_nfc_pn531(void)
-{
-	u32 ret;
-
-	ret = WpsNfcCloseDevice();
-	if (ret != WPS_NFCLIB_ERR_SUCCESS)
-		wpa_printf(MSG_ERROR, "WPS (PN531): Failed to close "
-			   "NFC Device: 0x%08x", ret);
-
-	ret = WpsNfcDeinit();
-	if (ret != WPS_NFCLIB_ERR_SUCCESS)
-		wpa_printf(MSG_ERROR, "WPS (PN531): Failed to deinitialize "
-			   "NFC Library: 0x%08x", ret);
-}
-
-
-struct oob_nfc_device_data oob_nfc_pn531_device_data = {
-	.init_func	= init_nfc_pn531,
-	.read_func	= read_nfc_pn531,
-	.write_func	= write_nfc_pn531,
-	.deinit_func	= deinit_nfc_pn531,
-};
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index 53684d6..b24836e 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -180,6 +180,9 @@
 	u8 authorized_macs_union[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN];
 
 	u8 p2p_dev_addr[ETH_ALEN];
+
+	u8 pbc_ignore_uuid[WPS_UUID_LEN];
+	struct os_time pbc_ignore_start;
 };
 
 
@@ -187,6 +190,8 @@
 static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx);
 static void wps_registrar_set_selected_timeout(void *eloop_ctx,
 					       void *timeout_ctx);
+static void wps_registrar_remove_pin(struct wps_registrar *reg,
+				     struct wps_uuid_pin *pin);
 
 
 static void wps_registrar_add_authorized_mac(struct wps_registrar *reg,
@@ -696,6 +701,21 @@
 }
 
 
+static void wps_registrar_invalidate_unused(struct wps_registrar *reg)
+{
+	struct wps_uuid_pin *pin;
+
+	dl_list_for_each(pin, &reg->pins, struct wps_uuid_pin, list) {
+		if (pin->wildcard_uuid == 1 && !(pin->flags & PIN_LOCKED)) {
+			wpa_printf(MSG_DEBUG, "WPS: Invalidate previously "
+				   "configured wildcard PIN");
+			wps_registrar_remove_pin(reg, pin);
+			break;
+		}
+	}
+}
+
+
 /**
  * wps_registrar_add_pin - Configure a new PIN for Registrar
  * @reg: Registrar data from wps_registrar_init()
@@ -735,6 +755,9 @@
 		p->expiration.sec += timeout;
 	}
 
+	if (p->wildcard_uuid)
+		wps_registrar_invalidate_unused(reg);
+
 	dl_list_add(&reg->pins, &p->list);
 
 	wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)",
@@ -1015,6 +1038,8 @@
 		wps_registrar_remove_pbc_session(registrar,
 						 uuid_e, NULL);
 		wps_registrar_pbc_completed(registrar);
+		os_get_time(&registrar->pbc_ignore_start);
+		os_memcpy(registrar->pbc_ignore_uuid, uuid_e, WPS_UUID_LEN);
 	} else {
 		wps_registrar_pin_completed(registrar);
 	}
@@ -1061,6 +1086,7 @@
 				int p2p_wildcard)
 {
 	struct wps_parse_attr attr;
+	int skip_add = 0;
 
 	wpa_hexdump_buf(MSG_MSGDUMP,
 			"WPS: Probe Request with WPS data received",
@@ -1112,7 +1138,24 @@
 	wpa_hexdump(MSG_DEBUG, "WPS: UUID-E from Probe Request", attr.uuid_e,
 		    WPS_UUID_LEN);
 
-	wps_registrar_add_pbc_session(reg, addr, attr.uuid_e);
+#ifdef WPS_WORKAROUNDS
+	if (reg->pbc_ignore_start.sec &&
+	    os_memcmp(attr.uuid_e, reg->pbc_ignore_uuid, WPS_UUID_LEN) == 0) {
+		struct os_time now, dur;
+		os_get_time(&now);
+		os_time_sub(&now, &reg->pbc_ignore_start, &dur);
+		if (dur.sec >= 0 && dur.sec < 5) {
+			wpa_printf(MSG_DEBUG, "WPS: Ignore PBC activation "
+				   "based on Probe Request from the Enrollee "
+				   "that just completed PBC provisioning");
+			skip_add = 1;
+		} else
+			reg->pbc_ignore_start.sec = 0;
+	}
+#endif /* WPS_WORKAROUNDS */
+
+	if (!skip_add)
+		wps_registrar_add_pbc_session(reg, addr, attr.uuid_e);
 	if (wps_registrar_pbc_overlap(reg, addr, attr.uuid_e)) {
 		wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected");
 		reg->force_pbc_overlap = 1;
@@ -2218,22 +2261,6 @@
 		return -1;
 	}
 
-#ifdef CONFIG_WPS_OOB
-	if (wps->wps->oob_conf.pubkey_hash != NULL) {
-		const u8 *addr[1];
-		u8 hash[WPS_HASH_LEN];
-
-		addr[0] = pk;
-		sha256_vector(1, addr, &pk_len, hash);
-		if (os_memcmp(hash,
-			      wpabuf_head(wps->wps->oob_conf.pubkey_hash),
-			      WPS_OOB_PUBKEY_HASH_LEN) != 0) {
-			wpa_printf(MSG_ERROR, "WPS: Public Key hash error");
-			return -1;
-		}
-	}
-#endif /* CONFIG_WPS_OOB */
-
 	wpabuf_free(wps->dh_pubkey_e);
 	wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len);
 	if (wps->dh_pubkey_e == NULL)
@@ -2529,16 +2556,6 @@
 	}
 #endif /* CONFIG_WPS_NFC */
 
-#ifdef CONFIG_WPS_OOB
-	if (wps->dev_pw_id >= 0x10 && wps->nfc_pw_token == NULL &&
-	    wps->dev_pw_id != wps->wps->oob_dev_pw_id) {
-		wpa_printf(MSG_DEBUG, "WPS: OOB Device Password ID "
-			   "%d mismatch", wps->dev_pw_id);
-		wps->state = SEND_M2D;
-		return WPS_CONTINUE;
-	}
-#endif /* CONFIG_WPS_OOB */
-
 	if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
 		if ((wps->wps->registrar->force_pbc_overlap ||
 		     wps_registrar_pbc_overlap(wps->wps->registrar,
@@ -3168,6 +3185,9 @@
 						 wps->uuid_e,
 						 wps->p2p_dev_addr);
 		wps_registrar_pbc_completed(wps->wps->registrar);
+		os_get_time(&wps->wps->registrar->pbc_ignore_start);
+		os_memcpy(wps->wps->registrar->pbc_ignore_uuid, wps->uuid_e,
+			  WPS_UUID_LEN);
 	} else {
 		wps_registrar_pin_completed(wps->wps->registrar);
 	}
diff --git a/src/wps/wps_ufd.c b/src/wps/wps_ufd.c
deleted file mode 100644
index f83bdf4..0000000
--- a/src/wps/wps_ufd.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * UFD routines for Wi-Fi Protected Setup
- * Copyright (c) 2009-2012, Masashi Honma <masashi.honma@gmail.com>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#include "includes.h"
-#include "common.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-
-#include "wps/wps.h"
-#include "wps/wps_i.h"
-
-#ifdef CONFIG_NATIVE_WINDOWS
-#define UFD_DIR1 "%s\\SMRTNTKY"
-#define UFD_DIR2 UFD_DIR1 "\\WFAWSC"
-#define UFD_FILE UFD_DIR2 "\\%s"
-#else /* CONFIG_NATIVE_WINDOWS */
-#define UFD_DIR1 "%s/SMRTNTKY"
-#define UFD_DIR2 UFD_DIR1 "/WFAWSC"
-#define UFD_FILE UFD_DIR2 "/%s"
-#endif /* CONFIG_NATIVE_WINDOWS */
-
-
-struct wps_ufd_data {
-	int ufd_fd;
-};
-
-
-static int dev_pwd_e_file_filter(const struct dirent *entry)
-{
-	unsigned int prefix;
-	char ext[5];
-
-	if (sscanf(entry->d_name, "%8x.%4s", &prefix, ext) != 2)
-		return 0;
-	if (prefix == 0)
-		return 0;
-	if (os_strcasecmp(ext, "WFA") != 0)
-		return 0;
-
-	return 1;
-}
-
-
-static int wps_get_dev_pwd_e_file_name(char *path, char *file_name)
-{
-	struct dirent **namelist;
-	int i, file_num;
-
-	file_num = scandir(path, &namelist, &dev_pwd_e_file_filter,
-			   alphasort);
-	if (file_num < 0) {
-		wpa_printf(MSG_ERROR, "WPS: OOB file not found: %d (%s)",
-			   errno, strerror(errno));
-		return -1;
-	}
-	if (file_num == 0) {
-		wpa_printf(MSG_ERROR, "WPS: OOB file not found");
-		os_free(namelist);
-		return -1;
-	}
-	os_strlcpy(file_name, namelist[0]->d_name, 13);
-	for (i = 0; i < file_num; i++)
-		os_free(namelist[i]);
-	os_free(namelist);
-	return 0;
-}
-
-
-static int get_file_name(struct wps_context *wps, int registrar,
-			 const char *path, char *file_name)
-{
-	switch (wps->oob_conf.oob_method) {
-	case OOB_METHOD_CRED:
-		os_snprintf(file_name, 13, "00000000.WSC");
-		break;
-	case OOB_METHOD_DEV_PWD_E:
-		if (registrar) {
-			char temp[128];
-			os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
-			if (wps_get_dev_pwd_e_file_name(temp, file_name) < 0)
-				return -1;
-		} else {
-			u8 *mac_addr = wps->dev.mac_addr;
-
-			os_snprintf(file_name, 13, "%02X%02X%02X%02X.WFA",
-				    mac_addr[2], mac_addr[3], mac_addr[4],
-				    mac_addr[5]);
-		}
-		break;
-	case OOB_METHOD_DEV_PWD_R:
-		os_snprintf(file_name, 13, "00000000.WFA");
-		break;
-	default:
-		wpa_printf(MSG_ERROR, "WPS: Invalid USBA OOB method");
-		return -1;
-	}
-	return 0;
-}
-
-
-static int ufd_mkdir(const char *path)
-{
-	if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST) {
-		wpa_printf(MSG_ERROR, "WPS (UFD): Failed to create directory "
-			   "'%s': %d (%s)", path, errno, strerror(errno));
-		return -1;
-	}
-	return 0;
-}
-
-
-static void * init_ufd(struct wps_context *wps,
-		       struct oob_device_data *oob_dev, int registrar)
-{
-	int write_f;
-	char temp[128];
-	char *path = oob_dev->device_path;
-	char filename[13];
-	struct wps_ufd_data *data;
-	int ufd_fd;
-
-	if (path == NULL)
-		return NULL;
-
-	write_f = wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ?
-		!registrar : registrar;
-
-	if (get_file_name(wps, registrar, path, filename) < 0) {
-		wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file name");
-		return NULL;
-	}
-
-	if (write_f) {
-		os_snprintf(temp, sizeof(temp), UFD_DIR1, path);
-		if (ufd_mkdir(temp))
-			return NULL;
-		os_snprintf(temp, sizeof(temp), UFD_DIR2, path);
-		if (ufd_mkdir(temp))
-			return NULL;
-	}
-
-	os_snprintf(temp, sizeof(temp), UFD_FILE, path, filename);
-	if (write_f)
-		ufd_fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC,
-			      S_IRUSR | S_IWUSR);
-	else
-		ufd_fd = open(temp, O_RDONLY);
-	if (ufd_fd < 0) {
-		wpa_printf(MSG_ERROR, "WPS (UFD): Failed to open %s: %s",
-			   temp, strerror(errno));
-		return NULL;
-	}
-
-	data = os_zalloc(sizeof(*data));
-	if (data == NULL) {
-		close(ufd_fd);
-		return NULL;
-	}
-	data->ufd_fd = ufd_fd;
-	return data;
-}
-
-
-static struct wpabuf * read_ufd(void *priv)
-{
-	struct wps_ufd_data *data = priv;
-	struct wpabuf *buf;
-	struct stat s;
-	size_t file_size;
-
-	if (fstat(data->ufd_fd, &s) < 0) {
-		wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file size");
-		return NULL;
-	}
-
-	file_size = s.st_size;
-	buf = wpabuf_alloc(file_size);
-	if (buf == NULL) {
-		wpa_printf(MSG_ERROR, "WPS (UFD): Failed to alloc read "
-			   "buffer");
-		return NULL;
-	}
-
-	if (read(data->ufd_fd, wpabuf_mhead(buf), file_size) !=
-	    (int) file_size) {
-		wpabuf_free(buf);
-		wpa_printf(MSG_ERROR, "WPS (UFD): Failed to read");
-		return NULL;
-	}
-	wpabuf_put(buf, file_size);
-	return buf;
-}
-
-
-static int write_ufd(void *priv, struct wpabuf *buf)
-{
-	struct wps_ufd_data *data = priv;
-
-	if (write(data->ufd_fd, wpabuf_mhead(buf), wpabuf_len(buf)) !=
-	    (int) wpabuf_len(buf)) {
-		wpa_printf(MSG_ERROR, "WPS (UFD): Failed to write");
-		return -1;
-	}
-	return 0;
-}
-
-
-static void deinit_ufd(void *priv)
-{
-	struct wps_ufd_data *data = priv;
-	close(data->ufd_fd);
-	os_free(data);
-}
-
-
-struct oob_device_data oob_ufd_device_data = {
-	.device_name	= NULL,
-	.device_path	= NULL,
-	.init_func	= init_ufd,
-	.read_func	= read_ufd,
-	.write_func	= write_ufd,
-	.deinit_func	= deinit_ufd,
-};