139beb93cSSam Leffler /* 239beb93cSSam Leffler * Wi-Fi Protected Setup - Enrollee 339beb93cSSam Leffler * Copyright (c) 2008, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler 1739beb93cSSam Leffler #include "common.h" 1839beb93cSSam Leffler #include "sha256.h" 1939beb93cSSam Leffler #include "wps_i.h" 2039beb93cSSam Leffler #include "wps_dev_attr.h" 2139beb93cSSam Leffler 2239beb93cSSam Leffler 2339beb93cSSam Leffler static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg) 2439beb93cSSam Leffler { 2539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * MAC Address"); 2639beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_MAC_ADDR); 2739beb93cSSam Leffler wpabuf_put_be16(msg, ETH_ALEN); 2839beb93cSSam Leffler wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN); 2939beb93cSSam Leffler return 0; 3039beb93cSSam Leffler } 3139beb93cSSam Leffler 3239beb93cSSam Leffler 3339beb93cSSam Leffler static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg) 3439beb93cSSam Leffler { 3539beb93cSSam Leffler u8 state; 3639beb93cSSam Leffler if (wps->wps->ap) 3739beb93cSSam Leffler state = wps->wps->wps_state; 3839beb93cSSam Leffler else 3939beb93cSSam Leffler state = WPS_STATE_NOT_CONFIGURED; 4039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", 4139beb93cSSam Leffler state); 4239beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_WPS_STATE); 4339beb93cSSam Leffler wpabuf_put_be16(msg, 1); 4439beb93cSSam Leffler wpabuf_put_u8(msg, WPS_STATE_NOT_CONFIGURED); 4539beb93cSSam Leffler return 0; 4639beb93cSSam Leffler } 4739beb93cSSam Leffler 4839beb93cSSam Leffler 4939beb93cSSam Leffler static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg) 5039beb93cSSam Leffler { 5139beb93cSSam Leffler u8 *hash; 5239beb93cSSam Leffler const u8 *addr[4]; 5339beb93cSSam Leffler size_t len[4]; 5439beb93cSSam Leffler 5539beb93cSSam Leffler if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) 5639beb93cSSam Leffler return -1; 5739beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN); 5839beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: E-S2", 5939beb93cSSam Leffler wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); 6039beb93cSSam Leffler 6139beb93cSSam Leffler if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { 6239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " 6339beb93cSSam Leffler "E-Hash derivation"); 6439beb93cSSam Leffler return -1; 6539beb93cSSam Leffler } 6639beb93cSSam Leffler 6739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * E-Hash1"); 6839beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_E_HASH1); 6939beb93cSSam Leffler wpabuf_put_be16(msg, SHA256_MAC_LEN); 7039beb93cSSam Leffler hash = wpabuf_put(msg, SHA256_MAC_LEN); 7139beb93cSSam Leffler /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ 7239beb93cSSam Leffler addr[0] = wps->snonce; 7339beb93cSSam Leffler len[0] = WPS_SECRET_NONCE_LEN; 7439beb93cSSam Leffler addr[1] = wps->psk1; 7539beb93cSSam Leffler len[1] = WPS_PSK_LEN; 7639beb93cSSam Leffler addr[2] = wpabuf_head(wps->dh_pubkey_e); 7739beb93cSSam Leffler len[2] = wpabuf_len(wps->dh_pubkey_e); 7839beb93cSSam Leffler addr[3] = wpabuf_head(wps->dh_pubkey_r); 7939beb93cSSam Leffler len[3] = wpabuf_len(wps->dh_pubkey_r); 8039beb93cSSam Leffler hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); 8139beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN); 8239beb93cSSam Leffler 8339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * E-Hash2"); 8439beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_E_HASH2); 8539beb93cSSam Leffler wpabuf_put_be16(msg, SHA256_MAC_LEN); 8639beb93cSSam Leffler hash = wpabuf_put(msg, SHA256_MAC_LEN); 8739beb93cSSam Leffler /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ 8839beb93cSSam Leffler addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; 8939beb93cSSam Leffler addr[1] = wps->psk2; 9039beb93cSSam Leffler hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); 9139beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN); 9239beb93cSSam Leffler 9339beb93cSSam Leffler return 0; 9439beb93cSSam Leffler } 9539beb93cSSam Leffler 9639beb93cSSam Leffler 9739beb93cSSam Leffler static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg) 9839beb93cSSam Leffler { 9939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1"); 10039beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_E_SNONCE1); 10139beb93cSSam Leffler wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); 10239beb93cSSam Leffler wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); 10339beb93cSSam Leffler return 0; 10439beb93cSSam Leffler } 10539beb93cSSam Leffler 10639beb93cSSam Leffler 10739beb93cSSam Leffler static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg) 10839beb93cSSam Leffler { 10939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2"); 11039beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_E_SNONCE2); 11139beb93cSSam Leffler wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); 11239beb93cSSam Leffler wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, 11339beb93cSSam Leffler WPS_SECRET_NONCE_LEN); 11439beb93cSSam Leffler return 0; 11539beb93cSSam Leffler } 11639beb93cSSam Leffler 11739beb93cSSam Leffler 11839beb93cSSam Leffler static struct wpabuf * wps_build_m1(struct wps_data *wps) 11939beb93cSSam Leffler { 12039beb93cSSam Leffler struct wpabuf *msg; 12139beb93cSSam Leffler u16 methods; 12239beb93cSSam Leffler 12339beb93cSSam Leffler if (os_get_random(wps->nonce_e, WPS_NONCE_LEN) < 0) 12439beb93cSSam Leffler return NULL; 12539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", 12639beb93cSSam Leffler wps->nonce_e, WPS_NONCE_LEN); 12739beb93cSSam Leffler 12839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); 12939beb93cSSam Leffler msg = wpabuf_alloc(1000); 13039beb93cSSam Leffler if (msg == NULL) 13139beb93cSSam Leffler return NULL; 13239beb93cSSam Leffler 13339beb93cSSam Leffler methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; 13439beb93cSSam Leffler if (wps->pbc) 13539beb93cSSam Leffler methods |= WPS_CONFIG_PUSHBUTTON; 13639beb93cSSam Leffler 13739beb93cSSam Leffler if (wps_build_version(msg) || 13839beb93cSSam Leffler wps_build_msg_type(msg, WPS_M1) || 13939beb93cSSam Leffler wps_build_uuid_e(msg, wps->uuid_e) || 14039beb93cSSam Leffler wps_build_mac_addr(wps, msg) || 14139beb93cSSam Leffler wps_build_enrollee_nonce(wps, msg) || 14239beb93cSSam Leffler wps_build_public_key(wps, msg) || 14339beb93cSSam Leffler wps_build_auth_type_flags(wps, msg) || 14439beb93cSSam Leffler wps_build_encr_type_flags(wps, msg) || 14539beb93cSSam Leffler wps_build_conn_type_flags(wps, msg) || 14639beb93cSSam Leffler wps_build_config_methods(msg, methods) || 14739beb93cSSam Leffler wps_build_wps_state(wps, msg) || 14839beb93cSSam Leffler wps_build_device_attrs(&wps->wps->dev, msg) || 14939beb93cSSam Leffler wps_build_rf_bands(&wps->wps->dev, msg) || 15039beb93cSSam Leffler wps_build_assoc_state(wps, msg) || 15139beb93cSSam Leffler wps_build_dev_password_id(msg, wps->dev_pw_id) || 15239beb93cSSam Leffler wps_build_config_error(msg, WPS_CFG_NO_ERROR) || 15339beb93cSSam Leffler wps_build_os_version(&wps->wps->dev, msg)) { 15439beb93cSSam Leffler wpabuf_free(msg); 15539beb93cSSam Leffler return NULL; 15639beb93cSSam Leffler } 15739beb93cSSam Leffler 15839beb93cSSam Leffler wps->state = RECV_M2; 15939beb93cSSam Leffler return msg; 16039beb93cSSam Leffler } 16139beb93cSSam Leffler 16239beb93cSSam Leffler 16339beb93cSSam Leffler static struct wpabuf * wps_build_m3(struct wps_data *wps) 16439beb93cSSam Leffler { 16539beb93cSSam Leffler struct wpabuf *msg; 16639beb93cSSam Leffler 16739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); 16839beb93cSSam Leffler 16939beb93cSSam Leffler if (wps->dev_password == NULL) { 17039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); 17139beb93cSSam Leffler return NULL; 17239beb93cSSam Leffler } 17339beb93cSSam Leffler wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); 17439beb93cSSam Leffler 17539beb93cSSam Leffler msg = wpabuf_alloc(1000); 17639beb93cSSam Leffler if (msg == NULL) 17739beb93cSSam Leffler return NULL; 17839beb93cSSam Leffler 17939beb93cSSam Leffler if (wps_build_version(msg) || 18039beb93cSSam Leffler wps_build_msg_type(msg, WPS_M3) || 18139beb93cSSam Leffler wps_build_registrar_nonce(wps, msg) || 18239beb93cSSam Leffler wps_build_e_hash(wps, msg) || 18339beb93cSSam Leffler wps_build_authenticator(wps, msg)) { 18439beb93cSSam Leffler wpabuf_free(msg); 18539beb93cSSam Leffler return NULL; 18639beb93cSSam Leffler } 18739beb93cSSam Leffler 18839beb93cSSam Leffler wps->state = RECV_M4; 18939beb93cSSam Leffler return msg; 19039beb93cSSam Leffler } 19139beb93cSSam Leffler 19239beb93cSSam Leffler 19339beb93cSSam Leffler static struct wpabuf * wps_build_m5(struct wps_data *wps) 19439beb93cSSam Leffler { 19539beb93cSSam Leffler struct wpabuf *msg, *plain; 19639beb93cSSam Leffler 19739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); 19839beb93cSSam Leffler 19939beb93cSSam Leffler plain = wpabuf_alloc(200); 20039beb93cSSam Leffler if (plain == NULL) 20139beb93cSSam Leffler return NULL; 20239beb93cSSam Leffler 20339beb93cSSam Leffler msg = wpabuf_alloc(1000); 20439beb93cSSam Leffler if (msg == NULL) { 20539beb93cSSam Leffler wpabuf_free(plain); 20639beb93cSSam Leffler return NULL; 20739beb93cSSam Leffler } 20839beb93cSSam Leffler 20939beb93cSSam Leffler if (wps_build_version(msg) || 21039beb93cSSam Leffler wps_build_msg_type(msg, WPS_M5) || 21139beb93cSSam Leffler wps_build_registrar_nonce(wps, msg) || 21239beb93cSSam Leffler wps_build_e_snonce1(wps, plain) || 21339beb93cSSam Leffler wps_build_key_wrap_auth(wps, plain) || 21439beb93cSSam Leffler wps_build_encr_settings(wps, msg, plain) || 21539beb93cSSam Leffler wps_build_authenticator(wps, msg)) { 21639beb93cSSam Leffler wpabuf_free(plain); 21739beb93cSSam Leffler wpabuf_free(msg); 21839beb93cSSam Leffler return NULL; 21939beb93cSSam Leffler } 22039beb93cSSam Leffler wpabuf_free(plain); 22139beb93cSSam Leffler 22239beb93cSSam Leffler wps->state = RECV_M6; 22339beb93cSSam Leffler return msg; 22439beb93cSSam Leffler } 22539beb93cSSam Leffler 22639beb93cSSam Leffler 22739beb93cSSam Leffler static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) 22839beb93cSSam Leffler { 22939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * SSID"); 23039beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_SSID); 23139beb93cSSam Leffler wpabuf_put_be16(msg, wps->wps->ssid_len); 23239beb93cSSam Leffler wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len); 23339beb93cSSam Leffler return 0; 23439beb93cSSam Leffler } 23539beb93cSSam Leffler 23639beb93cSSam Leffler 23739beb93cSSam Leffler static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) 23839beb93cSSam Leffler { 23939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * Authentication Type"); 24039beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_AUTH_TYPE); 24139beb93cSSam Leffler wpabuf_put_be16(msg, 2); 24239beb93cSSam Leffler wpabuf_put_be16(msg, wps->wps->auth_types); 24339beb93cSSam Leffler return 0; 24439beb93cSSam Leffler } 24539beb93cSSam Leffler 24639beb93cSSam Leffler 24739beb93cSSam Leffler static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) 24839beb93cSSam Leffler { 24939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * Encryption Type"); 25039beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_ENCR_TYPE); 25139beb93cSSam Leffler wpabuf_put_be16(msg, 2); 25239beb93cSSam Leffler wpabuf_put_be16(msg, wps->wps->encr_types); 25339beb93cSSam Leffler return 0; 25439beb93cSSam Leffler } 25539beb93cSSam Leffler 25639beb93cSSam Leffler 25739beb93cSSam Leffler static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) 25839beb93cSSam Leffler { 25939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * Network Key"); 26039beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_NETWORK_KEY); 26139beb93cSSam Leffler wpabuf_put_be16(msg, wps->wps->network_key_len); 26239beb93cSSam Leffler wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len); 26339beb93cSSam Leffler return 0; 26439beb93cSSam Leffler } 26539beb93cSSam Leffler 26639beb93cSSam Leffler 26739beb93cSSam Leffler static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg) 26839beb93cSSam Leffler { 26939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)"); 27039beb93cSSam Leffler wpabuf_put_be16(msg, ATTR_MAC_ADDR); 27139beb93cSSam Leffler wpabuf_put_be16(msg, ETH_ALEN); 27239beb93cSSam Leffler wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN); 27339beb93cSSam Leffler return 0; 27439beb93cSSam Leffler } 27539beb93cSSam Leffler 27639beb93cSSam Leffler 27739beb93cSSam Leffler static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain) 27839beb93cSSam Leffler { 27939beb93cSSam Leffler if (wps->wps->ap_settings) { 28039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: * AP Settings (pre-configured)"); 28139beb93cSSam Leffler wpabuf_put_data(plain, wps->wps->ap_settings, 28239beb93cSSam Leffler wps->wps->ap_settings_len); 28339beb93cSSam Leffler return 0; 28439beb93cSSam Leffler } 28539beb93cSSam Leffler 28639beb93cSSam Leffler return wps_build_cred_ssid(wps, plain) || 28739beb93cSSam Leffler wps_build_cred_mac_addr(wps, plain) || 28839beb93cSSam Leffler wps_build_cred_auth_type(wps, plain) || 28939beb93cSSam Leffler wps_build_cred_encr_type(wps, plain) || 29039beb93cSSam Leffler wps_build_cred_network_key(wps, plain); 29139beb93cSSam Leffler } 29239beb93cSSam Leffler 29339beb93cSSam Leffler 29439beb93cSSam Leffler static struct wpabuf * wps_build_m7(struct wps_data *wps) 29539beb93cSSam Leffler { 29639beb93cSSam Leffler struct wpabuf *msg, *plain; 29739beb93cSSam Leffler 29839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); 29939beb93cSSam Leffler 30039beb93cSSam Leffler plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); 30139beb93cSSam Leffler if (plain == NULL) 30239beb93cSSam Leffler return NULL; 30339beb93cSSam Leffler 30439beb93cSSam Leffler msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len); 30539beb93cSSam Leffler if (msg == NULL) { 30639beb93cSSam Leffler wpabuf_free(plain); 30739beb93cSSam Leffler return NULL; 30839beb93cSSam Leffler } 30939beb93cSSam Leffler 31039beb93cSSam Leffler if (wps_build_version(msg) || 31139beb93cSSam Leffler wps_build_msg_type(msg, WPS_M7) || 31239beb93cSSam Leffler wps_build_registrar_nonce(wps, msg) || 31339beb93cSSam Leffler wps_build_e_snonce2(wps, plain) || 31439beb93cSSam Leffler (wps->wps->ap && wps_build_ap_settings(wps, plain)) || 31539beb93cSSam Leffler wps_build_key_wrap_auth(wps, plain) || 31639beb93cSSam Leffler wps_build_encr_settings(wps, msg, plain) || 31739beb93cSSam Leffler wps_build_authenticator(wps, msg)) { 31839beb93cSSam Leffler wpabuf_free(plain); 31939beb93cSSam Leffler wpabuf_free(msg); 32039beb93cSSam Leffler return NULL; 32139beb93cSSam Leffler } 32239beb93cSSam Leffler wpabuf_free(plain); 32339beb93cSSam Leffler 32439beb93cSSam Leffler wps->state = RECV_M8; 32539beb93cSSam Leffler return msg; 32639beb93cSSam Leffler } 32739beb93cSSam Leffler 32839beb93cSSam Leffler 32939beb93cSSam Leffler static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) 33039beb93cSSam Leffler { 33139beb93cSSam Leffler struct wpabuf *msg; 33239beb93cSSam Leffler 33339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); 33439beb93cSSam Leffler 33539beb93cSSam Leffler msg = wpabuf_alloc(1000); 33639beb93cSSam Leffler if (msg == NULL) 33739beb93cSSam Leffler return NULL; 33839beb93cSSam Leffler 33939beb93cSSam Leffler if (wps_build_version(msg) || 34039beb93cSSam Leffler wps_build_msg_type(msg, WPS_WSC_DONE) || 34139beb93cSSam Leffler wps_build_enrollee_nonce(wps, msg) || 34239beb93cSSam Leffler wps_build_registrar_nonce(wps, msg)) { 34339beb93cSSam Leffler wpabuf_free(msg); 34439beb93cSSam Leffler return NULL; 34539beb93cSSam Leffler } 34639beb93cSSam Leffler 34739beb93cSSam Leffler if (wps->wps->ap) 34839beb93cSSam Leffler wps->state = RECV_ACK; 34939beb93cSSam Leffler else { 35039beb93cSSam Leffler wps_success_event(wps->wps); 35139beb93cSSam Leffler wps->state = WPS_FINISHED; 35239beb93cSSam Leffler } 35339beb93cSSam Leffler return msg; 35439beb93cSSam Leffler } 35539beb93cSSam Leffler 35639beb93cSSam Leffler 35739beb93cSSam Leffler static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) 35839beb93cSSam Leffler { 35939beb93cSSam Leffler struct wpabuf *msg; 36039beb93cSSam Leffler 36139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); 36239beb93cSSam Leffler 36339beb93cSSam Leffler msg = wpabuf_alloc(1000); 36439beb93cSSam Leffler if (msg == NULL) 36539beb93cSSam Leffler return NULL; 36639beb93cSSam Leffler 36739beb93cSSam Leffler if (wps_build_version(msg) || 36839beb93cSSam Leffler wps_build_msg_type(msg, WPS_WSC_ACK) || 36939beb93cSSam Leffler wps_build_enrollee_nonce(wps, msg) || 37039beb93cSSam Leffler wps_build_registrar_nonce(wps, msg)) { 37139beb93cSSam Leffler wpabuf_free(msg); 37239beb93cSSam Leffler return NULL; 37339beb93cSSam Leffler } 37439beb93cSSam Leffler 37539beb93cSSam Leffler return msg; 37639beb93cSSam Leffler } 37739beb93cSSam Leffler 37839beb93cSSam Leffler 37939beb93cSSam Leffler static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) 38039beb93cSSam Leffler { 38139beb93cSSam Leffler struct wpabuf *msg; 38239beb93cSSam Leffler 38339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); 38439beb93cSSam Leffler 38539beb93cSSam Leffler msg = wpabuf_alloc(1000); 38639beb93cSSam Leffler if (msg == NULL) 38739beb93cSSam Leffler return NULL; 38839beb93cSSam Leffler 38939beb93cSSam Leffler if (wps_build_version(msg) || 39039beb93cSSam Leffler wps_build_msg_type(msg, WPS_WSC_NACK) || 39139beb93cSSam Leffler wps_build_enrollee_nonce(wps, msg) || 39239beb93cSSam Leffler wps_build_registrar_nonce(wps, msg) || 39339beb93cSSam Leffler wps_build_config_error(msg, wps->config_error)) { 39439beb93cSSam Leffler wpabuf_free(msg); 39539beb93cSSam Leffler return NULL; 39639beb93cSSam Leffler } 39739beb93cSSam Leffler 39839beb93cSSam Leffler return msg; 39939beb93cSSam Leffler } 40039beb93cSSam Leffler 40139beb93cSSam Leffler 40239beb93cSSam Leffler struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, 40339beb93cSSam Leffler enum wsc_op_code *op_code) 40439beb93cSSam Leffler { 40539beb93cSSam Leffler struct wpabuf *msg; 40639beb93cSSam Leffler 40739beb93cSSam Leffler switch (wps->state) { 40839beb93cSSam Leffler case SEND_M1: 40939beb93cSSam Leffler msg = wps_build_m1(wps); 41039beb93cSSam Leffler *op_code = WSC_MSG; 41139beb93cSSam Leffler break; 41239beb93cSSam Leffler case SEND_M3: 41339beb93cSSam Leffler msg = wps_build_m3(wps); 41439beb93cSSam Leffler *op_code = WSC_MSG; 41539beb93cSSam Leffler break; 41639beb93cSSam Leffler case SEND_M5: 41739beb93cSSam Leffler msg = wps_build_m5(wps); 41839beb93cSSam Leffler *op_code = WSC_MSG; 41939beb93cSSam Leffler break; 42039beb93cSSam Leffler case SEND_M7: 42139beb93cSSam Leffler msg = wps_build_m7(wps); 42239beb93cSSam Leffler *op_code = WSC_MSG; 42339beb93cSSam Leffler break; 42439beb93cSSam Leffler case RECEIVED_M2D: 42539beb93cSSam Leffler if (wps->wps->ap) { 42639beb93cSSam Leffler msg = wps_build_wsc_nack(wps); 42739beb93cSSam Leffler *op_code = WSC_NACK; 42839beb93cSSam Leffler break; 42939beb93cSSam Leffler } 43039beb93cSSam Leffler msg = wps_build_wsc_ack(wps); 43139beb93cSSam Leffler *op_code = WSC_ACK; 43239beb93cSSam Leffler if (msg) { 43339beb93cSSam Leffler /* Another M2/M2D may be received */ 43439beb93cSSam Leffler wps->state = RECV_M2; 43539beb93cSSam Leffler } 43639beb93cSSam Leffler break; 43739beb93cSSam Leffler case SEND_WSC_NACK: 43839beb93cSSam Leffler msg = wps_build_wsc_nack(wps); 43939beb93cSSam Leffler *op_code = WSC_NACK; 44039beb93cSSam Leffler break; 44139beb93cSSam Leffler case WPS_MSG_DONE: 44239beb93cSSam Leffler msg = wps_build_wsc_done(wps); 44339beb93cSSam Leffler *op_code = WSC_Done; 44439beb93cSSam Leffler break; 44539beb93cSSam Leffler default: 44639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " 44739beb93cSSam Leffler "a message", wps->state); 44839beb93cSSam Leffler msg = NULL; 44939beb93cSSam Leffler break; 45039beb93cSSam Leffler } 45139beb93cSSam Leffler 45239beb93cSSam Leffler if (*op_code == WSC_MSG && msg) { 45339beb93cSSam Leffler /* Save a copy of the last message for Authenticator derivation 45439beb93cSSam Leffler */ 45539beb93cSSam Leffler wpabuf_free(wps->last_msg); 45639beb93cSSam Leffler wps->last_msg = wpabuf_dup(msg); 45739beb93cSSam Leffler } 45839beb93cSSam Leffler 45939beb93cSSam Leffler return msg; 46039beb93cSSam Leffler } 46139beb93cSSam Leffler 46239beb93cSSam Leffler 46339beb93cSSam Leffler static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) 46439beb93cSSam Leffler { 46539beb93cSSam Leffler if (r_nonce == NULL) { 46639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); 46739beb93cSSam Leffler return -1; 46839beb93cSSam Leffler } 46939beb93cSSam Leffler 47039beb93cSSam Leffler os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN); 47139beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", 47239beb93cSSam Leffler wps->nonce_r, WPS_NONCE_LEN); 47339beb93cSSam Leffler 47439beb93cSSam Leffler return 0; 47539beb93cSSam Leffler } 47639beb93cSSam Leffler 47739beb93cSSam Leffler 47839beb93cSSam Leffler static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) 47939beb93cSSam Leffler { 48039beb93cSSam Leffler if (e_nonce == NULL) { 48139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); 48239beb93cSSam Leffler return -1; 48339beb93cSSam Leffler } 48439beb93cSSam Leffler 48539beb93cSSam Leffler if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) { 48639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received"); 48739beb93cSSam Leffler return -1; 48839beb93cSSam Leffler } 48939beb93cSSam Leffler 49039beb93cSSam Leffler return 0; 49139beb93cSSam Leffler } 49239beb93cSSam Leffler 49339beb93cSSam Leffler 49439beb93cSSam Leffler static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r) 49539beb93cSSam Leffler { 49639beb93cSSam Leffler if (uuid_r == NULL) { 49739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No UUID-R received"); 49839beb93cSSam Leffler return -1; 49939beb93cSSam Leffler } 50039beb93cSSam Leffler 50139beb93cSSam Leffler os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN); 50239beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); 50339beb93cSSam Leffler 50439beb93cSSam Leffler return 0; 50539beb93cSSam Leffler } 50639beb93cSSam Leffler 50739beb93cSSam Leffler 50839beb93cSSam Leffler static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, 50939beb93cSSam Leffler size_t pk_len) 51039beb93cSSam Leffler { 51139beb93cSSam Leffler if (pk == NULL || pk_len == 0) { 51239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); 51339beb93cSSam Leffler return -1; 51439beb93cSSam Leffler } 51539beb93cSSam Leffler 51639beb93cSSam Leffler wpabuf_free(wps->dh_pubkey_r); 51739beb93cSSam Leffler wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len); 51839beb93cSSam Leffler if (wps->dh_pubkey_r == NULL) 51939beb93cSSam Leffler return -1; 52039beb93cSSam Leffler 52139beb93cSSam Leffler if (wps_derive_keys(wps) < 0) 52239beb93cSSam Leffler return -1; 52339beb93cSSam Leffler 52439beb93cSSam Leffler if (wps->request_type == WPS_REQ_WLAN_MANAGER_REGISTRAR && 52539beb93cSSam Leffler wps_derive_mgmt_keys(wps) < 0) 52639beb93cSSam Leffler return -1; 52739beb93cSSam Leffler 52839beb93cSSam Leffler return 0; 52939beb93cSSam Leffler } 53039beb93cSSam Leffler 53139beb93cSSam Leffler 53239beb93cSSam Leffler static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1) 53339beb93cSSam Leffler { 53439beb93cSSam Leffler if (r_hash1 == NULL) { 53539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received"); 53639beb93cSSam Leffler return -1; 53739beb93cSSam Leffler } 53839beb93cSSam Leffler 53939beb93cSSam Leffler os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN); 54039beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN); 54139beb93cSSam Leffler 54239beb93cSSam Leffler return 0; 54339beb93cSSam Leffler } 54439beb93cSSam Leffler 54539beb93cSSam Leffler 54639beb93cSSam Leffler static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2) 54739beb93cSSam Leffler { 54839beb93cSSam Leffler if (r_hash2 == NULL) { 54939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received"); 55039beb93cSSam Leffler return -1; 55139beb93cSSam Leffler } 55239beb93cSSam Leffler 55339beb93cSSam Leffler os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN); 55439beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN); 55539beb93cSSam Leffler 55639beb93cSSam Leffler return 0; 55739beb93cSSam Leffler } 55839beb93cSSam Leffler 55939beb93cSSam Leffler 56039beb93cSSam Leffler static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1) 56139beb93cSSam Leffler { 56239beb93cSSam Leffler u8 hash[SHA256_MAC_LEN]; 56339beb93cSSam Leffler const u8 *addr[4]; 56439beb93cSSam Leffler size_t len[4]; 56539beb93cSSam Leffler 56639beb93cSSam Leffler if (r_snonce1 == NULL) { 56739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received"); 56839beb93cSSam Leffler return -1; 56939beb93cSSam Leffler } 57039beb93cSSam Leffler 57139beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1, 57239beb93cSSam Leffler WPS_SECRET_NONCE_LEN); 57339beb93cSSam Leffler 57439beb93cSSam Leffler /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ 57539beb93cSSam Leffler addr[0] = r_snonce1; 57639beb93cSSam Leffler len[0] = WPS_SECRET_NONCE_LEN; 57739beb93cSSam Leffler addr[1] = wps->psk1; 57839beb93cSSam Leffler len[1] = WPS_PSK_LEN; 57939beb93cSSam Leffler addr[2] = wpabuf_head(wps->dh_pubkey_e); 58039beb93cSSam Leffler len[2] = wpabuf_len(wps->dh_pubkey_e); 58139beb93cSSam Leffler addr[3] = wpabuf_head(wps->dh_pubkey_r); 58239beb93cSSam Leffler len[3] = wpabuf_len(wps->dh_pubkey_r); 58339beb93cSSam Leffler hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); 58439beb93cSSam Leffler 58539beb93cSSam Leffler if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { 58639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does " 58739beb93cSSam Leffler "not match with the pre-committed value"); 58839beb93cSSam Leffler wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; 58939beb93cSSam Leffler wps_pwd_auth_fail_event(wps->wps, 1, 1); 59039beb93cSSam Leffler return -1; 59139beb93cSSam Leffler } 59239beb93cSSam Leffler 59339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first " 59439beb93cSSam Leffler "half of the device password"); 59539beb93cSSam Leffler 59639beb93cSSam Leffler return 0; 59739beb93cSSam Leffler } 59839beb93cSSam Leffler 59939beb93cSSam Leffler 60039beb93cSSam Leffler static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2) 60139beb93cSSam Leffler { 60239beb93cSSam Leffler u8 hash[SHA256_MAC_LEN]; 60339beb93cSSam Leffler const u8 *addr[4]; 60439beb93cSSam Leffler size_t len[4]; 60539beb93cSSam Leffler 60639beb93cSSam Leffler if (r_snonce2 == NULL) { 60739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received"); 60839beb93cSSam Leffler return -1; 60939beb93cSSam Leffler } 61039beb93cSSam Leffler 61139beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce2", r_snonce2, 61239beb93cSSam Leffler WPS_SECRET_NONCE_LEN); 61339beb93cSSam Leffler 61439beb93cSSam Leffler /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ 61539beb93cSSam Leffler addr[0] = r_snonce2; 61639beb93cSSam Leffler len[0] = WPS_SECRET_NONCE_LEN; 61739beb93cSSam Leffler addr[1] = wps->psk2; 61839beb93cSSam Leffler len[1] = WPS_PSK_LEN; 61939beb93cSSam Leffler addr[2] = wpabuf_head(wps->dh_pubkey_e); 62039beb93cSSam Leffler len[2] = wpabuf_len(wps->dh_pubkey_e); 62139beb93cSSam Leffler addr[3] = wpabuf_head(wps->dh_pubkey_r); 62239beb93cSSam Leffler len[3] = wpabuf_len(wps->dh_pubkey_r); 62339beb93cSSam Leffler hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); 62439beb93cSSam Leffler 62539beb93cSSam Leffler if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { 62639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does " 62739beb93cSSam Leffler "not match with the pre-committed value"); 62839beb93cSSam Leffler wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; 62939beb93cSSam Leffler wps_pwd_auth_fail_event(wps->wps, 1, 2); 63039beb93cSSam Leffler return -1; 63139beb93cSSam Leffler } 63239beb93cSSam Leffler 63339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second " 63439beb93cSSam Leffler "half of the device password"); 63539beb93cSSam Leffler 63639beb93cSSam Leffler return 0; 63739beb93cSSam Leffler } 63839beb93cSSam Leffler 63939beb93cSSam Leffler 64039beb93cSSam Leffler static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, 64139beb93cSSam Leffler size_t cred_len) 64239beb93cSSam Leffler { 64339beb93cSSam Leffler struct wps_parse_attr attr; 64439beb93cSSam Leffler struct wpabuf msg; 64539beb93cSSam Leffler 64639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received Credential"); 64739beb93cSSam Leffler os_memset(&wps->cred, 0, sizeof(wps->cred)); 64839beb93cSSam Leffler wpabuf_set(&msg, cred, cred_len); 64939beb93cSSam Leffler if (wps_parse_msg(&msg, &attr) < 0 || 65039beb93cSSam Leffler wps_process_cred(&attr, &wps->cred)) 65139beb93cSSam Leffler return -1; 65239beb93cSSam Leffler 65339beb93cSSam Leffler if (wps->wps->cred_cb) { 65439beb93cSSam Leffler wps->cred.cred_attr = cred - 4; 65539beb93cSSam Leffler wps->cred.cred_attr_len = cred_len + 4; 65639beb93cSSam Leffler wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); 65739beb93cSSam Leffler wps->cred.cred_attr = NULL; 65839beb93cSSam Leffler wps->cred.cred_attr_len = 0; 65939beb93cSSam Leffler } 66039beb93cSSam Leffler 66139beb93cSSam Leffler return 0; 66239beb93cSSam Leffler } 66339beb93cSSam Leffler 66439beb93cSSam Leffler 66539beb93cSSam Leffler static int wps_process_creds(struct wps_data *wps, const u8 *cred[], 66639beb93cSSam Leffler size_t cred_len[], size_t num_cred) 66739beb93cSSam Leffler { 66839beb93cSSam Leffler size_t i; 66939beb93cSSam Leffler 67039beb93cSSam Leffler if (wps->wps->ap) 67139beb93cSSam Leffler return 0; 67239beb93cSSam Leffler 67339beb93cSSam Leffler if (num_cred == 0) { 67439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Credential attributes " 67539beb93cSSam Leffler "received"); 67639beb93cSSam Leffler return -1; 67739beb93cSSam Leffler } 67839beb93cSSam Leffler 67939beb93cSSam Leffler for (i = 0; i < num_cred; i++) { 68039beb93cSSam Leffler if (wps_process_cred_e(wps, cred[i], cred_len[i])) 68139beb93cSSam Leffler return -1; 68239beb93cSSam Leffler } 68339beb93cSSam Leffler 68439beb93cSSam Leffler return 0; 68539beb93cSSam Leffler } 68639beb93cSSam Leffler 68739beb93cSSam Leffler 68839beb93cSSam Leffler static int wps_process_ap_settings_e(struct wps_data *wps, 68939beb93cSSam Leffler struct wps_parse_attr *attr, 69039beb93cSSam Leffler struct wpabuf *attrs) 69139beb93cSSam Leffler { 69239beb93cSSam Leffler struct wps_credential cred; 69339beb93cSSam Leffler 69439beb93cSSam Leffler if (!wps->wps->ap) 69539beb93cSSam Leffler return 0; 69639beb93cSSam Leffler 69739beb93cSSam Leffler if (wps_process_ap_settings(attr, &cred) < 0) 69839beb93cSSam Leffler return -1; 69939beb93cSSam Leffler 70039beb93cSSam Leffler wpa_printf(MSG_INFO, "WPS: Received new AP configuration from " 70139beb93cSSam Leffler "Registrar"); 70239beb93cSSam Leffler 70339beb93cSSam Leffler if (wps->wps->cred_cb) { 70439beb93cSSam Leffler cred.cred_attr = wpabuf_head(attrs); 70539beb93cSSam Leffler cred.cred_attr_len = wpabuf_len(attrs); 70639beb93cSSam Leffler wps->wps->cred_cb(wps->wps->cb_ctx, &cred); 70739beb93cSSam Leffler } 70839beb93cSSam Leffler 70939beb93cSSam Leffler return 0; 71039beb93cSSam Leffler } 71139beb93cSSam Leffler 71239beb93cSSam Leffler 71339beb93cSSam Leffler static enum wps_process_res wps_process_m2(struct wps_data *wps, 71439beb93cSSam Leffler const struct wpabuf *msg, 71539beb93cSSam Leffler struct wps_parse_attr *attr) 71639beb93cSSam Leffler { 71739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received M2"); 71839beb93cSSam Leffler 71939beb93cSSam Leffler if (wps->state != RECV_M2) { 72039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " 72139beb93cSSam Leffler "receiving M2", wps->state); 72239beb93cSSam Leffler wps->state = SEND_WSC_NACK; 72339beb93cSSam Leffler return WPS_CONTINUE; 72439beb93cSSam Leffler } 72539beb93cSSam Leffler 72639beb93cSSam Leffler if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || 72739beb93cSSam Leffler wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || 72839beb93cSSam Leffler wps_process_uuid_r(wps, attr->uuid_r) || 72939beb93cSSam Leffler wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || 73039beb93cSSam Leffler wps_process_authenticator(wps, attr->authenticator, msg)) { 73139beb93cSSam Leffler wps->state = SEND_WSC_NACK; 73239beb93cSSam Leffler return WPS_CONTINUE; 73339beb93cSSam Leffler } 73439beb93cSSam Leffler 73539beb93cSSam Leffler if (wps->wps->ap && wps->wps->ap_setup_locked) { 73639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " 73739beb93cSSam Leffler "registration of a new Registrar"); 73839beb93cSSam Leffler wps->config_error = WPS_CFG_SETUP_LOCKED; 73939beb93cSSam Leffler wps->state = SEND_WSC_NACK; 74039beb93cSSam Leffler return WPS_CONTINUE; 74139beb93cSSam Leffler } 74239beb93cSSam Leffler 74339beb93cSSam Leffler wps->state = SEND_M3; 74439beb93cSSam Leffler return WPS_CONTINUE; 74539beb93cSSam Leffler } 74639beb93cSSam Leffler 74739beb93cSSam Leffler 74839beb93cSSam Leffler static enum wps_process_res wps_process_m2d(struct wps_data *wps, 74939beb93cSSam Leffler struct wps_parse_attr *attr) 75039beb93cSSam Leffler { 75139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received M2D"); 75239beb93cSSam Leffler 75339beb93cSSam Leffler if (wps->state != RECV_M2) { 75439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " 75539beb93cSSam Leffler "receiving M2D", wps->state); 75639beb93cSSam Leffler wps->state = SEND_WSC_NACK; 75739beb93cSSam Leffler return WPS_CONTINUE; 75839beb93cSSam Leffler } 75939beb93cSSam Leffler 76039beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", 76139beb93cSSam Leffler attr->manufacturer, attr->manufacturer_len); 76239beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", 76339beb93cSSam Leffler attr->model_name, attr->model_name_len); 76439beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", 76539beb93cSSam Leffler attr->model_number, attr->model_number_len); 76639beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", 76739beb93cSSam Leffler attr->serial_number, attr->serial_number_len); 76839beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", 76939beb93cSSam Leffler attr->dev_name, attr->dev_name_len); 77039beb93cSSam Leffler 77139beb93cSSam Leffler if (wps->wps->event_cb) { 77239beb93cSSam Leffler union wps_event_data data; 77339beb93cSSam Leffler struct wps_event_m2d *m2d = &data.m2d; 77439beb93cSSam Leffler os_memset(&data, 0, sizeof(data)); 77539beb93cSSam Leffler if (attr->config_methods) 77639beb93cSSam Leffler m2d->config_methods = 77739beb93cSSam Leffler WPA_GET_BE16(attr->config_methods); 77839beb93cSSam Leffler m2d->manufacturer = attr->manufacturer; 77939beb93cSSam Leffler m2d->manufacturer_len = attr->manufacturer_len; 78039beb93cSSam Leffler m2d->model_name = attr->model_name; 78139beb93cSSam Leffler m2d->model_name_len = attr->model_name_len; 78239beb93cSSam Leffler m2d->model_number = attr->model_number; 78339beb93cSSam Leffler m2d->model_number_len = attr->model_number_len; 78439beb93cSSam Leffler m2d->serial_number = attr->serial_number; 78539beb93cSSam Leffler m2d->serial_number_len = attr->serial_number_len; 78639beb93cSSam Leffler m2d->dev_name = attr->dev_name; 78739beb93cSSam Leffler m2d->dev_name_len = attr->dev_name_len; 78839beb93cSSam Leffler m2d->primary_dev_type = attr->primary_dev_type; 78939beb93cSSam Leffler if (attr->config_error) 79039beb93cSSam Leffler m2d->config_error = 79139beb93cSSam Leffler WPA_GET_BE16(attr->config_error); 79239beb93cSSam Leffler if (attr->dev_password_id) 79339beb93cSSam Leffler m2d->dev_password_id = 79439beb93cSSam Leffler WPA_GET_BE16(attr->dev_password_id); 79539beb93cSSam Leffler wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_M2D, &data); 79639beb93cSSam Leffler } 79739beb93cSSam Leffler 79839beb93cSSam Leffler wps->state = RECEIVED_M2D; 79939beb93cSSam Leffler return WPS_CONTINUE; 80039beb93cSSam Leffler } 80139beb93cSSam Leffler 80239beb93cSSam Leffler 80339beb93cSSam Leffler static enum wps_process_res wps_process_m4(struct wps_data *wps, 80439beb93cSSam Leffler const struct wpabuf *msg, 80539beb93cSSam Leffler struct wps_parse_attr *attr) 80639beb93cSSam Leffler { 80739beb93cSSam Leffler struct wpabuf *decrypted; 80839beb93cSSam Leffler struct wps_parse_attr eattr; 80939beb93cSSam Leffler 81039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received M4"); 81139beb93cSSam Leffler 81239beb93cSSam Leffler if (wps->state != RECV_M4) { 81339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " 81439beb93cSSam Leffler "receiving M4", wps->state); 81539beb93cSSam Leffler wps->state = SEND_WSC_NACK; 81639beb93cSSam Leffler return WPS_CONTINUE; 81739beb93cSSam Leffler } 81839beb93cSSam Leffler 81939beb93cSSam Leffler if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || 82039beb93cSSam Leffler wps_process_authenticator(wps, attr->authenticator, msg) || 82139beb93cSSam Leffler wps_process_r_hash1(wps, attr->r_hash1) || 82239beb93cSSam Leffler wps_process_r_hash2(wps, attr->r_hash2)) { 82339beb93cSSam Leffler wps->state = SEND_WSC_NACK; 82439beb93cSSam Leffler return WPS_CONTINUE; 82539beb93cSSam Leffler } 82639beb93cSSam Leffler 82739beb93cSSam Leffler decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, 82839beb93cSSam Leffler attr->encr_settings_len); 82939beb93cSSam Leffler if (decrypted == NULL) { 83039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " 83139beb93cSSam Leffler "Settings attribute"); 83239beb93cSSam Leffler wps->state = SEND_WSC_NACK; 83339beb93cSSam Leffler return WPS_CONTINUE; 83439beb93cSSam Leffler } 83539beb93cSSam Leffler 83639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " 83739beb93cSSam Leffler "attribute"); 83839beb93cSSam Leffler if (wps_parse_msg(decrypted, &eattr) < 0 || 83939beb93cSSam Leffler wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || 84039beb93cSSam Leffler wps_process_r_snonce1(wps, eattr.r_snonce1)) { 84139beb93cSSam Leffler wpabuf_free(decrypted); 84239beb93cSSam Leffler wps->state = SEND_WSC_NACK; 84339beb93cSSam Leffler return WPS_CONTINUE; 84439beb93cSSam Leffler } 84539beb93cSSam Leffler wpabuf_free(decrypted); 84639beb93cSSam Leffler 84739beb93cSSam Leffler wps->state = SEND_M5; 84839beb93cSSam Leffler return WPS_CONTINUE; 84939beb93cSSam Leffler } 85039beb93cSSam Leffler 85139beb93cSSam Leffler 85239beb93cSSam Leffler static enum wps_process_res wps_process_m6(struct wps_data *wps, 85339beb93cSSam Leffler const struct wpabuf *msg, 85439beb93cSSam Leffler struct wps_parse_attr *attr) 85539beb93cSSam Leffler { 85639beb93cSSam Leffler struct wpabuf *decrypted; 85739beb93cSSam Leffler struct wps_parse_attr eattr; 85839beb93cSSam Leffler 85939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received M6"); 86039beb93cSSam Leffler 86139beb93cSSam Leffler if (wps->state != RECV_M6) { 86239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " 86339beb93cSSam Leffler "receiving M6", wps->state); 86439beb93cSSam Leffler wps->state = SEND_WSC_NACK; 86539beb93cSSam Leffler return WPS_CONTINUE; 86639beb93cSSam Leffler } 86739beb93cSSam Leffler 86839beb93cSSam Leffler if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || 86939beb93cSSam Leffler wps_process_authenticator(wps, attr->authenticator, msg)) { 87039beb93cSSam Leffler wps->state = SEND_WSC_NACK; 87139beb93cSSam Leffler return WPS_CONTINUE; 87239beb93cSSam Leffler } 87339beb93cSSam Leffler 87439beb93cSSam Leffler decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, 87539beb93cSSam Leffler attr->encr_settings_len); 87639beb93cSSam Leffler if (decrypted == NULL) { 87739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " 87839beb93cSSam Leffler "Settings attribute"); 87939beb93cSSam Leffler wps->state = SEND_WSC_NACK; 88039beb93cSSam Leffler return WPS_CONTINUE; 88139beb93cSSam Leffler } 88239beb93cSSam Leffler 88339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " 88439beb93cSSam Leffler "attribute"); 88539beb93cSSam Leffler if (wps_parse_msg(decrypted, &eattr) < 0 || 88639beb93cSSam Leffler wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || 88739beb93cSSam Leffler wps_process_r_snonce2(wps, eattr.r_snonce2)) { 88839beb93cSSam Leffler wpabuf_free(decrypted); 88939beb93cSSam Leffler wps->state = SEND_WSC_NACK; 89039beb93cSSam Leffler return WPS_CONTINUE; 89139beb93cSSam Leffler } 89239beb93cSSam Leffler wpabuf_free(decrypted); 89339beb93cSSam Leffler 89439beb93cSSam Leffler wps->state = SEND_M7; 89539beb93cSSam Leffler return WPS_CONTINUE; 89639beb93cSSam Leffler } 89739beb93cSSam Leffler 89839beb93cSSam Leffler 89939beb93cSSam Leffler static enum wps_process_res wps_process_m8(struct wps_data *wps, 90039beb93cSSam Leffler const struct wpabuf *msg, 90139beb93cSSam Leffler struct wps_parse_attr *attr) 90239beb93cSSam Leffler { 90339beb93cSSam Leffler struct wpabuf *decrypted; 90439beb93cSSam Leffler struct wps_parse_attr eattr; 90539beb93cSSam Leffler 90639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received M8"); 90739beb93cSSam Leffler 90839beb93cSSam Leffler if (wps->state != RECV_M8) { 90939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " 91039beb93cSSam Leffler "receiving M8", wps->state); 91139beb93cSSam Leffler wps->state = SEND_WSC_NACK; 91239beb93cSSam Leffler return WPS_CONTINUE; 91339beb93cSSam Leffler } 91439beb93cSSam Leffler 91539beb93cSSam Leffler if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || 91639beb93cSSam Leffler wps_process_authenticator(wps, attr->authenticator, msg)) { 91739beb93cSSam Leffler wps->state = SEND_WSC_NACK; 91839beb93cSSam Leffler return WPS_CONTINUE; 91939beb93cSSam Leffler } 92039beb93cSSam Leffler 92139beb93cSSam Leffler decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, 92239beb93cSSam Leffler attr->encr_settings_len); 92339beb93cSSam Leffler if (decrypted == NULL) { 92439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " 92539beb93cSSam Leffler "Settings attribute"); 92639beb93cSSam Leffler wps->state = SEND_WSC_NACK; 92739beb93cSSam Leffler return WPS_CONTINUE; 92839beb93cSSam Leffler } 92939beb93cSSam Leffler 93039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " 93139beb93cSSam Leffler "attribute"); 93239beb93cSSam Leffler if (wps_parse_msg(decrypted, &eattr) < 0 || 93339beb93cSSam Leffler wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || 93439beb93cSSam Leffler wps_process_creds(wps, eattr.cred, eattr.cred_len, 93539beb93cSSam Leffler eattr.num_cred) || 93639beb93cSSam Leffler wps_process_ap_settings_e(wps, &eattr, decrypted)) { 93739beb93cSSam Leffler wpabuf_free(decrypted); 93839beb93cSSam Leffler wps->state = SEND_WSC_NACK; 93939beb93cSSam Leffler return WPS_CONTINUE; 94039beb93cSSam Leffler } 94139beb93cSSam Leffler wpabuf_free(decrypted); 94239beb93cSSam Leffler 94339beb93cSSam Leffler wps->state = WPS_MSG_DONE; 94439beb93cSSam Leffler return WPS_CONTINUE; 94539beb93cSSam Leffler } 94639beb93cSSam Leffler 94739beb93cSSam Leffler 94839beb93cSSam Leffler static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, 94939beb93cSSam Leffler const struct wpabuf *msg) 95039beb93cSSam Leffler { 95139beb93cSSam Leffler struct wps_parse_attr attr; 95239beb93cSSam Leffler enum wps_process_res ret = WPS_CONTINUE; 95339beb93cSSam Leffler 95439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); 95539beb93cSSam Leffler 95639beb93cSSam Leffler if (wps_parse_msg(msg, &attr) < 0) 95739beb93cSSam Leffler return WPS_FAILURE; 95839beb93cSSam Leffler 95939beb93cSSam Leffler if (!wps_version_supported(attr.version)) { 96039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", 96139beb93cSSam Leffler attr.version ? *attr.version : 0); 96239beb93cSSam Leffler return WPS_FAILURE; 96339beb93cSSam Leffler } 96439beb93cSSam Leffler 96539beb93cSSam Leffler if (attr.enrollee_nonce == NULL || 96639beb93cSSam Leffler os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { 96739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); 96839beb93cSSam Leffler return WPS_FAILURE; 96939beb93cSSam Leffler } 97039beb93cSSam Leffler 97139beb93cSSam Leffler if (attr.msg_type == NULL) { 97239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); 97339beb93cSSam Leffler return WPS_FAILURE; 97439beb93cSSam Leffler } 97539beb93cSSam Leffler 97639beb93cSSam Leffler switch (*attr.msg_type) { 97739beb93cSSam Leffler case WPS_M2: 97839beb93cSSam Leffler ret = wps_process_m2(wps, msg, &attr); 97939beb93cSSam Leffler break; 98039beb93cSSam Leffler case WPS_M2D: 98139beb93cSSam Leffler ret = wps_process_m2d(wps, &attr); 98239beb93cSSam Leffler break; 98339beb93cSSam Leffler case WPS_M4: 98439beb93cSSam Leffler ret = wps_process_m4(wps, msg, &attr); 98539beb93cSSam Leffler if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) 98639beb93cSSam Leffler wps_fail_event(wps->wps, WPS_M4); 98739beb93cSSam Leffler break; 98839beb93cSSam Leffler case WPS_M6: 98939beb93cSSam Leffler ret = wps_process_m6(wps, msg, &attr); 99039beb93cSSam Leffler if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) 99139beb93cSSam Leffler wps_fail_event(wps->wps, WPS_M6); 99239beb93cSSam Leffler break; 99339beb93cSSam Leffler case WPS_M8: 99439beb93cSSam Leffler ret = wps_process_m8(wps, msg, &attr); 99539beb93cSSam Leffler if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) 99639beb93cSSam Leffler wps_fail_event(wps->wps, WPS_M8); 99739beb93cSSam Leffler break; 99839beb93cSSam Leffler default: 99939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", 100039beb93cSSam Leffler *attr.msg_type); 100139beb93cSSam Leffler return WPS_FAILURE; 100239beb93cSSam Leffler } 100339beb93cSSam Leffler 100439beb93cSSam Leffler /* 100539beb93cSSam Leffler * Save a copy of the last message for Authenticator derivation if we 100639beb93cSSam Leffler * are continuing. However, skip M2D since it is not authenticated and 100739beb93cSSam Leffler * neither is the ACK/NACK response frame. This allows the possibly 100839beb93cSSam Leffler * following M2 to be processed correctly by using the previously sent 100939beb93cSSam Leffler * M1 in Authenticator derivation. 101039beb93cSSam Leffler */ 101139beb93cSSam Leffler if (ret == WPS_CONTINUE && *attr.msg_type != WPS_M2D) { 101239beb93cSSam Leffler /* Save a copy of the last message for Authenticator derivation 101339beb93cSSam Leffler */ 101439beb93cSSam Leffler wpabuf_free(wps->last_msg); 101539beb93cSSam Leffler wps->last_msg = wpabuf_dup(msg); 101639beb93cSSam Leffler } 101739beb93cSSam Leffler 101839beb93cSSam Leffler return ret; 101939beb93cSSam Leffler } 102039beb93cSSam Leffler 102139beb93cSSam Leffler 102239beb93cSSam Leffler static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, 102339beb93cSSam Leffler const struct wpabuf *msg) 102439beb93cSSam Leffler { 102539beb93cSSam Leffler struct wps_parse_attr attr; 102639beb93cSSam Leffler 102739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); 102839beb93cSSam Leffler 102939beb93cSSam Leffler if (wps_parse_msg(msg, &attr) < 0) 103039beb93cSSam Leffler return WPS_FAILURE; 103139beb93cSSam Leffler 103239beb93cSSam Leffler if (!wps_version_supported(attr.version)) { 103339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", 103439beb93cSSam Leffler attr.version ? *attr.version : 0); 103539beb93cSSam Leffler return WPS_FAILURE; 103639beb93cSSam Leffler } 103739beb93cSSam Leffler 103839beb93cSSam Leffler if (attr.msg_type == NULL) { 103939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); 104039beb93cSSam Leffler return WPS_FAILURE; 104139beb93cSSam Leffler } 104239beb93cSSam Leffler 104339beb93cSSam Leffler if (*attr.msg_type != WPS_WSC_ACK) { 104439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", 104539beb93cSSam Leffler *attr.msg_type); 104639beb93cSSam Leffler return WPS_FAILURE; 104739beb93cSSam Leffler } 104839beb93cSSam Leffler 104939beb93cSSam Leffler if (attr.registrar_nonce == NULL || 105039beb93cSSam Leffler os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) 105139beb93cSSam Leffler { 105239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); 105339beb93cSSam Leffler return WPS_FAILURE; 105439beb93cSSam Leffler } 105539beb93cSSam Leffler 105639beb93cSSam Leffler if (attr.enrollee_nonce == NULL || 105739beb93cSSam Leffler os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { 105839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); 105939beb93cSSam Leffler return WPS_FAILURE; 106039beb93cSSam Leffler } 106139beb93cSSam Leffler 106239beb93cSSam Leffler if (wps->state == RECV_ACK && wps->wps->ap) { 106339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: External Registrar registration " 106439beb93cSSam Leffler "completed successfully"); 106539beb93cSSam Leffler wps_success_event(wps->wps); 106639beb93cSSam Leffler wps->state = WPS_FINISHED; 106739beb93cSSam Leffler return WPS_DONE; 106839beb93cSSam Leffler } 106939beb93cSSam Leffler 107039beb93cSSam Leffler return WPS_FAILURE; 107139beb93cSSam Leffler } 107239beb93cSSam Leffler 107339beb93cSSam Leffler 107439beb93cSSam Leffler static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, 107539beb93cSSam Leffler const struct wpabuf *msg) 107639beb93cSSam Leffler { 107739beb93cSSam Leffler struct wps_parse_attr attr; 107839beb93cSSam Leffler 107939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); 108039beb93cSSam Leffler 108139beb93cSSam Leffler if (wps_parse_msg(msg, &attr) < 0) 108239beb93cSSam Leffler return WPS_FAILURE; 108339beb93cSSam Leffler 108439beb93cSSam Leffler if (!wps_version_supported(attr.version)) { 108539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", 108639beb93cSSam Leffler attr.version ? *attr.version : 0); 108739beb93cSSam Leffler return WPS_FAILURE; 108839beb93cSSam Leffler } 108939beb93cSSam Leffler 109039beb93cSSam Leffler if (attr.msg_type == NULL) { 109139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); 109239beb93cSSam Leffler return WPS_FAILURE; 109339beb93cSSam Leffler } 109439beb93cSSam Leffler 109539beb93cSSam Leffler if (*attr.msg_type != WPS_WSC_NACK) { 109639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", 109739beb93cSSam Leffler *attr.msg_type); 109839beb93cSSam Leffler return WPS_FAILURE; 109939beb93cSSam Leffler } 110039beb93cSSam Leffler 110139beb93cSSam Leffler if (attr.registrar_nonce == NULL || 110239beb93cSSam Leffler os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN != 0)) 110339beb93cSSam Leffler { 110439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); 110539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: Received Registrar Nonce", 110639beb93cSSam Leffler attr.registrar_nonce, WPS_NONCE_LEN); 110739beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: Expected Registrar Nonce", 110839beb93cSSam Leffler wps->nonce_r, WPS_NONCE_LEN); 110939beb93cSSam Leffler return WPS_FAILURE; 111039beb93cSSam Leffler } 111139beb93cSSam Leffler 111239beb93cSSam Leffler if (attr.enrollee_nonce == NULL || 111339beb93cSSam Leffler os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN != 0)) { 111439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); 111539beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: Received Enrollee Nonce", 111639beb93cSSam Leffler attr.enrollee_nonce, WPS_NONCE_LEN); 111739beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "WPS: Expected Enrollee Nonce", 111839beb93cSSam Leffler wps->nonce_e, WPS_NONCE_LEN); 111939beb93cSSam Leffler return WPS_FAILURE; 112039beb93cSSam Leffler } 112139beb93cSSam Leffler 112239beb93cSSam Leffler if (attr.config_error == NULL) { 112339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " 112439beb93cSSam Leffler "in WSC_NACK"); 112539beb93cSSam Leffler return WPS_FAILURE; 112639beb93cSSam Leffler } 112739beb93cSSam Leffler 112839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with " 112939beb93cSSam Leffler "Configuration Error %d", WPA_GET_BE16(attr.config_error)); 113039beb93cSSam Leffler 113139beb93cSSam Leffler switch (wps->state) { 113239beb93cSSam Leffler case RECV_M4: 113339beb93cSSam Leffler wps_fail_event(wps->wps, WPS_M3); 113439beb93cSSam Leffler break; 113539beb93cSSam Leffler case RECV_M6: 113639beb93cSSam Leffler wps_fail_event(wps->wps, WPS_M5); 113739beb93cSSam Leffler break; 113839beb93cSSam Leffler case RECV_M8: 113939beb93cSSam Leffler wps_fail_event(wps->wps, WPS_M7); 114039beb93cSSam Leffler break; 114139beb93cSSam Leffler default: 114239beb93cSSam Leffler break; 114339beb93cSSam Leffler } 114439beb93cSSam Leffler 114539beb93cSSam Leffler /* Followed by NACK if Enrollee is Supplicant or EAP-Failure if 114639beb93cSSam Leffler * Enrollee is Authenticator */ 114739beb93cSSam Leffler wps->state = SEND_WSC_NACK; 114839beb93cSSam Leffler 114939beb93cSSam Leffler return WPS_FAILURE; 115039beb93cSSam Leffler } 115139beb93cSSam Leffler 115239beb93cSSam Leffler 115339beb93cSSam Leffler enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, 115439beb93cSSam Leffler enum wsc_op_code op_code, 115539beb93cSSam Leffler const struct wpabuf *msg) 115639beb93cSSam Leffler { 115739beb93cSSam Leffler 115839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " 115939beb93cSSam Leffler "op_code=%d)", 116039beb93cSSam Leffler (unsigned long) wpabuf_len(msg), op_code); 116139beb93cSSam Leffler 116239beb93cSSam Leffler switch (op_code) { 116339beb93cSSam Leffler case WSC_MSG: 116439beb93cSSam Leffler case WSC_UPnP: 116539beb93cSSam Leffler return wps_process_wsc_msg(wps, msg); 116639beb93cSSam Leffler case WSC_ACK: 116739beb93cSSam Leffler return wps_process_wsc_ack(wps, msg); 116839beb93cSSam Leffler case WSC_NACK: 116939beb93cSSam Leffler return wps_process_wsc_nack(wps, msg); 117039beb93cSSam Leffler default: 117139beb93cSSam Leffler wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); 117239beb93cSSam Leffler return WPS_FAILURE; 117339beb93cSSam Leffler } 117439beb93cSSam Leffler } 1175