diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index d2e71fad6e..ceb1b0175f 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -22,6 +22,7 @@ set(srcs "port/os_xtensa.c" "src/crypto/sha384-prf.c" "src/crypto/md4-internal.c" "src/crypto/sha1-tprf.c" + "src/eap_common/eap_wsc_common.c" "src/eap_peer/chap.c" "src/eap_peer/eap.c" "src/eap_peer/eap_common.c" @@ -51,9 +52,8 @@ set(srcs "port/os_xtensa.c" "src/wps/wps_attr_process.c" "src/wps/wps_common.c" "src/wps/wps_dev_attr.c" - "src/wps/wps_enrollee.c" - "src/wps/wps_registrar.c" - "src/wps/wps_validate.c") + "src/wps/wps_enrollee.c") +# "src/wps/wps_registrar.c") set(esp_srcs "esp_supplicant/src/esp_wpa2.c" "esp_supplicant/src/esp_wpa_main.c" @@ -66,7 +66,7 @@ if(CONFIG_ESP_WIFI_SOFTAP_SUPPORT) endif() if(CONFIG_WPA_MBEDTLS_CRYPTO) - set(tls_src "src/crypto/tls_mbedtls.c") + set(tls_src "esp_supplicant/src/crypto/tls_mbedtls.c") else() set(tls_src "src/tls/asn1.c" @@ -91,9 +91,9 @@ endif() if(CONFIG_WPA_MBEDTLS_CRYPTO) set(crypto_src - "src/crypto/crypto_mbedtls.c" - "src/crypto/crypto_mbedtls-bignum.c" - "src/crypto/crypto_mbedtls-ec.c") + "esp_supplicant/src/crypto/crypto_mbedtls.c" + "esp_supplicant/src/crypto/crypto_mbedtls-bignum.c" + "esp_supplicant/src/crypto/crypto_mbedtls-ec.c") # Add internal RC4 if RC4 is disabled in mbedtls if(CONFIG_MBEDTLS_RC4_DISABLED) set(crypto_src ${crypto_src} "src/crypto/rc4.c") @@ -133,7 +133,6 @@ else() "src/crypto/crypto_internal-cipher.c" "src/crypto/crypto_internal-modexp.c" "src/crypto/crypto_internal-rsa.c" - "src/crypto/crypto_mbedtls-rsa.c" "src/crypto/crypto_internal.c" "src/crypto/des-internal.c" "src/crypto/md4-internal.c" @@ -180,7 +179,7 @@ endif() idf_component_register(SRCS "${srcs}" ${esp_srcs} "${tls_src}" "${roaming_src}" "${crypto_src}" "${mbo_src}" "${dpp_src}" INCLUDE_DIRS include port/include esp_supplicant/include - PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src + PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src src/crypto PRIV_REQUIRES mbedtls esp_timer) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-strict-aliasing -Wno-write-strings -Werror) diff --git a/components/wpa_supplicant/esp_supplicant/include/esp_wps.h b/components/wpa_supplicant/esp_supplicant/include/esp_wps.h index 25c06782ec..ef885eb802 100644 --- a/components/wpa_supplicant/esp_supplicant/include/esp_wps.h +++ b/components/wpa_supplicant/esp_supplicant/include/esp_wps.h @@ -1,16 +1,8 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __ESP_WPS_H__ #define __ESP_WPS_H__ diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls-bignum.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c similarity index 100% rename from components/wpa_supplicant/src/crypto/crypto_mbedtls-bignum.c rename to components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-bignum.c diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c similarity index 100% rename from components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c rename to components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c similarity index 92% rename from components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c rename to components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c index 2f50f64eae..b9bc4d148f 100644 --- a/components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-rsa.c @@ -1,18 +1,7 @@ /* - * Copyright (C) Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD, Apache 2.0 License. + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ #ifdef ESP_PLATFORM diff --git a/components/wpa_supplicant/src/crypto/crypto_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c similarity index 100% rename from components/wpa_supplicant/src/crypto/crypto_mbedtls.c rename to components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c diff --git a/components/wpa_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c similarity index 100% rename from components/wpa_supplicant/src/crypto/tls_mbedtls.c rename to components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa2.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa2.c index f3fd00e490..a1dd2e25f5 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa2.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa2.c @@ -40,6 +40,7 @@ #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE #include "esp_crt_bundle.h" #endif +#include "esp_wpas_glue.h" #define WPA2_VERSION "v2.0" @@ -297,74 +298,6 @@ int wpa2_post(uint32_t sig, uint32_t par) #endif /* USE_WPA2_TASK */ -static void wpa2_sendto_wrapper(void *buffer, uint16_t len) -{ - esp_wifi_internal_tx(WIFI_IF_STA, buffer, len); -} - -static inline int wpa2_sm_ether_send(struct eap_sm *sm, const u8 *dest, u16 proto, - const u8 *data, size_t data_len) -{ - void *buffer = (void *)(data - sizeof(struct l2_ethhdr)); - struct l2_ethhdr *eth = NULL; - - if (!buffer) { - wpa_printf(MSG_ERROR, "wpa2: invalid data"); - return ESP_FAIL; - } else { - eth = (struct l2_ethhdr *)buffer; - memcpy(eth->h_dest, dest, ETH_ALEN); - memcpy(eth->h_source, sm->ownaddr, ETH_ALEN); - eth->h_proto = host_to_be16(proto); - wpa2_sendto_wrapper(buffer, sizeof(struct l2_ethhdr) + data_len); - } - - return ESP_OK; -} - -u8 *wpa2_sm_alloc_eapol(struct eap_sm *sm, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - void *buffer; - struct ieee802_1x_hdr *hdr; - - *msg_len = sizeof(struct ieee802_1x_hdr) + data_len; - /* XXX: reserve l2_ethhdr is enough */ - buffer = os_malloc(*msg_len + sizeof(struct l2_ethhdr)); - - if (buffer == NULL) { - return NULL; - } - - hdr = (struct ieee802_1x_hdr *)((char *)buffer + sizeof(struct l2_ethhdr)); - hdr->version = 0x01; - hdr->type = type; - hdr->length = host_to_be16(data_len); - - if (data) { - memcpy(hdr + 1, data, data_len); - } else { - memset(hdr + 1, 0, data_len); - } - - if (data_pos) { - *data_pos = hdr + 1; - } - - return (u8 *) hdr; -} - - -void wpa2_sm_free_eapol(u8 *buffer) -{ - if (buffer != NULL) { - buffer = buffer - sizeof(struct l2_ethhdr); - os_free(buffer); - } - -} - int eap_sm_send_eapol(struct eap_sm *sm, struct wpabuf *resp) { size_t outlen; @@ -379,15 +312,15 @@ int eap_sm_send_eapol(struct eap_sm *sm, struct wpabuf *resp) return WPA_ERR_INVALID_BSSID; } - outbuf = wpa2_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, + outbuf = wpa_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head_u8(resp), wpabuf_len(resp), &outlen, NULL); if (!outbuf) { return ESP_ERR_NO_MEM; } - ret = wpa2_sm_ether_send(sm, bssid, ETH_P_EAPOL, outbuf, outlen); - wpa2_sm_free_eapol(outbuf); + ret = wpa_ether_send(sm, bssid, ETH_P_EAPOL, outbuf, outlen); + wpa_free_eapol(outbuf); if (ret) { return ESP_FAIL; } @@ -718,14 +651,14 @@ static int wpa2_start_eapol_internal(void) return WPA_ERR_INVALID_BSSID; } - buf = wpa2_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, (u8 *)"", 0, &len, NULL); + buf = wpa_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, (u8 *)"", 0, &len, NULL); if (!buf) { return ESP_FAIL; } wpa2_set_eap_state(WPA2_ENT_EAP_STATE_IN_PROGRESS); - wpa2_sm_ether_send(sm, bssid, ETH_P_EAPOL, buf, len); - wpa2_sm_free_eapol(buf); + wpa_ether_send(sm, bssid, ETH_P_EAPOL, buf, len); + wpa_free_eapol(buf); return ESP_OK; } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c index 1e3fc424c7..aeb7bb8c6c 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c @@ -1,16 +1,8 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifdef ESP_SUPPLICANT @@ -19,10 +11,12 @@ #include "common/eapol_common.h" #include "rsn_supp/wpa.h" #include "rsn_supp/pmksa_cache.h" +#include "esp_wpas_glue.h" +#include "esp_private/wifi.h" -u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) +u8 *wpa_alloc_eapol(void *sm, u8 type, + const void *data, u16 data_len, + size_t *msg_len, void **data_pos) { void *buffer; struct ieee802_1x_hdr *hdr; @@ -38,7 +32,7 @@ u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, /* XXX: reserve l2_ethhdr is enough */ hdr = (struct ieee802_1x_hdr *)((char *)buffer + sizeof(struct l2_ethhdr)); - hdr->version = sm->eapol_version; + hdr->version = DEFAULT_EAPOL_VERSION; hdr->type = type; hdr->length = host_to_be16(data_len); @@ -55,12 +49,42 @@ u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, return (u8 *) hdr; } -void wpa_sm_free_eapol(u8 *buffer) +void wpa_free_eapol(u8 *buffer) { + if (!buffer) { + return; + } buffer = buffer - sizeof(struct l2_ethhdr); os_free(buffer); } +int wpa_ether_send(void *ctx, const u8 *dest, u16 proto, + const u8 *data, size_t data_len) +{ + void *buffer = (void *)(data - sizeof(struct l2_ethhdr)); + struct l2_ethhdr *eth = (struct l2_ethhdr *)buffer; + + os_memcpy(eth->h_dest, dest, ETH_ALEN); + os_memcpy(eth->h_source, gWpaSm.own_addr, ETH_ALEN); + eth->h_proto = host_to_be16(proto); + + esp_wifi_internal_tx(WIFI_IF_STA, buffer, sizeof(struct l2_ethhdr) + data_len); + + return ESP_OK; +} + +u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, + const void *data, u16 data_len, + size_t *msg_len, void **data_pos) +{ + return wpa_alloc_eapol(sm, type, data, data_len, msg_len, data_pos); +} + +void wpa_sm_free_eapol(u8 *buffer) +{ + return wpa_free_eapol(buffer); +} + void wpa_sm_deauthenticate(struct wpa_sm *sm, u8 reason_code) { diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h index 4d867962e7..7d702314dd 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h @@ -1,16 +1,8 @@ -// Copyright 2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef WPAS_GLUE_H #define WPAS_GLUE_H @@ -30,4 +22,13 @@ int wpa_sm_get_beacon_ie(struct wpa_sm *sm); void wpa_sm_free_eapol(u8 *buffer); +u8 *wpa_alloc_eapol(void *sm, u8 type, + const void *data, u16 data_len, + size_t *msg_len, void **data_pos); + +void wpa_free_eapol(u8 *buffer); + +int wpa_ether_send(void *ctx, const u8 *dest, u16 proto, + const u8 *data, size_t data_len); + #endif /* WPAS_GLUE_H */ diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wps.c b/components/wpa_supplicant/esp_supplicant/src/esp_wps.c index 68502972d4..3e040fe694 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wps.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wps.c @@ -26,6 +26,10 @@ #include "esp_wifi.h" #include "esp_err.h" #include "esp_private/wifi.h" +#include "esp_wps_i.h" +#include "esp_wps.h" +#include "eap_common/eap_wsc_common.h" +#include "esp_wpas_glue.h" #define API_MUTEX_TAKE() do {\ if (!s_wps_api_lock) {\ @@ -281,33 +285,26 @@ int wps_post(uint32_t sig, uint32_t par) } #endif -static void wps_sendto_wrapper(void *buffer, uint16_t len) -{ - esp_wifi_internal_tx(WIFI_IF_STA, buffer, len); -} - /* * wps_sm_ether_send - Send Ethernet frame * @wpa_s: Pointer to wpa_supplicant data -* @dest: Destination MAC address * @proto: Ethertype in host byte order * @buf: Frame payload starting from IEEE 802.1X header * @len: Frame payload length * Returns: >=0 on success, <0 on failure */ -static inline int wps_sm_ether_send(struct wps_sm *sm, const u8 *dest, u16 proto, +static inline int wps_sm_ether_send(struct wps_sm *sm, u16 proto, const u8 *data, size_t data_len) { - void *buffer = (void *)(data - sizeof(struct l2_ethhdr)); - struct l2_ethhdr *eth = (struct l2_ethhdr *)buffer; + u8 bssid[ETH_ALEN]; + int ret = esp_wifi_get_assoc_bssid_internal(bssid); - os_memcpy(eth->h_dest, dest, ETH_ALEN); - os_memcpy(eth->h_source, sm->ownaddr, ETH_ALEN); - eth->h_proto = host_to_be16(proto); + if (ret != 0) { + wpa_printf(MSG_ERROR, "bssid is empty!"); + return -1; + } - wps_sendto_wrapper(buffer, sizeof(struct l2_ethhdr) + data_len); - - return ESP_OK; + return wpa_ether_send(sm, bssid, proto, data, data_len); } @@ -315,189 +312,13 @@ u8 *wps_sm_alloc_eapol(struct wps_sm *sm, u8 type, const void *data, u16 data_len, size_t *msg_len, void **data_pos) { - void *buffer; - struct ieee802_1x_hdr *hdr; - - *msg_len = sizeof(struct ieee802_1x_hdr) + data_len; - /* XXX: reserve l2_ethhdr is enough */ - buffer = os_malloc(*msg_len + sizeof(struct l2_ethhdr)); - - if (buffer == NULL) { - return NULL; - } - hdr = (struct ieee802_1x_hdr *)((char *)buffer + sizeof(struct l2_ethhdr)); - - hdr->version = sm->eapol_version; - hdr->type = type; - hdr->length = host_to_be16(data_len); - - if (data) { - os_memcpy(hdr + 1, data, data_len); - } else { - os_memset(hdr + 1, 0, data_len); - } - - if (data_pos) { - *data_pos = hdr + 1; - } - - return (u8 *) hdr; + return wpa_alloc_eapol(sm, type, data, data_len, msg_len, data_pos); } void wps_sm_free_eapol(u8 *buffer) { - if (buffer != NULL) { - buffer = buffer - sizeof(struct l2_ethhdr); - os_free(buffer); - } -} - - -/** - * wps_init - Initialize WPS Registration protocol data - * @cfg: WPS configuration - * Returns: Pointer to allocated data or %NULL on failure - * - * This function is used to initialize WPS data for a registration protocol - * instance (i.e., each run of registration protocol as a Registrar of - * Enrollee. The caller is responsible for freeing this data after the - * registration run has been completed by calling wps_deinit(). - */ -struct wps_data *wps_init(void) -{ - struct wps_sm *sm = gWpsSm; - struct wps_data *data = (struct wps_data *)os_zalloc(sizeof(*data)); - const char *all_zero_pin = "00000000"; - - if (data == NULL) { - return NULL; - } - - data->wps = sm->wps_ctx; - - if (IS_WPS_REGISTRAR(wps_get_type())) { - data->registrar = 1; - } else { - data->registrar = 0; - } - - data->registrar = 0; /* currently, we force to support enrollee only */ - - if (data->registrar) { - os_memcpy(data->uuid_r, sm->uuid, WPS_UUID_LEN); - } else { - os_memcpy(data->mac_addr_e, sm->dev->mac_addr, ETH_ALEN); - os_memcpy(data->uuid_e, sm->uuid, WPS_UUID_LEN); - } - - if (wps_get_type() == WPS_TYPE_PIN) { - u32 spin = 0; - data->dev_pw_id = DEV_PW_DEFAULT; - data->dev_password_len = 8; - data->dev_password = (u8 *) os_zalloc(data->dev_password_len + 1); - if (data->dev_password == NULL) { - os_free(data); - return NULL; - } - - spin = wps_generate_pin(); - sprintf((char *)data->dev_password, "%08d", spin); - wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password", - data->dev_password, data->dev_password_len); - do { - char tmpp[9]; - os_bzero(tmpp, 9); - os_memcpy(tmpp, data->dev_password, 8); - wpa_printf(MSG_DEBUG, "WPS PIN [%s]", tmpp); - wifi_event_sta_wps_er_pin_t evt; - os_memcpy(evt.pin_code, data->dev_password, 8); - esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_PIN, &evt, sizeof(evt), portMAX_DELAY); - } while (0); - } else if (wps_get_type() == WPS_TYPE_PBC) { - data->pbc = 1; - /* Use special PIN '00000000' for PBC */ - data->dev_pw_id = DEV_PW_PUSHBUTTON; - if (data->dev_password) { - os_free(data->dev_password); - } - data->dev_password = (u8 *) os_zalloc(9); - if (data->dev_password == NULL) { - os_free(data); - return NULL; - } else { - strncpy((char *)data->dev_password, all_zero_pin, 9); - } - data->dev_password_len = 8; - } - -#ifdef CONFIG_WPS_NFC - if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) { - data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id; - os_free(data->dev_password); - data->dev_password = - os_malloc(wpabuf_len(cfg->wps->ap_nfc_dev_pw)); - if (data->dev_password == NULL) { - os_free(data); - return NULL; - } - os_memcpy(data->dev_password, - wpabuf_head(cfg->wps->ap_nfc_dev_pw), - wpabuf_len(cfg->wps->ap_nfc_dev_pw)); - data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw); - } -#endif /* CONFIG_WPS_NFC */ - data->wps->config_methods = WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_DISPLAY; -#ifdef CONFIG_WPS2 - data->wps->config_methods |= (WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_DISPLAY); -#endif - - data->state = data->registrar ? RECV_M1 : SEND_M1; - - return data; -} - - -/** - * wps_deinit - Deinitialize WPS Registration protocol data - * @data: WPS Registration protocol data from wps_init() - */ -void wps_deinit(void) -{ - struct wps_data *data = gWpsSm->wps; - -#ifdef CONFIG_WPS_NFC - if (data->registrar && data->nfc_pw_token) - wps_registrar_remove_nfc_pw_token(data->wps->registrar, - data->nfc_pw_token); -#endif /* CONFIG_WPS_NFC */ - - if (data->wps_pin_revealed) { - wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and " - "negotiation failed"); - } else if (data->registrar) - wpa_printf(MSG_DEBUG, "WPS: register information revealed and " - "negotiation failed"); - wpabuf_free(data->dh_privkey); - -#ifdef DESP32_WORKAROUND - /* - * due to the public key calculated when wps start, it will not calculate anymore even when we build M1 message, also calculate the key need take a long time - * which would cause WPS fail, so we clean the key after WPS finished . - */ - data->dh_privkey = NULL; -#endif //DESP32_WORKAROUND - - wpabuf_free(data->dh_pubkey_e); - wpabuf_free(data->dh_pubkey_r); - wpabuf_free(data->last_msg); - os_free(data->dev_password); - dh5_free(data->dh_ctx); - wps_dev_deinit(&data->peer_dev); -#ifdef CONFIG_WPS_NFC - os_free(data->nfc_pw_token); -#endif - os_free(data); + return wpa_free_eapol(buffer); } static void @@ -506,20 +327,17 @@ wps_build_ic_appie_wps_pr(void) struct wpabuf *extra_ie = NULL; struct wpabuf *wps_ie; struct wps_sm *sm = gWpsSm; + u16 pw_id; wpa_printf(MSG_DEBUG, "wps build: wps pr"); if (wps_get_type() == WPS_TYPE_PBC) { - wps_ie = (struct wpabuf *)wps_build_probe_req_ie(DEV_PW_PUSHBUTTON, - sm->dev, - sm->uuid, WPS_REQ_ENROLLEE, - 0, NULL); + pw_id = DEV_PW_PUSHBUTTON; } else { - wps_ie = (struct wpabuf *)wps_build_probe_req_ie(DEV_PW_DEFAULT, - sm->dev, - sm->uuid, WPS_REQ_ENROLLEE, - 0, NULL); + pw_id = DEV_PW_DEFAULT; } + wps_ie = wps_build_probe_req_ie(pw_id, sm->dev, sm->uuid, + WPS_REQ_ENROLLEE, 0, NULL); if (!wps_ie) { return; @@ -540,7 +358,7 @@ wps_build_ic_appie_wps_pr(void) static void wps_build_ic_appie_wps_ar(void) { - struct wpabuf *buf = (struct wpabuf *)wps_build_assoc_req_ie(WPS_REQ_ENROLLEE); + struct wpabuf *buf = wps_build_assoc_req_ie(WPS_REQ_ENROLLEE); wpa_printf(MSG_DEBUG, "wps build: wps ar"); @@ -555,13 +373,6 @@ wps_parse_scan_result(struct wps_scan_ie *scan) { struct wps_sm *sm = gWpsSm; wifi_mode_t op_mode = 0; -#ifdef WPS_DEBUG - char tmp[32]; - - os_bzero(tmp, 32); - strncpy(tmp, (char *)&scan->ssid[2], (int)scan->ssid[1]); - wpa_printf(MSG_DEBUG, "wps parse scan: %s", tmp); -#endif if (!sm->is_wps_scan || !scan->bssid) { return false; @@ -574,22 +385,26 @@ wps_parse_scan_result(struct wps_scan_ie *scan) return false; } - if (!scan->rsn && !scan->wpa && (scan->capinfo & WIFI_CAPINFO_PRIVACY)) { + esp_wifi_get_mode(&op_mode); + if ((op_mode != WIFI_MODE_STA) +#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT + && (op_mode != WIFI_MODE_APSTA) +#endif + ) { + return false; + } + + if (!scan->rsn && !scan->wpa && (scan->capinfo & WLAN_CAPABILITY_PRIVACY)) { wpa_printf(MSG_INFO, "WEP not suppported in WPS"); return false; } - if (sm->wps_pin_war) { + if (sm->ignore_sel_reg && !is_zero_ether_addr(sm->bssid)) { /* We have selected candidate for this scan */ return false; } - esp_wifi_get_mode(&op_mode); - if ((op_mode == WIFI_MODE_STA -#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT - || op_mode == WIFI_MODE_APSTA -#endif - ) && scan->wps) { + if (scan->wps) { bool ap_found = false; struct wpabuf *buf = wpabuf_alloc_copy(scan->wps + 6, scan->wps[1] - 4); int count; @@ -601,11 +416,7 @@ wps_parse_scan_result(struct wps_scan_ie *scan) sm->discard_ap_cnt = 0; ap_found = true; } - if ((op_mode == WIFI_MODE_STA -#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT - || op_mode == WIFI_MODE_APSTA -#endif - ) && wps_get_type() == WPS_TYPE_PIN && sm->ignore_sel_reg) { + if (wps_get_type() == WPS_TYPE_PIN && sm->ignore_sel_reg) { /* AP is in discard list? */ for (count = 0; count < WPS_MAX_DIS_AP_NUM; count++) { if (os_memcmp(sm->dis_ap_list[count].bssid, scan->bssid, ETH_ALEN) == 0) { @@ -613,22 +424,21 @@ wps_parse_scan_result(struct wps_scan_ie *scan) return false; } } - sm->wps_pin_war = true; } - if (ap_found || sm->wps_pin_war) { + if (ap_found || sm->ignore_sel_reg) { wpabuf_free(buf); esp_wifi_enable_sta_privacy_internal(); - os_memset(sm->config.ssid, 0, sizeof(sm->config.ssid)); - strncpy((char *)sm->config.ssid, (char *)&scan->ssid[2], (int)scan->ssid[1]); - if (scan->bssid && memcmp(sm->config.bssid, scan->bssid, ETH_ALEN) != 0) { - printf("sm BSSid: "MACSTR " scan BSSID " MACSTR "\n", MAC2STR(sm->config.bssid), MAC2STR(scan->bssid)); + os_memset(sm->ssid[0], 0, SSID_MAX_LEN); + strncpy((char *)sm->ssid[0], (char *)&scan->ssid[2], (int)scan->ssid[1]); + sm->ssid_len[0] = scan->ssid[1]; + if (scan->bssid && memcmp(sm->bssid, scan->bssid, ETH_ALEN) != 0) { + wpa_printf(MSG_INFO, "sm BSSid: "MACSTR " scan BSSID " MACSTR "\n", + MAC2STR(sm->bssid), MAC2STR(scan->bssid)); sm->discover_ssid_cnt++; os_memcpy(sm->bssid, scan->bssid, ETH_ALEN); - os_memcpy(sm->config.bssid, scan->bssid, ETH_ALEN); - sm->config.bssid_set = 1; } - wpa_printf(MSG_DEBUG, "wps discover [%s]", (char *)sm->config.ssid); + wpa_printf(MSG_DEBUG, "wps discover [%s]", (char *)sm->ssid); sm->channel = scan->chan; return true; @@ -643,7 +453,6 @@ int wps_send_eap_identity_rsp(u8 id) { struct wps_sm *sm = gWpsSm; struct wpabuf *eap_buf = NULL; - u8 bssid[6]; u8 *buf = NULL; int len; int ret = ESP_OK; @@ -656,12 +465,6 @@ int wps_send_eap_identity_rsp(u8 id) goto _err; } - ret = esp_wifi_get_assoc_bssid_internal(bssid); - if (ret != 0) { - wpa_printf(MSG_ERROR, "bssid is empty!"); - ret = ESP_FAIL; - goto _err; - } wpabuf_put_data(eap_buf, sm->identity, sm->identity_len); @@ -671,7 +474,7 @@ int wps_send_eap_identity_rsp(u8 id) goto _err; } - ret = wps_sm_ether_send(sm, bssid, ETH_P_EAPOL, buf, len); + ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); if (ret) { ret = ESP_FAIL; goto _err; @@ -687,11 +490,9 @@ int wps_send_frag_ack(u8 id) { struct wps_sm *sm = gWpsSm; struct wpabuf *eap_buf = NULL; - u8 bssid[6]; u8 *buf; int len; int ret = 0; - enum wsc_op_code opcode = WSC_FRAG_ACK; wpa_printf(MSG_DEBUG, "send frag ack id:%d", id); @@ -699,28 +500,19 @@ int wps_send_frag_ack(u8 id) return ESP_FAIL; } - ret = esp_wifi_get_assoc_bssid_internal(bssid); - if (ret != 0) { - wpa_printf(MSG_ERROR, "bssid is empty!"); - return ret; - } - - eap_buf = eap_msg_alloc(EAP_VENDOR_WFA, 0x00000001, 2, EAP_CODE_RESPONSE, id); + eap_buf = eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE); if (!eap_buf) { ret = ESP_ERR_NO_MEM; goto _err; } - wpabuf_put_u8(eap_buf, opcode); - wpabuf_put_u8(eap_buf, 0x00); /* flags */ - buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head_u8(eap_buf), wpabuf_len(eap_buf), (size_t *)&len, NULL); if (!buf) { ret = ESP_ERR_NO_MEM; goto _err; } - ret = wps_sm_ether_send(sm, bssid, ETH_P_EAPOL, buf, len); + ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); wps_sm_free_eapol(buf); if (ret) { ret = ESP_ERR_NO_MEM; @@ -859,7 +651,6 @@ int wps_send_wps_mX_rsp(u8 id) struct wps_sm *sm = gWpsSm; struct wpabuf *eap_buf = NULL; struct wpabuf *wps_buf = NULL; - u8 bssid[6]; u8 *buf; int len; int ret = 0; @@ -871,13 +662,7 @@ int wps_send_wps_mX_rsp(u8 id) return ESP_FAIL; } - ret = esp_wifi_get_assoc_bssid_internal(bssid); - if (ret != 0) { - wpa_printf(MSG_ERROR, "bssid is empty!"); - return ret; - } - - wps_buf = (struct wpabuf *)wps_enrollee_get_msg(sm->wps, &opcode); + wps_buf = wps_enrollee_get_msg(sm->wps, &opcode); if (!wps_buf) { ret = ESP_FAIL; goto _err; @@ -902,7 +687,7 @@ int wps_send_wps_mX_rsp(u8 id) goto _err; } - ret = wps_sm_ether_send(sm, bssid, ETH_P_EAPOL, buf, len); + ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); wps_sm_free_eapol(buf); if (ret) { ret = ESP_FAIL; @@ -919,16 +704,8 @@ _err: int wps_tx_start(void) { struct wps_sm *sm = gWpsSm; - u8 bssid[6]; u8 *buf; int len; - int ret = 0; - - ret = esp_wifi_get_assoc_bssid_internal(bssid); - if (ret != 0) { - wpa_printf(MSG_ERROR, "bssid is empty!"); - return ret; - } if (!sm) { return ESP_FAIL; @@ -940,7 +717,7 @@ int wps_tx_start(void) return ESP_ERR_NO_MEM; } - wps_sm_ether_send(sm, bssid, ETH_P_EAPOL, buf, len); + wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len); wps_sm_free_eapol(buf); ets_timer_arm(&sm->wps_eapol_start_timer, 3000, 0); @@ -958,6 +735,30 @@ int wps_start_pending(void) return wps_tx_start(); } +static void wps_stop_connection_timers(struct wps_sm *sm) +{ + esp_wifi_disarm_sta_connection_timer_internal(); + ets_timer_disarm(&sm->wps_msg_timeout_timer); + ets_timer_disarm(&sm->wps_success_cb_timer); +} + +static int wps_sm_init(struct wps_sm *sm) +{ + if (!sm) { + return -1; + } + sm->ignore_sel_reg = false; + sm->discard_ap_cnt = 0; + sm->scan_cnt = 0; + sm->discover_ssid_cnt = 0; + os_bzero(sm->bssid, ETH_ALEN); + os_bzero(sm->ssid, sizeof(sm->ssid)); + os_bzero(sm->ssid_len, sizeof(sm->ssid_len)); + sm->ap_cred_cnt = 0; + + return 0; +} + int wps_stop_process(wifi_event_sta_wps_fail_reason_t reason_code) { struct wps_sm *sm = gWpsSm; @@ -967,19 +768,10 @@ int wps_stop_process(wifi_event_sta_wps_fail_reason_t reason_code) } wps_set_status(WPS_STATUS_DISABLE); - sm->scan_cnt = 0; - sm->discover_ssid_cnt = 0; + wps_sm_init(sm); + sm->wps->state = SEND_M1; - os_bzero(sm->bssid, ETH_ALEN); - os_bzero(sm->ssid, sizeof(sm->ssid)); - os_bzero(sm->ssid_len, sizeof(sm->ssid_len)); - os_bzero((u8 *)&sm->config, sizeof(wifi_sta_config_t)); - sm->ap_cred_cnt = 0; - - esp_wifi_disarm_sta_connection_timer_internal(); - ets_timer_disarm(&sm->wps_msg_timeout_timer); - ets_timer_disarm(&sm->wps_success_cb_timer); - + wps_stop_connection_timers(sm); esp_wifi_disconnect(); wpa_printf(MSG_DEBUG, "Write wps_fail_information"); @@ -999,23 +791,17 @@ int wps_finish(void) } if (sm->wps->state == WPS_FINISHED) { - wpa_printf(MSG_DEBUG, "wps finished------>"); wps_set_status(WPS_STATUS_SUCCESS); - esp_wifi_disarm_sta_connection_timer_internal(); - ets_timer_disarm(&sm->wps_timeout_timer); - ets_timer_disarm(&sm->wps_msg_timeout_timer); + wps_stop_connection_timers(sm); if (sm->ap_cred_cnt == 1) { - wifi_config_t *config = (wifi_config_t *)os_zalloc(sizeof(wifi_config_t)); + wifi_config_t *config = os_zalloc(sizeof(wifi_config_t)); if (config == NULL) { - wifi_event_sta_wps_fail_reason_t reason_code = WPS_FAIL_REASON_NORMAL; - esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_FAILED, &reason_code, sizeof(reason_code), portMAX_DELAY); return ESP_FAIL; } - os_memset(config, 0x00, sizeof(wifi_sta_config_t)); os_memcpy(config->sta.ssid, sm->ssid[0], sm->ssid_len[0]); os_memcpy(config->sta.password, sm->key[0], sm->key_len[0]); os_memcpy(config->sta.bssid, sm->bssid, ETH_ALEN); @@ -1023,20 +809,19 @@ int wps_finish(void) esp_wifi_set_config(0, config); os_free(config); - config = NULL; } ets_timer_disarm(&sm->wps_success_cb_timer); ets_timer_arm(&sm->wps_success_cb_timer, 1000, 0); ret = 0; } else { - wpa_printf(MSG_ERROR, "wps failed-----> wps_pin_war=%d", sm->wps_pin_war); - if (sm->wps_pin_war) { + wpa_printf(MSG_ERROR, "wps failed-----> ignore_sel_reg=%d", sm->ignore_sel_reg); + if (sm->ignore_sel_reg) { sm->discover_ssid_cnt = 0; esp_wifi_disconnect(); os_bzero(sm->ssid, sizeof(sm->ssid)); os_bzero(sm->ssid_len, sizeof(sm->ssid_len)); - wps_add_discard_ap(sm->config.bssid); + wps_add_discard_ap(sm->bssid); } else { ret = wps_stop_process(WPS_FAIL_REASON_NORMAL); } @@ -1063,7 +848,7 @@ void wps_add_discard_ap(u8 *bssid) } sm->discard_ap_cnt = WPS_MAX_DIS_AP_NUM; } - os_memcpy(sm->dis_ap_list[cnt].bssid, bssid, 6); + os_memcpy(sm->dis_ap_list[cnt].bssid, bssid, ETH_ALEN); wpa_printf(MSG_INFO, "Added BSSID:"MACSTR" to discard list cnt=%d" , MAC2STR(bssid), sm->discard_ap_cnt); } @@ -1118,13 +903,13 @@ int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) #ifdef USE_WPS_TASK { - struct wps_rx_param *param = (struct wps_rx_param *)os_zalloc(sizeof(struct wps_rx_param)); /* free in task */ + struct wps_rx_param *param = os_zalloc(sizeof(struct wps_rx_param)); /* free in task */ if (!param) { return ESP_ERR_NO_MEM; } - param->buf = (u8 *)os_zalloc(len); /* free in task */ + param->buf = os_zalloc(len); /* free in task */ if (!param->buf) { os_free(param); return ESP_ERR_NO_MEM; @@ -1281,8 +1066,7 @@ int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len) break; } out: - if (ret != 0 && sm->wps_pin_war) { - sm->wps_pin_war = false; + if (ret != 0 && sm->ignore_sel_reg) { wifi_wps_scan(); } else if ((ret != 0 || res == WPS_FAILURE)) { wifi_event_sta_wps_fail_reason_t reason_code = WPS_FAIL_REASON_NORMAL; @@ -1381,35 +1165,35 @@ int wps_dev_init(void) } } - dev->manufacturer = (char *)os_zalloc(WPS_MAX_MANUFACTURER_LEN); + dev->manufacturer = os_zalloc(WPS_MAX_MANUFACTURER_LEN); if (!dev->manufacturer) { ret = ESP_FAIL; goto _out; } sprintf(dev->manufacturer, s_factory_info->manufacturer); - dev->model_name = (char *)os_zalloc(WPS_MAX_MODEL_NAME_LEN); + dev->model_name = os_zalloc(WPS_MAX_MODEL_NAME_LEN); if (!dev->model_name) { ret = ESP_FAIL; goto _out; } sprintf(dev->model_name, s_factory_info->model_name); - dev->model_number = (char *)os_zalloc(WPS_MAX_MODEL_NAME_LEN); + dev->model_number = os_zalloc(WPS_MAX_MODEL_NAME_LEN); if (!dev->model_number) { ret = ESP_FAIL; goto _out; } sprintf(dev->model_number, s_factory_info->model_number); - dev->device_name = (char *)os_zalloc(WPS_MAX_DEVICE_NAME_LEN); + dev->device_name = os_zalloc(WPS_MAX_DEVICE_NAME_LEN); if (!dev->device_name) { ret = ESP_FAIL; goto _out; } sprintf(dev->device_name, s_factory_info->device_name); - dev->serial_number = (char *)os_zalloc(16); + dev->serial_number = os_zalloc(16); if (!dev->serial_number) { ret = ESP_FAIL; goto _out; @@ -1424,30 +1208,7 @@ int wps_dev_init(void) return ESP_OK; _out: - if (!dev) { - return ret; - } - if (dev->manufacturer) { - os_free(dev->manufacturer); - } - if (dev->model_name) { - os_free(dev->model_name); - } - if (dev->model_number) { - os_free(dev->model_number); - } - if (dev->device_name) { - os_free(dev->device_name); - } - if (dev->serial_number) { - os_free(dev->serial_number); - } - - if (s_factory_info) { - os_free(s_factory_info); - s_factory_info = NULL; - } - + wps_dev_deinit(dev); return ret; } @@ -1524,17 +1285,16 @@ wifi_station_wps_msg_timeout_internal(void) return; } else if (sm->wps->state == RECV_M2) { wpa_printf(MSG_DEBUG, "wps msg timeout RECV_M2"); - wpa_printf(MSG_DEBUG, "wps recev m2/m2d timeout------>"); - if (!sm->wps_pin_war) { + if (!sm->ignore_sel_reg) { wps_stop_process(WPS_FAIL_REASON_RECV_M2D); } } - if (sm->wps_pin_war) { + if (sm->ignore_sel_reg) { esp_wifi_disconnect(); - wps_add_discard_ap(sm->config.bssid); - sm->wps_pin_war = false; + wps_add_discard_ap(sm->bssid); os_bzero(sm->ssid, sizeof(sm->ssid)); os_bzero(sm->ssid_len, sizeof(sm->ssid_len)); + os_bzero(sm->bssid, ETH_ALEN); sm->discover_ssid_cnt = 0; wifi_wps_scan(); } @@ -1557,7 +1317,7 @@ void wifi_station_wps_success_internal(void) int i; /* - * For only one AP credential don't sned event data, wps_finish() has already set + * For only one AP credential don't send event data, wps_finish() has already set * the config. This is for backward compatibility. */ if (sm->ap_cred_cnt > 1) { @@ -1600,12 +1360,35 @@ void wifi_station_wps_eapol_start_handle(void) #endif } +static int save_credentials_cb(void *ctx, const struct wps_credential *cred) +{ + if (!gWpsSm || !cred || gWpsSm->ap_cred_cnt > 2) { + return ESP_FAIL; + } + + os_memset(gWpsSm->ssid[gWpsSm->ap_cred_cnt], 0x00, sizeof(gWpsSm->ssid[gWpsSm->ap_cred_cnt])); + os_memset(gWpsSm->key[gWpsSm->ap_cred_cnt], 0x00, sizeof(gWpsSm->key[gWpsSm->ap_cred_cnt])); + + os_memcpy(gWpsSm->ssid[gWpsSm->ap_cred_cnt], cred->ssid, cred->ssid_len); + gWpsSm->ssid_len[gWpsSm->ap_cred_cnt] = cred->ssid_len; + os_memcpy(gWpsSm->key[gWpsSm->ap_cred_cnt], cred->key, cred->key_len); + gWpsSm->key_len[gWpsSm->ap_cred_cnt] = cred->key_len; + + gWpsSm->ap_cred_cnt++; + + wpa_hexdump_ascii(MSG_DEBUG, "ssid ", cred->ssid, cred->ssid_len); + wpa_hexdump_ascii(MSG_DEBUG, "key ", cred->key, cred->key_len); + + return ESP_OK; +} + int wifi_station_wps_init(void) { struct wps_funcs *wps_cb; struct wps_sm *sm = NULL; uint8_t mac[6]; + struct wps_config cfg = {0}; if (gWpsSm) { goto _out; @@ -1613,30 +1396,20 @@ wifi_station_wps_init(void) wpa_printf(MSG_DEBUG, "wifi sta wps init"); - gWpsSm = (struct wps_sm *)os_zalloc(sizeof(struct wps_sm)); /* alloc Wps_sm */ + gWpsSm = os_zalloc(sizeof(struct wps_sm)); /* alloc Wps_sm */ if (!gWpsSm) { goto _out; } sm = gWpsSm; - os_memset(sm, 0x00, sizeof(struct wps_sm)); esp_wifi_get_macaddr_internal(WIFI_IF_STA, mac); os_memcpy(sm->ownaddr, mac, ETH_ALEN); - sm->discover_ssid_cnt = 0; - sm->ignore_sel_reg = false; - sm->discard_ap_cnt = 0; - os_memset(&sm->dis_ap_list, 0, WPS_MAX_DIS_AP_NUM * sizeof(struct discard_ap_list_t)); - os_memset(&sm->config, 0x00, sizeof(wifi_sta_config_t)); - sm->eapol_version = 0x1; - sm->identity_len = 29; - os_memcpy(sm->identity, WPS_EAP_EXT_VENDOR_TYPE, sm->identity_len); - sm->wps_pin_war = false; + sm->identity_len = WSC_ID_ENROLLEE_LEN; + os_memcpy(sm->identity, WSC_ID_ENROLLEE, sm->identity_len); - sm->is_wps_scan = false; - - sm->wps_ctx = (struct wps_context *)os_zalloc(sizeof(struct wps_context)); /* alloc wps_ctx */ + sm->wps_ctx = os_zalloc(sizeof(struct wps_context)); /* alloc wps_ctx */ if (!sm->wps_ctx) { goto _err; } @@ -1645,10 +1418,42 @@ wifi_station_wps_init(void) goto _err; } - if ((sm->wps = wps_init()) == NULL) { /* alloc wps_data */ + cfg.wps = sm->wps_ctx; + if (IS_WPS_REGISTRAR(wps_get_type())) { + cfg.registrar = 1; + } + + /* TODO add for Registrar */ + if (wps_get_type() == WPS_TYPE_PIN) { + unsigned int spin = 0; + cfg.dev_pw_id = DEV_PW_DEFAULT; + cfg.pin_len = 8; + cfg.pin = os_zalloc(cfg.pin_len + 1); + if (!cfg.pin) { + goto _err; + } + if (wps_generate_pin(&spin) < 0) { + goto _err; + } + os_sprintf((char *)cfg.pin, "%08d", spin); + } else if (wps_get_type() == WPS_TYPE_PBC) { + cfg.pbc = 1; + } + + if ((sm->wps = wps_init(&cfg)) == NULL) { /* alloc wps_data */ goto _err; } + if (cfg.pin) { + os_free((u8 *)cfg.pin); + } + if (wps_get_type() == WPS_TYPE_PIN) { + wifi_event_sta_wps_er_pin_t evt; + os_memcpy(evt.pin_code, sm->wps->dev_password, 8); + esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_PIN, &evt, sizeof(evt), portMAX_DELAY); + } + + sm->wps->wps->cred_cb = save_credentials_cb; /**************80211 reference***************/ if (esp_wifi_get_appie_internal(WIFI_APPIE_WPS_PR) == NULL) { /* alloc probe req wps ie */ @@ -1670,8 +1475,6 @@ wifi_station_wps_init(void) ets_timer_disarm(&sm->wps_eapol_start_timer); ets_timer_setfn(&sm->wps_eapol_start_timer, (ETSTimerFunc *)wifi_station_wps_eapol_start_handle, NULL); - sm->scan_cnt = 0; - wps_cb = os_malloc(sizeof(struct wps_funcs)); if (wps_cb == NULL) { goto _err; @@ -1698,7 +1501,7 @@ _err: sm->wps_ctx = NULL; } if (sm->wps) { - wps_deinit(); + wps_deinit(sm->wps); sm->wps = NULL; } os_free(gWpsSm); @@ -1752,7 +1555,7 @@ wifi_station_wps_deinit(void) sm->wps_ctx = NULL; } if (sm->wps) { - wps_deinit(); + wps_deinit(sm->wps); sm->wps = NULL; } os_free(gWpsSm); @@ -1761,73 +1564,17 @@ wifi_station_wps_deinit(void) return ESP_OK; } -int -wps_station_wps_register_cb(wps_st_cb_t cb) -{ - if (!gWpsSm) { - return ESP_FAIL; - } - - gWpsSm->st_cb = cb; - return ESP_OK; -} - struct wps_sm * wps_sm_get(void) { return gWpsSm; } -int -wps_ssid_save(u8 *ssid, u8 ssid_len, u8 idx) -{ - u8 *tmpssid; - - if (!ssid || !gWpsSm || idx > 2) { - return ESP_FAIL; - } - - os_memset(gWpsSm->ssid[idx], 0x00, sizeof(gWpsSm->ssid[idx])); - os_memcpy(gWpsSm->ssid[idx], ssid, ssid_len); - gWpsSm->ssid_len[idx] = ssid_len; - gWpsSm->ap_cred_cnt++; - - tmpssid = (u8 *)os_zalloc(ssid_len + 1); - if (tmpssid) { - os_memcpy(tmpssid, ssid, ssid_len); - wpa_printf(MSG_DEBUG, "WPS: key[%s]", tmpssid); - os_free(tmpssid); - } - return ESP_OK; -} - -int -wps_key_save(char *key, u8 key_len, u8 idx) -{ - u8 *tmpkey; - - if (!key || !gWpsSm || idx > 2) { - return ESP_FAIL; - } - - os_memset(gWpsSm->key[idx], 0x00, sizeof(gWpsSm->key[idx])); - os_memcpy(gWpsSm->key[idx], key, key_len); - gWpsSm->key_len[idx] = key_len; - - tmpkey = (u8 *)os_zalloc(key_len + 1); - if (tmpkey) { - os_memcpy(tmpkey, key, key_len); - wpa_printf(MSG_DEBUG, "WPS: key[%s], idx - %d", tmpkey, idx); - os_free(tmpkey); - } - return ESP_OK; -} - void wifi_wps_scan_done(void *arg, STATUS status) { struct wps_sm *sm = gWpsSm; - wifi_config_t wifi_config; + wifi_config_t wifi_config = {0}; wpa_printf(MSG_INFO, "WPS: scan done"); if (wps_get_type() == WPS_TYPE_DISABLE) { @@ -1855,7 +1602,11 @@ wifi_wps_scan_done(void *arg, STATUS status) if (wps_get_status() == WPS_STATUS_PENDING) { esp_wifi_disconnect(); - os_memcpy(&wifi_config.sta, &sm->config, sizeof(wifi_sta_config_t)); + os_memcpy(wifi_config.sta.bssid, sm->bssid, ETH_ALEN); + os_strncpy((char *)wifi_config.sta.ssid, (char *)sm->ssid[0], sm->ssid_len[0]); + wifi_config.sta.bssid_set = 1; + wpa_printf(MSG_INFO, "WPS: connecting to %s, bssid=" MACSTR, + (char *)sm->ssid[0], MAC2STR(wifi_config.sta.bssid)); esp_wifi_set_config(0, &wifi_config); wpa_printf(MSG_DEBUG, "WPS: neg start"); @@ -1864,8 +1615,8 @@ wifi_wps_scan_done(void *arg, STATUS status) ets_timer_arm(&sm->wps_msg_timeout_timer, 2000, 0); } else if (wps_get_status() == WPS_STATUS_SCANNING) { if (wps_get_type() == WPS_TYPE_PIN && sm->scan_cnt > WPS_IGNORE_SEL_REG_MAX_CNT) { + wpa_printf(MSG_INFO, "WPS: ignore selected registrar after %d scans", sm->scan_cnt); sm->ignore_sel_reg = true; - sm->wps_pin_war = false; } ets_timer_arm(&sm->wps_scan_timer, 100, 0); } else { @@ -1911,11 +1662,14 @@ int wifi_station_wps_start(void) case WPS_STATUS_DISABLE: { sm->is_wps_scan = true; - wps_build_public_key(sm->wps, NULL, WPS_CALC_KEY_PRE_CALC); - + wps_build_public_key(sm->wps, NULL); + sm->wps->wps->dh_privkey = wpabuf_dup(sm->wps->dh_privkey); + sm->wps->wps->dh_ctx = sm->wps->dh_ctx; + sm->wps->wps->dh_pubkey = sm->wps->dh_pubkey_e; + sm->wps->wps->rf_band_cb = NULL; + wpabuf_clear_free(sm->wps->dh_privkey); + sm->wps->dh_privkey = NULL; wifi_wps_scan(); - - break; } case WPS_STATUS_SCANNING: @@ -2230,24 +1984,3 @@ int esp_wifi_wps_start(int timeout_ms) API_MUTEX_GIVE(); return ESP_OK; } - -bool -wifi_set_wps_cb(wps_st_cb_t cb) -{ - wifi_mode_t mode; - - esp_wifi_get_mode(&mode); - if ( -#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT - mode == WIFI_MODE_AP || -#endif - mode == WIFI_MODE_NULL) { - return false; - } - - if (wps_station_wps_register_cb(cb) == 0) { - return true; - } - - return false; -} diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h new file mode 100644 index 0000000000..945fd489b8 --- /dev/null +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* WPS message flag */ +enum wps_msg_flag { + WPS_MSG_FLAG_MORE = 0x01, + WPS_MSG_FLAG_LEN = 0x02 +}; + +#ifdef USE_WPS_TASK +enum wps_sig_type { + SIG_WPS_ENABLE = 1, //1 + SIG_WPS_DISABLE, //2 + SIG_WPS_START, //3 + SIG_WPS_RX, //4 + SIG_WPS_TIMER_TIMEOUT, //5 + SIG_WPS_TIMER_MSG_TIMEOUT, //6 + SIG_WPS_TIMER_SUCCESS_CB, //7 + SIG_WPS_TIMER_SCAN, //8 + SIG_WPS_TIMER_EAPOL_START, //9 + SIG_WPS_NUM, //10 +}; +#endif + +#define WPS_IGNORE_SEL_REG_MAX_CNT 4 + +#define WPS_MAX_DIS_AP_NUM 10 + +/* Bssid of the discard AP which is discarded for not select reg or other reason */ +struct discard_ap_list_t{ + u8 bssid[6]; +}; + +#ifndef MAX_PASSPHRASE_LEN +#define MAX_PASSPHRASE_LEN 64 +#endif + +#define WPS_OUTBUF_SIZE 500 +struct wps_sm { + struct wps_config *wps_cfg; + struct wps_context *wps_ctx; + struct wps_data *wps; + char identity[32]; + u8 identity_len; + u8 ownaddr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u8 ssid[MAX_CRED_COUNT][SSID_MAX_LEN]; + u8 ssid_len[MAX_CRED_COUNT]; + char key[MAX_CRED_COUNT][MAX_PASSPHRASE_LEN]; + u8 key_len[MAX_CRED_COUNT]; + u8 ap_cred_cnt; + struct wps_device_data *dev; + u8 uuid[16]; + ETSTimer wps_timeout_timer; + ETSTimer wps_msg_timeout_timer; + ETSTimer wps_scan_timer; + ETSTimer wps_success_cb_timer; + ETSTimer wps_eapol_start_timer; + u8 current_identifier; + bool is_wps_scan; + u8 channel; + u8 scan_cnt; +#ifdef USE_WPS_TASK + u8 wps_sig_cnt[SIG_WPS_NUM]; +#endif + u8 discover_ssid_cnt; + bool ignore_sel_reg; + struct discard_ap_list_t dis_ap_list[WPS_MAX_DIS_AP_NUM]; + u8 discard_ap_cnt; +}; + +struct wps_sm *wps_sm_get(void); +int wps_station_wps_unregister_cb(void); +int wps_start_pending(void); +int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); + +int wps_dev_deinit(struct wps_device_data *dev); diff --git a/components/wpa_supplicant/src/common/ieee802_11_defs.h b/components/wpa_supplicant/src/common/ieee802_11_defs.h index d4cab57655..4087166767 100644 --- a/components/wpa_supplicant/src/common/ieee802_11_defs.h +++ b/components/wpa_supplicant/src/common/ieee802_11_defs.h @@ -515,6 +515,12 @@ struct ieee80211_ht_operation { #define HT_OPER_PARAM_PCO_PHASE ((u16) BIT(11)) /* B36..B39 - Reserved */ +#define MULTI_AP_SUB_ELEM_TYPE 0x06 +#define MULTI_AP_TEAR_DOWN BIT(4) +#define MULTI_AP_FRONTHAUL_BSS BIT(5) +#define MULTI_AP_BACKHAUL_BSS BIT(6) +#define MULTI_AP_BACKHAUL_STA BIT(7) + #define WMM_OUI_TYPE 2 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 #define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 diff --git a/components/wpa_supplicant/src/common/wnm_sta.c b/components/wpa_supplicant/src/common/wnm_sta.c index 9e7c8a744d..4d2c7752e5 100644 --- a/components/wpa_supplicant/src/common/wnm_sta.c +++ b/components/wpa_supplicant/src/common/wnm_sta.c @@ -354,7 +354,7 @@ compare_scan_neighbor_results(struct wpa_supplicant *wpa_s, os_time_t age_secs, struct os_reltime now; if (os_get_reltime(&now) == 0 && - os_time_expired(&now, &target->last_update, + os_reltime_expired(&now, &target->last_update, age_secs)) { wpa_printf(MSG_DEBUG, "Candidate BSS is more than %jd seconds old", @@ -546,7 +546,7 @@ static void wnm_add_cand_list(struct wpa_supplicant *wpa_s, struct wpabuf **buf) * list. */ os_get_reltime(&now); - if (os_time_expired(&now, &wpa_s->last_scan, 10)) + if (os_reltime_expired(&now, &wpa_s->last_scan, 10)) return; wpa_printf(MSG_DEBUG, @@ -1010,7 +1010,7 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s, struct os_reltime now; os_get_reltime(&now); - if (!os_time_expired(&now, &wpa_s->last_scan, 10)) { + if (!os_reltime_expired(&now, &wpa_s->last_scan, 10)) { wpa_printf(MSG_DEBUG, "WNM: Try to use recent scan results"); if (wnm_scan_process(wpa_s, 0) > 0) diff --git a/components/wpa_supplicant/src/eap_common/eap_wsc_common.c b/components/wpa_supplicant/src/eap_common/eap_wsc_common.c new file mode 100644 index 0000000000..13b24ef1e7 --- /dev/null +++ b/components/wpa_supplicant/src/eap_common/eap_wsc_common.c @@ -0,0 +1,33 @@ +/* + * EAP-WSC common routines for Wi-Fi Protected Setup + * Copyright (c) 2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "eap_peer/eap_defs.h" +#include "eap_peer/eap_common.h" +#include "wps/wps.h" +#include "eap_wsc_common.h" + +struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code) +{ + struct wpabuf *msg; + + msg = eap_msg_alloc(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, 2, code, id); + if (msg == NULL) { + wpa_printf(MSG_ERROR, "EAP-WSC: Failed to allocate memory for " + "FRAG_ACK"); + return NULL; + } + + wpa_printf(MSG_DEBUG, "EAP-WSC: Send WSC/FRAG_ACK"); + wpabuf_put_u8(msg, WSC_FRAG_ACK); /* Op-Code */ + wpabuf_put_u8(msg, 0); /* Flags */ + + return msg; +} diff --git a/components/wpa_supplicant/src/eap_common/eap_wsc_common.h b/components/wpa_supplicant/src/eap_common/eap_wsc_common.h new file mode 100644 index 0000000000..0e7b653081 --- /dev/null +++ b/components/wpa_supplicant/src/eap_common/eap_wsc_common.h @@ -0,0 +1,27 @@ +/* + * EAP-WSC definitions for Wi-Fi Protected Setup + * Copyright (c) 2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef EAP_WSC_COMMON_H +#define EAP_WSC_COMMON_H + +#define EAP_VENDOR_TYPE_WSC 1 + +#define WSC_FLAGS_MF 0x01 +#define WSC_FLAGS_LF 0x02 + +#define WSC_ID_REGISTRAR "WFA-SimpleConfig-Registrar-1-0" +#define WSC_ID_REGISTRAR_LEN 30 +#define WSC_ID_ENROLLEE "WFA-SimpleConfig-Enrollee-1-0" +#define WSC_ID_ENROLLEE_LEN 29 + +#define WSC_FRAGMENT_SIZE 1400 + + +struct wpabuf * eap_wsc_build_frag_ack(u8 id, u8 code); + +#endif /* EAP_WSC_COMMON_H */ diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c index 0b1ec408d5..888028ec39 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c +++ b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c @@ -38,7 +38,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) { - wpa_bin_clear_free(entry, sizeof(*entry)); + bin_clear_free(entry, sizeof(*entry)); } diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 916d5f0e14..8b1cb67d3d 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -191,7 +191,7 @@ static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid) } /* - * wpa_ether_send - Send Ethernet frame + * wpa_sm_ether_send - Send Ethernet frame * @wpa_s: Pointer to wpa_supplicant data * @dest: Destination MAC address * @proto: Ethertype in host byte order @@ -199,18 +199,10 @@ static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid) * @len: Frame payload length * Returns: >=0 on success, <0 on failure */ -static inline int wpa_sm_ether_send( struct wpa_sm *sm, const u8 *dest, u16 proto, - const u8 *data, size_t data_len) +static inline int wpa_sm_ether_send(struct wpa_sm *sm, const u8 *dest, u16 proto, + const u8 *data, size_t data_len) { - void *buffer = (void *)(data - sizeof(struct l2_ethhdr)); - struct l2_ethhdr *eth = (struct l2_ethhdr *)buffer; - - memcpy(eth->h_dest, dest, ETH_ALEN); - memcpy(eth->h_source, sm->own_addr, ETH_ALEN); - eth->h_proto = host_to_be16(proto); - sm->sendto(buffer, sizeof(struct l2_ethhdr) + data_len); - - return 0; + return wpa_ether_send(sm, dest, proto, data, data_len); } /** @@ -2176,7 +2168,7 @@ bool wpa_sm_init(char * payload, WPA_SEND_FUNC snd_func, struct wpa_sm *sm = &gWpaSm; u16 spp_attrubute = 0; - sm->eapol_version = 0x1; /* DEFAULT_EAPOL_VERSION */ + sm->eapol_version = DEFAULT_EAPOL_VERSION; /* DEFAULT_EAPOL_VERSION */ sm->sendto = snd_func; sm->config_assoc_ie = set_assoc_ie_func; sm->install_ppkey = ppinstallkey; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index 40074e0bc5..8ba7a76806 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -19,10 +19,10 @@ #include "wpa_i.h" struct wpa_sm; +extern struct wpa_sm gWpaSm; #define WPA_SM_STATE(_sm) ((_sm)->wpa_state) - bool wpa_sta_is_cur_pmksa_set(void); bool wpa_sta_in_4way_handshake(void); bool wpa_sta_cur_pmksa_matches_akm(void); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index 451861ef98..c4c2c9c890 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -10,6 +10,8 @@ #define WPA_I_H extern struct wpa_sm gWpaSm; +#define DEFAULT_EAPOL_VERSION 1 + struct install_key { int keys_cleared; enum wpa_alg alg; diff --git a/components/wpa_supplicant/src/utils/common.c b/components/wpa_supplicant/src/utils/common.c index 1c619f5cc6..a230845253 100644 --- a/components/wpa_supplicant/src/utils/common.c +++ b/components/wpa_supplicant/src/utils/common.c @@ -1,35 +1,18 @@ /* * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2007, Jouni Malinen + * Copyright (c) 2002-2019, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ -#include "utils/includes.h" +#include "includes.h" +#include -#include "utils/common.h" #include +#include "common/ieee802_11_defs.h" +#include "common.h" -/** - * inc_byte_array - Increment arbitrary length byte array by one - * @counter: Pointer to byte array - * @len: Length of the counter in bytes - * - * This function increments the last byte of the counter by one and continues - * rolling over to more significant bytes if the byte was incremented from - * 0xff to 0x00. - */ -void inc_byte_array(u8 *counter, size_t len) -{ - int pos = len - 1; - while (pos >= 0) { - counter[pos]++; - if (counter[pos] != 0) - break; - pos--; - } -} static int hex2num(char c) { @@ -56,6 +39,36 @@ int hex2byte(const char *hex) } +/** + * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) + * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) + * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) + * Returns: Characters used (> 0) on success, -1 on failure + */ +int hwaddr_aton2(const char *txt, u8 *addr) +{ + int i; + const char *pos = txt; + + for (i = 0; i < 6; i++) { + int a, b; + + while (*pos == ':' || *pos == '.' || *pos == '-') + pos++; + + a = hex2num(*pos++); + if (a < 0) + return -1; + b = hex2num(*pos++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + } + + return pos - txt; +} + + /** * hexstr2bin - Convert ASCII hex string into binary data * @hex: ASCII hex string (e.g., "01ab") @@ -81,6 +94,28 @@ int hexstr2bin(const char *hex, u8 *buf, size_t len) return 0; } + +/** + * inc_byte_array - Increment arbitrary length byte array by one + * @counter: Pointer to byte array + * @len: Length of the counter in bytes + * + * This function increments the last byte of the counter by one and continues + * rolling over to more significant bytes if the byte was incremented from + * 0xff to 0x00. + */ +void inc_byte_array(u8 *counter, size_t len) +{ + int pos = len - 1; + while (pos >= 0) { + counter[pos]++; + if (counter[pos] != 0) + break; + pos--; + } +} + + void wpa_get_ntp_timestamp(u8 *buf) { struct os_time now; @@ -133,7 +168,7 @@ void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) *txt++ = 't'; break; default: - if (data[i] >= 32 && data[i] <= 127) { + if (data[i] >= 32 && data[i] <= 126) { *txt++ = data[i]; } else { txt += os_snprintf(txt, end - txt, "\\x%02x", @@ -229,6 +264,39 @@ size_t printf_decode(u8 *buf, size_t maxlen, const char *str) } +/** + * wpa_ssid_txt - Convert SSID to a printable string + * @ssid: SSID (32-octet string) + * @ssid_len: Length of ssid in octets + * Returns: Pointer to a printable string + * + * This function can be used to convert SSIDs into printable form. In most + * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard + * does not limit the used character set, so anything could be used in an SSID. + * + * This function uses a static buffer, so only one call can be used at the + * time, i.e., this is not re-entrant and the returned buffer must be used + * before calling this again. + */ +const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) +{ + static char ssid_txt[SSID_MAX_LEN * 4 + 1]; + + if (ssid == NULL) { + ssid_txt[0] = '\0'; + return ssid_txt; + } + + printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); + return ssid_txt; +} + + +void * __hide_aliasing_typecast(void *foo) +{ + return foo; +} + char * wpa_config_parse_string(const char *value, size_t *len) { @@ -312,6 +380,19 @@ int wpa_is_hex(const u8 *data, size_t len) } +int has_ctrl_char(const u8 *data, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) { + if (data[i] < 32 || data[i] == 127) + return 1; + } + return 0; +} + + + size_t wpa_merge_byte_arrays(u8 *res, size_t res_len, const u8 *src1, size_t src1_len, const u8 *src2, size_t src2_len) @@ -358,39 +439,36 @@ char * dup_binstr(const void *src, size_t len) return res; } -void wpa_bin_clear_free(void *bin, size_t len) -{ - if (bin) { - os_memset(bin, 0, len); - os_free(bin); - } -} -int int_array_len(const int *a) + +size_t int_array_len(const int *a) { - int i; + size_t i; + for (i = 0; a && a[i]; i++) ; return i; } -void bin_clear_free(void *bin, size_t len) -{ - if (bin) { - os_memset(bin, 0, len); - os_free(bin); - } -} - void str_clear_free(char *str) { if (str) { size_t len = os_strlen(str); - os_memset(str, 0, len); + forced_memzero(str, len); os_free(str); } } + +void bin_clear_free(void *bin, size_t len) +{ + if (bin) { + forced_memzero(bin, len); + os_free(bin); + } +} + + int os_gmtime(os_time_t t, struct os_tm *tm) { struct tm *tm2; @@ -430,6 +508,39 @@ int os_mktime(int year, int month, int day, int hour, int min, int sec, return 0; } +void * os_memdup(const void *src, size_t len) +{ + void *r = os_malloc(len); + + if (r && src) + os_memcpy(r, src, len); + return r; +} + +int os_reltime_expired(struct os_time *now, + struct os_time *ts, + os_time_t timeout_secs) +{ + struct os_time age; + + os_time_sub(now, ts, &age); + return (age.sec > timeout_secs) || + (age.sec == timeout_secs && age.usec > 0); +} + + +u8 rssi_to_rcpi(int rssi) +{ + if (!rssi) + return 255; /* not available */ + if (rssi < -110) + return 0; + if (rssi > 0) + return 220; + return (rssi + 110) * 2; +} + + char * get_param(const char *cmd, const char *param) { const char *pos, *end; @@ -453,102 +564,3 @@ char * get_param(const char *cmd, const char *param) val[len] = '\0'; return val; } - -void * os_memdup(const void *src, size_t len) -{ - void *r = os_malloc(len); - - if (r && src) - os_memcpy(r, src, len); - return r; -} - -/** - * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) - * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) - * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) - * Returns: Characters used (> 0) on success, -1 on failure - */ -int hwaddr_aton2(const char *txt, u8 *addr) -{ - int i; - const char *pos = txt; - - for (i = 0; i < 6; i++) { - int a, b; - - while (*pos == ':' || *pos == '.' || *pos == '-') - pos++; - - a = hex2num(*pos++); - if (a < 0) - return -1; - b = hex2num(*pos++); - if (b < 0) - return -1; - *addr++ = (a << 4) | b; - } - - return pos - txt; -} - -static inline int os_reltime_expired(struct os_time *now, - struct os_time *ts, - os_time_t timeout_secs) -{ - struct os_time age; - - os_time_sub(now, ts, &age); - return (age.sec > timeout_secs) || - (age.sec == timeout_secs && age.usec > 0); -} - -int os_time_expired(struct os_time *now, - struct os_time *ts, - os_time_t timeout_secs) -{ - return os_reltime_expired(now, ts, timeout_secs); -} - -u8 rssi_to_rcpi(int rssi) -{ - if (!rssi) - return 255; /* not available */ - if (rssi < -110) - return 0; - if (rssi > 0) - return 220; - return (rssi + 110) * 2; -} - -/** - * wpa_ssid_txt - Convert SSID to a printable string - * @ssid: SSID (32-octet string) - * @ssid_len: Length of ssid in octets - * Returns: Pointer to a printable string - * - * This function can be used to convert SSIDs into printable form. In most - * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard - * does not limit the used character set, so anything could be used in an SSID. - * - * This function uses a static buffer, so only one call can be used at the - * time, i.e., this is not re-entrant and the returned buffer must be used - * before calling this again. - */ -const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) -{ - static char ssid_txt[SSID_MAX_LEN * 4 + 1]; - - if (ssid == NULL) { - ssid_txt[0] = '\0'; - return ssid_txt; - } - - printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); - return ssid_txt; -} - -void * __hide_aliasing_typecast(void *foo) -{ - return foo; -} diff --git a/components/wpa_supplicant/src/utils/common.h b/components/wpa_supplicant/src/utils/common.h index ab4d3dda61..05e2f11b28 100644 --- a/components/wpa_supplicant/src/utils/common.h +++ b/components/wpa_supplicant/src/utils/common.h @@ -389,7 +389,7 @@ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask); u8 rssi_to_rcpi(int rssi); -int os_time_expired(struct os_time *now, +int os_reltime_expired(struct os_time *now, struct os_time *ts, os_time_t timeout_secs); @@ -408,6 +408,7 @@ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len); char * wpa_config_parse_string(const char *value, size_t *len); int wpa_is_hex(const u8 *data, size_t len); +int has_ctrl_char(const u8 *data, size_t len); size_t wpa_merge_byte_arrays(u8 *res, size_t res_len, const u8 *src1, size_t src1_len, const u8 *src2, size_t src2_len); @@ -447,8 +448,7 @@ struct wpa_freq_range_list { #define TEST_FAIL() 0 #endif -void wpa_bin_clear_free(void *bin, size_t len); -int int_array_len(const int *a); +size_t int_array_len(const int *a); void bin_clear_free(void *bin, size_t len); void str_clear_free(char *str); char * get_param(const char *cmd, const char *param); diff --git a/components/wpa_supplicant/src/utils/wpa_debug.c b/components/wpa_supplicant/src/utils/wpa_debug.c index 6436938cd7..3190ffa5df 100644 --- a/components/wpa_supplicant/src/utils/wpa_debug.c +++ b/components/wpa_supplicant/src/utils/wpa_debug.c @@ -1,15 +1,9 @@ /* * wpa_supplicant/hostapd / Debug prints - * Copyright (c) 2002-2007, Jouni Malinen + * Copyright (c) 2002-2013, Jouni Malinen * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #ifdef ESP_SUPPLICANT #include "utils/includes.h" diff --git a/components/wpa_supplicant/src/wps/wps.c b/components/wpa_supplicant/src/wps/wps.c index c505a02031..9265c2436a 100644 --- a/components/wpa_supplicant/src/wps/wps.c +++ b/components/wpa_supplicant/src/wps/wps.c @@ -5,20 +5,191 @@ * This software may be distributed under the terms of the BSD license. * See README for more details. */ -#include -#include "utils/includes.h" -#include "rsn_supp/wpa.h" -#include "utils/common.h" -#include "common/eapol_common.h" -#include "utils/wpa_debug.h" +#include "includes.h" + +#include "common.h" +#include "crypto/dh_group5.h" #include "common/ieee802_11_defs.h" +#include "wps_i.h" +#include "wps_dev_attr.h" -#include "wps/wps_i.h" -#include "wps/wps_dev_attr.h" -#include "eap_peer/eap_defs.h" -#include "eap_peer/eap_common.h" +#ifdef CONFIG_WPS_TESTING +int wps_version_number = 0x20; +int wps_testing_stub_cred = 0; +int wps_corrupt_pkhash = 0; +int wps_force_auth_types_in_use = 0; +u16 wps_force_auth_types = 0; +int wps_force_encr_types_in_use = 0; +u16 wps_force_encr_types = 0; +#endif /* CONFIG_WPS_TESTING */ + + +/** + * wps_init - Initialize WPS Registration protocol data + * @cfg: WPS configuration + * Returns: Pointer to allocated data or %NULL on failure + * + * This function is used to initialize WPS data for a registration protocol + * instance (i.e., each run of registration protocol as a Registrar of + * Enrollee. The caller is responsible for freeing this data after the + * registration run has been completed by calling wps_deinit(). + */ +struct wps_data * wps_init(const struct wps_config *cfg) +{ + struct wps_data *data = os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + data->wps = cfg->wps; + data->registrar = cfg->registrar; + if (cfg->registrar) { + os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN); + } else { + os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN); + os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN); + } + if (cfg->pin) { + data->dev_pw_id = cfg->dev_pw_id; + data->dev_password = os_memdup(cfg->pin, cfg->pin_len); + if (data->dev_password == NULL) { + os_free(data); + return NULL; + } + data->dev_password_len = cfg->pin_len; + wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password", + data->dev_password, data->dev_password_len); + } + +#ifdef CONFIG_WPS_NFC + if (cfg->pin == NULL && + cfg->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) + data->dev_pw_id = cfg->dev_pw_id; + + if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) { + /* Keep AP PIN as alternative Device Password */ + data->alt_dev_pw_id = data->dev_pw_id; + data->alt_dev_password = data->dev_password; + data->alt_dev_password_len = data->dev_password_len; + + data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id; + data->dev_password = + os_memdup(wpabuf_head(cfg->wps->ap_nfc_dev_pw), + wpabuf_len(cfg->wps->ap_nfc_dev_pw)); + if (data->dev_password == NULL) { + os_free(data); + return NULL; + } + data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw); + wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password", + data->dev_password, data->dev_password_len); + } +#endif /* CONFIG_WPS_NFC */ + + data->pbc = cfg->pbc; + if (cfg->pbc) { + /* Use special PIN '00000000' for PBC */ + data->dev_pw_id = DEV_PW_PUSHBUTTON; + bin_clear_free(data->dev_password, data->dev_password_len); + data->dev_password = (u8 *) os_strdup("00000000"); + if (data->dev_password == NULL) { + os_free(data); + return NULL; + } + data->dev_password_len = 8; + } + + data->state = data->registrar ? RECV_M1 : SEND_M1; + +#ifndef ESP_SUPPLICANT + if (cfg->assoc_wps_ie) { + struct wps_parse_attr attr; + wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq", + cfg->assoc_wps_ie); + if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) { + wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE " + "from (Re)AssocReq"); + } else if (attr.request_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute " + "in (Re)AssocReq WPS IE"); + } else { + wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE " + "in (Re)AssocReq WPS IE): %d", + *attr.request_type); + data->request_type = *attr.request_type; + } + } + + if (cfg->new_ap_settings) { + data->new_ap_settings = + os_memdup(cfg->new_ap_settings, + sizeof(*data->new_ap_settings)); + if (data->new_ap_settings == NULL) { + bin_clear_free(data->dev_password, + data->dev_password_len); + os_free(data); + return NULL; + } + } + + if (cfg->peer_addr) + os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN); + if (cfg->p2p_dev_addr) + os_memcpy(data->p2p_dev_addr, cfg->p2p_dev_addr, ETH_ALEN); + + data->use_psk_key = cfg->use_psk_key; + data->pbc_in_m1 = cfg->pbc_in_m1; + + if (cfg->peer_pubkey_hash) { + os_memcpy(data->peer_pubkey_hash, cfg->peer_pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN); + data->peer_pubkey_hash_set = 1; + } + + data->multi_ap_backhaul_sta = cfg->multi_ap_backhaul_sta; + +#endif + return data; +} + + +/** + * wps_deinit - Deinitialize WPS Registration protocol data + * @data: WPS Registration protocol data from wps_init() + */ +void wps_deinit(struct wps_data *data) +{ +#ifdef CONFIG_WPS_NFC + if (data->registrar && data->nfc_pw_token) + wps_registrar_remove_nfc_pw_token(data->wps->registrar, + data->nfc_pw_token); +#endif /* CONFIG_WPS_NFC */ + +#ifdef CONFIG_WPS_REGISTRAR + if (data->wps_pin_revealed) { + wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and " + "negotiation failed"); + if (data->registrar) + wps_registrar_invalidate_pin(data->wps->registrar, + data->uuid_e); + } else if (data->registrar) + wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e); +#endif + + wpabuf_clear_free(data->dh_privkey); + wpabuf_free(data->dh_pubkey_e); + wpabuf_free(data->dh_pubkey_r); + wpabuf_free(data->last_msg); + bin_clear_free(data->dev_password, data->dev_password_len); +#ifndef ESP_SUPPLICANT + bin_clear_free(data->alt_dev_password, data->alt_dev_password_len); + bin_clear_free(data->new_psk, data->new_psk_len); +#endif /* ESP_SUPPLICANT */ + wps_device_data_free(&data->peer_dev); + bin_clear_free(data->new_ap_settings, sizeof(*data->new_ap_settings)); + dh5_free(data->dh_ctx); + os_free(data); +} /** @@ -69,7 +240,7 @@ struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) */ int wps_is_selected_pbc_registrar(const struct wpabuf *msg) { - struct wps_parse_attr *attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + struct wps_parse_attr *attr = os_zalloc(sizeof(struct wps_parse_attr)); if (!attr) return 0; @@ -103,7 +274,6 @@ int wps_is_selected_pbc_registrar(const struct wpabuf *msg) return 1; } -#ifdef CONFIG_WPS_PIN static int is_selected_pin_registrar(struct wps_parse_attr *attr) { @@ -143,7 +313,7 @@ int wps_is_selected_pin_registrar(const struct wpabuf *msg) struct wps_parse_attr *attr; int ret; - attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + attr = os_zalloc(sizeof(struct wps_parse_attr)); if (attr == NULL) return -99; @@ -157,7 +327,6 @@ int wps_is_selected_pin_registrar(const struct wpabuf *msg) return ret; } -#endif /** * wps_is_addr_authorized - Check whether WPS IE authorizes MAC address @@ -176,7 +345,7 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, const u8 *pos; const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + attr = os_zalloc(sizeof(struct wps_parse_attr)); if (attr == NULL) { ret = 0; goto _out; @@ -192,11 +361,9 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, * Version 1.0 AP - AuthorizedMACs not used, so revert back to * old mechanism of using SelectedRegistrar. */ -#ifdef CONFIG_WPS_PIN ret = is_selected_pin_registrar(attr); goto _out; -#endif } if (!attr->authorized_macs) { @@ -343,7 +510,7 @@ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || - wps_build_wfa_ext(ie, 0, NULL, 0)) { + wps_build_wfa_ext(ie, 0, NULL, 0, 0)) { wpabuf_free(ie); return NULL; } @@ -377,7 +544,7 @@ struct wpabuf * wps_build_assoc_resp_ie(void) if (wps_build_version(ie) || wps_build_resp_type(ie, WPS_RESP_AP) || - wps_build_wfa_ext(ie, 0, NULL, 0)) { + wps_build_wfa_ext(ie, 0, NULL, 0, 0)) { wpabuf_free(ie); return NULL; } @@ -410,30 +577,26 @@ struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev, { struct wpabuf *ie; - wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request\n"); + wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); - ie = wpabuf_alloc(400); - if (ie == NULL) { - wpa_printf(MSG_ERROR, "WPS: ie alloc failed."); + ie = wpabuf_alloc(500); + if (ie == NULL) return NULL; - } if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || wps_build_config_methods(ie, dev->config_methods) || wps_build_uuid_e(ie, uuid) || wps_build_primary_dev_type(dev, ie) || - wps_build_rf_bands(dev, ie) || + wps_build_rf_bands(dev, ie, 0) || wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pw_id) || -#ifdef CONFIG_WPS2 wps_build_manufacturer(dev, ie) || wps_build_model_name(dev, ie) || wps_build_model_number(dev, ie) || wps_build_dev_name(dev, ie) || - wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) || -#endif /* CONFIG_WPS2 */ + wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0, 0) || wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types) || wps_build_secondary_dev_type(dev, ie) @@ -442,13 +605,6 @@ struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev, return NULL; } -#ifndef CONFIG_WPS2 - if (dev->p2p && wps_build_dev_name(dev, ie)) { - wpabuf_free(ie); - return NULL; - } -#endif /* CONFIG_WPS2 */ - return wps_ie_encapsulate(ie); } diff --git a/components/wpa_supplicant/src/wps/wps.h b/components/wpa_supplicant/src/wps/wps.h index 4164340450..aaf45cfc40 100644 --- a/components/wpa_supplicant/src/wps/wps.h +++ b/components/wpa_supplicant/src/wps/wps.h @@ -1,6 +1,6 @@ /* * Wi-Fi Protected Setup - * Copyright (c) 2007-2012, Jouni Malinen + * Copyright (c) 2007-2016, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -9,13 +9,8 @@ #ifndef WPS_H #define WPS_H -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/rom/ets_sys.h" // will be removed in idf v5.0 -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/ets_sys.h" -#endif +#include "common/ieee802_11_defs.h" #include "wps_defs.h" -#include "esp_wifi_types.h" /** * enum wsc_op_code - EAP-WSC OP-Code values @@ -31,6 +26,7 @@ enum wsc_op_code { }; struct wps_registrar; +struct upnp_wps_device_sm; struct wps_er; struct wps_parse_attr; @@ -38,7 +34,7 @@ struct wps_parse_attr; * struct wps_credential - WPS Credential * @ssid: SSID * @ssid_len: Length of SSID - * @auth_type: Authentication Type (WPS_WIFI_AUTH_OPEN, .. flags) + * @auth_type: Authentication Type (WPS_AUTH_OPEN, .. flags) * @encr_type: Encryption Type (WPS_ENCR_NONE, .. flags) * @key_idx: Key index * @key: Key @@ -47,10 +43,9 @@ struct wps_parse_attr; * @cred_attr: Unparsed Credential attribute data (used only in cred_cb()); * this may be %NULL, if not used * @cred_attr_len: Length of cred_attr in octets - * @ap_channel: AP channel */ struct wps_credential { - u8 ssid[32]; + u8 ssid[SSID_MAX_LEN]; size_t ssid_len; u16 auth_type; u16 encr_type; @@ -60,7 +55,6 @@ struct wps_credential { u8 mac_addr[ETH_ALEN]; const u8 *cred_attr; size_t cred_attr_len; - u16 ap_channel; }; #define WPS_DEV_TYPE_LEN 8 @@ -85,7 +79,7 @@ struct wps_credential { * @sec_dev_type: Array of secondary device types * @num_sec_dev_type: Number of secondary device types * @os_version: OS Version - * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ flags) + * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ, WPS_RF_60GHZ flags) * @p2p: Whether the device is a P2P device */ struct wps_device_data { @@ -104,8 +98,10 @@ struct wps_device_data { u16 config_methods; struct wpabuf *vendor_ext_m1; struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; + struct wpabuf *application_ext; int p2p; + u8 multi_ap_ext; }; /** @@ -136,7 +132,7 @@ struct wps_config { * pbc - Whether this is protocol run uses PBC */ int pbc; - +#ifndef ESP_SUPPLICANT /** * assoc_wps_ie: (Re)AssocReq WPS IE (in AP; %NULL if not AP) */ @@ -166,11 +162,13 @@ struct wps_config { */ int use_psk_key; +#endif /** * dev_pw_id - Device Password ID for Enrollee when PIN is used */ u16 dev_pw_id; +#ifndef ESP_SUPPLICANT /** * p2p_dev_addr - P2P Device Address from (Re)Association Request * @@ -188,16 +186,23 @@ struct wps_config { * PBC with the AP. */ int pbc_in_m1; + + /** + * peer_pubkey_hash - Peer public key hash or %NULL if not known + */ + const u8 *peer_pubkey_hash; + + /** + * multi_ap_backhaul_sta - Whether this is a Multi-AP backhaul STA + * enrollee + */ + int multi_ap_backhaul_sta; +#endif }; -/* Bssid of the discard AP which is discarded for not select reg or other reason */ -struct discard_ap_list_t{ - u8 bssid[6]; -}; +struct wps_data * wps_init(const struct wps_config *cfg); -struct wps_data * wps_init(void); - -void wps_deinit(void); +void wps_deinit(struct wps_data *data); /** * enum wps_process_res - WPS message processing result @@ -259,14 +264,15 @@ struct wps_registrar_config { * new_psk_cb - Callback for new PSK * @ctx: Higher layer context data (cb_ctx) * @mac_addr: MAC address of the Enrollee + * @p2p_dev_addr: P2P Device Address of the Enrollee or all zeros if not * @psk: The new PSK * @psk_len: The length of psk in octets * Returns: 0 on success, -1 on failure * * This callback is called when a new per-device PSK is provisioned. */ - int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, - size_t psk_len); + int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr, + const u8 *psk, size_t psk_len); /** * set_ie_cb - Callback for WPS IE changes @@ -344,6 +350,14 @@ struct wps_registrar_config { u16 dev_password_id, u8 request_type, const char *dev_name); + /** + * lookup_pskfile_cb - Callback for searching for PSK in wpa_psk_file + * @ctx: Higher layer context data (cb_ctx) + * @addr: Enrollee's MAC address + * @psk: Pointer to found PSK (output arg) + */ + int (*lookup_pskfile_cb)(void *ctx, const u8 *mac_addr, const u8 **psk); + /** * cb_ctx: Higher layer context data for Registrar callbacks */ @@ -386,15 +400,49 @@ struct wps_registrar_config { */ int disable_auto_conf; - /** - * static_wep_only - Whether the BSS supports only static WEP - */ - int static_wep_only; - /** * dualband - Whether this is a concurrent dualband AP */ int dualband; + + /** + * force_per_enrollee_psk - Force per-Enrollee random PSK + * + * This forces per-Enrollee random PSK to be generated even if a default + * PSK is set for a network. + */ + int force_per_enrollee_psk; + + /** + * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul + * enrollee + * + * This SSID is used by the Registrar to fill in information for + * Credentials when the enrollee advertises it is a Multi-AP backhaul + * STA. + */ + const u8 *multi_ap_backhaul_ssid; + + /** + * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in + * octets + */ + size_t multi_ap_backhaul_ssid_len; + + /** + * multi_ap_backhaul_network_key - The Network Key (PSK) for the + * Multi-AP backhaul enrollee. + * + * This key can be either the ASCII passphrase (8..63 characters) or the + * 32-octet PSK (64 hex characters). + */ + const u8 *multi_ap_backhaul_network_key; + + /** + * multi_ap_backhaul_network_key_len - Length of + * multi_ap_backhaul_network_key in octets + */ + size_t multi_ap_backhaul_network_key_len; }; @@ -432,6 +480,16 @@ enum wps_event { */ WPS_EV_PBC_TIMEOUT, + /** + * WPS_EV_PBC_ACTIVE - PBC mode was activated + */ + WPS_EV_PBC_ACTIVE, + + /** + * WPS_EV_PBC_DISABLE - PBC mode was disabled + */ + WPS_EV_PBC_DISABLE, + /** * WPS_EV_ER_AP_ADD - ER: AP added */ @@ -500,11 +558,17 @@ union wps_event_data { int msg; u16 config_error; u16 error_indication; + u8 peer_macaddr[ETH_ALEN]; } fail; + struct wps_event_success { + u8 peer_macaddr[ETH_ALEN]; + } success; + struct wps_event_pwd_auth_fail { int enrollee; int part; + u8 peer_macaddr[ETH_ALEN]; } pwd_auth_fail; struct wps_event_er_ap { @@ -568,7 +632,6 @@ struct upnp_pending_message { struct wpabuf *msg; enum wps_msg_type type; }; -void wps_free_pending_msgs(struct upnp_pending_message *msgs); #endif /** * struct wps_context - Long term WPS context data @@ -609,7 +672,7 @@ struct wps_context { * Credentials. In addition, AP uses it when acting as an Enrollee to * notify Registrar of the current configuration. */ - u8 ssid[32]; + u8 ssid[SSID_MAX_LEN]; /** * ssid_len - Length of ssid in octets @@ -648,11 +711,31 @@ struct wps_context { */ u16 encr_types; + /** + * encr_types_rsn - Enabled encryption types for RSN (WPS_ENCR_*) + */ + u16 encr_types_rsn; + + /** + * encr_types_wpa - Enabled encryption types for WPA (WPS_ENCR_*) + */ + u16 encr_types_wpa; + /** * auth_types - Authentication types (bit field of WPS_AUTH_*) */ u16 auth_types; + /** + * encr_types - Current AP encryption type (WPS_ENCR_*) + */ + u16 ap_encr_type; + + /** + * ap_auth_type - Current AP authentication types (WPS_AUTH_*) + */ + u16 ap_auth_type; + /** * network_key - The current Network Key (PSK) or %NULL to generate new * @@ -660,7 +743,7 @@ struct wps_context { * uses this when acting as an Enrollee to notify Registrar of the * current configuration. * - * When using WPA/WPA2-Person, this key can be either the ASCII + * When using WPA/WPA2-Personal, this key can be either the ASCII * passphrase (8..63 characters) or the 32-octet PSK (64 hex * characters). When this is set to the ASCII passphrase, the PSK can * be provided in the psk buffer and used per-Enrollee to control which @@ -743,35 +826,43 @@ struct wps_context { void (*event_cb)(void *ctx, enum wps_event event, union wps_event_data *data); + /** + * rf_band_cb - Fetch currently used RF band + * @ctx: Higher layer context data (cb_ctx) + * Return: Current used RF band or 0 if not known + */ + int (*rf_band_cb)(void *ctx); + /** * cb_ctx: Higher layer context data for callbacks */ void *cb_ctx; + struct upnp_wps_device_sm *wps_upnp; + /* Pending messages from UPnP PutWLANResponse */ -#ifdef CONFIG_WPS_NFC + struct upnp_pending_message *upnp_msgs; u16 ap_nfc_dev_pw_id; struct wpabuf *ap_nfc_dh_pubkey; struct wpabuf *ap_nfc_dh_privkey; struct wpabuf *ap_nfc_dev_pw; -#endif + + /* Whether to send WPA2-PSK passphrase as a passphrase instead of PSK + * for WPA3-Personal transition mode needs. */ + bool use_passphrase; }; struct wps_registrar * wps_registrar_init(struct wps_context *wps, const struct wps_registrar_config *cfg); void wps_registrar_deinit(struct wps_registrar *reg); -#ifdef CONFIG_WPS_PIN - int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, const u8 *uuid, const u8 *pin, size_t pin_len, int timeout); int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid); -int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid); -#endif int wps_registrar_wps_cancel(struct wps_registrar *reg); - +int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid); int wps_registrar_button_pushed(struct wps_registrar *reg, const u8 *p2p_dev_addr); void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e, @@ -788,27 +879,35 @@ int wps_registrar_config_ap(struct wps_registrar *reg, int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, const u8 *pubkey_hash, u16 pw_id, - const u8 *dev_pw, size_t dev_pw_len); + const u8 *dev_pw, size_t dev_pw_len, + int pk_hash_provided_oob); int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, const u8 *oob_dev_pw, size_t oob_dev_pw_len); #endif +void wps_registrar_flush(struct wps_registrar *reg); +int wps_registrar_update_multi_ap(struct wps_registrar *reg, + const u8 *multi_ap_backhaul_ssid, + size_t multi_ap_backhaul_ssid_len, + const u8 *multi_ap_backhaul_network_key, + size_t multi_ap_backhaul_network_key_len); + int wps_build_credential_wrap(struct wpabuf *msg, const struct wps_credential *cred); -#ifdef CONFIG_WPS_PIN + unsigned int wps_pin_checksum(unsigned int pin); unsigned int wps_pin_valid(unsigned int pin); +int wps_generate_pin(unsigned int *pin); int wps_pin_str_valid(const char *pin); -#endif - -unsigned int wps_generate_pin(void); +void wps_free_pending_msgs(struct upnp_pending_message *msgs); #ifdef CONFIG_WPS_OOB - -struct wpabuf * wps_get_oob_cred(struct wps_context *wps); +struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, + int channel); int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr); #endif int wps_attr_text(struct wpabuf *data, char *buf, char *end); +const char * wps_ei_str(enum wps_error_indication ei); struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname, const char *filter); @@ -816,18 +915,22 @@ void wps_er_refresh(struct wps_er *er); void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx); void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods); -int wps_er_pbc(struct wps_er *er, const u8 *uuid); -int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, - size_t pin_len); -int wps_er_set_config(struct wps_er *er, const u8 *uuid, +int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr); +const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr); +int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr, + const u8 *pin, size_t pin_len); +int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr, const struct wps_credential *cred); -int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin, - size_t pin_len, const struct wps_credential *cred); -#ifdef CONFIG_WPS_NFC - -struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid); - -#endif +int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, + const u8 *pin, size_t pin_len, + const struct wps_credential *cred); +struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, + struct wps_credential *cred); +struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, + const u8 *addr); +struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er, + struct wps_context *wps, const u8 *uuid, + const u8 *addr, struct wpabuf *pubkey); int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]); char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, @@ -840,15 +943,30 @@ u16 wps_config_methods_str2bin(const char *str); struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, const struct wpabuf *pubkey, const struct wpabuf *dev_pw); +struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey, + struct wpabuf *dev_pw); +int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey); struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, struct wpabuf **privkey, struct wpabuf **dev_pw); +struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey); +struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey, + const u8 *bssid, int freq); +struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey); +struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx, + int nfc_dev_pw_id, + struct wpabuf *nfc_dh_pubkey, + struct wpabuf *nfc_dev_pw); #endif /* ndef.c */ struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf); struct wpabuf * ndef_build_wifi(const struct wpabuf *buf); -struct wpabuf * ndef_build_wifi_hr(void); +struct wpabuf * ndef_parse_p2p(const struct wpabuf *buf); +struct wpabuf * ndef_build_p2p(const struct wpabuf *buf); #ifdef CONFIG_WPS_STRICT int wps_validate_beacon(const struct wpabuf *wps_ie); @@ -996,79 +1114,4 @@ static inline int wps_validate_upnp_set_selected_registrar( } #endif /* CONFIG_WPS_STRICT */ -enum wps_cb_status { - WPS_CB_ST_SUCCESS = 0, - WPS_CB_ST_FAILED, - WPS_CB_ST_TIMEOUT, - WPS_CB_ST_WEP, - WPS_CB_ST_SCAN_ERR, -}; - -typedef void (*wps_st_cb_t)(int status); - -#ifdef USE_WPS_TASK -enum wps_sig_type { - SIG_WPS_ENABLE = 1, //1 - SIG_WPS_DISABLE, //2 - SIG_WPS_START, //3 - SIG_WPS_RX, //4 - SIG_WPS_TIMER_TIMEOUT, //5 - SIG_WPS_TIMER_MSG_TIMEOUT, //6 - SIG_WPS_TIMER_SUCCESS_CB, //7 - SIG_WPS_TIMER_SCAN, //8 - SIG_WPS_TIMER_EAPOL_START, //9 - SIG_WPS_NUM, //10 -}; -#endif - -#define WPS_EAP_EXT_VENDOR_TYPE "WFA-SimpleConfig-Enrollee-1-0" -#define WPS_OUTBUF_SIZE 500 -struct wps_sm { - struct wps_config *wps_cfg; - struct wps_context *wps_ctx; - struct wps_data *wps; - char identity[32]; - u8 identity_len; - u8 ownaddr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - u8 ssid[MAX_WPS_AP_CRED][MAX_SSID_LEN]; - u8 ssid_len[MAX_WPS_AP_CRED]; - char key[MAX_WPS_AP_CRED][MAX_PASSPHRASE_LEN]; - u8 key_len[MAX_WPS_AP_CRED]; - u8 ap_cred_cnt; - struct wps_device_data *dev; - u8 uuid[16]; - u8 eapol_version; - ETSTimer wps_timeout_timer; - ETSTimer wps_msg_timeout_timer; - ETSTimer wps_scan_timer; - ETSTimer wps_success_cb_timer; - ETSTimer wps_eapol_start_timer; - wps_st_cb_t st_cb; - u8 current_identifier; - bool is_wps_scan; - u8 channel; - u8 scan_cnt; -#ifdef USE_WPS_TASK - u8 wps_sig_cnt[SIG_WPS_NUM]; -#endif - u8 discover_ssid_cnt; - bool ignore_sel_reg; - bool wps_pin_war; - struct discard_ap_list_t dis_ap_list[WPS_MAX_DIS_AP_NUM]; - u8 discard_ap_cnt; - wifi_sta_config_t config; -}; - -#define WIFI_CAPINFO_PRIVACY 0x0010 - -struct wps_sm *wps_sm_get(void); -int wps_ssid_save(u8 *ssid, u8 ssid_len, u8 idx); -int wps_key_save(char *key, u8 key_len, u8 idx); -int wps_station_wps_register_cb(wps_st_cb_t cb); -int wps_station_wps_unregister_cb(void); -int wps_start_pending(void); -int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); - -int wps_dev_deinit(struct wps_device_data *dev); #endif /* WPS_H */ diff --git a/components/wpa_supplicant/src/wps/wps_attr_build.c b/components/wpa_supplicant/src/wps/wps_attr_build.c index c61114bdb2..c7d739a0c3 100644 --- a/components/wpa_supplicant/src/wps/wps_attr_build.c +++ b/components/wpa_supplicant/src/wps/wps_attr_build.c @@ -1,86 +1,99 @@ /* * Wi-Fi Protected Setup - attribute building - * Copyright (c) 2008, Jouni Malinen + * Copyright (c) 2008-2016, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ -#include "utils/includes.h" -#include "utils/common.h" -#include "utils/wpa_debug.h" +#include "includes.h" + +#include "common.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" +#include "crypto/dh_group5.h" #include "crypto/sha256.h" #include "crypto/random.h" -#include "crypto/dh_group5.h" - #include "common/ieee802_11_defs.h" -#include "wps/wps_i.h" +#include "wps_i.h" -int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_t mode) + +int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *pubkey = NULL; - if (mode != WPS_CALC_KEY_NO_CALC) { - - wpa_printf(MSG_DEBUG, "WPS: * Public Key"); - wpabuf_free(wps->dh_privkey); - if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { - wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); - wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); - wps->dh_ctx = wps->wps->dh_ctx; - wps->wps->dh_ctx = NULL; - pubkey = wpabuf_dup(wps->wps->dh_pubkey); -#ifdef CONFIG_WPS_NFC - } else if (wps->dev_pw_id >= 0x10 && wps->wps->ap && - wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) { - wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys"); - wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey); - pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey); - wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); -#endif /* CONFIG_WPS_NFC */ - } else { - wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); - wps->dh_privkey = NULL; - dh5_free(wps->dh_ctx); - - wpa_printf(MSG_DEBUG, "build public key start\n"); - - wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); - - wpa_printf(MSG_DEBUG, "build public key finish\n"); - - pubkey = wpabuf_zeropad(pubkey, 192); - } - if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " - "Diffie-Hellman handshake"); - wpabuf_free(pubkey); + wpa_printf(MSG_DEBUG, "WPS: * Public Key"); + wpabuf_clear_free(wps->dh_privkey); + wps->dh_privkey = NULL; + if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey && + wps->wps->dh_ctx) { + wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); + if (wps->wps->dh_pubkey == NULL) { + wpa_printf(MSG_DEBUG, + "WPS: wps->wps->dh_pubkey == NULL"); return -1; } - wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); - wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); - - if (wps->registrar) { - wpabuf_free(wps->dh_pubkey_r); - wps->dh_pubkey_r = pubkey; - } else { - wpabuf_free(wps->dh_pubkey_e); - wps->dh_pubkey_e = pubkey; + wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); + wps->dh_ctx = wps->wps->dh_ctx; + wps->wps->dh_ctx = NULL; + pubkey = wpabuf_dup(wps->wps->dh_pubkey); +#ifdef CONFIG_WPS_NFC + } else if ((wps->dev_pw_id >= 0x10 || + wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) && + (wps->wps->ap || + (wps->wps->ap_nfc_dh_pubkey && + wps->wps->ap_nfc_dev_pw_id == + DEV_PW_NFC_CONNECTION_HANDOVER && + wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)) && + (wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id || + wps->wps->ap_nfc_dh_pubkey)) { + wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys"); + if (wps->wps->ap_nfc_dh_privkey == NULL) { + wpa_printf(MSG_DEBUG, + "WPS: wps->wps->ap_nfc_dh_privkey == NULL"); + return -1; } - + if (wps->wps->ap_nfc_dh_pubkey == NULL) { + wpa_printf(MSG_DEBUG, + "WPS: wps->wps->ap_nfc_dh_pubkey == NULL"); + return -1; + } + wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey); + pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey); + if (wps->dh_privkey && pubkey) + wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); +#endif /* CONFIG_WPS_NFC */ + } else { + wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); + dh5_free(wps->dh_ctx); + wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); + pubkey = wpabuf_zeropad(pubkey, 192); } + if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " + "Diffie-Hellman handshake"); + wpabuf_free(pubkey); + return -1; + } + wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); + wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); - if (mode != WPS_CALC_KEY_PRE_CALC) { - if (wps->registrar) - pubkey = wps->dh_pubkey_r; - else - pubkey = wps->dh_pubkey_e; +#ifdef ESP_SUPPLICANT + if (msg) { +#endif + wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); + wpabuf_put_be16(msg, wpabuf_len(pubkey)); + wpabuf_put_buf(msg, pubkey); +#ifdef ESP_SUPPLICANT + } +#endif - wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); - wpabuf_put_be16(msg, wpabuf_len(pubkey)); - wpabuf_put_buf(msg, pubkey); + if (wps->registrar) { + wpabuf_free(wps->dh_pubkey_r); + wps->dh_pubkey_r = pubkey; + } else { + wpabuf_free(wps->dh_pubkey_e); + wps->dh_pubkey_e = pubkey; } return 0; @@ -89,7 +102,7 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_ int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) { - wpa_printf(MSG_DEBUG, "WPS: * Request Type"); + wpa_printf(MSG_DEBUG, "WPS: * Request Type"); wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, type); @@ -99,7 +112,7 @@ int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) { - wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); + wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, type); @@ -109,7 +122,7 @@ int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) int wps_build_config_methods(struct wpabuf *msg, u16 methods) { - wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); + wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, methods); @@ -119,7 +132,9 @@ int wps_build_config_methods(struct wpabuf *msg, u16 methods) int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) { - wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); + if (wpabuf_tailroom(msg) < 4 + WPS_UUID_LEN) + return -1; + wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); wpabuf_put_be16(msg, ATTR_UUID_E); wpabuf_put_be16(msg, WPS_UUID_LEN); wpabuf_put_data(msg, uuid, WPS_UUID_LEN); @@ -129,7 +144,7 @@ int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) int wps_build_dev_password_id(struct wpabuf *msg, u16 id) { - wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); + wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, id); @@ -139,7 +154,7 @@ int wps_build_dev_password_id(struct wpabuf *msg, u16 id) int wps_build_config_error(struct wpabuf *msg, u16 err) { - wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); + wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, err); @@ -154,7 +169,7 @@ int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) size_t len[2]; if (wps->last_msg == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Last message not available for " + wpa_printf(MSG_DEBUG, "WPS: Last message not available for " "building authenticator"); return -1; } @@ -166,8 +181,11 @@ int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) len[0] = wpabuf_len(wps->last_msg); addr[1] = wpabuf_head(msg); len[1] = wpabuf_len(msg); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); - wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); + if (hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, + hash) < 0) + return -1; + + wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); @@ -183,7 +201,9 @@ int wps_build_version(struct wpabuf *msg) * backwards compatibility reasons. The real version negotiation is * done with Version2. */ - wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)"); + if (wpabuf_tailroom(msg) < 5) + return -1; + wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)"); wpabuf_put_be16(msg, ATTR_VERSION); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 0x10); @@ -192,22 +212,31 @@ int wps_build_version(struct wpabuf *msg) int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, - const u8 *auth_macs, size_t auth_macs_count) + const u8 *auth_macs, size_t auth_macs_count, + u8 multi_ap_subelem) { -#ifdef CONFIG_WPS2 u8 *len; +#ifdef CONFIG_WPS_TESTING + if (WPS_VERSION == 0x10) + return 0; +#endif /* CONFIG_WPS_TESTING */ + + if (wpabuf_tailroom(msg) < + 7 + 3 + (req_to_enroll ? 3 : 0) + + (auth_macs ? 2 + auth_macs_count * ETH_ALEN : 0)) + return -1; wpabuf_put_be16(msg, ATTR_VENDOR_EXT); len = wpabuf_put(msg, 2); /* to be filled */ wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA); - wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION); + wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION); wpabuf_put_u8(msg, WFA_ELEM_VERSION2); wpabuf_put_u8(msg, 1); wpabuf_put_u8(msg, WPS_VERSION); if (req_to_enroll) { - wpa_printf(MSG_DEBUG, "WPS: * Request to Enroll (1)"); + wpa_printf(MSG_DEBUG, "WPS: * Request to Enroll (1)"); wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL); wpabuf_put_u8(msg, 1); wpabuf_put_u8(msg, 1); @@ -215,22 +244,31 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, if (auth_macs && auth_macs_count) { size_t i; - wpa_printf(MSG_DEBUG, "WPS: * AuthorizedMACs (count=%d)", + wpa_printf(MSG_DEBUG, "WPS: * AuthorizedMACs (count=%d)", (int) auth_macs_count); wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS); wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN); wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN); for (i = 0; i < auth_macs_count; i++) - wpa_printf(MSG_DEBUG, "WPS: AuthorizedMAC: " MACSTR, + wpa_printf(MSG_DEBUG, "WPS: AuthorizedMAC: " MACSTR, MAC2STR(&auth_macs[i * ETH_ALEN])); } + if (multi_ap_subelem) { + wpa_printf(MSG_DEBUG, "WPS: * Multi-AP (0x%x)", + multi_ap_subelem); + wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP); + wpabuf_put_u8(msg, 1); /* length */ + wpabuf_put_u8(msg, multi_ap_subelem); + } + WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2); -#endif /* CONFIG_WPS2 */ #ifdef CONFIG_WPS_TESTING if (WPS_VERSION > 0x20) { - wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra " + if (wpabuf_tailroom(msg) < 5) + return -1; + wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra " "attribute"); wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST); wpabuf_put_be16(msg, 1); @@ -243,7 +281,7 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) { - wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); + wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); wpabuf_put_be16(msg, ATTR_MSG_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, msg_type); @@ -253,7 +291,7 @@ int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); + wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); @@ -263,7 +301,7 @@ int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); + wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); @@ -274,10 +312,23 @@ int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) { u16 auth_types = WPS_AUTH_TYPES; -#ifdef CONFIG_WPS2 + /* WPA/WPA2-Enterprise enrollment not supported through WPS */ + auth_types &= ~WPS_AUTH_WPA; + auth_types &= ~WPS_AUTH_WPA2; auth_types &= ~WPS_AUTH_SHARED; -#endif /* CONFIG_WPS2 */ - wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags"); +#ifdef CONFIG_NO_TKIP + auth_types &= ~WPS_AUTH_WPAPSK; +#endif /* CONFIG_NO_TKIP */ +#ifdef CONFIG_WPS_TESTING + if (wps_force_auth_types_in_use) { + wpa_printf(MSG_DEBUG, + "WPS: Testing - replace auth type 0x%x with 0x%x", + auth_types, wps_force_auth_types); + auth_types = wps_force_auth_types; + } +#endif /* CONFIG_WPS_TESTING */ + wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags (0x%x)", + auth_types); wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, auth_types); @@ -288,10 +339,20 @@ int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) { u16 encr_types = WPS_ENCR_TYPES; -#ifdef CONFIG_WPS2 encr_types &= ~WPS_ENCR_WEP; -#endif /* CONFIG_WPS2 */ - wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags"); +#ifdef CONFIG_NO_TKIP + encr_types &= ~WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ +#ifdef CONFIG_WPS_TESTING + if (wps_force_encr_types_in_use) { + wpa_printf(MSG_DEBUG, + "WPS: Testing - replace encr type 0x%x with 0x%x", + encr_types, wps_force_encr_types); + encr_types = wps_force_encr_types; + } +#endif /* CONFIG_WPS_TESTING */ + wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags (0x%x)", + encr_types); wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, encr_types); @@ -301,7 +362,7 @@ int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); + wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, WPS_CONN_ESS); @@ -311,7 +372,7 @@ int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * Association State"); + wpa_printf(MSG_DEBUG, "WPS: * Association State"); wpabuf_put_be16(msg, ATTR_ASSOC_STATE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); @@ -323,9 +384,11 @@ int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) { u8 hash[SHA256_MAC_LEN]; - wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), - wpabuf_len(msg), hash); + wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); + if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), + wpabuf_len(msg), hash) < 0) + return -1; + wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); wpabuf_put_be16(msg, WPS_KWA_LEN); wpabuf_put_data(msg, hash, WPS_KWA_LEN); @@ -340,7 +403,7 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, const size_t block_size = 16; u8 *iv, *data; - wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); + wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); /* PKCS#5 v2.0 pad */ pad_len = block_size - wpabuf_len(plain) % block_size; @@ -355,9 +418,9 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, data = wpabuf_put(msg, 0); wpabuf_put_buf(msg, plain); - wpa_printf(MSG_DEBUG, "WPS: * AES 128 Encrypted Settings"); if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) return -1; + return 0; } @@ -371,14 +434,32 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, const u8 *addr[1]; u8 pubkey_hash[WPS_HASH_LEN]; + wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password (dev_pw_id=%u)", + dev_pw_id); addr[0] = wpabuf_head(pubkey); hash_len = wpabuf_len(pubkey); - sha256_vector(1, addr, &hash_len, pubkey_hash); + if (sha256_vector(1, addr, &hash_len, pubkey_hash) < 0) + return -1; +#ifdef CONFIG_WPS_TESTING + if (wps_corrupt_pkhash) { + wpa_hexdump(MSG_DEBUG, "WPS: Real Public Key Hash", + pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); + wpa_printf(MSG_INFO, "WPS: Testing - corrupt public key hash"); + pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN - 2]++; + } +#endif /* CONFIG_WPS_TESTING */ + wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len); + wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash", + pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); wpabuf_put_be16(msg, dev_pw_id); - wpabuf_put_data(msg, dev_pw, dev_pw_len); + if (dev_pw) { + wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password", + dev_pw, dev_pw_len); + wpabuf_put_data(msg, dev_pw, dev_pw_len); + } return 0; } @@ -415,3 +496,34 @@ struct wpabuf * wps_ie_encapsulate(struct wpabuf *data) return ie; } + + +int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr) +{ + wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", + MAC2STR(addr)); + wpabuf_put_be16(msg, ATTR_MAC_ADDR); + wpabuf_put_be16(msg, ETH_ALEN); + wpabuf_put_data(msg, addr, ETH_ALEN); + return 0; +} + + +int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands) +{ + wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", rf_bands); + wpabuf_put_be16(msg, ATTR_RF_BANDS); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, rf_bands); + return 0; +} + + +int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel) +{ + wpa_printf(MSG_DEBUG, "WPS: * AP Channel (%u)", ap_channel); + wpabuf_put_be16(msg, ATTR_AP_CHANNEL); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, ap_channel); + return 0; +} diff --git a/components/wpa_supplicant/src/wps/wps_attr_parse.c b/components/wpa_supplicant/src/wps/wps_attr_parse.c index 4d1a56fc73..fd51635158 100644 --- a/components/wpa_supplicant/src/wps/wps_attr_parse.c +++ b/components/wpa_supplicant/src/wps/wps_attr_parse.c @@ -5,11 +5,12 @@ * This software may be distributed under the terms of the BSD license. * See README for more details. */ -#include "utils/includes.h" -#include "utils/common.h" -#include "wps/wps_defs.h" -#include "wps/wps_attr_parse.h" +#include "includes.h" + +#include "common.h" +#include "wps_defs.h" +#include "wps_attr_parse.h" #ifndef CONFIG_WPS_STRICT #define WPS_WORKAROUNDS @@ -19,12 +20,12 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr, u8 id, u8 len, const u8 *pos) { - wpa_printf(MSG_MSGDUMP, "WPS: WFA subelement id=%u len=%u", + wpa_printf(MSG_EXCESSIVE, "WPS: WFA subelement id=%u len=%u", id, len); switch (id) { case WFA_ELEM_VERSION2: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length " + wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length " "%u", len); return -1; } @@ -36,7 +37,7 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr, break; case WFA_ELEM_NETWORK_KEY_SHAREABLE: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key " + wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key " "Shareable length %u", len); return -1; } @@ -44,7 +45,7 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr, break; case WFA_ELEM_REQUEST_TO_ENROLL: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll " + wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll " "length %u", len); return -1; } @@ -52,14 +53,33 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr, break; case WFA_ELEM_SETTINGS_DELAY_TIME: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay " + wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay " "Time length %u", len); return -1; } attr->settings_delay_time = pos; break; + case WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Configuration Methods length %u", + len); + return -1; + } + attr->registrar_configuration_methods = pos; + break; + case WFA_ELEM_MULTI_AP: + if (len != 1) { + wpa_printf(MSG_DEBUG, + "WPS: Invalid Multi-AP Extension length %u", + len); + return -1; + } + attr->multi_ap_ext = *pos; + wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x", + attr->multi_ap_ext); + break; default: - wpa_printf(MSG_DEBUG, "WPS: Skipped unknown WFA Vendor " + wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor " "Extension subelement %u", id); break; } @@ -74,10 +94,10 @@ static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos, const u8 *end = pos + len; u8 id, elen; - while (pos + 2 < end) { + while (end - pos >= 2) { id = *pos++; elen = *pos++; - if (pos + elen > end) + if (elen > end - pos) break; if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0) return -1; @@ -94,7 +114,7 @@ static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos, u32 vendor_id; if (len < 3) { - wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension"); + wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension"); return 0; } @@ -106,17 +126,17 @@ static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos, /* Handle unknown vendor extensions */ - wpa_printf(MSG_DEBUG, "WPS: Unknown Vendor Extension (Vendor ID %u)", + wpa_printf(MSG_MSGDUMP, "WPS: Unknown Vendor Extension (Vendor ID %u)", vendor_id); if (len > WPS_MAX_VENDOR_EXT_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)", + wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)", len); return -1; } if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) { - wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension " + wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension " "attribute (max %d vendor extensions)", MAX_WPS_PARSE_VENDOR_EXT); return -1; @@ -128,13 +148,14 @@ static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos, return 0; } + static int wps_set_attr(struct wps_parse_attr *attr, u16 type, const u8 *pos, u16 len) { switch (type) { case ATTR_VERSION: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", + wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", len); return -1; } @@ -142,7 +163,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_MSG_TYPE: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " "length %u", len); return -1; } @@ -150,7 +171,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_ENROLLEE_NONCE: if (len != WPS_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " + wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " "length %u", len); return -1; } @@ -158,7 +179,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_REGISTRAR_NONCE: if (len != WPS_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " + wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " "length %u", len); return -1; } @@ -166,7 +187,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_UUID_E: if (len != WPS_UUID_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", + wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", len); return -1; } @@ -174,7 +195,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_UUID_R: if (len != WPS_UUID_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", + wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", len); return -1; } @@ -182,7 +203,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_AUTH_TYPE_FLAGS: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " + wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " "Type Flags length %u", len); return -1; } @@ -190,7 +211,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_ENCR_TYPE_FLAGS: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " + wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " "Flags length %u", len); return -1; } @@ -198,7 +219,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_CONN_TYPE_FLAGS: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " + wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " "Flags length %u", len); return -1; } @@ -206,7 +227,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_CONFIG_METHODS: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " + wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " "length %u", len); return -1; } @@ -214,7 +235,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " + wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " "Registrar Config Methods length %u", len); return -1; } @@ -222,7 +243,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_PRIMARY_DEV_TYPE: if (len != WPS_DEV_TYPE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " + wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " "Type length %u", len); return -1; } @@ -230,7 +251,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_RF_BANDS: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " + wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " "%u", len); return -1; } @@ -238,7 +259,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_ASSOC_STATE: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " + wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " "length %u", len); return -1; } @@ -246,7 +267,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_CONFIG_ERROR: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " + wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " "Error length %u", len); return -1; } @@ -254,18 +275,21 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_DEV_PASSWORD_ID: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " + wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " "ID length %u", len); return -1; } attr->dev_password_id = pos; break; case ATTR_OOB_DEVICE_PASSWORD: - if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 + - WPS_OOB_DEVICE_PASSWORD_MIN_LEN || + if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 || len > WPS_OOB_PUBKEY_HASH_LEN + 2 + - WPS_OOB_DEVICE_PASSWORD_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " + WPS_OOB_DEVICE_PASSWORD_LEN || + (len < WPS_OOB_PUBKEY_HASH_LEN + 2 + + WPS_OOB_DEVICE_PASSWORD_MIN_LEN && + WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) != + DEV_PW_NFC_CONNECTION_HANDOVER)) { + wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " "Password length %u", len); return -1; } @@ -274,7 +298,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_OS_VERSION: if (len != 4) { - wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " + wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " "%u", len); return -1; } @@ -282,7 +306,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_WPS_STATE: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " + wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " "Setup State length %u", len); return -1; } @@ -290,7 +314,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_AUTHENTICATOR: if (len != WPS_AUTHENTICATOR_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " + wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " "length %u", len); return -1; } @@ -298,7 +322,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_R_HASH1: if (len != WPS_HASH_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", + wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", len); return -1; } @@ -306,7 +330,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_R_HASH2: if (len != WPS_HASH_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", + wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", len); return -1; } @@ -314,7 +338,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_E_HASH1: if (len != WPS_HASH_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", + wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", len); return -1; } @@ -322,7 +346,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_E_HASH2: if (len != WPS_HASH_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", + wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", len); return -1; } @@ -330,7 +354,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_R_SNONCE1: if (len != WPS_SECRET_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " + wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " "%u", len); return -1; } @@ -338,7 +362,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_R_SNONCE2: if (len != WPS_SECRET_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " + wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " "%u", len); return -1; } @@ -346,7 +370,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_E_SNONCE1: if (len != WPS_SECRET_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " + wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " "%u", len); return -1; } @@ -354,7 +378,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_E_SNONCE2: if (len != WPS_SECRET_NONCE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " + wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " "%u", len); return -1; } @@ -362,7 +386,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_KEY_WRAP_AUTH: if (len != WPS_KWA_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " + wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " "Authenticator length %u", len); return -1; } @@ -370,7 +394,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_AUTH_TYPE: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " + wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " "Type length %u", len); return -1; } @@ -378,7 +402,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_ENCR_TYPE: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " + wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " "Type length %u", len); return -1; } @@ -386,7 +410,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_NETWORK_INDEX: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " + wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " "length %u", len); return -1; } @@ -394,7 +418,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_NETWORK_KEY_INDEX: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " + wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " "length %u", len); return -1; } @@ -402,31 +426,15 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_MAC_ADDR: if (len != ETH_ALEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " + wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " "length %u", len); return -1; } attr->mac_addr = pos; break; - case ATTR_KEY_PROVIDED_AUTO: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided " - "Automatically length %u", len); - return -1; - } - attr->key_prov_auto = pos; - break; - case ATTR_802_1X_ENABLED: - if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled " - "length %u", len); - return -1; - } - attr->dot1x_enabled = pos; - break; case ATTR_SELECTED_REGISTRAR: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" + wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" " length %u", len); return -1; } @@ -434,7 +442,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_REQUEST_TYPE: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " + wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " "length %u", len); return -1; } @@ -442,7 +450,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_RESPONSE_TYPE: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " + wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " "length %u", len); return -1; } @@ -450,25 +458,55 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_MANUFACTURER: attr->manufacturer = pos; - attr->manufacturer_len = len; + if (len > WPS_MANUFACTURER_MAX_LEN) + attr->manufacturer_len = WPS_MANUFACTURER_MAX_LEN; + else + attr->manufacturer_len = len; break; case ATTR_MODEL_NAME: attr->model_name = pos; - attr->model_name_len = len; + if (len > WPS_MODEL_NAME_MAX_LEN) + attr->model_name_len = WPS_MODEL_NAME_MAX_LEN; + else + attr->model_name_len = len; break; case ATTR_MODEL_NUMBER: attr->model_number = pos; - attr->model_number_len = len; + if (len > WPS_MODEL_NUMBER_MAX_LEN) + attr->model_number_len = WPS_MODEL_NUMBER_MAX_LEN; + else + attr->model_number_len = len; break; case ATTR_SERIAL_NUMBER: attr->serial_number = pos; - attr->serial_number_len = len; + if (len > WPS_SERIAL_NUMBER_MAX_LEN) + attr->serial_number_len = WPS_SERIAL_NUMBER_MAX_LEN; + else + attr->serial_number_len = len; break; case ATTR_DEV_NAME: + if (len > WPS_DEV_NAME_MAX_LEN) { + wpa_printf(MSG_DEBUG, + "WPS: Ignore too long Device Name (len=%u)", + len); + break; + } attr->dev_name = pos; attr->dev_name_len = len; break; case ATTR_PUBLIC_KEY: + /* + * The Public Key attribute is supposed to be exactly 192 bytes + * in length. Allow couple of bytes shorter one to try to + * interoperate with implementations that do not use proper + * zero-padding. + */ + if (len < 190 || len > 192) { + wpa_printf(MSG_DEBUG, + "WPS: Ignore Public Key with unexpected length %u", + len); + break; + } attr->public_key = pos; attr->public_key_len = len; break; @@ -478,7 +516,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_CRED: if (attr->num_cred >= MAX_CRED_COUNT) { - wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " + wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " "attribute (max %d credentials)", MAX_CRED_COUNT); break; @@ -488,6 +526,11 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, attr->num_cred++; break; case ATTR_SSID: + if (len > SSID_MAX_LEN) { + wpa_printf(MSG_DEBUG, + "WPS: Ignore too long SSID (len=%u)", len); + break; + } attr->ssid = pos; attr->ssid_len = len; break; @@ -495,17 +538,9 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, attr->network_key = pos; attr->network_key_len = len; break; - case ATTR_EAP_TYPE: - attr->eap_type = pos; - attr->eap_type_len = len; - break; - case ATTR_EAP_IDENTITY: - attr->eap_identity = pos; - attr->eap_identity_len = len; - break; case ATTR_AP_SETUP_LOCKED: if (len != 1) { - wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " + wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " "length %u", len); return -1; } @@ -513,12 +548,12 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_REQUESTED_DEV_TYPE: if (len != WPS_DEV_TYPE_LEN) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device " + wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device " "Type length %u", len); return -1; } if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) { - wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device " + wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device " "Type attribute (max %u types)", MAX_REQ_DEV_TYPE_COUNT); break; @@ -529,7 +564,7 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, case ATTR_SECONDARY_DEV_TYPE_LIST: if (len > WPS_SEC_DEV_TYPE_MAX_LEN || (len % WPS_DEV_TYPE_LEN) > 0) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device " + wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device " "Type length %u", len); return -1; } @@ -542,14 +577,14 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type, break; case ATTR_AP_CHANNEL: if (len != 2) { - wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel " + wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel " "length %u", len); return -1; } attr->ap_channel = pos; break; default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " + wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " "len=%u", type, len); break; } @@ -572,7 +607,7 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) while (pos < end) { if (end - pos < 4) { - wpa_printf(MSG_DEBUG, "WPS: Invalid message - " + wpa_printf(MSG_DEBUG, "WPS: Invalid message - " "%lu bytes remaining", (unsigned long) (end - pos)); return -1; @@ -582,10 +617,10 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) pos += 2; len = WPA_GET_BE16(pos); pos += 2; - wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u", + wpa_printf(MSG_EXCESSIVE, "WPS: attr type=0x%x len=%u", type, len); if (len > end - pos) { - wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); + wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg); #ifdef WPS_WORKAROUNDS /* @@ -597,7 +632,7 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) */ if ((type & 0xff00) != 0x1000 && prev_type == ATTR_NETWORK_KEY) { - wpa_printf(MSG_DEBUG, "WPS: Workaround - try " + wpa_printf(MSG_DEBUG, "WPS: Workaround - try " "to skip unexpected octet after " "Network Key"); pos -= 3; @@ -619,7 +654,7 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) break; } if (i == end - pos) { - wpa_printf(MSG_DEBUG, "WPS: Workaround - skip " + wpa_printf(MSG_DEBUG, "WPS: Workaround - skip " "unexpected message padding"); break; } diff --git a/components/wpa_supplicant/src/wps/wps_attr_parse.h b/components/wpa_supplicant/src/wps/wps_attr_parse.h index 86061aea06..4de27b26d4 100644 --- a/components/wpa_supplicant/src/wps/wps_attr_parse.h +++ b/components/wpa_supplicant/src/wps/wps_attr_parse.h @@ -9,7 +9,7 @@ #ifndef WPS_ATTR_PARSE_H #define WPS_ATTR_PARSE_H -#include "wps/wps.h" +#include "wps.h" struct wps_parse_attr { /* fixed length fields */ @@ -47,8 +47,6 @@ struct wps_parse_attr { const u8 *network_idx; /* 1 octet */ const u8 *network_key_idx; /* 1 octet */ const u8 *mac_addr; /* ETH_ALEN (6) octets */ - const u8 *key_prov_auto; /* 1 octet (Bool) */ - const u8 *dot1x_enabled; /* 1 octet (Bool) */ const u8 *selected_registrar; /* 1 octet (Bool) */ const u8 *request_type; /* 1 octet */ const u8 *response_type; /* 1 octet */ @@ -57,50 +55,49 @@ struct wps_parse_attr { const u8 *network_key_shareable; /* 1 octet (Bool) */ const u8 *request_to_enroll; /* 1 octet (Bool) */ const u8 *ap_channel; /* 2 octets */ + const u8 *registrar_configuration_methods; /* 2 octets */ /* variable length fields */ const u8 *manufacturer; - size_t manufacturer_len; const u8 *model_name; - size_t model_name_len; const u8 *model_number; - size_t model_number_len; const u8 *serial_number; - size_t serial_number_len; const u8 *dev_name; - size_t dev_name_len; const u8 *public_key; - size_t public_key_len; const u8 *encr_settings; - size_t encr_settings_len; const u8 *ssid; /* <= 32 octets */ - size_t ssid_len; const u8 *network_key; /* <= 64 octets */ - size_t network_key_len; - const u8 *eap_type; /* <= 8 octets */ - size_t eap_type_len; - const u8 *eap_identity; /* <= 64 octets */ - size_t eap_identity_len; const u8 *authorized_macs; /* <= 30 octets */ - size_t authorized_macs_len; const u8 *sec_dev_type_list; /* <= 128 octets */ - size_t sec_dev_type_list_len; const u8 *oob_dev_password; /* 38..54 octets */ - size_t oob_dev_password_len; + u16 manufacturer_len; + u16 model_name_len; + u16 model_number_len; + u16 serial_number_len; + u16 dev_name_len; + u16 public_key_len; + u16 encr_settings_len; + u16 ssid_len; + u16 network_key_len; + u16 authorized_macs_len; + u16 sec_dev_type_list_len; + u16 oob_dev_password_len; /* attributes that can occur multiple times */ #define MAX_CRED_COUNT 10 - const u8 *cred[MAX_CRED_COUNT]; - size_t cred_len[MAX_CRED_COUNT]; - size_t num_cred; - #define MAX_REQ_DEV_TYPE_COUNT 10 - const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT]; - size_t num_req_dev_type; + unsigned int num_cred; + unsigned int num_req_dev_type; + unsigned int num_vendor_ext; + + u16 cred_len[MAX_CRED_COUNT]; + u16 vendor_ext_len[MAX_WPS_PARSE_VENDOR_EXT]; + + const u8 *cred[MAX_CRED_COUNT]; + const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT]; const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT]; - size_t vendor_ext_len[MAX_WPS_PARSE_VENDOR_EXT]; - size_t num_vendor_ext; + u8 multi_ap_ext; }; int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); diff --git a/components/wpa_supplicant/src/wps/wps_attr_process.c b/components/wpa_supplicant/src/wps/wps_attr_process.c index c298df3f69..44436a4862 100644 --- a/components/wpa_supplicant/src/wps/wps_attr_process.c +++ b/components/wpa_supplicant/src/wps/wps_attr_process.c @@ -5,11 +5,12 @@ * This software may be distributed under the terms of the BSD license. * See README for more details. */ -#include "utils/includes.h" -#include "utils/common.h" +#include "includes.h" + +#include "common.h" #include "crypto/sha256.h" -#include "wps/wps_i.h" +#include "wps_i.h" int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, @@ -20,13 +21,13 @@ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, size_t len[2]; if (authenticator == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute " + wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute " "included"); return -1; } if (wps->last_msg == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Last message not available for " + wpa_printf(MSG_DEBUG, "WPS: Last message not available for " "validating authenticator"); return -1; } @@ -38,9 +39,11 @@ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, len[0] = wpabuf_len(wps->last_msg); addr[1] = wpabuf_head(msg); len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN; - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); - if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator"); + + if (hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, + hash) < 0 || + os_memcmp_const(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator"); return -1; } @@ -56,21 +59,21 @@ int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, size_t len; if (key_wrap_auth == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute"); + wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute"); return -1; } head = wpabuf_head(msg); len = wpabuf_len(msg) - 4 - WPS_KWA_LEN; if (head + len != key_wrap_auth - 4) { - wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the " + wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the " "decrypted attribute"); return -1; } - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash); - if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Invalid KWA"); + if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash) < 0 || + os_memcmp_const(hash, key_wrap_auth, WPS_KWA_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Invalid KWA"); return -1; } @@ -82,12 +85,12 @@ static int wps_process_cred_network_idx(struct wps_credential *cred, const u8 *idx) { if (idx == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Network Index"); return -1; } - wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx); + wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx); return 0; } @@ -97,7 +100,7 @@ static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid, size_t ssid_len) { if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID"); + wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID"); return -1; } @@ -120,13 +123,13 @@ static int wps_process_cred_auth_type(struct wps_credential *cred, const u8 *auth_type) { if (auth_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Authentication Type"); return -1; } cred->auth_type = WPA_GET_BE16(auth_type); - wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x", + wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x", cred->auth_type); return 0; @@ -137,13 +140,13 @@ static int wps_process_cred_encr_type(struct wps_credential *cred, const u8 *encr_type) { if (encr_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Encryption Type"); return -1; } cred->encr_type = WPA_GET_BE16(encr_type); - wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x", + wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x", cred->encr_type); return 0; @@ -156,7 +159,7 @@ static int wps_process_cred_network_key_idx(struct wps_credential *cred, if (key_idx == NULL) return 0; /* optional attribute */ - wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx); + wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx); cred->key_idx = *key_idx; return 0; @@ -167,11 +170,11 @@ static int wps_process_cred_network_key(struct wps_credential *cred, const u8 *key, size_t key_len) { if (key == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Network Key"); - if (cred->auth_type == WPS_WIFI_AUTH_OPEN && + if (cred->auth_type == WPS_AUTH_OPEN && cred->encr_type == WPS_ENCR_NONE) { - wpa_printf(MSG_DEBUG, "WPS: Workaround - Allow " + wpa_printf(MSG_DEBUG, "WPS: Workaround - Allow " "missing mandatory Network Key attribute " "for open network"); return 0; @@ -193,82 +196,18 @@ static int wps_process_cred_mac_addr(struct wps_credential *cred, const u8 *mac_addr) { if (mac_addr == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "MAC Address"); return -1; } - wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr)); + wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr)); os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN); return 0; } -static int wps_process_cred_eap_type(struct wps_credential *cred, - const u8 *eap_type, size_t eap_type_len) -{ - if (eap_type == NULL) - return 0; /* optional attribute */ - - wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len); - - return 0; -} - - -static int wps_process_cred_eap_identity(struct wps_credential *cred, - const u8 *identity, - size_t identity_len) -{ - if (identity == NULL) - return 0; /* optional attribute */ - - wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity", - identity, identity_len); - - return 0; -} - - -static int wps_process_cred_key_prov_auto(struct wps_credential *cred, - const u8 *key_prov_auto) -{ - if (key_prov_auto == NULL) - return 0; /* optional attribute */ - - wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d", - *key_prov_auto); - - return 0; -} - - -static int wps_process_cred_802_1x_enabled(struct wps_credential *cred, - const u8 *dot1x_enabled) -{ - if (dot1x_enabled == NULL) - return 0; /* optional attribute */ - - wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled); - - return 0; -} - - -static int wps_process_cred_ap_channel(struct wps_credential *cred, - const u8 *ap_channel) -{ - if (ap_channel == NULL) - return 0; /* optional attribute */ - - cred->ap_channel = WPA_GET_BE16(ap_channel); - wpa_printf(MSG_DEBUG, "WPS: AP Channel: %u", cred->ap_channel); - - return 0; -} - - static int wps_workaround_cred_key(struct wps_credential *cred) { if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) && @@ -286,11 +225,21 @@ static int wps_workaround_cred_key(struct wps_credential *cred) * passphrases incorrectly. Remove the extra NULL termination * to fix the encoding. */ - wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL " + wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL " "termination from ASCII passphrase"); cred->key_len--; #endif /* CONFIG_WPS_STRICT */ } + + + if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) && + (cred->key_len < 8 || has_ctrl_char(cred->key, cred->key_len))) { + wpa_printf(MSG_INFO, "WPS: Reject credential with invalid WPA/WPA2-Personal passphrase"); + wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key", + cred->key, cred->key_len); + return -1; + } + return 0; } @@ -298,7 +247,7 @@ static int wps_workaround_cred_key(struct wps_credential *cred) int wps_process_cred(struct wps_parse_attr *attr, struct wps_credential *cred) { - wpa_printf(MSG_DEBUG, "WPS: Process Credential"); + wpa_printf(MSG_DEBUG, "WPS: Process Credential"); /* TODO: support multiple Network Keys */ if (wps_process_cred_network_idx(cred, attr->network_idx) || @@ -308,14 +257,7 @@ int wps_process_cred(struct wps_parse_attr *attr, wps_process_cred_network_key_idx(cred, attr->network_key_idx) || wps_process_cred_network_key(cred, attr->network_key, attr->network_key_len) || - wps_process_cred_mac_addr(cred, attr->mac_addr) || - wps_process_cred_eap_type(cred, attr->eap_type, - attr->eap_type_len) || - wps_process_cred_eap_identity(cred, attr->eap_identity, - attr->eap_identity_len) || - wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) || - wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled) || - wps_process_cred_ap_channel(cred, attr->ap_channel)) + wps_process_cred_mac_addr(cred, attr->mac_addr)) return -1; return wps_workaround_cred_key(cred); @@ -325,7 +267,7 @@ int wps_process_cred(struct wps_parse_attr *attr, int wps_process_ap_settings(struct wps_parse_attr *attr, struct wps_credential *cred) { - wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings"); + wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings"); os_memset(cred, 0, sizeof(*cred)); /* TODO: optional attributes New Password and Device Password ID */ if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || diff --git a/components/wpa_supplicant/src/wps/wps_common.c b/components/wpa_supplicant/src/wps/wps_common.c index ead31af3e0..4835d4a15c 100644 --- a/components/wpa_supplicant/src/wps/wps_common.c +++ b/components/wpa_supplicant/src/wps/wps_common.c @@ -5,19 +5,21 @@ * This software may be distributed under the terms of the BSD license. * See README for more details. */ -#include -#include "utils/includes.h" -#include "utils/common.h" +#include "includes.h" +#include "common.h" +#include "common/defs.h" +#include "common/ieee802_11_common.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" +#include "crypto/dh_group5.h" #include "crypto/sha1.h" #include "crypto/sha256.h" -#include "crypto/dh_group5.h" #include "crypto/random.h" +#include "wps_i.h" +#include "wps_dev_attr.h" -#include "wps/wps_i.h" void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, const char *label, u8 *res, size_t res_len) @@ -66,13 +68,13 @@ int wps_derive_keys(struct wps_data *wps) u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; if (wps->dh_privkey == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); + wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); return -1; } pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; if (pubkey == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); + wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); return -1; } @@ -83,17 +85,17 @@ int wps_derive_keys(struct wps_data *wps) wps->dh_ctx = NULL; dh_shared = wpabuf_zeropad(dh_shared, 192); if (dh_shared == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); + wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); return -1; } /* Own DH private key is not needed anymore */ -/* - * due to the public key calculated when wps start, it will not calculate anymore even when we build M1 message, also calculate the key need take a long time - * which would cause WPS fail, so we clean the key after WPS finished . - */ + /* + * due to the public key calculated when wps start, it will not calculate anymore even when we build M1 message, also calculate the key need take a long time + * which would cause WPS fail, so we clean the key after WPS finished . + */ #ifndef ESP32_WORKAROUND - wpabuf_free(wps->dh_privkey); + wpabuf_clear_free(wps->dh_privkey); wps->dh_privkey = NULL; #endif //ESP32_WORKAROUND @@ -102,10 +104,9 @@ int wps_derive_keys(struct wps_data *wps) /* DHKey = SHA-256(g^AB mod p) */ addr[0] = wpabuf_head(dh_shared); len[0] = wpabuf_len(dh_shared); - sha256_vector(1, addr, len, dhkey); wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); - wpabuf_free(dh_shared); + wpabuf_clear_free(dh_shared); /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ addr[0] = wps->nonce_e; @@ -134,23 +135,26 @@ int wps_derive_keys(struct wps_data *wps) } -void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, - size_t dev_passwd_len) +int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, + size_t dev_passwd_len) { u8 hash[SHA256_MAC_LEN]; - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, - (dev_passwd_len + 1) / 2, hash); + if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, + (dev_passwd_len + 1) / 2, hash) < 0) + return -1; os_memcpy(wps->psk1, hash, WPS_PSK_LEN); - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, - dev_passwd + (dev_passwd_len + 1) / 2, - dev_passwd_len / 2, hash); + if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, + dev_passwd + (dev_passwd_len + 1) / 2, + dev_passwd_len / 2, hash) < 0) + return -1; os_memcpy(wps->psk2, hash, WPS_PSK_LEN); wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", dev_passwd, dev_passwd_len); wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); + return 0; } @@ -166,7 +170,7 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, /* AES-128-CBC */ if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) { - wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); + wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); return NULL; } @@ -176,10 +180,9 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); - wpa_printf(MSG_DEBUG, "WPS: AES Decrypt setting"); if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), - wpabuf_len(decrypted))) { - wpabuf_free(decrypted); + wpabuf_len(decrypted))) { + wpabuf_clear_free(decrypted); return NULL; } @@ -189,15 +192,15 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; pad = *pos; if (pad > wpabuf_len(decrypted)) { - wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); - wpabuf_free(decrypted); + wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); + wpabuf_clear_free(decrypted); return NULL; } for (i = 0; i < pad; i++) { if (*pos-- != pad) { - wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " + wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " "string"); - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); return NULL; } } @@ -206,7 +209,7 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, return decrypted; } -#ifdef CONFIG_WPS_PIN + /** * wps_pin_checksum - Compute PIN checksum * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) @@ -241,18 +244,18 @@ unsigned int wps_pin_valid(unsigned int pin) * wps_generate_pin - Generate a random PIN * Returns: Eight digit PIN (i.e., including the checksum digit) */ -unsigned int wps_generate_pin(void) +int wps_generate_pin(unsigned int *pin) { unsigned int val; /* Generate seven random digits for the PIN */ - if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) { + if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) return -1; - } val %= 10000000; /* Append checksum digit */ - return val * 10 + wps_pin_checksum(val); + *pin = val * 10 + wps_pin_checksum(val); + return 0; } @@ -270,58 +273,51 @@ int wps_pin_str_valid(const char *pin) len = p - pin; return len == 4 || len == 8; } -#endif + void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, - u16 config_error, u16 error_indication) + u16 config_error, u16 error_indication, const u8 *mac_addr) { - union wps_event_data *data; + union wps_event_data data; - data = (union wps_event_data *)os_zalloc(sizeof(union wps_event_data)); - if (data == NULL) - return; - - if (wps->event_cb == NULL) { - os_free(data); - return; - } - - os_memset(data, 0, sizeof(union wps_event_data)); - data->fail.msg = msg; - data->fail.config_error = config_error; - data->fail.error_indication = error_indication; - wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, data); - os_free(data); -} - - -void wps_success_event(struct wps_context *wps) -{ if (wps->event_cb == NULL) return; - wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL); + os_memset(&data, 0, sizeof(data)); + data.fail.msg = msg; + data.fail.config_error = config_error; + data.fail.error_indication = error_indication; + os_memcpy(data.fail.peer_macaddr, mac_addr, ETH_ALEN); + wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); } -void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part) +void wps_success_event(struct wps_context *wps, const u8 *mac_addr) { - union wps_event_data *data; + union wps_event_data data; - data = (union wps_event_data *)os_zalloc(sizeof(union wps_event_data)); - if (data == NULL) + if (wps->event_cb == NULL) return; - if (wps->event_cb == NULL) { - os_free(data); - return; - } + os_memset(&data, 0, sizeof(data)); + os_memcpy(data.success.peer_macaddr, mac_addr, ETH_ALEN); + wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, &data); +} - os_memset(data, 0, sizeof(union wps_event_data)); - data->pwd_auth_fail.enrollee = enrollee; - data->pwd_auth_fail.part = part; - wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, data); - os_free(data); + +void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part, + const u8 *mac_addr) +{ + union wps_event_data data; + + if (wps->event_cb == NULL) + return; + + os_memset(&data, 0, sizeof(data)); + data.pwd_auth_fail.enrollee = enrollee; + data.pwd_auth_fail.part = part; + os_memcpy(data.pwd_auth_fail.peer_macaddr, mac_addr, ETH_ALEN); + wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); } @@ -343,38 +339,78 @@ void wps_pbc_timeout_event(struct wps_context *wps) } +void wps_pbc_active_event(struct wps_context *wps) +{ + if (wps->event_cb == NULL) + return; + + wps->event_cb(wps->cb_ctx, WPS_EV_PBC_ACTIVE, NULL); +} + + +void wps_pbc_disable_event(struct wps_context *wps) +{ + if (wps->event_cb == NULL) + return; + + wps->event_cb(wps->cb_ctx, WPS_EV_PBC_DISABLE, NULL); +} + + #ifdef CONFIG_WPS_OOB -struct wpabuf * wps_get_oob_cred(struct wps_context *wps) +struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, + int channel) { - struct wps_data *data; + struct wps_data data; struct wpabuf *plain; - data = (struct wps_data *)os_zalloc(sizeof(struct wps_data)); - if (data == NULL) - return NULL; - plain = wpabuf_alloc(500); if (plain == NULL) { - os_free(data); - wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " + wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "credential"); return NULL; } - os_memset(data, 0, sizeof(struct wps_data)); - data->wps = wps; - data->auth_type = wps->auth_types; - data->encr_type = wps->encr_types; - if (wps_build_version(plain) || - wps_build_cred(data, plain) || - wps_build_wfa_ext(plain, 0, NULL, 0)) { - wpabuf_free(plain); - os_free(data); + os_memset(&data, 0, sizeof(data)); + data.wps = wps; + data.auth_type = wps->auth_types; + data.encr_type = wps->encr_types; + if (wps_build_cred(&data, plain) || + (rf_band && wps_build_rf_bands_attr(plain, rf_band)) || + (channel && wps_build_ap_channel(plain, channel)) || + wps_build_mac_addr(plain, wps->dev.mac_addr) || + wps_build_wfa_ext(plain, 0, NULL, 0, 0)) { + os_free(data.new_psk); + wpabuf_clear_free(plain); return NULL; } - os_free(data); + if (wps->wps_state == WPS_STATE_NOT_CONFIGURED && data.new_psk && + wps->ap) { + struct wps_credential cred; + + wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " + "on credential token generation"); + + os_memset(&cred, 0, sizeof(cred)); + os_memcpy(cred.ssid, wps->ssid, wps->ssid_len); + cred.ssid_len = wps->ssid_len; + cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; + cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; + os_memcpy(cred.key, data.new_psk, data.new_psk_len); + cred.key_len = data.new_psk_len; + + wps->wps_state = WPS_STATE_CONFIGURED; + wpa_hexdump_ascii_key(MSG_DEBUG, + "WPS: Generated random passphrase", + data.new_psk, data.new_psk_len); + if (wps->cred_cb) + wps->cred_cb(wps->cb_ctx, &cred); + } + + os_free(data.new_psk); + return plain; } @@ -390,13 +426,12 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, if (data == NULL) return NULL; - if (wps_build_version(data) || - wps_build_oob_dev_pw(data, dev_pw_id, pubkey, + if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey, wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || - wps_build_wfa_ext(data, 0, NULL, 0)) { - wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " + wps_build_wfa_ext(data, 0, NULL, 0, 0)) { + wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " "token"); - wpabuf_free(data); + wpabuf_clear_free(data); return NULL; } @@ -418,7 +453,7 @@ int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr) wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]); if (wps_parse_msg(&msg, &cattr) < 0 || wps_process_cred(&cattr, &local_cred)) { - wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " + wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " "credential"); return -1; } @@ -438,13 +473,13 @@ int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) /* -- */ WPA_PUT_BE16(dev_type, atoi(str)); - pos = (char *)os_strchr(str, '-'); + pos = os_strchr(str, '-'); if (pos == NULL) return -1; pos++; if (hexstr2bin(pos, &dev_type[2], 4)) return -1; - pos = (char *)os_strchr(pos, '-'); + pos = os_strchr(pos, '-'); if (pos == NULL) return -1; pos++; @@ -460,10 +495,10 @@ char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, { int ret; - ret = snprintf(buf, buf_len, "%u-%08X-%u", + ret = os_snprintf(buf, buf_len, "%u-%08X-%u", WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), WPA_GET_BE16(&dev_type[6])); - if (ret < 0 || (unsigned int) ret >= buf_len) + if (os_snprintf_error(buf_len, ret)) return NULL; return buf; @@ -502,15 +537,16 @@ u16 wps_config_methods_str2bin(const char *str) { u16 methods = 0; - if (str == NULL) { + if (str == NULL || str[0] == '\0') { /* Default to enabling methods based on build configuration */ methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; -#ifdef CONFIG_WPS2 methods |= WPS_CONFIG_VIRT_DISPLAY; -#endif /* CONFIG_WPS2 */ #ifdef CONFIG_WPS_NFC methods |= WPS_CONFIG_NFC_INTERFACE; #endif /* CONFIG_WPS_NFC */ +#ifdef CONFIG_P2P + methods |= WPS_CONFIG_P2PS; +#endif /* CONFIG_P2P */ } else { if (os_strstr(str, "ethernet")) methods |= WPS_CONFIG_ETHERNET; @@ -528,7 +564,6 @@ u16 wps_config_methods_str2bin(const char *str) methods |= WPS_CONFIG_PUSHBUTTON; if (os_strstr(str, "keypad")) methods |= WPS_CONFIG_KEYPAD; -#ifdef CONFIG_WPS2 if (os_strstr(str, "virtual_display")) methods |= WPS_CONFIG_VIRT_DISPLAY; if (os_strstr(str, "physical_display")) @@ -537,7 +572,8 @@ u16 wps_config_methods_str2bin(const char *str) methods |= WPS_CONFIG_VIRT_PUSHBUTTON; if (os_strstr(str, "physical_push_button")) methods |= WPS_CONFIG_PHY_PUSHBUTTON; -#endif /* CONFIG_WPS2 */ + if (os_strstr(str, "p2ps")) + methods |= WPS_CONFIG_P2PS; } return methods; @@ -548,7 +584,7 @@ struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) { struct wpabuf *msg; - wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); + wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); msg = wpabuf_alloc(1000); if (msg == NULL) @@ -558,7 +594,7 @@ struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) wps_build_msg_type(msg, WPS_WSC_ACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -571,7 +607,7 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) { struct wpabuf *msg; - wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); + wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); msg = wpabuf_alloc(1000); if (msg == NULL) @@ -582,7 +618,7 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_config_error(msg, wps->config_error) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -592,12 +628,60 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) #ifdef CONFIG_WPS_NFC + +struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey, + struct wpabuf *dev_pw) +{ + struct wpabuf *ret; + + if (pubkey == NULL || dev_pw == NULL) + return NULL; + + ret = wps_build_nfc_pw_token(id, pubkey, dev_pw); + if (ndef && ret) { + struct wpabuf *tmp; + tmp = ndef_build_wifi(ret); + wpabuf_free(ret); + if (tmp == NULL) + return NULL; + ret = tmp; + } + + return ret; +} + + +int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey) +{ + struct wpabuf *priv = NULL, *pub = NULL; + void *dh_ctx; + + dh_ctx = dh5_init(&priv, &pub); + if (dh_ctx == NULL) + return -1; + pub = wpabuf_zeropad(pub, 192); + if (pub == NULL) { + wpabuf_free(priv); + dh5_free(dh_ctx); + return -1; + } + wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub); + dh5_free(dh_ctx); + + wpabuf_free(*pubkey); + *pubkey = pub; + wpabuf_clear_free(*privkey); + *privkey = priv; + + return 0; +} + + struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, struct wpabuf **privkey, struct wpabuf **dev_pw) { - struct wpabuf *priv = NULL, *pub = NULL, *pw, *ret; - void *dh_ctx; + struct wpabuf *pw; u16 val; pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN); @@ -611,31 +695,225 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, return NULL; } - dh_ctx = dh5_init(&priv, &pub); - if (dh_ctx == NULL) { + if (wps_nfc_gen_dh(pubkey, privkey) < 0) { wpabuf_free(pw); return NULL; } - dh5_free(dh_ctx); *id = 0x10 + val % 0xfff0; - wpabuf_free(*pubkey); - *pubkey = pub; - wpabuf_free(*privkey); - *privkey = priv; - wpabuf_free(*dev_pw); + wpabuf_clear_free(*dev_pw); *dev_pw = pw; - ret = wps_build_nfc_pw_token(*id, *pubkey, *dev_pw); - if (ndef && ret) { - struct wpabuf *tmp; - tmp = ndef_build_wifi(ret); - wpabuf_free(ret); - if (tmp == NULL) - return NULL; - ret = tmp; + return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw); +} + + +struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey) +{ + struct wpabuf *msg; + void *len; + + if (ctx == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " + "handover request"); + + if (nfc_dh_pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " + "configured"); + return NULL; } - return ret; + msg = wpabuf_alloc(1000); + if (msg == NULL) + return msg; + len = wpabuf_put(msg, 2); + + if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, + nfc_dh_pubkey, NULL, 0) || + wps_build_uuid_e(msg, ctx->uuid) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { + wpabuf_free(msg); + return NULL; + } + + WPA_PUT_BE16(len, wpabuf_len(msg) - 2); + + return msg; } + + +static int wps_build_ssid(struct wpabuf *msg, struct wps_context *wps) +{ + wpa_printf(MSG_DEBUG, "WPS: * SSID"); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID in Connection Handover Select", + wps->ssid, wps->ssid_len); + wpabuf_put_be16(msg, ATTR_SSID); + wpabuf_put_be16(msg, wps->ssid_len); + wpabuf_put_data(msg, wps->ssid, wps->ssid_len); + return 0; +} + + +static int wps_build_ap_freq(struct wpabuf *msg, int freq) +{ + enum hostapd_hw_mode mode; + u8 channel, rf_band; + u16 ap_channel; + + if (freq <= 0) + return 0; + + mode = ieee80211_freq_to_chan(freq, &channel); + if (mode == NUM_HOSTAPD_MODES) + return 0; /* Unknown channel */ + + if (mode == HOSTAPD_MODE_IEEE80211G || mode == HOSTAPD_MODE_IEEE80211B) + rf_band = WPS_RF_24GHZ; + else if (mode == HOSTAPD_MODE_IEEE80211A) + rf_band = WPS_RF_50GHZ; + else if (mode == HOSTAPD_MODE_IEEE80211AD) + rf_band = WPS_RF_60GHZ; + else + return 0; /* Unknown band */ + ap_channel = channel; + + if (wps_build_rf_bands_attr(msg, rf_band) || + wps_build_ap_channel(msg, ap_channel)) + return -1; + + return 0; +} + + +struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey, + const u8 *bssid, int freq) +{ + struct wpabuf *msg; + void *len; + + if (ctx == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " + "handover select"); + + if (nfc_dh_pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " + "configured"); + return NULL; + } + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return msg; + len = wpabuf_put(msg, 2); + + if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, + nfc_dh_pubkey, NULL, 0) || + wps_build_ssid(msg, ctx) || + wps_build_ap_freq(msg, freq) || + (bssid && wps_build_mac_addr(msg, bssid)) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { + wpabuf_free(msg); + return NULL; + } + + WPA_PUT_BE16(len, wpabuf_len(msg) - 2); + + return msg; +} + + +struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey) +{ + struct wpabuf *msg; + + if (ctx == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " + "handover request (P2P)"); + + if (nfc_dh_pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No NFC DH Public Key configured"); + return NULL; + } + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return msg; + + if (wps_build_manufacturer(&ctx->dev, msg) || + wps_build_model_name(&ctx->dev, msg) || + wps_build_model_number(&ctx->dev, msg) || + wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, + nfc_dh_pubkey, NULL, 0) || + wps_build_rf_bands(&ctx->dev, msg, 0) || + wps_build_serial_number(&ctx->dev, msg) || + wps_build_uuid_e(msg, ctx->uuid) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { + wpabuf_free(msg); + return NULL; + } + + return msg; +} + + +struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx, + int nfc_dev_pw_id, + struct wpabuf *nfc_dh_pubkey, + struct wpabuf *nfc_dev_pw) +{ + struct wpabuf *msg; + const u8 *dev_pw; + size_t dev_pw_len; + + if (ctx == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection " + "handover select (P2P)"); + + if (nfc_dh_pubkey == NULL || + (nfc_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && + nfc_dev_pw == NULL)) { + wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password " + "configured"); + return NULL; + } + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return msg; + + if (nfc_dev_pw) { + dev_pw = wpabuf_head(nfc_dev_pw); + dev_pw_len = wpabuf_len(nfc_dev_pw); + } else { + dev_pw = NULL; + dev_pw_len = 0; + } + + if (wps_build_manufacturer(&ctx->dev, msg) || + wps_build_model_name(&ctx->dev, msg) || + wps_build_model_number(&ctx->dev, msg) || + wps_build_oob_dev_pw(msg, nfc_dev_pw_id, nfc_dh_pubkey, + dev_pw, dev_pw_len) || + wps_build_rf_bands(&ctx->dev, msg, 0) || + wps_build_serial_number(&ctx->dev, msg) || + wps_build_uuid_e(msg, ctx->uuid) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { + wpabuf_free(msg); + return NULL; + } + + return msg; +} + #endif /* CONFIG_WPS_NFC */ diff --git a/components/wpa_supplicant/src/wps/wps_defs.h b/components/wpa_supplicant/src/wps/wps_defs.h index 8cce648528..1fd2b353f3 100644 --- a/components/wpa_supplicant/src/wps/wps_defs.h +++ b/components/wpa_supplicant/src/wps/wps_defs.h @@ -12,16 +12,17 @@ #ifdef CONFIG_WPS_TESTING extern int wps_version_number; -extern int wps_testing_dummy_cred; +extern int wps_testing_stub_cred; +extern int wps_corrupt_pkhash; +extern int wps_force_auth_types_in_use; +extern u16 wps_force_auth_types; +extern int wps_force_encr_types_in_use; +extern u16 wps_force_encr_types; #define WPS_VERSION wps_version_number #else /* CONFIG_WPS_TESTING */ -#ifdef CONFIG_WPS2 #define WPS_VERSION 0x20 -#else /* CONFIG_WPS2 */ -#define WPS_VERSION 0x10 -#endif /* CONFIG_WPS2 */ #endif /* CONFIG_WPS_TESTING */ @@ -44,6 +45,11 @@ extern int wps_testing_dummy_cred; #define WPS_OOB_DEVICE_PASSWORD_MIN_LEN 16 #define WPS_OOB_DEVICE_PASSWORD_LEN 32 #define WPS_OOB_PUBKEY_HASH_LEN 20 +#define WPS_DEV_NAME_MAX_LEN 32 +#define WPS_MANUFACTURER_MAX_LEN 64 +#define WPS_MODEL_NAME_MAX_LEN 32 +#define WPS_MODEL_NUMBER_MAX_LEN 32 +#define WPS_SERIAL_NUMBER_MAX_LEN 32 /* Attribute Types */ enum wps_attribute { @@ -145,7 +151,9 @@ enum { WFA_ELEM_AUTHORIZEDMACS = 0x01, WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02, WFA_ELEM_REQUEST_TO_ENROLL = 0x03, - WFA_ELEM_SETTINGS_DELAY_TIME = 0x04 + WFA_ELEM_SETTINGS_DELAY_TIME = 0x04, + WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05, + WFA_ELEM_MULTI_AP = 0x06 }; /* Device Password ID */ @@ -155,13 +163,9 @@ enum wps_dev_password_id { DEV_PW_MACHINE_SPECIFIED = 0x0002, DEV_PW_REKEY = 0x0003, DEV_PW_PUSHBUTTON = 0x0004, - DEV_PW_REGISTRAR_SPECIFIED = 0x0005 -}; - -/* WPS message flag */ -enum wps_msg_flag { - WPS_MSG_FLAG_MORE = 0x01, - WPS_MSG_FLAG_LEN = 0x02 + DEV_PW_REGISTRAR_SPECIFIED = 0x0005, + DEV_PW_NFC_CONNECTION_HANDOVER = 0x0007, + DEV_PW_P2PS_DEFAULT = 0x0008 }; /* Message Type */ @@ -184,18 +188,18 @@ enum wps_msg_type { }; /* Authentication Type Flags */ -#define WPS_WIFI_AUTH_OPEN 0x0001 +#define WPS_AUTH_OPEN 0x0001 #define WPS_AUTH_WPAPSK 0x0002 -#define WPS_AUTH_SHARED 0x0004 +#define WPS_AUTH_SHARED 0x0004 /* deprecated */ #define WPS_AUTH_WPA 0x0008 #define WPS_AUTH_WPA2 0x0010 #define WPS_AUTH_WPA2PSK 0x0020 -#define WPS_AUTH_TYPES (WPS_WIFI_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \ +#define WPS_AUTH_TYPES (WPS_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \ WPS_AUTH_WPA | WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK) /* Encryption Type Flags */ #define WPS_ENCR_NONE 0x0001 -#define WPS_ENCR_WEP 0x0002 +#define WPS_ENCR_WEP 0x0002 /* deprecated */ #define WPS_ENCR_TKIP 0x0004 #define WPS_ENCR_AES 0x0008 #define WPS_ENCR_TYPES (WPS_ENCR_NONE | WPS_ENCR_WEP | WPS_ENCR_TKIP | \ @@ -221,7 +225,9 @@ enum wps_config_error { WPS_CFG_SETUP_LOCKED = 15, WPS_CFG_MSG_TIMEOUT = 16, WPS_CFG_REG_SESS_TIMEOUT = 17, - WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18 + WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18, + WPS_CFG_60G_CHAN_NOT_SUPPORTED = 19, + WPS_CFG_PUBLIC_KEY_HASH_MISMATCH = 20 }; /* Vendor specific Error Indication for WPS event messages */ @@ -229,12 +235,14 @@ enum wps_error_indication { WPS_EI_NO_ERROR, WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED, WPS_EI_SECURITY_WEP_PROHIBITED, + WPS_EI_AUTH_FAILURE, NUM_WPS_EI_VALUES }; /* RF Bands */ #define WPS_RF_24GHZ 0x01 #define WPS_RF_50GHZ 0x02 +#define WPS_RF_60GHZ 0x04 /* Config Methods */ #define WPS_CONFIG_USBA 0x0001 @@ -246,12 +254,11 @@ enum wps_error_indication { #define WPS_CONFIG_NFC_INTERFACE 0x0040 #define WPS_CONFIG_PUSHBUTTON 0x0080 #define WPS_CONFIG_KEYPAD 0x0100 -#ifdef CONFIG_WPS2 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480 +#define WPS_CONFIG_P2PS 0x1000 #define WPS_CONFIG_VIRT_DISPLAY 0x2008 #define WPS_CONFIG_PHY_DISPLAY 0x4008 -#endif /* CONFIG_WPS2 */ /* Connection Type Flags */ #define WPS_CONN_ESS 0x01 @@ -285,7 +292,8 @@ enum wps_dev_categ { WPS_DEV_DISPLAY = 7, WPS_DEV_MULTIMEDIA = 8, WPS_DEV_GAMING = 9, - WPS_DEV_PHONE = 10 + WPS_DEV_PHONE = 10, + WPS_DEV_AUDIO = 11, }; enum wps_dev_subcateg { @@ -334,8 +342,4 @@ enum wps_response_type { #define WPS_MAX_AUTHORIZED_MACS 5 -#define WPS_IGNORE_SEL_REG_MAX_CNT 4 - -#define WPS_MAX_DIS_AP_NUM 10 - #endif /* WPS_DEFS_H */ diff --git a/components/wpa_supplicant/src/wps/wps_dev_attr.c b/components/wpa_supplicant/src/wps/wps_dev_attr.c index 9ef2fde03b..84be012297 100644 --- a/components/wpa_supplicant/src/wps/wps_dev_attr.c +++ b/components/wpa_supplicant/src/wps/wps_dev_attr.c @@ -5,11 +5,13 @@ * This software may be distributed under the terms of the BSD license. * See README for more details. */ -#include "utils/includes.h" -#include "utils/common.h" -#include "wps/wps_i.h" -#include "wps/wps_dev_attr.h" +#include "includes.h" + +#include "common.h" +#include "wps_i.h" +#include "wps_dev_attr.h" + int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg) { @@ -83,8 +85,7 @@ int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg) } -static int wps_build_serial_number(struct wps_device_data *dev, - struct wpabuf *msg) +int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Serial Number"); @@ -215,13 +216,10 @@ int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg) } -int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg) +int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg, + u8 rf_band) { - wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", dev->rf_bands); - wpabuf_put_be16(msg, ATTR_RF_BANDS); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, dev->rf_bands); - return 0; + return wps_build_rf_bands_attr(msg, rf_band ? rf_band : dev->rf_bands); } @@ -244,6 +242,21 @@ int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg) } +int wps_build_application_ext(struct wps_device_data *dev, struct wpabuf *msg) +{ + if (!dev->application_ext) + return 0; + + wpa_hexdump_buf(MSG_DEBUG, "WPS: * Application Extension", + dev->application_ext); + wpabuf_put_be16(msg, ATTR_APPLICATION_EXT); + wpabuf_put_be16(msg, wpabuf_len(dev->application_ext)); + wpabuf_put_buf(msg, dev->application_ext); + + return 0; +} + + static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str, size_t str_len) { @@ -255,11 +268,9 @@ static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str, wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len); os_free(dev->manufacturer); - dev->manufacturer = (char *)os_malloc(str_len + 1); + dev->manufacturer = dup_binstr(str, str_len); if (dev->manufacturer == NULL) return -1; - os_memcpy(dev->manufacturer, str, str_len); - dev->manufacturer[str_len] = '\0'; return 0; } @@ -276,11 +287,9 @@ static int wps_process_model_name(struct wps_device_data *dev, const u8 *str, wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len); os_free(dev->model_name); - dev->model_name = (char *)os_malloc(str_len + 1); + dev->model_name = dup_binstr(str, str_len); if (dev->model_name == NULL) return -1; - os_memcpy(dev->model_name, str, str_len); - dev->model_name[str_len] = '\0'; return 0; } @@ -297,11 +306,9 @@ static int wps_process_model_number(struct wps_device_data *dev, const u8 *str, wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len); os_free(dev->model_number); - dev->model_number = (char *)os_malloc(str_len + 1); + dev->model_number = dup_binstr(str, str_len); if (dev->model_number == NULL) return -1; - os_memcpy(dev->model_number, str, str_len); - dev->model_number[str_len] = '\0'; return 0; } @@ -318,11 +325,9 @@ static int wps_process_serial_number(struct wps_device_data *dev, wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len); os_free(dev->serial_number); - dev->serial_number = (char *)os_malloc(str_len + 1); + dev->serial_number = dup_binstr(str, str_len); if (dev->serial_number == NULL) return -1; - os_memcpy(dev->serial_number, str, str_len); - dev->serial_number[str_len] = '\0'; return 0; } @@ -339,11 +344,9 @@ static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str, wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len); os_free(dev->device_name); - dev->device_name = (char *)os_malloc(str_len + 1); + dev->device_name = dup_binstr(str, str_len); if (dev->device_name == NULL) return -1; - os_memcpy(dev->device_name, str, str_len); - dev->device_name[str_len] = '\0'; return 0; } @@ -352,12 +355,21 @@ static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str, static int wps_process_primary_dev_type(struct wps_device_data *dev, const u8 *dev_type) { +#ifdef DEBUG_PRINT + char devtype[WPS_DEV_TYPE_BUFSIZE]; +#endif /* CONFIG_NO_STDOUT_DEBUG */ + if (dev_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received"); return -1; } os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN); +#ifdef DEBUG_PRINT + wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s", + wps_dev_type_bin2str(dev->pri_dev_type, devtype, + sizeof(devtype))); +#endif return 0; } @@ -395,6 +407,14 @@ int wps_process_os_version(struct wps_device_data *dev, const u8 *ver) } +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext) +{ + dev->multi_ap_ext = ext; + wpa_printf(MSG_DEBUG, "WPS: Multi-AP extension value %02x", + dev->multi_ap_ext); +} + + int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) { if (bands == NULL) { @@ -409,25 +429,6 @@ int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) } -void wps_device_data_dup(struct wps_device_data *dst, - const struct wps_device_data *src) -{ - if (src->device_name) - dst->device_name = os_strdup(src->device_name); - if (src->manufacturer) - dst->manufacturer = os_strdup(src->manufacturer); - if (src->model_name) - dst->model_name = os_strdup(src->model_name); - if (src->model_number) - dst->model_number = os_strdup(src->model_number); - if (src->serial_number) - dst->serial_number = os_strdup(src->serial_number); - os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN); - dst->os_version = src->os_version; - dst->rf_bands = src->rf_bands; -} - - void wps_device_data_free(struct wps_device_data *dev) { os_free(dev->device_name); @@ -440,4 +441,6 @@ void wps_device_data_free(struct wps_device_data *dev) dev->model_number = NULL; os_free(dev->serial_number); dev->serial_number = NULL; + wpabuf_free(dev->application_ext); + dev->application_ext = NULL; } diff --git a/components/wpa_supplicant/src/wps/wps_dev_attr.h b/components/wpa_supplicant/src/wps/wps_dev_attr.h index 200c9c45ad..81fdd5f4e9 100644 --- a/components/wpa_supplicant/src/wps/wps_dev_attr.h +++ b/components/wpa_supplicant/src/wps/wps_dev_attr.h @@ -14,11 +14,13 @@ struct wps_parse_attr; int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg); -int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg, + u8 rf_band); int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_secondary_dev_type(struct wps_device_data *dev, @@ -27,11 +29,11 @@ int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); int wps_process_device_attrs(struct wps_device_data *dev, struct wps_parse_attr *attr); int wps_process_os_version(struct wps_device_data *dev, const u8 *ver); +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext); int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); -void wps_device_data_dup(struct wps_device_data *dst, - const struct wps_device_data *src); void wps_device_data_free(struct wps_device_data *dev); int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_application_ext(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg, unsigned int num_req_dev_types, const u8 *req_dev_types); diff --git a/components/wpa_supplicant/src/wps/wps_enrollee.c b/components/wpa_supplicant/src/wps/wps_enrollee.c index a124713e45..59e128d5c3 100644 --- a/components/wpa_supplicant/src/wps/wps_enrollee.c +++ b/components/wpa_supplicant/src/wps/wps_enrollee.c @@ -5,28 +5,17 @@ * This software may be distributed under the terms of the BSD license. * See README for more details. */ -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/rom/ets_sys.h" // for ets_timer_disarm -#endif -#include "utils/includes.h" -#include "utils/common.h" +#include "includes.h" + +#include "common.h" #include "crypto/crypto.h" #include "crypto/sha256.h" #include "crypto/random.h" -#include "wps/wps_i.h" -#include "wps/wps.h" -#include "wps/wps_dev_attr.h" - - -static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * MAC Address"); - wpabuf_put_be16(msg, ATTR_MAC_ADDR); - wpabuf_put_be16(msg, ETH_ALEN); - wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN); - return 0; -} +#include "wps_i.h" +#include "wps_dev_attr.h" +#include "esp_wps_i.h" static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg) { @@ -35,7 +24,7 @@ static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg) state = wps->wps->wps_state; else state = WPS_STATE_NOT_CONFIGURED; - wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", + wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", state); wpabuf_put_be16(msg, ATTR_WPS_STATE); wpabuf_put_be16(msg, 1); @@ -57,12 +46,12 @@ static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg) wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { - wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " + wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " "E-Hash derivation"); return -1; } - wpa_printf(MSG_DEBUG, "WPS: * E-Hash1"); + wpa_printf(MSG_DEBUG, "WPS: * E-Hash1"); wpabuf_put_be16(msg, ATTR_E_HASH1); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); @@ -78,7 +67,7 @@ static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg) hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN); - wpa_printf(MSG_DEBUG, "WPS: * E-Hash2"); + wpa_printf(MSG_DEBUG, "WPS: * E-Hash2"); wpabuf_put_be16(msg, ATTR_E_HASH2); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); @@ -94,7 +83,7 @@ static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg) static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1"); + wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1"); wpabuf_put_be16(msg, ATTR_E_SNONCE1); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); @@ -104,7 +93,7 @@ static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg) static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2"); + wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2"); wpabuf_put_be16(msg, ATTR_E_SNONCE2); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, @@ -117,13 +106,14 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps) { struct wpabuf *msg; u16 config_methods; + u8 multi_ap_backhaul_sta = 0; if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0) return NULL; wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); - wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; @@ -142,30 +132,36 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps) * workaround. */ config_methods &= ~WPS_CONFIG_PUSHBUTTON; -#ifdef CONFIG_WPS2 config_methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_PUSHBUTTON); -#endif /* CONFIG_WPS2 */ } + if (wps->multi_ap_backhaul_sta) + multi_ap_backhaul_sta = MULTI_AP_BACKHAUL_STA; + if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M1) || wps_build_uuid_e(msg, wps->uuid_e) || - wps_build_mac_addr(wps, msg) || + wps_build_mac_addr(msg, wps->mac_addr_e) || wps_build_enrollee_nonce(wps, msg) || - wps_build_public_key(wps, msg, WPS_CALC_KEY_NO_CALC) || + wps_build_public_key(wps, msg) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods(msg, config_methods) || wps_build_wps_state(wps, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || - wps_build_rf_bands(&wps->wps->dev, msg) || + wps_build_rf_bands(&wps->wps->dev, msg, +#ifdef ESP_SUPPLICANT + wps->wps->dev.rf_bands) || +#else + wps->wps->rf_band_cb(wps->wps->cb_ctx)) || +#endif wps_build_assoc_state(wps, msg) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_os_version(&wps->wps->dev, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, multi_ap_backhaul_sta) || wps_build_vendor_ext_m1(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; @@ -180,13 +176,20 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps) { struct wpabuf *msg; - wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); if (wps->dev_password == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); + wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); + return NULL; + } + if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0) + return NULL; + + if (wps->wps->ap && random_pool_ready() != 1) { + wpa_printf(MSG_INFO, + "WPS: Not enough entropy in random pool to proceed - do not allow AP PIN to be used"); return NULL; } - wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); msg = wpabuf_alloc(1000); if (msg == NULL) @@ -196,7 +199,7 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps) wps_build_msg_type(msg, WPS_M3) || wps_build_registrar_nonce(wps, msg) || wps_build_e_hash(wps, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; @@ -211,7 +214,7 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps) { struct wpabuf *msg, *plain; - wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); plain = wpabuf_alloc(200); if (plain == NULL) @@ -229,13 +232,13 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps) wps_build_e_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { - wpabuf_free(plain); + wpabuf_clear_free(plain); wpabuf_free(msg); return NULL; } - wpabuf_free(plain); + wpabuf_clear_free(plain); wps->state = RECV_M6; return msg; @@ -244,7 +247,7 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps) static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * SSID"); + wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpabuf_put_be16(msg, ATTR_SSID); wpabuf_put_be16(msg, wps->wps->ssid_len); wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len); @@ -254,19 +257,21 @@ static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) { - u16 auth_type = wps->wps->auth_types; + u16 auth_type = wps->wps->ap_auth_type; - /* Select the best authentication type */ + /* + * Work around issues with Windows 7 WPS implementation not liking + * multiple Authentication Type bits in M7 AP Settings attribute by + * showing only the most secure option from current configuration. + */ if (auth_type & WPS_AUTH_WPA2PSK) auth_type = WPS_AUTH_WPA2PSK; else if (auth_type & WPS_AUTH_WPAPSK) auth_type = WPS_AUTH_WPAPSK; - else if (auth_type & WPS_WIFI_AUTH_OPEN) - auth_type = WPS_WIFI_AUTH_OPEN; - else if (auth_type & WPS_AUTH_SHARED) - auth_type = WPS_AUTH_SHARED; + else if (auth_type & WPS_AUTH_OPEN) + auth_type = WPS_AUTH_OPEN; - wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", auth_type); + wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", auth_type); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, auth_type); @@ -276,22 +281,21 @@ static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) { - u16 encr_type = wps->wps->encr_types; + u16 encr_type = wps->wps->ap_encr_type; - /* Select the best encryption type */ - if (wps->wps->auth_types & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) { + /* + * Work around issues with Windows 7 WPS implementation not liking + * multiple Encryption Type bits in M7 AP Settings attribute by + * showing only the most secure option from current configuration. + */ + if (wps->wps->ap_auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) { if (encr_type & WPS_ENCR_AES) encr_type = WPS_ENCR_AES; else if (encr_type & WPS_ENCR_TKIP) encr_type = WPS_ENCR_TKIP; - } else { - if (encr_type & WPS_ENCR_WEP) - encr_type = WPS_ENCR_WEP; - else if (encr_type & WPS_ENCR_NONE) - encr_type = WPS_ENCR_NONE; } - wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", encr_type); + wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", encr_type); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, encr_type); @@ -301,7 +305,37 @@ static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * Network Key"); + if ((wps->wps->ap_auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) && + wps->wps->network_key_len == 0) { + char hex[65]; + u8 psk[32]; + /* Generate a random per-device PSK */ + if (random_pool_ready() != 1 || + random_get_bytes(psk, sizeof(psk)) < 0) { + wpa_printf(MSG_INFO, + "WPS: Could not generate random PSK"); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK", + psk, sizeof(psk)); + wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%u)", + (unsigned int) wps->new_psk_len * 2); + wpa_snprintf_hex(hex, sizeof(hex), psk, sizeof(psk)); + wpabuf_put_be16(msg, ATTR_NETWORK_KEY); + wpabuf_put_be16(msg, sizeof(psk) * 2); + wpabuf_put_data(msg, hex, sizeof(psk) * 2); +#ifdef CONFIG_WPS_REGISTRAR + if (wps->wps->registrar) { + wps_cb_new_psk(wps->wps->registrar, + wps->peer_dev.mac_addr, + wps->p2p_dev_addr, psk, sizeof(psk)); + } +#endif + return 0; + } + + wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%u)", + (unsigned int) wps->wps->network_key_len); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, wps->wps->network_key_len); wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len); @@ -311,7 +345,7 @@ static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)"); + wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)"); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN); @@ -321,18 +355,35 @@ static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg) static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain) { +#ifdef DEBUG_PRINT + const u8 *start, *end; +#endif + int ret; + if (wps->wps->ap_settings) { - wpa_printf(MSG_DEBUG, "WPS: * AP Settings (pre-configured)"); + wpa_printf(MSG_DEBUG, "WPS: * AP Settings (pre-configured)"); wpabuf_put_data(plain, wps->wps->ap_settings, wps->wps->ap_settings_len); return 0; } - return wps_build_cred_ssid(wps, plain) || + wpa_printf(MSG_DEBUG, "WPS: * AP Settings based on current configuration"); +#ifdef DEBUG_PRINT + start = wpabuf_put(plain, 0); +#endif + ret = wps_build_cred_ssid(wps, plain) || wps_build_cred_mac_addr(wps, plain) || wps_build_cred_auth_type(wps, plain) || wps_build_cred_encr_type(wps, plain) || wps_build_cred_network_key(wps, plain); +#ifdef DEBUG_PRINT + end = wpabuf_put(plain, 0); + + wpa_hexdump_key(MSG_DEBUG, "WPS: Plaintext AP Settings", + start, end - start); +#endif + + return ret; } @@ -340,7 +391,7 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps) { struct wpabuf *msg, *plain; - wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); if (plain == NULL) @@ -359,14 +410,15 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps) (wps->wps->ap && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { - wpabuf_free(plain); + wpabuf_clear_free(plain); wpabuf_free(msg); return NULL; } - wpabuf_free(plain); + wpabuf_clear_free(plain); +#ifdef CONFIG_WPS_REGISTRAR if (wps->wps->ap && wps->wps->registrar) { /* * If the Registrar is only learning our current configuration, @@ -376,6 +428,7 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps) wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_r); } +#endif wps->state = RECV_M8; return msg; @@ -386,7 +439,7 @@ static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) { struct wpabuf *msg; - wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); + wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); msg = wpabuf_alloc(1000); if (msg == NULL) @@ -396,7 +449,7 @@ static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) wps_build_msg_type(msg, WPS_WSC_DONE) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -404,7 +457,7 @@ static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) if (wps->wps->ap) wps->state = RECV_ACK; else { - wps_success_event(wps->wps); + wps_success_event(wps->wps, wps->peer_dev.mac_addr); wps->state = WPS_FINISHED; } return msg; @@ -455,7 +508,7 @@ struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, *op_code = WSC_Done; break; default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " + wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " "a message", wps->state); msg = NULL; break; @@ -475,7 +528,7 @@ struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) { if (r_nonce == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); + wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); return -1; } @@ -490,12 +543,12 @@ static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) { if (e_nonce == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); + wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); return -1; } if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received"); + wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received"); return -1; } @@ -506,7 +559,7 @@ static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r) { if (uuid_r == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No UUID-R received"); + wpa_printf(MSG_DEBUG, "WPS: No UUID-R received"); return -1; } @@ -521,22 +574,35 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, size_t pk_len) { if (pk == NULL || pk_len == 0) { - wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); + wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); return -1; } + if (wps->peer_pubkey_hash_set) { + u8 hash[WPS_HASH_LEN]; + sha256_vector(1, &pk, &pk_len, hash); + if (os_memcmp_const(hash, wps->peer_pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN) != 0) { + wpa_printf(MSG_ERROR, "WPS: Public Key hash mismatch"); + wpa_hexdump(MSG_DEBUG, "WPS: Received public key", + pk, pk_len); + wpa_hexdump(MSG_DEBUG, "WPS: Calculated public key " + "hash", hash, WPS_OOB_PUBKEY_HASH_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: Expected public key hash", + wps->peer_pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN); + wps->config_error = WPS_CFG_PUBLIC_KEY_HASH_MISMATCH; + return -1; + } + } + wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len); if (wps->dh_pubkey_r == NULL) return -1; - wpa_printf(MSG_DEBUG, "process pubkey start\n"); - - if (wps_derive_keys(wps) < 0) { + if (wps_derive_keys(wps) < 0) return -1; - } - - wpa_printf(MSG_DEBUG, "process pubkey finish\n"); return 0; } @@ -545,7 +611,7 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1) { if (r_hash1 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received"); + wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received"); return -1; } @@ -559,7 +625,7 @@ static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1) static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2) { if (r_hash2 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received"); + wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received"); return -1; } @@ -577,7 +643,7 @@ static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1) size_t len[4]; if (r_snonce1 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received"); + wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received"); return -1; } @@ -593,17 +659,17 @@ static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1) len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does " + + if (os_memcmp_const(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; - wps_pwd_auth_fail_event(wps->wps, 1, 1); + wps_pwd_auth_fail_event(wps->wps, 1, 1, wps->peer_dev.mac_addr); return -1; } - wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first " + wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first " "half of the device password"); return 0; @@ -617,7 +683,7 @@ static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2) size_t len[4]; if (r_snonce2 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received"); + wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received"); return -1; } @@ -633,18 +699,17 @@ static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2) len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does " + if (os_memcmp_const(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; - wps_pwd_auth_fail_event(wps->wps, 1, 2); + wps_pwd_auth_fail_event(wps->wps, 1, 2, wps->peer_dev.mac_addr); return -1; } - wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second " + wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second " "half of the device password"); return 0; @@ -652,7 +717,7 @@ static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2) static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, - size_t cred_len, int cred_idx, int wps2) + size_t cred_len, int wps2) { struct wps_parse_attr *attr; struct wpabuf msg; @@ -695,7 +760,6 @@ static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, #endif /* CONFIG_WPS_STRICT */ } -#ifdef CONFIG_WPS2 if (!(wps->cred.encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (wps->cred.encr_type & WPS_ENCR_WEP) { @@ -711,9 +775,6 @@ static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, ret = -1; goto _out; } -#endif /* CONFIG_WPS2 */ - wps_ssid_save(wps->cred.ssid, wps->cred.ssid_len, cred_idx); - wps_key_save((char *)wps->cred.key, wps->cred.key_len, cred_idx); if (wps->wps->cred_cb) { wps->cred.cred_attr = cred - 4; @@ -732,7 +793,7 @@ _out: static int wps_process_creds(struct wps_data *wps, const u8 *cred[], - size_t cred_len[], size_t num_cred, int wps2) + u16 cred_len[], unsigned int num_cred, int wps2) { size_t i; int ok = 0; @@ -741,25 +802,24 @@ static int wps_process_creds(struct wps_data *wps, const u8 *cred[], return 0; if (num_cred == 0) { - wpa_printf(MSG_DEBUG, "WPS: No Credential attributes " + wpa_printf(MSG_DEBUG, "WPS: No Credential attributes " "received"); return -1; } for (i = 0; i < num_cred; i++) { int res; - res = wps_process_cred_e(wps, cred[i], cred_len[i], i, wps2); + res = wps_process_cred_e(wps, cred[i], cred_len[i], wps2); if (res == 0) ok++; - else if (res == -2) { - wpa_printf(MSG_DEBUG, "WPS: WEP credential skipped"); - } + else if (res == -2) + wpa_printf(MSG_DEBUG, "WPS: WEP credential skipped"); else return -1; } if (ok == 0) { - wpa_printf(MSG_DEBUG, "WPS: No valid Credential attribute " + wpa_printf(MSG_DEBUG, "WPS: No valid Credential attribute " "received"); return -1; } @@ -817,7 +877,6 @@ static int wps_process_ap_settings_e(struct wps_data *wps, #endif /* CONFIG_WPS_STRICT */ } -#ifdef CONFIG_WPS2 if (!(cred->encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (cred->encr_type & WPS_ENCR_WEP) { @@ -833,7 +892,6 @@ static int wps_process_ap_settings_e(struct wps_data *wps, ret = -1; goto _out; } -#endif /* CONFIG_WPS2 */ #ifdef CONFIG_WPS_STRICT if (wps2) { @@ -851,7 +909,6 @@ static int wps_process_ap_settings_e(struct wps_data *wps, } #endif /* CONFIG_WPS_STRICT */ -#ifdef CONFIG_WPS2 if ((cred->encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP) { wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> " @@ -865,7 +922,6 @@ static int wps_process_ap_settings_e(struct wps_data *wps, "WPAPSK+WPA2PSK"); cred->auth_type |= WPS_AUTH_WPA2PSK; } -#endif /* CONFIG_WPS2 */ if (wps->wps->cred_cb) { cred->cred_attr = wpabuf_head(attrs); @@ -881,14 +937,71 @@ _out: } +static int wps_process_dev_pw_id(struct wps_data *wps, const u8 *dev_pw_id) +{ + u16 id; + + if (dev_pw_id == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Device Password ID"); + return -1; + } + + id = WPA_GET_BE16(dev_pw_id); + if (wps->dev_pw_id == id) { + wpa_printf(MSG_DEBUG, "WPS: Device Password ID %u", id); + return 0; + } + +#ifdef CONFIG_P2P + if ((id == DEV_PW_DEFAULT && + wps->dev_pw_id == DEV_PW_REGISTRAR_SPECIFIED) || + (id == DEV_PW_REGISTRAR_SPECIFIED && + wps->dev_pw_id == DEV_PW_DEFAULT)) { + /* + * Common P2P use cases indicate whether the PIN is from the + * client or GO using Device Password Id in M1/M2 in a way that + * does not look fully compliant with WSC specification. Anyway, + * this is deployed and needs to be allowed, so ignore changes + * between Registrar-Specified and Default PIN. + */ + wpa_printf(MSG_DEBUG, "WPS: Allow PIN Device Password ID " + "change"); + return 0; + } +#endif /* CONFIG_P2P */ + + wpa_printf(MSG_DEBUG, "WPS: Registrar trying to change Device Password " + "ID from %u to %u", wps->dev_pw_id, id); + + if (wps->dev_pw_id == DEV_PW_PUSHBUTTON && id == DEV_PW_DEFAULT) { + wpa_printf(MSG_DEBUG, + "WPS: Workaround - ignore PBC-to-PIN change"); + return 0; + } + + if (wps->alt_dev_password && wps->alt_dev_pw_id == id) { + wpa_printf(MSG_DEBUG, "WPS: Found a matching Device Password"); + bin_clear_free(wps->dev_password, wps->dev_password_len); + wps->dev_pw_id = wps->alt_dev_pw_id; + wps->dev_password = wps->alt_dev_password; + wps->dev_password_len = wps->alt_dev_password_len; + wps->alt_dev_password = NULL; + wps->alt_dev_password_len = 0; + return 0; + } + + return -1; +} + + static enum wps_process_res wps_process_m2(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { - wpa_printf(MSG_DEBUG, "WPS: Received M2"); + wpa_printf(MSG_DEBUG, "WPS: Received M2"); if (wps->state != RECV_M2) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M2", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; @@ -896,7 +1009,8 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps, if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || - wps_process_uuid_r(wps, attr->uuid_r)) { + wps_process_uuid_r(wps, attr->uuid_r) || + wps_process_dev_pw_id(wps, attr->dev_password_id)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } @@ -910,7 +1024,7 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps, if (wps->wps->ap && ((wps->wps->ap_setup_locked && wps->wps->ap_setup_locked != 2) || wps->dev_password == NULL)) { - wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " + wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " "registration of a new Registrar"); wps->config_error = WPS_CFG_SETUP_LOCKED; wps->state = SEND_WSC_NACK; @@ -924,6 +1038,38 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps, return WPS_CONTINUE; } +#ifdef CONFIG_WPS_NFC + if (wps->peer_pubkey_hash_set) { + struct wpabuf *decrypted; + struct wps_parse_attr eattr; + + decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, + attr->encr_settings_len); + if (decrypted == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt " + "Encrypted Settings attribute"); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted " + "Settings attribute"); + if (wps_parse_msg(decrypted, &eattr) < 0 || + wps_process_key_wrap_auth(wps, decrypted, + eattr.key_wrap_auth) || + wps_process_creds(wps, eattr.cred, eattr.cred_len, + eattr.num_cred, attr->version2 != NULL)) { + wpabuf_clear_free(decrypted); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + wpabuf_clear_free(decrypted); + + wps->state = WPS_MSG_DONE; + return WPS_CONTINUE; + } +#endif /* CONFIG_WPS_NFC */ + wps->state = SEND_M3; return WPS_CONTINUE; } @@ -932,10 +1078,10 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps, static enum wps_process_res wps_process_m2d(struct wps_data *wps, struct wps_parse_attr *attr) { - wpa_printf(MSG_DEBUG, "WPS: Received M2D"); + wpa_printf(MSG_DEBUG, "WPS: Received M2D"); if (wps->state != RECV_M2) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M2D", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; @@ -1002,7 +1148,7 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps, } if (wps->state != RECV_M4) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M4", wps->state); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; @@ -1021,7 +1167,7 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps, decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; @@ -1029,13 +1175,13 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps, } if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) { - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; goto _out; } - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr->key_wrap_auth) || @@ -1045,7 +1191,7 @@ static enum wps_process_res wps_process_m4(struct wps_data *wps, res = WPS_CONTINUE; goto _out; } - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_M5; res = WPS_CONTINUE; @@ -1064,7 +1210,7 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps, struct wps_parse_attr *eattr; enum wps_process_res res; - wpa_printf(MSG_DEBUG, "WPS: Received M6"); + wpa_printf(MSG_DEBUG, "WPS: Received M6"); eattr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); if (eattr == NULL) { @@ -1074,7 +1220,7 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps, } if (wps->state != RECV_M6) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M6", wps->state); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; @@ -1091,7 +1237,7 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps, decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; @@ -1099,13 +1245,13 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps, } if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) { - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; goto _out; } - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr->key_wrap_auth) || @@ -1115,7 +1261,7 @@ static enum wps_process_res wps_process_m6(struct wps_data *wps, res = WPS_CONTINUE; goto _out; } - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); if (wps->wps->ap) wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS, @@ -1138,7 +1284,7 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps, struct wps_parse_attr *eattr; enum wps_process_res res; - wpa_printf(MSG_DEBUG, "WPS: Received M8"); + wpa_printf(MSG_DEBUG, "WPS: Received M8"); eattr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); if (eattr == NULL) { @@ -1148,7 +1294,7 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps, } if (wps->state != RECV_M8) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M8", wps->state); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; @@ -1168,7 +1314,7 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps, * protocol to continue beyond M2. This allows ER to learn the * current AP settings without changing them. */ - wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " + wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " "registration of a new Registrar"); wps->config_error = WPS_CFG_SETUP_LOCKED; wps->state = SEND_WSC_NACK; @@ -1179,7 +1325,7 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps, decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; @@ -1188,13 +1334,13 @@ static enum wps_process_res wps_process_m8(struct wps_data *wps, if (wps_validate_m8_encr(decrypted, wps->wps->ap, attr->version2 != NULL) < 0) { - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; res = WPS_CONTINUE; goto _out; } - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr->key_wrap_auth) || @@ -1232,11 +1378,6 @@ static enum wps_process_res wps_process_wsc_start(struct wps_data *wps, return ret; } -#define WPS_IGNORE_STATE(wps_st) do {\ - if (wps->state <= RECV_M8 && ((wps_st) == wps->state - 1 || (wps_st) == wps->state - 2)) { \ - return WPS_IGNORE;\ - }\ -} while (0) static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, const struct wpabuf *msg) @@ -1259,13 +1400,13 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, if (attr->enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr->enrollee_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); ret = WPS_FAILURE; goto _out; } if (attr->msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); wps->state = SEND_WSC_NACK; ret = WPS_CONTINUE; goto _out; @@ -1273,7 +1414,6 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, switch (*attr->msg_type) { case WPS_M2: - WPS_IGNORE_STATE(RECV_M2); if (wps_validate_m2(msg) < 0) { ret = WPS_FAILURE; goto _out; @@ -1288,7 +1428,6 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, ret = wps_process_m2d(wps, attr); break; case WPS_M4: - WPS_IGNORE_STATE(RECV_M4); if (wps_validate_m4(msg) < 0) { ret = WPS_FAILURE; goto _out; @@ -1296,10 +1435,10 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, ret = wps_process_m4(wps, msg, attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M4, wps->config_error, - wps->error_indication); + wps->error_indication, + wps->peer_dev.mac_addr); break; case WPS_M6: - WPS_IGNORE_STATE(RECV_M6); if (wps_validate_m6(msg) < 0) { ret = WPS_FAILURE; goto _out; @@ -1307,10 +1446,10 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, ret = wps_process_m6(wps, msg, attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M6, wps->config_error, - wps->error_indication); + wps->error_indication, + wps->peer_dev.mac_addr); break; case WPS_M8: - WPS_IGNORE_STATE(RECV_M8); if (wps_validate_m8(msg) < 0) { ret = WPS_FAILURE; goto _out; @@ -1318,10 +1457,11 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, ret = wps_process_m8(wps, msg, attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M8, wps->config_error, - wps->error_indication); + wps->error_indication, + wps->peer_dev.mac_addr); break; default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", + wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", *attr->msg_type); ret = WPS_FAILURE; goto _out; @@ -1355,7 +1495,7 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, struct wps_parse_attr *attr; enum wps_process_res res; - wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); + wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); if (attr == NULL) { @@ -1399,7 +1539,7 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, if (wps->state == RECV_ACK && wps->wps->ap) { wpa_printf(MSG_DEBUG, "WPS: External Registrar registration " "completed successfully"); - wps_success_event(wps->wps); + wps_success_event(wps->wps, wps->peer_dev.mac_addr); wps->state = WPS_FINISHED; res = WPS_DONE; goto _out; @@ -1484,15 +1624,15 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, switch (wps->state) { case RECV_M4: wps_fail_event(wps->wps, WPS_M3, config_error, - wps->error_indication); + wps->error_indication, wps->peer_dev.mac_addr); break; case RECV_M6: wps_fail_event(wps->wps, WPS_M5, config_error, - wps->error_indication); + wps->error_indication, wps->peer_dev.mac_addr); break; case RECV_M8: wps_fail_event(wps->wps, WPS_M7, config_error, - wps->error_indication); + wps->error_indication, wps->peer_dev.mac_addr); break; default: break; @@ -1546,7 +1686,7 @@ enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, return WPS_FAILURE; return wps_process_wsc_nack(wps, msg); default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); + wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); return WPS_FAILURE; } } diff --git a/components/wpa_supplicant/src/wps/wps_i.h b/components/wpa_supplicant/src/wps/wps_i.h index 5cdd51ec3c..c956af8505 100644 --- a/components/wpa_supplicant/src/wps/wps_i.h +++ b/components/wpa_supplicant/src/wps/wps_i.h @@ -11,8 +11,6 @@ #include "wps.h" #include "wps_attr_parse.h" -#include "esp_wps.h" -#include "esp_wifi_crypto_types.h" #ifdef CONFIG_WPS_NFC struct wps_nfc_pw_token; @@ -74,6 +72,12 @@ struct wps_data { size_t dev_password_len; u16 dev_pw_id; int pbc; + u8 *alt_dev_password; + size_t alt_dev_password_len; + u16 alt_dev_pw_id; + + u8 peer_pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; + int peer_pubkey_hash_set; /** * request_type - Request Type attribute from (Re)AssocReq @@ -120,38 +124,36 @@ struct wps_data { u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or * 00:00:00:00:00:00 if not a P2p client */ int pbc_in_m1; -#ifdef CONFIG_WPS_NFC + struct wps_nfc_pw_token *nfc_pw_token; -#endif + + int multi_ap_backhaul_sta; }; + /* wps_common.c */ void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, const char *label, u8 *res, size_t res_len); int wps_derive_keys(struct wps_data *wps); -void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, - size_t dev_passwd_len); +int wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, + size_t dev_passwd_len); struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, size_t encr_len); void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, - u16 config_error, u16 error_indication); -void wps_success_event(struct wps_context *wps); -void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part); + u16 config_error, u16 error_indication, const u8 *mac_addr); +void wps_success_event(struct wps_context *wps, const u8 *mac_addr); +void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part, + const u8 *mac_addr); void wps_pbc_overlap_event(struct wps_context *wps); void wps_pbc_timeout_event(struct wps_context *wps); +void wps_pbc_active_event(struct wps_context *wps); +void wps_pbc_disable_event(struct wps_context *wps); struct wpabuf * wps_build_wsc_ack(struct wps_data *wps); struct wpabuf * wps_build_wsc_nack(struct wps_data *wps); -typedef enum wps_calc_key_mode { - WPS_CALC_KEY_NORMAL = 0, - WPS_CALC_KEY_NO_CALC, - WPS_CALC_KEY_PRE_CALC, - WPS_CALC_KEY_MAX, -} wps_key_mode_t; - /* wps_attr_build.c */ -int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_t mode); +int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg); int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type); int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type); int wps_build_config_methods(struct wpabuf *msg, u16 methods); @@ -164,7 +166,8 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, struct wpabuf *plain); int wps_build_version(struct wpabuf *msg); int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, - const u8 *auth_macs, size_t auth_macs_count); + const u8 *auth_macs, size_t auth_macs_count, + u8 multi_ap_subelem); int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type); int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg); int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg); @@ -176,6 +179,9 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, const struct wpabuf *pubkey, const u8 *dev_pw, size_t dev_pw_len); struct wpabuf * wps_ie_encapsulate(struct wpabuf *data); +int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr); +int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands); +int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel); /* wps_attr_process.c */ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, @@ -203,7 +209,8 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, int wps_build_cred(struct wps_data *wps, struct wpabuf *msg); int wps_device_store(struct wps_registrar *reg, struct wps_device_data *dev, const u8 *uuid); -void wps_registrar_selected_registrar_changed(struct wps_registrar *reg); +void wps_registrar_selected_registrar_changed(struct wps_registrar *reg, + u16 dev_pw_id); const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count); int wps_registrar_pbc_overlap(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e); @@ -212,5 +219,7 @@ int wps_registrar_pbc_overlap(struct wps_registrar *reg, void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg, struct wps_nfc_pw_token *token); #endif +int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, + const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len); #endif /* WPS_I_H */ diff --git a/components/wpa_supplicant/src/wps/wps_registrar.c b/components/wpa_supplicant/src/wps/wps_registrar.c index 677a6510a5..14c9072a05 100644 --- a/components/wpa_supplicant/src/wps/wps_registrar.c +++ b/components/wpa_supplicant/src/wps/wps_registrar.c @@ -1,12 +1,13 @@ /* * Wi-Fi Protected Setup - Registrar - * Copyright (c) 2008-2012, Jouni Malinen + * Copyright (c) 2008-2016, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ + #include "utils/includes.h" -#include "utils/list.h" + #include "utils/common.h" #include "utils/base64.h" #include "utils/uuid.h" @@ -15,8 +16,9 @@ #include "crypto/sha256.h" #include "crypto/random.h" #include "common/ieee802_11_defs.h" -#include "wps/wps_i.h" -#include "wps/wps_dev_attr.h" +#include "common/wpa_common.h" +#include "wps_i.h" +#include "wps_dev_attr.h" #ifndef CONFIG_WPS_STRICT #define WPS_WORKAROUNDS @@ -27,16 +29,18 @@ struct wps_nfc_pw_token { struct dl_list list; u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; + unsigned int peer_pk_hash_known:1; u16 pw_id; - u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN]; + u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1]; size_t dev_pw_len; + int pk_hash_provided_oob; /* whether own PK hash was provided OOB */ }; static void wps_remove_nfc_pw_token(struct wps_nfc_pw_token *token) { dl_list_del(&token->list); - os_free(token); + bin_clear_free(token, sizeof(*token)); } @@ -68,7 +72,6 @@ static struct wps_nfc_pw_token * wps_get_nfc_pw_token(struct dl_list *tokens, #endif /* CONFIG_WPS_NFC */ -#ifdef CONFIG_WPS_PIN struct wps_uuid_pin { struct dl_list list; @@ -79,14 +82,14 @@ struct wps_uuid_pin { #define PIN_LOCKED BIT(0) #define PIN_EXPIRES BIT(1) int flags; - struct os_time expiration; + struct os_reltime expiration; u8 enrollee_addr[ETH_ALEN]; }; static void wps_free_pin(struct wps_uuid_pin *pin) { - os_free(pin->pin); + bin_clear_free(pin->pin, pin->pin_len); os_free(pin); } @@ -105,13 +108,12 @@ static void wps_free_pins(struct dl_list *pins) wps_remove_pin(pin); } -#endif struct wps_pbc_session { struct wps_pbc_session *next; u8 addr[ETH_ALEN]; u8 uuid_e[WPS_UUID_LEN]; - struct os_time timestamp; + struct os_reltime timestamp; }; @@ -140,8 +142,8 @@ struct wps_registrar { int pbc; int selected_registrar; - int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, - size_t psk_len); + int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr, + const u8 *psk, size_t psk_len); int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie, struct wpabuf *probe_resp_ie); void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, @@ -155,6 +157,7 @@ struct wps_registrar { const u8 *pri_dev_type, u16 config_methods, u16 dev_password_id, u8 request_type, const char *dev_name); + int (*lookup_pskfile_cb)(void *ctx, const u8 *mac_addr, const u8 **psk); void *cb_ctx; struct dl_list pins; @@ -167,8 +170,8 @@ struct wps_registrar { int sel_reg_union; int sel_reg_dev_password_id_override; int sel_reg_config_methods_override; - int static_wep_only; int dualband; + int force_per_enrollee_psk; struct wps_registrar_device *devices; @@ -180,28 +183,61 @@ struct wps_registrar { u8 p2p_dev_addr[ETH_ALEN]; u8 pbc_ignore_uuid[WPS_UUID_LEN]; - struct os_time pbc_ignore_start; +#ifdef WPS_WORKAROUNDS + struct os_reltime pbc_ignore_start; +#endif /* WPS_WORKAROUNDS */ + + /** + * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul + * enrollee + * + * This SSID is used by the Registrar to fill in information for + * Credentials when the enrollee advertises it is a Multi-AP backhaul + * STA. + */ + u8 multi_ap_backhaul_ssid[SSID_MAX_LEN]; + + /** + * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in + * octets + */ + size_t multi_ap_backhaul_ssid_len; + + /** + * multi_ap_backhaul_network_key - The Network Key (PSK) for the + * Multi-AP backhaul enrollee. + * + * This key can be either the ASCII passphrase (8..63 characters) or the + * 32-octet PSK (64 hex characters). + */ + u8 *multi_ap_backhaul_network_key; + + /** + * multi_ap_backhaul_network_key_len - Length of + * multi_ap_backhaul_network_key in octets + */ + size_t multi_ap_backhaul_network_key_len; }; static int wps_set_ie(struct wps_registrar *reg); -static void wps_registrar_pbc_timeout(void *eloop_ctx); +static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx); +static void wps_registrar_set_selected_timeout(void *eloop_ctx, + void *timeout_ctx); -#ifdef CONFIG_WPS_PIN static void wps_registrar_remove_pin(struct wps_registrar *reg, struct wps_uuid_pin *pin); -#endif static void wps_registrar_add_authorized_mac(struct wps_registrar *reg, const u8 *addr) { int i; - wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC " MACSTR, + wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC " MACSTR, MAC2STR(addr)); for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++) if (os_memcmp(reg->authorized_macs[i], addr, ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was " + wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was " "already in the list"); return; /* already in list */ } @@ -218,14 +254,14 @@ static void wps_registrar_remove_authorized_mac(struct wps_registrar *reg, const u8 *addr) { int i; - wpa_printf(MSG_DEBUG, "WPS: Remove authorized MAC " MACSTR, + wpa_printf(MSG_DEBUG, "WPS: Remove authorized MAC " MACSTR, MAC2STR(addr)); for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++) { if (os_memcmp(reg->authorized_macs, addr, ETH_ALEN) == 0) break; } if (i == WPS_MAX_AUTHORIZED_MACS) { - wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was not in the " + wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was not in the " "list"); return; /* not in the list */ } @@ -291,7 +327,7 @@ int wps_device_store(struct wps_registrar *reg, d = wps_device_get(reg, dev->mac_addr); if (d == NULL) { - d = (struct wps_registrar_device *)os_zalloc(sizeof(*d)); + d = os_zalloc(sizeof(*d)); if (d == NULL) return -1; d->next = reg->devices; @@ -309,9 +345,9 @@ static void wps_registrar_add_pbc_session(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e) { struct wps_pbc_session *pbc, *prev = NULL; - struct os_time now; + struct os_reltime now; - os_get_time(&now); + os_get_reltime(&now); pbc = reg->pbc_sessions; while (pbc) { @@ -328,7 +364,7 @@ static void wps_registrar_add_pbc_session(struct wps_registrar *reg, } if (!pbc) { - pbc = (struct wps_pbc_session *)os_zalloc(sizeof(*pbc)); + pbc = os_zalloc(sizeof(*pbc)); if (pbc == NULL) return; os_memcpy(pbc->addr, addr, ETH_ALEN); @@ -345,7 +381,8 @@ static void wps_registrar_add_pbc_session(struct wps_registrar *reg, pbc = pbc->next; while (pbc) { - if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) { + if (os_reltime_expired(&now, &pbc->timestamp, + WPS_PBC_WALK_TIME)) { prev->next = NULL; wps_free_pbc_sessions(pbc); break; @@ -374,7 +411,7 @@ static void wps_registrar_remove_pbc_session(struct wps_registrar *reg, reg->pbc_sessions = pbc->next; tmp = pbc; pbc = pbc->next; - wpa_printf(MSG_DEBUG, "WPS: Removing PBC session for " + wpa_printf(MSG_DEBUG, "WPS: Removing PBC session for " "addr=" MACSTR, MAC2STR(tmp->addr)); wpa_hexdump(MSG_DEBUG, "WPS: Removed UUID-E", tmp->uuid_e, WPS_UUID_LEN); @@ -393,44 +430,44 @@ int wps_registrar_pbc_overlap(struct wps_registrar *reg, int count = 0; struct wps_pbc_session *pbc; struct wps_pbc_session *first = NULL; - struct os_time now; + struct os_reltime now; - os_get_time(&now); + os_get_reltime(&now); - wpa_printf(MSG_DEBUG, "WPS: Checking active PBC sessions for overlap"); + wpa_printf(MSG_DEBUG, "WPS: Checking active PBC sessions for overlap"); if (uuid_e) { - wpa_printf(MSG_DEBUG, "WPS: Add one for the requested UUID"); + wpa_printf(MSG_DEBUG, "WPS: Add one for the requested UUID"); wpa_hexdump(MSG_DEBUG, "WPS: Requested UUID", uuid_e, WPS_UUID_LEN); count++; } for (pbc = reg->pbc_sessions; pbc; pbc = pbc->next) { - wpa_printf(MSG_DEBUG, "WPS: Consider PBC session with " MACSTR, + wpa_printf(MSG_DEBUG, "WPS: Consider PBC session with " MACSTR, MAC2STR(pbc->addr)); wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", pbc->uuid_e, WPS_UUID_LEN); - if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) { - wpa_printf(MSG_DEBUG, "WPS: PBC walk time has " - "expired"); + if (os_reltime_expired(&now, &pbc->timestamp, + WPS_PBC_WALK_TIME)) { + wpa_printf(MSG_DEBUG, "WPS: PBC walk time has expired"); break; } if (first && os_memcmp(pbc->uuid_e, first->uuid_e, WPS_UUID_LEN) == 0) { - wpa_printf(MSG_DEBUG, "WPS: Same Enrollee"); + wpa_printf(MSG_DEBUG, "WPS: Same Enrollee"); continue; /* same Enrollee */ } if (uuid_e == NULL || os_memcmp(uuid_e, pbc->uuid_e, WPS_UUID_LEN)) { - wpa_printf(MSG_DEBUG, "WPS: New Enrollee"); + wpa_printf(MSG_DEBUG, "WPS: New Enrollee"); count++; } if (first == NULL) first = pbc; } - wpa_printf(MSG_DEBUG, "WPS: %u active PBC session(s) found", count); + wpa_printf(MSG_DEBUG, "WPS: %u active PBC session(s) found", count); return count > 1 ? 1 : 0; } @@ -438,7 +475,7 @@ int wps_registrar_pbc_overlap(struct wps_registrar *reg, static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", + wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", wps->wps_state); wpabuf_put_be16(msg, ATTR_WPS_STATE); wpabuf_put_be16(msg, 1); @@ -458,7 +495,7 @@ static void wps_registrar_free_pending_m2(struct wps_context *wps) wps->upnp_msgs = p->next; else prev->next = p->next; - wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D"); + wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D"); p2 = p; p = p->next; wpabuf_free(p2->msg); @@ -476,7 +513,7 @@ static int wps_build_ap_setup_locked(struct wps_context *wps, struct wpabuf *msg) { if (wps->ap_setup_locked && wps->ap_setup_locked != 2) { - wpa_printf(MSG_DEBUG, "WPS: * AP Setup Locked"); + wpa_printf(MSG_DEBUG, "WPS: * AP Setup Locked"); wpabuf_put_be16(msg, ATTR_AP_SETUP_LOCKED); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); @@ -490,7 +527,7 @@ static int wps_build_selected_registrar(struct wps_registrar *reg, { if (!reg->sel_reg_union) return 0; - wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar"); + wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar"); wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); @@ -506,7 +543,7 @@ static int wps_build_sel_reg_dev_password_id(struct wps_registrar *reg, return 0; if (reg->sel_reg_dev_password_id_override >= 0) id = reg->sel_reg_dev_password_id_override; - wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); + wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, id); @@ -531,7 +568,6 @@ static int wps_build_sel_pbc_reg_uuid_e(struct wps_registrar *reg, static void wps_set_pushbutton(u16 *methods, u16 conf_methods) { *methods |= WPS_CONFIG_PUSHBUTTON; -#ifdef CONFIG_WPS2 if ((conf_methods & WPS_CONFIG_VIRT_PUSHBUTTON) == WPS_CONFIG_VIRT_PUSHBUTTON) *methods |= WPS_CONFIG_VIRT_PUSHBUTTON; @@ -549,7 +585,6 @@ static void wps_set_pushbutton(u16 *methods, u16 conf_methods) */ *methods |= WPS_CONFIG_PHY_PUSHBUTTON; } -#endif /* CONFIG_WPS2 */ } @@ -561,15 +596,13 @@ static int wps_build_sel_reg_config_methods(struct wps_registrar *reg, return 0; methods = reg->wps->config_methods; methods &= ~WPS_CONFIG_PUSHBUTTON; -#ifdef CONFIG_WPS2 methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_PUSHBUTTON); -#endif /* CONFIG_WPS2 */ if (reg->pbc) wps_set_pushbutton(&methods, reg->wps->config_methods); if (reg->sel_reg_config_methods_override >= 0) methods = reg->sel_reg_config_methods_override; - wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar Config Methods (%x)", + wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); @@ -587,11 +620,9 @@ static int wps_build_probe_config_methods(struct wps_registrar *reg, * external Registrars. */ methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; -#ifdef CONFIG_WPS2 methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_PUSHBUTTON); -#endif /* CONFIG_WPS2 */ - wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); + wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, methods); @@ -610,13 +641,11 @@ const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count) { *count = 0; -#ifdef CONFIG_WPS2 while (*count < WPS_MAX_AUTHORIZED_MACS) { if (is_zero_ether_addr(reg->authorized_macs_union[*count])) break; (*count)++; } -#endif /* CONFIG_WPS2 */ return (const u8 *) reg->authorized_macs_union; } @@ -634,27 +663,26 @@ const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count) * responsible for freeing the returned data with wps_registrar_deinit() when * Registrar functionality is not needed anymore. */ -struct wps_registrar * wps_registrar_init(struct wps_context *wps, +struct wps_registrar * +wps_registrar_init(struct wps_context *wps, const struct wps_registrar_config *cfg) { - struct wps_registrar *reg = (struct wps_registrar *)os_zalloc(sizeof(*reg)); + struct wps_registrar *reg = os_zalloc(sizeof(*reg)); if (reg == NULL) return NULL; -#ifdef CONFIG_WPS_PIN + dl_list_init(®->pins); -#endif #ifdef CONFIG_WPS_NFC dl_list_init(®->nfc_pw_tokens); #endif reg->wps = wps; reg->new_psk_cb = cfg->new_psk_cb; reg->set_ie_cb = cfg->set_ie_cb; -#ifdef CONFIG_WPS_PIN reg->pin_needed_cb = cfg->pin_needed_cb; -#endif reg->reg_success_cb = cfg->reg_success_cb; reg->set_sel_reg_cb = cfg->set_sel_reg_cb; reg->enrollee_seen_cb = cfg->enrollee_seen_cb; + reg->lookup_pskfile_cb = cfg->lookup_pskfile_cb; reg->cb_ctx = cfg->cb_ctx; reg->skip_cred_build = cfg->skip_cred_build; if (cfg->extra_cred) { @@ -668,8 +696,24 @@ struct wps_registrar * wps_registrar_init(struct wps_context *wps, reg->disable_auto_conf = cfg->disable_auto_conf; reg->sel_reg_dev_password_id_override = -1; reg->sel_reg_config_methods_override = -1; - reg->static_wep_only = cfg->static_wep_only; reg->dualband = cfg->dualband; + reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk; + + if (cfg->multi_ap_backhaul_ssid) { + os_memcpy(reg->multi_ap_backhaul_ssid, + cfg->multi_ap_backhaul_ssid, + cfg->multi_ap_backhaul_ssid_len); + reg->multi_ap_backhaul_ssid_len = + cfg->multi_ap_backhaul_ssid_len; + } + if (cfg->multi_ap_backhaul_network_key) { + reg->multi_ap_backhaul_network_key = + os_memdup(cfg->multi_ap_backhaul_network_key, + cfg->multi_ap_backhaul_network_key_len); + if (reg->multi_ap_backhaul_network_key) + reg->multi_ap_backhaul_network_key_len = + cfg->multi_ap_backhaul_network_key_len; + } if (wps_set_ie(reg)) { wps_registrar_deinit(reg); @@ -680,6 +724,22 @@ struct wps_registrar * wps_registrar_init(struct wps_context *wps, } +void wps_registrar_flush(struct wps_registrar *reg) +{ + if (reg == NULL) + return; + wps_free_pins(®->pins); + wps_free_nfc_pw_tokens(®->nfc_pw_tokens, 0); + wps_free_pbc_sessions(reg->pbc_sessions); + reg->pbc_sessions = NULL; + wps_free_devices(reg->devices); + reg->devices = NULL; +#ifdef WPS_WORKAROUNDS + reg->pbc_ignore_start.sec = 0; +#endif /* WPS_WORKAROUNDS */ +} + + /** * wps_registrar_deinit - Deinitialize WPS Registrar data * @reg: Registrar data from wps_registrar_init() @@ -688,20 +748,15 @@ void wps_registrar_deinit(struct wps_registrar *reg) { if (reg == NULL) return; - -#ifdef CONFIG_WPS_PIN - wps_free_pins(®->pins); -#endif -#ifdef CONFIG_WPS_NFC - wps_free_nfc_pw_tokens(®->nfc_pw_tokens, 0); -#endif - wps_free_pbc_sessions(reg->pbc_sessions); - wpabuf_free(reg->extra_cred); - wps_free_devices(reg->devices); + eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); + eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + wps_registrar_flush(reg); + wpabuf_clear_free(reg->extra_cred); + bin_clear_free(reg->multi_ap_backhaul_network_key, + reg->multi_ap_backhaul_network_key_len); os_free(reg); } -#ifdef CONFIG_WPS_PIN static void wps_registrar_invalidate_unused(struct wps_registrar *reg) { @@ -709,7 +764,7 @@ static void wps_registrar_invalidate_unused(struct wps_registrar *reg) dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (pin->wildcard_uuid == 1 && !(pin->flags & PIN_LOCKED)) { - wpa_printf(MSG_DEBUG, "WPS: Invalidate previously " + wpa_printf(MSG_DEBUG, "WPS: Invalidate previously " "configured wildcard PIN"); wps_registrar_remove_pin(reg, pin); break; @@ -734,7 +789,7 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, { struct wps_uuid_pin *p; - p = (struct wps_uuid_pin *)os_zalloc(sizeof(*p)); + p = os_zalloc(sizeof(*p)); if (p == NULL) return -1; if (addr) @@ -743,17 +798,16 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, p->wildcard_uuid = 1; else os_memcpy(p->uuid, uuid, WPS_UUID_LEN); - p->pin = (u8 *)os_malloc(pin_len); + p->pin = os_memdup(pin, pin_len); if (p->pin == NULL) { os_free(p); return -1; } - os_memcpy(p->pin, pin, pin_len); p->pin_len = pin_len; if (timeout) { p->flags |= PIN_EXPIRES; - os_get_time(&p->expiration); + os_get_reltime(&p->expiration); p->expiration.sec += timeout; } @@ -762,7 +816,7 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, dl_list_add(®->pins, &p->list); - wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)", + wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)", timeout); wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN); wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len); @@ -773,7 +827,11 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, else wps_registrar_add_authorized_mac( reg, (u8 *) "\xff\xff\xff\xff\xff\xff"); - wps_registrar_selected_registrar_changed(reg); + wps_registrar_selected_registrar_changed(reg, 0); + eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + eloop_register_timeout(WPS_PBC_WALK_TIME, 0, + wps_registrar_set_selected_timeout, + reg, NULL); return 0; } @@ -791,20 +849,20 @@ static void wps_registrar_remove_pin(struct wps_registrar *reg, addr = pin->enrollee_addr; wps_registrar_remove_authorized_mac(reg, addr); wps_remove_pin(pin); - wps_registrar_selected_registrar_changed(reg); + wps_registrar_selected_registrar_changed(reg, 0); } static void wps_registrar_expire_pins(struct wps_registrar *reg) { struct wps_uuid_pin *pin, *prev; - struct os_time now; + struct os_reltime now; - os_get_time(&now); + os_get_reltime(&now); dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) { if ((pin->flags & PIN_EXPIRES) && - os_time_before(&pin->expiration, &now)) { + os_reltime_before(&pin->expiration, &now)) { wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID", pin->uuid, WPS_UUID_LEN); wps_registrar_remove_pin(reg, pin); @@ -830,7 +888,7 @@ static int wps_registrar_invalidate_wildcard_pin(struct wps_registrar *reg, { if (dev_pw && pin->pin && (dev_pw_len != pin->pin_len || - os_memcmp(dev_pw, pin->pin, dev_pw_len) != 0)) + os_memcmp_const(dev_pw, pin->pin, dev_pw_len) != 0)) continue; /* different PIN */ if (pin->wildcard_uuid) { wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID", @@ -872,6 +930,7 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, const u8 *uuid, size_t *pin_len) { struct wps_uuid_pin *pin, *found = NULL; + int wildcard = 0; wps_registrar_expire_pins(reg); @@ -889,9 +948,9 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (pin->wildcard_uuid == 1 || pin->wildcard_uuid == 2) { - wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " + wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " "PIN. Assigned it for this UUID-E"); - pin->wildcard_uuid++; + wildcard = 1; os_memcpy(pin->uuid, uuid, WPS_UUID_LEN); found = pin; break; @@ -907,12 +966,14 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, * that could otherwise avoid PIN invalidations. */ if (found->flags & PIN_LOCKED) { - wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not " + wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not " "allow concurrent re-use"); return NULL; } *pin_len = found->pin_len; found->flags |= PIN_LOCKED; + if (wildcard) + found->wildcard_uuid++; return found->pin; } @@ -934,7 +995,7 @@ int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid) dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { if (pin->wildcard_uuid == 3) { - wpa_printf(MSG_DEBUG, "WPS: Invalidating used " + wpa_printf(MSG_DEBUG, "WPS: Invalidating used " "wildcard PIN"); return wps_registrar_invalidate_pin(reg, uuid); } @@ -945,7 +1006,7 @@ int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid) return -1; } -#endif + static void wps_registrar_stop_pbc(struct wps_registrar *reg) { @@ -954,15 +1015,15 @@ static void wps_registrar_stop_pbc(struct wps_registrar *reg) os_memset(reg->p2p_dev_addr, 0, ETH_ALEN); wps_registrar_remove_authorized_mac(reg, (u8 *) "\xff\xff\xff\xff\xff\xff"); - wps_registrar_selected_registrar_changed(reg); + wps_registrar_selected_registrar_changed(reg, 0); } -static void wps_registrar_pbc_timeout(void *eloop_ctx) +static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx) { struct wps_registrar *reg = eloop_ctx; - wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode"); + wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode"); wps_pbc_timeout_event(reg->wps); wps_registrar_stop_pbc(reg); } @@ -987,12 +1048,12 @@ int wps_registrar_button_pushed(struct wps_registrar *reg, { if (p2p_dev_addr == NULL && wps_registrar_pbc_overlap(reg, NULL, NULL)) { - wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC " + wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC " "mode"); wps_pbc_overlap_event(reg->wps); return -2; } - wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started"); + wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started"); reg->force_pbc_overlap = 0; reg->selected_registrar = 1; reg->pbc = 1; @@ -1002,28 +1063,34 @@ int wps_registrar_button_pushed(struct wps_registrar *reg, os_memset(reg->p2p_dev_addr, 0, ETH_ALEN); wps_registrar_add_authorized_mac(reg, (u8 *) "\xff\xff\xff\xff\xff\xff"); - wps_registrar_selected_registrar_changed(reg); + wps_registrar_selected_registrar_changed(reg, 0); + wps_pbc_active_event(reg->wps); + eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); + eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout, + reg, NULL); return 0; } static void wps_registrar_pbc_completed(struct wps_registrar *reg) { - wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode"); - + wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode"); + eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); wps_registrar_stop_pbc(reg); + wps_pbc_disable_event(reg->wps); } -#ifdef CONFIG_WPS_PIN static void wps_registrar_pin_completed(struct wps_registrar *reg) { - wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar"); + wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar"); + eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); reg->selected_registrar = 0; - wps_registrar_selected_registrar_changed(reg); + wps_registrar_selected_registrar_changed(reg, 0); } -#endif + void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e, const u8 *dev_pw, size_t dev_pw_len) @@ -1032,40 +1099,36 @@ void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e, wps_registrar_remove_pbc_session(registrar, uuid_e, NULL); wps_registrar_pbc_completed(registrar); - os_get_time(®istrar->pbc_ignore_start); +#ifdef WPS_WORKAROUNDS + os_get_reltime(®istrar->pbc_ignore_start); +#endif /* WPS_WORKAROUNDS */ os_memcpy(registrar->pbc_ignore_uuid, uuid_e, WPS_UUID_LEN); } else { -#ifdef CONFIG_WPS_PIN wps_registrar_pin_completed(registrar); -#endif } -#ifdef CONFIG_WPS_PIN + if (dev_pw && wps_registrar_invalidate_wildcard_pin(registrar, dev_pw, dev_pw_len) == 0) { wpa_hexdump_key(MSG_DEBUG, "WPS: Invalidated wildcard PIN", dev_pw, dev_pw_len); } -#endif } int wps_registrar_wps_cancel(struct wps_registrar *reg) { if (reg->pbc) { - wpa_printf(MSG_DEBUG, "WPS: PBC is set - cancelling it"); - wps_registrar_pbc_timeout(reg); - + wpa_printf(MSG_DEBUG, "WPS: PBC is set - cancelling it"); + wps_registrar_pbc_timeout(reg, NULL); + eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); return 1; } else if (reg->selected_registrar) { -#ifdef CONFIG_WPS_PIN - /* PIN Method */ - wpa_printf(MSG_DEBUG, "WPS: PIN is set - cancelling it"); + wpa_printf(MSG_DEBUG, "WPS: PIN is set - cancelling it"); wps_registrar_pin_completed(reg); wps_registrar_invalidate_wildcard_pin(reg, NULL, 0); return 1; -#endif } return 0; } @@ -1096,13 +1159,13 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, return; if (attr.config_methods == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in " + wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in " "Probe Request"); return; } if (attr.dev_password_id == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Device Password Id attribute " + wpa_printf(MSG_DEBUG, "WPS: No Device Password Id attribute " "in Probe Request"); return; } @@ -1111,7 +1174,7 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, attr.primary_dev_type && attr.request_type && !p2p_wildcard) { char *dev_name = NULL; if (attr.dev_name) { - dev_name = (char *)os_zalloc(attr.dev_name_len + 1); + dev_name = os_zalloc(attr.dev_name_len + 1); if (dev_name) { os_memcpy(dev_name, attr.dev_name, attr.dev_name_len); @@ -1128,10 +1191,10 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, if (WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) return; /* Not PBC */ - wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from " + wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from " MACSTR, MAC2STR(addr)); if (attr.uuid_e == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Probe Request WPS IE: No " + wpa_printf(MSG_DEBUG, "WPS: Invalid Probe Request WPS IE: No " "UUID-E included"); return; } @@ -1141,11 +1204,11 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, #ifdef WPS_WORKAROUNDS if (reg->pbc_ignore_start.sec && os_memcmp(attr.uuid_e, reg->pbc_ignore_uuid, WPS_UUID_LEN) == 0) { - struct os_time now, dur; - os_get_time(&now); - os_time_sub(&now, ®->pbc_ignore_start, &dur); + struct os_reltime now, dur; + os_get_reltime(&now); + os_reltime_sub(&now, ®->pbc_ignore_start, &dur); if (dur.sec >= 0 && dur.sec < 5) { - wpa_printf(MSG_DEBUG, "WPS: Ignore PBC activation " + wpa_printf(MSG_DEBUG, "WPS: Ignore PBC activation " "based on Probe Request from the Enrollee " "that just completed PBC provisioning"); skip_add = 1; @@ -1157,23 +1220,23 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, if (!skip_add) wps_registrar_add_pbc_session(reg, addr, attr.uuid_e); if (wps_registrar_pbc_overlap(reg, addr, attr.uuid_e)) { - wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected"); + wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected"); reg->force_pbc_overlap = 1; wps_pbc_overlap_event(reg->wps); } } -static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, - const u8 *psk, size_t psk_len) +int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, + const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len) { if (reg->new_psk_cb == NULL) return 0; - return reg->new_psk_cb(reg->cb_ctx, mac_addr, psk, psk_len); + return reg->new_psk_cb(reg->cb_ctx, mac_addr, p2p_dev_addr, psk, + psk_len); } -#ifdef CONFIG_WPS_PIN static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e, const struct wps_device_data *dev) @@ -1183,7 +1246,7 @@ static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e, reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev); } -#endif + static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr, const u8 *uuid_e, const u8 *dev_pw, @@ -1211,15 +1274,13 @@ static void wps_cb_set_sel_reg(struct wps_registrar *reg) if (reg->selected_registrar) { methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; -#ifdef CONFIG_WPS2 methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_PUSHBUTTON); -#endif /* CONFIG_WPS2 */ if (reg->pbc) wps_set_pushbutton(&methods, reg->wps->config_methods); } - wpa_printf(MSG_DEBUG, "WPS: wps_cb_set_sel_reg: sel_reg=%d " + wpa_printf(MSG_DEBUG, "WPS: wps_cb_set_sel_reg: sel_reg=%d " "config_methods=0x%x pbc=%d methods=0x%x", reg->selected_registrar, reg->wps->config_methods, reg->pbc, methods); @@ -1230,6 +1291,15 @@ static void wps_cb_set_sel_reg(struct wps_registrar *reg) } +static int wps_cp_lookup_pskfile(struct wps_registrar *reg, const u8 *mac_addr, + const u8 **psk) +{ + if (!reg->lookup_pskfile_cb) + return 0; + return reg->lookup_pskfile_cb(reg->cb_ctx, mac_addr, psk); +} + + static int wps_set_ie(struct wps_registrar *reg) { struct wpabuf *beacon; @@ -1250,17 +1320,13 @@ static int wps_set_ie(struct wps_registrar *reg) } beacon = wpabuf_alloc(400 + vendor_len); - if (beacon == NULL) - return -1; probe = wpabuf_alloc(500 + vendor_len); - if (probe == NULL) { - wpabuf_free(beacon); - return -1; - } + if (!beacon || !probe) + goto fail; auth_macs = wps_authorized_macs(reg, &count); - wpa_printf(MSG_DEBUG, "WPS: Build Beacon IEs"); + wpa_printf(MSG_DEBUG, "WPS: Build Beacon IEs"); if (wps_build_version(beacon) || wps_build_wps_state(reg->wps, beacon) || @@ -1269,24 +1335,19 @@ static int wps_set_ie(struct wps_registrar *reg) wps_build_sel_reg_dev_password_id(reg, beacon) || wps_build_sel_reg_config_methods(reg, beacon) || wps_build_sel_pbc_reg_uuid_e(reg, beacon) || - (reg->dualband && wps_build_rf_bands(®->wps->dev, beacon)) || - wps_build_wfa_ext(beacon, 0, auth_macs, count) || - wps_build_vendor_ext(®->wps->dev, beacon)) { - wpabuf_free(beacon); - wpabuf_free(probe); - return -1; - } + (reg->dualband && wps_build_rf_bands(®->wps->dev, beacon, 0)) || + wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) || + wps_build_vendor_ext(®->wps->dev, beacon) || + wps_build_application_ext(®->wps->dev, beacon)) + goto fail; #ifdef CONFIG_P2P if (wps_build_dev_name(®->wps->dev, beacon) || - wps_build_primary_dev_type(®->wps->dev, beacon)) { - wpabuf_free(beacon); - wpabuf_free(probe); - return -1; - } + wps_build_primary_dev_type(®->wps->dev, beacon)) + goto fail; #endif /* CONFIG_P2P */ - wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs"); + wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs"); if (wps_build_version(probe) || wps_build_wps_state(reg->wps, probe) || @@ -1299,46 +1360,23 @@ static int wps_set_ie(struct wps_registrar *reg) wps_build_uuid_e(probe, reg->wps->uuid) || wps_build_device_attrs(®->wps->dev, probe) || wps_build_probe_config_methods(reg, probe) || - (reg->dualband && wps_build_rf_bands(®->wps->dev, probe)) || - wps_build_wfa_ext(probe, 0, auth_macs, count) || - wps_build_vendor_ext(®->wps->dev, probe)) { - wpabuf_free(beacon); - wpabuf_free(probe); - return -1; - } + (reg->dualband && wps_build_rf_bands(®->wps->dev, probe, 0)) || + wps_build_wfa_ext(probe, 0, auth_macs, count, 0) || + wps_build_vendor_ext(®->wps->dev, probe) || + wps_build_application_ext(®->wps->dev, probe)) + goto fail; beacon = wps_ie_encapsulate(beacon); probe = wps_ie_encapsulate(probe); - if (!beacon || !probe) { - wpabuf_free(beacon); - wpabuf_free(probe); - return -1; - } - - if (reg->static_wep_only) { - /* - * Windows XP and Vista clients can get confused about - * EAP-Identity/Request when they probe the network with - * EAPOL-Start. In such a case, they may assume the network is - * using IEEE 802.1X and prompt user for a certificate while - * the correct (non-WPS) behavior would be to ask for the - * static WEP key. As a workaround, use Microsoft Provisioning - * IE to advertise that legacy 802.1X is not supported. - */ - const u8 ms_wps[7] = { - WLAN_EID_VENDOR_SPECIFIC, 5, - /* Microsoft Provisioning IE (00:50:f2:5) */ - 0x00, 0x50, 0xf2, 5, - 0x00 /* no legacy 802.1X or MS WPS */ - }; - wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE " - "into Beacon/Probe Response frames"); - wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps)); - wpabuf_put_data(probe, ms_wps, sizeof(ms_wps)); - } + if (!beacon || !probe) + goto fail; return wps_cb_set_ie(reg, beacon, probe); +fail: + wpabuf_free(beacon); + wpabuf_free(probe); + return -1; } @@ -1347,39 +1385,57 @@ static int wps_get_dev_password(struct wps_data *wps) const u8 *pin; size_t pin_len = 0; - os_free(wps->dev_password); + bin_clear_free(wps->dev_password, wps->dev_password_len); wps->dev_password = NULL; if (wps->pbc) { - wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC"); + wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC"); pin = (const u8 *) "00000000"; pin_len = 8; #ifdef CONFIG_WPS_NFC } else if (wps->nfc_pw_token) { - wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC " + if (wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) + { + wpa_printf(MSG_DEBUG, "WPS: Using NFC connection " + "handover and abbreviated WPS handshake " + "without Device Password"); + return 0; + } + wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC " "Password Token"); pin = wps->nfc_pw_token->dev_pw; pin_len = wps->nfc_pw_token->dev_pw_len; + } else if (wps->dev_pw_id >= 0x10 && + wps->wps->ap_nfc_dev_pw_id == wps->dev_pw_id && + wps->wps->ap_nfc_dev_pw) { + wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from own NFC Password Token"); + pin = wpabuf_head(wps->wps->ap_nfc_dev_pw); + pin_len = wpabuf_len(wps->wps->ap_nfc_dev_pw); #endif /* CONFIG_WPS_NFC */ } else { -#ifdef CONFIG_WPS_PIN - pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e, &pin_len); + if (pin && wps->dev_pw_id >= 0x10) { + wpa_printf(MSG_DEBUG, "WPS: No match for OOB Device " + "Password ID, but PIN found"); + /* + * See whether Enrollee is willing to use PIN instead. + */ + wps->dev_pw_id = DEV_PW_DEFAULT; + } } if (pin == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Device Password available for " - "the Enrollee"); + wpa_printf(MSG_DEBUG, "WPS: No Device Password available for " + "the Enrollee (context %p registrar %p)", + wps->wps, wps->wps->registrar); wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e, &wps->peer_dev); return -1; -#endif } - wps->dev_password = (u8 *)os_malloc(pin_len); + wps->dev_password = os_memdup(pin, pin_len); if (wps->dev_password == NULL) return -1; - os_memcpy(wps->dev_password, pin, pin_len); wps->dev_password_len = pin_len; return 0; @@ -1388,7 +1444,7 @@ static int wps_get_dev_password(struct wps_data *wps) static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * UUID-R"); + wpa_printf(MSG_DEBUG, "WPS: * UUID-R"); wpabuf_put_be16(msg, ATTR_UUID_R); wpabuf_put_be16(msg, WPS_UUID_LEN); wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN); @@ -1409,12 +1465,12 @@ static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg) wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { - wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " + wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " "R-Hash derivation"); return -1; } - wpa_printf(MSG_DEBUG, "WPS: * R-Hash1"); + wpa_printf(MSG_DEBUG, "WPS: * R-Hash1"); wpabuf_put_be16(msg, ATTR_R_HASH1); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); @@ -1430,7 +1486,7 @@ static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg) hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN); - wpa_printf(MSG_DEBUG, "WPS: * R-Hash2"); + wpa_printf(MSG_DEBUG, "WPS: * R-Hash2"); wpabuf_put_be16(msg, ATTR_R_HASH2); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); @@ -1446,7 +1502,7 @@ static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg) static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1"); + wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1"); wpabuf_put_be16(msg, ATTR_R_SNONCE1); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); @@ -1456,7 +1512,7 @@ static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg) static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2"); + wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2"); wpabuf_put_be16(msg, ATTR_R_SNONCE2); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, @@ -1468,7 +1524,7 @@ static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_network_idx(struct wpabuf *msg, const struct wps_credential *cred) { - wpa_printf(MSG_DEBUG, "WPS: * Network Index (1)"); + wpa_printf(MSG_DEBUG, "WPS: * Network Index (1)"); wpabuf_put_be16(msg, ATTR_NETWORK_INDEX); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); @@ -1479,7 +1535,7 @@ static int wps_build_cred_network_idx(struct wpabuf *msg, static int wps_build_cred_ssid(struct wpabuf *msg, const struct wps_credential *cred) { - wpa_printf(MSG_DEBUG, "WPS: * SSID"); + wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID for Credential", cred->ssid, cred->ssid_len); wpabuf_put_be16(msg, ATTR_SSID); @@ -1492,7 +1548,7 @@ static int wps_build_cred_ssid(struct wpabuf *msg, static int wps_build_cred_auth_type(struct wpabuf *msg, const struct wps_credential *cred) { - wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", + wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", cred->auth_type); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); @@ -1504,7 +1560,7 @@ static int wps_build_cred_auth_type(struct wpabuf *msg, static int wps_build_cred_encr_type(struct wpabuf *msg, const struct wps_credential *cred) { - wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", + wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", cred->encr_type); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); @@ -1516,7 +1572,7 @@ static int wps_build_cred_encr_type(struct wpabuf *msg, static int wps_build_cred_network_key(struct wpabuf *msg, const struct wps_credential *cred) { - wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%d)", + wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%d)", (int) cred->key_len); wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", cred->key, cred->key_len); @@ -1527,18 +1583,6 @@ static int wps_build_cred_network_key(struct wpabuf *msg, } -static int wps_build_cred_mac_addr(struct wpabuf *msg, - const struct wps_credential *cred) -{ - wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", - MAC2STR(cred->mac_addr)); - wpabuf_put_be16(msg, ATTR_MAC_ADDR); - wpabuf_put_be16(msg, ETH_ALEN); - wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN); - return 0; -} - - static int wps_build_credential(struct wpabuf *msg, const struct wps_credential *cred) { @@ -1547,7 +1591,7 @@ static int wps_build_credential(struct wpabuf *msg, wps_build_cred_auth_type(msg, cred) || wps_build_cred_encr_type(msg, cred) || wps_build_cred_network_key(msg, cred) || - wps_build_cred_mac_addr(msg, cred)) + wps_build_mac_addr(msg, cred->mac_addr)) return -1; return 0; } @@ -1561,13 +1605,13 @@ int wps_build_credential_wrap(struct wpabuf *msg, if (wbuf == NULL) return -1; if (wps_build_credential(wbuf, cred)) { - wpabuf_free(wbuf); + wpabuf_clear_free(wbuf); return -1; } wpabuf_put_be16(msg, ATTR_CRED); wpabuf_put_be16(msg, wpabuf_len(wbuf)); wpabuf_put_buf(msg, wbuf); - wpabuf_free(wbuf); + wpabuf_clear_free(wbuf); return 0; } @@ -1575,54 +1619,95 @@ int wps_build_credential_wrap(struct wpabuf *msg, int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *cred; + struct wps_registrar *reg = wps->wps->registrar; + const u8 *pskfile_psk; + char hex[65]; if (wps->wps->registrar->skip_cred_build) goto skip_cred_build; - wpa_printf(MSG_DEBUG, "WPS: * Credential"); + wpa_printf(MSG_DEBUG, "WPS: * Credential"); if (wps->use_cred) { os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred)); goto use_provided; } os_memset(&wps->cred, 0, sizeof(wps->cred)); + if (wps->peer_dev.multi_ap_ext == MULTI_AP_BACKHAUL_STA && + reg->multi_ap_backhaul_ssid_len) { + wpa_printf(MSG_DEBUG, "WPS: Use backhaul STA credentials"); + os_memcpy(wps->cred.ssid, reg->multi_ap_backhaul_ssid, + reg->multi_ap_backhaul_ssid_len); + wps->cred.ssid_len = reg->multi_ap_backhaul_ssid_len; + /* Backhaul is always WPA2PSK */ + wps->cred.auth_type = WPS_AUTH_WPA2PSK; + wps->cred.encr_type = WPS_ENCR_AES; + /* Set MAC address in the Credential to be the Enrollee's MAC + * address + */ + os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN); + if (reg->multi_ap_backhaul_network_key) { + os_memcpy(wps->cred.key, + reg->multi_ap_backhaul_network_key, + reg->multi_ap_backhaul_network_key_len); + wps->cred.key_len = + reg->multi_ap_backhaul_network_key_len; + } + goto use_provided; + } + os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len); wps->cred.ssid_len = wps->wps->ssid_len; /* Select the best authentication and encryption type */ + wpa_printf(MSG_DEBUG, + "WPS: Own auth types 0x%x - masked Enrollee auth types 0x%x", + wps->wps->auth_types, wps->auth_type); if (wps->auth_type & WPS_AUTH_WPA2PSK) wps->auth_type = WPS_AUTH_WPA2PSK; +#ifndef CONFIG_NO_TKIP else if (wps->auth_type & WPS_AUTH_WPAPSK) wps->auth_type = WPS_AUTH_WPAPSK; - else if (wps->auth_type & WPS_WIFI_AUTH_OPEN) - wps->auth_type = WPS_WIFI_AUTH_OPEN; - else if (wps->auth_type & WPS_AUTH_SHARED) - wps->auth_type = WPS_AUTH_SHARED; +#endif /* CONFIG_NO_TKIP */ + else if (wps->auth_type & WPS_AUTH_OPEN) + wps->auth_type = WPS_AUTH_OPEN; else { - wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x", + wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x", wps->auth_type); return -1; } wps->cred.auth_type = wps->auth_type; + wpa_printf(MSG_DEBUG, + "WPS: Own encr types 0x%x (rsn: 0x%x, wpa: 0x%x) - masked Enrollee encr types 0x%x", + wps->wps->encr_types, wps->wps->encr_types_rsn, + wps->wps->encr_types_wpa, wps->encr_type); + if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPA2PSK) + wps->encr_type &= wps->wps->encr_types_rsn; + else if (wps->wps->ap && wps->auth_type == WPS_AUTH_WPAPSK) + wps->encr_type &= wps->wps->encr_types_wpa; if (wps->auth_type == WPS_AUTH_WPA2PSK || wps->auth_type == WPS_AUTH_WPAPSK) { if (wps->encr_type & WPS_ENCR_AES) wps->encr_type = WPS_ENCR_AES; +#ifndef CONFIG_NO_TKIP else if (wps->encr_type & WPS_ENCR_TKIP) wps->encr_type = WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ else { - wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " + wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " "type for WPA/WPA2"); return -1; } } else { - if (wps->encr_type & WPS_ENCR_WEP) - wps->encr_type = WPS_ENCR_WEP; - else if (wps->encr_type & WPS_ENCR_NONE) + if (wps->encr_type & WPS_ENCR_NONE) wps->encr_type = WPS_ENCR_NONE; +#ifdef CONFIG_TESTING_OPTIONS + else if (wps->encr_type & WPS_ENCR_WEP) + wps->encr_type = WPS_ENCR_WEP; +#endif /* CONFIG_TESTING_OPTIONS */ else { - wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " + wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " "type for non-WPA/WPA2 mode"); return -1; } @@ -1637,19 +1722,24 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) !wps->wps->registrar->disable_auto_conf) { u8 r[16]; /* Generate a random passphrase */ - if (random_get_bytes(r, sizeof(r)) < 0) + if (random_pool_ready() != 1 || + random_get_bytes(r, sizeof(r)) < 0) { + wpa_printf(MSG_INFO, + "WPS: Could not generate random PSK"); return -1; + } os_free(wps->new_psk); - wps->new_psk = (u8 *)base64_encode(r, sizeof(r), &wps->new_psk_len); + wps->new_psk = (u8 *) base64_encode(r, sizeof(r), + &wps->new_psk_len); if (wps->new_psk == NULL) return -1; wps->new_psk_len--; /* remove newline */ while (wps->new_psk_len && - wps->new_psk[wps->new_psk_len - 1] == '=') // NOLINT(clang-analyzer-unix.Malloc) + wps->new_psk[wps->new_psk_len - 1] == '=') wps->new_psk_len--; wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase", wps->new_psk, wps->new_psk_len); - os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len); // NOLINT(clang-analyzer-unix.Malloc) + os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len); wps->cred.key_len = wps->new_psk_len; } else if (wps->use_psk_key && wps->wps->psk_set) { char hex[65] = {0}; @@ -1661,43 +1751,47 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) wps->wps->network_key_len); wps->cred.key_len = wps->wps->network_key_len; } else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) { - char hex[65]; /* Generate a random per-device PSK */ os_free(wps->new_psk); - wps->new_psk_len = 32; - wps->new_psk = (u8 *)os_malloc(wps->new_psk_len); + wps->new_psk_len = PMK_LEN; + wps->new_psk = os_malloc(wps->new_psk_len); if (wps->new_psk == NULL) return -1; - if (random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) { + if (random_pool_ready() != 1 || + random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) { + wpa_printf(MSG_INFO, + "WPS: Could not generate random PSK"); os_free(wps->new_psk); wps->new_psk = NULL; return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK", wps->new_psk, wps->new_psk_len); + wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk, + wps->new_psk_len); os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2); wps->cred.key_len = wps->new_psk_len * 2; } use_provided: #ifdef CONFIG_WPS_TESTING - if (wps_testing_dummy_cred) + if (wps_testing_stub_cred) cred = wpabuf_alloc(200); else cred = NULL; if (cred) { - struct wps_credential dummy; - wpa_printf(MSG_DEBUG, "WPS: Add dummy credential"); - os_memset(&dummy, 0, sizeof(dummy)); - os_memcpy(dummy.ssid, "dummy", 5); - dummy.ssid_len = 5; - dummy.auth_type = WPS_AUTH_WPA2PSK; - dummy.encr_type = WPS_ENCR_AES; - os_memcpy(dummy.key, "dummy psk", 9); - dummy.key_len = 9; - os_memcpy(dummy.mac_addr, wps->mac_addr_e, ETH_ALEN); - wps_build_credential(cred, &dummy); - wpa_hexdump_buf(MSG_DEBUG, "WPS: Dummy Credential", cred); + struct wps_credential stub; + wpa_printf(MSG_DEBUG, "WPS: Add stub credential"); + os_memset(&stub, 0, sizeof(stub)); + os_memcpy(stub.ssid, "stub", 5); + stub.ssid_len = 5; + stub.auth_type = WPS_AUTH_WPA2PSK; + stub.encr_type = WPS_ENCR_AES; + os_memcpy(stub.key, "stub psk", 9); + stub.key_len = 9; + os_memcpy(stub.mac_addr, wps->mac_addr_e, ETH_ALEN); + wps_build_credential(cred, &stub); + wpa_hexdump_buf(MSG_DEBUG, "WPS: Stub Credential", cred); wpabuf_put_be16(msg, ATTR_CRED); wpabuf_put_be16(msg, wpabuf_len(cred)); @@ -1712,18 +1806,18 @@ use_provided: return -1; if (wps_build_credential(cred, &wps->cred)) { - wpabuf_free(cred); + wpabuf_clear_free(cred); return -1; } wpabuf_put_be16(msg, ATTR_CRED); wpabuf_put_be16(msg, wpabuf_len(cred)); wpabuf_put_buf(msg, cred); - wpabuf_free(cred); + wpabuf_clear_free(cred); skip_cred_build: if (wps->wps->registrar->extra_cred) { - wpa_printf(MSG_DEBUG, "WPS: * Credential (pre-configured)"); + wpa_printf(MSG_DEBUG, "WPS: * Credential (pre-configured)"); wpabuf_put_buf(msg, wps->wps->registrar->extra_cred); } @@ -1733,7 +1827,7 @@ skip_cred_build: static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg) { - wpa_printf(MSG_DEBUG, "WPS: * AP Settings"); + wpa_printf(MSG_DEBUG, "WPS: * AP Settings"); if (wps_build_credential(msg, &wps->cred)) return -1; @@ -1757,7 +1851,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps) } if (wps_build_ap_settings(wps, plain)) { - wpabuf_free(plain); + wpabuf_clear_free(plain); wpabuf_free(msg); return NULL; } @@ -1765,7 +1859,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps) wpabuf_put_be16(msg, ATTR_CRED); wpabuf_put_be16(msg, wpabuf_len(plain)); wpabuf_put_buf(msg, plain); - wpabuf_free(plain); + wpabuf_clear_free(plain); return msg; } @@ -1774,6 +1868,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps) static struct wpabuf * wps_build_m2(struct wps_data *wps) { struct wpabuf *msg; + int config_in_m2 = 0; if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0) return NULL; @@ -1781,7 +1876,7 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps) wps->nonce_r, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); - wpa_printf(MSG_DEBUG, "WPS: Building Message M2"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M2"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; @@ -1791,26 +1886,54 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps) wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_uuid_r(wps, msg) || - wps_build_public_key(wps, msg, WPS_CALC_KEY_NORMAL) || + wps_build_public_key(wps, msg) || wps_derive_keys(wps) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods_r(wps->wps->registrar, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || - wps_build_rf_bands(&wps->wps->dev, msg) || + wps_build_rf_bands(&wps->wps->dev, msg, + wps->wps->rf_band_cb(wps->wps->cb_ctx)) || wps_build_assoc_state(wps, msg) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_os_version(&wps->wps->dev, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0) || - wps_build_authenticator(wps, msg)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { + wpabuf_free(msg); + return NULL; + } + +#ifdef CONFIG_WPS_NFC + if (wps->nfc_pw_token && wps->nfc_pw_token->pk_hash_provided_oob && + wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) { + /* + * Use abbreviated handshake since public key hash allowed + * Enrollee to validate our public key similarly to how Enrollee + * public key was validated. There is no need to validate Device + * Password in this case. + */ + struct wpabuf *plain = wpabuf_alloc(500); + if (plain == NULL || + wps_build_cred(wps, plain) || + wps_build_key_wrap_auth(wps, plain) || + wps_build_encr_settings(wps, msg, plain)) { + wpabuf_free(msg); + wpabuf_clear_free(plain); + return NULL; + } + wpabuf_clear_free(plain); + config_in_m2 = 1; + } +#endif /* CONFIG_WPS_NFC */ + + if (wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->int_reg = 1; - wps->state = RECV_M3; + wps->state = config_in_m2 ? RECV_DONE : RECV_M3; return msg; } @@ -1820,7 +1943,7 @@ static struct wpabuf * wps_build_m2d(struct wps_data *wps) struct wpabuf *msg; u16 err = wps->config_error; - wpa_printf(MSG_DEBUG, "WPS: Building Message M2D"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M2D"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; @@ -1839,11 +1962,12 @@ static struct wpabuf * wps_build_m2d(struct wps_data *wps) wps_build_conn_type_flags(wps, msg) || wps_build_config_methods_r(wps->wps->registrar, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || - wps_build_rf_bands(&wps->wps->dev, msg) || + wps_build_rf_bands(&wps->wps->dev, msg, + wps->wps->rf_band_cb(wps->wps->cb_ctx)) || wps_build_assoc_state(wps, msg) || wps_build_config_error(msg, err) || wps_build_os_version(&wps->wps->dev, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -1857,9 +1981,10 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps) { struct wpabuf *msg, *plain; - wpa_printf(MSG_DEBUG, "WPS: Building Message M4"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M4"); - wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); + if (wps_derive_psk(wps, wps->dev_password, wps->dev_password_len) < 0) + return NULL; plain = wpabuf_alloc(200); if (plain == NULL) @@ -1878,13 +2003,13 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps) wps_build_r_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { - wpabuf_free(plain); + wpabuf_clear_free(plain); wpabuf_free(msg); return NULL; } - wpabuf_free(plain); + wpabuf_clear_free(plain); wps->state = RECV_M5; return msg; @@ -1895,7 +2020,7 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps) { struct wpabuf *msg, *plain; - wpa_printf(MSG_DEBUG, "WPS: Building Message M6"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M6"); plain = wpabuf_alloc(200); if (plain == NULL) @@ -1913,13 +2038,13 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps) wps_build_r_snonce2(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { - wpabuf_free(plain); + wpabuf_clear_free(plain); wpabuf_free(msg); return NULL; } - wpabuf_free(plain); + wpabuf_clear_free(plain); wps->wps_pin_revealed = 1; wps->state = RECV_M7; @@ -1931,7 +2056,7 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps) { struct wpabuf *msg, *plain; - wpa_printf(MSG_DEBUG, "WPS: Building Message M8"); + wpa_printf(MSG_DEBUG, "WPS: Building Message M8"); plain = wpabuf_alloc(500); if (plain == NULL) @@ -1950,13 +2075,13 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps) (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { - wpabuf_free(plain); - wpabuf_free(msg); + wpabuf_clear_free(plain); + wpabuf_clear_free(msg); return NULL; } - wpabuf_free(plain); + wpabuf_clear_free(plain); wps->state = RECV_DONE; return msg; @@ -1980,7 +2105,7 @@ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, p = p->next; } if (p) { - wpa_printf(MSG_DEBUG, "WPS: Use pending message from " + wpa_printf(MSG_DEBUG, "WPS: Use pending message from " "UPnP"); if (prev) prev->next = NULL; @@ -2005,7 +2130,7 @@ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, } } if (wps->ext_reg) { - wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no " + wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no " "pending message available"); return NULL; } @@ -2044,7 +2169,7 @@ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, *op_code = WSC_NACK; break; default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " + wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " "a message", wps->state); msg = NULL; break; @@ -2064,7 +2189,7 @@ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) { if (e_nonce == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); + wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); return -1; } @@ -2079,12 +2204,12 @@ static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) { if (r_nonce == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); + wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); return -1; } if (os_memcmp(wps->nonce_r, r_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received"); + wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received"); return -1; } @@ -2095,7 +2220,7 @@ static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e) { if (uuid_e == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No UUID-E received"); + wpa_printf(MSG_DEBUG, "WPS: No UUID-E received"); return -1; } @@ -2109,12 +2234,12 @@ static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e) static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id) { if (pw_id == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received"); + wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received"); return -1; } wps->dev_pw_id = WPA_GET_BE16(pw_id); - wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id); + wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id); return 0; } @@ -2123,7 +2248,7 @@ static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id) static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1) { if (e_hash1 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received"); + wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received"); return -1; } @@ -2137,7 +2262,7 @@ static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1) static int wps_process_e_hash2(struct wps_data *wps, const u8 *e_hash2) { if (e_hash2 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received"); + wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received"); return -1; } @@ -2155,7 +2280,7 @@ static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1) size_t len[4]; if (e_snonce1 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received"); + wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received"); return -1; } @@ -2172,15 +2297,16 @@ static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1) addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does " + + if (os_memcmp_const(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; - wps_pwd_auth_fail_event(wps->wps, 0, 1); + wps_pwd_auth_fail_event(wps->wps, 0, 1, wps->mac_addr_e); return -1; } - wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first " + wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first " "half of the device password"); return 0; @@ -2194,7 +2320,7 @@ static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2) size_t len[4]; if (e_snonce2 == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received"); + wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received"); return -1; } @@ -2210,23 +2336,20 @@ static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2) len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); - hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); - if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does " + + if (os_memcmp_const(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does " "not match with the pre-committed value"); -#ifdef CONFIG_WPS_PIN wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); -#endif wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; - wps_pwd_auth_fail_event(wps->wps, 0, 2); + wps_pwd_auth_fail_event(wps->wps, 0, 2, wps->mac_addr_e); return -1; } - wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second " + wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second " "half of the device password"); wps->wps_pin_revealed = 0; -#ifdef CONFIG_WPS_PIN wps_registrar_unlock_pin(wps->wps->registrar, wps->uuid_e); /* @@ -2235,7 +2358,7 @@ static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2) * sure the PIN gets invalidated here. */ wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); -#endif + return 0; } @@ -2243,11 +2366,11 @@ static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2) static int wps_process_mac_addr(struct wps_data *wps, const u8 *mac_addr) { if (mac_addr == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No MAC Address received"); + wpa_printf(MSG_DEBUG, "WPS: No MAC Address received"); return -1; } - wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR, + wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR, MAC2STR(mac_addr)); os_memcpy(wps->mac_addr_e, mac_addr, ETH_ALEN); os_memcpy(wps->peer_dev.mac_addr, mac_addr, ETH_ALEN); @@ -2260,7 +2383,7 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, size_t pk_len) { if (pk == NULL || pk_len == 0) { - wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); + wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); return -1; } @@ -2278,18 +2401,35 @@ static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth) u16 auth_types; if (auth == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags " + wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags " "received"); return -1; } auth_types = WPA_GET_BE16(auth); - wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x", + wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x", auth_types); +#ifdef WPS_WORKAROUNDS + /* + * Some deployed implementations seem to advertise incorrect information + * in this attribute. A value of 0x1b (WPA2 + WPA + WPAPSK + OPEN, but + * no WPA2PSK) has been reported to be used. Add WPA2PSK to the list to + * avoid issues with building Credentials that do not use the strongest + * actually supported authentication option (that device does support + * WPA2PSK even when it does not claim it here). + */ + if ((auth_types & + (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) == + (WPS_AUTH_WPA2 | WPS_AUTH_WPAPSK)) { + wpa_printf(MSG_DEBUG, + "WPS: Workaround - assume Enrollee supports WPA2PSK based on claimed WPA2 support"); + auth_types |= WPS_AUTH_WPA2PSK; + } +#endif /* WPS_WORKAROUNDS */ wps->auth_type = wps->wps->auth_types & auth_types; if (wps->auth_type == 0) { - wpa_printf(MSG_DEBUG, "WPS: No match in supported " + wpa_printf(MSG_DEBUG, "WPS: No match in supported " "authentication types (own 0x%x Enrollee 0x%x)", wps->wps->auth_types, auth_types); #ifdef WPS_WORKAROUNDS @@ -2300,7 +2440,7 @@ static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth) * In order to interoperate with existing implementations, * assume that the Enrollee supports everything we do. */ - wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " + wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " "does not advertise supported authentication types " "correctly"); wps->auth_type = wps->wps->auth_types; @@ -2318,18 +2458,18 @@ static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr) u16 encr_types; if (encr == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags " + wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags " "received"); return -1; } encr_types = WPA_GET_BE16(encr); - wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x", + wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x", encr_types); wps->encr_type = wps->wps->encr_types & encr_types; if (wps->encr_type == 0) { - wpa_printf(MSG_DEBUG, "WPS: No match in supported " + wpa_printf(MSG_DEBUG, "WPS: No match in supported " "encryption types (own 0x%x Enrollee 0x%x)", wps->wps->encr_types, encr_types); #ifdef WPS_WORKAROUNDS @@ -2340,7 +2480,7 @@ static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr) * In order to interoperate with existing implementations, * assume that the Enrollee supports everything we do. */ - wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " + wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " "does not advertise supported encryption types " "correctly"); wps->encr_type = wps->wps->encr_types; @@ -2356,12 +2496,12 @@ static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr) static int wps_process_conn_type_flags(struct wps_data *wps, const u8 *conn) { if (conn == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags " + wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags " "received"); return -1; } - wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x", + wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x", *conn); return 0; @@ -2373,13 +2513,13 @@ static int wps_process_config_methods(struct wps_data *wps, const u8 *methods) u16 m; if (methods == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Config Methods received"); + wpa_printf(MSG_DEBUG, "WPS: No Config Methods received"); return -1; } m = WPA_GET_BE16(methods); - wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x" + wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x" "%s%s%s%s%s%s%s%s%s", m, m & WPS_CONFIG_USBA ? " [USBA]" : "", m & WPS_CONFIG_ETHERNET ? " [Ethernet]" : "", @@ -2397,7 +2537,7 @@ static int wps_process_config_methods(struct wps_data *wps, const u8 *methods) * able to show the passphrase to a user and as such, could * benefit from receiving PSK to reduce key derivation time. */ - wpa_printf(MSG_DEBUG, "WPS: Prefer PSK format key due to " + wpa_printf(MSG_DEBUG, "WPS: Prefer PSK format key due to " "Enrollee not supporting display"); wps->use_psk_key = 1; } @@ -2409,12 +2549,12 @@ static int wps_process_config_methods(struct wps_data *wps, const u8 *methods) static int wps_process_wps_state(struct wps_data *wps, const u8 *state) { if (state == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State " + wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State " "received"); return -1; } - wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d", + wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d", *state); return 0; @@ -2423,19 +2563,15 @@ static int wps_process_wps_state(struct wps_data *wps, const u8 *state) static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc) { -#ifdef DEBUG_PRINT - u16 a; -#endif + u16 a; if (assoc == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Association State received"); + wpa_printf(MSG_DEBUG, "WPS: No Association State received"); return -1; } -#ifdef DEBUG_PRINT a = WPA_GET_BE16(assoc); -#endif - wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a); + wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a); return 0; } @@ -2443,19 +2579,15 @@ static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc) static int wps_process_config_error(struct wps_data *wps, const u8 *err) { -#ifdef DEBUG_PRINT - u16 e; -#endif + u16 e; if (err == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received"); + wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received"); return -1; } -#ifdef DEBUG_PRINT e = WPA_GET_BE16(err); -#endif - wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e); + wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e); return 0; } @@ -2470,7 +2602,7 @@ static int wps_registrar_p2p_dev_addr_match(struct wps_data *wps) return 1; /* no filtering in use */ if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: No match on P2P Device Address " + wpa_printf(MSG_DEBUG, "WPS: No match on P2P Device Address " "filtering for PBC: expected " MACSTR " was " MACSTR " - indicate PBC session overlap", MAC2STR(reg->p2p_dev_addr), @@ -2491,7 +2623,7 @@ static int wps_registrar_skip_overlap(struct wps_data *wps) return 0; /* no specific Enrollee selected */ if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, "WPS: Skip PBC overlap due to selected " + wpa_printf(MSG_DEBUG, "WPS: Skip PBC overlap due to selected " "Enrollee match"); return 1; } @@ -2503,10 +2635,10 @@ static int wps_registrar_skip_overlap(struct wps_data *wps) static enum wps_process_res wps_process_m1(struct wps_data *wps, struct wps_parse_attr *attr) { - wpa_printf(MSG_DEBUG, "WPS: Received M1"); + wpa_printf(MSG_DEBUG, "WPS: Received M1"); if (wps->state != RECV_M1) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M1", wps->state); return WPS_FAILURE; } @@ -2530,39 +2662,61 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, if (wps->dev_pw_id < 0x10 && wps->dev_pw_id != DEV_PW_DEFAULT && + wps->dev_pw_id != DEV_PW_P2PS_DEFAULT && wps->dev_pw_id != DEV_PW_USER_SPECIFIED && wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED && wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED && +#ifdef CONFIG_WPS_NFC + wps->dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && +#endif /* CONFIG_WPS_NFC */ (wps->dev_pw_id != DEV_PW_PUSHBUTTON || !wps->wps->registrar->pbc)) { - wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d", + wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d", wps->dev_pw_id); wps->state = SEND_M2D; return WPS_CONTINUE; } #ifdef CONFIG_WPS_NFC - if (wps->dev_pw_id >= 0x10) { + if (wps->dev_pw_id >= 0x10 || + wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) { struct wps_nfc_pw_token *token; const u8 *addr[1]; u8 hash[WPS_HASH_LEN]; + wpa_printf(MSG_DEBUG, "WPS: Searching for NFC token match for id=%d (ctx %p registrar %p)", + wps->dev_pw_id, wps->wps, wps->wps->registrar); token = wps_get_nfc_pw_token( &wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id); - if (token) { - wpa_printf(MSG_DEBUG, "WPS: Found matching NFC " + if (token && token->peer_pk_hash_known) { + size_t len; + + wpa_printf(MSG_DEBUG, "WPS: Found matching NFC " "Password Token"); dl_list_del(&token->list); wps->nfc_pw_token = token; addr[0] = attr->public_key; - sha256_vector(1, addr, &attr->public_key_len, hash); - if (os_memcmp(hash, wps->nfc_pw_token->pubkey_hash, - WPS_OOB_PUBKEY_HASH_LEN) != 0) { - wpa_printf(MSG_ERROR, "WPS: Public Key hash " + len = attr->public_key_len; + sha256_vector(1, addr, &len, hash); + if (os_memcmp_const(hash, + wps->nfc_pw_token->pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN) != 0) { + wpa_printf(MSG_ERROR, "WPS: Public Key hash " "mismatch"); - return WPS_FAILURE; + wps->state = SEND_M2D; + wps->config_error = + WPS_CFG_PUBLIC_KEY_HASH_MISMATCH; + return WPS_CONTINUE; } + } else if (token) { + wpa_printf(MSG_DEBUG, "WPS: Found matching NFC " + "Password Token (no peer PK hash)"); + wps->nfc_pw_token = token; + } else if (wps->dev_pw_id >= 0x10 && + wps->wps->ap_nfc_dev_pw_id == wps->dev_pw_id && + wps->wps->ap_nfc_dev_pw) { + wpa_printf(MSG_DEBUG, "WPS: Found match with own NFC Password Token"); } } #endif /* CONFIG_WPS_NFC */ @@ -2573,14 +2727,14 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, wps->mac_addr_e, wps->uuid_e) || !wps_registrar_p2p_dev_addr_match(wps)) && !wps_registrar_skip_overlap(wps)) { - wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC " + wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC " "negotiation"); wps->state = SEND_M2D; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; wps_pbc_overlap_event(wps->wps); wps_fail_event(wps->wps, WPS_M1, WPS_CFG_MULTIPLE_PBC_DETECTED, - WPS_EI_NO_ERROR); + WPS_EI_NO_ERROR, wps->mac_addr_e); wps->wps->registrar->force_pbc_overlap = 1; return WPS_CONTINUE; } @@ -2600,11 +2754,12 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, os_strncmp(wps->peer_dev.manufacturer, "Apple ", 6) == 0 && wps->peer_dev.model_name && os_strcmp(wps->peer_dev.model_name, "AirPort") == 0) { - wpa_printf(MSG_DEBUG, "WPS: Workaround - Force Network Key in " + wpa_printf(MSG_DEBUG, "WPS: Workaround - Force Network Key in " "PSK format"); wps->use_psk_key = 1; } #endif /* WPS_WORKAROUNDS */ + wps_process_vendor_ext_m1(&wps->peer_dev, attr->multi_ap_ext); wps->state = SEND_M2; return WPS_CONTINUE; @@ -2615,10 +2770,10 @@ static enum wps_process_res wps_process_m3(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { - wpa_printf(MSG_DEBUG, "WPS: Received M3"); + wpa_printf(MSG_DEBUG, "WPS: Received M3"); if (wps->state != RECV_M3) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M3", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; @@ -2626,7 +2781,7 @@ static enum wps_process_res wps_process_m3(struct wps_data *wps, if (wps->pbc && wps->wps->registrar->force_pbc_overlap && !wps_registrar_skip_overlap(wps)) { - wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " + wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; @@ -2653,10 +2808,10 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps, struct wpabuf *decrypted; struct wps_parse_attr eattr; - wpa_printf(MSG_DEBUG, "WPS: Received M5"); + wpa_printf(MSG_DEBUG, "WPS: Received M5"); if (wps->state != RECV_M5) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M5", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; @@ -2664,7 +2819,7 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps, if (wps->pbc && wps->wps->registrar->force_pbc_overlap && !wps_registrar_skip_overlap(wps)) { - wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " + wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; @@ -2680,28 +2835,28 @@ static enum wps_process_res wps_process_m5(struct wps_data *wps, decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_validate_m5_encr(decrypted, attr->version2 != NULL) < 0) { - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_e_snonce1(wps, eattr.e_snonce1)) { - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_M6; return WPS_CONTINUE; @@ -2723,7 +2878,7 @@ static void wps_sta_cred_cb(struct wps_data *wps) wps->cred.encr_type = WPS_ENCR_AES; else if (wps->cred.encr_type & WPS_ENCR_TKIP) wps->cred.encr_type = WPS_ENCR_TKIP; - wpa_printf(MSG_DEBUG, "WPS: Update local configuration based on the " + wpa_printf(MSG_DEBUG, "WPS: Update local configuration based on the " "AP configuration"); if (wps->wps->cred_cb) wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); @@ -2763,7 +2918,6 @@ static int wps_process_ap_settings_r(struct wps_data *wps, wps_cred_update(&wps->cred, wps->new_ap_settings); return 0; } else { -#ifdef CONFIG_WPS_PIN /* * Use the AP PIN only to receive the current AP settings, not * to reconfigure the AP. @@ -2774,7 +2928,7 @@ static int wps_process_ap_settings_r(struct wps_data *wps, * WSC_Done in this protocol run. */ wps_registrar_pin_completed(wps->wps->registrar); -#endif + msg = wps_build_ap_cred(wps); if (msg == NULL) return -1; @@ -2805,10 +2959,10 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps, struct wpabuf *decrypted; struct wps_parse_attr eattr; - wpa_printf(MSG_DEBUG, "WPS: Received M7"); + wpa_printf(MSG_DEBUG, "WPS: Received M7"); if (wps->state != RECV_M7) { - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M7", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; @@ -2816,7 +2970,7 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps, if (wps->pbc && wps->wps->registrar->force_pbc_overlap && !wps_registrar_skip_overlap(wps)) { - wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " + wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; @@ -2832,7 +2986,7 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps, decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { - wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt Encrypted " + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; @@ -2840,23 +2994,23 @@ static enum wps_process_res wps_process_m7(struct wps_data *wps, if (wps_validate_m7_encr(decrypted, wps->wps->ap || wps->er, attr->version2 != NULL) < 0) { - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } - wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_e_snonce2(wps, eattr.e_snonce2) || wps_process_ap_settings_r(wps, &eattr)) { - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } - wpabuf_free(decrypted); + wpabuf_clear_free(decrypted); wps->state = SEND_M8; return WPS_CONTINUE; @@ -2869,13 +3023,13 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, struct wps_parse_attr attr; enum wps_process_res ret = WPS_CONTINUE; - wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); + wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } @@ -2884,7 +3038,7 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } @@ -2911,7 +3065,7 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, ret = wps_process_m3(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M3, wps->config_error, - wps->error_indication); + wps->error_indication, wps->mac_addr_e); break; case WPS_M5: if (wps_validate_m5(msg) < 0) @@ -2919,7 +3073,7 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, ret = wps_process_m5(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M5, wps->config_error, - wps->error_indication); + wps->error_indication, wps->mac_addr_e); break; case WPS_M7: if (wps_validate_m7(msg) < 0) @@ -2927,10 +3081,10 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, ret = wps_process_m7(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M7, wps->config_error, - wps->error_indication); + wps->error_indication, wps->mac_addr_e); break; default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", + wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", *attr.msg_type); return WPS_FAILURE; } @@ -2951,18 +3105,18 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, { struct wps_parse_attr attr; - wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); + wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_ACK) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } @@ -2972,7 +3126,7 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, upnp_wps_subscribers(wps->wps->wps_upnp)) { if (wps->wps->upnp_msgs) return WPS_CONTINUE; - wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " + wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " "external Registrar"); return WPS_PENDING; } @@ -2981,13 +3135,13 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } @@ -2999,13 +3153,13 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, return WPS_CONTINUE; if (wps->ext_reg == 0) wps->ext_reg = 1; - wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " + wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " "external Registrar"); return WPS_PENDING; } #endif /* CONFIG_WPS_UPNP */ - wpa_printf(MSG_DEBUG, "WPS: No more registrars available - " + wpa_printf(MSG_DEBUG, "WPS: No more registrars available - " "terminate negotiation"); } @@ -3020,7 +3174,7 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, int old_state; u16 config_error; - wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); + wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); old_state = wps->state; wps->state = SEND_WSC_NACK; @@ -3029,19 +3183,19 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, return WPS_FAILURE; if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_NACK) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && wps->ext_reg) { - wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " + wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " "Registrar terminated by the Enrollee"); return WPS_FAILURE; } @@ -3050,42 +3204,42 @@ static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (attr.config_error == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " + wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " "in WSC_NACK"); return WPS_FAILURE; } config_error = WPA_GET_BE16(attr.config_error); - wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with " + wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with " "Configuration Error %d", config_error); switch (old_state) { case RECV_M3: wps_fail_event(wps->wps, WPS_M2, config_error, - wps->error_indication); + wps->error_indication, wps->mac_addr_e); break; case RECV_M5: wps_fail_event(wps->wps, WPS_M4, config_error, - wps->error_indication); + wps->error_indication, wps->mac_addr_e); break; case RECV_M7: wps_fail_event(wps->wps, WPS_M6, config_error, - wps->error_indication); + wps->error_indication, wps->mac_addr_e); break; case RECV_DONE: wps_fail_event(wps->wps, WPS_M8, config_error, - wps->error_indication); + wps->error_indication, wps->mac_addr_e); break; default: break; @@ -3100,10 +3254,11 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, { struct wps_parse_attr attr; - wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done"); + wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done"); - if (wps->state != RECV_DONE && (!wps->ext_reg)){ - wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + if (wps->state != RECV_DONE && + (!wps->wps->wps_upnp || !wps->ext_reg)) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving WSC_Done", wps->state); return WPS_FAILURE; } @@ -3112,19 +3267,19 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, return WPS_FAILURE; if (attr.msg_type == NULL) { - wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_DONE) { - wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && wps->ext_reg) { - wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " + wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " "Registrar completed successfully"); wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_e); @@ -3135,17 +3290,17 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } - wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully"); + wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully"); wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_e); @@ -3153,14 +3308,19 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, wps->wps->ap && !wps->wps->registrar->disable_auto_conf) { struct wps_credential cred; - wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " + wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " "on first Enrollee connection"); os_memset(&cred, 0, sizeof(cred)); os_memcpy(cred.ssid, wps->wps->ssid, wps->wps->ssid_len); cred.ssid_len = wps->wps->ssid_len; - cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; - cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; + if (wps->wps->rf_band_cb(wps->wps->cb_ctx) == WPS_RF_60GHZ) { + cred.auth_type = WPS_AUTH_WPA2PSK; + cred.encr_type = WPS_ENCR_AES; + } else { + cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; + cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; + } os_memcpy(cred.key, wps->new_psk, wps->new_psk_len); cred.key_len = wps->new_psk_len; @@ -3180,8 +3340,9 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, if (wps->new_psk) { if (wps_cb_new_psk(wps->wps->registrar, wps->mac_addr_e, - wps->new_psk, wps->new_psk_len)) { - wpa_printf(MSG_DEBUG, "WPS: Failed to configure the " + wps->p2p_dev_addr, wps->new_psk, + wps->new_psk_len)) { + wpa_printf(MSG_DEBUG, "WPS: Failed to configure the " "new PSK"); } os_free(wps->new_psk); @@ -3196,18 +3357,18 @@ static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, wps->uuid_e, wps->p2p_dev_addr); wps_registrar_pbc_completed(wps->wps->registrar); - os_get_time(&wps->wps->registrar->pbc_ignore_start); +#ifdef WPS_WORKAROUNDS + os_get_reltime(&wps->wps->registrar->pbc_ignore_start); +#endif /* WPS_WORKAROUNDS */ os_memcpy(wps->wps->registrar->pbc_ignore_uuid, wps->uuid_e, WPS_UUID_LEN); } else { -#ifdef CONFIG_WPS_PIN wps_registrar_pin_completed(wps->wps->registrar); -#endif } /* TODO: maintain AuthorizedMACs somewhere separately for each ER and * merge them into APs own list.. */ - wps_success_event(wps->wps); + wps_success_event(wps->wps, wps->mac_addr_e); return WPS_DONE; } @@ -3219,7 +3380,7 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, { enum wps_process_res ret; - wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " + wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " "op_code=%d)", (unsigned long) wpabuf_len(msg), op_code); @@ -3242,7 +3403,7 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, type = -1; else type = *attr.msg_type; - wpa_printf(MSG_DEBUG, "WPS: Sending received message (type %d)" + wpa_printf(MSG_DEBUG, "WPS: Sending received message (type %d)" " to external Registrar for processing", type); upnp_wps_device_send_wlan_event(wps->wps->wps_upnp, wps->mac_addr_e, @@ -3251,7 +3412,7 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, if (op_code == WSC_MSG) return WPS_PENDING; } else if (wps->wps->wps_upnp && wps->ext_reg && op_code == WSC_MSG) { - wpa_printf(MSG_DEBUG, "WPS: Skip internal processing - using " + wpa_printf(MSG_DEBUG, "WPS: Skip internal processing - using " "external Registrar"); return WPS_CONTINUE; } @@ -3276,11 +3437,11 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, wps->state = SEND_WSC_NACK; wps_fail_event(wps->wps, WPS_WSC_DONE, wps->config_error, - wps->error_indication); + wps->error_indication, wps->mac_addr_e); } return ret; default: - wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); + wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); return WPS_FAILURE; } } @@ -3292,12 +3453,26 @@ int wps_registrar_update_ie(struct wps_registrar *reg) } +static void wps_registrar_set_selected_timeout(void *eloop_ctx, + void *timeout_ctx) +{ + struct wps_registrar *reg = eloop_ctx; + + wpa_printf(MSG_DEBUG, "WPS: Selected Registrar timeout - " + "unselect internal Registrar"); + reg->selected_registrar = 0; + reg->pbc = 0; + wps_registrar_expire_pins(reg); + wps_registrar_selected_registrar_changed(reg, 0); +} + + #ifdef CONFIG_WPS_UPNP static void wps_registrar_sel_reg_add(struct wps_registrar *reg, struct subscription *s) { int i, j; - wpa_printf(MSG_DEBUG, "WPS: External Registrar selected (dev_pw_id=%d " + wpa_printf(MSG_DEBUG, "WPS: External Registrar selected (dev_pw_id=%d " "config_methods=0x%x)", s->dev_password_id, s->config_methods); reg->sel_reg_union = 1; @@ -3313,7 +3488,7 @@ static void wps_registrar_sel_reg_add(struct wps_registrar *reg, j++) { if (is_zero_ether_addr(s->authorized_macs[j])) break; - wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC into union: " + wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC into union: " MACSTR, MAC2STR(s->authorized_macs[j])); os_memcpy(reg->authorized_macs_union[i], s->authorized_macs[j], ETH_ALEN); @@ -3339,14 +3514,14 @@ static void wps_registrar_sel_reg_union(struct wps_registrar *reg) struct subscr_addr *sa; sa = dl_list_first(&s->addr_list, struct subscr_addr, list); if (sa) { - wpa_printf(MSG_DEBUG, "WPS: External Registrar %s:%d", + wpa_printf(MSG_DEBUG, "WPS: External Registrar %s:%d", inet_ntoa(sa->saddr.sin_addr), ntohs(sa->saddr.sin_port)); } if (s->selected_registrar) wps_registrar_sel_reg_add(reg, s); else - wpa_printf(MSG_DEBUG, "WPS: External Registrar not " + wpa_printf(MSG_DEBUG, "WPS: External Registrar not " "selected"); } #endif /* CONFIG_WPS_UPNP */ @@ -3360,9 +3535,10 @@ static void wps_registrar_sel_reg_union(struct wps_registrar *reg) * This function is called when selected registrar state changes, e.g., when an * AP receives a SetSelectedRegistrar UPnP message. */ -void wps_registrar_selected_registrar_changed(struct wps_registrar *reg) +void wps_registrar_selected_registrar_changed(struct wps_registrar *reg, + u16 dev_pw_id) { - wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed"); + wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed"); reg->sel_reg_union = reg->selected_registrar; reg->sel_reg_dev_password_id_override = -1; @@ -3376,22 +3552,19 @@ void wps_registrar_selected_registrar_changed(struct wps_registrar *reg) u16 methods; methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; -#ifdef CONFIG_WPS2 methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_PUSHBUTTON); -#endif /* CONFIG_WPS2 */ if (reg->pbc) { reg->sel_reg_dev_password_id_override = DEV_PW_PUSHBUTTON; wps_set_pushbutton(&methods, reg->wps->config_methods); - } - wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected " + } else if (dev_pw_id) + reg->sel_reg_dev_password_id_override = dev_pw_id; + wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected " "(pbc=%d)", reg->pbc); reg->sel_reg_config_methods_override = methods; - } else { - wpa_printf(MSG_DEBUG, "WPS: Internal Registrar not selected"); - return; - } + } else + wpa_printf(MSG_DEBUG, "WPS: Internal Registrar not selected"); wps_registrar_sel_reg_union(reg); @@ -3414,7 +3587,7 @@ int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, if (uuid_bin2str(d->uuid, uuid, sizeof(uuid))) return 0; - ret = snprintf(buf + len, buflen - len, + ret = os_snprintf(buf + len, buflen - len, "wpsUuid=%s\n" "wpsPrimaryDeviceType=%s\n" "wpsDeviceName=%s\n" @@ -3430,7 +3603,7 @@ int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, d->dev.model_name ? d->dev.model_name : "", d->dev.model_number ? d->dev.model_number : "", d->dev.serial_number ? d->dev.serial_number : ""); - if (ret < 0 || (size_t) ret >= buflen - len) + if (os_snprintf_error(buflen - len, ret)) return len; len += ret; @@ -3441,7 +3614,7 @@ int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, int wps_registrar_config_ap(struct wps_registrar *reg, struct wps_credential *cred) { -#ifdef CONFIG_WPS2 + wpa_printf(MSG_DEBUG, "WPS: encr_type=0x%x", cred->encr_type); if (!(cred->encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { if (cred->encr_type & WPS_ENCR_WEP) { @@ -3457,18 +3630,17 @@ int wps_registrar_config_ap(struct wps_registrar *reg, if ((cred->encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP) { - wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> " + wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> " "TKIP+AES"); cred->encr_type |= WPS_ENCR_AES; } if ((cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) == WPS_AUTH_WPAPSK) { - wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> " + wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> " "WPAPSK+WPA2PSK"); cred->auth_type |= WPS_AUTH_WPA2PSK; } -#endif /* CONFIG_WPS2 */ if (reg->wps->cred_cb) return reg->wps->cred_cb(reg->wps->cb_ctx, cred); @@ -3477,27 +3649,72 @@ int wps_registrar_config_ap(struct wps_registrar *reg, } +int wps_registrar_update_multi_ap(struct wps_registrar *reg, + const u8 *multi_ap_backhaul_ssid, + size_t multi_ap_backhaul_ssid_len, + const u8 *multi_ap_backhaul_network_key, + size_t multi_ap_backhaul_network_key_len) +{ + if (multi_ap_backhaul_ssid) { + os_memcpy(reg->multi_ap_backhaul_ssid, + multi_ap_backhaul_ssid, multi_ap_backhaul_ssid_len); + reg->multi_ap_backhaul_ssid_len = multi_ap_backhaul_ssid_len; + } + + os_free(reg->multi_ap_backhaul_network_key); + reg->multi_ap_backhaul_network_key = NULL; + reg->multi_ap_backhaul_network_key_len = 0; + if (multi_ap_backhaul_network_key) { + reg->multi_ap_backhaul_network_key = + os_memdup(multi_ap_backhaul_network_key, + multi_ap_backhaul_network_key_len); + if (!reg->multi_ap_backhaul_network_key) + return -1; + reg->multi_ap_backhaul_network_key_len = + multi_ap_backhaul_network_key_len; + } + + return 0; +} + + #ifdef CONFIG_WPS_NFC int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, const u8 *pubkey_hash, u16 pw_id, - const u8 *dev_pw, size_t dev_pw_len) + const u8 *dev_pw, size_t dev_pw_len, + int pk_hash_provided_oob) { struct wps_nfc_pw_token *token; if (dev_pw_len > WPS_OOB_DEVICE_PASSWORD_LEN) return -1; + if (pw_id == DEV_PW_NFC_CONNECTION_HANDOVER && + (pubkey_hash == NULL || !pk_hash_provided_oob)) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected NFC Password Token " + "addition - missing public key hash"); + return -1; + } + wps_free_nfc_pw_tokens(®->nfc_pw_tokens, pw_id); token = os_zalloc(sizeof(*token)); if (token == NULL) return -1; - os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); + token->peer_pk_hash_known = pubkey_hash != NULL; + if (pubkey_hash) + os_memcpy(token->pubkey_hash, pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN); token->pw_id = pw_id; - os_memcpy(token->dev_pw, dev_pw, dev_pw_len); - token->dev_pw_len = dev_pw_len; + token->pk_hash_provided_oob = pk_hash_provided_oob; + if (dev_pw) { + wpa_snprintf_hex_uppercase((char *) token->dev_pw, + sizeof(token->dev_pw), + dev_pw, dev_pw_len); + token->dev_pw_len = dev_pw_len * 2; + } dl_list_add(®->nfc_pw_tokens, &token->list); @@ -3505,7 +3722,15 @@ int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, reg->pbc = 0; wps_registrar_add_authorized_mac(reg, (u8 *) "\xff\xff\xff\xff\xff\xff"); - wps_registrar_selected_registrar_changed(reg); + wps_registrar_selected_registrar_changed(reg, pw_id); + eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + eloop_register_timeout(WPS_PBC_WALK_TIME, 0, + wps_registrar_set_selected_timeout, + reg, NULL); + + wpa_printf(MSG_DEBUG, "WPS: Added NFC Device Password %u to Registrar", + pw_id); + return 0; } @@ -3518,8 +3743,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, u16 id; size_t dev_pw_len; - if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 + - WPS_OOB_DEVICE_PASSWORD_MIN_LEN || + if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 || oob_dev_pw_len > WPS_OOB_PUBKEY_HASH_LEN + 2 + WPS_OOB_DEVICE_PASSWORD_LEN) return -1; @@ -3530,7 +3754,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, dev_pw = pos + 2; dev_pw_len = oob_dev_pw + oob_dev_pw_len - dev_pw; - wpa_printf(MSG_DEBUG, "WPS: Add NFC Password Token for Password ID %u", + wpa_printf(MSG_DEBUG, "WPS: Add NFC Password Token for Password ID %u", id); wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash", @@ -3538,7 +3762,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len); return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw, - dev_pw_len); + dev_pw_len, 0); } @@ -3547,7 +3771,15 @@ void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg, { wps_registrar_remove_authorized_mac(reg, (u8 *) "\xff\xff\xff\xff\xff\xff"); - wps_registrar_selected_registrar_changed(reg); + wps_registrar_selected_registrar_changed(reg, 0); + + /* + * Free the NFC password token if it was used only for a single protocol + * run. The static handover case uses the same password token multiple + * times, so do not free that case here. + */ + if (token->peer_pk_hash_known) + os_free(token); } #endif /* CONFIG_WPS_NFC */ diff --git a/components/wpa_supplicant/src/wps/wps_validate.c b/components/wpa_supplicant/src/wps/wps_validate.c index 14274c17e3..96631ef8cf 100644 --- a/components/wpa_supplicant/src/wps/wps_validate.c +++ b/components/wpa_supplicant/src/wps/wps_validate.c @@ -5,15 +5,14 @@ * This software may be distributed under the terms of the BSD license. * See README for more details. */ + #include "utils/includes.h" #include "utils/common.h" -#include "wps/wps_i.h" -#include "wps/wps.h" +#include "wps_i.h" +#include "wps.h" -#ifdef CONFIG_WPS_STRICT - #ifndef WPS_STRICT_ALL #define WPS_STRICT_WPS2 #endif /* WPS_STRICT_ALL */ @@ -98,11 +97,23 @@ static int wps_validate_response_type(const u8 *response_type, int mandatory) static int valid_config_methods(u16 val, int wps2) { if (wps2) { + if ((val & 0x6000) && !(val & WPS_CONFIG_DISPLAY)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Physical/Virtual " + "Display flag without old Display flag " + "set"); + return 0; + } if (!(val & 0x6000) && (val & WPS_CONFIG_DISPLAY)) { wpa_printf(MSG_INFO, "WPS-STRICT: Display flag " "without Physical/Virtual Display flag"); return 0; } + if ((val & 0x0600) && !(val & WPS_CONFIG_PUSHBUTTON)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Physical/Virtual " + "PushButton flag without old PushButton " + "flag set"); + return 0; + } if (!(val & 0x0600) && (val & WPS_CONFIG_PUSHBUTTON)) { wpa_printf(MSG_INFO, "WPS-STRICT: PushButton flag " "without Physical/Virtual PushButton flag"); @@ -213,6 +224,8 @@ static int wps_validate_rf_bands(const u8 *rf_bands, int mandatory) return 0; } if (*rf_bands != WPS_RF_24GHZ && *rf_bands != WPS_RF_50GHZ && + *rf_bands != WPS_RF_60GHZ && + *rf_bands != (WPS_RF_24GHZ | WPS_RF_50GHZ | WPS_RF_60GHZ) && *rf_bands != (WPS_RF_24GHZ | WPS_RF_50GHZ)) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Rf Bands " "attribute value 0x%x", *rf_bands); @@ -256,7 +269,7 @@ static int wps_validate_config_error(const u8 *config_error, int mandatory) return 0; } val = WPA_GET_BE16(config_error); - if (val > 18) { + if (val > 20) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration Error " "attribute value 0x%04x", val); return -1; @@ -279,7 +292,7 @@ static int wps_validate_dev_password_id(const u8 *dev_password_id, return 0; } val = WPA_GET_BE16(dev_password_id); - if (val >= 0x0006 && val <= 0x000f) { + if (val >= 0x0008 && val <= 0x000f) { wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Device Password ID " "attribute value 0x%04x", val); return -1; @@ -1059,7 +1072,7 @@ _out: } -static int wps_validate_credential(const u8 *cred[], size_t len[], size_t num, +static int wps_validate_credential(const u8 *cred[], u16 len[], size_t num, int mandatory) { size_t i; @@ -2363,4 +2376,3 @@ _out: return ret; } -#endif diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 54bb0222ff..b74a439925 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1657,13 +1657,10 @@ components/wifi_provisioning/src/wifi_config.c components/wifi_provisioning/src/wifi_provisioning_priv.h components/wifi_provisioning/src/wifi_scan.c components/wpa_supplicant/esp_supplicant/include/esp_rrm.h -components/wpa_supplicant/esp_supplicant/include/esp_wps.h components/wpa_supplicant/esp_supplicant/src/esp_scan_i.h components/wpa_supplicant/esp_supplicant/src/esp_wpa3.c components/wpa_supplicant/esp_supplicant/src/esp_wpa3_i.h components/wpa_supplicant/esp_supplicant/src/esp_wpa_err.h -components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c -components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h components/wpa_supplicant/include/utils/wpa_debug.h components/wpa_supplicant/include/utils/wpabuf.h components/wpa_supplicant/port/include/byteswap.h