]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/wpa/src/wps/wps_validate.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / wpa / src / wps / wps_validate.c
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
21 static 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
40 static 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
59 static 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
78 static 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
97 static 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
128 static 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
152 static 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
173 static 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
187 static 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
201 static 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
216 static 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
236 static 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
257 static 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 > 18) {
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
279 static 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 >= 0x0006 && 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
302 static 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
322 static 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
342 static 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
362 static 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
383 static 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
403 static 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
423 static 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
438 static 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
458 static 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
478 static 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
498 static 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
523 static 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
543 static 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
562 static 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
581 static 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
595 static 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
610 static 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
630 static 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
639 static 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
661 static 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
685 static 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
707 static 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
730 static 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
750 static 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
764 static 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
778 static 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
792 static 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
806 static 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
820 static 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
834 static 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
854 static 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
868 static 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
882 static 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
896 static 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
910 static 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
924 static 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
938 static 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
957 static 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
971 static 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
985 static 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
1007 static 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
1026 static 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
1058 static 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
1081 int 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
1119 int 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
1178 int 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
1225 int 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
1254 int 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
1283 int 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
1339 int 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
1394 int 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
1446 int 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
1482 int 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
1520 int 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
1551 int 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
1587 int 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
1618 int 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
1654 int 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
1685 int 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
1722 int 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
1760 int 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
1796 int 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
1833 int 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
1867 int 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
1902 int 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
1936 int 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 }