1/*
2 * Wi-Fi Protected Setup - Strict protocol validation routines
3 * Copyright (c) 2010, Atheros Communications, Inc.
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 "utils/includes.h"
16
17#include "utils/common.h"
18#include "wps_i.h"
19#include "wps.h"
20
21
22#ifndef WPS_STRICT_ALL
23#define WPS_STRICT_WPS2
24#endif /* WPS_STRICT_ALL */
25
26
27static int wps_validate_version(const u8 *version, int mandatory)
28{
29	if (version == NULL) {
30		if (mandatory) {
31			wpa_printf(MSG_INFO, "WPS-STRICT: Version attribute "
32				   "missing");
33			return -1;
34		}
35		return 0;
36	}
37	if (*version != 0x10) {
38		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Version attribute "
39			   "value 0x%x", *version);
40		return -1;
41	}
42	return 0;
43}
44
45
46static int wps_validate_version2(const u8 *version2, int mandatory)
47{
48	if (version2 == NULL) {
49		if (mandatory) {
50			wpa_printf(MSG_INFO, "WPS-STRICT: Version2 attribute "
51				   "missing");
52			return -1;
53		}
54		return 0;
55	}
56	if (*version2 < 0x20) {
57		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Version2 attribute "
58			   "value 0x%x", *version2);
59		return -1;
60	}
61	return 0;
62}
63
64
65static int wps_validate_request_type(const u8 *request_type, int mandatory)
66{
67	if (request_type == NULL) {
68		if (mandatory) {
69			wpa_printf(MSG_INFO, "WPS-STRICT: Request Type "
70				   "attribute missing");
71			return -1;
72		}
73		return 0;
74	}
75	if (*request_type > 0x03) {
76		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Request Type "
77			   "attribute value 0x%x", *request_type);
78		return -1;
79	}
80	return 0;
81}
82
83
84static int wps_validate_response_type(const u8 *response_type, int mandatory)
85{
86	if (response_type == NULL) {
87		if (mandatory) {
88			wpa_printf(MSG_INFO, "WPS-STRICT: Response Type "
89				   "attribute missing");
90			return -1;
91		}
92		return 0;
93	}
94	if (*response_type > 0x03) {
95		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Response Type "
96			   "attribute value 0x%x", *response_type);
97		return -1;
98	}
99	return 0;
100}
101
102
103static int valid_config_methods(u16 val, int wps2)
104{
105	if (wps2) {
106		if ((val & 0x6000) && !(val & WPS_CONFIG_DISPLAY)) {
107			wpa_printf(MSG_INFO, "WPS-STRICT: Physical/Virtual "
108				   "Display flag without old Display flag "
109				   "set");
110			return 0;
111		}
112		if (!(val & 0x6000) && (val & WPS_CONFIG_DISPLAY)) {
113			wpa_printf(MSG_INFO, "WPS-STRICT: Display flag "
114				   "without Physical/Virtual Display flag");
115			return 0;
116		}
117		if ((val & 0x0600) && !(val & WPS_CONFIG_PUSHBUTTON)) {
118			wpa_printf(MSG_INFO, "WPS-STRICT: Physical/Virtual "
119				   "PushButton flag without old PushButton "
120				   "flag set");
121			return 0;
122		}
123		if (!(val & 0x0600) && (val & WPS_CONFIG_PUSHBUTTON)) {
124			wpa_printf(MSG_INFO, "WPS-STRICT: PushButton flag "
125				   "without Physical/Virtual PushButton flag");
126			return 0;
127		}
128	}
129
130	return 1;
131}
132
133
134static int wps_validate_config_methods(const u8 *config_methods, int wps2,
135				       int mandatory)
136{
137	u16 val;
138
139	if (config_methods == NULL) {
140		if (mandatory) {
141			wpa_printf(MSG_INFO, "WPS-STRICT: Configuration "
142				   "Methods attribute missing");
143			return -1;
144		}
145		return 0;
146	}
147
148	val = WPA_GET_BE16(config_methods);
149	if (!valid_config_methods(val, wps2)) {
150		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration "
151			   "Methods attribute value 0x%04x", val);
152		return -1;
153	}
154	return 0;
155}
156
157
158static int wps_validate_ap_config_methods(const u8 *config_methods, int wps2,
159					  int mandatory)
160{
161	u16 val;
162
163	if (wps_validate_config_methods(config_methods, wps2, mandatory) < 0)
164		return -1;
165	if (config_methods == NULL)
166		return 0;
167	val = WPA_GET_BE16(config_methods);
168	if (val & WPS_CONFIG_PUSHBUTTON) {
169		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration "
170			   "Methods attribute value 0x%04x in AP info "
171			   "(PushButton not allowed for registering new ER)",
172			   val);
173		return -1;
174	}
175	return 0;
176}
177
178
179static int wps_validate_uuid_e(const u8 *uuid_e, int mandatory)
180{
181	if (uuid_e == NULL) {
182		if (mandatory) {
183			wpa_printf(MSG_INFO, "WPS-STRICT: UUID-E "
184				   "attribute missing");
185			return -1;
186		}
187		return 0;
188	}
189	return 0;
190}
191
192
193static int wps_validate_uuid_r(const u8 *uuid_r, int mandatory)
194{
195	if (uuid_r == NULL) {
196		if (mandatory) {
197			wpa_printf(MSG_INFO, "WPS-STRICT: UUID-R "
198				   "attribute missing");
199			return -1;
200		}
201		return 0;
202	}
203	return 0;
204}
205
206
207static int wps_validate_primary_dev_type(const u8 *primary_dev_type,
208					 int mandatory)
209{
210	if (primary_dev_type == NULL) {
211		if (mandatory) {
212			wpa_printf(MSG_INFO, "WPS-STRICT: Primary Device Type "
213				   "attribute missing");
214			return -1;
215		}
216		return 0;
217	}
218	return 0;
219}
220
221
222static int wps_validate_rf_bands(const u8 *rf_bands, int mandatory)
223{
224	if (rf_bands == NULL) {
225		if (mandatory) {
226			wpa_printf(MSG_INFO, "WPS-STRICT: RF Bands "
227				   "attribute missing");
228			return -1;
229		}
230		return 0;
231	}
232	if (*rf_bands != WPS_RF_24GHZ && *rf_bands != WPS_RF_50GHZ &&
233	    *rf_bands != (WPS_RF_24GHZ | WPS_RF_50GHZ)) {
234		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Rf Bands "
235			   "attribute value 0x%x", *rf_bands);
236		return -1;
237	}
238	return 0;
239}
240
241
242static int wps_validate_assoc_state(const u8 *assoc_state, int mandatory)
243{
244	u16 val;
245	if (assoc_state == NULL) {
246		if (mandatory) {
247			wpa_printf(MSG_INFO, "WPS-STRICT: Association State "
248				   "attribute missing");
249			return -1;
250		}
251		return 0;
252	}
253	val = WPA_GET_BE16(assoc_state);
254	if (val > 4) {
255		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Association State "
256			   "attribute value 0x%04x", val);
257		return -1;
258	}
259	return 0;
260}
261
262
263static int wps_validate_config_error(const u8 *config_error, int mandatory)
264{
265	u16 val;
266
267	if (config_error == NULL) {
268		if (mandatory) {
269			wpa_printf(MSG_INFO, "WPS-STRICT: Configuration Error "
270				   "attribute missing");
271			return -1;
272		}
273		return 0;
274	}
275	val = WPA_GET_BE16(config_error);
276	if (val > 18) {
277		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration Error "
278			   "attribute value 0x%04x", val);
279		return -1;
280	}
281	return 0;
282}
283
284
285static int wps_validate_dev_password_id(const u8 *dev_password_id,
286					int mandatory)
287{
288	u16 val;
289
290	if (dev_password_id == NULL) {
291		if (mandatory) {
292			wpa_printf(MSG_INFO, "WPS-STRICT: Device Password ID "
293				   "attribute missing");
294			return -1;
295		}
296		return 0;
297	}
298	val = WPA_GET_BE16(dev_password_id);
299	if (val >= 0x0006 && val <= 0x000f) {
300		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Device Password ID "
301			   "attribute value 0x%04x", val);
302		return -1;
303	}
304	return 0;
305}
306
307
308static int wps_validate_manufacturer(const u8 *manufacturer, size_t len,
309				     int mandatory)
310{
311	if (manufacturer == NULL) {
312		if (mandatory) {
313			wpa_printf(MSG_INFO, "WPS-STRICT: Manufacturer "
314				   "attribute missing");
315			return -1;
316		}
317		return 0;
318	}
319	if (len > 0 && manufacturer[len - 1] == 0) {
320		wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Manufacturer "
321			   "attribute value", manufacturer, len);
322		return -1;
323	}
324	return 0;
325}
326
327
328static int wps_validate_model_name(const u8 *model_name, size_t len,
329				   int mandatory)
330{
331	if (model_name == NULL) {
332		if (mandatory) {
333			wpa_printf(MSG_INFO, "WPS-STRICT: Model Name "
334				   "attribute missing");
335			return -1;
336		}
337		return 0;
338	}
339	if (len > 0 && model_name[len - 1] == 0) {
340		wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Model Name "
341			   "attribute value", model_name, len);
342		return -1;
343	}
344	return 0;
345}
346
347
348static int wps_validate_model_number(const u8 *model_number, size_t len,
349				     int mandatory)
350{
351	if (model_number == NULL) {
352		if (mandatory) {
353			wpa_printf(MSG_INFO, "WPS-STRICT: Model Number "
354				   "attribute missing");
355			return -1;
356		}
357		return 0;
358	}
359	if (len > 0 && model_number[len - 1] == 0) {
360		wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Model Number "
361			   "attribute value", model_number, len);
362		return -1;
363	}
364	return 0;
365}
366
367
368static int wps_validate_serial_number(const u8 *serial_number, size_t len,
369				      int mandatory)
370{
371	if (serial_number == NULL) {
372		if (mandatory) {
373			wpa_printf(MSG_INFO, "WPS-STRICT: Serial Number "
374				   "attribute missing");
375			return -1;
376		}
377		return 0;
378	}
379	if (len > 0 && serial_number[len - 1] == 0) {
380		wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Serial "
381				  "Number attribute value",
382				  serial_number, len);
383		return -1;
384	}
385	return 0;
386}
387
388
389static int wps_validate_dev_name(const u8 *dev_name, size_t len,
390				 int mandatory)
391{
392	if (dev_name == NULL) {
393		if (mandatory) {
394			wpa_printf(MSG_INFO, "WPS-STRICT: Device Name "
395				   "attribute missing");
396			return -1;
397		}
398		return 0;
399	}
400	if (len > 0 && dev_name[len - 1] == 0) {
401		wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Device Name "
402			   "attribute value", dev_name, len);
403		return -1;
404	}
405	return 0;
406}
407
408
409static int wps_validate_request_to_enroll(const u8 *request_to_enroll,
410					  int mandatory)
411{
412	if (request_to_enroll == NULL) {
413		if (mandatory) {
414			wpa_printf(MSG_INFO, "WPS-STRICT: Request to Enroll "
415				   "attribute missing");
416			return -1;
417		}
418		return 0;
419	}
420	if (*request_to_enroll > 0x01) {
421		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Request to Enroll "
422			   "attribute value 0x%x", *request_to_enroll);
423		return -1;
424	}
425	return 0;
426}
427
428
429static int wps_validate_req_dev_type(const u8 *req_dev_type[], size_t num,
430				     int mandatory)
431{
432	if (num == 0) {
433		if (mandatory) {
434			wpa_printf(MSG_INFO, "WPS-STRICT: Requested Device "
435				   "Type attribute missing");
436			return -1;
437		}
438		return 0;
439	}
440	return 0;
441}
442
443
444static int wps_validate_wps_state(const u8 *wps_state, int mandatory)
445{
446	if (wps_state == NULL) {
447		if (mandatory) {
448			wpa_printf(MSG_INFO, "WPS-STRICT: Wi-Fi Protected "
449				   "Setup State attribute missing");
450			return -1;
451		}
452		return 0;
453	}
454	if (*wps_state != WPS_STATE_NOT_CONFIGURED &&
455	    *wps_state != WPS_STATE_CONFIGURED) {
456		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Wi-Fi Protected "
457			   "Setup State attribute value 0x%x", *wps_state);
458		return -1;
459	}
460	return 0;
461}
462
463
464static int wps_validate_ap_setup_locked(const u8 *ap_setup_locked,
465					int mandatory)
466{
467	if (ap_setup_locked == NULL) {
468		if (mandatory) {
469			wpa_printf(MSG_INFO, "WPS-STRICT: AP Setup Locked "
470				   "attribute missing");
471			return -1;
472		}
473		return 0;
474	}
475	if (*ap_setup_locked > 1) {
476		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid AP Setup Locked "
477			   "attribute value 0x%x", *ap_setup_locked);
478		return -1;
479	}
480	return 0;
481}
482
483
484static int wps_validate_selected_registrar(const u8 *selected_registrar,
485					   int mandatory)
486{
487	if (selected_registrar == NULL) {
488		if (mandatory) {
489			wpa_printf(MSG_INFO, "WPS-STRICT: Selected Registrar "
490				   "attribute missing");
491			return -1;
492		}
493		return 0;
494	}
495	if (*selected_registrar > 1) {
496		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Selected Registrar "
497			   "attribute value 0x%x", *selected_registrar);
498		return -1;
499	}
500	return 0;
501}
502
503
504static int wps_validate_sel_reg_config_methods(const u8 *config_methods,
505					       int wps2, int mandatory)
506{
507	u16 val;
508
509	if (config_methods == NULL) {
510		if (mandatory) {
511			wpa_printf(MSG_INFO, "WPS-STRICT: Selected Registrar "
512				   "Configuration Methods attribute missing");
513			return -1;
514		}
515		return 0;
516	}
517
518	val = WPA_GET_BE16(config_methods);
519	if (!valid_config_methods(val, wps2)) {
520		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Selected Registrar "
521			   "Configuration Methods attribute value 0x%04x",
522			   val);
523		return -1;
524	}
525	return 0;
526}
527
528
529static int wps_validate_authorized_macs(const u8 *authorized_macs, size_t len,
530					int mandatory)
531{
532	if (authorized_macs == NULL) {
533		if (mandatory) {
534			wpa_printf(MSG_INFO, "WPS-STRICT: Authorized MACs "
535				   "attribute missing");
536			return -1;
537		}
538		return 0;
539	}
540	if (len > 30 && (len % ETH_ALEN) != 0) {
541		wpa_hexdump(MSG_INFO, "WPS-STRICT: Invalid Authorized "
542			    "MACs attribute value", authorized_macs, len);
543		return -1;
544	}
545	return 0;
546}
547
548
549static int wps_validate_msg_type(const u8 *msg_type, int mandatory)
550{
551	if (msg_type == NULL) {
552		if (mandatory) {
553			wpa_printf(MSG_INFO, "WPS-STRICT: Message Type "
554				   "attribute missing");
555			return -1;
556		}
557		return 0;
558	}
559	if (*msg_type < WPS_Beacon || *msg_type > WPS_WSC_DONE) {
560		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Message Type "
561			   "attribute value 0x%x", *msg_type);
562		return -1;
563	}
564	return 0;
565}
566
567
568static int wps_validate_mac_addr(const u8 *mac_addr, int mandatory)
569{
570	if (mac_addr == NULL) {
571		if (mandatory) {
572			wpa_printf(MSG_INFO, "WPS-STRICT: MAC Address "
573				   "attribute missing");
574			return -1;
575		}
576		return 0;
577	}
578	if (mac_addr[0] & 0x01) {
579		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid MAC Address "
580			   "attribute value " MACSTR, MAC2STR(mac_addr));
581		return -1;
582	}
583	return 0;
584}
585
586
587static int wps_validate_enrollee_nonce(const u8 *enrollee_nonce, int mandatory)
588{
589	if (enrollee_nonce == NULL) {
590		if (mandatory) {
591			wpa_printf(MSG_INFO, "WPS-STRICT: Enrollee Nonce "
592				   "attribute missing");
593			return -1;
594		}
595		return 0;
596	}
597	return 0;
598}
599
600
601static int wps_validate_registrar_nonce(const u8 *registrar_nonce,
602					int mandatory)
603{
604	if (registrar_nonce == NULL) {
605		if (mandatory) {
606			wpa_printf(MSG_INFO, "WPS-STRICT: Registrar Nonce "
607				   "attribute missing");
608			return -1;
609		}
610		return 0;
611	}
612	return 0;
613}
614
615
616static int wps_validate_public_key(const u8 *public_key, size_t len,
617				   int mandatory)
618{
619	if (public_key == NULL) {
620		if (mandatory) {
621			wpa_printf(MSG_INFO, "WPS-STRICT: Public Key "
622				   "attribute missing");
623			return -1;
624		}
625		return 0;
626	}
627	if (len != 192) {
628		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Public Key "
629			   "attribute length %d", (int) len);
630		return -1;
631	}
632	return 0;
633}
634
635
636static int num_bits_set(u16 val)
637{
638	int c;
639	for (c = 0; val; c++)
640		val &= val - 1;
641	return c;
642}
643
644
645static int wps_validate_auth_type_flags(const u8 *flags, int mandatory)
646{
647	u16 val;
648
649	if (flags == NULL) {
650		if (mandatory) {
651			wpa_printf(MSG_INFO, "WPS-STRICT: Authentication Type "
652				   "Flags attribute missing");
653			return -1;
654		}
655		return 0;
656	}
657	val = WPA_GET_BE16(flags);
658	if ((val & ~WPS_AUTH_TYPES) || !(val & WPS_AUTH_WPA2PSK)) {
659		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Authentication Type "
660			   "Flags attribute value 0x%04x", val);
661		return -1;
662	}
663	return 0;
664}
665
666
667static int wps_validate_auth_type(const u8 *type, int mandatory)
668{
669	u16 val;
670
671	if (type == NULL) {
672		if (mandatory) {
673			wpa_printf(MSG_INFO, "WPS-STRICT: Authentication Type "
674				   "attribute missing");
675			return -1;
676		}
677		return 0;
678	}
679	val = WPA_GET_BE16(type);
680	if ((val & ~WPS_AUTH_TYPES) || val == 0 ||
681	    (num_bits_set(val) > 1 &&
682	     val != (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK))) {
683		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Authentication Type "
684			   "attribute value 0x%04x", val);
685		return -1;
686	}
687	return 0;
688}
689
690
691static int wps_validate_encr_type_flags(const u8 *flags, int mandatory)
692{
693	u16 val;
694
695	if (flags == NULL) {
696		if (mandatory) {
697			wpa_printf(MSG_INFO, "WPS-STRICT: Encryption Type "
698				   "Flags attribute missing");
699			return -1;
700		}
701		return 0;
702	}
703	val = WPA_GET_BE16(flags);
704	if ((val & ~WPS_ENCR_TYPES) || !(val & WPS_ENCR_AES)) {
705		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Encryption Type "
706			   "Flags attribute value 0x%04x", val);
707		return -1;
708	}
709	return 0;
710}
711
712
713static int wps_validate_encr_type(const u8 *type, int mandatory)
714{
715	u16 val;
716
717	if (type == NULL) {
718		if (mandatory) {
719			wpa_printf(MSG_INFO, "WPS-STRICT: Encryption Type "
720				   "attribute missing");
721			return -1;
722		}
723		return 0;
724	}
725	val = WPA_GET_BE16(type);
726	if ((val & ~WPS_ENCR_TYPES) || val == 0 ||
727	    (num_bits_set(val) > 1 && val != (WPS_ENCR_TKIP | WPS_ENCR_AES))) {
728		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Encryption Type "
729			   "attribute value 0x%04x", val);
730		return -1;
731	}
732	return 0;
733}
734
735
736static int wps_validate_conn_type_flags(const u8 *flags, int mandatory)
737{
738	if (flags == NULL) {
739		if (mandatory) {
740			wpa_printf(MSG_INFO, "WPS-STRICT: Connection Type "
741				   "Flags attribute missing");
742			return -1;
743		}
744		return 0;
745	}
746	if ((*flags & ~(WPS_CONN_ESS | WPS_CONN_IBSS)) ||
747	    !(*flags & WPS_CONN_ESS)) {
748		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Connection Type "
749			   "Flags attribute value 0x%02x", *flags);
750		return -1;
751	}
752	return 0;
753}
754
755
756static int wps_validate_os_version(const u8 *os_version, int mandatory)
757{
758	if (os_version == NULL) {
759		if (mandatory) {
760			wpa_printf(MSG_INFO, "WPS-STRICT: OS Version "
761				   "attribute missing");
762			return -1;
763		}
764		return 0;
765	}
766	return 0;
767}
768
769
770static int wps_validate_authenticator(const u8 *authenticator, int mandatory)
771{
772	if (authenticator == NULL) {
773		if (mandatory) {
774			wpa_printf(MSG_INFO, "WPS-STRICT: Authenticator "
775				   "attribute missing");
776			return -1;
777		}
778		return 0;
779	}
780	return 0;
781}
782
783
784static int wps_validate_e_hash1(const u8 *hash, int mandatory)
785{
786	if (hash == NULL) {
787		if (mandatory) {
788			wpa_printf(MSG_INFO, "WPS-STRICT: E-Hash1 "
789				   "attribute missing");
790			return -1;
791		}
792		return 0;
793	}
794	return 0;
795}
796
797
798static int wps_validate_e_hash2(const u8 *hash, int mandatory)
799{
800	if (hash == NULL) {
801		if (mandatory) {
802			wpa_printf(MSG_INFO, "WPS-STRICT: E-Hash2 "
803				   "attribute missing");
804			return -1;
805		}
806		return 0;
807	}
808	return 0;
809}
810
811
812static int wps_validate_r_hash1(const u8 *hash, int mandatory)
813{
814	if (hash == NULL) {
815		if (mandatory) {
816			wpa_printf(MSG_INFO, "WPS-STRICT: R-Hash1 "
817				   "attribute missing");
818			return -1;
819		}
820		return 0;
821	}
822	return 0;
823}
824
825
826static int wps_validate_r_hash2(const u8 *hash, int mandatory)
827{
828	if (hash == NULL) {
829		if (mandatory) {
830			wpa_printf(MSG_INFO, "WPS-STRICT: R-Hash2 "
831				   "attribute missing");
832			return -1;
833		}
834		return 0;
835	}
836	return 0;
837}
838
839
840static int wps_validate_encr_settings(const u8 *encr_settings, size_t len,
841				   int mandatory)
842{
843	if (encr_settings == NULL) {
844		if (mandatory) {
845			wpa_printf(MSG_INFO, "WPS-STRICT: Encrypted Settings "
846				   "attribute missing");
847			return -1;
848		}
849		return 0;
850	}
851	if (len < 16) {
852		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Encrypted Settings "
853			   "attribute length %d", (int) len);
854		return -1;
855	}
856	return 0;
857}
858
859
860static int wps_validate_settings_delay_time(const u8 *delay, int mandatory)
861{
862	if (delay == NULL) {
863		if (mandatory) {
864			wpa_printf(MSG_INFO, "WPS-STRICT: Settings Delay Time "
865				   "attribute missing");
866			return -1;
867		}
868		return 0;
869	}
870	return 0;
871}
872
873
874static int wps_validate_r_snonce1(const u8 *nonce, int mandatory)
875{
876	if (nonce == NULL) {
877		if (mandatory) {
878			wpa_printf(MSG_INFO, "WPS-STRICT: R-SNonce1 "
879				   "attribute missing");
880			return -1;
881		}
882		return 0;
883	}
884	return 0;
885}
886
887
888static int wps_validate_r_snonce2(const u8 *nonce, int mandatory)
889{
890	if (nonce == NULL) {
891		if (mandatory) {
892			wpa_printf(MSG_INFO, "WPS-STRICT: R-SNonce2 "
893				   "attribute missing");
894			return -1;
895		}
896		return 0;
897	}
898	return 0;
899}
900
901
902static int wps_validate_e_snonce1(const u8 *nonce, int mandatory)
903{
904	if (nonce == NULL) {
905		if (mandatory) {
906			wpa_printf(MSG_INFO, "WPS-STRICT: E-SNonce1 "
907				   "attribute missing");
908			return -1;
909		}
910		return 0;
911	}
912	return 0;
913}
914
915
916static int wps_validate_e_snonce2(const u8 *nonce, int mandatory)
917{
918	if (nonce == NULL) {
919		if (mandatory) {
920			wpa_printf(MSG_INFO, "WPS-STRICT: E-SNonce2 "
921				   "attribute missing");
922			return -1;
923		}
924		return 0;
925	}
926	return 0;
927}
928
929
930static int wps_validate_key_wrap_auth(const u8 *auth, int mandatory)
931{
932	if (auth == NULL) {
933		if (mandatory) {
934			wpa_printf(MSG_INFO, "WPS-STRICT: Key Wrap "
935				   "Authenticator attribute missing");
936			return -1;
937		}
938		return 0;
939	}
940	return 0;
941}
942
943
944static int wps_validate_ssid(const u8 *ssid, size_t ssid_len, int mandatory)
945{
946	if (ssid == NULL) {
947		if (mandatory) {
948			wpa_printf(MSG_INFO, "WPS-STRICT: SSID "
949				   "attribute missing");
950			return -1;
951		}
952		return 0;
953	}
954	if (ssid_len == 0 || ssid[ssid_len - 1] == 0) {
955		wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid SSID "
956				  "attribute value", ssid, ssid_len);
957		return -1;
958	}
959	return 0;
960}
961
962
963static int wps_validate_network_key_index(const u8 *idx, int mandatory)
964{
965	if (idx == NULL) {
966		if (mandatory) {
967			wpa_printf(MSG_INFO, "WPS-STRICT: Network Key Index "
968				   "attribute missing");
969			return -1;
970		}
971		return 0;
972	}
973	return 0;
974}
975
976
977static int wps_validate_network_idx(const u8 *idx, int mandatory)
978{
979	if (idx == NULL) {
980		if (mandatory) {
981			wpa_printf(MSG_INFO, "WPS-STRICT: Network Index "
982				   "attribute missing");
983			return -1;
984		}
985		return 0;
986	}
987	return 0;
988}
989
990
991static int wps_validate_network_key(const u8 *key, size_t key_len,
992				    const u8 *encr_type, int mandatory)
993{
994	if (key == NULL) {
995		if (mandatory) {
996			wpa_printf(MSG_INFO, "WPS-STRICT: Network Key "
997				   "attribute missing");
998			return -1;
999		}
1000		return 0;
1001	}
1002	if (((encr_type == NULL || WPA_GET_BE16(encr_type) != WPS_ENCR_WEP) &&
1003	     key_len > 8 && key_len < 64 && key[key_len - 1] == 0) ||
1004	    key_len > 64) {
1005		wpa_hexdump_ascii_key(MSG_INFO, "WPS-STRICT: Invalid Network "
1006				      "Key attribute value", key, key_len);
1007		return -1;
1008	}
1009	return 0;
1010}
1011
1012
1013static int wps_validate_network_key_shareable(const u8 *val, int mandatory)
1014{
1015	if (val == NULL) {
1016		if (mandatory) {
1017			wpa_printf(MSG_INFO, "WPS-STRICT: Network Key "
1018				   "Shareable attribute missing");
1019			return -1;
1020		}
1021		return 0;
1022	}
1023	if (*val > 1) {
1024		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Network Key "
1025			   "Shareable attribute value 0x%x", *val);
1026		return -1;
1027	}
1028	return 0;
1029}
1030
1031
1032static int wps_validate_cred(const u8 *cred, size_t len)
1033{
1034	struct wps_parse_attr attr;
1035	struct wpabuf buf;
1036
1037	if (cred == NULL)
1038		return -1;
1039	wpabuf_set(&buf, cred, len);
1040	if (wps_parse_msg(&buf, &attr) < 0) {
1041		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse Credential");
1042		return -1;
1043	}
1044
1045	if (wps_validate_network_idx(attr.network_idx, 1) ||
1046	    wps_validate_ssid(attr.ssid, attr.ssid_len, 1) ||
1047	    wps_validate_auth_type(attr.auth_type, 1) ||
1048	    wps_validate_encr_type(attr.encr_type, 1) ||
1049	    wps_validate_network_key_index(attr.network_key_idx, 0) ||
1050	    wps_validate_network_key(attr.network_key, attr.network_key_len,
1051				     attr.encr_type, 1) ||
1052	    wps_validate_mac_addr(attr.mac_addr, 1) ||
1053	    wps_validate_network_key_shareable(attr.network_key_shareable, 0))
1054	{
1055		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Credential");
1056		return -1;
1057	}
1058
1059
1060	return 0;
1061}
1062
1063
1064static int wps_validate_credential(const u8 *cred[], size_t len[], size_t num,
1065				   int mandatory)
1066{
1067	size_t i;
1068
1069	if (num == 0) {
1070		if (mandatory) {
1071			wpa_printf(MSG_INFO, "WPS-STRICT: Credential "
1072				   "attribute missing");
1073			return -1;
1074		}
1075		return 0;
1076	}
1077
1078	for (i = 0; i < num; i++) {
1079		if (wps_validate_cred(cred[i], len[i]) < 0)
1080			return -1;
1081	}
1082
1083	return 0;
1084}
1085
1086
1087int wps_validate_beacon(const struct wpabuf *wps_ie)
1088{
1089	struct wps_parse_attr attr;
1090	int wps2, sel_reg;
1091
1092	if (wps_ie == NULL) {
1093		wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in Beacon frame");
1094		return -1;
1095	}
1096	if (wps_parse_msg(wps_ie, &attr) < 0) {
1097		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1098			   "Beacon frame");
1099		return -1;
1100	}
1101
1102	wps2 = attr.version2 != NULL;
1103	sel_reg = attr.selected_registrar != NULL &&
1104		*attr.selected_registrar != 0;
1105	if (wps_validate_version(attr.version, 1) ||
1106	    wps_validate_wps_state(attr.wps_state, 1) ||
1107	    wps_validate_ap_setup_locked(attr.ap_setup_locked, 0) ||
1108	    wps_validate_selected_registrar(attr.selected_registrar, 0) ||
1109	    wps_validate_dev_password_id(attr.dev_password_id, sel_reg) ||
1110	    wps_validate_sel_reg_config_methods(attr.sel_reg_config_methods,
1111						wps2, sel_reg) ||
1112	    wps_validate_uuid_e(attr.uuid_e, 0) ||
1113	    wps_validate_rf_bands(attr.rf_bands, 0) ||
1114	    wps_validate_version2(attr.version2, wps2) ||
1115	    wps_validate_authorized_macs(attr.authorized_macs,
1116					 attr.authorized_macs_len, 0)) {
1117		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Beacon frame");
1118		return -1;
1119	}
1120
1121	return 0;
1122}
1123
1124
1125int wps_validate_beacon_probe_resp(const struct wpabuf *wps_ie, int probe,
1126				   const u8 *addr)
1127{
1128	struct wps_parse_attr attr;
1129	int wps2, sel_reg;
1130
1131	if (wps_ie == NULL) {
1132		wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in "
1133			   "%sProbe Response frame", probe ? "" : "Beacon/");
1134		return -1;
1135	}
1136	if (wps_parse_msg(wps_ie, &attr) < 0) {
1137		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1138			   "%sProbe Response frame", probe ? "" : "Beacon/");
1139		return -1;
1140	}
1141
1142	wps2 = attr.version2 != NULL;
1143	sel_reg = attr.selected_registrar != NULL &&
1144		*attr.selected_registrar != 0;
1145	if (wps_validate_version(attr.version, 1) ||
1146	    wps_validate_wps_state(attr.wps_state, 1) ||
1147	    wps_validate_ap_setup_locked(attr.ap_setup_locked, 0) ||
1148	    wps_validate_selected_registrar(attr.selected_registrar, 0) ||
1149	    wps_validate_dev_password_id(attr.dev_password_id, sel_reg) ||
1150	    wps_validate_sel_reg_config_methods(attr.sel_reg_config_methods,
1151						wps2, sel_reg) ||
1152	    wps_validate_response_type(attr.response_type, probe) ||
1153	    wps_validate_uuid_e(attr.uuid_e, probe) ||
1154	    wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1155				      probe) ||
1156	    wps_validate_model_name(attr.model_name, attr.model_name_len,
1157				    probe) ||
1158	    wps_validate_model_number(attr.model_number, attr.model_number_len,
1159				      probe) ||
1160	    wps_validate_serial_number(attr.serial_number,
1161				       attr.serial_number_len, probe) ||
1162	    wps_validate_primary_dev_type(attr.primary_dev_type, probe) ||
1163	    wps_validate_dev_name(attr.dev_name, attr.dev_name_len, probe) ||
1164	    wps_validate_ap_config_methods(attr.config_methods, wps2, probe) ||
1165	    wps_validate_rf_bands(attr.rf_bands, 0) ||
1166	    wps_validate_version2(attr.version2, wps2) ||
1167	    wps_validate_authorized_macs(attr.authorized_macs,
1168					 attr.authorized_macs_len, 0)) {
1169		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid %sProbe Response "
1170			   "frame from " MACSTR, probe ? "" : "Beacon/",
1171			   MAC2STR(addr));
1172#ifdef WPS_STRICT_WPS2
1173		if (wps2)
1174			return -1;
1175#else /* WPS_STRICT_WPS2 */
1176		return -1;
1177#endif /* WPS_STRICT_WPS2 */
1178	}
1179
1180	return 0;
1181}
1182
1183
1184int wps_validate_probe_req(const struct wpabuf *wps_ie, const u8 *addr)
1185{
1186	struct wps_parse_attr attr;
1187	int wps2;
1188
1189	if (wps_ie == NULL) {
1190		wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in "
1191			   "Probe Request frame");
1192		return -1;
1193	}
1194	if (wps_parse_msg(wps_ie, &attr) < 0) {
1195		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1196			   "Probe Request frame");
1197		return -1;
1198	}
1199
1200	wps2 = attr.version2 != NULL;
1201	if (wps_validate_version(attr.version, 1) ||
1202	    wps_validate_request_type(attr.request_type, 1) ||
1203	    wps_validate_config_methods(attr.config_methods, wps2, 1) ||
1204	    wps_validate_uuid_e(attr.uuid_e, attr.uuid_r == NULL) ||
1205	    wps_validate_uuid_r(attr.uuid_r, attr.uuid_e == NULL) ||
1206	    wps_validate_primary_dev_type(attr.primary_dev_type, 1) ||
1207	    wps_validate_rf_bands(attr.rf_bands, 1) ||
1208	    wps_validate_assoc_state(attr.assoc_state, 1) ||
1209	    wps_validate_config_error(attr.config_error, 1) ||
1210	    wps_validate_dev_password_id(attr.dev_password_id, 1) ||
1211	    wps_validate_version2(attr.version2, wps2) ||
1212	    wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1213				      wps2) ||
1214	    wps_validate_model_name(attr.model_name, attr.model_name_len,
1215				    wps2) ||
1216	    wps_validate_model_number(attr.model_number, attr.model_number_len,
1217				      wps2) ||
1218	    wps_validate_dev_name(attr.dev_name, attr.dev_name_len, wps2) ||
1219	    wps_validate_request_to_enroll(attr.request_to_enroll, 0) ||
1220	    wps_validate_req_dev_type(attr.req_dev_type, attr.num_req_dev_type,
1221				      0)) {
1222		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Probe Request "
1223			   "frame from " MACSTR, MAC2STR(addr));
1224		return -1;
1225	}
1226
1227	return 0;
1228}
1229
1230
1231int wps_validate_assoc_req(const struct wpabuf *wps_ie)
1232{
1233	struct wps_parse_attr attr;
1234	int wps2;
1235
1236	if (wps_ie == NULL) {
1237		wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in "
1238			   "(Re)Association Request frame");
1239		return -1;
1240	}
1241	if (wps_parse_msg(wps_ie, &attr) < 0) {
1242		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1243			   "(Re)Association Request frame");
1244		return -1;
1245	}
1246
1247	wps2 = attr.version2 != NULL;
1248	if (wps_validate_version(attr.version, 1) ||
1249	    wps_validate_request_type(attr.request_type, 1) ||
1250	    wps_validate_version2(attr.version2, wps2)) {
1251		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid (Re)Association "
1252			   "Request frame");
1253		return -1;
1254	}
1255
1256	return 0;
1257}
1258
1259
1260int wps_validate_assoc_resp(const struct wpabuf *wps_ie)
1261{
1262	struct wps_parse_attr attr;
1263	int wps2;
1264
1265	if (wps_ie == NULL) {
1266		wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in "
1267			   "(Re)Association Response frame");
1268		return -1;
1269	}
1270	if (wps_parse_msg(wps_ie, &attr) < 0) {
1271		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1272			   "(Re)Association Response frame");
1273		return -1;
1274	}
1275
1276	wps2 = attr.version2 != NULL;
1277	if (wps_validate_version(attr.version, 1) ||
1278	    wps_validate_response_type(attr.response_type, 1) ||
1279	    wps_validate_version2(attr.version2, wps2)) {
1280		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid (Re)Association "
1281			   "Response frame");
1282		return -1;
1283	}
1284
1285	return 0;
1286}
1287
1288
1289int wps_validate_m1(const struct wpabuf *tlvs)
1290{
1291	struct wps_parse_attr attr;
1292	int wps2;
1293
1294	if (tlvs == NULL) {
1295		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M1");
1296		return -1;
1297	}
1298	if (wps_parse_msg(tlvs, &attr) < 0) {
1299		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1300			   "in M1");
1301		return -1;
1302	}
1303
1304	wps2 = attr.version2 != NULL;
1305	if (wps_validate_version(attr.version, 1) ||
1306	    wps_validate_msg_type(attr.msg_type, 1) ||
1307	    wps_validate_uuid_e(attr.uuid_e, 1) ||
1308	    wps_validate_mac_addr(attr.mac_addr, 1) ||
1309	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1310	    wps_validate_public_key(attr.public_key, attr.public_key_len, 1) ||
1311	    wps_validate_auth_type_flags(attr.auth_type_flags, 1) ||
1312	    wps_validate_encr_type_flags(attr.encr_type_flags, 1) ||
1313	    wps_validate_conn_type_flags(attr.conn_type_flags, 1) ||
1314	    wps_validate_config_methods(attr.config_methods, wps2, 1) ||
1315	    wps_validate_wps_state(attr.wps_state, 1) ||
1316	    wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1317				      1) ||
1318	    wps_validate_model_name(attr.model_name, attr.model_name_len, 1) ||
1319	    wps_validate_model_number(attr.model_number, attr.model_number_len,
1320				      1) ||
1321	    wps_validate_serial_number(attr.serial_number,
1322				       attr.serial_number_len, 1) ||
1323	    wps_validate_primary_dev_type(attr.primary_dev_type, 1) ||
1324	    wps_validate_dev_name(attr.dev_name, attr.dev_name_len, 1) ||
1325	    wps_validate_rf_bands(attr.rf_bands, 1) ||
1326	    wps_validate_assoc_state(attr.assoc_state, 1) ||
1327	    wps_validate_dev_password_id(attr.dev_password_id, 1) ||
1328	    wps_validate_config_error(attr.config_error, 1) ||
1329	    wps_validate_os_version(attr.os_version, 1) ||
1330	    wps_validate_version2(attr.version2, wps2) ||
1331	    wps_validate_request_to_enroll(attr.request_to_enroll, 0)) {
1332		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M1");
1333#ifdef WPS_STRICT_WPS2
1334		if (wps2)
1335			return -1;
1336#else /* WPS_STRICT_WPS2 */
1337		return -1;
1338#endif /* WPS_STRICT_WPS2 */
1339	}
1340
1341	return 0;
1342}
1343
1344
1345int wps_validate_m2(const struct wpabuf *tlvs)
1346{
1347	struct wps_parse_attr attr;
1348	int wps2;
1349
1350	if (tlvs == NULL) {
1351		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M2");
1352		return -1;
1353	}
1354	if (wps_parse_msg(tlvs, &attr) < 0) {
1355		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1356			   "in M2");
1357		return -1;
1358	}
1359
1360	wps2 = attr.version2 != NULL;
1361	if (wps_validate_version(attr.version, 1) ||
1362	    wps_validate_msg_type(attr.msg_type, 1) ||
1363	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1364	    wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1365	    wps_validate_uuid_r(attr.uuid_r, 1) ||
1366	    wps_validate_public_key(attr.public_key, attr.public_key_len, 1) ||
1367	    wps_validate_auth_type_flags(attr.auth_type_flags, 1) ||
1368	    wps_validate_encr_type_flags(attr.encr_type_flags, 1) ||
1369	    wps_validate_conn_type_flags(attr.conn_type_flags, 1) ||
1370	    wps_validate_config_methods(attr.config_methods, wps2, 1) ||
1371	    wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1372				      1) ||
1373	    wps_validate_model_name(attr.model_name, attr.model_name_len, 1) ||
1374	    wps_validate_model_number(attr.model_number, attr.model_number_len,
1375				      1) ||
1376	    wps_validate_serial_number(attr.serial_number,
1377				       attr.serial_number_len, 1) ||
1378	    wps_validate_primary_dev_type(attr.primary_dev_type, 1) ||
1379	    wps_validate_dev_name(attr.dev_name, attr.dev_name_len, 1) ||
1380	    wps_validate_rf_bands(attr.rf_bands, 1) ||
1381	    wps_validate_assoc_state(attr.assoc_state, 1) ||
1382	    wps_validate_config_error(attr.config_error, 1) ||
1383	    wps_validate_dev_password_id(attr.dev_password_id, 1) ||
1384	    wps_validate_os_version(attr.os_version, 1) ||
1385	    wps_validate_version2(attr.version2, wps2) ||
1386	    wps_validate_authenticator(attr.authenticator, 1)) {
1387		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M2");
1388#ifdef WPS_STRICT_WPS2
1389		if (wps2)
1390			return -1;
1391#else /* WPS_STRICT_WPS2 */
1392		return -1;
1393#endif /* WPS_STRICT_WPS2 */
1394	}
1395
1396	return 0;
1397}
1398
1399
1400int wps_validate_m2d(const struct wpabuf *tlvs)
1401{
1402	struct wps_parse_attr attr;
1403	int wps2;
1404
1405	if (tlvs == NULL) {
1406		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M2D");
1407		return -1;
1408	}
1409	if (wps_parse_msg(tlvs, &attr) < 0) {
1410		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1411			   "in M2D");
1412		return -1;
1413	}
1414
1415	wps2 = attr.version2 != NULL;
1416	if (wps_validate_version(attr.version, 1) ||
1417	    wps_validate_msg_type(attr.msg_type, 1) ||
1418	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1419	    wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1420	    wps_validate_uuid_r(attr.uuid_r, 1) ||
1421	    wps_validate_auth_type_flags(attr.auth_type_flags, 1) ||
1422	    wps_validate_encr_type_flags(attr.encr_type_flags, 1) ||
1423	    wps_validate_conn_type_flags(attr.conn_type_flags, 1) ||
1424	    wps_validate_config_methods(attr.config_methods, wps2, 1) ||
1425	    wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1426				      1) ||
1427	    wps_validate_model_name(attr.model_name, attr.model_name_len, 1) ||
1428	    wps_validate_model_number(attr.model_number, attr.model_number_len,
1429				      1) ||
1430	    wps_validate_serial_number(attr.serial_number,
1431				       attr.serial_number_len, 1) ||
1432	    wps_validate_primary_dev_type(attr.primary_dev_type, 1) ||
1433	    wps_validate_dev_name(attr.dev_name, attr.dev_name_len, 1) ||
1434	    wps_validate_rf_bands(attr.rf_bands, 1) ||
1435	    wps_validate_assoc_state(attr.assoc_state, 1) ||
1436	    wps_validate_config_error(attr.config_error, 1) ||
1437	    wps_validate_os_version(attr.os_version, 1) ||
1438	    wps_validate_version2(attr.version2, wps2)) {
1439		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M2D");
1440#ifdef WPS_STRICT_WPS2
1441		if (wps2)
1442			return -1;
1443#else /* WPS_STRICT_WPS2 */
1444		return -1;
1445#endif /* WPS_STRICT_WPS2 */
1446	}
1447
1448	return 0;
1449}
1450
1451
1452int wps_validate_m3(const struct wpabuf *tlvs)
1453{
1454	struct wps_parse_attr attr;
1455	int wps2;
1456
1457	if (tlvs == NULL) {
1458		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M3");
1459		return -1;
1460	}
1461	if (wps_parse_msg(tlvs, &attr) < 0) {
1462		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1463			   "in M3");
1464		return -1;
1465	}
1466
1467	wps2 = attr.version2 != NULL;
1468	if (wps_validate_version(attr.version, 1) ||
1469	    wps_validate_msg_type(attr.msg_type, 1) ||
1470	    wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1471	    wps_validate_e_hash1(attr.e_hash1, 1) ||
1472	    wps_validate_e_hash2(attr.e_hash2, 1) ||
1473	    wps_validate_version2(attr.version2, wps2) ||
1474	    wps_validate_authenticator(attr.authenticator, 1)) {
1475		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M3");
1476#ifdef WPS_STRICT_WPS2
1477		if (wps2)
1478			return -1;
1479#else /* WPS_STRICT_WPS2 */
1480		return -1;
1481#endif /* WPS_STRICT_WPS2 */
1482	}
1483
1484	return 0;
1485}
1486
1487
1488int wps_validate_m4(const struct wpabuf *tlvs)
1489{
1490	struct wps_parse_attr attr;
1491	int wps2;
1492
1493	if (tlvs == NULL) {
1494		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M4");
1495		return -1;
1496	}
1497	if (wps_parse_msg(tlvs, &attr) < 0) {
1498		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1499			   "in M4");
1500		return -1;
1501	}
1502
1503	wps2 = attr.version2 != NULL;
1504	if (wps_validate_version(attr.version, 1) ||
1505	    wps_validate_msg_type(attr.msg_type, 1) ||
1506	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1507	    wps_validate_r_hash1(attr.r_hash1, 1) ||
1508	    wps_validate_r_hash2(attr.r_hash2, 1) ||
1509	    wps_validate_encr_settings(attr.encr_settings,
1510				       attr.encr_settings_len, 1) ||
1511	    wps_validate_version2(attr.version2, wps2) ||
1512	    wps_validate_authenticator(attr.authenticator, 1)) {
1513		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M4");
1514#ifdef WPS_STRICT_WPS2
1515		if (wps2)
1516			return -1;
1517#else /* WPS_STRICT_WPS2 */
1518		return -1;
1519#endif /* WPS_STRICT_WPS2 */
1520	}
1521
1522	return 0;
1523}
1524
1525
1526int wps_validate_m4_encr(const struct wpabuf *tlvs, int wps2)
1527{
1528	struct wps_parse_attr attr;
1529
1530	if (tlvs == NULL) {
1531		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M4 encrypted "
1532			   "settings");
1533		return -1;
1534	}
1535	if (wps_parse_msg(tlvs, &attr) < 0) {
1536		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1537			   "in M4 encrypted settings");
1538		return -1;
1539	}
1540
1541	if (wps_validate_r_snonce1(attr.r_snonce1, 1) ||
1542	    wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1543		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M4 encrypted "
1544			   "settings");
1545#ifdef WPS_STRICT_WPS2
1546		if (wps2)
1547			return -1;
1548#else /* WPS_STRICT_WPS2 */
1549		return -1;
1550#endif /* WPS_STRICT_WPS2 */
1551	}
1552
1553	return 0;
1554}
1555
1556
1557int wps_validate_m5(const struct wpabuf *tlvs)
1558{
1559	struct wps_parse_attr attr;
1560	int wps2;
1561
1562	if (tlvs == NULL) {
1563		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M5");
1564		return -1;
1565	}
1566	if (wps_parse_msg(tlvs, &attr) < 0) {
1567		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1568			   "in M5");
1569		return -1;
1570	}
1571
1572	wps2 = attr.version2 != NULL;
1573	if (wps_validate_version(attr.version, 1) ||
1574	    wps_validate_msg_type(attr.msg_type, 1) ||
1575	    wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1576	    wps_validate_encr_settings(attr.encr_settings,
1577				       attr.encr_settings_len, 1) ||
1578	    wps_validate_version2(attr.version2, wps2) ||
1579	    wps_validate_authenticator(attr.authenticator, 1)) {
1580		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M5");
1581#ifdef WPS_STRICT_WPS2
1582		if (wps2)
1583			return -1;
1584#else /* WPS_STRICT_WPS2 */
1585		return -1;
1586#endif /* WPS_STRICT_WPS2 */
1587	}
1588
1589	return 0;
1590}
1591
1592
1593int wps_validate_m5_encr(const struct wpabuf *tlvs, int wps2)
1594{
1595	struct wps_parse_attr attr;
1596
1597	if (tlvs == NULL) {
1598		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M5 encrypted "
1599			   "settings");
1600		return -1;
1601	}
1602	if (wps_parse_msg(tlvs, &attr) < 0) {
1603		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1604			   "in M5 encrypted settings");
1605		return -1;
1606	}
1607
1608	if (wps_validate_e_snonce1(attr.e_snonce1, 1) ||
1609	    wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1610		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M5 encrypted "
1611			   "settings");
1612#ifdef WPS_STRICT_WPS2
1613		if (wps2)
1614			return -1;
1615#else /* WPS_STRICT_WPS2 */
1616		return -1;
1617#endif /* WPS_STRICT_WPS2 */
1618	}
1619
1620	return 0;
1621}
1622
1623
1624int wps_validate_m6(const struct wpabuf *tlvs)
1625{
1626	struct wps_parse_attr attr;
1627	int wps2;
1628
1629	if (tlvs == NULL) {
1630		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M6");
1631		return -1;
1632	}
1633	if (wps_parse_msg(tlvs, &attr) < 0) {
1634		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1635			   "in M6");
1636		return -1;
1637	}
1638
1639	wps2 = attr.version2 != NULL;
1640	if (wps_validate_version(attr.version, 1) ||
1641	    wps_validate_msg_type(attr.msg_type, 1) ||
1642	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1643	    wps_validate_encr_settings(attr.encr_settings,
1644				       attr.encr_settings_len, 1) ||
1645	    wps_validate_version2(attr.version2, wps2) ||
1646	    wps_validate_authenticator(attr.authenticator, 1)) {
1647		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M6");
1648#ifdef WPS_STRICT_WPS2
1649		if (wps2)
1650			return -1;
1651#else /* WPS_STRICT_WPS2 */
1652		return -1;
1653#endif /* WPS_STRICT_WPS2 */
1654	}
1655
1656	return 0;
1657}
1658
1659
1660int wps_validate_m6_encr(const struct wpabuf *tlvs, int wps2)
1661{
1662	struct wps_parse_attr attr;
1663
1664	if (tlvs == NULL) {
1665		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M6 encrypted "
1666			   "settings");
1667		return -1;
1668	}
1669	if (wps_parse_msg(tlvs, &attr) < 0) {
1670		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1671			   "in M6 encrypted settings");
1672		return -1;
1673	}
1674
1675	if (wps_validate_r_snonce2(attr.r_snonce2, 1) ||
1676	    wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1677		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M6 encrypted "
1678			   "settings");
1679#ifdef WPS_STRICT_WPS2
1680		if (wps2)
1681			return -1;
1682#else /* WPS_STRICT_WPS2 */
1683		return -1;
1684#endif /* WPS_STRICT_WPS2 */
1685	}
1686
1687	return 0;
1688}
1689
1690
1691int wps_validate_m7(const struct wpabuf *tlvs)
1692{
1693	struct wps_parse_attr attr;
1694	int wps2;
1695
1696	if (tlvs == NULL) {
1697		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M7");
1698		return -1;
1699	}
1700	if (wps_parse_msg(tlvs, &attr) < 0) {
1701		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1702			   "in M7");
1703		return -1;
1704	}
1705
1706	wps2 = attr.version2 != NULL;
1707	if (wps_validate_version(attr.version, 1) ||
1708	    wps_validate_msg_type(attr.msg_type, 1) ||
1709	    wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1710	    wps_validate_encr_settings(attr.encr_settings,
1711				       attr.encr_settings_len, 1) ||
1712	    wps_validate_settings_delay_time(attr.settings_delay_time, 0) ||
1713	    wps_validate_version2(attr.version2, wps2) ||
1714	    wps_validate_authenticator(attr.authenticator, 1)) {
1715		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M7");
1716#ifdef WPS_STRICT_WPS2
1717		if (wps2)
1718			return -1;
1719#else /* WPS_STRICT_WPS2 */
1720		return -1;
1721#endif /* WPS_STRICT_WPS2 */
1722	}
1723
1724	return 0;
1725}
1726
1727
1728int wps_validate_m7_encr(const struct wpabuf *tlvs, int ap, int wps2)
1729{
1730	struct wps_parse_attr attr;
1731
1732	if (tlvs == NULL) {
1733		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M7 encrypted "
1734			   "settings");
1735		return -1;
1736	}
1737	if (wps_parse_msg(tlvs, &attr) < 0) {
1738		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1739			   "in M7 encrypted settings");
1740		return -1;
1741	}
1742
1743	if (wps_validate_e_snonce2(attr.e_snonce2, 1) ||
1744	    wps_validate_ssid(attr.ssid, attr.ssid_len, !ap) ||
1745	    wps_validate_mac_addr(attr.mac_addr, !ap) ||
1746	    wps_validate_auth_type(attr.auth_type, !ap) ||
1747	    wps_validate_encr_type(attr.encr_type, !ap) ||
1748	    wps_validate_network_key_index(attr.network_key_idx, 0) ||
1749	    wps_validate_network_key(attr.network_key, attr.network_key_len,
1750				     attr.encr_type, !ap) ||
1751	    wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1752		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M7 encrypted "
1753			   "settings");
1754#ifdef WPS_STRICT_WPS2
1755		if (wps2)
1756			return -1;
1757#else /* WPS_STRICT_WPS2 */
1758		return -1;
1759#endif /* WPS_STRICT_WPS2 */
1760	}
1761
1762	return 0;
1763}
1764
1765
1766int wps_validate_m8(const struct wpabuf *tlvs)
1767{
1768	struct wps_parse_attr attr;
1769	int wps2;
1770
1771	if (tlvs == NULL) {
1772		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M8");
1773		return -1;
1774	}
1775	if (wps_parse_msg(tlvs, &attr) < 0) {
1776		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1777			   "in M8");
1778		return -1;
1779	}
1780
1781	wps2 = attr.version2 != NULL;
1782	if (wps_validate_version(attr.version, 1) ||
1783	    wps_validate_msg_type(attr.msg_type, 1) ||
1784	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1785	    wps_validate_encr_settings(attr.encr_settings,
1786				       attr.encr_settings_len, 1) ||
1787	    wps_validate_version2(attr.version2, wps2) ||
1788	    wps_validate_authenticator(attr.authenticator, 1)) {
1789		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M8");
1790#ifdef WPS_STRICT_WPS2
1791		if (wps2)
1792			return -1;
1793#else /* WPS_STRICT_WPS2 */
1794		return -1;
1795#endif /* WPS_STRICT_WPS2 */
1796	}
1797
1798	return 0;
1799}
1800
1801
1802int wps_validate_m8_encr(const struct wpabuf *tlvs, int ap, int wps2)
1803{
1804	struct wps_parse_attr attr;
1805
1806	if (tlvs == NULL) {
1807		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M8 encrypted "
1808			   "settings");
1809		return -1;
1810	}
1811	if (wps_parse_msg(tlvs, &attr) < 0) {
1812		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1813			   "in M8 encrypted settings");
1814		return -1;
1815	}
1816
1817	if (wps_validate_ssid(attr.ssid, attr.ssid_len, ap) ||
1818	    wps_validate_auth_type(attr.auth_type, ap) ||
1819	    wps_validate_encr_type(attr.encr_type, ap) ||
1820	    wps_validate_network_key_index(attr.network_key_idx, 0) ||
1821	    wps_validate_mac_addr(attr.mac_addr, ap) ||
1822	    wps_validate_credential(attr.cred, attr.cred_len, attr.num_cred,
1823				    !ap) ||
1824	    wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1825		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M8 encrypted "
1826			   "settings");
1827#ifdef WPS_STRICT_WPS2
1828		if (wps2)
1829			return -1;
1830#else /* WPS_STRICT_WPS2 */
1831		return -1;
1832#endif /* WPS_STRICT_WPS2 */
1833	}
1834
1835	return 0;
1836}
1837
1838
1839int wps_validate_wsc_ack(const struct wpabuf *tlvs)
1840{
1841	struct wps_parse_attr attr;
1842	int wps2;
1843
1844	if (tlvs == NULL) {
1845		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_ACK");
1846		return -1;
1847	}
1848	if (wps_parse_msg(tlvs, &attr) < 0) {
1849		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1850			   "in WSC_ACK");
1851		return -1;
1852	}
1853
1854	wps2 = attr.version2 != NULL;
1855	if (wps_validate_version(attr.version, 1) ||
1856	    wps_validate_msg_type(attr.msg_type, 1) ||
1857	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1858	    wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1859	    wps_validate_version2(attr.version2, wps2)) {
1860		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_ACK");
1861#ifdef WPS_STRICT_WPS2
1862		if (wps2)
1863			return -1;
1864#else /* WPS_STRICT_WPS2 */
1865		return -1;
1866#endif /* WPS_STRICT_WPS2 */
1867	}
1868
1869	return 0;
1870}
1871
1872
1873int wps_validate_wsc_nack(const struct wpabuf *tlvs)
1874{
1875	struct wps_parse_attr attr;
1876	int wps2;
1877
1878	if (tlvs == NULL) {
1879		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_NACK");
1880		return -1;
1881	}
1882	if (wps_parse_msg(tlvs, &attr) < 0) {
1883		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1884			   "in WSC_NACK");
1885		return -1;
1886	}
1887
1888	wps2 = attr.version2 != NULL;
1889	if (wps_validate_version(attr.version, 1) ||
1890	    wps_validate_msg_type(attr.msg_type, 1) ||
1891	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1892	    wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1893	    wps_validate_config_error(attr.config_error, 1) ||
1894	    wps_validate_version2(attr.version2, wps2)) {
1895		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_NACK");
1896#ifdef WPS_STRICT_WPS2
1897		if (wps2)
1898			return -1;
1899#else /* WPS_STRICT_WPS2 */
1900		return -1;
1901#endif /* WPS_STRICT_WPS2 */
1902	}
1903
1904	return 0;
1905}
1906
1907
1908int wps_validate_wsc_done(const struct wpabuf *tlvs)
1909{
1910	struct wps_parse_attr attr;
1911	int wps2;
1912
1913	if (tlvs == NULL) {
1914		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_Done");
1915		return -1;
1916	}
1917	if (wps_parse_msg(tlvs, &attr) < 0) {
1918		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1919			   "in WSC_Done");
1920		return -1;
1921	}
1922
1923	wps2 = attr.version2 != NULL;
1924	if (wps_validate_version(attr.version, 1) ||
1925	    wps_validate_msg_type(attr.msg_type, 1) ||
1926	    wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1927	    wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1928	    wps_validate_version2(attr.version2, wps2)) {
1929		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_Done");
1930#ifdef WPS_STRICT_WPS2
1931		if (wps2)
1932			return -1;
1933#else /* WPS_STRICT_WPS2 */
1934		return -1;
1935#endif /* WPS_STRICT_WPS2 */
1936	}
1937
1938	return 0;
1939}
1940
1941
1942int wps_validate_upnp_set_selected_registrar(const struct wpabuf *tlvs)
1943{
1944	struct wps_parse_attr attr;
1945	int wps2;
1946	int sel_reg;
1947
1948	if (tlvs == NULL) {
1949		wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in "
1950			   "SetSelectedRegistrar");
1951		return -1;
1952	}
1953	if (wps_parse_msg(tlvs, &attr) < 0) {
1954		wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1955			   "in SetSelectedRegistrar");
1956		return -1;
1957	}
1958
1959	wps2 = attr.version2 != NULL;
1960	sel_reg = attr.selected_registrar != NULL &&
1961		*attr.selected_registrar != 0;
1962	if (wps_validate_version(attr.version, 1) ||
1963	    wps_validate_dev_password_id(attr.dev_password_id, sel_reg) ||
1964	    wps_validate_sel_reg_config_methods(attr.sel_reg_config_methods,
1965						wps2, sel_reg) ||
1966	    wps_validate_version2(attr.version2, wps2) ||
1967	    wps_validate_authorized_macs(attr.authorized_macs,
1968					 attr.authorized_macs_len, wps2) ||
1969	    wps_validate_uuid_r(attr.uuid_r, wps2)) {
1970		wpa_printf(MSG_INFO, "WPS-STRICT: Invalid "
1971			   "SetSelectedRegistrar");
1972#ifdef WPS_STRICT_WPS2
1973		if (wps2)
1974			return -1;
1975#else /* WPS_STRICT_WPS2 */
1976		return -1;
1977#endif /* WPS_STRICT_WPS2 */
1978	}
1979
1980	return 0;
1981}
1982