55d3677e9fa29c2a3cbc7ce1f6c9737d54d92dd6
[libeap.git] / src / wps / wps_validate.c
1 /*
2  * Wi-Fi Protected Setup - Strict protocol validation routines
3  * Copyright (c) 2010, Atheros Communications, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "utils/includes.h"
16
17 #include "utils/common.h"
18 #include "wps_i.h"
19 #include "wps.h"
20
21
22 #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 {
1127         struct wps_parse_attr attr;
1128         int wps2, sel_reg;
1129
1130         if (wps_ie == NULL) {
1131                 wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in "
1132                            "%sProbe Response frame", probe ? "" : "Beacon/");
1133                 return -1;
1134         }
1135         if (wps_parse_msg(wps_ie, &attr) < 0) {
1136                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1137                            "%sProbe Response frame", probe ? "" : "Beacon/");
1138                 return -1;
1139         }
1140
1141         wps2 = attr.version2 != NULL;
1142         sel_reg = attr.selected_registrar != NULL &&
1143                 *attr.selected_registrar != 0;
1144         if (wps_validate_version(attr.version, 1) ||
1145             wps_validate_wps_state(attr.wps_state, 1) ||
1146             wps_validate_ap_setup_locked(attr.ap_setup_locked, 0) ||
1147             wps_validate_selected_registrar(attr.selected_registrar, 0) ||
1148             wps_validate_dev_password_id(attr.dev_password_id, sel_reg) ||
1149             wps_validate_sel_reg_config_methods(attr.sel_reg_config_methods,
1150                                                 wps2, sel_reg) ||
1151             wps_validate_response_type(attr.response_type, probe) ||
1152             wps_validate_uuid_e(attr.uuid_e, probe) ||
1153             wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1154                                       probe) ||
1155             wps_validate_model_name(attr.model_name, attr.model_name_len,
1156                                     probe) ||
1157             wps_validate_model_number(attr.model_number, attr.model_number_len,
1158                                       probe) ||
1159             wps_validate_serial_number(attr.serial_number,
1160                                        attr.serial_number_len, probe) ||
1161             wps_validate_primary_dev_type(attr.primary_dev_type, probe) ||
1162             wps_validate_dev_name(attr.dev_name, attr.dev_name_len, probe) ||
1163             wps_validate_ap_config_methods(attr.config_methods, wps2, probe) ||
1164             wps_validate_rf_bands(attr.rf_bands, 0) ||
1165             wps_validate_version2(attr.version2, wps2) ||
1166             wps_validate_authorized_macs(attr.authorized_macs,
1167                                          attr.authorized_macs_len, 0)) {
1168                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid %sProbe Response "
1169                            "frame", probe ? "" : "Beacon/");
1170 #ifdef WPS_STRICT_WPS2
1171                 if (wps2)
1172                         return -1;
1173 #else /* WPS_STRICT_WPS2 */
1174                 return -1;
1175 #endif /* WPS_STRICT_WPS2 */
1176         }
1177
1178         return 0;
1179 }
1180
1181
1182 int wps_validate_probe_req(const struct wpabuf *wps_ie)
1183 {
1184         struct wps_parse_attr attr;
1185         int wps2;
1186
1187         if (wps_ie == NULL) {
1188                 wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in "
1189                            "Probe Request frame");
1190                 return -1;
1191         }
1192         if (wps_parse_msg(wps_ie, &attr) < 0) {
1193                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1194                            "Probe Request frame");
1195                 return -1;
1196         }
1197
1198         wps2 = attr.version2 != NULL;
1199         if (wps_validate_version(attr.version, 1) ||
1200             wps_validate_request_type(attr.request_type, 1) ||
1201             wps_validate_config_methods(attr.config_methods, wps2, 1) ||
1202             wps_validate_uuid_e(attr.uuid_e, attr.uuid_r == NULL) ||
1203             wps_validate_uuid_r(attr.uuid_r, attr.uuid_e == NULL) ||
1204             wps_validate_primary_dev_type(attr.primary_dev_type, 1) ||
1205             wps_validate_rf_bands(attr.rf_bands, 1) ||
1206             wps_validate_assoc_state(attr.assoc_state, 1) ||
1207             wps_validate_config_error(attr.config_error, 1) ||
1208             wps_validate_dev_password_id(attr.dev_password_id, 1) ||
1209             wps_validate_version2(attr.version2, wps2) ||
1210             wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1211                                       wps2) ||
1212             wps_validate_model_name(attr.model_name, attr.model_name_len,
1213                                     wps2) ||
1214             wps_validate_model_number(attr.model_number, attr.model_number_len,
1215                                       wps2) ||
1216             wps_validate_dev_name(attr.dev_name, attr.dev_name_len, wps2) ||
1217             wps_validate_request_to_enroll(attr.request_to_enroll, 0) ||
1218             wps_validate_req_dev_type(attr.req_dev_type, attr.num_req_dev_type,
1219                                       0)) {
1220                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Probe Request "
1221                            "frame");
1222                 return -1;
1223         }
1224
1225         return 0;
1226 }
1227
1228
1229 int wps_validate_assoc_req(const struct wpabuf *wps_ie)
1230 {
1231         struct wps_parse_attr attr;
1232         int wps2;
1233
1234         if (wps_ie == NULL) {
1235                 wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in "
1236                            "(Re)Association Request frame");
1237                 return -1;
1238         }
1239         if (wps_parse_msg(wps_ie, &attr) < 0) {
1240                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1241                            "(Re)Association Request frame");
1242                 return -1;
1243         }
1244
1245         wps2 = attr.version2 != NULL;
1246         if (wps_validate_version(attr.version, 1) ||
1247             wps_validate_request_type(attr.request_type, 1) ||
1248             wps_validate_version2(attr.version2, wps2)) {
1249                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid (Re)Association "
1250                            "Request frame");
1251                 return -1;
1252         }
1253
1254         return 0;
1255 }
1256
1257
1258 int wps_validate_assoc_resp(const struct wpabuf *wps_ie)
1259 {
1260         struct wps_parse_attr attr;
1261         int wps2;
1262
1263         if (wps_ie == NULL) {
1264                 wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in "
1265                            "(Re)Association Response frame");
1266                 return -1;
1267         }
1268         if (wps_parse_msg(wps_ie, &attr) < 0) {
1269                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in "
1270                            "(Re)Association Response frame");
1271                 return -1;
1272         }
1273
1274         wps2 = attr.version2 != NULL;
1275         if (wps_validate_version(attr.version, 1) ||
1276             wps_validate_request_type(attr.request_type, 1) ||
1277             wps_validate_version2(attr.version2, wps2)) {
1278                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid (Re)Association "
1279                            "Response frame");
1280                 return -1;
1281         }
1282
1283         return 0;
1284 }
1285
1286
1287 int wps_validate_m1(const struct wpabuf *tlvs)
1288 {
1289         struct wps_parse_attr attr;
1290         int wps2;
1291
1292         if (tlvs == NULL) {
1293                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M1");
1294                 return -1;
1295         }
1296         if (wps_parse_msg(tlvs, &attr) < 0) {
1297                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1298                            "in M1");
1299                 return -1;
1300         }
1301
1302         wps2 = attr.version2 != NULL;
1303         if (wps_validate_version(attr.version, 1) ||
1304             wps_validate_msg_type(attr.msg_type, 1) ||
1305             wps_validate_uuid_e(attr.uuid_e, 1) ||
1306             wps_validate_mac_addr(attr.mac_addr, 1) ||
1307             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1308             wps_validate_public_key(attr.public_key, attr.public_key_len, 1) ||
1309             wps_validate_auth_type_flags(attr.auth_type_flags, 1) ||
1310             wps_validate_encr_type_flags(attr.encr_type_flags, 1) ||
1311             wps_validate_conn_type_flags(attr.conn_type_flags, 1) ||
1312             wps_validate_config_methods(attr.config_methods, wps2, 1) ||
1313             wps_validate_wps_state(attr.wps_state, 1) ||
1314             wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1315                                       1) ||
1316             wps_validate_model_name(attr.model_name, attr.model_name_len, 1) ||
1317             wps_validate_model_number(attr.model_number, attr.model_number_len,
1318                                       1) ||
1319             wps_validate_serial_number(attr.serial_number,
1320                                        attr.serial_number_len, 1) ||
1321             wps_validate_primary_dev_type(attr.primary_dev_type, 1) ||
1322             wps_validate_dev_name(attr.dev_name, attr.dev_name_len, 1) ||
1323             wps_validate_rf_bands(attr.rf_bands, 1) ||
1324             wps_validate_assoc_state(attr.assoc_state, 1) ||
1325             wps_validate_dev_password_id(attr.dev_password_id, 1) ||
1326             wps_validate_config_error(attr.config_error, 1) ||
1327             wps_validate_os_version(attr.os_version, 1) ||
1328             wps_validate_version2(attr.version2, wps2) ||
1329             wps_validate_request_to_enroll(attr.request_to_enroll, 0)) {
1330                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M1");
1331 #ifdef WPS_STRICT_WPS2
1332                 if (wps2)
1333                         return -1;
1334 #else /* WPS_STRICT_WPS2 */
1335                 return -1;
1336 #endif /* WPS_STRICT_WPS2 */
1337         }
1338
1339         return 0;
1340 }
1341
1342
1343 int wps_validate_m2(const struct wpabuf *tlvs)
1344 {
1345         struct wps_parse_attr attr;
1346         int wps2;
1347
1348         if (tlvs == NULL) {
1349                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M2");
1350                 return -1;
1351         }
1352         if (wps_parse_msg(tlvs, &attr) < 0) {
1353                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1354                            "in M2");
1355                 return -1;
1356         }
1357
1358         wps2 = attr.version2 != NULL;
1359         if (wps_validate_version(attr.version, 1) ||
1360             wps_validate_msg_type(attr.msg_type, 1) ||
1361             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1362             wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1363             wps_validate_uuid_r(attr.uuid_r, 1) ||
1364             wps_validate_public_key(attr.public_key, attr.public_key_len, 1) ||
1365             wps_validate_auth_type_flags(attr.auth_type_flags, 1) ||
1366             wps_validate_encr_type_flags(attr.encr_type_flags, 1) ||
1367             wps_validate_conn_type_flags(attr.conn_type_flags, 1) ||
1368             wps_validate_config_methods(attr.config_methods, wps2, 1) ||
1369             wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1370                                       1) ||
1371             wps_validate_model_name(attr.model_name, attr.model_name_len, 1) ||
1372             wps_validate_model_number(attr.model_number, attr.model_number_len,
1373                                       1) ||
1374             wps_validate_serial_number(attr.serial_number,
1375                                        attr.serial_number_len, 1) ||
1376             wps_validate_primary_dev_type(attr.primary_dev_type, 1) ||
1377             wps_validate_dev_name(attr.dev_name, attr.dev_name_len, 1) ||
1378             wps_validate_rf_bands(attr.rf_bands, 1) ||
1379             wps_validate_assoc_state(attr.assoc_state, 1) ||
1380             wps_validate_config_error(attr.config_error, 1) ||
1381             wps_validate_dev_password_id(attr.dev_password_id, 1) ||
1382             wps_validate_os_version(attr.os_version, 1) ||
1383             wps_validate_version2(attr.version2, wps2) ||
1384             wps_validate_authenticator(attr.authenticator, 1)) {
1385                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M2");
1386 #ifdef WPS_STRICT_WPS2
1387                 if (wps2)
1388                         return -1;
1389 #else /* WPS_STRICT_WPS2 */
1390                 return -1;
1391 #endif /* WPS_STRICT_WPS2 */
1392         }
1393
1394         return 0;
1395 }
1396
1397
1398 int wps_validate_m2d(const struct wpabuf *tlvs)
1399 {
1400         struct wps_parse_attr attr;
1401         int wps2;
1402
1403         if (tlvs == NULL) {
1404                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M2D");
1405                 return -1;
1406         }
1407         if (wps_parse_msg(tlvs, &attr) < 0) {
1408                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1409                            "in M2D");
1410                 return -1;
1411         }
1412
1413         wps2 = attr.version2 != NULL;
1414         if (wps_validate_version(attr.version, 1) ||
1415             wps_validate_msg_type(attr.msg_type, 1) ||
1416             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1417             wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1418             wps_validate_uuid_r(attr.uuid_r, 1) ||
1419             wps_validate_auth_type_flags(attr.auth_type_flags, 1) ||
1420             wps_validate_encr_type_flags(attr.encr_type_flags, 1) ||
1421             wps_validate_conn_type_flags(attr.conn_type_flags, 1) ||
1422             wps_validate_config_methods(attr.config_methods, wps2, 1) ||
1423             wps_validate_manufacturer(attr.manufacturer, attr.manufacturer_len,
1424                                       1) ||
1425             wps_validate_model_name(attr.model_name, attr.model_name_len, 1) ||
1426             wps_validate_model_number(attr.model_number, attr.model_number_len,
1427                                       1) ||
1428             wps_validate_serial_number(attr.serial_number,
1429                                        attr.serial_number_len, 1) ||
1430             wps_validate_primary_dev_type(attr.primary_dev_type, 1) ||
1431             wps_validate_dev_name(attr.dev_name, attr.dev_name_len, 1) ||
1432             wps_validate_rf_bands(attr.rf_bands, 1) ||
1433             wps_validate_assoc_state(attr.assoc_state, 1) ||
1434             wps_validate_config_error(attr.config_error, 1) ||
1435             wps_validate_os_version(attr.os_version, 1) ||
1436             wps_validate_version2(attr.version2, wps2)) {
1437                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M2D");
1438 #ifdef WPS_STRICT_WPS2
1439                 if (wps2)
1440                         return -1;
1441 #else /* WPS_STRICT_WPS2 */
1442                 return -1;
1443 #endif /* WPS_STRICT_WPS2 */
1444         }
1445
1446         return 0;
1447 }
1448
1449
1450 int wps_validate_m3(const struct wpabuf *tlvs)
1451 {
1452         struct wps_parse_attr attr;
1453         int wps2;
1454
1455         if (tlvs == NULL) {
1456                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M3");
1457                 return -1;
1458         }
1459         if (wps_parse_msg(tlvs, &attr) < 0) {
1460                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1461                            "in M3");
1462                 return -1;
1463         }
1464
1465         wps2 = attr.version2 != NULL;
1466         if (wps_validate_version(attr.version, 1) ||
1467             wps_validate_msg_type(attr.msg_type, 1) ||
1468             wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1469             wps_validate_e_hash1(attr.e_hash1, 1) ||
1470             wps_validate_e_hash2(attr.e_hash2, 1) ||
1471             wps_validate_version2(attr.version2, wps2) ||
1472             wps_validate_authenticator(attr.authenticator, 1)) {
1473                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M3");
1474 #ifdef WPS_STRICT_WPS2
1475                 if (wps2)
1476                         return -1;
1477 #else /* WPS_STRICT_WPS2 */
1478                 return -1;
1479 #endif /* WPS_STRICT_WPS2 */
1480         }
1481
1482         return 0;
1483 }
1484
1485
1486 int wps_validate_m4(const struct wpabuf *tlvs)
1487 {
1488         struct wps_parse_attr attr;
1489         int wps2;
1490
1491         if (tlvs == NULL) {
1492                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M4");
1493                 return -1;
1494         }
1495         if (wps_parse_msg(tlvs, &attr) < 0) {
1496                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1497                            "in M4");
1498                 return -1;
1499         }
1500
1501         wps2 = attr.version2 != NULL;
1502         if (wps_validate_version(attr.version, 1) ||
1503             wps_validate_msg_type(attr.msg_type, 1) ||
1504             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1505             wps_validate_r_hash1(attr.r_hash1, 1) ||
1506             wps_validate_r_hash2(attr.r_hash2, 1) ||
1507             wps_validate_encr_settings(attr.encr_settings,
1508                                        attr.encr_settings_len, 1) ||
1509             wps_validate_version2(attr.version2, wps2) ||
1510             wps_validate_authenticator(attr.authenticator, 1)) {
1511                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M4");
1512 #ifdef WPS_STRICT_WPS2
1513                 if (wps2)
1514                         return -1;
1515 #else /* WPS_STRICT_WPS2 */
1516                 return -1;
1517 #endif /* WPS_STRICT_WPS2 */
1518         }
1519
1520         return 0;
1521 }
1522
1523
1524 int wps_validate_m4_encr(const struct wpabuf *tlvs)
1525 {
1526         struct wps_parse_attr attr;
1527         int wps2;
1528
1529         if (tlvs == NULL) {
1530                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M4 encrypted "
1531                            "settings");
1532                 return -1;
1533         }
1534         if (wps_parse_msg(tlvs, &attr) < 0) {
1535                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1536                            "in M4 encrypted settings");
1537                 return -1;
1538         }
1539
1540         wps2 = attr.version2 != NULL;
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)
1594 {
1595         struct wps_parse_attr attr;
1596         int wps2;
1597
1598         if (tlvs == NULL) {
1599                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M5 encrypted "
1600                            "settings");
1601                 return -1;
1602         }
1603         if (wps_parse_msg(tlvs, &attr) < 0) {
1604                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1605                            "in M5 encrypted settings");
1606                 return -1;
1607         }
1608
1609         wps2 = attr.version2 != NULL;
1610         if (wps_validate_e_snonce1(attr.e_snonce1, 1) ||
1611             wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1612                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M5 encrypted "
1613                            "settings");
1614 #ifdef WPS_STRICT_WPS2
1615                 if (wps2)
1616                         return -1;
1617 #else /* WPS_STRICT_WPS2 */
1618                 return -1;
1619 #endif /* WPS_STRICT_WPS2 */
1620         }
1621
1622         return 0;
1623 }
1624
1625
1626 int wps_validate_m6(const struct wpabuf *tlvs)
1627 {
1628         struct wps_parse_attr attr;
1629         int wps2;
1630
1631         if (tlvs == NULL) {
1632                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M6");
1633                 return -1;
1634         }
1635         if (wps_parse_msg(tlvs, &attr) < 0) {
1636                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1637                            "in M6");
1638                 return -1;
1639         }
1640
1641         wps2 = attr.version2 != NULL;
1642         if (wps_validate_version(attr.version, 1) ||
1643             wps_validate_msg_type(attr.msg_type, 1) ||
1644             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1645             wps_validate_encr_settings(attr.encr_settings,
1646                                        attr.encr_settings_len, 1) ||
1647             wps_validate_version2(attr.version2, wps2) ||
1648             wps_validate_authenticator(attr.authenticator, 1)) {
1649                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M6");
1650 #ifdef WPS_STRICT_WPS2
1651                 if (wps2)
1652                         return -1;
1653 #else /* WPS_STRICT_WPS2 */
1654                 return -1;
1655 #endif /* WPS_STRICT_WPS2 */
1656         }
1657
1658         return 0;
1659 }
1660
1661
1662 int wps_validate_m6_encr(const struct wpabuf *tlvs)
1663 {
1664         struct wps_parse_attr attr;
1665         int wps2;
1666
1667         if (tlvs == NULL) {
1668                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M6 encrypted "
1669                            "settings");
1670                 return -1;
1671         }
1672         if (wps_parse_msg(tlvs, &attr) < 0) {
1673                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1674                            "in M6 encrypted settings");
1675                 return -1;
1676         }
1677
1678         wps2 = attr.version2 != NULL;
1679         if (wps_validate_r_snonce2(attr.r_snonce2, 1) ||
1680             wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1681                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M6 encrypted "
1682                            "settings");
1683 #ifdef WPS_STRICT_WPS2
1684                 if (wps2)
1685                         return -1;
1686 #else /* WPS_STRICT_WPS2 */
1687                 return -1;
1688 #endif /* WPS_STRICT_WPS2 */
1689         }
1690
1691         return 0;
1692 }
1693
1694
1695 int wps_validate_m7(const struct wpabuf *tlvs)
1696 {
1697         struct wps_parse_attr attr;
1698         int wps2;
1699
1700         if (tlvs == NULL) {
1701                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M7");
1702                 return -1;
1703         }
1704         if (wps_parse_msg(tlvs, &attr) < 0) {
1705                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1706                            "in M7");
1707                 return -1;
1708         }
1709
1710         wps2 = attr.version2 != NULL;
1711         if (wps_validate_version(attr.version, 1) ||
1712             wps_validate_msg_type(attr.msg_type, 1) ||
1713             wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1714             wps_validate_encr_settings(attr.encr_settings,
1715                                        attr.encr_settings_len, 1) ||
1716             wps_validate_settings_delay_time(attr.settings_delay_time, 0) ||
1717             wps_validate_version2(attr.version2, wps2) ||
1718             wps_validate_authenticator(attr.authenticator, 1)) {
1719                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M7");
1720 #ifdef WPS_STRICT_WPS2
1721                 if (wps2)
1722                         return -1;
1723 #else /* WPS_STRICT_WPS2 */
1724                 return -1;
1725 #endif /* WPS_STRICT_WPS2 */
1726         }
1727
1728         return 0;
1729 }
1730
1731
1732 int wps_validate_m7_encr(const struct wpabuf *tlvs, int ap)
1733 {
1734         struct wps_parse_attr attr;
1735         int wps2;
1736
1737         if (tlvs == NULL) {
1738                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M7 encrypted "
1739                            "settings");
1740                 return -1;
1741         }
1742         if (wps_parse_msg(tlvs, &attr) < 0) {
1743                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1744                            "in M7 encrypted settings");
1745                 return -1;
1746         }
1747
1748         wps2 = attr.version2 != NULL;
1749         if (wps_validate_e_snonce2(attr.e_snonce2, 1) ||
1750             wps_validate_ssid(attr.ssid, attr.ssid_len, !ap) ||
1751             wps_validate_mac_addr(attr.mac_addr, !ap) ||
1752             wps_validate_auth_type(attr.auth_type, !ap) ||
1753             wps_validate_encr_type(attr.encr_type, !ap) ||
1754             wps_validate_network_key_index(attr.network_key_idx, 0) ||
1755             wps_validate_network_key(attr.network_key, attr.network_key_len,
1756                                      attr.encr_type, !ap) ||
1757             wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1758                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M7 encrypted "
1759                            "settings");
1760 #ifdef WPS_STRICT_WPS2
1761                 if (wps2)
1762                         return -1;
1763 #else /* WPS_STRICT_WPS2 */
1764                 return -1;
1765 #endif /* WPS_STRICT_WPS2 */
1766         }
1767
1768         return 0;
1769 }
1770
1771
1772 int wps_validate_m8(const struct wpabuf *tlvs)
1773 {
1774         struct wps_parse_attr attr;
1775         int wps2;
1776
1777         if (tlvs == NULL) {
1778                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M8");
1779                 return -1;
1780         }
1781         if (wps_parse_msg(tlvs, &attr) < 0) {
1782                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1783                            "in M8");
1784                 return -1;
1785         }
1786
1787         wps2 = attr.version2 != NULL;
1788         if (wps_validate_version(attr.version, 1) ||
1789             wps_validate_msg_type(attr.msg_type, 1) ||
1790             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1791             wps_validate_encr_settings(attr.encr_settings,
1792                                        attr.encr_settings_len, 1) ||
1793             wps_validate_version2(attr.version2, wps2) ||
1794             wps_validate_authenticator(attr.authenticator, 1)) {
1795                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M8");
1796 #ifdef WPS_STRICT_WPS2
1797                 if (wps2)
1798                         return -1;
1799 #else /* WPS_STRICT_WPS2 */
1800                 return -1;
1801 #endif /* WPS_STRICT_WPS2 */
1802         }
1803
1804         return 0;
1805 }
1806
1807
1808 int wps_validate_m8_encr(const struct wpabuf *tlvs, int ap)
1809 {
1810         struct wps_parse_attr attr;
1811         int wps2;
1812
1813         if (tlvs == NULL) {
1814                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M8 encrypted "
1815                            "settings");
1816                 return -1;
1817         }
1818         if (wps_parse_msg(tlvs, &attr) < 0) {
1819                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1820                            "in M8 encrypted settings");
1821                 return -1;
1822         }
1823
1824         wps2 = attr.version2 != NULL;
1825         if (wps_validate_ssid(attr.ssid, attr.ssid_len, ap) ||
1826             wps_validate_auth_type(attr.auth_type, ap) ||
1827             wps_validate_encr_type(attr.encr_type, ap) ||
1828             wps_validate_network_key_index(attr.network_key_idx, 0) ||
1829             wps_validate_mac_addr(attr.mac_addr, ap) ||
1830             wps_validate_credential(attr.cred, attr.cred_len, attr.num_cred,
1831                                     !ap) ||
1832             wps_validate_key_wrap_auth(attr.key_wrap_auth, 1)) {
1833                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M8 encrypted "
1834                            "settings");
1835 #ifdef WPS_STRICT_WPS2
1836                 if (wps2)
1837                         return -1;
1838 #else /* WPS_STRICT_WPS2 */
1839                 return -1;
1840 #endif /* WPS_STRICT_WPS2 */
1841         }
1842
1843         return 0;
1844 }
1845
1846
1847 int wps_validate_wsc_ack(const struct wpabuf *tlvs)
1848 {
1849         struct wps_parse_attr attr;
1850         int wps2;
1851
1852         if (tlvs == NULL) {
1853                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_ACK");
1854                 return -1;
1855         }
1856         if (wps_parse_msg(tlvs, &attr) < 0) {
1857                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1858                            "in WSC_ACK");
1859                 return -1;
1860         }
1861
1862         wps2 = attr.version2 != NULL;
1863         if (wps_validate_version(attr.version, 1) ||
1864             wps_validate_msg_type(attr.msg_type, 1) ||
1865             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1866             wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1867             wps_validate_version2(attr.version2, wps2)) {
1868                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_ACK");
1869 #ifdef WPS_STRICT_WPS2
1870                 if (wps2)
1871                         return -1;
1872 #else /* WPS_STRICT_WPS2 */
1873                 return -1;
1874 #endif /* WPS_STRICT_WPS2 */
1875         }
1876
1877         return 0;
1878 }
1879
1880
1881 int wps_validate_wsc_nack(const struct wpabuf *tlvs)
1882 {
1883         struct wps_parse_attr attr;
1884         int wps2;
1885
1886         if (tlvs == NULL) {
1887                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_NACK");
1888                 return -1;
1889         }
1890         if (wps_parse_msg(tlvs, &attr) < 0) {
1891                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1892                            "in WSC_NACK");
1893                 return -1;
1894         }
1895
1896         wps2 = attr.version2 != NULL;
1897         if (wps_validate_version(attr.version, 1) ||
1898             wps_validate_msg_type(attr.msg_type, 1) ||
1899             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1900             wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1901             wps_validate_config_error(attr.config_error, 1) ||
1902             wps_validate_version2(attr.version2, wps2)) {
1903                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_NACK");
1904 #ifdef WPS_STRICT_WPS2
1905                 if (wps2)
1906                         return -1;
1907 #else /* WPS_STRICT_WPS2 */
1908                 return -1;
1909 #endif /* WPS_STRICT_WPS2 */
1910         }
1911
1912         return 0;
1913 }
1914
1915
1916 int wps_validate_wsc_done(const struct wpabuf *tlvs)
1917 {
1918         struct wps_parse_attr attr;
1919         int wps2;
1920
1921         if (tlvs == NULL) {
1922                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_Done");
1923                 return -1;
1924         }
1925         if (wps_parse_msg(tlvs, &attr) < 0) {
1926                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1927                            "in WSC_Done");
1928                 return -1;
1929         }
1930
1931         wps2 = attr.version2 != NULL;
1932         if (wps_validate_version(attr.version, 1) ||
1933             wps_validate_msg_type(attr.msg_type, 1) ||
1934             wps_validate_enrollee_nonce(attr.enrollee_nonce, 1) ||
1935             wps_validate_registrar_nonce(attr.registrar_nonce, 1) ||
1936             wps_validate_version2(attr.version2, wps2)) {
1937                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_Done");
1938 #ifdef WPS_STRICT_WPS2
1939                 if (wps2)
1940                         return -1;
1941 #else /* WPS_STRICT_WPS2 */
1942                 return -1;
1943 #endif /* WPS_STRICT_WPS2 */
1944         }
1945
1946         return 0;
1947 }
1948
1949
1950 int wps_validate_upnp_set_selected_registrar(const struct wpabuf *tlvs)
1951 {
1952         struct wps_parse_attr attr;
1953         int wps2;
1954         int sel_reg;
1955
1956         if (tlvs == NULL) {
1957                 wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in "
1958                            "SetSelectedRegistrar");
1959                 return -1;
1960         }
1961         if (wps_parse_msg(tlvs, &attr) < 0) {
1962                 wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes "
1963                            "in SetSelectedRegistrar");
1964                 return -1;
1965         }
1966
1967         wps2 = attr.version2 != NULL;
1968         sel_reg = attr.selected_registrar != NULL &&
1969                 *attr.selected_registrar != 0;
1970         if (wps_validate_version(attr.version, 1) ||
1971             wps_validate_dev_password_id(attr.dev_password_id, sel_reg) ||
1972             wps_validate_sel_reg_config_methods(attr.sel_reg_config_methods,
1973                                                 wps2, sel_reg) ||
1974             wps_validate_version2(attr.version2, wps2) ||
1975             wps_validate_authorized_macs(attr.authorized_macs,
1976                                          attr.authorized_macs_len, wps2) ||
1977             wps_validate_uuid_r(attr.uuid_r, wps2)) {
1978                 wpa_printf(MSG_INFO, "WPS-STRICT: Invalid "
1979                            "SetSelectedRegistrar");
1980 #ifdef WPS_STRICT_WPS2
1981                 if (wps2)
1982                         return -1;
1983 #else /* WPS_STRICT_WPS2 */
1984                 return -1;
1985 #endif /* WPS_STRICT_WPS2 */
1986         }
1987
1988         return 0;
1989 }