wps_attr_parse.c revision 337817
1117395Skan/* 2132718Skan * Wi-Fi Protected Setup - attribute parsing 3117395Skan * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 4132718Skan * 5117395Skan * This software may be distributed under the terms of the BSD license. 6117395Skan * See README for more details. 7117395Skan */ 8117395Skan 9117395Skan#include "includes.h" 10117395Skan 11117395Skan#include "common.h" 12117395Skan#include "wps_defs.h" 13117395Skan#include "wps_attr_parse.h" 14117395Skan 15117395Skan#ifndef CONFIG_WPS_STRICT 16117395Skan#define WPS_WORKAROUNDS 17117395Skan#endif /* CONFIG_WPS_STRICT */ 18117395Skan 19117395Skan 20117395Skanstatic int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr, 21117395Skan u8 id, u8 len, const u8 *pos) 22117395Skan{ 23169689Skan wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u", 24169689Skan id, len); 25117395Skan switch (id) { 26117395Skan case WFA_ELEM_VERSION2: 27117395Skan if (len != 1) { 28117395Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length " 29117395Skan "%u", len); 30117395Skan return -1; 31117395Skan } 32117395Skan attr->version2 = pos; 33117395Skan break; 34146895Skan case WFA_ELEM_AUTHORIZEDMACS: 35117395Skan attr->authorized_macs = pos; 36119256Skan attr->authorized_macs_len = len; 37117395Skan break; 38146895Skan case WFA_ELEM_NETWORK_KEY_SHAREABLE: 39146895Skan if (len != 1) { 40117395Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key " 41117395Skan "Shareable length %u", len); 42117395Skan return -1; 43117395Skan } 44117395Skan attr->network_key_shareable = pos; 45117395Skan break; 46117395Skan case WFA_ELEM_REQUEST_TO_ENROLL: 47117395Skan if (len != 1) { 48117395Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll " 49117395Skan "length %u", len); 50117395Skan return -1; 51117395Skan } 52117395Skan attr->request_to_enroll = pos; 53117395Skan break; 54117395Skan case WFA_ELEM_SETTINGS_DELAY_TIME: 55117395Skan if (len != 1) { 56117395Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay " 57117395Skan "Time length %u", len); 58117395Skan return -1; 59117395Skan } 60117395Skan attr->settings_delay_time = pos; 61117395Skan break; 62117395Skan case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS: 63117395Skan if (len != 2) { 64117395Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u", 65117395Skan len); 66146895Skan return -1; 67146895Skan } 68146895Skan attr->registrar_configuration_methods = pos; 69117395Skan break; 70117395Skan default: 71117395Skan wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor " 72117395Skan "Extension subelement %u", id); 73117395Skan break; 74117395Skan } 75117395Skan 76117395Skan return 0; 77117395Skan} 78117395Skan 79117395Skan 80117395Skanstatic int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos, 81117395Skan u16 len) 82117395Skan{ 83117395Skan const u8 *end = pos + len; 84117395Skan u8 id, elen; 85117395Skan 86117395Skan while (end - pos >= 2) { 87117395Skan id = *pos++; 88117395Skan elen = *pos++; 89117395Skan if (elen > end - pos) 90117395Skan break; 91117395Skan if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0) 92117395Skan return -1; 93117395Skan pos += elen; 94117395Skan } 95117395Skan 96117395Skan return 0; 97117395Skan} 98117395Skan 99117395Skan 100117395Skanstatic int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos, 101117395Skan u16 len) 102117395Skan{ 103117395Skan u32 vendor_id; 104117395Skan 105117395Skan if (len < 3) { 106117395Skan wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension"); 107117395Skan return 0; 108117395Skan } 109117395Skan 110117395Skan vendor_id = WPA_GET_BE24(pos); 111117395Skan switch (vendor_id) { 112117395Skan case WPS_VENDOR_ID_WFA: 113117395Skan return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3); 114117395Skan } 115117395Skan 116117395Skan /* Handle unknown vendor extensions */ 117117395Skan 118117395Skan wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)", 119117395Skan vendor_id); 120117395Skan 121117395Skan if (len > WPS_MAX_VENDOR_EXT_LEN) { 122117395Skan wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)", 123117395Skan len); 124117395Skan return -1; 125117395Skan } 126117395Skan 127117395Skan if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) { 128117395Skan wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension " 129117395Skan "attribute (max %d vendor extensions)", 130117395Skan MAX_WPS_PARSE_VENDOR_EXT); 131117395Skan return -1; 132117395Skan } 133117395Skan attr->vendor_ext[attr->num_vendor_ext] = pos; 134117395Skan attr->vendor_ext_len[attr->num_vendor_ext] = len; 135117395Skan attr->num_vendor_ext++; 136117395Skan 137117395Skan return 0; 138117395Skan} 139117395Skan 140117395Skan 141117395Skanstatic int wps_set_attr(struct wps_parse_attr *attr, u16 type, 142117395Skan const u8 *pos, u16 len) 143117395Skan{ 144117395Skan switch (type) { 145117395Skan case ATTR_VERSION: 146117395Skan if (len != 1) { 147117395Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", 148117395Skan len); 149146895Skan return -1; 150146895Skan } 151117395Skan attr->version = pos; 152117395Skan break; 153117395Skan case ATTR_MSG_TYPE: 154117395Skan if (len != 1) { 155117395Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " 156146895Skan "length %u", len); 157146895Skan return -1; 158117395Skan } 159117395Skan attr->msg_type = pos; 160146895Skan break; 161146895Skan case ATTR_ENROLLEE_NONCE: 162146895Skan if (len != WPS_NONCE_LEN) { 163146895Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " 164146895Skan "length %u", len); 165146895Skan return -1; 166117395Skan } 167117395Skan attr->enrollee_nonce = pos; 168117395Skan break; 169117395Skan case ATTR_REGISTRAR_NONCE: 170117395Skan if (len != WPS_NONCE_LEN) { 171146895Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " 172117395Skan "length %u", len); 173117395Skan return -1; 174117395Skan } 175117395Skan attr->registrar_nonce = pos; 176117395Skan break; 177117395Skan case ATTR_UUID_E: 178117395Skan if (len != WPS_UUID_LEN) { 179117395Skan wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", 180146895Skan len); 181146895Skan return -1; 182146895Skan } 183146895Skan attr->uuid_e = pos; 184117395Skan break; 185169689Skan case ATTR_UUID_R: 186169689Skan if (len != WPS_UUID_LEN) { 187169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", 188169689Skan len); 189169689Skan return -1; 190169689Skan } 191169689Skan attr->uuid_r = pos; 192169689Skan break; 193169689Skan case ATTR_AUTH_TYPE_FLAGS: 194169689Skan if (len != 2) { 195169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " 196169689Skan "Type Flags length %u", len); 197169689Skan return -1; 198169689Skan } 199169689Skan attr->auth_type_flags = pos; 200169689Skan break; 201169689Skan case ATTR_ENCR_TYPE_FLAGS: 202169689Skan if (len != 2) { 203169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " 204169689Skan "Flags length %u", len); 205169689Skan return -1; 206169689Skan } 207169689Skan attr->encr_type_flags = pos; 208169689Skan break; 209169689Skan case ATTR_CONN_TYPE_FLAGS: 210169689Skan if (len != 1) { 211169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " 212169689Skan "Flags length %u", len); 213169689Skan return -1; 214169689Skan } 215169689Skan attr->conn_type_flags = pos; 216169689Skan break; 217169689Skan case ATTR_CONFIG_METHODS: 218169689Skan if (len != 2) { 219169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " 220169689Skan "length %u", len); 221169689Skan return -1; 222169689Skan } 223169689Skan attr->config_methods = pos; 224169689Skan break; 225169689Skan case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: 226169689Skan if (len != 2) { 227169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " 228169689Skan "Registrar Config Methods length %u", len); 229169689Skan return -1; 230169689Skan } 231169689Skan attr->sel_reg_config_methods = pos; 232169689Skan break; 233169689Skan case ATTR_PRIMARY_DEV_TYPE: 234169689Skan if (len != WPS_DEV_TYPE_LEN) { 235169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " 236169689Skan "Type length %u", len); 237169689Skan return -1; 238169689Skan } 239169689Skan attr->primary_dev_type = pos; 240169689Skan break; 241169689Skan case ATTR_RF_BANDS: 242169689Skan if (len != 1) { 243169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " 244169689Skan "%u", len); 245169689Skan return -1; 246169689Skan } 247169689Skan attr->rf_bands = pos; 248169689Skan break; 249169689Skan case ATTR_ASSOC_STATE: 250169689Skan if (len != 2) { 251169689Skan wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " 252169689Skan "length %u", len); 253169689Skan return -1; 254169689Skan } 255 attr->assoc_state = pos; 256 break; 257 case ATTR_CONFIG_ERROR: 258 if (len != 2) { 259 wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " 260 "Error length %u", len); 261 return -1; 262 } 263 attr->config_error = pos; 264 break; 265 case ATTR_DEV_PASSWORD_ID: 266 if (len != 2) { 267 wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " 268 "ID length %u", len); 269 return -1; 270 } 271 attr->dev_password_id = pos; 272 break; 273 case ATTR_OOB_DEVICE_PASSWORD: 274 if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 || 275 len > WPS_OOB_PUBKEY_HASH_LEN + 2 + 276 WPS_OOB_DEVICE_PASSWORD_LEN || 277 (len < WPS_OOB_PUBKEY_HASH_LEN + 2 + 278 WPS_OOB_DEVICE_PASSWORD_MIN_LEN && 279 WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) != 280 DEV_PW_NFC_CONNECTION_HANDOVER)) { 281 wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " 282 "Password length %u", len); 283 return -1; 284 } 285 attr->oob_dev_password = pos; 286 attr->oob_dev_password_len = len; 287 break; 288 case ATTR_OS_VERSION: 289 if (len != 4) { 290 wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " 291 "%u", len); 292 return -1; 293 } 294 attr->os_version = pos; 295 break; 296 case ATTR_WPS_STATE: 297 if (len != 1) { 298 wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " 299 "Setup State length %u", len); 300 return -1; 301 } 302 attr->wps_state = pos; 303 break; 304 case ATTR_AUTHENTICATOR: 305 if (len != WPS_AUTHENTICATOR_LEN) { 306 wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " 307 "length %u", len); 308 return -1; 309 } 310 attr->authenticator = pos; 311 break; 312 case ATTR_R_HASH1: 313 if (len != WPS_HASH_LEN) { 314 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", 315 len); 316 return -1; 317 } 318 attr->r_hash1 = pos; 319 break; 320 case ATTR_R_HASH2: 321 if (len != WPS_HASH_LEN) { 322 wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", 323 len); 324 return -1; 325 } 326 attr->r_hash2 = pos; 327 break; 328 case ATTR_E_HASH1: 329 if (len != WPS_HASH_LEN) { 330 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", 331 len); 332 return -1; 333 } 334 attr->e_hash1 = pos; 335 break; 336 case ATTR_E_HASH2: 337 if (len != WPS_HASH_LEN) { 338 wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", 339 len); 340 return -1; 341 } 342 attr->e_hash2 = pos; 343 break; 344 case ATTR_R_SNONCE1: 345 if (len != WPS_SECRET_NONCE_LEN) { 346 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " 347 "%u", len); 348 return -1; 349 } 350 attr->r_snonce1 = pos; 351 break; 352 case ATTR_R_SNONCE2: 353 if (len != WPS_SECRET_NONCE_LEN) { 354 wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " 355 "%u", len); 356 return -1; 357 } 358 attr->r_snonce2 = pos; 359 break; 360 case ATTR_E_SNONCE1: 361 if (len != WPS_SECRET_NONCE_LEN) { 362 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " 363 "%u", len); 364 return -1; 365 } 366 attr->e_snonce1 = pos; 367 break; 368 case ATTR_E_SNONCE2: 369 if (len != WPS_SECRET_NONCE_LEN) { 370 wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " 371 "%u", len); 372 return -1; 373 } 374 attr->e_snonce2 = pos; 375 break; 376 case ATTR_KEY_WRAP_AUTH: 377 if (len != WPS_KWA_LEN) { 378 wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " 379 "Authenticator length %u", len); 380 return -1; 381 } 382 attr->key_wrap_auth = pos; 383 break; 384 case ATTR_AUTH_TYPE: 385 if (len != 2) { 386 wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " 387 "Type length %u", len); 388 return -1; 389 } 390 attr->auth_type = pos; 391 break; 392 case ATTR_ENCR_TYPE: 393 if (len != 2) { 394 wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " 395 "Type length %u", len); 396 return -1; 397 } 398 attr->encr_type = pos; 399 break; 400 case ATTR_NETWORK_INDEX: 401 if (len != 1) { 402 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " 403 "length %u", len); 404 return -1; 405 } 406 attr->network_idx = pos; 407 break; 408 case ATTR_NETWORK_KEY_INDEX: 409 if (len != 1) { 410 wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " 411 "length %u", len); 412 return -1; 413 } 414 attr->network_key_idx = pos; 415 break; 416 case ATTR_MAC_ADDR: 417 if (len != ETH_ALEN) { 418 wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " 419 "length %u", len); 420 return -1; 421 } 422 attr->mac_addr = pos; 423 break; 424 case ATTR_SELECTED_REGISTRAR: 425 if (len != 1) { 426 wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" 427 " length %u", len); 428 return -1; 429 } 430 attr->selected_registrar = pos; 431 break; 432 case ATTR_REQUEST_TYPE: 433 if (len != 1) { 434 wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " 435 "length %u", len); 436 return -1; 437 } 438 attr->request_type = pos; 439 break; 440 case ATTR_RESPONSE_TYPE: 441 if (len != 1) { 442 wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " 443 "length %u", len); 444 return -1; 445 } 446 attr->response_type = pos; 447 break; 448 case ATTR_MANUFACTURER: 449 attr->manufacturer = pos; 450 if (len > WPS_MANUFACTURER_MAX_LEN) 451 attr->manufacturer_len = WPS_MANUFACTURER_MAX_LEN; 452 else 453 attr->manufacturer_len = len; 454 break; 455 case ATTR_MODEL_NAME: 456 attr->model_name = pos; 457 if (len > WPS_MODEL_NAME_MAX_LEN) 458 attr->model_name_len = WPS_MODEL_NAME_MAX_LEN; 459 else 460 attr->model_name_len = len; 461 break; 462 case ATTR_MODEL_NUMBER: 463 attr->model_number = pos; 464 if (len > WPS_MODEL_NUMBER_MAX_LEN) 465 attr->model_number_len = WPS_MODEL_NUMBER_MAX_LEN; 466 else 467 attr->model_number_len = len; 468 break; 469 case ATTR_SERIAL_NUMBER: 470 attr->serial_number = pos; 471 if (len > WPS_SERIAL_NUMBER_MAX_LEN) 472 attr->serial_number_len = WPS_SERIAL_NUMBER_MAX_LEN; 473 else 474 attr->serial_number_len = len; 475 break; 476 case ATTR_DEV_NAME: 477 if (len > WPS_DEV_NAME_MAX_LEN) { 478 wpa_printf(MSG_DEBUG, 479 "WPS: Ignore too long Device Name (len=%u)", 480 len); 481 break; 482 } 483 attr->dev_name = pos; 484 attr->dev_name_len = len; 485 break; 486 case ATTR_PUBLIC_KEY: 487 /* 488 * The Public Key attribute is supposed to be exactly 192 bytes 489 * in length. Allow couple of bytes shorter one to try to 490 * interoperate with implementations that do not use proper 491 * zero-padding. 492 */ 493 if (len < 190 || len > 192) { 494 wpa_printf(MSG_DEBUG, 495 "WPS: Ignore Public Key with unexpected length %u", 496 len); 497 break; 498 } 499 attr->public_key = pos; 500 attr->public_key_len = len; 501 break; 502 case ATTR_ENCR_SETTINGS: 503 attr->encr_settings = pos; 504 attr->encr_settings_len = len; 505 break; 506 case ATTR_CRED: 507 if (attr->num_cred >= MAX_CRED_COUNT) { 508 wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " 509 "attribute (max %d credentials)", 510 MAX_CRED_COUNT); 511 break; 512 } 513 attr->cred[attr->num_cred] = pos; 514 attr->cred_len[attr->num_cred] = len; 515 attr->num_cred++; 516 break; 517 case ATTR_SSID: 518 if (len > SSID_MAX_LEN) { 519 wpa_printf(MSG_DEBUG, 520 "WPS: Ignore too long SSID (len=%u)", len); 521 break; 522 } 523 attr->ssid = pos; 524 attr->ssid_len = len; 525 break; 526 case ATTR_NETWORK_KEY: 527 attr->network_key = pos; 528 attr->network_key_len = len; 529 break; 530 case ATTR_AP_SETUP_LOCKED: 531 if (len != 1) { 532 wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " 533 "length %u", len); 534 return -1; 535 } 536 attr->ap_setup_locked = pos; 537 break; 538 case ATTR_REQUESTED_DEV_TYPE: 539 if (len != WPS_DEV_TYPE_LEN) { 540 wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device " 541 "Type length %u", len); 542 return -1; 543 } 544 if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) { 545 wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device " 546 "Type attribute (max %u types)", 547 MAX_REQ_DEV_TYPE_COUNT); 548 break; 549 } 550 attr->req_dev_type[attr->num_req_dev_type] = pos; 551 attr->num_req_dev_type++; 552 break; 553 case ATTR_SECONDARY_DEV_TYPE_LIST: 554 if (len > WPS_SEC_DEV_TYPE_MAX_LEN || 555 (len % WPS_DEV_TYPE_LEN) > 0) { 556 wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device " 557 "Type length %u", len); 558 return -1; 559 } 560 attr->sec_dev_type_list = pos; 561 attr->sec_dev_type_list_len = len; 562 break; 563 case ATTR_VENDOR_EXT: 564 if (wps_parse_vendor_ext(attr, pos, len) < 0) 565 return -1; 566 break; 567 case ATTR_AP_CHANNEL: 568 if (len != 2) { 569 wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel " 570 "length %u", len); 571 return -1; 572 } 573 attr->ap_channel = pos; 574 break; 575 default: 576 wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " 577 "len=%u", type, len); 578 break; 579 } 580 581 return 0; 582} 583 584 585int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) 586{ 587 const u8 *pos, *end; 588 u16 type, len; 589#ifdef WPS_WORKAROUNDS 590 u16 prev_type = 0; 591#endif /* WPS_WORKAROUNDS */ 592 593 os_memset(attr, 0, sizeof(*attr)); 594 pos = wpabuf_head(msg); 595 end = pos + wpabuf_len(msg); 596 597 while (pos < end) { 598 if (end - pos < 4) { 599 wpa_printf(MSG_DEBUG, "WPS: Invalid message - " 600 "%lu bytes remaining", 601 (unsigned long) (end - pos)); 602 return -1; 603 } 604 605 type = WPA_GET_BE16(pos); 606 pos += 2; 607 len = WPA_GET_BE16(pos); 608 pos += 2; 609 wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u", 610 type, len); 611 if (len > end - pos) { 612 wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); 613 wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg); 614#ifdef WPS_WORKAROUNDS 615 /* 616 * Some deployed APs seem to have a bug in encoding of 617 * Network Key attribute in the Credential attribute 618 * where they add an extra octet after the Network Key 619 * attribute at least when open network is being 620 * provisioned. 621 */ 622 if ((type & 0xff00) != 0x1000 && 623 prev_type == ATTR_NETWORK_KEY) { 624 wpa_printf(MSG_DEBUG, "WPS: Workaround - try " 625 "to skip unexpected octet after " 626 "Network Key"); 627 pos -= 3; 628 continue; 629 } 630#endif /* WPS_WORKAROUNDS */ 631 return -1; 632 } 633 634#ifdef WPS_WORKAROUNDS 635 if (type == 0 && len == 0) { 636 /* 637 * Mac OS X 10.6 seems to be adding 0x00 padding to the 638 * end of M1. Skip those to avoid interop issues. 639 */ 640 int i; 641 for (i = 0; i < end - pos; i++) { 642 if (pos[i]) 643 break; 644 } 645 if (i == end - pos) { 646 wpa_printf(MSG_DEBUG, "WPS: Workaround - skip " 647 "unexpected message padding"); 648 break; 649 } 650 } 651#endif /* WPS_WORKAROUNDS */ 652 653 if (wps_set_attr(attr, type, pos, len) < 0) 654 return -1; 655 656#ifdef WPS_WORKAROUNDS 657 prev_type = type; 658#endif /* WPS_WORKAROUNDS */ 659 pos += len; 660 } 661 662 return 0; 663} 664