wps_common.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
1/* 2 * Wi-Fi Protected Setup - common functionality 3 * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi> 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 "includes.h" 16 17#include "common.h" 18#include "crypto/aes_wrap.h" 19#include "crypto/crypto.h" 20#include "crypto/dh_group5.h" 21#include "crypto/sha1.h" 22#include "crypto/sha256.h" 23#include "crypto/random.h" 24#include "wps_i.h" 25 26 27void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, 28 const char *label, u8 *res, size_t res_len) 29{ 30 u8 i_buf[4], key_bits[4]; 31 const u8 *addr[4]; 32 size_t len[4]; 33 int i, iter; 34 u8 hash[SHA256_MAC_LEN], *opos; 35 size_t left; 36 37 WPA_PUT_BE32(key_bits, res_len * 8); 38 39 addr[0] = i_buf; 40 len[0] = sizeof(i_buf); 41 addr[1] = label_prefix; 42 len[1] = label_prefix_len; 43 addr[2] = (const u8 *) label; 44 len[2] = os_strlen(label); 45 addr[3] = key_bits; 46 len[3] = sizeof(key_bits); 47 48 iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; 49 opos = res; 50 left = res_len; 51 52 for (i = 1; i <= iter; i++) { 53 WPA_PUT_BE32(i_buf, i); 54 hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash); 55 if (i < iter) { 56 os_memcpy(opos, hash, SHA256_MAC_LEN); 57 opos += SHA256_MAC_LEN; 58 left -= SHA256_MAC_LEN; 59 } else 60 os_memcpy(opos, hash, left); 61 } 62} 63 64 65int wps_derive_keys(struct wps_data *wps) 66{ 67 struct wpabuf *pubkey, *dh_shared; 68 u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; 69 const u8 *addr[3]; 70 size_t len[3]; 71 u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; 72 73 if (wps->dh_privkey == NULL) { 74 wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); 75 return -1; 76 } 77 78 pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; 79 if (pubkey == NULL) { 80 wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); 81 return -1; 82 } 83 84 wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); 85 wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey); 86 dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); 87 dh5_free(wps->dh_ctx); 88 wps->dh_ctx = NULL; 89 dh_shared = wpabuf_zeropad(dh_shared, 192); 90 if (dh_shared == NULL) { 91 wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); 92 return -1; 93 } 94 95 /* Own DH private key is not needed anymore */ 96 wpabuf_free(wps->dh_privkey); 97 wps->dh_privkey = NULL; 98 99 wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); 100 101 /* DHKey = SHA-256(g^AB mod p) */ 102 addr[0] = wpabuf_head(dh_shared); 103 len[0] = wpabuf_len(dh_shared); 104 sha256_vector(1, addr, len, dhkey); 105 wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); 106 wpabuf_free(dh_shared); 107 108 /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ 109 addr[0] = wps->nonce_e; 110 len[0] = WPS_NONCE_LEN; 111 addr[1] = wps->mac_addr_e; 112 len[1] = ETH_ALEN; 113 addr[2] = wps->nonce_r; 114 len[2] = WPS_NONCE_LEN; 115 hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk); 116 wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); 117 118 wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", 119 keys, sizeof(keys)); 120 os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); 121 os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); 122 os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, 123 WPS_EMSK_LEN); 124 125 wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", 126 wps->authkey, WPS_AUTHKEY_LEN); 127 wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", 128 wps->keywrapkey, WPS_KEYWRAPKEY_LEN); 129 wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); 130 131 return 0; 132} 133 134 135void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, 136 size_t dev_passwd_len) 137{ 138 u8 hash[SHA256_MAC_LEN]; 139 140 hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, 141 (dev_passwd_len + 1) / 2, hash); 142 os_memcpy(wps->psk1, hash, WPS_PSK_LEN); 143 hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, 144 dev_passwd + (dev_passwd_len + 1) / 2, 145 dev_passwd_len / 2, hash); 146 os_memcpy(wps->psk2, hash, WPS_PSK_LEN); 147 148 wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", 149 dev_passwd, dev_passwd_len); 150 wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); 151 wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); 152} 153 154 155struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, 156 size_t encr_len) 157{ 158 struct wpabuf *decrypted; 159 const size_t block_size = 16; 160 size_t i; 161 u8 pad; 162 const u8 *pos; 163 164 /* AES-128-CBC */ 165 if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) 166 { 167 wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); 168 return NULL; 169 } 170 171 decrypted = wpabuf_alloc(encr_len - block_size); 172 if (decrypted == NULL) 173 return NULL; 174 175 wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); 176 wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); 177 if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), 178 wpabuf_len(decrypted))) { 179 wpabuf_free(decrypted); 180 return NULL; 181 } 182 183 wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", 184 decrypted); 185 186 pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; 187 pad = *pos; 188 if (pad > wpabuf_len(decrypted)) { 189 wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); 190 wpabuf_free(decrypted); 191 return NULL; 192 } 193 for (i = 0; i < pad; i++) { 194 if (*pos-- != pad) { 195 wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " 196 "string"); 197 wpabuf_free(decrypted); 198 return NULL; 199 } 200 } 201 decrypted->used -= pad; 202 203 return decrypted; 204} 205 206 207/** 208 * wps_pin_checksum - Compute PIN checksum 209 * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) 210 * Returns: Checksum digit 211 */ 212unsigned int wps_pin_checksum(unsigned int pin) 213{ 214 unsigned int accum = 0; 215 while (pin) { 216 accum += 3 * (pin % 10); 217 pin /= 10; 218 accum += pin % 10; 219 pin /= 10; 220 } 221 222 return (10 - accum % 10) % 10; 223} 224 225 226/** 227 * wps_pin_valid - Check whether a PIN has a valid checksum 228 * @pin: Eight digit PIN (i.e., including the checksum digit) 229 * Returns: 1 if checksum digit is valid, or 0 if not 230 */ 231unsigned int wps_pin_valid(unsigned int pin) 232{ 233 return wps_pin_checksum(pin / 10) == (pin % 10); 234} 235 236 237/** 238 * wps_generate_pin - Generate a random PIN 239 * Returns: Eight digit PIN (i.e., including the checksum digit) 240 */ 241unsigned int wps_generate_pin(void) 242{ 243 unsigned int val; 244 245 /* Generate seven random digits for the PIN */ 246 if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) { 247 struct os_time now; 248 os_get_time(&now); 249 val = os_random() ^ now.sec ^ now.usec; 250 } 251 val %= 10000000; 252 253 /* Append checksum digit */ 254 return val * 10 + wps_pin_checksum(val); 255} 256 257 258void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, 259 u16 config_error, u16 error_indication) 260{ 261 union wps_event_data data; 262 263 if (wps->event_cb == NULL) 264 return; 265 266 os_memset(&data, 0, sizeof(data)); 267 data.fail.msg = msg; 268 data.fail.config_error = config_error; 269 data.fail.error_indication = error_indication; 270 wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); 271} 272 273 274void wps_success_event(struct wps_context *wps) 275{ 276 if (wps->event_cb == NULL) 277 return; 278 279 wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL); 280} 281 282 283void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part) 284{ 285 union wps_event_data data; 286 287 if (wps->event_cb == NULL) 288 return; 289 290 os_memset(&data, 0, sizeof(data)); 291 data.pwd_auth_fail.enrollee = enrollee; 292 data.pwd_auth_fail.part = part; 293 wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); 294} 295 296 297void wps_pbc_overlap_event(struct wps_context *wps) 298{ 299 if (wps->event_cb == NULL) 300 return; 301 302 wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); 303} 304 305 306void wps_pbc_timeout_event(struct wps_context *wps) 307{ 308 if (wps->event_cb == NULL) 309 return; 310 311 wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); 312} 313 314 315#ifdef CONFIG_WPS_OOB 316 317static struct wpabuf * wps_get_oob_cred(struct wps_context *wps) 318{ 319 struct wps_data data; 320 struct wpabuf *plain; 321 322 plain = wpabuf_alloc(500); 323 if (plain == NULL) { 324 wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 325 "credential"); 326 return NULL; 327 } 328 329 os_memset(&data, 0, sizeof(data)); 330 data.wps = wps; 331 data.auth_type = wps->auth_types; 332 data.encr_type = wps->encr_types; 333 if (wps_build_version(plain) || 334 wps_build_cred(&data, plain) || 335 wps_build_wfa_ext(plain, 0, NULL, 0)) { 336 wpabuf_free(plain); 337 return NULL; 338 } 339 340 return plain; 341} 342 343 344static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps) 345{ 346 struct wpabuf *data; 347 348 data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); 349 if (data == NULL) { 350 wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 351 "device password attribute"); 352 return NULL; 353 } 354 355 wpabuf_free(wps->oob_conf.dev_password); 356 wps->oob_conf.dev_password = 357 wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); 358 if (wps->oob_conf.dev_password == NULL) { 359 wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 360 "device password"); 361 wpabuf_free(data); 362 return NULL; 363 } 364 365 if (wps_build_version(data) || 366 wps_build_oob_dev_password(data, wps) || 367 wps_build_wfa_ext(data, 0, NULL, 0)) { 368 wpa_printf(MSG_ERROR, "WPS: Build OOB device password " 369 "attribute error"); 370 wpabuf_free(data); 371 return NULL; 372 } 373 374 return data; 375} 376 377 378static int wps_parse_oob_dev_pwd(struct wps_context *wps, 379 struct wpabuf *data) 380{ 381 struct oob_conf_data *oob_conf = &wps->oob_conf; 382 struct wps_parse_attr attr; 383 const u8 *pos; 384 385 if (wps_parse_msg(data, &attr) < 0 || 386 attr.oob_dev_password == NULL) { 387 wpa_printf(MSG_ERROR, "WPS: OOB device password not found"); 388 return -1; 389 } 390 391 pos = attr.oob_dev_password; 392 393 oob_conf->pubkey_hash = 394 wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN); 395 if (oob_conf->pubkey_hash == NULL) { 396 wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 397 "public key hash"); 398 return -1; 399 } 400 pos += WPS_OOB_PUBKEY_HASH_LEN; 401 402 wps->oob_dev_pw_id = WPA_GET_BE16(pos); 403 pos += sizeof(wps->oob_dev_pw_id); 404 405 oob_conf->dev_password = 406 wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); 407 if (oob_conf->dev_password == NULL) { 408 wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " 409 "device password"); 410 return -1; 411 } 412 wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password, 413 wpabuf_size(oob_conf->dev_password)), 414 wpabuf_size(oob_conf->dev_password), pos, 415 WPS_OOB_DEVICE_PASSWORD_LEN); 416 417 return 0; 418} 419 420 421static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data) 422{ 423 struct wpabuf msg; 424 struct wps_parse_attr attr; 425 size_t i; 426 427 if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) { 428 wpa_printf(MSG_ERROR, "WPS: OOB credential not found"); 429 return -1; 430 } 431 432 for (i = 0; i < attr.num_cred; i++) { 433 struct wps_credential local_cred; 434 struct wps_parse_attr cattr; 435 436 os_memset(&local_cred, 0, sizeof(local_cred)); 437 wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]); 438 if (wps_parse_msg(&msg, &cattr) < 0 || 439 wps_process_cred(&cattr, &local_cred)) { 440 wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " 441 "credential"); 442 return -1; 443 } 444 wps->cred_cb(wps->cb_ctx, &local_cred); 445 } 446 447 return 0; 448} 449 450 451int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev, 452 int registrar) 453{ 454 struct wpabuf *data; 455 int ret, write_f, oob_method = wps->oob_conf.oob_method; 456 void *oob_priv; 457 458 write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar; 459 460 oob_priv = oob_dev->init_func(wps, oob_dev, registrar); 461 if (oob_priv == NULL) { 462 wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device"); 463 return -1; 464 } 465 466 if (write_f) { 467 if (oob_method == OOB_METHOD_CRED) 468 data = wps_get_oob_cred(wps); 469 else 470 data = wps_get_oob_dev_pwd(wps); 471 472 ret = 0; 473 if (data == NULL || oob_dev->write_func(oob_priv, data) < 0) 474 ret = -1; 475 } else { 476 data = oob_dev->read_func(oob_priv); 477 if (data == NULL) 478 ret = -1; 479 else { 480 if (oob_method == OOB_METHOD_CRED) 481 ret = wps_parse_oob_cred(wps, data); 482 else 483 ret = wps_parse_oob_dev_pwd(wps, data); 484 } 485 } 486 wpabuf_free(data); 487 oob_dev->deinit_func(oob_priv); 488 489 if (ret < 0) { 490 wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data"); 491 return -1; 492 } 493 494 return 0; 495} 496 497 498struct oob_device_data * wps_get_oob_device(char *device_type) 499{ 500#ifdef CONFIG_WPS_UFD 501 if (os_strstr(device_type, "ufd") != NULL) 502 return &oob_ufd_device_data; 503#endif /* CONFIG_WPS_UFD */ 504#ifdef CONFIG_WPS_NFC 505 if (os_strstr(device_type, "nfc") != NULL) 506 return &oob_nfc_device_data; 507#endif /* CONFIG_WPS_NFC */ 508 509 return NULL; 510} 511 512 513#ifdef CONFIG_WPS_NFC 514struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name) 515{ 516 if (device_name == NULL) 517 return NULL; 518#ifdef CONFIG_WPS_NFC_PN531 519 if (os_strstr(device_name, "pn531") != NULL) 520 return &oob_nfc_pn531_device_data; 521#endif /* CONFIG_WPS_NFC_PN531 */ 522 523 return NULL; 524} 525#endif /* CONFIG_WPS_NFC */ 526 527 528int wps_get_oob_method(char *method) 529{ 530 if (os_strstr(method, "pin-e") != NULL) 531 return OOB_METHOD_DEV_PWD_E; 532 if (os_strstr(method, "pin-r") != NULL) 533 return OOB_METHOD_DEV_PWD_R; 534 if (os_strstr(method, "cred") != NULL) 535 return OOB_METHOD_CRED; 536 return OOB_METHOD_UNKNOWN; 537} 538 539#endif /* CONFIG_WPS_OOB */ 540 541 542int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) 543{ 544 const char *pos; 545 546 /* <categ>-<OUI>-<subcateg> */ 547 WPA_PUT_BE16(dev_type, atoi(str)); 548 pos = os_strchr(str, '-'); 549 if (pos == NULL) 550 return -1; 551 pos++; 552 if (hexstr2bin(pos, &dev_type[2], 4)) 553 return -1; 554 pos = os_strchr(pos, '-'); 555 if (pos == NULL) 556 return -1; 557 pos++; 558 WPA_PUT_BE16(&dev_type[6], atoi(pos)); 559 560 561 return 0; 562} 563 564 565char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, 566 size_t buf_len) 567{ 568 int ret; 569 570 ret = os_snprintf(buf, buf_len, "%u-%08X-%u", 571 WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), 572 WPA_GET_BE16(&dev_type[6])); 573 if (ret < 0 || (unsigned int) ret >= buf_len) 574 return NULL; 575 576 return buf; 577} 578 579 580void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) 581{ 582 const u8 *addr[2]; 583 size_t len[2]; 584 u8 hash[SHA1_MAC_LEN]; 585 u8 nsid[16] = { 586 0x52, 0x64, 0x80, 0xf8, 587 0xc9, 0x9b, 588 0x4b, 0xe5, 589 0xa6, 0x55, 590 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 591 }; 592 593 addr[0] = nsid; 594 len[0] = sizeof(nsid); 595 addr[1] = mac_addr; 596 len[1] = 6; 597 sha1_vector(2, addr, len, hash); 598 os_memcpy(uuid, hash, 16); 599 600 /* Version: 5 = named-based version using SHA-1 */ 601 uuid[6] = (5 << 4) | (uuid[6] & 0x0f); 602 603 /* Variant specified in RFC 4122 */ 604 uuid[8] = 0x80 | (uuid[8] & 0x3f); 605} 606 607 608u16 wps_config_methods_str2bin(const char *str) 609{ 610 u16 methods = 0; 611 612 if (str == NULL) { 613 /* Default to enabling methods based on build configuration */ 614 methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 615#ifdef CONFIG_WPS2 616 methods |= WPS_CONFIG_VIRT_DISPLAY; 617#endif /* CONFIG_WPS2 */ 618#ifdef CONFIG_WPS_UFD 619 methods |= WPS_CONFIG_USBA; 620#endif /* CONFIG_WPS_UFD */ 621#ifdef CONFIG_WPS_NFC 622 methods |= WPS_CONFIG_NFC_INTERFACE; 623#endif /* CONFIG_WPS_NFC */ 624 } else { 625 if (os_strstr(str, "usba")) 626 methods |= WPS_CONFIG_USBA; 627 if (os_strstr(str, "ethernet")) 628 methods |= WPS_CONFIG_ETHERNET; 629 if (os_strstr(str, "label")) 630 methods |= WPS_CONFIG_LABEL; 631 if (os_strstr(str, "display")) 632 methods |= WPS_CONFIG_DISPLAY; 633 if (os_strstr(str, "ext_nfc_token")) 634 methods |= WPS_CONFIG_EXT_NFC_TOKEN; 635 if (os_strstr(str, "int_nfc_token")) 636 methods |= WPS_CONFIG_INT_NFC_TOKEN; 637 if (os_strstr(str, "nfc_interface")) 638 methods |= WPS_CONFIG_NFC_INTERFACE; 639 if (os_strstr(str, "push_button")) 640 methods |= WPS_CONFIG_PUSHBUTTON; 641 if (os_strstr(str, "keypad")) 642 methods |= WPS_CONFIG_KEYPAD; 643#ifdef CONFIG_WPS2 644 if (os_strstr(str, "virtual_display")) 645 methods |= WPS_CONFIG_VIRT_DISPLAY; 646 if (os_strstr(str, "physical_display")) 647 methods |= WPS_CONFIG_PHY_DISPLAY; 648 if (os_strstr(str, "virtual_push_button")) 649 methods |= WPS_CONFIG_VIRT_PUSHBUTTON; 650 if (os_strstr(str, "physical_push_button")) 651 methods |= WPS_CONFIG_PHY_PUSHBUTTON; 652#endif /* CONFIG_WPS2 */ 653 } 654 655 return methods; 656} 657 658 659struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) 660{ 661 struct wpabuf *msg; 662 663 wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); 664 665 msg = wpabuf_alloc(1000); 666 if (msg == NULL) 667 return NULL; 668 669 if (wps_build_version(msg) || 670 wps_build_msg_type(msg, WPS_WSC_ACK) || 671 wps_build_enrollee_nonce(wps, msg) || 672 wps_build_registrar_nonce(wps, msg) || 673 wps_build_wfa_ext(msg, 0, NULL, 0)) { 674 wpabuf_free(msg); 675 return NULL; 676 } 677 678 return msg; 679} 680 681 682struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) 683{ 684 struct wpabuf *msg; 685 686 wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); 687 688 msg = wpabuf_alloc(1000); 689 if (msg == NULL) 690 return NULL; 691 692 if (wps_build_version(msg) || 693 wps_build_msg_type(msg, WPS_WSC_NACK) || 694 wps_build_enrollee_nonce(wps, msg) || 695 wps_build_registrar_nonce(wps, msg) || 696 wps_build_config_error(msg, wps->config_error) || 697 wps_build_wfa_ext(msg, 0, NULL, 0)) { 698 wpabuf_free(msg); 699 return NULL; 700 } 701 702 return msg; 703} 704