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