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