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