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