]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/wps/wps_attr_parse.c
Update hostapd/wpa_supplicant to 2.8 to fix multiple vulnerabilities.
[FreeBSD/FreeBSD.git] / contrib / wpa / src / wps / wps_attr_parse.c
1 /*
2  * Wi-Fi Protected Setup - attribute parsing
3  * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "wps_defs.h"
13 #include "wps_attr_parse.h"
14
15 #ifndef CONFIG_WPS_STRICT
16 #define WPS_WORKAROUNDS
17 #endif /* CONFIG_WPS_STRICT */
18
19
20 static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
21                                           u8 id, u8 len, const u8 *pos)
22 {
23         wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u",
24                    id, len);
25         switch (id) {
26         case WFA_ELEM_VERSION2:
27                 if (len != 1) {
28                         wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length "
29                                    "%u", len);
30                         return -1;
31                 }
32                 attr->version2 = pos;
33                 break;
34         case WFA_ELEM_AUTHORIZEDMACS:
35                 attr->authorized_macs = pos;
36                 attr->authorized_macs_len = len;
37                 break;
38         case WFA_ELEM_NETWORK_KEY_SHAREABLE:
39                 if (len != 1) {
40                         wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key "
41                                    "Shareable length %u", len);
42                         return -1;
43                 }
44                 attr->network_key_shareable = pos;
45                 break;
46         case WFA_ELEM_REQUEST_TO_ENROLL:
47                 if (len != 1) {
48                         wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll "
49                                    "length %u", len);
50                         return -1;
51                 }
52                 attr->request_to_enroll = pos;
53                 break;
54         case WFA_ELEM_SETTINGS_DELAY_TIME:
55                 if (len != 1) {
56                         wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay "
57                                    "Time length %u", len);
58                         return -1;
59                 }
60                 attr->settings_delay_time = pos;
61                 break;
62         case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS:
63                 if (len != 2) {
64                         wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u",
65                                    len);
66                         return -1;
67                 }
68                 attr->registrar_configuration_methods = pos;
69                 break;
70         case WFA_ELEM_MULTI_AP:
71                 if (len != 1) {
72                         wpa_printf(MSG_DEBUG,
73                                    "WPS: Invalid Multi-AP Extension length %u",
74                                    len);
75                         return -1;
76                 }
77                 attr->multi_ap_ext = *pos;
78                 wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x",
79                            attr->multi_ap_ext);
80                 break;
81         default:
82                 wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor "
83                            "Extension subelement %u", id);
84                 break;
85         }
86
87         return 0;
88 }
89
90
91 static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos,
92                                     u16 len)
93 {
94         const u8 *end = pos + len;
95         u8 id, elen;
96
97         while (end - pos >= 2) {
98                 id = *pos++;
99                 elen = *pos++;
100                 if (elen > end - pos)
101                         break;
102                 if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0)
103                         return -1;
104                 pos += elen;
105         }
106
107         return 0;
108 }
109
110
111 static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos,
112                                 u16 len)
113 {
114         u32 vendor_id;
115
116         if (len < 3) {
117                 wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension");
118                 return 0;
119         }
120
121         vendor_id = WPA_GET_BE24(pos);
122         switch (vendor_id) {
123         case WPS_VENDOR_ID_WFA:
124                 return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3);
125         }
126
127         /* Handle unknown vendor extensions */
128
129         wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)",
130                    vendor_id);
131
132         if (len > WPS_MAX_VENDOR_EXT_LEN) {
133                 wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)",
134                            len);
135                 return -1;
136         }
137
138         if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) {
139                 wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension "
140                            "attribute (max %d vendor extensions)",
141                            MAX_WPS_PARSE_VENDOR_EXT);
142                 return -1;
143         }
144         attr->vendor_ext[attr->num_vendor_ext] = pos;
145         attr->vendor_ext_len[attr->num_vendor_ext] = len;
146         attr->num_vendor_ext++;
147
148         return 0;
149 }
150
151
152 static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
153                         const u8 *pos, u16 len)
154 {
155         switch (type) {
156         case ATTR_VERSION:
157                 if (len != 1) {
158                         wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u",
159                                    len);
160                         return -1;
161                 }
162                 attr->version = pos;
163                 break;
164         case ATTR_MSG_TYPE:
165                 if (len != 1) {
166                         wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type "
167                                    "length %u", len);
168                         return -1;
169                 }
170                 attr->msg_type = pos;
171                 break;
172         case ATTR_ENROLLEE_NONCE:
173                 if (len != WPS_NONCE_LEN) {
174                         wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce "
175                                    "length %u", len);
176                         return -1;
177                 }
178                 attr->enrollee_nonce = pos;
179                 break;
180         case ATTR_REGISTRAR_NONCE:
181                 if (len != WPS_NONCE_LEN) {
182                         wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce "
183                                    "length %u", len);
184                         return -1;
185                 }
186                 attr->registrar_nonce = pos;
187                 break;
188         case ATTR_UUID_E:
189                 if (len != WPS_UUID_LEN) {
190                         wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u",
191                                    len);
192                         return -1;
193                 }
194                 attr->uuid_e = pos;
195                 break;
196         case ATTR_UUID_R:
197                 if (len != WPS_UUID_LEN) {
198                         wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u",
199                                    len);
200                         return -1;
201                 }
202                 attr->uuid_r = pos;
203                 break;
204         case ATTR_AUTH_TYPE_FLAGS:
205                 if (len != 2) {
206                         wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
207                                    "Type Flags length %u", len);
208                         return -1;
209                 }
210                 attr->auth_type_flags = pos;
211                 break;
212         case ATTR_ENCR_TYPE_FLAGS:
213                 if (len != 2) {
214                         wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type "
215                                    "Flags length %u", len);
216                         return -1;
217                 }
218                 attr->encr_type_flags = pos;
219                 break;
220         case ATTR_CONN_TYPE_FLAGS:
221                 if (len != 1) {
222                         wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type "
223                                    "Flags length %u", len);
224                         return -1;
225                 }
226                 attr->conn_type_flags = pos;
227                 break;
228         case ATTR_CONFIG_METHODS:
229                 if (len != 2) {
230                         wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods "
231                                    "length %u", len);
232                         return -1;
233                 }
234                 attr->config_methods = pos;
235                 break;
236         case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS:
237                 if (len != 2) {
238                         wpa_printf(MSG_DEBUG, "WPS: Invalid Selected "
239                                    "Registrar Config Methods length %u", len);
240                         return -1;
241                 }
242                 attr->sel_reg_config_methods = pos;
243                 break;
244         case ATTR_PRIMARY_DEV_TYPE:
245                 if (len != WPS_DEV_TYPE_LEN) {
246                         wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device "
247                                    "Type length %u", len);
248                         return -1;
249                 }
250                 attr->primary_dev_type = pos;
251                 break;
252         case ATTR_RF_BANDS:
253                 if (len != 1) {
254                         wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length "
255                                    "%u", len);
256                         return -1;
257                 }
258                 attr->rf_bands = pos;
259                 break;
260         case ATTR_ASSOC_STATE:
261                 if (len != 2) {
262                         wpa_printf(MSG_DEBUG, "WPS: Invalid Association State "
263                                    "length %u", len);
264                         return -1;
265                 }
266                 attr->assoc_state = pos;
267                 break;
268         case ATTR_CONFIG_ERROR:
269                 if (len != 2) {
270                         wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration "
271                                    "Error length %u", len);
272                         return -1;
273                 }
274                 attr->config_error = pos;
275                 break;
276         case ATTR_DEV_PASSWORD_ID:
277                 if (len != 2) {
278                         wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password "
279                                    "ID length %u", len);
280                         return -1;
281                 }
282                 attr->dev_password_id = pos;
283                 break;
284         case ATTR_OOB_DEVICE_PASSWORD:
285                 if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
286                     len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
287                     WPS_OOB_DEVICE_PASSWORD_LEN ||
288                     (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
289                      WPS_OOB_DEVICE_PASSWORD_MIN_LEN &&
290                      WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) !=
291                      DEV_PW_NFC_CONNECTION_HANDOVER)) {
292                         wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
293                                    "Password length %u", len);
294                         return -1;
295                 }
296                 attr->oob_dev_password = pos;
297                 attr->oob_dev_password_len = len;
298                 break;
299         case ATTR_OS_VERSION:
300                 if (len != 4) {
301                         wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length "
302                                    "%u", len);
303                         return -1;
304                 }
305                 attr->os_version = pos;
306                 break;
307         case ATTR_WPS_STATE:
308                 if (len != 1) {
309                         wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected "
310                                    "Setup State length %u", len);
311                         return -1;
312                 }
313                 attr->wps_state = pos;
314                 break;
315         case ATTR_AUTHENTICATOR:
316                 if (len != WPS_AUTHENTICATOR_LEN) {
317                         wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator "
318                                    "length %u", len);
319                         return -1;
320                 }
321                 attr->authenticator = pos;
322                 break;
323         case ATTR_R_HASH1:
324                 if (len != WPS_HASH_LEN) {
325                         wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u",
326                                    len);
327                         return -1;
328                 }
329                 attr->r_hash1 = pos;
330                 break;
331         case ATTR_R_HASH2:
332                 if (len != WPS_HASH_LEN) {
333                         wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u",
334                                    len);
335                         return -1;
336                 }
337                 attr->r_hash2 = pos;
338                 break;
339         case ATTR_E_HASH1:
340                 if (len != WPS_HASH_LEN) {
341                         wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u",
342                                    len);
343                         return -1;
344                 }
345                 attr->e_hash1 = pos;
346                 break;
347         case ATTR_E_HASH2:
348                 if (len != WPS_HASH_LEN) {
349                         wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u",
350                                    len);
351                         return -1;
352                 }
353                 attr->e_hash2 = pos;
354                 break;
355         case ATTR_R_SNONCE1:
356                 if (len != WPS_SECRET_NONCE_LEN) {
357                         wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length "
358                                    "%u", len);
359                         return -1;
360                 }
361                 attr->r_snonce1 = pos;
362                 break;
363         case ATTR_R_SNONCE2:
364                 if (len != WPS_SECRET_NONCE_LEN) {
365                         wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length "
366                                    "%u", len);
367                         return -1;
368                 }
369                 attr->r_snonce2 = pos;
370                 break;
371         case ATTR_E_SNONCE1:
372                 if (len != WPS_SECRET_NONCE_LEN) {
373                         wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length "
374                                    "%u", len);
375                         return -1;
376                 }
377                 attr->e_snonce1 = pos;
378                 break;
379         case ATTR_E_SNONCE2:
380                 if (len != WPS_SECRET_NONCE_LEN) {
381                         wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length "
382                                    "%u", len);
383                         return -1;
384                 }
385                 attr->e_snonce2 = pos;
386                 break;
387         case ATTR_KEY_WRAP_AUTH:
388                 if (len != WPS_KWA_LEN) {
389                         wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap "
390                                    "Authenticator length %u", len);
391                         return -1;
392                 }
393                 attr->key_wrap_auth = pos;
394                 break;
395         case ATTR_AUTH_TYPE:
396                 if (len != 2) {
397                         wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication "
398                                    "Type length %u", len);
399                         return -1;
400                 }
401                 attr->auth_type = pos;
402                 break;
403         case ATTR_ENCR_TYPE:
404                 if (len != 2) {
405                         wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption "
406                                    "Type length %u", len);
407                         return -1;
408                 }
409                 attr->encr_type = pos;
410                 break;
411         case ATTR_NETWORK_INDEX:
412                 if (len != 1) {
413                         wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index "
414                                    "length %u", len);
415                         return -1;
416                 }
417                 attr->network_idx = pos;
418                 break;
419         case ATTR_NETWORK_KEY_INDEX:
420                 if (len != 1) {
421                         wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index "
422                                    "length %u", len);
423                         return -1;
424                 }
425                 attr->network_key_idx = pos;
426                 break;
427         case ATTR_MAC_ADDR:
428                 if (len != ETH_ALEN) {
429                         wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address "
430                                    "length %u", len);
431                         return -1;
432                 }
433                 attr->mac_addr = pos;
434                 break;
435         case ATTR_SELECTED_REGISTRAR:
436                 if (len != 1) {
437                         wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar"
438                                    " length %u", len);
439                         return -1;
440                 }
441                 attr->selected_registrar = pos;
442                 break;
443         case ATTR_REQUEST_TYPE:
444                 if (len != 1) {
445                         wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type "
446                                    "length %u", len);
447                         return -1;
448                 }
449                 attr->request_type = pos;
450                 break;
451         case ATTR_RESPONSE_TYPE:
452                 if (len != 1) {
453                         wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type "
454                                    "length %u", len);
455                         return -1;
456                 }
457                 attr->response_type = pos;
458                 break;
459         case ATTR_MANUFACTURER:
460                 attr->manufacturer = pos;
461                 if (len > WPS_MANUFACTURER_MAX_LEN)
462                         attr->manufacturer_len = WPS_MANUFACTURER_MAX_LEN;
463                 else
464                         attr->manufacturer_len = len;
465                 break;
466         case ATTR_MODEL_NAME:
467                 attr->model_name = pos;
468                 if (len > WPS_MODEL_NAME_MAX_LEN)
469                         attr->model_name_len = WPS_MODEL_NAME_MAX_LEN;
470                 else
471                         attr->model_name_len = len;
472                 break;
473         case ATTR_MODEL_NUMBER:
474                 attr->model_number = pos;
475                 if (len > WPS_MODEL_NUMBER_MAX_LEN)
476                         attr->model_number_len = WPS_MODEL_NUMBER_MAX_LEN;
477                 else
478                         attr->model_number_len = len;
479                 break;
480         case ATTR_SERIAL_NUMBER:
481                 attr->serial_number = pos;
482                 if (len > WPS_SERIAL_NUMBER_MAX_LEN)
483                         attr->serial_number_len = WPS_SERIAL_NUMBER_MAX_LEN;
484                 else
485                         attr->serial_number_len = len;
486                 break;
487         case ATTR_DEV_NAME:
488                 if (len > WPS_DEV_NAME_MAX_LEN) {
489                         wpa_printf(MSG_DEBUG,
490                                    "WPS: Ignore too long Device Name (len=%u)",
491                                    len);
492                         break;
493                 }
494                 attr->dev_name = pos;
495                 attr->dev_name_len = len;
496                 break;
497         case ATTR_PUBLIC_KEY:
498                 /*
499                  * The Public Key attribute is supposed to be exactly 192 bytes
500                  * in length. Allow couple of bytes shorter one to try to
501                  * interoperate with implementations that do not use proper
502                  * zero-padding.
503                  */
504                 if (len < 190 || len > 192) {
505                         wpa_printf(MSG_DEBUG,
506                                    "WPS: Ignore Public Key with unexpected length %u",
507                                    len);
508                         break;
509                 }
510                 attr->public_key = pos;
511                 attr->public_key_len = len;
512                 break;
513         case ATTR_ENCR_SETTINGS:
514                 attr->encr_settings = pos;
515                 attr->encr_settings_len = len;
516                 break;
517         case ATTR_CRED:
518                 if (attr->num_cred >= MAX_CRED_COUNT) {
519                         wpa_printf(MSG_DEBUG, "WPS: Skipped Credential "
520                                    "attribute (max %d credentials)",
521                                    MAX_CRED_COUNT);
522                         break;
523                 }
524                 attr->cred[attr->num_cred] = pos;
525                 attr->cred_len[attr->num_cred] = len;
526                 attr->num_cred++;
527                 break;
528         case ATTR_SSID:
529                 if (len > SSID_MAX_LEN) {
530                         wpa_printf(MSG_DEBUG,
531                                    "WPS: Ignore too long SSID (len=%u)", len);
532                         break;
533                 }
534                 attr->ssid = pos;
535                 attr->ssid_len = len;
536                 break;
537         case ATTR_NETWORK_KEY:
538                 attr->network_key = pos;
539                 attr->network_key_len = len;
540                 break;
541         case ATTR_AP_SETUP_LOCKED:
542                 if (len != 1) {
543                         wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked "
544                                    "length %u", len);
545                         return -1;
546                 }
547                 attr->ap_setup_locked = pos;
548                 break;
549         case ATTR_REQUESTED_DEV_TYPE:
550                 if (len != WPS_DEV_TYPE_LEN) {
551                         wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device "
552                                    "Type length %u", len);
553                         return -1;
554                 }
555                 if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) {
556                         wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device "
557                                    "Type attribute (max %u types)",
558                                    MAX_REQ_DEV_TYPE_COUNT);
559                         break;
560                 }
561                 attr->req_dev_type[attr->num_req_dev_type] = pos;
562                 attr->num_req_dev_type++;
563                 break;
564         case ATTR_SECONDARY_DEV_TYPE_LIST:
565                 if (len > WPS_SEC_DEV_TYPE_MAX_LEN ||
566                     (len % WPS_DEV_TYPE_LEN) > 0) {
567                         wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device "
568                                    "Type length %u", len);
569                         return -1;
570                 }
571                 attr->sec_dev_type_list = pos;
572                 attr->sec_dev_type_list_len = len;
573                 break;
574         case ATTR_VENDOR_EXT:
575                 if (wps_parse_vendor_ext(attr, pos, len) < 0)
576                         return -1;
577                 break;
578         case ATTR_AP_CHANNEL:
579                 if (len != 2) {
580                         wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel "
581                                    "length %u", len);
582                         return -1;
583                 }
584                 attr->ap_channel = pos;
585                 break;
586         default:
587                 wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x "
588                            "len=%u", type, len);
589                 break;
590         }
591
592         return 0;
593 }
594
595
596 int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr)
597 {
598         const u8 *pos, *end;
599         u16 type, len;
600 #ifdef WPS_WORKAROUNDS
601         u16 prev_type = 0;
602 #endif /* WPS_WORKAROUNDS */
603
604         os_memset(attr, 0, sizeof(*attr));
605         pos = wpabuf_head(msg);
606         end = pos + wpabuf_len(msg);
607
608         while (pos < end) {
609                 if (end - pos < 4) {
610                         wpa_printf(MSG_DEBUG, "WPS: Invalid message - "
611                                    "%lu bytes remaining",
612                                    (unsigned long) (end - pos));
613                         return -1;
614                 }
615
616                 type = WPA_GET_BE16(pos);
617                 pos += 2;
618                 len = WPA_GET_BE16(pos);
619                 pos += 2;
620                 wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u",
621                            type, len);
622                 if (len > end - pos) {
623                         wpa_printf(MSG_DEBUG, "WPS: Attribute overflow");
624                         wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg);
625 #ifdef WPS_WORKAROUNDS
626                         /*
627                          * Some deployed APs seem to have a bug in encoding of
628                          * Network Key attribute in the Credential attribute
629                          * where they add an extra octet after the Network Key
630                          * attribute at least when open network is being
631                          * provisioned.
632                          */
633                         if ((type & 0xff00) != 0x1000 &&
634                             prev_type == ATTR_NETWORK_KEY) {
635                                 wpa_printf(MSG_DEBUG, "WPS: Workaround - try "
636                                            "to skip unexpected octet after "
637                                            "Network Key");
638                                 pos -= 3;
639                                 continue;
640                         }
641 #endif /* WPS_WORKAROUNDS */
642                         return -1;
643                 }
644
645 #ifdef WPS_WORKAROUNDS
646                 if (type == 0 && len == 0) {
647                         /*
648                          * Mac OS X 10.6 seems to be adding 0x00 padding to the
649                          * end of M1. Skip those to avoid interop issues.
650                          */
651                         int i;
652                         for (i = 0; i < end - pos; i++) {
653                                 if (pos[i])
654                                         break;
655                         }
656                         if (i == end - pos) {
657                                 wpa_printf(MSG_DEBUG, "WPS: Workaround - skip "
658                                            "unexpected message padding");
659                                 break;
660                         }
661                 }
662 #endif /* WPS_WORKAROUNDS */
663
664                 if (wps_set_attr(attr, type, pos, len) < 0)
665                         return -1;
666
667 #ifdef WPS_WORKAROUNDS
668                 prev_type = type;
669 #endif /* WPS_WORKAROUNDS */
670                 pos += len;
671         }
672
673         return 0;
674 }