blob: c3071a0dbd18b1f1c9be834dc7cd1064dbe1c845 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
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
27static 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
46static 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
65static 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
84static 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
103static 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
134static 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
158static 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
179static 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
193static 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
207static 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
222static 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
242static 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
263static 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
285static 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
308static 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
328static 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
348static 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
368static 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
389static 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
409static 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
429static 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
444static 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
464static 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
484static 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
504static 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
529static 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
549static 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
568static 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
587static 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
601static 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
616static 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
636static 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
645static 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
667static 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
691static 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
713static 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
736static 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
756static 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
770static 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
784static 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
798static 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
812static 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
826static 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
840static 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
860static 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
874static 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
888static 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
902static 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
916static 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
930static 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
944static 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
963static 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
977static 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
991static 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
1013static 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
1032static 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
1064static 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
1087int 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
1125int 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
1184int 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
1231int 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
1260int 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
1289int 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
1345int 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
1400int 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
1452int 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
1488int 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
1526int 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
1557int 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
1593int 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
1624int 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
1660int 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
1691int 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
1728int 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
1766int 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
1802int 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
1839int 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
1873int 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
1908int 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
1942int 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}