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