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