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