forked from espressif/esp-idf
Merge branch 'feature/wps_code_updation' into 'master'
wpa_supplicant: wps code cleanup See merge request espressif/esp-idf!16577
This commit is contained in:
@@ -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)
|
||||
|
@@ -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__
|
||||
|
@@ -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
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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,8 +11,10 @@
|
||||
#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,
|
||||
u8 *wpa_alloc_eapol(void *sm, u8 type,
|
||||
const void *data, u16 data_len,
|
||||
size_t *msg_len, void **data_pos)
|
||||
{
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
80
components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h
Normal file
80
components/wpa_supplicant/esp_supplicant/src/esp_wps_i.h
Normal file
@@ -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);
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
33
components/wpa_supplicant/src/eap_common/eap_wsc_common.c
Normal file
33
components/wpa_supplicant/src/eap_common/eap_wsc_common.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* EAP-WSC common routines for Wi-Fi Protected Setup
|
||||
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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;
|
||||
}
|
27
components/wpa_supplicant/src/eap_common/eap_wsc_common.h
Normal file
27
components/wpa_supplicant/src/eap_common/eap_wsc_common.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* EAP-WSC definitions for Wi-Fi Protected Setup
|
||||
* Copyright (c) 2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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 */
|
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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
|
||||
@@ -202,15 +202,7 @@ static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid)
|
||||
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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -1,35 +1,18 @@
|
||||
/*
|
||||
* wpa_supplicant/hostapd / common helper functions, etc.
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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 <limits.h>
|
||||
|
||||
#include "utils/common.h"
|
||||
#include <time.h>
|
||||
#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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -1,15 +1,9 @@
|
||||
/*
|
||||
* wpa_supplicant/hostapd / Debug prints
|
||||
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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"
|
||||
|
@@ -5,20 +5,191 @@
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Wi-Fi Protected Setup
|
||||
* Copyright (c) 2007-2012, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2007-2016, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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 */
|
||||
|
@@ -1,56 +1,72 @@
|
||||
/*
|
||||
* Wi-Fi Protected Setup - attribute building
|
||||
* Copyright (c) 2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2008-2016, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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) {
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
} 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");
|
||||
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) {
|
||||
@@ -62,6 +78,16 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_
|
||||
wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey);
|
||||
wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey);
|
||||
|
||||
#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
|
||||
|
||||
if (wps->registrar) {
|
||||
wpabuf_free(wps->dh_pubkey_r);
|
||||
wps->dh_pubkey_r = pubkey;
|
||||
@@ -70,19 +96,6 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_
|
||||
wps->dh_pubkey_e = pubkey;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mode != WPS_CALC_KEY_PRE_CALC) {
|
||||
if (wps->registrar)
|
||||
pubkey = wps->dh_pubkey_r;
|
||||
else
|
||||
pubkey = wps->dh_pubkey_e;
|
||||
|
||||
wpabuf_put_be16(msg, ATTR_PUBLIC_KEY);
|
||||
wpabuf_put_be16(msg, wpabuf_len(pubkey));
|
||||
wpabuf_put_buf(msg, pubkey);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -119,6 +132,8 @@ int wps_build_config_methods(struct wpabuf *msg, u16 methods)
|
||||
|
||||
int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid)
|
||||
{
|
||||
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);
|
||||
@@ -166,7 +181,10 @@ 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);
|
||||
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);
|
||||
@@ -183,6 +201,8 @@ int wps_build_version(struct wpabuf *msg)
|
||||
* backwards compatibility reasons. The real version negotiation is
|
||||
* done with Version2.
|
||||
*/
|
||||
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);
|
||||
@@ -192,11 +212,20 @@ 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);
|
||||
@@ -225,11 +254,20 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll,
|
||||
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) {
|
||||
if (wpabuf_tailroom(msg) < 5)
|
||||
return -1;
|
||||
wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra "
|
||||
"attribute");
|
||||
wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST);
|
||||
@@ -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);
|
||||
@@ -324,8 +385,10 @@ 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);
|
||||
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);
|
||||
@@ -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);
|
||||
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;
|
||||
}
|
||||
|
@@ -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,7 +20,7 @@
|
||||
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:
|
||||
@@ -58,8 +59,27 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr,
|
||||
}
|
||||
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;
|
||||
@@ -106,7 +126,7 @@ 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) {
|
||||
@@ -128,6 +148,7 @@ 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)
|
||||
{
|
||||
@@ -261,10 +282,13 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
|
||||
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) {
|
||||
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;
|
||||
@@ -408,22 +432,6 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
|
||||
}
|
||||
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"
|
||||
@@ -450,25 +458,55 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
|
||||
break;
|
||||
case ATTR_MANUFACTURER:
|
||||
attr->manufacturer = pos;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
@@ -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,14 +538,6 @@ 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 "
|
||||
@@ -582,7 +617,7 @@ 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");
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
@@ -38,8 +39,10 @@ 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) {
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -68,8 +71,8 @@ int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg,
|
||||
return -1;
|
||||
}
|
||||
|
||||
hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash);
|
||||
if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
|
||||
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;
|
||||
}
|
||||
@@ -169,7 +172,7 @@ static int wps_process_cred_network_key(struct wps_credential *cred,
|
||||
if (key == NULL) {
|
||||
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 "
|
||||
"missing mandatory Network Key attribute "
|
||||
@@ -205,70 +208,6 @@ static int wps_process_cred_mac_addr(struct wps_credential *cred,
|
||||
}
|
||||
|
||||
|
||||
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) &&
|
||||
@@ -291,6 +230,16 @@ static int wps_workaround_cred_key(struct wps_credential *cred)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
@@ -5,19 +5,21 @@
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#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)
|
||||
@@ -93,7 +95,7 @@ int wps_derive_keys(struct wps_data *wps)
|
||||
* 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,
|
||||
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,
|
||||
if (hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN,
|
||||
dev_passwd + (dev_passwd_len + 1) / 2,
|
||||
dev_passwd_len / 2, hash);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_clear_free(decrypted);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -190,14 +193,14 @@ struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr,
|
||||
pad = *pos;
|
||||
if (pad > wpabuf_len(decrypted)) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value");
|
||||
wpabuf_free(decrypted);
|
||||
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 "
|
||||
"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 "
|
||||
"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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -438,13 +473,13 @@ int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN])
|
||||
|
||||
/* <categ>-<OUI>-<subcateg> */
|
||||
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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
{
|
||||
@@ -117,6 +106,7 @@ 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;
|
||||
@@ -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;
|
||||
@@ -186,7 +182,14 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps)
|
||||
wpa_printf(MSG_DEBUG, "WPS: No Device Password available");
|
||||
return NULL;
|
||||
}
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -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;
|
||||
@@ -254,17 +257,19 @@ 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);
|
||||
wpabuf_put_be16(msg, ATTR_AUTH_TYPE);
|
||||
@@ -276,19 +281,18 @@ 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);
|
||||
@@ -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);
|
||||
@@ -321,6 +355,11 @@ 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)");
|
||||
wpabuf_put_data(plain, wps->wps->ap_settings,
|
||||
@@ -328,11 +367,23 @@ static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -525,18 +578,31 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
|
||||
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;
|
||||
}
|
||||
@@ -593,13 +659,13 @@ 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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -633,14 +699,13 @@ 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) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -748,12 +809,11 @@ static int wps_process_creds(struct wps_data *wps, const u8 *cred[],
|
||||
|
||||
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) {
|
||||
else if (res == -2)
|
||||
wpa_printf(MSG_DEBUG, "WPS: WEP credential skipped");
|
||||
}
|
||||
else
|
||||
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,6 +937,63 @@ _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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1029,7 +1175,7 @@ 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;
|
||||
@@ -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;
|
||||
@@ -1099,7 +1245,7 @@ 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;
|
||||
@@ -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,
|
||||
@@ -1188,7 +1334,7 @@ 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;
|
||||
@@ -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)
|
||||
@@ -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,7 +1457,8 @@ 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",
|
||||
@@ -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;
|
||||
|
@@ -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,
|
||||
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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user