wps_enrollee.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
1/*
2 * Wi-Fi Protected Setup - Enrollee
3 * Copyright (c) 2008, 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 "crypto/crypto.h"
19#include "crypto/sha256.h"
20#include "crypto/random.h"
21#include "wps_i.h"
22#include "wps_dev_attr.h"
23
24
25static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg)
26{
27	wpa_printf(MSG_DEBUG, "WPS:  * MAC Address");
28	wpabuf_put_be16(msg, ATTR_MAC_ADDR);
29	wpabuf_put_be16(msg, ETH_ALEN);
30	wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN);
31	return 0;
32}
33
34
35static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg)
36{
37	u8 state;
38	if (wps->wps->ap)
39		state = wps->wps->wps_state;
40	else
41		state = WPS_STATE_NOT_CONFIGURED;
42	wpa_printf(MSG_DEBUG, "WPS:  * Wi-Fi Protected Setup State (%d)",
43		   state);
44	wpabuf_put_be16(msg, ATTR_WPS_STATE);
45	wpabuf_put_be16(msg, 1);
46	wpabuf_put_u8(msg, state);
47	return 0;
48}
49
50
51static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg)
52{
53	u8 *hash;
54	const u8 *addr[4];
55	size_t len[4];
56
57	if (random_get_bytes(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0)
58		return -1;
59	wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN);
60	wpa_hexdump(MSG_DEBUG, "WPS: E-S2",
61		    wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN);
62
63	if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) {
64		wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for "
65			   "E-Hash derivation");
66		return -1;
67	}
68
69	wpa_printf(MSG_DEBUG, "WPS:  * E-Hash1");
70	wpabuf_put_be16(msg, ATTR_E_HASH1);
71	wpabuf_put_be16(msg, SHA256_MAC_LEN);
72	hash = wpabuf_put(msg, SHA256_MAC_LEN);
73	/* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */
74	addr[0] = wps->snonce;
75	len[0] = WPS_SECRET_NONCE_LEN;
76	addr[1] = wps->psk1;
77	len[1] = WPS_PSK_LEN;
78	addr[2] = wpabuf_head(wps->dh_pubkey_e);
79	len[2] = wpabuf_len(wps->dh_pubkey_e);
80	addr[3] = wpabuf_head(wps->dh_pubkey_r);
81	len[3] = wpabuf_len(wps->dh_pubkey_r);
82	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
83	wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN);
84
85	wpa_printf(MSG_DEBUG, "WPS:  * E-Hash2");
86	wpabuf_put_be16(msg, ATTR_E_HASH2);
87	wpabuf_put_be16(msg, SHA256_MAC_LEN);
88	hash = wpabuf_put(msg, SHA256_MAC_LEN);
89	/* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */
90	addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN;
91	addr[1] = wps->psk2;
92	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
93	wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN);
94
95	return 0;
96}
97
98
99static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg)
100{
101	wpa_printf(MSG_DEBUG, "WPS:  * E-SNonce1");
102	wpabuf_put_be16(msg, ATTR_E_SNONCE1);
103	wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
104	wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN);
105	return 0;
106}
107
108
109static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg)
110{
111	wpa_printf(MSG_DEBUG, "WPS:  * E-SNonce2");
112	wpabuf_put_be16(msg, ATTR_E_SNONCE2);
113	wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN);
114	wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN,
115			WPS_SECRET_NONCE_LEN);
116	return 0;
117}
118
119
120static struct wpabuf * wps_build_m1(struct wps_data *wps)
121{
122	struct wpabuf *msg;
123	u16 config_methods;
124
125	if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0)
126		return NULL;
127	wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce",
128		    wps->nonce_e, WPS_NONCE_LEN);
129
130	wpa_printf(MSG_DEBUG, "WPS: Building Message M1");
131	msg = wpabuf_alloc(1000);
132	if (msg == NULL)
133		return NULL;
134
135	config_methods = wps->wps->config_methods;
136	if (wps->wps->ap && !wps->pbc_in_m1 &&
137	    (wps->dev_password_len != 0 ||
138	     (config_methods & WPS_CONFIG_DISPLAY))) {
139		/*
140		 * These are the methods that the AP supports as an Enrollee
141		 * for adding external Registrars, so remove PushButton.
142		 *
143		 * As a workaround for Windows 7 mechanism for probing WPS
144		 * capabilities from M1, leave PushButton option if no PIN
145		 * method is available or if WPS configuration enables PBC
146		 * workaround.
147		 */
148		config_methods &= ~WPS_CONFIG_PUSHBUTTON;
149#ifdef CONFIG_WPS2
150		config_methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
151				    WPS_CONFIG_PHY_PUSHBUTTON);
152#endif /* CONFIG_WPS2 */
153	}
154
155	if (wps_build_version(msg) ||
156	    wps_build_msg_type(msg, WPS_M1) ||
157	    wps_build_uuid_e(msg, wps->uuid_e) ||
158	    wps_build_mac_addr(wps, msg) ||
159	    wps_build_enrollee_nonce(wps, msg) ||
160	    wps_build_public_key(wps, msg) ||
161	    wps_build_auth_type_flags(wps, msg) ||
162	    wps_build_encr_type_flags(wps, msg) ||
163	    wps_build_conn_type_flags(wps, msg) ||
164	    wps_build_config_methods(msg, config_methods) ||
165	    wps_build_wps_state(wps, msg) ||
166	    wps_build_device_attrs(&wps->wps->dev, msg) ||
167	    wps_build_rf_bands(&wps->wps->dev, msg) ||
168	    wps_build_assoc_state(wps, msg) ||
169	    wps_build_dev_password_id(msg, wps->dev_pw_id) ||
170	    wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
171	    wps_build_os_version(&wps->wps->dev, msg) ||
172	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
173		wpabuf_free(msg);
174		return NULL;
175	}
176
177	wps->state = RECV_M2;
178	return msg;
179}
180
181
182static struct wpabuf * wps_build_m3(struct wps_data *wps)
183{
184	struct wpabuf *msg;
185
186	wpa_printf(MSG_DEBUG, "WPS: Building Message M3");
187
188	if (wps->dev_password == NULL) {
189		wpa_printf(MSG_DEBUG, "WPS: No Device Password available");
190		return NULL;
191	}
192	wps_derive_psk(wps, wps->dev_password, wps->dev_password_len);
193
194	msg = wpabuf_alloc(1000);
195	if (msg == NULL)
196		return NULL;
197
198	if (wps_build_version(msg) ||
199	    wps_build_msg_type(msg, WPS_M3) ||
200	    wps_build_registrar_nonce(wps, msg) ||
201	    wps_build_e_hash(wps, msg) ||
202	    wps_build_wfa_ext(msg, 0, NULL, 0) ||
203	    wps_build_authenticator(wps, msg)) {
204		wpabuf_free(msg);
205		return NULL;
206	}
207
208	wps->state = RECV_M4;
209	return msg;
210}
211
212
213static struct wpabuf * wps_build_m5(struct wps_data *wps)
214{
215	struct wpabuf *msg, *plain;
216
217	wpa_printf(MSG_DEBUG, "WPS: Building Message M5");
218
219	plain = wpabuf_alloc(200);
220	if (plain == NULL)
221		return NULL;
222
223	msg = wpabuf_alloc(1000);
224	if (msg == NULL) {
225		wpabuf_free(plain);
226		return NULL;
227	}
228
229	if (wps_build_version(msg) ||
230	    wps_build_msg_type(msg, WPS_M5) ||
231	    wps_build_registrar_nonce(wps, msg) ||
232	    wps_build_e_snonce1(wps, plain) ||
233	    wps_build_key_wrap_auth(wps, plain) ||
234	    wps_build_encr_settings(wps, msg, plain) ||
235	    wps_build_wfa_ext(msg, 0, NULL, 0) ||
236	    wps_build_authenticator(wps, msg)) {
237		wpabuf_free(plain);
238		wpabuf_free(msg);
239		return NULL;
240	}
241	wpabuf_free(plain);
242
243	wps->state = RECV_M6;
244	return msg;
245}
246
247
248static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg)
249{
250	wpa_printf(MSG_DEBUG, "WPS:  * SSID");
251	wpabuf_put_be16(msg, ATTR_SSID);
252	wpabuf_put_be16(msg, wps->wps->ssid_len);
253	wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len);
254	return 0;
255}
256
257
258static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg)
259{
260	wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type");
261	wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
262	wpabuf_put_be16(msg, 2);
263	wpabuf_put_be16(msg, wps->wps->auth_types);
264	return 0;
265}
266
267
268static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg)
269{
270	wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type");
271	wpabuf_put_be16(msg, ATTR_ENCR_TYPE);
272	wpabuf_put_be16(msg, 2);
273	wpabuf_put_be16(msg, wps->wps->encr_types);
274	return 0;
275}
276
277
278static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg)
279{
280	wpa_printf(MSG_DEBUG, "WPS:  * Network Key");
281	wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
282	wpabuf_put_be16(msg, wps->wps->network_key_len);
283	wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len);
284	return 0;
285}
286
287
288static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg)
289{
290	wpa_printf(MSG_DEBUG, "WPS:  * MAC Address (AP BSSID)");
291	wpabuf_put_be16(msg, ATTR_MAC_ADDR);
292	wpabuf_put_be16(msg, ETH_ALEN);
293	wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN);
294	return 0;
295}
296
297
298static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain)
299{
300	if (wps->wps->ap_settings) {
301		wpa_printf(MSG_DEBUG, "WPS:  * AP Settings (pre-configured)");
302		wpabuf_put_data(plain, wps->wps->ap_settings,
303				wps->wps->ap_settings_len);
304		return 0;
305	}
306
307	return wps_build_cred_ssid(wps, plain) ||
308		wps_build_cred_mac_addr(wps, plain) ||
309		wps_build_cred_auth_type(wps, plain) ||
310		wps_build_cred_encr_type(wps, plain) ||
311		wps_build_cred_network_key(wps, plain);
312}
313
314
315static struct wpabuf * wps_build_m7(struct wps_data *wps)
316{
317	struct wpabuf *msg, *plain;
318
319	wpa_printf(MSG_DEBUG, "WPS: Building Message M7");
320
321	plain = wpabuf_alloc(500 + wps->wps->ap_settings_len);
322	if (plain == NULL)
323		return NULL;
324
325	msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len);
326	if (msg == NULL) {
327		wpabuf_free(plain);
328		return NULL;
329	}
330
331	if (wps_build_version(msg) ||
332	    wps_build_msg_type(msg, WPS_M7) ||
333	    wps_build_registrar_nonce(wps, msg) ||
334	    wps_build_e_snonce2(wps, plain) ||
335	    (wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
336	    wps_build_key_wrap_auth(wps, plain) ||
337	    wps_build_encr_settings(wps, msg, plain) ||
338	    wps_build_wfa_ext(msg, 0, NULL, 0) ||
339	    wps_build_authenticator(wps, msg)) {
340		wpabuf_free(plain);
341		wpabuf_free(msg);
342		return NULL;
343	}
344	wpabuf_free(plain);
345
346	if (wps->wps->ap && wps->wps->registrar) {
347		/*
348		 * If the Registrar is only learning our current configuration,
349		 * it may not continue protocol run to successful completion.
350		 * Store information here to make sure it remains available.
351		 */
352		wps_device_store(wps->wps->registrar, &wps->peer_dev,
353				 wps->uuid_r);
354	}
355
356	wps->state = RECV_M8;
357	return msg;
358}
359
360
361static struct wpabuf * wps_build_wsc_done(struct wps_data *wps)
362{
363	struct wpabuf *msg;
364
365	wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done");
366
367	msg = wpabuf_alloc(1000);
368	if (msg == NULL)
369		return NULL;
370
371	if (wps_build_version(msg) ||
372	    wps_build_msg_type(msg, WPS_WSC_DONE) ||
373	    wps_build_enrollee_nonce(wps, msg) ||
374	    wps_build_registrar_nonce(wps, msg) ||
375	    wps_build_wfa_ext(msg, 0, NULL, 0)) {
376		wpabuf_free(msg);
377		return NULL;
378	}
379
380	if (wps->wps->ap)
381		wps->state = RECV_ACK;
382	else {
383		wps_success_event(wps->wps);
384		wps->state = WPS_FINISHED;
385	}
386	return msg;
387}
388
389
390struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps,
391				     enum wsc_op_code *op_code)
392{
393	struct wpabuf *msg;
394
395	switch (wps->state) {
396	case SEND_M1:
397		msg = wps_build_m1(wps);
398		*op_code = WSC_MSG;
399		break;
400	case SEND_M3:
401		msg = wps_build_m3(wps);
402		*op_code = WSC_MSG;
403		break;
404	case SEND_M5:
405		msg = wps_build_m5(wps);
406		*op_code = WSC_MSG;
407		break;
408	case SEND_M7:
409		msg = wps_build_m7(wps);
410		*op_code = WSC_MSG;
411		break;
412	case RECEIVED_M2D:
413		if (wps->wps->ap) {
414			msg = wps_build_wsc_nack(wps);
415			*op_code = WSC_NACK;
416			break;
417		}
418		msg = wps_build_wsc_ack(wps);
419		*op_code = WSC_ACK;
420		if (msg) {
421			/* Another M2/M2D may be received */
422			wps->state = RECV_M2;
423		}
424		break;
425	case SEND_WSC_NACK:
426		msg = wps_build_wsc_nack(wps);
427		*op_code = WSC_NACK;
428		break;
429	case WPS_MSG_DONE:
430		msg = wps_build_wsc_done(wps);
431		*op_code = WSC_Done;
432		break;
433	default:
434		wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building "
435			   "a message", wps->state);
436		msg = NULL;
437		break;
438	}
439
440	if (*op_code == WSC_MSG && msg) {
441		/* Save a copy of the last message for Authenticator derivation
442		 */
443		wpabuf_free(wps->last_msg);
444		wps->last_msg = wpabuf_dup(msg);
445	}
446
447	return msg;
448}
449
450
451static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce)
452{
453	if (r_nonce == NULL) {
454		wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received");
455		return -1;
456	}
457
458	os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN);
459	wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce",
460		    wps->nonce_r, WPS_NONCE_LEN);
461
462	return 0;
463}
464
465
466static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce)
467{
468	if (e_nonce == NULL) {
469		wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received");
470		return -1;
471	}
472
473	if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) {
474		wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received");
475		return -1;
476	}
477
478	return 0;
479}
480
481
482static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r)
483{
484	if (uuid_r == NULL) {
485		wpa_printf(MSG_DEBUG, "WPS: No UUID-R received");
486		return -1;
487	}
488
489	os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN);
490	wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN);
491
492	return 0;
493}
494
495
496static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
497			      size_t pk_len)
498{
499	if (pk == NULL || pk_len == 0) {
500		wpa_printf(MSG_DEBUG, "WPS: No Public Key received");
501		return -1;
502	}
503
504#ifdef CONFIG_WPS_OOB
505	if (wps->dev_pw_id != DEV_PW_DEFAULT &&
506	    wps->wps->oob_conf.pubkey_hash) {
507		const u8 *addr[1];
508		u8 hash[WPS_HASH_LEN];
509
510		addr[0] = pk;
511		sha256_vector(1, addr, &pk_len, hash);
512		if (os_memcmp(hash,
513			      wpabuf_head(wps->wps->oob_conf.pubkey_hash),
514			      WPS_OOB_PUBKEY_HASH_LEN) != 0) {
515			wpa_printf(MSG_ERROR, "WPS: Public Key hash error");
516			return -1;
517		}
518	}
519#endif /* CONFIG_WPS_OOB */
520
521	wpabuf_free(wps->dh_pubkey_r);
522	wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len);
523	if (wps->dh_pubkey_r == NULL)
524		return -1;
525
526	if (wps_derive_keys(wps) < 0)
527		return -1;
528
529	return 0;
530}
531
532
533static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1)
534{
535	if (r_hash1 == NULL) {
536		wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received");
537		return -1;
538	}
539
540	os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN);
541	wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN);
542
543	return 0;
544}
545
546
547static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2)
548{
549	if (r_hash2 == NULL) {
550		wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received");
551		return -1;
552	}
553
554	os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN);
555	wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN);
556
557	return 0;
558}
559
560
561static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1)
562{
563	u8 hash[SHA256_MAC_LEN];
564	const u8 *addr[4];
565	size_t len[4];
566
567	if (r_snonce1 == NULL) {
568		wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received");
569		return -1;
570	}
571
572	wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1,
573			WPS_SECRET_NONCE_LEN);
574
575	/* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */
576	addr[0] = r_snonce1;
577	len[0] = WPS_SECRET_NONCE_LEN;
578	addr[1] = wps->psk1;
579	len[1] = WPS_PSK_LEN;
580	addr[2] = wpabuf_head(wps->dh_pubkey_e);
581	len[2] = wpabuf_len(wps->dh_pubkey_e);
582	addr[3] = wpabuf_head(wps->dh_pubkey_r);
583	len[3] = wpabuf_len(wps->dh_pubkey_r);
584	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
585
586	if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
587		wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does "
588			   "not match with the pre-committed value");
589		wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
590		wps_pwd_auth_fail_event(wps->wps, 1, 1);
591		return -1;
592	}
593
594	wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first "
595		   "half of the device password");
596
597	return 0;
598}
599
600
601static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2)
602{
603	u8 hash[SHA256_MAC_LEN];
604	const u8 *addr[4];
605	size_t len[4];
606
607	if (r_snonce2 == NULL) {
608		wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received");
609		return -1;
610	}
611
612	wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce2", r_snonce2,
613			WPS_SECRET_NONCE_LEN);
614
615	/* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */
616	addr[0] = r_snonce2;
617	len[0] = WPS_SECRET_NONCE_LEN;
618	addr[1] = wps->psk2;
619	len[1] = WPS_PSK_LEN;
620	addr[2] = wpabuf_head(wps->dh_pubkey_e);
621	len[2] = wpabuf_len(wps->dh_pubkey_e);
622	addr[3] = wpabuf_head(wps->dh_pubkey_r);
623	len[3] = wpabuf_len(wps->dh_pubkey_r);
624	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
625
626	if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
627		wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does "
628			   "not match with the pre-committed value");
629		wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
630		wps_pwd_auth_fail_event(wps->wps, 1, 2);
631		return -1;
632	}
633
634	wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second "
635		   "half of the device password");
636
637	return 0;
638}
639
640
641static int wps_process_cred_e(struct wps_data *wps, const u8 *cred,
642			      size_t cred_len, int wps2)
643{
644	struct wps_parse_attr attr;
645	struct wpabuf msg;
646
647	wpa_printf(MSG_DEBUG, "WPS: Received Credential");
648	os_memset(&wps->cred, 0, sizeof(wps->cred));
649	wpabuf_set(&msg, cred, cred_len);
650	if (wps_parse_msg(&msg, &attr) < 0 ||
651	    wps_process_cred(&attr, &wps->cred))
652		return -1;
653
654	if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) !=
655	    0) {
656		wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential ("
657			   MACSTR ") does not match with own address (" MACSTR
658			   ")", MAC2STR(wps->cred.mac_addr),
659			   MAC2STR(wps->wps->dev.mac_addr));
660		/*
661		 * In theory, this could be consider fatal error, but there are
662		 * number of deployed implementations using other address here
663		 * due to unclarity in the specification. For interoperability
664		 * reasons, allow this to be processed since we do not really
665		 * use the MAC Address information for anything.
666		 */
667#ifdef CONFIG_WPS_STRICT
668		if (wps2) {
669			wpa_printf(MSG_INFO, "WPS: Do not accept incorrect "
670				   "MAC Address in AP Settings");
671			return -1;
672		}
673#endif /* CONFIG_WPS_STRICT */
674	}
675
676#ifdef CONFIG_WPS2
677	if (!(wps->cred.encr_type &
678	      (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) {
679		if (wps->cred.encr_type & WPS_ENCR_WEP) {
680			wpa_printf(MSG_INFO, "WPS: Reject Credential "
681				   "due to WEP configuration");
682			wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED;
683			return -2;
684		}
685
686		wpa_printf(MSG_INFO, "WPS: Reject Credential due to "
687			   "invalid encr_type 0x%x", wps->cred.encr_type);
688		return -1;
689	}
690#endif /* CONFIG_WPS2 */
691
692	if (wps->wps->cred_cb) {
693		wps->cred.cred_attr = cred - 4;
694		wps->cred.cred_attr_len = cred_len + 4;
695		wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred);
696		wps->cred.cred_attr = NULL;
697		wps->cred.cred_attr_len = 0;
698	}
699
700	return 0;
701}
702
703
704static int wps_process_creds(struct wps_data *wps, const u8 *cred[],
705			     size_t cred_len[], size_t num_cred, int wps2)
706{
707	size_t i;
708	int ok = 0;
709
710	if (wps->wps->ap)
711		return 0;
712
713	if (num_cred == 0) {
714		wpa_printf(MSG_DEBUG, "WPS: No Credential attributes "
715			   "received");
716		return -1;
717	}
718
719	for (i = 0; i < num_cred; i++) {
720		int res;
721		res = wps_process_cred_e(wps, cred[i], cred_len[i], wps2);
722		if (res == 0)
723			ok++;
724		else if (res == -2)
725			wpa_printf(MSG_DEBUG, "WPS: WEP credential skipped");
726		else
727			return -1;
728	}
729
730	if (ok == 0) {
731		wpa_printf(MSG_DEBUG, "WPS: No valid Credential attribute "
732			   "received");
733		return -1;
734	}
735
736	return 0;
737}
738
739
740static int wps_process_ap_settings_e(struct wps_data *wps,
741				     struct wps_parse_attr *attr,
742				     struct wpabuf *attrs, int wps2)
743{
744	struct wps_credential cred;
745
746	if (!wps->wps->ap)
747		return 0;
748
749	if (wps_process_ap_settings(attr, &cred) < 0)
750		return -1;
751
752	wpa_printf(MSG_INFO, "WPS: Received new AP configuration from "
753		   "Registrar");
754
755	if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) !=
756	    0) {
757		wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings ("
758			   MACSTR ") does not match with own address (" MACSTR
759			   ")", MAC2STR(cred.mac_addr),
760			   MAC2STR(wps->wps->dev.mac_addr));
761		/*
762		 * In theory, this could be consider fatal error, but there are
763		 * number of deployed implementations using other address here
764		 * due to unclarity in the specification. For interoperability
765		 * reasons, allow this to be processed since we do not really
766		 * use the MAC Address information for anything.
767		 */
768#ifdef CONFIG_WPS_STRICT
769		if (wps2) {
770			wpa_printf(MSG_INFO, "WPS: Do not accept incorrect "
771				   "MAC Address in AP Settings");
772			return -1;
773		}
774#endif /* CONFIG_WPS_STRICT */
775	}
776
777#ifdef CONFIG_WPS2
778	if (!(cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES)))
779	{
780		if (cred.encr_type & WPS_ENCR_WEP) {
781			wpa_printf(MSG_INFO, "WPS: Reject new AP settings "
782				   "due to WEP configuration");
783			wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED;
784			return -1;
785		}
786
787		wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to "
788			   "invalid encr_type 0x%x", cred.encr_type);
789		return -1;
790	}
791#endif /* CONFIG_WPS2 */
792
793#ifdef CONFIG_WPS_STRICT
794	if (wps2) {
795		if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) ==
796		    WPS_ENCR_TKIP ||
797		    (cred.auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) ==
798		    WPS_AUTH_WPAPSK) {
799			wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC 2.0 "
800				   "AP Settings: WPA-Personal/TKIP only");
801			wps->error_indication =
802				WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED;
803			return -1;
804		}
805	}
806#endif /* CONFIG_WPS_STRICT */
807
808#ifdef CONFIG_WPS2
809	if ((cred.encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP)
810	{
811		wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> "
812			   "TKIP+AES");
813		cred.encr_type |= WPS_ENCR_AES;
814	}
815
816	if ((cred.auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) ==
817	    WPS_AUTH_WPAPSK) {
818		wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> "
819			   "WPAPSK+WPA2PSK");
820		cred.auth_type |= WPS_AUTH_WPA2PSK;
821	}
822#endif /* CONFIG_WPS2 */
823
824	if (wps->wps->cred_cb) {
825		cred.cred_attr = wpabuf_head(attrs);
826		cred.cred_attr_len = wpabuf_len(attrs);
827		wps->wps->cred_cb(wps->wps->cb_ctx, &cred);
828	}
829
830	return 0;
831}
832
833
834static enum wps_process_res wps_process_m2(struct wps_data *wps,
835					   const struct wpabuf *msg,
836					   struct wps_parse_attr *attr)
837{
838	wpa_printf(MSG_DEBUG, "WPS: Received M2");
839
840	if (wps->state != RECV_M2) {
841		wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
842			   "receiving M2", wps->state);
843		wps->state = SEND_WSC_NACK;
844		return WPS_CONTINUE;
845	}
846
847	if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
848	    wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
849	    wps_process_uuid_r(wps, attr->uuid_r)) {
850		wps->state = SEND_WSC_NACK;
851		return WPS_CONTINUE;
852	}
853
854	/*
855	 * Stop here on an AP as an Enrollee if AP Setup is locked unless the
856	 * special locked mode is used to allow protocol run up to M7 in order
857	 * to support external Registrars that only learn the current AP
858	 * configuration without changing it.
859	 */
860	if (wps->wps->ap &&
861	    ((wps->wps->ap_setup_locked && wps->wps->ap_setup_locked != 2) ||
862	     wps->dev_password == NULL)) {
863		wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse "
864			   "registration of a new Registrar");
865		wps->config_error = WPS_CFG_SETUP_LOCKED;
866		wps->state = SEND_WSC_NACK;
867		return WPS_CONTINUE;
868	}
869
870	if (wps_process_pubkey(wps, attr->public_key, attr->public_key_len) ||
871	    wps_process_authenticator(wps, attr->authenticator, msg) ||
872	    wps_process_device_attrs(&wps->peer_dev, attr)) {
873		wps->state = SEND_WSC_NACK;
874		return WPS_CONTINUE;
875	}
876
877	wps->state = SEND_M3;
878	return WPS_CONTINUE;
879}
880
881
882static enum wps_process_res wps_process_m2d(struct wps_data *wps,
883					    struct wps_parse_attr *attr)
884{
885	wpa_printf(MSG_DEBUG, "WPS: Received M2D");
886
887	if (wps->state != RECV_M2) {
888		wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
889			   "receiving M2D", wps->state);
890		wps->state = SEND_WSC_NACK;
891		return WPS_CONTINUE;
892	}
893
894	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer",
895			  attr->manufacturer, attr->manufacturer_len);
896	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name",
897			  attr->model_name, attr->model_name_len);
898	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number",
899			  attr->model_number, attr->model_number_len);
900	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number",
901			  attr->serial_number, attr->serial_number_len);
902	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name",
903			  attr->dev_name, attr->dev_name_len);
904
905	if (wps->wps->event_cb) {
906		union wps_event_data data;
907		struct wps_event_m2d *m2d = &data.m2d;
908		os_memset(&data, 0, sizeof(data));
909		if (attr->config_methods)
910			m2d->config_methods =
911				WPA_GET_BE16(attr->config_methods);
912		m2d->manufacturer = attr->manufacturer;
913		m2d->manufacturer_len = attr->manufacturer_len;
914		m2d->model_name = attr->model_name;
915		m2d->model_name_len = attr->model_name_len;
916		m2d->model_number = attr->model_number;
917		m2d->model_number_len = attr->model_number_len;
918		m2d->serial_number = attr->serial_number;
919		m2d->serial_number_len = attr->serial_number_len;
920		m2d->dev_name = attr->dev_name;
921		m2d->dev_name_len = attr->dev_name_len;
922		m2d->primary_dev_type = attr->primary_dev_type;
923		if (attr->config_error)
924			m2d->config_error =
925				WPA_GET_BE16(attr->config_error);
926		if (attr->dev_password_id)
927			m2d->dev_password_id =
928				WPA_GET_BE16(attr->dev_password_id);
929		wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_M2D, &data);
930	}
931
932	wps->state = RECEIVED_M2D;
933	return WPS_CONTINUE;
934}
935
936
937static enum wps_process_res wps_process_m4(struct wps_data *wps,
938					   const struct wpabuf *msg,
939					   struct wps_parse_attr *attr)
940{
941	struct wpabuf *decrypted;
942	struct wps_parse_attr eattr;
943
944	wpa_printf(MSG_DEBUG, "WPS: Received M4");
945
946	if (wps->state != RECV_M4) {
947		wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
948			   "receiving M4", wps->state);
949		wps->state = SEND_WSC_NACK;
950		return WPS_CONTINUE;
951	}
952
953	if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
954	    wps_process_authenticator(wps, attr->authenticator, msg) ||
955	    wps_process_r_hash1(wps, attr->r_hash1) ||
956	    wps_process_r_hash2(wps, attr->r_hash2)) {
957		wps->state = SEND_WSC_NACK;
958		return WPS_CONTINUE;
959	}
960
961	decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
962					      attr->encr_settings_len);
963	if (decrypted == NULL) {
964		wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
965			   "Settings attribute");
966		wps->state = SEND_WSC_NACK;
967		return WPS_CONTINUE;
968	}
969
970	if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) {
971		wpabuf_free(decrypted);
972		wps->state = SEND_WSC_NACK;
973		return WPS_CONTINUE;
974	}
975
976	wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
977		   "attribute");
978	if (wps_parse_msg(decrypted, &eattr) < 0 ||
979	    wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
980	    wps_process_r_snonce1(wps, eattr.r_snonce1)) {
981		wpabuf_free(decrypted);
982		wps->state = SEND_WSC_NACK;
983		return WPS_CONTINUE;
984	}
985	wpabuf_free(decrypted);
986
987	wps->state = SEND_M5;
988	return WPS_CONTINUE;
989}
990
991
992static enum wps_process_res wps_process_m6(struct wps_data *wps,
993					   const struct wpabuf *msg,
994					   struct wps_parse_attr *attr)
995{
996	struct wpabuf *decrypted;
997	struct wps_parse_attr eattr;
998
999	wpa_printf(MSG_DEBUG, "WPS: Received M6");
1000
1001	if (wps->state != RECV_M6) {
1002		wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1003			   "receiving M6", wps->state);
1004		wps->state = SEND_WSC_NACK;
1005		return WPS_CONTINUE;
1006	}
1007
1008	if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
1009	    wps_process_authenticator(wps, attr->authenticator, msg)) {
1010		wps->state = SEND_WSC_NACK;
1011		return WPS_CONTINUE;
1012	}
1013
1014	decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
1015					      attr->encr_settings_len);
1016	if (decrypted == NULL) {
1017		wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
1018			   "Settings attribute");
1019		wps->state = SEND_WSC_NACK;
1020		return WPS_CONTINUE;
1021	}
1022
1023	if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) {
1024		wpabuf_free(decrypted);
1025		wps->state = SEND_WSC_NACK;
1026		return WPS_CONTINUE;
1027	}
1028
1029	wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
1030		   "attribute");
1031	if (wps_parse_msg(decrypted, &eattr) < 0 ||
1032	    wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
1033	    wps_process_r_snonce2(wps, eattr.r_snonce2)) {
1034		wpabuf_free(decrypted);
1035		wps->state = SEND_WSC_NACK;
1036		return WPS_CONTINUE;
1037	}
1038	wpabuf_free(decrypted);
1039
1040	wps->state = SEND_M7;
1041	return WPS_CONTINUE;
1042}
1043
1044
1045static enum wps_process_res wps_process_m8(struct wps_data *wps,
1046					   const struct wpabuf *msg,
1047					   struct wps_parse_attr *attr)
1048{
1049	struct wpabuf *decrypted;
1050	struct wps_parse_attr eattr;
1051
1052	wpa_printf(MSG_DEBUG, "WPS: Received M8");
1053
1054	if (wps->state != RECV_M8) {
1055		wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for "
1056			   "receiving M8", wps->state);
1057		wps->state = SEND_WSC_NACK;
1058		return WPS_CONTINUE;
1059	}
1060
1061	if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
1062	    wps_process_authenticator(wps, attr->authenticator, msg)) {
1063		wps->state = SEND_WSC_NACK;
1064		return WPS_CONTINUE;
1065	}
1066
1067	if (wps->wps->ap && wps->wps->ap_setup_locked) {
1068		/*
1069		 * Stop here if special ap_setup_locked == 2 mode allowed the
1070		 * protocol to continue beyond M2. This allows ER to learn the
1071		 * current AP settings without changing them.
1072		 */
1073		wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse "
1074			   "registration of a new Registrar");
1075		wps->config_error = WPS_CFG_SETUP_LOCKED;
1076		wps->state = SEND_WSC_NACK;
1077		return WPS_CONTINUE;
1078	}
1079
1080	decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
1081					      attr->encr_settings_len);
1082	if (decrypted == NULL) {
1083		wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
1084			   "Settings attribute");
1085		wps->state = SEND_WSC_NACK;
1086		return WPS_CONTINUE;
1087	}
1088
1089	if (wps_validate_m8_encr(decrypted, wps->wps->ap,
1090				 attr->version2 != NULL) < 0) {
1091		wpabuf_free(decrypted);
1092		wps->state = SEND_WSC_NACK;
1093		return WPS_CONTINUE;
1094	}
1095
1096	wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings "
1097		   "attribute");
1098	if (wps_parse_msg(decrypted, &eattr) < 0 ||
1099	    wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) ||
1100	    wps_process_creds(wps, eattr.cred, eattr.cred_len,
1101			      eattr.num_cred, attr->version2 != NULL) ||
1102	    wps_process_ap_settings_e(wps, &eattr, decrypted,
1103				      attr->version2 != NULL)) {
1104		wpabuf_free(decrypted);
1105		wps->state = SEND_WSC_NACK;
1106		return WPS_CONTINUE;
1107	}
1108	wpabuf_free(decrypted);
1109
1110	wps->state = WPS_MSG_DONE;
1111	return WPS_CONTINUE;
1112}
1113
1114
1115static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
1116						const struct wpabuf *msg)
1117{
1118	struct wps_parse_attr attr;
1119	enum wps_process_res ret = WPS_CONTINUE;
1120
1121	wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG");
1122
1123	if (wps_parse_msg(msg, &attr) < 0)
1124		return WPS_FAILURE;
1125
1126	if (attr.enrollee_nonce == NULL ||
1127	    os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
1128		wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
1129		return WPS_FAILURE;
1130	}
1131
1132	if (attr.msg_type == NULL) {
1133		wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
1134		wps->state = SEND_WSC_NACK;
1135		return WPS_CONTINUE;
1136	}
1137
1138	switch (*attr.msg_type) {
1139	case WPS_M2:
1140		if (wps_validate_m2(msg) < 0)
1141			return WPS_FAILURE;
1142		ret = wps_process_m2(wps, msg, &attr);
1143		break;
1144	case WPS_M2D:
1145		if (wps_validate_m2d(msg) < 0)
1146			return WPS_FAILURE;
1147		ret = wps_process_m2d(wps, &attr);
1148		break;
1149	case WPS_M4:
1150		if (wps_validate_m4(msg) < 0)
1151			return WPS_FAILURE;
1152		ret = wps_process_m4(wps, msg, &attr);
1153		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
1154			wps_fail_event(wps->wps, WPS_M4, wps->config_error,
1155				       wps->error_indication);
1156		break;
1157	case WPS_M6:
1158		if (wps_validate_m6(msg) < 0)
1159			return WPS_FAILURE;
1160		ret = wps_process_m6(wps, msg, &attr);
1161		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
1162			wps_fail_event(wps->wps, WPS_M6, wps->config_error,
1163				       wps->error_indication);
1164		break;
1165	case WPS_M8:
1166		if (wps_validate_m8(msg) < 0)
1167			return WPS_FAILURE;
1168		ret = wps_process_m8(wps, msg, &attr);
1169		if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK)
1170			wps_fail_event(wps->wps, WPS_M8, wps->config_error,
1171				       wps->error_indication);
1172		break;
1173	default:
1174		wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d",
1175			   *attr.msg_type);
1176		return WPS_FAILURE;
1177	}
1178
1179	/*
1180	 * Save a copy of the last message for Authenticator derivation if we
1181	 * are continuing. However, skip M2D since it is not authenticated and
1182	 * neither is the ACK/NACK response frame. This allows the possibly
1183	 * following M2 to be processed correctly by using the previously sent
1184	 * M1 in Authenticator derivation.
1185	 */
1186	if (ret == WPS_CONTINUE && *attr.msg_type != WPS_M2D) {
1187		/* Save a copy of the last message for Authenticator derivation
1188		 */
1189		wpabuf_free(wps->last_msg);
1190		wps->last_msg = wpabuf_dup(msg);
1191	}
1192
1193	return ret;
1194}
1195
1196
1197static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
1198						const struct wpabuf *msg)
1199{
1200	struct wps_parse_attr attr;
1201
1202	wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK");
1203
1204	if (wps_parse_msg(msg, &attr) < 0)
1205		return WPS_FAILURE;
1206
1207	if (attr.msg_type == NULL) {
1208		wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
1209		return WPS_FAILURE;
1210	}
1211
1212	if (*attr.msg_type != WPS_WSC_ACK) {
1213		wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
1214			   *attr.msg_type);
1215		return WPS_FAILURE;
1216	}
1217
1218	if (attr.registrar_nonce == NULL ||
1219	    os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0))
1220	{
1221		wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
1222		return WPS_FAILURE;
1223	}
1224
1225	if (attr.enrollee_nonce == NULL ||
1226	    os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
1227		wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
1228		return WPS_FAILURE;
1229	}
1230
1231	if (wps->state == RECV_ACK && wps->wps->ap) {
1232		wpa_printf(MSG_DEBUG, "WPS: External Registrar registration "
1233			   "completed successfully");
1234		wps_success_event(wps->wps);
1235		wps->state = WPS_FINISHED;
1236		return WPS_DONE;
1237	}
1238
1239	return WPS_FAILURE;
1240}
1241
1242
1243static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps,
1244						 const struct wpabuf *msg)
1245{
1246	struct wps_parse_attr attr;
1247	u16 config_error;
1248
1249	wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK");
1250
1251	if (wps_parse_msg(msg, &attr) < 0)
1252		return WPS_FAILURE;
1253
1254	if (attr.msg_type == NULL) {
1255		wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute");
1256		return WPS_FAILURE;
1257	}
1258
1259	if (*attr.msg_type != WPS_WSC_NACK) {
1260		wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d",
1261			   *attr.msg_type);
1262		return WPS_FAILURE;
1263	}
1264
1265	if (attr.registrar_nonce == NULL ||
1266	    os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0))
1267	{
1268		wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce");
1269		wpa_hexdump(MSG_DEBUG, "WPS: Received Registrar Nonce",
1270			    attr.registrar_nonce, WPS_NONCE_LEN);
1271		wpa_hexdump(MSG_DEBUG, "WPS: Expected Registrar Nonce",
1272			    wps->nonce_r, WPS_NONCE_LEN);
1273		return WPS_FAILURE;
1274	}
1275
1276	if (attr.enrollee_nonce == NULL ||
1277	    os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) {
1278		wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce");
1279		wpa_hexdump(MSG_DEBUG, "WPS: Received Enrollee Nonce",
1280			    attr.enrollee_nonce, WPS_NONCE_LEN);
1281		wpa_hexdump(MSG_DEBUG, "WPS: Expected Enrollee Nonce",
1282			    wps->nonce_e, WPS_NONCE_LEN);
1283		return WPS_FAILURE;
1284	}
1285
1286	if (attr.config_error == NULL) {
1287		wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute "
1288			   "in WSC_NACK");
1289		return WPS_FAILURE;
1290	}
1291
1292	config_error = WPA_GET_BE16(attr.config_error);
1293	wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with "
1294		   "Configuration Error %d", config_error);
1295
1296	switch (wps->state) {
1297	case RECV_M4:
1298		wps_fail_event(wps->wps, WPS_M3, config_error,
1299			       wps->error_indication);
1300		break;
1301	case RECV_M6:
1302		wps_fail_event(wps->wps, WPS_M5, config_error,
1303			       wps->error_indication);
1304		break;
1305	case RECV_M8:
1306		wps_fail_event(wps->wps, WPS_M7, config_error,
1307			       wps->error_indication);
1308		break;
1309	default:
1310		break;
1311	}
1312
1313	/* Followed by NACK if Enrollee is Supplicant or EAP-Failure if
1314	 * Enrollee is Authenticator */
1315	wps->state = SEND_WSC_NACK;
1316
1317	return WPS_FAILURE;
1318}
1319
1320
1321enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps,
1322					      enum wsc_op_code op_code,
1323					      const struct wpabuf *msg)
1324{
1325
1326	wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu "
1327		   "op_code=%d)",
1328		   (unsigned long) wpabuf_len(msg), op_code);
1329
1330	if (op_code == WSC_UPnP) {
1331		/* Determine the OpCode based on message type attribute */
1332		struct wps_parse_attr attr;
1333		if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) {
1334			if (*attr.msg_type == WPS_WSC_ACK)
1335				op_code = WSC_ACK;
1336			else if (*attr.msg_type == WPS_WSC_NACK)
1337				op_code = WSC_NACK;
1338		}
1339	}
1340
1341	switch (op_code) {
1342	case WSC_MSG:
1343	case WSC_UPnP:
1344		return wps_process_wsc_msg(wps, msg);
1345	case WSC_ACK:
1346		if (wps_validate_wsc_ack(msg) < 0)
1347			return WPS_FAILURE;
1348		return wps_process_wsc_ack(wps, msg);
1349	case WSC_NACK:
1350		if (wps_validate_wsc_nack(msg) < 0)
1351			return WPS_FAILURE;
1352		return wps_process_wsc_nack(wps, msg);
1353	default:
1354		wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code);
1355		return WPS_FAILURE;
1356	}
1357}
1358