xref: /netbsd-src/external/bsd/wpa/dist/wpa_supplicant/wps_supplicant.c (revision e61202360d5611414dd6f6115934a96aa1f50b1a)
1 /*
2  * wpa_supplicant / WPS integration
3  * Copyright (c) 2008-2010, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 #include "eloop.h"
19 #include "uuid.h"
20 #include "crypto/dh_group5.h"
21 #include "common/ieee802_11_defs.h"
22 #include "common/ieee802_11_common.h"
23 #include "common/wpa_common.h"
24 #include "common/wpa_ctrl.h"
25 #include "eap_common/eap_wsc_common.h"
26 #include "eap_peer/eap.h"
27 #include "eapol_supp/eapol_supp_sm.h"
28 #include "rsn_supp/wpa.h"
29 #include "config.h"
30 #include "wpa_supplicant_i.h"
31 #include "driver_i.h"
32 #include "notify.h"
33 #include "blacklist.h"
34 #include "bss.h"
35 #include "scan.h"
36 #include "ap.h"
37 #include "p2p/p2p.h"
38 #include "p2p_supplicant.h"
39 #include "wps_supplicant.h"
40 
41 
42 #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
43 #define WPS_PIN_SCAN_IGNORE_SEL_REG 3
44 #endif /* WPS_PIN_SCAN_IGNORE_SEL_REG */
45 
46 static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx);
47 static void wpas_clear_wps(struct wpa_supplicant *wpa_s);
48 
49 
50 int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
51 {
52 	if (!wpa_s->wps_success &&
53 	    wpa_s->current_ssid &&
54 	    eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) {
55 		const u8 *bssid = wpa_s->bssid;
56 		if (is_zero_ether_addr(bssid))
57 			bssid = wpa_s->pending_bssid;
58 
59 		wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
60 			   " did not succeed - continue trying to find "
61 			   "suitable AP", MAC2STR(bssid));
62 		wpa_blacklist_add(wpa_s, bssid);
63 
64 		wpa_supplicant_deauthenticate(wpa_s,
65 					      WLAN_REASON_DEAUTH_LEAVING);
66 		wpa_s->reassociate = 1;
67 		wpa_supplicant_req_scan(wpa_s,
68 					wpa_s->blacklist_cleared ? 5 : 0, 0);
69 		wpa_s->blacklist_cleared = 0;
70 		return 1;
71 	}
72 
73 	eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
74 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && !wpa_s->wps_success)
75 		wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_FAIL);
76 
77 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid &&
78 	    !(wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
79 		int disabled = wpa_s->current_ssid->disabled;
80 		unsigned int freq = wpa_s->assoc_freq;
81 		wpa_printf(MSG_DEBUG, "WPS: Network configuration replaced - "
82 			   "try to associate with the received credential "
83 			   "(freq=%u)", freq);
84 		wpa_supplicant_deauthenticate(wpa_s,
85 					      WLAN_REASON_DEAUTH_LEAVING);
86 		if (disabled) {
87 			wpa_printf(MSG_DEBUG, "WPS: Current network is "
88 				   "disabled - wait for user to enable");
89 			return 1;
90 		}
91 		wpa_s->after_wps = 5;
92 		wpa_s->wps_freq = freq;
93 		wpa_s->reassociate = 1;
94 		wpa_supplicant_req_scan(wpa_s, 0, 0);
95 		return 1;
96 	}
97 
98 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS && wpa_s->current_ssid) {
99 		wpa_printf(MSG_DEBUG, "WPS: Registration completed - waiting "
100 			   "for external credential processing");
101 		wpas_clear_wps(wpa_s);
102 		wpa_supplicant_deauthenticate(wpa_s,
103 					      WLAN_REASON_DEAUTH_LEAVING);
104 		return 1;
105 	}
106 
107 	return 0;
108 }
109 
110 
111 static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s,
112 					 struct wpa_ssid *ssid,
113 					 const struct wps_credential *cred)
114 {
115 	struct wpa_driver_capa capa;
116 	struct wpa_bss *bss;
117 	const u8 *ie;
118 	struct wpa_ie_data adv;
119 	int wpa2 = 0, ccmp = 0;
120 
121 	/*
122 	 * Many existing WPS APs do not know how to negotiate WPA2 or CCMP in
123 	 * case they are configured for mixed mode operation (WPA+WPA2 and
124 	 * TKIP+CCMP). Try to use scan results to figure out whether the AP
125 	 * actually supports stronger security and select that if the client
126 	 * has support for it, too.
127 	 */
128 
129 	if (wpa_drv_get_capa(wpa_s, &capa))
130 		return; /* Unknown what driver supports */
131 
132 	if (ssid->ssid == NULL)
133 		return;
134 	bss = wpa_bss_get(wpa_s, cred->mac_addr, ssid->ssid, ssid->ssid_len);
135 	if (bss == NULL) {
136 		wpa_printf(MSG_DEBUG, "WPS: The AP was not found from BSS "
137 			   "table - use credential as-is");
138 		return;
139 	}
140 
141 	wpa_printf(MSG_DEBUG, "WPS: AP found from BSS table");
142 
143 	ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
144 	if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0) {
145 		wpa2 = 1;
146 		if (adv.pairwise_cipher & WPA_CIPHER_CCMP)
147 			ccmp = 1;
148 	} else {
149 		ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
150 		if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &adv) == 0 &&
151 		    adv.pairwise_cipher & WPA_CIPHER_CCMP)
152 			ccmp = 1;
153 	}
154 
155 	if (ie == NULL && (ssid->proto & WPA_PROTO_WPA) &&
156 	    (ssid->pairwise_cipher & WPA_CIPHER_TKIP)) {
157 		/*
158 		 * TODO: This could be the initial AP configuration and the
159 		 * Beacon contents could change shortly. Should request a new
160 		 * scan and delay addition of the network until the updated
161 		 * scan results are available.
162 		 */
163 		wpa_printf(MSG_DEBUG, "WPS: The AP did not yet advertise WPA "
164 			   "support - use credential as-is");
165 		return;
166 	}
167 
168 	if (ccmp && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
169 	    (ssid->pairwise_cipher & WPA_CIPHER_TKIP) &&
170 	    (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
171 		wpa_printf(MSG_DEBUG, "WPS: Add CCMP into the credential "
172 			   "based on scan results");
173 		if (wpa_s->conf->ap_scan == 1)
174 			ssid->pairwise_cipher |= WPA_CIPHER_CCMP;
175 		else
176 			ssid->pairwise_cipher = WPA_CIPHER_CCMP;
177 	}
178 
179 	if (wpa2 && !(ssid->proto & WPA_PROTO_RSN) &&
180 	    (ssid->proto & WPA_PROTO_WPA) &&
181 	    (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP)) {
182 		wpa_printf(MSG_DEBUG, "WPS: Add WPA2 into the credential "
183 			   "based on scan results");
184 		if (wpa_s->conf->ap_scan == 1)
185 			ssid->proto |= WPA_PROTO_RSN;
186 		else
187 			ssid->proto = WPA_PROTO_RSN;
188 	}
189 }
190 
191 
192 static int wpa_supplicant_wps_cred(void *ctx,
193 				   const struct wps_credential *cred)
194 {
195 	struct wpa_supplicant *wpa_s = ctx;
196 	struct wpa_ssid *ssid = wpa_s->current_ssid;
197 	u8 key_idx = 0;
198 	u16 auth_type;
199 #ifdef CONFIG_WPS_REG_DISABLE_OPEN
200 	int registrar = 0;
201 #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
202 
203 	if ((wpa_s->conf->wps_cred_processing == 1 ||
204 	     wpa_s->conf->wps_cred_processing == 2) && cred->cred_attr) {
205 		size_t blen = cred->cred_attr_len * 2 + 1;
206 		char *buf = os_malloc(blen);
207 		if (buf) {
208 			wpa_snprintf_hex(buf, blen,
209 					 cred->cred_attr, cred->cred_attr_len);
210 			wpa_msg(wpa_s, MSG_INFO, "%s%s",
211 				WPS_EVENT_CRED_RECEIVED, buf);
212 			os_free(buf);
213 		}
214 
215 		wpas_notify_wps_credential(wpa_s, cred);
216 	} else
217 		wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_CRED_RECEIVED);
218 
219 	wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
220 			cred->cred_attr, cred->cred_attr_len);
221 
222 	if (wpa_s->conf->wps_cred_processing == 1)
223 		return 0;
224 
225 	wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len);
226 	wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x",
227 		   cred->auth_type);
228 	wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type);
229 	wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx);
230 	wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key",
231 			cred->key, cred->key_len);
232 	wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR,
233 		   MAC2STR(cred->mac_addr));
234 
235 	auth_type = cred->auth_type;
236 	if (auth_type == (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
237 		wpa_printf(MSG_DEBUG, "WPS: Workaround - convert mixed-mode "
238 			   "auth_type into WPA2PSK");
239 		auth_type = WPS_AUTH_WPA2PSK;
240 	}
241 
242 	if (auth_type != WPS_AUTH_OPEN &&
243 	    auth_type != WPS_AUTH_SHARED &&
244 	    auth_type != WPS_AUTH_WPAPSK &&
245 	    auth_type != WPS_AUTH_WPA2PSK) {
246 		wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for "
247 			   "unsupported authentication type 0x%x",
248 			   auth_type);
249 		return 0;
250 	}
251 
252 	if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
253 		wpa_printf(MSG_DEBUG, "WPS: Replace WPS network block based "
254 			   "on the received credential");
255 #ifdef CONFIG_WPS_REG_DISABLE_OPEN
256 		if (ssid->eap.identity &&
257 		    ssid->eap.identity_len == WSC_ID_REGISTRAR_LEN &&
258 		    os_memcmp(ssid->eap.identity, WSC_ID_REGISTRAR,
259 			      WSC_ID_REGISTRAR_LEN) == 0)
260 			registrar = 1;
261 #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
262 		os_free(ssid->eap.identity);
263 		ssid->eap.identity = NULL;
264 		ssid->eap.identity_len = 0;
265 		os_free(ssid->eap.phase1);
266 		ssid->eap.phase1 = NULL;
267 		os_free(ssid->eap.eap_methods);
268 		ssid->eap.eap_methods = NULL;
269 		if (!ssid->p2p_group)
270 			ssid->temporary = 0;
271 	} else {
272 		wpa_printf(MSG_DEBUG, "WPS: Create a new network based on the "
273 			   "received credential");
274 		ssid = wpa_config_add_network(wpa_s->conf);
275 		if (ssid == NULL)
276 			return -1;
277 		wpas_notify_network_added(wpa_s, ssid);
278 	}
279 
280 	wpa_config_set_network_defaults(ssid);
281 
282 	os_free(ssid->ssid);
283 	ssid->ssid = os_malloc(cred->ssid_len);
284 	if (ssid->ssid) {
285 		os_memcpy(ssid->ssid, cred->ssid, cred->ssid_len);
286 		ssid->ssid_len = cred->ssid_len;
287 	}
288 
289 	switch (cred->encr_type) {
290 	case WPS_ENCR_NONE:
291 		break;
292 	case WPS_ENCR_WEP:
293 		if (cred->key_len <= 0)
294 			break;
295 		if (cred->key_len != 5 && cred->key_len != 13 &&
296 		    cred->key_len != 10 && cred->key_len != 26) {
297 			wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key length "
298 				   "%lu", (unsigned long) cred->key_len);
299 			return -1;
300 		}
301 		if (cred->key_idx > NUM_WEP_KEYS) {
302 			wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key index %d",
303 				   cred->key_idx);
304 			return -1;
305 		}
306 		if (cred->key_idx)
307 			key_idx = cred->key_idx - 1;
308 		if (cred->key_len == 10 || cred->key_len == 26) {
309 			if (hexstr2bin((char *) cred->key,
310 				       ssid->wep_key[key_idx],
311 				       cred->key_len / 2) < 0) {
312 				wpa_printf(MSG_ERROR, "WPS: Invalid WEP Key "
313 					   "%d", key_idx);
314 				return -1;
315 			}
316 			ssid->wep_key_len[key_idx] = cred->key_len / 2;
317 		} else {
318 			os_memcpy(ssid->wep_key[key_idx], cred->key,
319 				  cred->key_len);
320 			ssid->wep_key_len[key_idx] = cred->key_len;
321 		}
322 		ssid->wep_tx_keyidx = key_idx;
323 		break;
324 	case WPS_ENCR_TKIP:
325 		ssid->pairwise_cipher = WPA_CIPHER_TKIP;
326 		break;
327 	case WPS_ENCR_AES:
328 		ssid->pairwise_cipher = WPA_CIPHER_CCMP;
329 		break;
330 	}
331 
332 	switch (auth_type) {
333 	case WPS_AUTH_OPEN:
334 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
335 		ssid->key_mgmt = WPA_KEY_MGMT_NONE;
336 		ssid->proto = 0;
337 #ifdef CONFIG_WPS_REG_DISABLE_OPEN
338 		if (registrar) {
339 			wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OPEN_NETWORK
340 				"id=%d - Credentials for an open "
341 				"network disabled by default - use "
342 				"'select_network %d' to enable",
343 				ssid->id, ssid->id);
344 			ssid->disabled = 1;
345 		}
346 #endif /* CONFIG_WPS_REG_DISABLE_OPEN */
347 		break;
348 	case WPS_AUTH_SHARED:
349 		ssid->auth_alg = WPA_AUTH_ALG_SHARED;
350 		ssid->key_mgmt = WPA_KEY_MGMT_NONE;
351 		ssid->proto = 0;
352 		break;
353 	case WPS_AUTH_WPAPSK:
354 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
355 		ssid->key_mgmt = WPA_KEY_MGMT_PSK;
356 		ssid->proto = WPA_PROTO_WPA;
357 		break;
358 	case WPS_AUTH_WPA:
359 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
360 		ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
361 		ssid->proto = WPA_PROTO_WPA;
362 		break;
363 	case WPS_AUTH_WPA2:
364 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
365 		ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
366 		ssid->proto = WPA_PROTO_RSN;
367 		break;
368 	case WPS_AUTH_WPA2PSK:
369 		ssid->auth_alg = WPA_AUTH_ALG_OPEN;
370 		ssid->key_mgmt = WPA_KEY_MGMT_PSK;
371 		ssid->proto = WPA_PROTO_RSN;
372 		break;
373 	}
374 
375 	if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) {
376 		if (cred->key_len == 2 * PMK_LEN) {
377 			if (hexstr2bin((const char *) cred->key, ssid->psk,
378 				       PMK_LEN)) {
379 				wpa_printf(MSG_ERROR, "WPS: Invalid Network "
380 					   "Key");
381 				return -1;
382 			}
383 			ssid->psk_set = 1;
384 			ssid->export_keys = 1;
385 		} else if (cred->key_len >= 8 && cred->key_len < 2 * PMK_LEN) {
386 			os_free(ssid->passphrase);
387 			ssid->passphrase = os_malloc(cred->key_len + 1);
388 			if (ssid->passphrase == NULL)
389 				return -1;
390 			os_memcpy(ssid->passphrase, cred->key, cred->key_len);
391 			ssid->passphrase[cred->key_len] = '\0';
392 			wpa_config_update_psk(ssid);
393 			ssid->export_keys = 1;
394 		} else {
395 			wpa_printf(MSG_ERROR, "WPS: Invalid Network Key "
396 				   "length %lu",
397 				   (unsigned long) cred->key_len);
398 			return -1;
399 		}
400 	}
401 
402 	wpas_wps_security_workaround(wpa_s, ssid, cred);
403 
404 #ifndef CONFIG_NO_CONFIG_WRITE
405 	if (wpa_s->conf->update_config &&
406 	    wpa_config_write(wpa_s->confname, wpa_s->conf)) {
407 		wpa_printf(MSG_DEBUG, "WPS: Failed to update configuration");
408 		return -1;
409 	}
410 #endif /* CONFIG_NO_CONFIG_WRITE */
411 
412 	return 0;
413 }
414 
415 
416 #ifdef CONFIG_P2P
417 static void wpas_wps_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx)
418 {
419 	struct wpa_supplicant *wpa_s = eloop_ctx;
420 	wpas_p2p_notif_pbc_overlap(wpa_s);
421 }
422 #endif /* CONFIG_P2P */
423 
424 
425 static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s,
426 					 struct wps_event_m2d *m2d)
427 {
428 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_M2D
429 		"dev_password_id=%d config_error=%d",
430 		m2d->dev_password_id, m2d->config_error);
431 	wpas_notify_wps_event_m2d(wpa_s, m2d);
432 #ifdef CONFIG_P2P
433 	if (wpa_s->parent && wpa_s->parent != wpa_s) {
434 		wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_M2D
435 			"dev_password_id=%d config_error=%d",
436 			m2d->dev_password_id, m2d->config_error);
437 	}
438 	if (m2d->config_error == WPS_CFG_MULTIPLE_PBC_DETECTED) {
439 		/*
440 		 * Notify P2P from eloop timeout to avoid issues with the
441 		 * interface getting removed while processing a message.
442 		 */
443 		eloop_register_timeout(0, 0, wpas_wps_pbc_overlap_cb, wpa_s,
444 				       NULL);
445 	}
446 #endif /* CONFIG_P2P */
447 }
448 
449 
450 static const char * wps_event_fail_reason[NUM_WPS_EI_VALUES] = {
451 	"No Error", /* WPS_EI_NO_ERROR */
452 	"TKIP Only Prohibited", /* WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED */
453 	"WEP Prohibited" /* WPS_EI_SECURITY_WEP_PROHIBITED */
454 };
455 
456 static void wpa_supplicant_wps_event_fail(struct wpa_supplicant *wpa_s,
457 					  struct wps_event_fail *fail)
458 {
459 	if (fail->error_indication > 0 &&
460 	    fail->error_indication < NUM_WPS_EI_VALUES) {
461 		wpa_msg(wpa_s, MSG_INFO,
462 			WPS_EVENT_FAIL "msg=%d config_error=%d reason=%d (%s)",
463 			fail->msg, fail->config_error, fail->error_indication,
464 			wps_event_fail_reason[fail->error_indication]);
465 		if (wpa_s->parent && wpa_s->parent != wpa_s)
466 			wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
467 				"msg=%d config_error=%d reason=%d (%s)",
468 				fail->msg, fail->config_error,
469 				fail->error_indication,
470 				wps_event_fail_reason[fail->error_indication]);
471 	} else {
472 		wpa_msg(wpa_s, MSG_INFO,
473 			WPS_EVENT_FAIL "msg=%d config_error=%d",
474 			fail->msg, fail->config_error);
475 		if (wpa_s->parent && wpa_s->parent != wpa_s)
476 			wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_FAIL
477 				"msg=%d config_error=%d",
478 				fail->msg, fail->config_error);
479 	}
480 	wpas_clear_wps(wpa_s);
481 	wpas_notify_wps_event_fail(wpa_s, fail);
482 #ifdef CONFIG_P2P
483 	wpas_p2p_wps_failed(wpa_s, fail);
484 #endif /* CONFIG_P2P */
485 }
486 
487 
488 static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s)
489 {
490 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_SUCCESS);
491 	wpa_s->wps_success = 1;
492 	wpas_notify_wps_event_success(wpa_s);
493 #ifdef CONFIG_P2P
494 	wpas_p2p_wps_success(wpa_s, wpa_s->bssid, 0);
495 #endif /* CONFIG_P2P */
496 }
497 
498 
499 static void wpa_supplicant_wps_event_er_ap_add(struct wpa_supplicant *wpa_s,
500 					       struct wps_event_er_ap *ap)
501 {
502 	char uuid_str[100];
503 	char dev_type[WPS_DEV_TYPE_BUFSIZE];
504 
505 	uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str));
506 	if (ap->pri_dev_type)
507 		wps_dev_type_bin2str(ap->pri_dev_type, dev_type,
508 				     sizeof(dev_type));
509 	else
510 		dev_type[0] = '\0';
511 
512 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_ADD "%s " MACSTR
513 		" pri_dev_type=%s wps_state=%d |%s|%s|%s|%s|%s|%s|",
514 		uuid_str, MAC2STR(ap->mac_addr), dev_type, ap->wps_state,
515 		ap->friendly_name ? ap->friendly_name : "",
516 		ap->manufacturer ? ap->manufacturer : "",
517 		ap->model_description ? ap->model_description : "",
518 		ap->model_name ? ap->model_name : "",
519 		ap->manufacturer_url ? ap->manufacturer_url : "",
520 		ap->model_url ? ap->model_url : "");
521 }
522 
523 
524 static void wpa_supplicant_wps_event_er_ap_remove(struct wpa_supplicant *wpa_s,
525 						  struct wps_event_er_ap *ap)
526 {
527 	char uuid_str[100];
528 	uuid_bin2str(ap->uuid, uuid_str, sizeof(uuid_str));
529 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_REMOVE "%s", uuid_str);
530 }
531 
532 
533 static void wpa_supplicant_wps_event_er_enrollee_add(
534 	struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee)
535 {
536 	char uuid_str[100];
537 	char dev_type[WPS_DEV_TYPE_BUFSIZE];
538 
539 	uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str));
540 	if (enrollee->pri_dev_type)
541 		wps_dev_type_bin2str(enrollee->pri_dev_type, dev_type,
542 				     sizeof(dev_type));
543 	else
544 		dev_type[0] = '\0';
545 
546 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_ADD "%s " MACSTR
547 		" M1=%d config_methods=0x%x dev_passwd_id=%d pri_dev_type=%s "
548 		"|%s|%s|%s|%s|%s|",
549 		uuid_str, MAC2STR(enrollee->mac_addr), enrollee->m1_received,
550 		enrollee->config_methods, enrollee->dev_passwd_id, dev_type,
551 		enrollee->dev_name ? enrollee->dev_name : "",
552 		enrollee->manufacturer ? enrollee->manufacturer : "",
553 		enrollee->model_name ? enrollee->model_name : "",
554 		enrollee->model_number ? enrollee->model_number : "",
555 		enrollee->serial_number ? enrollee->serial_number : "");
556 }
557 
558 
559 static void wpa_supplicant_wps_event_er_enrollee_remove(
560 	struct wpa_supplicant *wpa_s, struct wps_event_er_enrollee *enrollee)
561 {
562 	char uuid_str[100];
563 	uuid_bin2str(enrollee->uuid, uuid_str, sizeof(uuid_str));
564 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_ENROLLEE_REMOVE "%s " MACSTR,
565 		uuid_str, MAC2STR(enrollee->mac_addr));
566 }
567 
568 
569 static void wpa_supplicant_wps_event_er_ap_settings(
570 	struct wpa_supplicant *wpa_s,
571 	struct wps_event_er_ap_settings *ap_settings)
572 {
573 	char uuid_str[100];
574 	char key_str[65];
575 	const struct wps_credential *cred = ap_settings->cred;
576 
577 	key_str[0] = '\0';
578 	if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) {
579 		if (cred->key_len >= 8 && cred->key_len <= 64) {
580 			os_memcpy(key_str, cred->key, cred->key_len);
581 			key_str[cred->key_len] = '\0';
582 		}
583 	}
584 
585 	uuid_bin2str(ap_settings->uuid, uuid_str, sizeof(uuid_str));
586 	/* Use wpa_msg_ctrl to avoid showing the key in debug log */
587 	wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_ER_AP_SETTINGS
588 		     "uuid=%s ssid=%s auth_type=0x%04x encr_type=0x%04x "
589 		     "key=%s",
590 		     uuid_str, wpa_ssid_txt(cred->ssid, cred->ssid_len),
591 		     cred->auth_type, cred->encr_type, key_str);
592 }
593 
594 
595 static void wpa_supplicant_wps_event_er_set_sel_reg(
596 	struct wpa_supplicant *wpa_s,
597 	struct wps_event_er_set_selected_registrar *ev)
598 {
599 	char uuid_str[100];
600 
601 	uuid_bin2str(ev->uuid, uuid_str, sizeof(uuid_str));
602 	switch (ev->state) {
603 	case WPS_ER_SET_SEL_REG_START:
604 		wpa_msg(wpa_s, MSG_DEBUG, WPS_EVENT_ER_SET_SEL_REG
605 			"uuid=%s state=START sel_reg=%d dev_passwd_id=%u "
606 			"sel_reg_config_methods=0x%x",
607 			uuid_str, ev->sel_reg, ev->dev_passwd_id,
608 			ev->sel_reg_config_methods);
609 		break;
610 	case WPS_ER_SET_SEL_REG_DONE:
611 		wpa_msg(wpa_s, MSG_DEBUG, WPS_EVENT_ER_SET_SEL_REG
612 			"uuid=%s state=DONE", uuid_str);
613 		break;
614 	case WPS_ER_SET_SEL_REG_FAILED:
615 		wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_ER_SET_SEL_REG
616 			"uuid=%s state=FAILED", uuid_str);
617 		break;
618 	}
619 }
620 
621 
622 static void wpa_supplicant_wps_event(void *ctx, enum wps_event event,
623 				     union wps_event_data *data)
624 {
625 	struct wpa_supplicant *wpa_s = ctx;
626 	switch (event) {
627 	case WPS_EV_M2D:
628 		wpa_supplicant_wps_event_m2d(wpa_s, &data->m2d);
629 		break;
630 	case WPS_EV_FAIL:
631 		wpa_supplicant_wps_event_fail(wpa_s, &data->fail);
632 		break;
633 	case WPS_EV_SUCCESS:
634 		wpa_supplicant_wps_event_success(wpa_s);
635 		break;
636 	case WPS_EV_PWD_AUTH_FAIL:
637 #ifdef CONFIG_AP
638 		if (wpa_s->ap_iface && data->pwd_auth_fail.enrollee)
639 			wpa_supplicant_ap_pwd_auth_fail(wpa_s);
640 #endif /* CONFIG_AP */
641 		break;
642 	case WPS_EV_PBC_OVERLAP:
643 		break;
644 	case WPS_EV_PBC_TIMEOUT:
645 		break;
646 	case WPS_EV_ER_AP_ADD:
647 		wpa_supplicant_wps_event_er_ap_add(wpa_s, &data->ap);
648 		break;
649 	case WPS_EV_ER_AP_REMOVE:
650 		wpa_supplicant_wps_event_er_ap_remove(wpa_s, &data->ap);
651 		break;
652 	case WPS_EV_ER_ENROLLEE_ADD:
653 		wpa_supplicant_wps_event_er_enrollee_add(wpa_s,
654 							 &data->enrollee);
655 		break;
656 	case WPS_EV_ER_ENROLLEE_REMOVE:
657 		wpa_supplicant_wps_event_er_enrollee_remove(wpa_s,
658 							    &data->enrollee);
659 		break;
660 	case WPS_EV_ER_AP_SETTINGS:
661 		wpa_supplicant_wps_event_er_ap_settings(wpa_s,
662 							&data->ap_settings);
663 		break;
664 	case WPS_EV_ER_SET_SELECTED_REGISTRAR:
665 		wpa_supplicant_wps_event_er_set_sel_reg(wpa_s,
666 							&data->set_sel_reg);
667 		break;
668 	case WPS_EV_AP_PIN_SUCCESS:
669 		break;
670 	}
671 }
672 
673 
674 enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid)
675 {
676 	if (eap_is_wps_pbc_enrollee(&ssid->eap) ||
677 	    eap_is_wps_pin_enrollee(&ssid->eap))
678 		return WPS_REQ_ENROLLEE;
679 	else
680 		return WPS_REQ_REGISTRAR;
681 }
682 
683 
684 static void wpas_clear_wps(struct wpa_supplicant *wpa_s)
685 {
686 	int id;
687 	struct wpa_ssid *ssid, *remove_ssid = NULL, *prev_current;
688 
689 	prev_current = wpa_s->current_ssid;
690 
691 	eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
692 
693 	/* Remove any existing WPS network from configuration */
694 	ssid = wpa_s->conf->ssid;
695 	while (ssid) {
696 		if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
697 			if (ssid == wpa_s->current_ssid) {
698 				wpa_s->current_ssid = NULL;
699 				if (ssid != NULL)
700 					wpas_notify_network_changed(wpa_s);
701 			}
702 			id = ssid->id;
703 			remove_ssid = ssid;
704 		} else
705 			id = -1;
706 		ssid = ssid->next;
707 		if (id >= 0) {
708 			if (prev_current == remove_ssid) {
709 				wpa_sm_set_config(wpa_s->wpa, NULL);
710 				eapol_sm_notify_config(wpa_s->eapol, NULL,
711 						       NULL);
712 			}
713 			wpas_notify_network_removed(wpa_s, remove_ssid);
714 			wpa_config_remove_network(wpa_s->conf, id);
715 		}
716 	}
717 }
718 
719 
720 static void wpas_wps_timeout(void *eloop_ctx, void *timeout_ctx)
721 {
722 	struct wpa_supplicant *wpa_s = eloop_ctx;
723 	wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_TIMEOUT "Requested operation timed "
724 		"out");
725 	wpas_clear_wps(wpa_s);
726 }
727 
728 
729 static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s,
730 					      int registrar, const u8 *bssid)
731 {
732 	struct wpa_ssid *ssid;
733 
734 	ssid = wpa_config_add_network(wpa_s->conf);
735 	if (ssid == NULL)
736 		return NULL;
737 	wpas_notify_network_added(wpa_s, ssid);
738 	wpa_config_set_network_defaults(ssid);
739 	ssid->temporary = 1;
740 	if (wpa_config_set(ssid, "key_mgmt", "WPS", 0) < 0 ||
741 	    wpa_config_set(ssid, "eap", "WSC", 0) < 0 ||
742 	    wpa_config_set(ssid, "identity", registrar ?
743 			   "\"" WSC_ID_REGISTRAR "\"" :
744 			   "\"" WSC_ID_ENROLLEE "\"", 0) < 0) {
745 		wpas_notify_network_removed(wpa_s, ssid);
746 		wpa_config_remove_network(wpa_s->conf, ssid->id);
747 		return NULL;
748 	}
749 
750 	if (bssid) {
751 #ifndef CONFIG_P2P
752 		struct wpa_bss *bss;
753 		int count = 0;
754 #endif /* CONFIG_P2P */
755 
756 		os_memcpy(ssid->bssid, bssid, ETH_ALEN);
757 		ssid->bssid_set = 1;
758 
759 		/*
760 		 * Note: With P2P, the SSID may change at the time the WPS
761 		 * provisioning is started, so better not filter the AP based
762 		 * on the current SSID in the scan results.
763 		 */
764 #ifndef CONFIG_P2P
765 		dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
766 			if (os_memcmp(bssid, bss->bssid, ETH_ALEN) != 0)
767 				continue;
768 
769 			os_free(ssid->ssid);
770 			ssid->ssid = os_malloc(bss->ssid_len);
771 			if (ssid->ssid == NULL)
772 				break;
773 			os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len);
774 			ssid->ssid_len = bss->ssid_len;
775 			wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from "
776 					  "scan results",
777 					  ssid->ssid, ssid->ssid_len);
778 			count++;
779 		}
780 
781 		if (count > 1) {
782 			wpa_printf(MSG_DEBUG, "WPS: More than one SSID found "
783 				   "for the AP; use wildcard");
784 			os_free(ssid->ssid);
785 			ssid->ssid = NULL;
786 			ssid->ssid_len = 0;
787 		}
788 #endif /* CONFIG_P2P */
789 	}
790 
791 	return ssid;
792 }
793 
794 
795 static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
796 			     struct wpa_ssid *selected)
797 {
798 	struct wpa_ssid *ssid;
799 
800 	if (wpa_s->current_ssid)
801 		wpa_supplicant_deauthenticate(
802 			wpa_s, WLAN_REASON_DEAUTH_LEAVING);
803 
804 	/* Mark all other networks disabled and trigger reassociation */
805 	ssid = wpa_s->conf->ssid;
806 	while (ssid) {
807 		int was_disabled = ssid->disabled;
808 		/*
809 		 * In case the network object corresponds to a persistent group
810 		 * then do not send out network disabled signal. In addition,
811 		 * do not change disabled status of persistent network objects
812 		 * from 2 to 1 should we connect to another network.
813 		 */
814 		if (was_disabled != 2) {
815 			ssid->disabled = ssid != selected;
816 			if (was_disabled != ssid->disabled)
817 				wpas_notify_network_enabled_changed(wpa_s,
818 								    ssid);
819 		}
820 		ssid = ssid->next;
821 	}
822 	wpa_s->disconnected = 0;
823 	wpa_s->reassociate = 1;
824 	wpa_s->scan_runs = 0;
825 	wpa_s->wps_success = 0;
826 	wpa_s->blacklist_cleared = 0;
827 	wpa_supplicant_req_scan(wpa_s, 0, 0);
828 }
829 
830 
831 int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid,
832 		       int p2p_group)
833 {
834 	struct wpa_ssid *ssid;
835 	wpas_clear_wps(wpa_s);
836 	ssid = wpas_wps_add_network(wpa_s, 0, bssid);
837 	if (ssid == NULL)
838 		return -1;
839 	ssid->temporary = 1;
840 	ssid->p2p_group = p2p_group;
841 #ifdef CONFIG_P2P
842 	if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
843 		ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
844 		if (ssid->ssid) {
845 			ssid->ssid_len = wpa_s->go_params->ssid_len;
846 			os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
847 				  ssid->ssid_len);
848 			wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
849 					  "SSID", ssid->ssid, ssid->ssid_len);
850 		}
851 	}
852 #endif /* CONFIG_P2P */
853 	wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0);
854 	if (wpa_s->wps_fragment_size)
855 		ssid->eap.fragment_size = wpa_s->wps_fragment_size;
856 	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
857 			       wpa_s, NULL);
858 	wpas_wps_reassoc(wpa_s, ssid);
859 	return 0;
860 }
861 
862 
863 int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid,
864 		       const char *pin, int p2p_group, u16 dev_pw_id)
865 {
866 	struct wpa_ssid *ssid;
867 	char val[128];
868 	unsigned int rpin = 0;
869 
870 	wpas_clear_wps(wpa_s);
871 	ssid = wpas_wps_add_network(wpa_s, 0, bssid);
872 	if (ssid == NULL)
873 		return -1;
874 	ssid->temporary = 1;
875 	ssid->p2p_group = p2p_group;
876 #ifdef CONFIG_P2P
877 	if (p2p_group && wpa_s->go_params && wpa_s->go_params->ssid_len) {
878 		ssid->ssid = os_zalloc(wpa_s->go_params->ssid_len + 1);
879 		if (ssid->ssid) {
880 			ssid->ssid_len = wpa_s->go_params->ssid_len;
881 			os_memcpy(ssid->ssid, wpa_s->go_params->ssid,
882 				  ssid->ssid_len);
883 			wpa_hexdump_ascii(MSG_DEBUG, "WPS: Use specific AP "
884 					  "SSID", ssid->ssid, ssid->ssid_len);
885 		}
886 	}
887 #endif /* CONFIG_P2P */
888 	if (pin)
889 		os_snprintf(val, sizeof(val), "\"pin=%s dev_pw_id=%u\"",
890 			    pin, dev_pw_id);
891 	else {
892 		rpin = wps_generate_pin();
893 		os_snprintf(val, sizeof(val), "\"pin=%08d dev_pw_id=%u\"",
894 			    rpin, dev_pw_id);
895 	}
896 	wpa_config_set(ssid, "phase1", val, 0);
897 	if (wpa_s->wps_fragment_size)
898 		ssid->eap.fragment_size = wpa_s->wps_fragment_size;
899 	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
900 			       wpa_s, NULL);
901 	wpas_wps_reassoc(wpa_s, ssid);
902 	return rpin;
903 }
904 
905 
906 /* Cancel the wps pbc/pin requests */
907 int wpas_wps_cancel(struct wpa_supplicant *wpa_s)
908 {
909 #ifdef CONFIG_AP
910 	if (wpa_s->ap_iface) {
911 		wpa_printf(MSG_DEBUG, "WPS: Cancelling in AP mode");
912 		return wpa_supplicant_ap_wps_cancel(wpa_s);
913 	}
914 #endif /* CONFIG_AP */
915 
916 	if (wpa_s->wpa_state == WPA_SCANNING) {
917 		wpa_printf(MSG_DEBUG, "WPS: Cancel operation - cancel scan");
918 		wpa_supplicant_cancel_scan(wpa_s);
919 		wpas_clear_wps(wpa_s);
920 	} else if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
921 		wpa_printf(MSG_DEBUG, "WPS: Cancel operation - "
922 			   "deauthenticate");
923 		wpa_supplicant_deauthenticate(wpa_s,
924 					      WLAN_REASON_DEAUTH_LEAVING);
925 		wpas_clear_wps(wpa_s);
926 	}
927 
928 	return 0;
929 }
930 
931 
932 #ifdef CONFIG_WPS_OOB
933 int wpas_wps_start_oob(struct wpa_supplicant *wpa_s, char *device_type,
934 		       char *path, char *method, char *name)
935 {
936 	struct wps_context *wps = wpa_s->wps;
937 	struct oob_device_data *oob_dev;
938 
939 	oob_dev = wps_get_oob_device(device_type);
940 	if (oob_dev == NULL)
941 		return -1;
942 	oob_dev->device_path = path;
943 	oob_dev->device_name = name;
944 	wps->oob_conf.oob_method = wps_get_oob_method(method);
945 
946 	if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E) {
947 		/*
948 		 * Use pre-configured DH keys in order to be able to write the
949 		 * key hash into the OOB file.
950 		 */
951 		wpabuf_free(wps->dh_pubkey);
952 		wpabuf_free(wps->dh_privkey);
953 		wps->dh_privkey = NULL;
954 		wps->dh_pubkey = NULL;
955 		dh5_free(wps->dh_ctx);
956 		wps->dh_ctx = dh5_init(&wps->dh_privkey, &wps->dh_pubkey);
957 		wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192);
958 		if (wps->dh_ctx == NULL || wps->dh_pubkey == NULL) {
959 			wpa_printf(MSG_ERROR, "WPS: Failed to initialize "
960 				   "Diffie-Hellman handshake");
961 			return -1;
962 		}
963 	}
964 
965 	if (wps->oob_conf.oob_method == OOB_METHOD_CRED)
966 		wpas_clear_wps(wpa_s);
967 
968 	if (wps_process_oob(wps, oob_dev, 0) < 0)
969 		return -1;
970 
971 	if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ||
972 	     wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) &&
973 	    wpas_wps_start_pin(wpa_s, NULL,
974 			       wpabuf_head(wps->oob_conf.dev_password), 0,
975 			       DEV_PW_DEFAULT) < 0)
976 			return -1;
977 
978 	return 0;
979 }
980 #endif /* CONFIG_WPS_OOB */
981 
982 
983 int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid,
984 		       const char *pin, struct wps_new_ap_settings *settings)
985 {
986 	struct wpa_ssid *ssid;
987 	char val[200];
988 	char *pos, *end;
989 	int res;
990 
991 	if (!pin)
992 		return -1;
993 	wpas_clear_wps(wpa_s);
994 	ssid = wpas_wps_add_network(wpa_s, 1, bssid);
995 	if (ssid == NULL)
996 		return -1;
997 	ssid->temporary = 1;
998 	pos = val;
999 	end = pos + sizeof(val);
1000 	res = os_snprintf(pos, end - pos, "\"pin=%s", pin);
1001 	if (res < 0 || res >= end - pos)
1002 		return -1;
1003 	pos += res;
1004 	if (settings) {
1005 		res = os_snprintf(pos, end - pos, " new_ssid=%s new_auth=%s "
1006 				  "new_encr=%s new_key=%s",
1007 				  settings->ssid_hex, settings->auth,
1008 				  settings->encr, settings->key_hex);
1009 		if (res < 0 || res >= end - pos)
1010 			return -1;
1011 		pos += res;
1012 	}
1013 	res = os_snprintf(pos, end - pos, "\"");
1014 	if (res < 0 || res >= end - pos)
1015 		return -1;
1016 	wpa_config_set(ssid, "phase1", val, 0);
1017 	if (wpa_s->wps_fragment_size)
1018 		ssid->eap.fragment_size = wpa_s->wps_fragment_size;
1019 	eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout,
1020 			       wpa_s, NULL);
1021 	wpas_wps_reassoc(wpa_s, ssid);
1022 	return 0;
1023 }
1024 
1025 
1026 static int wpas_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
1027 			       size_t psk_len)
1028 {
1029 	wpa_printf(MSG_DEBUG, "WPS: Received new WPA/WPA2-PSK from WPS for "
1030 		   "STA " MACSTR, MAC2STR(mac_addr));
1031 	wpa_hexdump_key(MSG_DEBUG, "Per-device PSK", psk, psk_len);
1032 
1033 	/* TODO */
1034 
1035 	return 0;
1036 }
1037 
1038 
1039 static void wpas_wps_pin_needed_cb(void *ctx, const u8 *uuid_e,
1040 				   const struct wps_device_data *dev)
1041 {
1042 	char uuid[40], txt[400];
1043 	int len;
1044 	char devtype[WPS_DEV_TYPE_BUFSIZE];
1045 	if (uuid_bin2str(uuid_e, uuid, sizeof(uuid)))
1046 		return;
1047 	wpa_printf(MSG_DEBUG, "WPS: PIN needed for UUID-E %s", uuid);
1048 	len = os_snprintf(txt, sizeof(txt), "WPS-EVENT-PIN-NEEDED %s " MACSTR
1049 			  " [%s|%s|%s|%s|%s|%s]",
1050 			  uuid, MAC2STR(dev->mac_addr), dev->device_name,
1051 			  dev->manufacturer, dev->model_name,
1052 			  dev->model_number, dev->serial_number,
1053 			  wps_dev_type_bin2str(dev->pri_dev_type, devtype,
1054 					       sizeof(devtype)));
1055 	if (len > 0 && len < (int) sizeof(txt))
1056 		wpa_printf(MSG_INFO, "%s", txt);
1057 }
1058 
1059 
1060 static void wpas_wps_set_sel_reg_cb(void *ctx, int sel_reg, u16 dev_passwd_id,
1061 				    u16 sel_reg_config_methods)
1062 {
1063 #ifdef CONFIG_WPS_ER
1064 	struct wpa_supplicant *wpa_s = ctx;
1065 
1066 	if (wpa_s->wps_er == NULL)
1067 		return;
1068 	wpa_printf(MSG_DEBUG, "WPS ER: SetSelectedRegistrar - sel_reg=%d "
1069 		   "dev_password_id=%u sel_reg_config_methods=0x%x",
1070 		   sel_reg, dev_passwd_id, sel_reg_config_methods);
1071 	wps_er_set_sel_reg(wpa_s->wps_er, sel_reg, dev_passwd_id,
1072 			   sel_reg_config_methods);
1073 #endif /* CONFIG_WPS_ER */
1074 }
1075 
1076 
1077 static u16 wps_fix_config_methods(u16 config_methods)
1078 {
1079 #ifdef CONFIG_WPS2
1080 	if ((config_methods &
1081 	     (WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY |
1082 	      WPS_CONFIG_PHY_DISPLAY)) == WPS_CONFIG_DISPLAY) {
1083 		wpa_printf(MSG_INFO, "WPS: Converting display to "
1084 			   "virtual_display for WPS 2.0 compliance");
1085 		config_methods |= WPS_CONFIG_VIRT_DISPLAY;
1086 	}
1087 	if ((config_methods &
1088 	     (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON |
1089 	      WPS_CONFIG_PHY_PUSHBUTTON)) == WPS_CONFIG_PUSHBUTTON) {
1090 		wpa_printf(MSG_INFO, "WPS: Converting push_button to "
1091 			   "virtual_push_button for WPS 2.0 compliance");
1092 		config_methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
1093 	}
1094 #endif /* CONFIG_WPS2 */
1095 
1096 	return config_methods;
1097 }
1098 
1099 
1100 static void wpas_wps_set_uuid(struct wpa_supplicant *wpa_s,
1101 			      struct wps_context *wps)
1102 {
1103 	wpa_printf(MSG_DEBUG, "WPS: Set UUID for interface %s", wpa_s->ifname);
1104 	if (is_nil_uuid(wpa_s->conf->uuid)) {
1105 		struct wpa_supplicant *first;
1106 		first = wpa_s->global->ifaces;
1107 		while (first && first->next)
1108 			first = first->next;
1109 		if (first && first != wpa_s) {
1110 			os_memcpy(wps->uuid, wpa_s->global->ifaces->wps->uuid,
1111 				  WPS_UUID_LEN);
1112 			wpa_hexdump(MSG_DEBUG, "WPS: UUID from the first "
1113 				    "interface", wps->uuid, WPS_UUID_LEN);
1114 		} else {
1115 			uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
1116 			wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC "
1117 				    "address", wps->uuid, WPS_UUID_LEN);
1118 		}
1119 	} else {
1120 		os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);
1121 		wpa_hexdump(MSG_DEBUG, "WPS: UUID based on configuration",
1122 			    wps->uuid, WPS_UUID_LEN);
1123 	}
1124 }
1125 
1126 
1127 int wpas_wps_init(struct wpa_supplicant *wpa_s)
1128 {
1129 	struct wps_context *wps;
1130 	struct wps_registrar_config rcfg;
1131 	struct hostapd_hw_modes *modes;
1132 	u16 m;
1133 
1134 	wps = os_zalloc(sizeof(*wps));
1135 	if (wps == NULL)
1136 		return -1;
1137 
1138 	wps->cred_cb = wpa_supplicant_wps_cred;
1139 	wps->event_cb = wpa_supplicant_wps_event;
1140 	wps->cb_ctx = wpa_s;
1141 
1142 	wps->dev.device_name = wpa_s->conf->device_name;
1143 	wps->dev.manufacturer = wpa_s->conf->manufacturer;
1144 	wps->dev.model_name = wpa_s->conf->model_name;
1145 	wps->dev.model_number = wpa_s->conf->model_number;
1146 	wps->dev.serial_number = wpa_s->conf->serial_number;
1147 	wps->config_methods =
1148 		wps_config_methods_str2bin(wpa_s->conf->config_methods);
1149 	if ((wps->config_methods & (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) ==
1150 	    (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) {
1151 		wpa_printf(MSG_ERROR, "WPS: Both Label and Display config "
1152 			   "methods are not allowed at the same time");
1153 		os_free(wps);
1154 		return -1;
1155 	}
1156 	wps->config_methods = wps_fix_config_methods(wps->config_methods);
1157 	wps->dev.config_methods = wps->config_methods;
1158 	os_memcpy(wps->dev.pri_dev_type, wpa_s->conf->device_type,
1159 		  WPS_DEV_TYPE_LEN);
1160 
1161 	wps->dev.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
1162 	os_memcpy(wps->dev.sec_dev_type, wpa_s->conf->sec_device_type,
1163 		  WPS_DEV_TYPE_LEN * wps->dev.num_sec_dev_types);
1164 
1165 	wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
1166 	modes = wpa_s->hw.modes;
1167 	if (modes) {
1168 		for (m = 0; m < wpa_s->hw.num_modes; m++) {
1169 			if (modes[m].mode == HOSTAPD_MODE_IEEE80211B ||
1170 			    modes[m].mode == HOSTAPD_MODE_IEEE80211G)
1171 				wps->dev.rf_bands |= WPS_RF_24GHZ;
1172 			else if (modes[m].mode == HOSTAPD_MODE_IEEE80211A)
1173 				wps->dev.rf_bands |= WPS_RF_50GHZ;
1174 		}
1175 	}
1176 	if (wps->dev.rf_bands == 0) {
1177 		/*
1178 		 * Default to claiming support for both bands if the driver
1179 		 * does not provide support for fetching supported bands.
1180 		 */
1181 		wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ;
1182 	}
1183 	os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN);
1184 	wpas_wps_set_uuid(wpa_s, wps);
1185 
1186 	wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
1187 	wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;
1188 
1189 	os_memset(&rcfg, 0, sizeof(rcfg));
1190 	rcfg.new_psk_cb = wpas_wps_new_psk_cb;
1191 	rcfg.pin_needed_cb = wpas_wps_pin_needed_cb;
1192 	rcfg.set_sel_reg_cb = wpas_wps_set_sel_reg_cb;
1193 	rcfg.cb_ctx = wpa_s;
1194 
1195 	wps->registrar = wps_registrar_init(wps, &rcfg);
1196 	if (wps->registrar == NULL) {
1197 		wpa_printf(MSG_DEBUG, "Failed to initialize WPS Registrar");
1198 		os_free(wps);
1199 		return -1;
1200 	}
1201 
1202 	wpa_s->wps = wps;
1203 
1204 	return 0;
1205 }
1206 
1207 
1208 void wpas_wps_deinit(struct wpa_supplicant *wpa_s)
1209 {
1210 	eloop_cancel_timeout(wpas_wps_timeout, wpa_s, NULL);
1211 
1212 	if (wpa_s->wps == NULL)
1213 		return;
1214 
1215 #ifdef CONFIG_WPS_ER
1216 	wps_er_deinit(wpa_s->wps_er, NULL, NULL);
1217 	wpa_s->wps_er = NULL;
1218 #endif /* CONFIG_WPS_ER */
1219 
1220 	wps_registrar_deinit(wpa_s->wps->registrar);
1221 	wpabuf_free(wpa_s->wps->dh_pubkey);
1222 	wpabuf_free(wpa_s->wps->dh_privkey);
1223 	wpabuf_free(wpa_s->wps->oob_conf.pubkey_hash);
1224 	wpabuf_free(wpa_s->wps->oob_conf.dev_password);
1225 	os_free(wpa_s->wps->network_key);
1226 	os_free(wpa_s->wps);
1227 	wpa_s->wps = NULL;
1228 }
1229 
1230 
1231 int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s,
1232 			    struct wpa_ssid *ssid, struct wpa_scan_res *bss)
1233 {
1234 	struct wpabuf *wps_ie;
1235 
1236 	if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
1237 		return -1;
1238 
1239 	wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1240 	if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
1241 		if (!wps_ie) {
1242 			wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
1243 			return 0;
1244 		}
1245 
1246 		if (!wps_is_selected_pbc_registrar(wps_ie)) {
1247 			wpa_printf(MSG_DEBUG, "   skip - WPS AP "
1248 				   "without active PBC Registrar");
1249 			wpabuf_free(wps_ie);
1250 			return 0;
1251 		}
1252 
1253 		/* TODO: overlap detection */
1254 		wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
1255 			   "(Active PBC)");
1256 		wpabuf_free(wps_ie);
1257 		return 1;
1258 	}
1259 
1260 	if (eap_is_wps_pin_enrollee(&ssid->eap)) {
1261 		if (!wps_ie) {
1262 			wpa_printf(MSG_DEBUG, "   skip - non-WPS AP");
1263 			return 0;
1264 		}
1265 
1266 		/*
1267 		 * Start with WPS APs that advertise our address as an
1268 		 * authorized MAC (v2.0) or active PIN Registrar (v1.0) and
1269 		 * allow any WPS AP after couple of scans since some APs do not
1270 		 * set Selected Registrar attribute properly when using
1271 		 * external Registrar.
1272 		 */
1273 		if (!wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) {
1274 			if (wpa_s->scan_runs < WPS_PIN_SCAN_IGNORE_SEL_REG) {
1275 				wpa_printf(MSG_DEBUG, "   skip - WPS AP "
1276 					   "without active PIN Registrar");
1277 				wpabuf_free(wps_ie);
1278 				return 0;
1279 			}
1280 			wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
1281 		} else {
1282 			wpa_printf(MSG_DEBUG, "   selected based on WPS IE "
1283 				   "(Authorized MAC or Active PIN)");
1284 		}
1285 		wpabuf_free(wps_ie);
1286 		return 1;
1287 	}
1288 
1289 	if (wps_ie) {
1290 		wpa_printf(MSG_DEBUG, "   selected based on WPS IE");
1291 		wpabuf_free(wps_ie);
1292 		return 1;
1293 	}
1294 
1295 	return -1;
1296 }
1297 
1298 
1299 int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s,
1300 			      struct wpa_ssid *ssid,
1301 			      struct wpa_scan_res *bss)
1302 {
1303 	struct wpabuf *wps_ie = NULL;
1304 	int ret = 0;
1305 
1306 	if (eap_is_wps_pbc_enrollee(&ssid->eap)) {
1307 		wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1308 		if (wps_ie && wps_is_selected_pbc_registrar(wps_ie)) {
1309 			/* allow wildcard SSID for WPS PBC */
1310 			ret = 1;
1311 		}
1312 	} else if (eap_is_wps_pin_enrollee(&ssid->eap)) {
1313 		wps_ie = wpa_scan_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1314 		if (wps_ie &&
1315 		    (wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1) ||
1316 		     wpa_s->scan_runs >= WPS_PIN_SCAN_IGNORE_SEL_REG)) {
1317 			/* allow wildcard SSID for WPS PIN */
1318 			ret = 1;
1319 		}
1320 	}
1321 
1322 	if (!ret && ssid->bssid_set &&
1323 	    os_memcmp(ssid->bssid, bss->bssid, ETH_ALEN) == 0) {
1324 		/* allow wildcard SSID due to hardcoded BSSID match */
1325 		ret = 1;
1326 	}
1327 
1328 #ifdef CONFIG_WPS_STRICT
1329 	if (wps_ie) {
1330 		if (wps_validate_beacon_probe_resp(wps_ie, bss->beacon_ie_len >
1331 						   0, bss->bssid) < 0)
1332 			ret = 0;
1333 		if (bss->beacon_ie_len) {
1334 			struct wpabuf *bcn_wps;
1335 			bcn_wps = wpa_scan_get_vendor_ie_multi_beacon(
1336 				bss, WPS_IE_VENDOR_TYPE);
1337 			if (bcn_wps == NULL) {
1338 				wpa_printf(MSG_DEBUG, "WPS: Mandatory WPS IE "
1339 					   "missing from AP Beacon");
1340 				ret = 0;
1341 			} else {
1342 				if (wps_validate_beacon(wps_ie) < 0)
1343 					ret = 0;
1344 				wpabuf_free(bcn_wps);
1345 			}
1346 		}
1347 	}
1348 #endif /* CONFIG_WPS_STRICT */
1349 
1350 	wpabuf_free(wps_ie);
1351 
1352 	return ret;
1353 }
1354 
1355 
1356 int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s,
1357 			      struct wpa_bss *selected, struct wpa_ssid *ssid)
1358 {
1359 	const u8 *sel_uuid, *uuid;
1360 	struct wpabuf *wps_ie;
1361 	int ret = 0;
1362 	struct wpa_bss *bss;
1363 
1364 	if (!eap_is_wps_pbc_enrollee(&ssid->eap))
1365 		return 0;
1366 
1367 	wpa_printf(MSG_DEBUG, "WPS: Check whether PBC session overlap is "
1368 		   "present in scan results; selected BSSID " MACSTR,
1369 		   MAC2STR(selected->bssid));
1370 
1371 	/* Make sure that only one AP is in active PBC mode */
1372 	wps_ie = wpa_bss_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE);
1373 	if (wps_ie) {
1374 		sel_uuid = wps_get_uuid_e(wps_ie);
1375 		wpa_hexdump(MSG_DEBUG, "WPS: UUID of the selected BSS",
1376 			    sel_uuid, UUID_LEN);
1377 	} else {
1378 		wpa_printf(MSG_DEBUG, "WPS: Selected BSS does not include "
1379 			   "WPS IE?!");
1380 		sel_uuid = NULL;
1381 	}
1382 
1383 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1384 		struct wpabuf *ie;
1385 		if (bss == selected)
1386 			continue;
1387 		ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1388 		if (!ie)
1389 			continue;
1390 		if (!wps_is_selected_pbc_registrar(ie)) {
1391 			wpabuf_free(ie);
1392 			continue;
1393 		}
1394 		wpa_printf(MSG_DEBUG, "WPS: Another BSS in active PBC mode: "
1395 			   MACSTR, MAC2STR(bss->bssid));
1396 		uuid = wps_get_uuid_e(ie);
1397 		wpa_hexdump(MSG_DEBUG, "WPS: UUID of the other BSS",
1398 			    uuid, UUID_LEN);
1399 		if (sel_uuid == NULL || uuid == NULL ||
1400 		    os_memcmp(sel_uuid, uuid, UUID_LEN) != 0) {
1401 			ret = 1; /* PBC overlap */
1402 			wpa_msg(wpa_s, MSG_INFO, "WPS: PBC overlap detected: "
1403 				MACSTR " and " MACSTR,
1404 				MAC2STR(selected->bssid),
1405 				MAC2STR(bss->bssid));
1406 			wpabuf_free(ie);
1407 			break;
1408 		}
1409 
1410 		/* TODO: verify that this is reasonable dual-band situation */
1411 
1412 		wpabuf_free(ie);
1413 	}
1414 
1415 	wpabuf_free(wps_ie);
1416 
1417 	return ret;
1418 }
1419 
1420 
1421 void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s)
1422 {
1423 	struct wpa_bss *bss;
1424 	unsigned int pbc = 0, auth = 0, pin = 0, wps = 0;
1425 
1426 	if (wpa_s->disconnected || wpa_s->wpa_state >= WPA_ASSOCIATED)
1427 		return;
1428 
1429 	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1430 		struct wpabuf *ie;
1431 		ie = wpa_bss_get_vendor_ie_multi(bss, WPS_IE_VENDOR_TYPE);
1432 		if (!ie)
1433 			continue;
1434 		if (wps_is_selected_pbc_registrar(ie))
1435 			pbc++;
1436 		else if (wps_is_addr_authorized(ie, wpa_s->own_addr, 0))
1437 			auth++;
1438 		else if (wps_is_selected_pin_registrar(ie))
1439 			pin++;
1440 		else
1441 			wps++;
1442 		wpabuf_free(ie);
1443 	}
1444 
1445 	if (pbc)
1446 		wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PBC);
1447 	else if (auth)
1448 		wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_AUTH);
1449 	else if (pin)
1450 		wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE_PIN);
1451 	else if (wps)
1452 		wpa_msg_ctrl(wpa_s, MSG_INFO, WPS_EVENT_AP_AVAILABLE);
1453 }
1454 
1455 
1456 int wpas_wps_searching(struct wpa_supplicant *wpa_s)
1457 {
1458 	struct wpa_ssid *ssid;
1459 
1460 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1461 		if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && !ssid->disabled)
1462 			return 1;
1463 	}
1464 
1465 	return 0;
1466 }
1467 
1468 
1469 int wpas_wps_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
1470 			      char *end)
1471 {
1472 	struct wpabuf *wps_ie;
1473 	int ret;
1474 
1475 	wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, WPS_DEV_OUI_WFA);
1476 	if (wps_ie == NULL)
1477 		return 0;
1478 
1479 	ret = wps_attr_text(wps_ie, buf, end);
1480 	wpabuf_free(wps_ie);
1481 	return ret;
1482 }
1483 
1484 
1485 int wpas_wps_er_start(struct wpa_supplicant *wpa_s, const char *filter)
1486 {
1487 #ifdef CONFIG_WPS_ER
1488 	if (wpa_s->wps_er) {
1489 		wps_er_refresh(wpa_s->wps_er);
1490 		return 0;
1491 	}
1492 	wpa_s->wps_er = wps_er_init(wpa_s->wps, wpa_s->ifname, filter);
1493 	if (wpa_s->wps_er == NULL)
1494 		return -1;
1495 	return 0;
1496 #else /* CONFIG_WPS_ER */
1497 	return 0;
1498 #endif /* CONFIG_WPS_ER */
1499 }
1500 
1501 
1502 int wpas_wps_er_stop(struct wpa_supplicant *wpa_s)
1503 {
1504 #ifdef CONFIG_WPS_ER
1505 	wps_er_deinit(wpa_s->wps_er, NULL, NULL);
1506 	wpa_s->wps_er = NULL;
1507 #endif /* CONFIG_WPS_ER */
1508 	return 0;
1509 }
1510 
1511 
1512 #ifdef CONFIG_WPS_ER
1513 int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const u8 *addr,
1514 			const char *uuid, const char *pin)
1515 {
1516 	u8 u[UUID_LEN];
1517 	int any = 0;
1518 
1519 	if (os_strcmp(uuid, "any") == 0)
1520 		any = 1;
1521 	else if (uuid_str2bin(uuid, u))
1522 		return -1;
1523 	return wps_registrar_add_pin(wpa_s->wps->registrar, addr,
1524 				     any ? NULL : u,
1525 				     (const u8 *) pin, os_strlen(pin), 300);
1526 }
1527 
1528 
1529 int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid)
1530 {
1531 	u8 u[UUID_LEN];
1532 
1533 	if (uuid_str2bin(uuid, u))
1534 		return -1;
1535 	return wps_er_pbc(wpa_s->wps_er, u);
1536 }
1537 
1538 
1539 int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid,
1540 		      const char *pin)
1541 {
1542 	u8 u[UUID_LEN];
1543 
1544 	if (uuid_str2bin(uuid, u))
1545 		return -1;
1546 	return wps_er_learn(wpa_s->wps_er, u, (const u8 *) pin,
1547 			    os_strlen(pin));
1548 }
1549 
1550 
1551 int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid,
1552 			   int id)
1553 {
1554 	u8 u[UUID_LEN];
1555 	struct wpa_ssid *ssid;
1556 	struct wps_credential cred;
1557 
1558 	if (uuid_str2bin(uuid, u))
1559 		return -1;
1560 	ssid = wpa_config_get_network(wpa_s->conf, id);
1561 	if (ssid == NULL || ssid->ssid == NULL)
1562 		return -1;
1563 
1564 	os_memset(&cred, 0, sizeof(cred));
1565 	if (ssid->ssid_len > 32)
1566 		return -1;
1567 	os_memcpy(cred.ssid, ssid->ssid, ssid->ssid_len);
1568 	cred.ssid_len = ssid->ssid_len;
1569 	if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
1570 		cred.auth_type = (ssid->proto & WPA_PROTO_RSN) ?
1571 			WPS_AUTH_WPA2PSK : WPS_AUTH_WPAPSK;
1572 		if (ssid->pairwise_cipher & WPA_CIPHER_CCMP)
1573 			cred.encr_type = WPS_ENCR_AES;
1574 		else
1575 			cred.encr_type = WPS_ENCR_TKIP;
1576 		if (ssid->passphrase) {
1577 			cred.key_len = os_strlen(ssid->passphrase);
1578 			if (cred.key_len >= 64)
1579 				return -1;
1580 			os_memcpy(cred.key, ssid->passphrase, cred.key_len);
1581 		} else if (ssid->psk_set) {
1582 			cred.key_len = 32;
1583 			os_memcpy(cred.key, ssid->psk, 32);
1584 		} else
1585 			return -1;
1586 	} else {
1587 		cred.auth_type = WPS_AUTH_OPEN;
1588 		cred.encr_type = WPS_ENCR_NONE;
1589 	}
1590 	return wps_er_set_config(wpa_s->wps_er, u, &cred);
1591 }
1592 
1593 
1594 int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid,
1595 		       const char *pin, struct wps_new_ap_settings *settings)
1596 {
1597 	u8 u[UUID_LEN];
1598 	struct wps_credential cred;
1599 	size_t len;
1600 
1601 	if (uuid_str2bin(uuid, u))
1602 		return -1;
1603 	if (settings->ssid_hex == NULL || settings->auth == NULL ||
1604 	    settings->encr == NULL || settings->key_hex == NULL)
1605 		return -1;
1606 
1607 	os_memset(&cred, 0, sizeof(cred));
1608 	len = os_strlen(settings->ssid_hex);
1609 	if ((len & 1) || len > 2 * sizeof(cred.ssid) ||
1610 	    hexstr2bin(settings->ssid_hex, cred.ssid, len / 2))
1611 		return -1;
1612 	cred.ssid_len = len / 2;
1613 
1614 	len = os_strlen(settings->key_hex);
1615 	if ((len & 1) || len > 2 * sizeof(cred.key) ||
1616 	    hexstr2bin(settings->key_hex, cred.key, len / 2))
1617 		return -1;
1618 	cred.key_len = len / 2;
1619 
1620 	if (os_strcmp(settings->auth, "OPEN") == 0)
1621 		cred.auth_type = WPS_AUTH_OPEN;
1622 	else if (os_strcmp(settings->auth, "WPAPSK") == 0)
1623 		cred.auth_type = WPS_AUTH_WPAPSK;
1624 	else if (os_strcmp(settings->auth, "WPA2PSK") == 0)
1625 		cred.auth_type = WPS_AUTH_WPA2PSK;
1626 	else
1627 		return -1;
1628 
1629 	if (os_strcmp(settings->encr, "NONE") == 0)
1630 		cred.encr_type = WPS_ENCR_NONE;
1631 	else if (os_strcmp(settings->encr, "WEP") == 0)
1632 		cred.encr_type = WPS_ENCR_WEP;
1633 	else if (os_strcmp(settings->encr, "TKIP") == 0)
1634 		cred.encr_type = WPS_ENCR_TKIP;
1635 	else if (os_strcmp(settings->encr, "CCMP") == 0)
1636 		cred.encr_type = WPS_ENCR_AES;
1637 	else
1638 		return -1;
1639 
1640 	return wps_er_config(wpa_s->wps_er, u, (const u8 *) pin,
1641 			     os_strlen(pin), &cred);
1642 }
1643 
1644 
1645 static int callbacks_pending = 0;
1646 
1647 static void wpas_wps_terminate_cb(void *ctx)
1648 {
1649 	wpa_printf(MSG_DEBUG, "WPS ER: Terminated");
1650 	if (--callbacks_pending <= 0)
1651 		eloop_terminate();
1652 }
1653 #endif /* CONFIG_WPS_ER */
1654 
1655 
1656 int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s)
1657 {
1658 #ifdef CONFIG_WPS_ER
1659 	if (wpa_s->wps_er) {
1660 		callbacks_pending++;
1661 		wps_er_deinit(wpa_s->wps_er, wpas_wps_terminate_cb, wpa_s);
1662 		wpa_s->wps_er = NULL;
1663 		return 1;
1664 	}
1665 #endif /* CONFIG_WPS_ER */
1666 	return 0;
1667 }
1668 
1669 
1670 int wpas_wps_in_progress(struct wpa_supplicant *wpa_s)
1671 {
1672 	struct wpa_ssid *ssid;
1673 
1674 	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1675 		if (!ssid->disabled && ssid->key_mgmt == WPA_KEY_MGMT_WPS)
1676 			return 1;
1677 	}
1678 
1679 	return 0;
1680 }
1681 
1682 
1683 void wpas_wps_update_config(struct wpa_supplicant *wpa_s)
1684 {
1685 	struct wps_context *wps = wpa_s->wps;
1686 
1687 	if (wps == NULL)
1688 		return;
1689 
1690 	if (wpa_s->conf->changed_parameters & CFG_CHANGED_CONFIG_METHODS) {
1691 		wps->config_methods = wps_config_methods_str2bin(
1692 			wpa_s->conf->config_methods);
1693 		if ((wps->config_methods &
1694 		     (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) ==
1695 		    (WPS_CONFIG_DISPLAY | WPS_CONFIG_LABEL)) {
1696 			wpa_printf(MSG_ERROR, "WPS: Both Label and Display "
1697 				   "config methods are not allowed at the "
1698 				   "same time");
1699 			wps->config_methods &= ~WPS_CONFIG_LABEL;
1700 		}
1701 	}
1702 	wps->config_methods = wps_fix_config_methods(wps->config_methods);
1703 
1704 	if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_TYPE)
1705 		os_memcpy(wps->dev.pri_dev_type, wpa_s->conf->device_type,
1706 			  WPS_DEV_TYPE_LEN);
1707 
1708 	if (wpa_s->conf->changed_parameters & CFG_CHANGED_SEC_DEVICE_TYPE) {
1709 		wps->dev.num_sec_dev_types = wpa_s->conf->num_sec_device_types;
1710 		os_memcpy(wps->dev.sec_dev_type, wpa_s->conf->sec_device_type,
1711 			  wps->dev.num_sec_dev_types * WPS_DEV_TYPE_LEN);
1712 	}
1713 
1714 	if (wpa_s->conf->changed_parameters & CFG_CHANGED_OS_VERSION)
1715 		wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
1716 
1717 	if (wpa_s->conf->changed_parameters & CFG_CHANGED_UUID)
1718 		wpas_wps_set_uuid(wpa_s, wps);
1719 
1720 	if (wpa_s->conf->changed_parameters &
1721 	    (CFG_CHANGED_DEVICE_NAME | CFG_CHANGED_WPS_STRING)) {
1722 		/* Update pointers to make sure they refer current values */
1723 		wps->dev.device_name = wpa_s->conf->device_name;
1724 		wps->dev.manufacturer = wpa_s->conf->manufacturer;
1725 		wps->dev.model_name = wpa_s->conf->model_name;
1726 		wps->dev.model_number = wpa_s->conf->model_number;
1727 		wps->dev.serial_number = wpa_s->conf->serial_number;
1728 	}
1729 }
1730