mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 10:40:47 +03:00
Merge branch 'fix/backport_some_wifi_fixes_v6.1' into 'release/v6.1'
fix(wifi): backport some wifi fixes to v6.1 See merge request espressif/esp-idf!50183
This commit is contained in:
@@ -46,7 +46,7 @@ void * esp_coex_common_spin_lock_create_wrapper(void)
|
||||
void *mux = heap_caps_malloc(sizeof(portMUX_TYPE), MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
||||
|
||||
if (mux) {
|
||||
memcpy(mux,&tmp,sizeof(portMUX_TYPE));
|
||||
memcpy(mux, &tmp, sizeof(portMUX_TYPE));
|
||||
return mux;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@@ -39,7 +39,7 @@ bool IRAM_ATTR esp_coex_common_env_is_chip_wrapper(void)
|
||||
void *esp_coex_common_spin_lock_create_wrapper(void)
|
||||
{
|
||||
portMUX_TYPE tmp = portMUX_INITIALIZER_UNLOCKED;
|
||||
void *mux = malloc(sizeof(portMUX_TYPE));
|
||||
void *mux = heap_caps_malloc(sizeof(portMUX_TYPE), MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
||||
|
||||
if (mux) {
|
||||
memcpy(mux, &tmp, sizeof(portMUX_TYPE));
|
||||
|
||||
@@ -40,7 +40,7 @@ bool IRAM_ATTR esp_coex_common_env_is_chip_wrapper(void)
|
||||
void *esp_coex_common_spin_lock_create_wrapper(void)
|
||||
{
|
||||
portMUX_TYPE tmp = portMUX_INITIALIZER_UNLOCKED;
|
||||
void *mux = malloc(sizeof(portMUX_TYPE));
|
||||
void *mux = heap_caps_malloc(sizeof(portMUX_TYPE), MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
||||
|
||||
if (mux) {
|
||||
memcpy(mux, &tmp, sizeof(portMUX_TYPE));
|
||||
|
||||
@@ -40,7 +40,7 @@ bool IRAM_ATTR esp_coex_common_env_is_chip_wrapper(void)
|
||||
void *esp_coex_common_spin_lock_create_wrapper(void)
|
||||
{
|
||||
portMUX_TYPE tmp = portMUX_INITIALIZER_UNLOCKED;
|
||||
void *mux = malloc(sizeof(portMUX_TYPE));
|
||||
void *mux = heap_caps_malloc(sizeof(portMUX_TYPE), MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
||||
|
||||
if (mux) {
|
||||
memcpy(mux, &tmp, sizeof(portMUX_TYPE));
|
||||
|
||||
@@ -40,10 +40,10 @@ bool IRAM_ATTR esp_coex_common_env_is_chip_wrapper(void)
|
||||
void *esp_coex_common_spin_lock_create_wrapper(void)
|
||||
{
|
||||
portMUX_TYPE tmp = portMUX_INITIALIZER_UNLOCKED;
|
||||
void *mux = malloc(sizeof(portMUX_TYPE));
|
||||
void *mux = heap_caps_malloc(sizeof(portMUX_TYPE), MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
||||
|
||||
if (mux) {
|
||||
memcpy(mux, &tmp, sizeof(portMUX_TYPE));
|
||||
memcpy(mux,&tmp,sizeof(portMUX_TYPE));
|
||||
return mux;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
components/esp_coex/test_apps/:
|
||||
disable:
|
||||
- if: IDF_TARGET not in ["esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32h2", "esp32c5", "esp32c61", "esp32s31"]
|
||||
reason: only supported with s2, s3, c3, c2, c6, h2, c5, c61 and s31
|
||||
- if: IDF_TARGET not in ["esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32h2", "esp32c5", "esp32c61", "esp32s31", "esp32h4", "esp32h21"]
|
||||
reason: only supported with s2, s3, c3, c2, c6, h2, c5, c61, s31, esp32h4 and esp32h21
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | --------- |
|
||||
| Supported Targets | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -36,12 +36,15 @@ TEST_CASE("enable external coex", "[external_coex]")
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61
|
||||
#define EXTERNAL_COEX_CONF 0x600AF4A0
|
||||
#define WDEV_RW_BT_COEX_EN (BIT(9))
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32H21
|
||||
#define EXTERNAL_COEX_CONF 0x600AD4A0
|
||||
#define WDEV_RW_BT_COEX_EN (BIT(9))
|
||||
#elif CONFIG_IDF_TARGET_ESP32S31
|
||||
#define EXTERNAL_COEX_CONF 0x2010F4A0
|
||||
#define WDEV_RW_BT_COEX_EN (BIT(9))
|
||||
#elif CONFIG_IDF_TARGET_ESP32H4
|
||||
#define EXTERNAL_COEX_CONF 0x600CF4A0
|
||||
#define WDEV_RW_BT_COEX_EN (BIT(9))
|
||||
#endif
|
||||
|
||||
esp_extern_coex_work_mode_t mode = EXTERNAL_COEX_LEADER_ROLE;
|
||||
|
||||
+2
-1
@@ -8,9 +8,10 @@ from pytest_embedded_idf.utils import idf_parametrize
|
||||
@pytest.mark.generic
|
||||
@idf_parametrize(
|
||||
'target',
|
||||
['esp32h2', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c6', 'esp32c61', 'esp32c5', 'esp32s31'],
|
||||
['esp32h2', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c6', 'esp32c61', 'esp32c5', 'esp32s31', 'esp32h4', 'esp32h21'],
|
||||
indirect=['target'],
|
||||
)
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runners')
|
||||
def test_external_coex_unit_test(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases()
|
||||
|
||||
|
||||
@@ -525,7 +525,7 @@ pm_disable_sleep_delay_timer = 0x40001b74;
|
||||
/*pm_dream = 0x40001b78;*/
|
||||
pm_mac_wakeup = 0x40001b7c;
|
||||
pm_mac_sleep = 0x40001b80;
|
||||
pm_enable_active_timer = 0x40001b84;
|
||||
//pm_enable_active_timer = 0x40001b84;
|
||||
pm_enable_sleep_delay_timer = 0x40001b88;
|
||||
pm_local_tsf_process = 0x40001b8c;
|
||||
//pm_set_beacon_filter = 0x40001b90;
|
||||
|
||||
@@ -712,7 +712,7 @@ pm_disable_sleep_delay_timer = 0x40001650;
|
||||
/*pm_dream = 0x40001654;*/
|
||||
pm_mac_wakeup = 0x40001658;
|
||||
pm_mac_sleep = 0x4000165c;
|
||||
pm_enable_active_timer = 0x40001660;
|
||||
//pm_enable_active_timer = 0x40001660;
|
||||
pm_enable_sleep_delay_timer = 0x40001664;
|
||||
pm_local_tsf_process = 0x40001668;
|
||||
//pm_set_beacon_filter = 0x4000166c;
|
||||
|
||||
@@ -110,7 +110,7 @@ pm_disable_sleep_delay_timer = 0x40000d50;
|
||||
pm_dream = 0x40000d54;
|
||||
pm_mac_wakeup = 0x40000d58;
|
||||
pm_mac_sleep = 0x40000d5c;
|
||||
pm_enable_active_timer = 0x40000d60;
|
||||
//pm_enable_active_timer = 0x40000d60;
|
||||
pm_enable_sleep_delay_timer = 0x40000d64;
|
||||
pm_local_tsf_process = 0x40000d68;
|
||||
//pm_set_beacon_filter = 0x40000d6c;
|
||||
|
||||
@@ -107,7 +107,7 @@ pm_disable_sleep_delay_timer = 0x40000cbc;
|
||||
pm_dream = 0x40000cc0;
|
||||
pm_mac_wakeup = 0x40000cc4;
|
||||
pm_mac_sleep = 0x40000cc8;
|
||||
pm_enable_active_timer = 0x40000ccc;
|
||||
//pm_enable_active_timer = 0x40000ccc;
|
||||
pm_enable_sleep_delay_timer = 0x40000cd0;
|
||||
pm_local_tsf_process = 0x40000cd4;
|
||||
/*pm_set_beacon_filter = 0x40000cd8;*/
|
||||
|
||||
@@ -966,7 +966,7 @@ pm_disable_sleep_delay_timer = 0x40005430;
|
||||
/*pm_dream = 0x4000543c;*/
|
||||
pm_mac_wakeup = 0x40005448;
|
||||
pm_mac_sleep = 0x40005454;
|
||||
pm_enable_active_timer = 0x40005460;
|
||||
//pm_enable_active_timer = 0x40005460;
|
||||
pm_enable_sleep_delay_timer = 0x4000546c;
|
||||
pm_local_tsf_process = 0x40005478;
|
||||
//pm_set_beacon_filter = 0x40005484;
|
||||
|
||||
@@ -109,7 +109,7 @@ pm_disable_sleep_delay_timer = 0x2f800e6c;
|
||||
pm_dream = 0x2f800e70;
|
||||
pm_mac_wakeup = 0x2f800e74;
|
||||
pm_mac_sleep = 0x2f800e78;
|
||||
pm_enable_active_timer = 0x2f800e7c;
|
||||
//pm_enable_active_timer = 0x2f800e7c;
|
||||
pm_enable_sleep_delay_timer = 0x2f800e80;
|
||||
pm_local_tsf_process = 0x2f800e84;
|
||||
pm_set_beacon_filter = 0x2f800e88;
|
||||
@@ -139,7 +139,7 @@ pm_extend_tbtt_adaptive_servo = 0x2f800ee4;
|
||||
pm_scale_listen_interval = 0x2f800ee8;
|
||||
pm_parse_mbssid_element = 0x2f800eec;
|
||||
pm_disconnected_wake = 0x2f800ef0;
|
||||
pm_tx_data_process = 0x2f800ef4;
|
||||
//pm_tx_data_process = 0x2f800ef4;
|
||||
pm_is_twt_awake = 0x2f800ef8;
|
||||
pm_enable_twt_keep_alive = 0x2f800efc;
|
||||
pm_twt_on_tsf_timer = 0x2f800f00;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -230,35 +230,35 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32S31
|
||||
//TODO: Dummy values, remove or update when FTM loopback and auto-calibration is verified
|
||||
// 20 MHz FTM in 20MHz PHY - Initiator Values
|
||||
#define EST_PHY_INIT_FTM_COMP_20_20U_MHZ 859 // Connected Initiator in 20MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_20U_MHZ_DIS 859 // Disconnected Initiator in 20MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_20D_MHZ 869 // Connected Initiator in 20MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_20D_MHZ_DIS 869 // Disconnected Initiator in 20MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_20U_MHZ 437 // Connected Initiator in 20MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_20U_MHZ_DIS 433 // Disconnected Initiator in 20MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_20D_MHZ 443 // Connected Initiator in 20MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_20D_MHZ_DIS 442 // Disconnected Initiator in 20MHz (Ch 11) using 20MHz FTM
|
||||
// 20 MHz FTM in 20MHz PHY - Responder Values
|
||||
#define EST_PHY_RESP_FTM_COMP_20_20U_MHZ 867 // Connected Responder in 20MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_20U_MHZ_DIS 867 // Disconnected Responder in 20MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_20D_MHZ 857 // Connected Responder in 20MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_20D_MHZ_DIS 857 // Disconnected Responder in 20MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_20U_MHZ 426 // Connected Responder in 20MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_20U_MHZ_DIS 429 // Disconnected Responder in 20MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_20D_MHZ 420 // Connected Responder in 20MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_20D_MHZ_DIS 421 // Disconnected Responder in 20MHz (Ch 11) using 20MHz FTM
|
||||
// 20 MHz FTM in 40MHz PHY - Initiator Values
|
||||
#define EST_PHY_INIT_FTM_COMP_20_40U_MHZ 746 // Connected Initiator in 40MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_40U_MHZ_DIS 744 // Disconnected Initiator in 40MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_40D_MHZ 758 // Connected Initiator in 40MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_40D_MHZ_DIS 755 // Disconnected Initiator in 40MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_40U_MHZ 462 // Connected Initiator in 40MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_40U_MHZ_DIS 433 // Disconnected Initiator in 40MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_40D_MHZ 438 // Connected Initiator in 40MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_20_40D_MHZ_DIS 442 // Disconnected Initiator in 40MHz (Ch 11) using 20MHz FTM
|
||||
// 20 MHz FTM in 40MHz PHY - Responder Values
|
||||
#define EST_PHY_RESP_FTM_COMP_20_40U_MHZ 754 // Connected Responder in 40MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_40U_MHZ_DIS 753 // Disconnected Responder in 40MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_40D_MHZ 744 // Connected Responder in 40MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_40D_MHZ_DIS 744 // Disconnected Responder in 40MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_40U_MHZ 425 // Connected Responder in 40MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_40U_MHZ_DIS 430 // Disconnected Responder in 40MHz (Ch 1) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_40D_MHZ 420 // Connected Responder in 40MHz (Ch 11) using 20MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_20_40D_MHZ_DIS 420 // Disconnected Responder in 40MHz (Ch 11) using 20MHz FTM
|
||||
// 40 MHz FTM in 40MHz PHY - Initiator Values
|
||||
#define EST_PHY_INIT_FTM_COMP_40_40U_MHZ 931 // Connected Initiator in 40MHz (Ch 1) using 40MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_40_40U_MHZ_DIS 931 // Disconnected Initiator in 40MHz (Ch 1) using 40MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_40_40D_MHZ 931 // Connected Initiator in 40MHz (Ch 11) using 40MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_40_40D_MHZ_DIS 931 // Disconnected Initiator in 40MHz (Ch 11) using 40MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_40_40U_MHZ 237 // Connected Initiator in 40MHz (Ch 1) using 40MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_40_40U_MHZ_DIS 237 // Disconnected Initiator in 40MHz (Ch 1) using 40MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_40_40D_MHZ 234 // Connected Initiator in 40MHz (Ch 11) using 40MHz FTM
|
||||
#define EST_PHY_INIT_FTM_COMP_40_40D_MHZ_DIS 234 // Disconnected Initiator in 40MHz (Ch 11) using 40MHz FTM
|
||||
// 40 MHz FTM in 40MHz PHY - Responder Values
|
||||
#define EST_PHY_RESP_FTM_COMP_40_40U_MHZ 566 // Connected Responder in 40MHz (Ch 1) using 40MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_40_40U_MHZ_DIS 566 // Disconnected Responder in 40MHz (Ch 1) using 40MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_40_40D_MHZ 567 // Connected Responder in 40MHz (Ch 11) using 40MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_40_40D_MHZ_DIS 567 // Disconnected Responder in 40MHz (Ch 11) using 40MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_40_40U_MHZ 626 // Connected Responder in 40MHz (Ch 1) using 40MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_40_40U_MHZ_DIS 626 // Disconnected Responder in 40MHz (Ch 1) using 40MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_40_40D_MHZ 629 // Connected Responder in 40MHz (Ch 11) using 40MHz FTM
|
||||
#define EST_PHY_RESP_FTM_COMP_40_40D_MHZ_DIS 629 // Disconnected Responder in 40MHz (Ch 11) using 40MHz FTM
|
||||
#endif
|
||||
|
||||
/********************************************** 5 GHz Values *******************************************************/
|
||||
|
||||
@@ -195,6 +195,7 @@ struct nan_sync_callbacks {
|
||||
void (* receive_pasn)(uint8_t *buf, size_t len, uint16_t trans_seq, uint16_t status);
|
||||
uint32_t (* get_nira_len)(void);
|
||||
int (* construct_nira)(uint8_t *frm);
|
||||
bool (*verify_nira)(uint8_t *peer_mac, uint8_t *nira_attr, uint16_t nira_attr_len);
|
||||
};
|
||||
|
||||
/* Host helpers for NAN encrypted-datapath, registered via
|
||||
@@ -231,6 +232,9 @@ struct nan_secure_dp_funcs {
|
||||
* encrypted KDE payload (GTK/IGTK/BIGTK). */
|
||||
int (*ndp_security_install_get_shared_desc_len)(void);
|
||||
|
||||
uint8_t (*get_ndp_resp_num_pmkids)(uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
uint32_t (*get_ndp_resp_shared_key_desc_len)(uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* --- CSIA / SCIA construction. Each writes a complete NAN
|
||||
* attribute (header + body) at @c frm and returns bytes
|
||||
* written, or -1 on error. --- */
|
||||
@@ -1197,6 +1201,17 @@ uint32_t esp_nan_get_nira_len(void);
|
||||
*/
|
||||
int esp_nan_construct_nira(uint8_t *frm);
|
||||
|
||||
/**
|
||||
* @brief Verify a received NAN Identity Resolution Attribute (NIRA)
|
||||
*
|
||||
* @param[in] peer_mac NMI of the sender
|
||||
* @param[in] nira_attr NIRA attribute buffer
|
||||
* @param[in] nira_attr_len Attribute length in bytes
|
||||
*
|
||||
* @return true if the tag matches, false otherwise
|
||||
*/
|
||||
bool esp_nan_verify_nira(uint8_t *peer_mac, uint8_t *nira_attr, uint16_t nira_attr_len);
|
||||
|
||||
/**
|
||||
* @brief Get the time information from the MAC clock. The time is precise only if modem sleep or light sleep is not enabled.
|
||||
*
|
||||
|
||||
@@ -78,26 +78,26 @@ typedef int (*esp_aes_128_encrypt_t)(const unsigned char *key, const unsigned ch
|
||||
typedef int (*esp_aes_128_decrypt_t)(const unsigned char *key, const unsigned char *iv, unsigned char *data, int data_len);
|
||||
|
||||
/**
|
||||
* @brief The AES wrap callback function used by esp_wifi.
|
||||
* @brief The AES key wrap (RFC 3394) callback function used by esp_wifi.
|
||||
*
|
||||
* @param kek 16-octet Key encryption key (KEK).
|
||||
* @param kek Key encryption key (KEK).
|
||||
* @param kek_len Length of the KEK in bytes.
|
||||
* @param n Length of the plaintext key in 64-bit units;
|
||||
* @param plain Plaintext key to be wrapped, n * 64 bits
|
||||
* @param cipher Wrapped key, (n + 1) * 64 bits
|
||||
*
|
||||
*/
|
||||
typedef int (*esp_aes_wrap_t)(const unsigned char *kek, int n, const unsigned char *plain, unsigned char *cipher);
|
||||
typedef int (*esp_aes_wrap_t)(const unsigned char *kek, size_t kek_len, int n, const unsigned char *plain, unsigned char *cipher);
|
||||
|
||||
/**
|
||||
* @brief The AES unwrap callback function used by esp_wifi.
|
||||
* @brief The AES key unwrap (RFC 3394) callback function used by esp_wifi.
|
||||
*
|
||||
* @param kek 16-octet Key decryption key (KEK).
|
||||
* @param kek Key encryption key (KEK).
|
||||
* @param kek_len Length of the KEK in bytes.
|
||||
* @param n Length of the plaintext key in 64-bit units;
|
||||
* @param cipher Wrapped key to be unwrapped, (n + 1) * 64 bits
|
||||
* @param plain Plaintext key, n * 64 bits
|
||||
*
|
||||
*/
|
||||
typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, int n, const unsigned char *cipher, unsigned char *plain);
|
||||
typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, size_t kek_len, int n, const unsigned char *cipher, unsigned char *plain);
|
||||
|
||||
/**
|
||||
* @brief The SHA256 callback function used by esp_wifi.
|
||||
@@ -404,6 +404,8 @@ typedef struct wpa_crypto_funcs_t {
|
||||
esp_ccmp_encrypt_t ccmp_encrypt; /**< Encrypt data callback function using CCMP */
|
||||
esp_aes_gmac_t aes_gmac; /**< One-Key GMAC hash callback function with AES for MIC computation */
|
||||
esp_sha256_vector_t sha256_vector; /**< SHA256 hash callback function for data vector */
|
||||
esp_aes_wrap_t aes_wrap; /**< The AES key wrap (RFC 3394) callback function used by esp_wifi */
|
||||
esp_aes_unwrap_t aes_unwrap; /**< The AES key unwrap (RFC 3394) callback function used by esp_wifi */
|
||||
} wpa_crypto_funcs_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -604,9 +604,8 @@ typedef struct {
|
||||
uint8_t scan_time; /**< Scan time in seconds while searching for a NAN cluster */
|
||||
uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */
|
||||
bool disable_random_mac;/**< Disable the MAC Randomisation in NAN */
|
||||
uint8_t nik[ESP_WIFI_NAN_NIK_LEN]; /**< Optional NIK. Auto-generated when nik_valid is false. */
|
||||
uint8_t nik_valid: 1; /**< NIK present in nik[] and should be used as-is. */
|
||||
uint8_t reserved: 7; /**< Reserved for future use. */
|
||||
bool reset_current_nvs_creds; /**< Erase all NAN credentials (own NIK and cached peer NIK/NPK entries) saved in NVS before starting. */
|
||||
bool use_nvs_for_caching; /**< Persist newly-learned peer credentials (NIK/NPK) to NVS so they survive across reboots. */
|
||||
} wifi_nan_sync_config_t;
|
||||
|
||||
/**
|
||||
@@ -874,7 +873,9 @@ typedef struct {
|
||||
#define ESP_WIFI_NDP_ROLE_RESPONDER 2 /**< Responder role for NAN Data Path */
|
||||
|
||||
#define ESP_WIFI_NAN_NDP_PMK_LEN 32 /**< Length of NAN Datapath PMK */
|
||||
#define ESP_WIFI_NAN_NPK_LEN ESP_WIFI_NAN_NDP_PMK_LEN /**< Length of NAN Pairwise Key (same as NDP PMK) */
|
||||
#define ESP_WIFI_NAN_NDP_PMKID_LEN 16 /**< Length of NAN Datapath PMKID */
|
||||
#define ESP_WIFI_NAN_MAX_PEER_CREDS 2 /**< Maximum number of NAN peer credentials that can be stored */
|
||||
#define ESP_WIFI_NAN_MAX_CREDS_PER_SVC 4 /**< Maximum number of NAN security credentials per service (passphrase/PMK entries) */
|
||||
|
||||
#define ESP_WIFI_MAX_SVC_NAME_LEN 256 /**< Maximum length of NAN service name */
|
||||
@@ -1307,7 +1308,8 @@ typedef enum {
|
||||
WIFI_EVENT_NAN_BOOTSTRAP_INDICATION, /**< Received NAN Pairing Bootstrapping Request from a Peer */
|
||||
WIFI_EVENT_NAN_BOOTSTRAP_COMPLETED, /**< NAN Pairing Bootstrapping completed (success/failure) */
|
||||
WIFI_EVENT_NAN_PAIRING_INDICATION, /**< Received NAN Pairing indication (reserved) */
|
||||
WIFI_EVENT_NAN_PAIRING_CONFIRM, /**< NAN PASN pairwise key installation completed */
|
||||
WIFI_EVENT_NAN_PAIRING_CONFIRM, /**< NAN pairing completed after NIK follow-up exchange */
|
||||
WIFI_EVENT_NAN_CLUSTER_JOIN, /**< Posted when the device joins, starts, or merges into a NAN cluster */
|
||||
WIFI_EVENT_MAX, /**< Invalid Wi-Fi event ID */
|
||||
} wifi_event_t;
|
||||
|
||||
@@ -1578,6 +1580,13 @@ typedef struct {
|
||||
uint8_t ssi[]; /**< Service specific info of Subscriber */
|
||||
} wifi_event_nan_replied_t;
|
||||
|
||||
/**
|
||||
* @brief Argument structure for WIFI_EVENT_NAN_CLUSTER_JOIN event
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t cluster_id[6]; /**< NAN Cluster ID (BSSID) that was joined/started by the device */
|
||||
} wifi_event_nan_cluster_join_t;
|
||||
|
||||
/**
|
||||
* @brief Argument structure for WIFI_EVENT_NAN_RECEIVE event
|
||||
*/
|
||||
@@ -1662,9 +1671,6 @@ typedef struct {
|
||||
|
||||
/**
|
||||
* @brief Argument structure for WIFI_EVENT_NAN_PAIRING_CONFIRM event
|
||||
*
|
||||
* Posted when PASN pairwise key installation completes.
|
||||
* Distinct from WIFI_EVENT_NAN_BOOTSTRAP_COMPLETED (NPBA follow-up bootstrapping).
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t status; /**< 0=Accepted, 1=Rejected (wifi_nan_pairing_status_t) */
|
||||
|
||||
+1
-1
Submodule components/esp_wifi/lib updated: e54196faa0...9ff50d7c69
@@ -78,26 +78,26 @@ typedef int (*esp_aes_128_encrypt_t)(const unsigned char *key, const unsigned ch
|
||||
typedef int (*esp_aes_128_decrypt_t)(const unsigned char *key, const unsigned char *iv, unsigned char *data, int data_len);
|
||||
|
||||
/**
|
||||
* @brief The AES wrap callback function used by esp_wifi.
|
||||
* @brief The AES key wrap (RFC 3394) callback function used by esp_wifi.
|
||||
*
|
||||
* @param kek 16-octet Key encryption key (KEK).
|
||||
* @param kek Key encryption key (KEK).
|
||||
* @param kek_len Length of the KEK in bytes.
|
||||
* @param n Length of the plaintext key in 64-bit units;
|
||||
* @param plain Plaintext key to be wrapped, n * 64 bits
|
||||
* @param cipher Wrapped key, (n + 1) * 64 bits
|
||||
*
|
||||
*/
|
||||
typedef int (*esp_aes_wrap_t)(const unsigned char *kek, int n, const unsigned char *plain, unsigned char *cipher);
|
||||
typedef int (*esp_aes_wrap_t)(const unsigned char *kek, size_t kek_len, int n, const unsigned char *plain, unsigned char *cipher);
|
||||
|
||||
/**
|
||||
* @brief The AES unwrap callback function used by esp_wifi.
|
||||
* @brief The AES key unwrap (RFC 3394) callback function used by esp_wifi.
|
||||
*
|
||||
* @param kek 16-octet Key decryption key (KEK).
|
||||
* @param kek Key encryption key (KEK).
|
||||
* @param kek_len Length of the KEK in bytes.
|
||||
* @param n Length of the plaintext key in 64-bit units;
|
||||
* @param cipher Wrapped key to be unwrapped, (n + 1) * 64 bits
|
||||
* @param plain Plaintext key, n * 64 bits
|
||||
*
|
||||
*/
|
||||
typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, int n, const unsigned char *cipher, unsigned char *plain);
|
||||
typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, size_t kek_len, int n, const unsigned char *cipher, unsigned char *plain);
|
||||
|
||||
/**
|
||||
* @brief The SHA256 callback function used by esp_wifi.
|
||||
@@ -404,6 +404,8 @@ typedef struct wpa_crypto_funcs_t {
|
||||
esp_ccmp_encrypt_t ccmp_encrypt; /**< Encrypt data callback function using CCMP */
|
||||
esp_aes_gmac_t aes_gmac; /**< One-Key GMAC hash callback function with AES for MIC computation */
|
||||
esp_sha256_vector_t sha256_vector; /**< SHA256 hash callback function for data vector */
|
||||
esp_aes_wrap_t aes_wrap; /**< The AES key wrap (RFC 3394) callback function used by esp_wifi */
|
||||
esp_aes_unwrap_t aes_unwrap; /**< The AES key unwrap (RFC 3394) callback function used by esp_wifi */
|
||||
} wpa_crypto_funcs_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -604,9 +604,8 @@ typedef struct {
|
||||
uint8_t scan_time; /**< Scan time in seconds while searching for a NAN cluster */
|
||||
uint16_t warm_up_sec; /**< Warm up time before assuming NAN Anchor Master role */
|
||||
bool disable_random_mac;/**< Disable the MAC Randomisation in NAN */
|
||||
uint8_t nik[ESP_WIFI_NAN_NIK_LEN]; /**< Optional NIK. Auto-generated when nik_valid is false. */
|
||||
uint8_t nik_valid: 1; /**< NIK present in nik[] and should be used as-is. */
|
||||
uint8_t reserved: 7; /**< Reserved for future use. */
|
||||
bool reset_current_nvs_creds; /**< Erase all NAN credentials (own NIK and cached peer NIK/NPK entries) saved in NVS before starting. */
|
||||
bool use_nvs_for_caching; /**< Persist newly-learned peer credentials (NIK/NPK) to NVS so they survive across reboots. */
|
||||
} wifi_nan_sync_config_t;
|
||||
|
||||
/**
|
||||
@@ -874,7 +873,9 @@ typedef struct {
|
||||
#define ESP_WIFI_NDP_ROLE_RESPONDER 2 /**< Responder role for NAN Data Path */
|
||||
|
||||
#define ESP_WIFI_NAN_NDP_PMK_LEN 32 /**< Length of NAN Datapath PMK */
|
||||
#define ESP_WIFI_NAN_NPK_LEN ESP_WIFI_NAN_NDP_PMK_LEN /**< Length of NAN Pairwise Key (same as NDP PMK) */
|
||||
#define ESP_WIFI_NAN_NDP_PMKID_LEN 16 /**< Length of NAN Datapath PMKID */
|
||||
#define ESP_WIFI_NAN_MAX_PEER_CREDS 2 /**< Maximum number of NAN peer credentials that can be stored */
|
||||
#define ESP_WIFI_NAN_MAX_CREDS_PER_SVC 4 /**< Maximum number of NAN security credentials per service (passphrase/PMK entries) */
|
||||
|
||||
#define ESP_WIFI_MAX_SVC_NAME_LEN 256 /**< Maximum length of NAN service name */
|
||||
@@ -1307,7 +1308,8 @@ typedef enum {
|
||||
WIFI_EVENT_NAN_BOOTSTRAP_INDICATION, /**< Received NAN Pairing Bootstrapping Request from a Peer */
|
||||
WIFI_EVENT_NAN_BOOTSTRAP_COMPLETED, /**< NAN Pairing Bootstrapping completed (success/failure) */
|
||||
WIFI_EVENT_NAN_PAIRING_INDICATION, /**< Received NAN Pairing indication (reserved) */
|
||||
WIFI_EVENT_NAN_PAIRING_CONFIRM, /**< NAN PASN pairwise key installation completed */
|
||||
WIFI_EVENT_NAN_PAIRING_CONFIRM, /**< NAN pairing completed after NIK follow-up exchange */
|
||||
WIFI_EVENT_NAN_CLUSTER_JOIN, /**< Posted when the device joins, starts, or merges into a NAN cluster */
|
||||
WIFI_EVENT_MAX, /**< Invalid Wi-Fi event ID */
|
||||
} wifi_event_t;
|
||||
|
||||
@@ -1578,6 +1580,13 @@ typedef struct {
|
||||
uint8_t ssi[]; /**< Service specific info of Subscriber */
|
||||
} wifi_event_nan_replied_t;
|
||||
|
||||
/**
|
||||
* @brief Argument structure for WIFI_EVENT_NAN_CLUSTER_JOIN event
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t cluster_id[6]; /**< NAN Cluster ID (BSSID) that was joined/started by the device */
|
||||
} wifi_event_nan_cluster_join_t;
|
||||
|
||||
/**
|
||||
* @brief Argument structure for WIFI_EVENT_NAN_RECEIVE event
|
||||
*/
|
||||
@@ -1662,9 +1671,6 @@ typedef struct {
|
||||
|
||||
/**
|
||||
* @brief Argument structure for WIFI_EVENT_NAN_PAIRING_CONFIRM event
|
||||
*
|
||||
* Posted when PASN pairwise key installation completes.
|
||||
* Distinct from WIFI_EVENT_NAN_BOOTSTRAP_COMPLETED (NPBA follow-up bootstrapping).
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t status; /**< 0=Accepted, 1=Rejected (wifi_nan_pairing_status_t) */
|
||||
|
||||
@@ -51,13 +51,141 @@ void esp_nan_action_stop(void);
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_PASN_SUPPORT)
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
|
||||
#define WIFI_NAN_PAIRING_REASON_NIK_FUP_TIMEOUT 1 /**< Local reason: peer NIK follow-up not received within timeout.
|
||||
See Wi-Fi Aware v4.0 §7.6.4.2 for the NIK-exchange procedure. */
|
||||
|
||||
#ifndef NAN_PAIRING_PINCODE_MIN
|
||||
#define NAN_PAIRING_PINCODE_MIN 0
|
||||
#endif
|
||||
#ifndef NAN_PAIRING_PINCODE_MAX
|
||||
#define NAN_PAIRING_PINCODE_MAX 999999
|
||||
#endif
|
||||
|
||||
union pairing_cred_t {
|
||||
uint32_t pincode; /**< 6-digit PIN in range of NAN_PAIRING_PINCODE_MIN to NAN_PAIRING_PINCODE_MAX */
|
||||
};
|
||||
|
||||
enum nan_pairing_role {
|
||||
NAN_PAIRING_ROLE_INITIATOR,
|
||||
NAN_PAIRING_ROLE_RESPONDER,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t peer_svc_id;
|
||||
uint8_t peer_nmi[6];
|
||||
enum nan_pairing_role self_role;
|
||||
union pairing_cred_t cred;
|
||||
} wifi_nan_pairing_config_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Pairing Bootstrapping status values
|
||||
*/
|
||||
typedef enum {
|
||||
WIFI_NAN_PAIRING_STATUS_ACCEPTED = 0, /**< Bootstrapping request accepted */
|
||||
WIFI_NAN_PAIRING_STATUS_REJECTED = 1, /**< Bootstrapping request rejected */
|
||||
WIFI_NAN_PAIRING_STATUS_COMEBACK = 2, /**< Comeback - responder needs more time */
|
||||
} wifi_nan_pairing_status_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Pairing Bootstrapping Request parameters (initiator -> responder)
|
||||
*
|
||||
* Used by a subscriber (bootstrapping initiator) to send a bootstrapping
|
||||
* request follow-up message with NPBA attribute (Type=Request) to a publisher.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t inst_id; /**< Own service instance id */
|
||||
uint8_t peer_inst_id; /**< Peer's service instance id */
|
||||
uint8_t peer_mac[6]; /**< Peer's NAN Management Interface MAC */
|
||||
uint16_t selected_method; /**< One selected WIFI_NAN_BOOTSTRAP_* method bit */
|
||||
wifi_nan_pairing_status_t status; /**< Set to COMEBACK when resending with cookie */
|
||||
uint16_t comeback_after; /**< Comeback deferral time in TUs (only when status=COMEBACK) */
|
||||
uint32_t cookie; /**< Opaque cookie from responder (only when status=COMEBACK) */
|
||||
} wifi_nan_pairing_bootstrap_req_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Pairing Bootstrapping Response parameters (responder -> initiator)
|
||||
*
|
||||
* Used by a publisher (bootstrapping responder) to respond to a bootstrapping
|
||||
* request follow-up message with NPBA attribute (Type=Response).
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t inst_id; /**< Own service instance id */
|
||||
uint8_t peer_inst_id; /**< Peer's service instance id */
|
||||
uint8_t peer_mac[6]; /**< Peer's NAN Management Interface MAC */
|
||||
wifi_nan_pairing_status_t status; /**< Accepted, Rejected, or Comeback */
|
||||
uint16_t matched_method; /**< Matched bootstrapping method, one WIFI_NAN_BOOTSTRAP_* bit (valid if accepted) */
|
||||
uint8_t reason_code; /**< Rejection reason code (valid if rejected) */
|
||||
uint16_t comeback_after; /**< Comeback deferral time in TUs (only when status=COMEBACK) */
|
||||
uint32_t cookie; /**< Opaque cookie for comeback (only when status=COMEBACK) */
|
||||
} wifi_nan_pairing_bootstrapping_resp_t;
|
||||
|
||||
/**
|
||||
* @brief Send a NAN Pairing Bootstrapping request to a matched publisher
|
||||
*
|
||||
* @attention This API should be called by the Subscriber after a service match
|
||||
* (WIFI_EVENT_NAN_SVC_MATCH) with a Publisher that has pairing enabled.
|
||||
* The selected_method must match one of the methods advertised by the publisher.
|
||||
*
|
||||
* @param req Pairing bootstrapping request parameters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Bootstrapping request follow-up sent successfully
|
||||
* - ESP_ERR_INVALID_ARG: Invalid parameters
|
||||
* - ESP_FAIL: Failed to send
|
||||
*/
|
||||
esp_err_t esp_wifi_nan_bootstrap_request(wifi_nan_pairing_bootstrap_req_t *req);
|
||||
|
||||
/**
|
||||
* @brief Respond to a NAN Pairing Bootstrapping request from a peer
|
||||
*
|
||||
* @attention This API should be called by the Publisher after receiving a
|
||||
* WIFI_EVENT_NAN_BOOTSTRAP_INDICATION event.
|
||||
*
|
||||
* @param resp Pairing bootstrapping response parameters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Bootstrapping response follow-up sent successfully
|
||||
* - ESP_ERR_INVALID_ARG: Invalid parameters
|
||||
* - ESP_FAIL: Failed to send
|
||||
*/
|
||||
esp_err_t esp_wifi_nan_bootstrap_response(wifi_nan_pairing_bootstrapping_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief Start NAN Pairing process after credentials are shared Out-of-band
|
||||
*
|
||||
* @attention This API should be called after Bootstrapping is completed
|
||||
*
|
||||
* @param req Pairing setup parameters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Bootstrapping request follow-up sent successfully
|
||||
* - ESP_ERR_INVALID_ARG: Invalid parameters
|
||||
* - ESP_FAIL: Failed to send
|
||||
*/
|
||||
esp_err_t esp_wifi_nan_pairing_start(wifi_nan_pairing_config_t *cfg);
|
||||
|
||||
struct nan_pasn_data;
|
||||
|
||||
/**
|
||||
* @brief Get the NAN PASN context held by the NAN App.
|
||||
*
|
||||
* @return Pointer to the current NAN PASN data, or NULL if none is set.
|
||||
*/
|
||||
struct nan_pasn_data *esp_nan_app_get_pasn_data(void);
|
||||
|
||||
/**
|
||||
* @brief Store the NAN PASN context in the NAN App.
|
||||
*
|
||||
* @attention Ownership is not transferred; the caller remains responsible for
|
||||
* the lifetime of @p pd. Pass NULL to clear the stored context.
|
||||
*
|
||||
* @param pd Pointer to the NAN PASN data to store, or NULL to clear it.
|
||||
*/
|
||||
void esp_nan_app_set_pasn_data(struct nan_pasn_data *pd);
|
||||
//void esp_nan_app_post_pasn_pairing_indication(const wifi_event_nan_pasn_pairing_indication_t *evt);
|
||||
//void esp_nan_app_post_pasn_pairing_confirm(const wifi_event_nan_pasn_pairing_confirm_t *evt);
|
||||
#endif /* CONFIG_ESP_WIFI_PASN_SUPPORT */
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@ extern "C" {
|
||||
.scan_time = 3, \
|
||||
.warm_up_sec = 5, \
|
||||
.disable_random_mac = false, \
|
||||
.nik_valid = false, \
|
||||
.reset_current_nvs_creds = false, \
|
||||
.use_nvs_for_caching = false, \
|
||||
};
|
||||
|
||||
#define NDP_STATUS_ACCEPTED 1
|
||||
@@ -58,25 +59,6 @@ struct nan_peer_record {
|
||||
uint8_t peer_ndi[6]; /**< Peer's NAN Data Interface address, only valid when ndp_id is non-zero */
|
||||
};
|
||||
|
||||
#define NAN_PAIRING_PINCODE_MIN 000000
|
||||
#define NAN_PAIRING_PINCODE_MAX 999999
|
||||
|
||||
union pairing_cred_t {
|
||||
uint32_t pincode; /**< 6-digit PIN in range of NAN_PAIRING_PINCODE_MIN to NAN_PAIRING_PINCODE_MAX */
|
||||
};
|
||||
|
||||
enum nan_pairing_role {
|
||||
NAN_PAIRING_ROLE_INITIATOR,
|
||||
NAN_PAIRING_ROLE_RESPONDER,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t peer_svc_id;
|
||||
uint8_t peer_nmi[6];
|
||||
enum nan_pairing_role self_role;
|
||||
union pairing_cred_t cred;
|
||||
} wifi_nan_pairing_config_t;
|
||||
|
||||
/**
|
||||
* @brief Start NAN Synchronization using the provided parameters.
|
||||
* @note Discovery traffic begins only after publish/subscribe services are started.
|
||||
@@ -197,97 +179,6 @@ esp_err_t esp_wifi_nan_get_peer_records(int *num_peer_records, uint8_t own_svc_i
|
||||
|
||||
esp_err_t esp_wifi_nan_get_peer_info(char *svc_name, uint8_t *peer_mac, struct nan_peer_record *peer_info);
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
|
||||
/**
|
||||
* @brief NAN Pairing Bootstrapping status values
|
||||
*/
|
||||
typedef enum {
|
||||
WIFI_NAN_PAIRING_STATUS_ACCEPTED = 0, /**< Bootstrapping request accepted */
|
||||
WIFI_NAN_PAIRING_STATUS_REJECTED = 1, /**< Bootstrapping request rejected */
|
||||
WIFI_NAN_PAIRING_STATUS_COMEBACK = 2, /**< Comeback - responder needs more time */
|
||||
} wifi_nan_pairing_status_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Pairing Bootstrapping Request parameters (initiator -> responder)
|
||||
*
|
||||
* Used by a subscriber (bootstrapping initiator) to send a bootstrapping
|
||||
* request follow-up message with NPBA attribute (Type=Request) to a publisher.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t inst_id; /**< Own service instance id */
|
||||
uint8_t peer_inst_id; /**< Peer's service instance id */
|
||||
uint8_t peer_mac[6]; /**< Peer's NAN Management Interface MAC */
|
||||
uint16_t selected_method; /**< One selected WIFI_NAN_BOOTSTRAP_* method bit */
|
||||
wifi_nan_pairing_status_t status; /**< Set to COMEBACK when resending with cookie */
|
||||
uint16_t comeback_after; /**< Comeback deferral time in TUs (only when status=COMEBACK) */
|
||||
uint32_t cookie; /**< Opaque cookie from responder (only when status=COMEBACK) */
|
||||
} wifi_nan_pairing_bootstrap_req_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Pairing Bootstrapping Response parameters (responder -> initiator)
|
||||
*
|
||||
* Used by a publisher (bootstrapping responder) to respond to a bootstrapping
|
||||
* request follow-up message with NPBA attribute (Type=Response).
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t inst_id; /**< Own service instance id */
|
||||
uint8_t peer_inst_id; /**< Peer's service instance id */
|
||||
uint8_t peer_mac[6]; /**< Peer's NAN Management Interface MAC */
|
||||
wifi_nan_pairing_status_t status; /**< Accepted, Rejected, or Comeback */
|
||||
uint16_t matched_method; /**< Matched bootstrapping method, one WIFI_NAN_BOOTSTRAP_* bit (valid if accepted) */
|
||||
uint8_t reason_code; /**< Rejection reason code (valid if rejected) */
|
||||
uint16_t comeback_after; /**< Comeback deferral time in TUs (only when status=COMEBACK) */
|
||||
uint32_t cookie; /**< Opaque cookie for comeback (only when status=COMEBACK) */
|
||||
} wifi_nan_pairing_bootstrapping_resp_t;
|
||||
|
||||
/**
|
||||
* @brief Send a NAN Pairing Bootstrapping request to a matched publisher
|
||||
*
|
||||
* @attention This API should be called by the Subscriber after a service match
|
||||
* (WIFI_EVENT_NAN_SVC_MATCH) with a Publisher that has pairing enabled.
|
||||
* The selected_method must match one of the methods advertised by the publisher.
|
||||
*
|
||||
* @param req Pairing bootstrapping request parameters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Bootstrapping request follow-up sent successfully
|
||||
* - ESP_ERR_INVALID_ARG: Invalid parameters
|
||||
* - ESP_FAIL: Failed to send
|
||||
*/
|
||||
esp_err_t esp_wifi_nan_bootstrap_request(wifi_nan_pairing_bootstrap_req_t *req);
|
||||
|
||||
/**
|
||||
* @brief Respond to a NAN Pairing Bootstrapping request from a peer
|
||||
*
|
||||
* @attention This API should be called by the Publisher after receiving a
|
||||
* WIFI_EVENT_NAN_BOOTSTRAP_INDICATION event.
|
||||
*
|
||||
* @param resp Pairing bootstrapping response parameters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Bootstrapping response follow-up sent successfully
|
||||
* - ESP_ERR_INVALID_ARG: Invalid parameters
|
||||
* - ESP_FAIL: Failed to send
|
||||
*/
|
||||
esp_err_t esp_wifi_nan_bootstrap_response(wifi_nan_pairing_bootstrapping_resp_t *resp);
|
||||
|
||||
/**
|
||||
* @brief Start NAN Pairing process after credentials are shared Out-of-band
|
||||
*
|
||||
* @attention This API should be called after Bootstrapping is completed
|
||||
*
|
||||
* @param req Pairing setup parameters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Bootstrapping request follow-up sent successfully
|
||||
* - ESP_ERR_INVALID_ARG: Invalid parameters
|
||||
* - ESP_FAIL: Failed to send
|
||||
*/
|
||||
esp_err_t esp_wifi_nan_pairing_start(wifi_nan_pairing_config_t *cfg);
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING */
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_NAN_SYNC_ENABLE) || defined(CONFIG_ESP_WIFI_NAN_USD_ENABLE)
|
||||
|
||||
@@ -24,30 +24,6 @@
|
||||
#include "esp_private/esp_nan_usd.h"
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
|
||||
|
||||
bool esp_nan_ndp_info_present(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t esp_nan_ndp_get_info_len(void)
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
|
||||
int esp_nan_construct_ndp_info(uint8_t *frm)
|
||||
{
|
||||
static const uint8_t ndp_info_attr[] = {
|
||||
0x01, 0x09, 0x00, 0x50, 0x6f, 0x9a, 0x02, 0x00, 0x02, 0x00, 0x05, 0x0d
|
||||
};
|
||||
|
||||
if (!frm) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(frm, ndp_info_attr, sizeof(ndp_info_attr));
|
||||
return sizeof(ndp_info_attr);
|
||||
}
|
||||
|
||||
#if !CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
uint32_t esp_nan_get_nira_len(void)
|
||||
{
|
||||
@@ -59,6 +35,14 @@ int esp_nan_construct_nira(uint8_t *frm)
|
||||
(void)frm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool esp_nan_verify_nira(uint8_t *peer_mac, uint8_t *nira_attr, uint16_t nira_attr_len)
|
||||
{
|
||||
(void)peer_mac;
|
||||
(void)nira_attr;
|
||||
(void)nira_attr_len;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_NAN_SYNC_ENABLE) && defined(CONFIG_ESP_WIFI_PASN_SUPPORT)
|
||||
@@ -406,6 +390,9 @@ static void nan_reset_service(uint8_t svc_id, bool reset_all)
|
||||
while (idx < ESP_WIFI_NAN_MAX_SVC_SUPPORTED) {
|
||||
p_own_svc = &s_nan_ctx.own_svc[idx++];
|
||||
if (reset_all || (svc_id && p_own_svc->svc_id == svc_id)) {
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
nan_pairing_cancel_svc_pending(p_own_svc);
|
||||
#endif
|
||||
SLIST_FOREACH_SAFE(p_peer_svc, &(p_own_svc->peer_list), next, temp) {
|
||||
SLIST_REMOVE(&(p_own_svc->peer_list), p_peer_svc, peer_svc_info, next);
|
||||
os_free(p_peer_svc);
|
||||
@@ -442,6 +429,36 @@ static bool nan_services_limit_reached(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Service ID = first 6 bytes of SHA256(lowercase(service_name))
|
||||
* per Wi-Fi Aware v4.0 §5.1.5 (Service Name and Service ID).
|
||||
*/
|
||||
bool nan_compute_service_id(const char *service_name, uint8_t service_id[6])
|
||||
{
|
||||
if (!service_name || !g_wifi_default_wpa_crypto_funcs.sha256_vector) {
|
||||
return false;
|
||||
}
|
||||
size_t name_len = strlen(service_name);
|
||||
char *lower = os_malloc(name_len + 1);
|
||||
if (!lower) {
|
||||
return false;
|
||||
}
|
||||
strlcpy(lower, service_name, name_len + 1);
|
||||
for (char *p = lower; *p; p++) {
|
||||
*p = tolower((unsigned char) * p);
|
||||
}
|
||||
uint8_t hash[32];
|
||||
const uint8_t *addr[1] = {(const uint8_t *)lower};
|
||||
size_t len[1] = {name_len};
|
||||
int ret = g_wifi_default_wpa_crypto_funcs.sha256_vector(1, addr, len, hash);
|
||||
os_free(lower);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
memcpy(service_id, hash, 6);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Pre-claim a slot for an upcoming publish/subscribe service. The slot is
|
||||
* marked with a pending sentinel svc_id (0xFF) so nan_find_own_svc_by_name()
|
||||
* can find it from the derive callback running on the WiFi task — that's how
|
||||
@@ -451,7 +468,7 @@ static bool nan_services_limit_reached(void)
|
||||
#define NAN_SVC_ID_PENDING 0xFF
|
||||
|
||||
static struct own_svc_info *nan_claim_own_svc_slot(uint8_t type, const char svc_name[],
|
||||
const wifi_nan_discovery_security_params_t *security_cfg)
|
||||
const wifi_nan_discovery_security_params_t *security_cfg, wifi_nan_pairing_cfg_t *pairing)
|
||||
{
|
||||
struct own_svc_info *p_svc = NULL;
|
||||
for (int i = 0; i < ESP_WIFI_NAN_MAX_SVC_SUPPORTED; i++) {
|
||||
@@ -468,12 +485,18 @@ static struct own_svc_info *nan_claim_own_svc_slot(uint8_t type, const char svc_
|
||||
p_svc->type = type;
|
||||
strlcpy(p_svc->svc_name, svc_name, ESP_WIFI_MAX_SVC_NAME_LEN);
|
||||
SLIST_INIT(&p_svc->peer_list);
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
forced_memzero(&p_svc->user_cfg, sizeof(p_svc->user_cfg));
|
||||
forced_memzero(&p_svc->derived_security, sizeof(p_svc->derived_security));
|
||||
if (security_cfg) {
|
||||
memcpy(&p_svc->user_cfg, security_cfg, sizeof(*security_cfg));
|
||||
}
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
if (pairing) {
|
||||
memcpy(&p_svc->pairing, pairing, sizeof(*pairing));
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
(void)security_cfg;
|
||||
#endif
|
||||
@@ -483,13 +506,14 @@ static struct own_svc_info *nan_claim_own_svc_slot(uint8_t type, const char svc_
|
||||
/* Stamp the real svc_id and per-publish flags after the blob accepts the
|
||||
* service. Looked up by name since the WiFi-task derive callback may have
|
||||
* already populated derived_security[] before this runs. */
|
||||
static void nan_finalize_own_svc(const char *svc_name, uint8_t id, bool ndp_resp_needed)
|
||||
static void nan_finalize_own_svc(const char *svc_name, uint8_t id, bool ndp_resp_needed, uint8_t service_hash[6])
|
||||
{
|
||||
struct own_svc_info *p_svc = nan_find_own_svc_by_name(svc_name);
|
||||
if (!p_svc) {
|
||||
return;
|
||||
}
|
||||
p_svc->svc_id = id;
|
||||
memcpy(p_svc->svc_hash, service_hash, 6);
|
||||
if (p_svc->type == ESP_NAN_PUBLISH) {
|
||||
p_svc->ndp_resp_needed = ndp_resp_needed;
|
||||
}
|
||||
@@ -726,8 +750,8 @@ void nan_app_post_event(int32_t event_id, void* event_data, size_t event_data_si
|
||||
g_wifi_osi_funcs._event_post(WIFI_EVENT, event_id, event_data, event_data_size, OSI_FUNCS_TIME_BLOCKING);
|
||||
}
|
||||
|
||||
void nan_app_service_match_cb(uint8_t sub_id, struct nan_cb_peer_info *peer_info,
|
||||
struct nan_cb_npba_t *npba)
|
||||
static void nan_app_service_match_cb(uint8_t sub_id, struct nan_cb_peer_info *peer_info,
|
||||
struct nan_cb_npba_t *npba)
|
||||
{
|
||||
if (!peer_info) {
|
||||
return;
|
||||
@@ -838,7 +862,7 @@ void nan_app_service_match_cb(uint8_t sub_id, struct nan_cb_peer_info *peer_info
|
||||
os_free(evt);
|
||||
}
|
||||
|
||||
void nan_app_replied_cb(uint8_t pub_id, struct nan_cb_peer_info *peer_info)
|
||||
static void nan_app_replied_cb(uint8_t pub_id, struct nan_cb_peer_info *peer_info)
|
||||
{
|
||||
if (!peer_info) {
|
||||
return;
|
||||
@@ -877,7 +901,7 @@ void nan_app_replied_cb(uint8_t pub_id, struct nan_cb_peer_info *peer_info)
|
||||
os_free(evt);
|
||||
}
|
||||
|
||||
void nan_app_receive_cb(uint8_t svc_id, struct nan_cb_peer_info *peer_info,
|
||||
static void nan_app_receive_cb(uint8_t svc_id, struct nan_cb_peer_info *peer_info,
|
||||
uint8_t *shared_key_attr, uint16_t shared_key_attr_buf_len,
|
||||
struct nan_cb_npba_t *npba)
|
||||
{
|
||||
@@ -930,7 +954,7 @@ void nan_app_receive_cb(uint8_t svc_id, struct nan_cb_peer_info *peer_info,
|
||||
os_free(evt);
|
||||
}
|
||||
|
||||
void nan_app_ndp_indication_cb(uint8_t pub_id, struct ndp_cb_peer_info *peer_info, uint32_t device_caps)
|
||||
static void nan_app_ndp_indication_cb(uint8_t pub_id, struct ndp_cb_peer_info *peer_info, uint32_t device_caps)
|
||||
{
|
||||
/*
|
||||
* Responder-side NDP indication. Security parsers (CSIA/SCIA/
|
||||
@@ -1061,7 +1085,7 @@ void nan_app_ndp_indication_cb(uint8_t pub_id, struct ndp_cb_peer_info *peer_inf
|
||||
os_free(evt);
|
||||
}
|
||||
|
||||
void nan_app_ndp_response_indication_cb(struct ndp_cb_peer_info *peer_info)
|
||||
static void nan_app_ndp_response_indication_cb(struct ndp_cb_peer_info *peer_info)
|
||||
{
|
||||
if (!peer_info) {
|
||||
return;
|
||||
@@ -1111,7 +1135,7 @@ static void nan_ndp_confirm_teardown(const uint8_t peer_nmi[6], uint8_t ndp_id)
|
||||
os_event_group_set_bits(nan_event_group, NDP_REJECTED);
|
||||
}
|
||||
|
||||
void nan_app_ndp_confirm_cb(uint8_t status, struct ndp_cb_peer_info *peer_info,
|
||||
static void nan_app_ndp_confirm_cb(uint8_t status, struct ndp_cb_peer_info *peer_info,
|
||||
uint8_t own_ndi[6], uint8_t ipv6_identifier[8])
|
||||
{
|
||||
if (!peer_info) {
|
||||
@@ -1248,7 +1272,7 @@ done:
|
||||
return;
|
||||
}
|
||||
|
||||
void nan_app_ndp_terminated_cb(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[6])
|
||||
static void nan_app_ndp_terminated_cb(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[6])
|
||||
{
|
||||
NAN_DATA_LOCK();
|
||||
if (s_nan_ctx.nan_netif && !nan_is_datapath_active()) {
|
||||
@@ -1274,7 +1298,7 @@ void nan_app_ndp_terminated_cb(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[
|
||||
os_event_group_set_bits(nan_event_group, NDP_TERMINATED);
|
||||
}
|
||||
|
||||
void nan_action_txdone_cb(uint32_t context, bool tx_status)
|
||||
static void nan_action_txdone_cb(uint32_t context, bool tx_status)
|
||||
{
|
||||
if (nan_event_group && s_fup_context == context) {
|
||||
if (tx_status) {
|
||||
@@ -1285,7 +1309,7 @@ void nan_action_txdone_cb(uint32_t context, bool tx_status)
|
||||
}
|
||||
}
|
||||
|
||||
void esp_nan_ndp_tx_done_cb(uint8_t ndp_id, const uint8_t *peer_nmi, uint8_t msg_type, bool tx_status)
|
||||
static void esp_nan_ndp_tx_done_cb(uint8_t ndp_id, const uint8_t *peer_nmi, uint8_t msg_type, bool tx_status)
|
||||
{
|
||||
NAN_DATA_LOCK();
|
||||
|
||||
@@ -1327,6 +1351,8 @@ static struct nan_secure_dp_funcs s_nan_secure_dp_funcs = {
|
||||
.get_scia_len = esp_nan_get_scia_len,
|
||||
.get_shared_key_desc_attr_len = esp_nan_get_shared_key_desc_attr_len,
|
||||
.ndp_security_install_get_shared_desc_len = esp_nan_ndp_security_install_get_shared_desc_len,
|
||||
.get_ndp_resp_num_pmkids = esp_nan_get_ndp_resp_num_pmkids,
|
||||
.get_ndp_resp_shared_key_desc_len = esp_nan_get_ndp_resp_shared_key_desc_len,
|
||||
|
||||
/* CSIA / SCIA construction */
|
||||
.construct_csia = esp_nan_construct_csia,
|
||||
@@ -1435,6 +1461,7 @@ void esp_nan_action_start(esp_netif_t *nan_netif)
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
.get_nira_len = esp_nan_get_nira_len,
|
||||
.construct_nira = esp_nan_construct_nira,
|
||||
.verify_nira = esp_nan_verify_nira,
|
||||
.receive_pasn = handle_auth_pasn,
|
||||
#endif
|
||||
};
|
||||
@@ -1505,17 +1532,36 @@ esp_err_t esp_wifi_nan_sync_start(const wifi_nan_sync_config_t *nan_cfg)
|
||||
return ESP_OK;
|
||||
}
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
if (nan_cfg->nik_valid) {
|
||||
memcpy(s_nan_ctx.own_nik, nan_cfg->nik, ESP_WIFI_NAN_NIK_LEN);
|
||||
s_nan_ctx.own_nik_valid = true;
|
||||
} else {
|
||||
s_nan_ctx.own_nik_valid = false;
|
||||
s_nan_ctx.num_peer_creds = 0;
|
||||
memset(s_nan_ctx.peer_creds, 0, sizeof(s_nan_ctx.peer_creds));
|
||||
s_nan_ctx.use_nvs_for_caching = nan_cfg->use_nvs_for_caching;
|
||||
|
||||
if (nan_cfg->reset_current_nvs_creds) {
|
||||
/* Start from a clean slate: drop every credential persisted in NVS. */
|
||||
esp_wifi_nan_erase_all_creds();
|
||||
} else if (esp_wifi_nan_load_saved_creds(s_nan_ctx.own_nik, &s_nan_ctx.own_nik_valid,
|
||||
s_nan_ctx.peer_creds, &s_nan_ctx.num_peer_creds) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to load saved NAN credentials");
|
||||
s_nan_ctx.own_nik_valid = false;
|
||||
s_nan_ctx.num_peer_creds = 0;
|
||||
}
|
||||
|
||||
if (!s_nan_ctx.own_nik_valid) {
|
||||
if (os_get_random(s_nan_ctx.own_nik, ESP_WIFI_NAN_NIK_LEN) != 0) {
|
||||
NAN_DATA_UNLOCK();
|
||||
ESP_LOGE(TAG, "Failed to generate NAN NIK");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
s_nan_ctx.own_nik_valid = true;
|
||||
/* Persist the freshly generated NIK only when NVS caching is enabled;
|
||||
* otherwise the identity stays ephemeral for this session. */
|
||||
if (s_nan_ctx.use_nvs_for_caching) {
|
||||
esp_wifi_nan_save_own_nik(s_nan_ctx.own_nik);
|
||||
}
|
||||
}
|
||||
/* Drop the cached NIRA tag; it was derived from the previous NIK. */
|
||||
s_nan_ctx.nira_cached = false;
|
||||
#endif
|
||||
NAN_DATA_UNLOCK();
|
||||
|
||||
@@ -1588,9 +1634,23 @@ esp_err_t esp_wifi_nan_sync_stop(void)
|
||||
}
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_SYNC_ENABLE */
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
static bool nan_check_paired_service_hash(uint8_t service_hash[6])
|
||||
{
|
||||
for (uint8_t i = 0; i < s_nan_ctx.num_peer_creds; i++) {
|
||||
if (s_nan_ctx.peer_creds[i].is_valid &&
|
||||
os_memcmp(s_nan_ctx.peer_creds[i].service_hash, service_hash, 6) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg)
|
||||
{
|
||||
int pub_id = 0;
|
||||
uint8_t service_id[6] = {0};
|
||||
|
||||
if (publish_cfg->usd_discovery_flag && !s_usd_in_progress) {
|
||||
ESP_LOGE(TAG, "Can not start Publish function with USD Discovery "
|
||||
@@ -1722,11 +1782,27 @@ uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg)
|
||||
* into p_svc->derived_security[]. Doing the derive on WiFi task (not the
|
||||
* app/main task) keeps PBKDF2's hardware-SHA polling off IDLE0 and avoids
|
||||
* tripping the task watchdog when num_credentials > 1. */
|
||||
if (!nan_compute_service_id(publish_cfg->service_name, service_id)) {
|
||||
ESP_LOGE(TAG, "Failed to compute Service ID for %s", publish_cfg->service_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
if (nan_check_paired_service_hash(service_id)) {
|
||||
cfg->pairing->pairing_setup = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!nan_claim_own_svc_slot(ESP_NAN_PUBLISH, publish_cfg->service_name,
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
cfg->security_cfg
|
||||
cfg->security_cfg,
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
cfg->pairing
|
||||
#else
|
||||
NULL
|
||||
#endif
|
||||
#else
|
||||
NULL, NULL
|
||||
#endif
|
||||
)) {
|
||||
ESP_LOGE(TAG, "No free service slot");
|
||||
@@ -1740,7 +1816,7 @@ uint8_t esp_wifi_nan_publish_service(const wifi_nan_publish_cfg_t *publish_cfg)
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Started Publishing %s [Service ID - %u]", publish_cfg->service_name, pub_id);
|
||||
nan_finalize_own_svc(publish_cfg->service_name, pub_id, publish_cfg->ndp_resp_needed);
|
||||
nan_finalize_own_svc(publish_cfg->service_name, pub_id, publish_cfg->ndp_resp_needed, service_id);
|
||||
if (cfg->pairing) {
|
||||
os_free(cfg->pairing);
|
||||
}
|
||||
@@ -1764,6 +1840,7 @@ fail:
|
||||
uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe_cfg)
|
||||
{
|
||||
int sub_id = 0;
|
||||
uint8_t service_id[6] = {0};
|
||||
|
||||
if (subscribe_cfg->usd_discovery_flag && !s_usd_in_progress) {
|
||||
ESP_LOGE(TAG, "Can not start Subscribe function with USD Discovery "
|
||||
@@ -1864,8 +1941,20 @@ uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe
|
||||
|
||||
/* Pre-claim host slot BEFORE the blob's subscribe call; see comment on
|
||||
* the publish path for the watchdog rationale. */
|
||||
|
||||
if (!nan_compute_service_id(subscribe_cfg->service_name, service_id)) {
|
||||
ESP_LOGE(TAG, "Failed to compute Service ID for %s", subscribe_cfg->service_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
if (nan_check_paired_service_hash(service_id)) {
|
||||
subscribe_cfg->pairing->pairing_setup = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!nan_claim_own_svc_slot(ESP_NAN_SUBSCRIBE, subscribe_cfg->service_name,
|
||||
subscribe_cfg->security_cfg)) {
|
||||
subscribe_cfg->security_cfg, subscribe_cfg->pairing)) {
|
||||
ESP_LOGE(TAG, "No free service slot");
|
||||
goto fail;
|
||||
}
|
||||
@@ -1877,7 +1966,7 @@ uint8_t esp_wifi_nan_subscribe_service(const wifi_nan_subscribe_cfg_t *subscribe
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Started Subscribing to %s [Service ID - %u]", subscribe_cfg->service_name, sub_id);
|
||||
nan_finalize_own_svc(subscribe_cfg->service_name, (uint8_t) sub_id, false);
|
||||
nan_finalize_own_svc(subscribe_cfg->service_name, (uint8_t) sub_id, false, service_id);
|
||||
NAN_DATA_UNLOCK();
|
||||
|
||||
return sub_id;
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "esp_wifi_types_generic.h"
|
||||
#include "esp_private/wifi.h"
|
||||
#include "esp_nan.h"
|
||||
#include "utils/common.h" /* u8/u16 typedefs required by esp_wifi_driver.h */
|
||||
#include "esp_wifi_driver.h" /* wifi_nan_peer_creds_t + NAN credential NVS APIs */
|
||||
#include "os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -220,9 +222,17 @@ struct own_svc_info {
|
||||
* per-service array the blob caches in svc_entry->self_security_params[].
|
||||
* Valid entries: [0, user_cfg.num_credentials). */
|
||||
wifi_nan_security_params_t derived_security[ESP_WIFI_NAN_MAX_CREDS_PER_SVC];
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
wifi_nan_pairing_cfg_t pairing;
|
||||
#endif
|
||||
#endif
|
||||
uint8_t num_peer_records;
|
||||
SLIST_HEAD(peer_list_t, peer_svc_info) peer_list;
|
||||
#if CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
bool nik_fup_pending;
|
||||
uint8_t nik_fup_pending_peer_nmi[MACADDR_LEN];
|
||||
#endif
|
||||
uint8_t svc_hash[6];
|
||||
};
|
||||
|
||||
/* Per-NDP link state */
|
||||
@@ -287,9 +297,17 @@ typedef struct {
|
||||
struct own_svc_info own_svc[ESP_WIFI_NAN_MAX_SVC_SUPPORTED];
|
||||
esp_netif_t *nan_netif;
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
/* Own NAN Identity Key (NIK) cached for pairing/security flows. */
|
||||
uint8_t own_nik[ESP_WIFI_NAN_NIK_LEN];
|
||||
bool own_nik_valid;
|
||||
uint8_t cached_nira_nonce[8];
|
||||
uint8_t cached_nira_tag[8];
|
||||
bool nira_cached;
|
||||
/* Peer NIK/NPK credentials loaded from NVS at start and refreshed as peers
|
||||
* are paired. Drives NIRA identity resolution; optionally persisted to NVS
|
||||
* when @c use_nvs_for_caching is set. */
|
||||
wifi_nan_peer_creds_t peer_creds[ESP_WIFI_NAN_MAX_PEER_CREDS];
|
||||
uint8_t num_peer_creds;
|
||||
bool use_nvs_for_caching;
|
||||
#endif
|
||||
#ifdef CONFIG_ESP_WIFI_PASN_SUPPORT
|
||||
struct nan_pasn_data *nan_pasn_data;
|
||||
@@ -309,36 +327,7 @@ struct own_svc_info *nan_find_own_svc(uint8_t svc_id);
|
||||
struct own_svc_info *nan_find_own_svc_by_name(const char *svc_name);
|
||||
struct ndl_info *nan_find_ndl(uint8_t ndp_id, uint8_t peer_nmi[]);
|
||||
struct ndl_info *nan_find_ndl_by_pub_id_and_peer(uint8_t pub_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* === nan_secure_dp_funcs initializer targets === */
|
||||
|
||||
/* Always-present (defined in nan_app.c) */
|
||||
void esp_nan_ndp_tx_done_cb(uint8_t ndp_id, const uint8_t *peer_nmi,
|
||||
uint8_t msg_type, bool tx_status);
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
void nan_app_post_event(int32_t event_id, void *event_data, size_t event_data_size);
|
||||
struct peer_svc_info *nan_find_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[]);
|
||||
EventGroupHandle_t nan_pairing_get_event_group(void);
|
||||
uint32_t *nan_pairing_get_fup_context(void);
|
||||
const uint8_t *nan_pairing_get_null_mac(void);
|
||||
|
||||
bool nan_pairing_validate_publish_bootstrapping(uint16_t bootstrapping_methods);
|
||||
bool nan_pairing_validate_subscribe_bootstrapping(uint16_t bootstrapping_methods);
|
||||
|
||||
uint16_t nan_app_parse_npba_from_publish(const struct nan_cb_npba_t *npba);
|
||||
|
||||
void nan_app_bootstrap_indication(uint8_t peer_svc_id, uint8_t pub_id,
|
||||
uint8_t peer_nmi[6], uint16_t selected_method);
|
||||
void nan_app_bootstrap_completed(uint8_t status, uint8_t peer_svc_id, uint8_t sub_id,
|
||||
uint8_t peer_nmi[6], uint16_t matched_method,
|
||||
uint8_t reason_code);
|
||||
bool nan_app_parse_npba_from_receive(uint8_t own_svc_id, uint8_t peer_svc_id,
|
||||
uint8_t peer_nmi[6], const struct nan_cb_npba_t *npba);
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING */
|
||||
bool nan_compute_service_id(const char *service_name, uint8_t service_id[6]);
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
/* Security-gated (defined in nan_security.c) */
|
||||
@@ -346,6 +335,8 @@ uint32_t esp_nan_get_csia_len(uint16_t own_csid_bitmap, uint16_t peer_csid_bitma
|
||||
uint32_t esp_nan_get_scia_len(uint8_t num_pmkids);
|
||||
uint32_t esp_nan_get_shared_key_desc_attr_len(uint16_t key_data_len);
|
||||
int esp_nan_ndp_security_install_get_shared_desc_len(void);
|
||||
uint8_t esp_nan_get_ndp_resp_num_pmkids(uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
uint32_t esp_nan_get_ndp_resp_shared_key_desc_len(uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
int esp_nan_construct_csia(uint8_t *frm, uint8_t pub_id,
|
||||
uint16_t own_csid_bitmap, uint16_t peer_csid_bitmap);
|
||||
@@ -443,13 +434,33 @@ bool nan_security_service_match(const struct own_svc_info *own_svc,
|
||||
const wifi_nan_peer_sdf_security_t *peer_sec);
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_SECURITY */
|
||||
#if CONFIG_ESP_WIFI_NAN_PAIRING
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
|
||||
void nan_app_post_event(int32_t event_id, void *event_data, size_t event_data_size);
|
||||
struct peer_svc_info *nan_find_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[]);
|
||||
EventGroupHandle_t nan_pairing_get_event_group(void);
|
||||
uint32_t *nan_pairing_get_fup_context(void);
|
||||
const uint8_t *nan_pairing_get_null_mac(void);
|
||||
|
||||
bool nan_pairing_validate_publish_bootstrapping(uint16_t bootstrapping_methods);
|
||||
bool nan_pairing_validate_subscribe_bootstrapping(uint16_t bootstrapping_methods);
|
||||
|
||||
uint16_t nan_app_parse_npba_from_publish(const struct nan_cb_npba_t *npba);
|
||||
|
||||
void nan_app_bootstrap_indication(uint8_t peer_svc_id, uint8_t pub_id,
|
||||
uint8_t peer_nmi[6], uint16_t selected_method);
|
||||
void nan_app_bootstrap_completed(uint8_t status, uint8_t peer_svc_id, uint8_t sub_id,
|
||||
uint8_t peer_nmi[6], uint16_t matched_method,
|
||||
uint8_t reason_code);
|
||||
bool nan_app_parse_npba_from_receive(uint8_t own_svc_id, uint8_t peer_svc_id,
|
||||
uint8_t peer_nmi[6], const struct nan_cb_npba_t *npba);
|
||||
void nan_pairing_cancel_svc_pending(struct own_svc_info *own);
|
||||
|
||||
void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
|
||||
const uint8_t *peer_mac,
|
||||
const uint8_t *shared_key_attr,
|
||||
size_t shared_key_attr_buf_len);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
/*
|
||||
* Paired-peer cache API. Called from nan_pairing.c after the PASN install
|
||||
* callback fires; consumed by the NDP security layer to source ND-PMK + cipher
|
||||
@@ -468,7 +479,8 @@ esp_err_t nan_app_register_paired_peer(const uint8_t *peer_nmi,
|
||||
const struct nan_paired_peer *nan_app_find_paired_peer(const uint8_t *peer_nmi);
|
||||
void nan_app_remove_paired_peer(const uint8_t *peer_nmi);
|
||||
void nan_app_clear_paired_peers(void);
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_SECURITY */
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -21,11 +21,10 @@
|
||||
#include "nan_i.h"
|
||||
#include "os.h"
|
||||
#include "utils/common.h"
|
||||
#include "utils/eloop.h"
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_PASN_SUPPORT)
|
||||
#include "esp_private/esp_supp_nan.h"
|
||||
#include "apps_private/wifi_apps_private.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "nan_pairing";
|
||||
|
||||
@@ -34,7 +33,6 @@ static const char *TAG = "nan_pairing";
|
||||
* Shared Key Descriptor (Wi-Fi Aware v4.0 §7.6.4.2). */
|
||||
#define NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC 86400U
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_PASN_SUPPORT)
|
||||
struct nan_pasn_data *esp_nan_app_get_pasn_data(void)
|
||||
{
|
||||
return s_nan_ctx.nan_pasn_data;
|
||||
@@ -49,43 +47,8 @@ static void nan_pairing_key_installed_cb(const uint8_t *peer_nmi,
|
||||
uint8_t role,
|
||||
uint8_t ndp_csid,
|
||||
const uint8_t *nd_pmk,
|
||||
size_t nd_pmk_len)
|
||||
{
|
||||
wifi_event_nan_pairing_complete_t evt = {0};
|
||||
|
||||
if (!peer_nmi) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_NAN_SECURITY)
|
||||
/* Cache ND-PMK for future paired NDPs (Wi-Fi Aware v4.0 §7.6.4.2). The
|
||||
* NDP cipher (CSID) is determined by the PASN cipher and resolved on the
|
||||
* supplicant side before this callback fires; if either is missing, the
|
||||
* pairing event still fires but the security layer will fall back to its
|
||||
* service-credential path for any subsequent NDP. */
|
||||
if (ndp_csid && nd_pmk && nd_pmk_len == ESP_WIFI_NAN_NDP_PMK_LEN) {
|
||||
(void)nan_app_register_paired_peer(peer_nmi, role, ndp_csid,
|
||||
nd_pmk, nd_pmk_len,
|
||||
NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Pairing complete for " MACSTR
|
||||
": ND-PMK unavailable (csid=%u nd_pmk_len=%u); "
|
||||
"paired-peer cache not updated",
|
||||
MAC2STR(peer_nmi), ndp_csid, (unsigned)nd_pmk_len);
|
||||
}
|
||||
#else
|
||||
(void)role;
|
||||
(void)ndp_csid;
|
||||
(void)nd_pmk;
|
||||
(void)nd_pmk_len;
|
||||
#endif
|
||||
|
||||
evt.status = WIFI_NAN_PAIRING_STATUS_ACCEPTED;
|
||||
evt.reason_code = 0;
|
||||
MACADDR_COPY(evt.peer_nmi, peer_nmi);
|
||||
nan_app_post_event(WIFI_EVENT_NAN_PAIRING_CONFIRM, &evt, sizeof(evt));
|
||||
}
|
||||
#endif
|
||||
size_t nd_pmk_len,
|
||||
uint32_t nik_lifetime_sec);
|
||||
|
||||
bool nan_pairing_validate_publish_bootstrapping(uint16_t bootstrapping_methods)
|
||||
{
|
||||
@@ -287,12 +250,19 @@ esp_err_t esp_wifi_nan_pairing_start(wifi_nan_pairing_config_t *cfg)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_PASN_SUPPORT)
|
||||
if (cfg->cred.pincode != UINT32_MAX &&
|
||||
cfg->cred.pincode > NAN_PAIRING_PINCODE_MAX) {
|
||||
ESP_LOGE(TAG, "Invalid pincode %u (valid range %u..%u or UINT32_MAX for default)",
|
||||
cfg->cred.pincode, NAN_PAIRING_PINCODE_MIN, NAN_PAIRING_PINCODE_MAX);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int ret;
|
||||
|
||||
switch (cfg->self_role) {
|
||||
case NAN_PAIRING_ROLE_RESPONDER:
|
||||
ret = esp_nan_supp_pasn_responder_init(cfg->peer_nmi, cfg->cred.pincode,
|
||||
NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC,
|
||||
nan_pairing_key_installed_cb);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "NAN PASN responder init failed for "MACSTR, MAC2STR(cfg->peer_nmi));
|
||||
@@ -301,6 +271,7 @@ esp_err_t esp_wifi_nan_pairing_start(wifi_nan_pairing_config_t *cfg)
|
||||
break;
|
||||
case NAN_PAIRING_ROLE_INITIATOR:
|
||||
ret = esp_nan_supp_pasn_initiator_auth(cfg->peer_nmi, cfg->cred.pincode,
|
||||
NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC,
|
||||
nan_pairing_key_installed_cb);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "NAN PASN initiator auth failed for "MACSTR, MAC2STR(cfg->peer_nmi));
|
||||
@@ -312,10 +283,6 @@ esp_err_t esp_wifi_nan_pairing_start(wifi_nan_pairing_config_t *cfg)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
#else
|
||||
ESP_LOGE(TAG, "NAN PASN support not enabled");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* NIRA: ID(1) + Len(2) + CipherVersion(1) + Nonce(8) + Tag(8) = 20 */
|
||||
@@ -332,195 +299,6 @@ uint32_t esp_nan_get_nira_len(void)
|
||||
return NAN_NIRA_ATTR_LEN;
|
||||
}
|
||||
|
||||
int esp_nan_construct_nira(uint8_t *frm)
|
||||
{
|
||||
uint8_t nonce[NAN_NIRA_NONCE_LEN];
|
||||
uint8_t tag[NAN_NIRA_TAG_LEN];
|
||||
|
||||
if (!frm) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (os_get_random(nonce, sizeof(nonce)) != 0) {
|
||||
ESP_LOGE(TAG, "NIRA: failed to generate nonce");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
uint8_t own_nmi[MACADDR_LEN];
|
||||
const unsigned char *addr[3];
|
||||
int len_arr[3];
|
||||
uint8_t digest[32];
|
||||
|
||||
if (!s_nan_ctx.own_nik_valid) {
|
||||
ESP_LOGW(TAG, "NIRA: own NIK is not available");
|
||||
return 0;
|
||||
}
|
||||
if (!g_wifi_default_wpa_crypto_funcs.hmac_sha256_vector) {
|
||||
ESP_LOGE(TAG, "NIRA: hmac_sha256_vector not registered");
|
||||
return 0;
|
||||
}
|
||||
if (esp_wifi_get_mac(WIFI_IF_NAN, own_nmi) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "NIRA: failed to read NAN NMI");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Tag = Truncate-64(HMAC-SHA-256(NIK, "NIR" || NMI || Nonce)) */
|
||||
addr[0] = (const unsigned char *)NAN_NIRA_STR;
|
||||
len_arr[0] = NAN_NIRA_STR_LEN;
|
||||
addr[1] = own_nmi;
|
||||
len_arr[1] = MACADDR_LEN;
|
||||
addr[2] = nonce;
|
||||
len_arr[2] = NAN_NIRA_NONCE_LEN;
|
||||
if (g_wifi_default_wpa_crypto_funcs.hmac_sha256_vector(s_nan_ctx.own_nik,
|
||||
ESP_WIFI_NAN_NIK_LEN,
|
||||
3, addr, len_arr,
|
||||
digest) != 0) {
|
||||
ESP_LOGE(TAG, "NIRA: tag derivation failed");
|
||||
return 0;
|
||||
}
|
||||
memcpy(tag, digest, NAN_NIRA_TAG_LEN);
|
||||
memset(digest, 0, sizeof(digest));
|
||||
#else
|
||||
/* NIRA requires an available NIK; skip when NAN security is not enabled. */
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
uint8_t *p = frm;
|
||||
*p++ = NAN_ATTR_ID_IDENTITY_RESOLUTION;
|
||||
/* Attribute Length: CipherVersion(1) + Nonce(8) + Tag(8) = 17 */
|
||||
*p++ = 17 & 0xFF;
|
||||
*p++ = (17 >> 8) & 0xFF;
|
||||
*p++ = NAN_NIRA_CIPHER_VER;
|
||||
memcpy(p, nonce, NAN_NIRA_NONCE_LEN);
|
||||
p += NAN_NIRA_NONCE_LEN;
|
||||
memcpy(p, tag, NAN_NIRA_TAG_LEN);
|
||||
p += NAN_NIRA_TAG_LEN;
|
||||
|
||||
return (int)(p - frm);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_NAN_PAIRING) && defined(CONFIG_ESP_WIFI_PASN_SUPPORT) && defined(CONFIG_ESP_WIFI_NAN_SECURITY)
|
||||
|
||||
#include "crypto/sha256.h"
|
||||
#include "utils/eloop.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/wpa_common.h"
|
||||
|
||||
#define NAN_PAIRING_FUP_MIN_ATTR_LEN 3
|
||||
#define NAN_PASN_KDE_OUI_TYPE_NIK 36
|
||||
#define NAN_PASN_KDE_OUI_TYPE_LIFETIME 37
|
||||
#define NAN_PASN_KEY_LIFETIME_NIK_BIT BIT(3)
|
||||
/* NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC is defined at file scope above. */
|
||||
#define NAN_ATTR_ID_SHARED_KEY_DESC 0x24
|
||||
#define GSP_SUBATTR_TRANSPORT_PORT 0x00
|
||||
#define GSP_SUBATTR_INSTANCE_NAME 0x03
|
||||
#define NAN_PAIRING_SRV_PORT 3333
|
||||
#define NAN_PAIRING_SRV_HOSTNAME "ESP-SRV-1234"
|
||||
#define NAN_PAIRING_SSI_BUF_LEN 64
|
||||
|
||||
struct nan_pairing_fup_ctx {
|
||||
uint8_t svc_id;
|
||||
uint8_t peer_svc_id;
|
||||
uint8_t peer_mac[MACADDR_LEN];
|
||||
size_t shared_key_attr_len;
|
||||
uint8_t shared_key_attr[];
|
||||
};
|
||||
|
||||
static struct peer_svc_info *nan_find_peer_svc_exact(uint8_t own_svc_id, uint8_t peer_svc_id,
|
||||
const uint8_t *peer_mac)
|
||||
{
|
||||
struct peer_svc_info *temp;
|
||||
|
||||
if (!own_svc_id || !peer_svc_id || !peer_mac) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ESP_WIFI_NAN_MAX_SVC_SUPPORTED; i++) {
|
||||
struct own_svc_info *own = &s_nan_ctx.own_svc[i];
|
||||
|
||||
if (own->svc_id != own_svc_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SLIST_FOREACH(temp, &(own->peer_list), next) {
|
||||
if (temp->svc_id == peer_svc_id &&
|
||||
memcmp(temp->peer_nmi, peer_mac, MACADDR_LEN) == 0) {
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the WFA OUI + GSP protocol header that prefixes a Generic Service
|
||||
* Protocol SSI (Wi-Fi Aware v4.0 §4.2.7). Ported from esp-nsd
|
||||
* @c add_ssi_gsp_attr (wa_sd.c).
|
||||
*/
|
||||
static int nan_pairing_add_ssi_gsp_attr(uint8_t *buf)
|
||||
{
|
||||
wifi_nan_wfa_ssi_t *wfa_ssi = (wifi_nan_wfa_ssi_t *)buf;
|
||||
static const uint8_t oui_wfa[WIFI_OUI_LEN] = { 0x50, 0x6F, 0x9A };
|
||||
|
||||
memcpy(wfa_ssi->wfa_oui, oui_wfa, WIFI_OUI_LEN);
|
||||
wfa_ssi->proto = WIFI_SVC_PROTO_GENERIC;
|
||||
|
||||
return sizeof(wifi_nan_wfa_ssi_t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a single GSP sub-attribute (TLV: ID(1) | Length(2 LE) | Value).
|
||||
* Ported from esp-nsd @c add_gsp_subattr (wa_sd.c).
|
||||
*/
|
||||
static int nan_pairing_add_gsp_subattr(uint8_t *buf, uint8_t sub_attr_id,
|
||||
const void *payload, uint16_t len)
|
||||
{
|
||||
uint8_t *p = buf;
|
||||
|
||||
*p++ = sub_attr_id;
|
||||
*((uint16_t *)p) = len;
|
||||
p += sizeof(uint16_t);
|
||||
memcpy(p, payload, len);
|
||||
|
||||
return 1 + 2 + len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a GSP SSI carrying the SRV record (Transport Port + Instance Name).
|
||||
* Ported from esp-nsd @c get_ssi_for_srv_record (wa_sd.c) with a stack
|
||||
* buffer and a fixed (hostname, port) instead of dynamic allocation.
|
||||
*/
|
||||
static size_t nan_pairing_build_srv_ssi(uint8_t *buf, size_t buf_len,
|
||||
const char *hostname, uint16_t port)
|
||||
{
|
||||
uint8_t *p = buf;
|
||||
size_t hostname_len;
|
||||
size_t need;
|
||||
|
||||
if (!buf || !hostname) {
|
||||
return 0;
|
||||
}
|
||||
hostname_len = strlen(hostname);
|
||||
need = sizeof(wifi_nan_wfa_ssi_t)
|
||||
+ (1 + 2 + sizeof(port))
|
||||
+ (1 + 2 + hostname_len);
|
||||
if (buf_len < need) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
p += nan_pairing_add_ssi_gsp_attr(p);
|
||||
p += nan_pairing_add_gsp_subattr(p, GSP_SUBATTR_TRANSPORT_PORT,
|
||||
&port, sizeof(port));
|
||||
p += nan_pairing_add_gsp_subattr(p, GSP_SUBATTR_INSTANCE_NAME,
|
||||
hostname, hostname_len);
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive a NIRA tag for cipher version 0 (Wi-Fi Aware v4.0):
|
||||
* Tag = Truncate-64(HMAC-SHA-256(NIK, "NIR" || NMI || Nonce))
|
||||
@@ -562,38 +340,191 @@ static int nan_pairing_derive_nira_tag(const uint8_t nik[NAN_PASN_NIK_LEN],
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a NIRA attribute (ID 0x2B) into @a buf using the NIK and our NMI.
|
||||
* Returns total attribute length on success, 0 on failure.
|
||||
*/
|
||||
static size_t nan_pairing_build_nira_attr(uint8_t *buf, size_t buf_len,
|
||||
const uint8_t nik[NAN_PASN_NIK_LEN],
|
||||
const uint8_t nmi_addr[ETH_ALEN])
|
||||
int esp_nan_construct_nira(uint8_t *frm)
|
||||
{
|
||||
uint8_t nonce[NAN_NIRA_NONCE_LEN];
|
||||
uint8_t tag[NAN_NIRA_TAG_LEN];
|
||||
uint8_t *p = buf;
|
||||
const uint8_t *nonce;
|
||||
const uint8_t *tag;
|
||||
uint8_t fresh_nonce[NAN_NIRA_NONCE_LEN];
|
||||
uint8_t fresh_tag[NAN_NIRA_TAG_LEN];
|
||||
|
||||
if (!buf || !nik || !nmi_addr || buf_len < NAN_NIRA_ATTR_LEN) {
|
||||
return 0;
|
||||
}
|
||||
if (os_get_random(nonce, sizeof(nonce)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (nan_pairing_derive_nira_tag(nik, nmi_addr, nonce, tag) != 0) {
|
||||
if (!frm) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s_nan_ctx.nira_cached) {
|
||||
nonce = s_nan_ctx.cached_nira_nonce;
|
||||
tag = s_nan_ctx.cached_nira_tag;
|
||||
} else {
|
||||
uint8_t own_nmi[MACADDR_LEN];
|
||||
|
||||
if (!s_nan_ctx.own_nik_valid) {
|
||||
ESP_LOGW(TAG, "NIRA: own NIK is not available");
|
||||
return 0;
|
||||
}
|
||||
if (esp_wifi_get_mac(WIFI_IF_NAN, own_nmi) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "NIRA: failed to read NAN NMI");
|
||||
return 0;
|
||||
}
|
||||
if (os_get_random(fresh_nonce, sizeof(fresh_nonce)) != 0) {
|
||||
ESP_LOGE(TAG, "NIRA: failed to generate nonce");
|
||||
return 0;
|
||||
}
|
||||
/* Tag = Truncate-64(HMAC-SHA-256(NIK, "NIR" || NMI || Nonce)) */
|
||||
if (nan_pairing_derive_nira_tag(s_nan_ctx.own_nik, own_nmi,
|
||||
fresh_nonce, fresh_tag) != 0) {
|
||||
ESP_LOGE(TAG, "NIRA: tag derivation failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(s_nan_ctx.cached_nira_nonce, fresh_nonce, NAN_NIRA_NONCE_LEN);
|
||||
memcpy(s_nan_ctx.cached_nira_tag, fresh_tag, NAN_NIRA_TAG_LEN);
|
||||
s_nan_ctx.nira_cached = true;
|
||||
|
||||
nonce = fresh_nonce;
|
||||
tag = fresh_tag;
|
||||
}
|
||||
|
||||
uint8_t *p = frm;
|
||||
*p++ = NAN_ATTR_ID_IDENTITY_RESOLUTION;
|
||||
/* Attribute Length (LE16): CipherVersion(1) + Nonce(8) + Tag(8) = 17 */
|
||||
WPA_PUT_LE16(p, 1 + NAN_NIRA_NONCE_LEN + NAN_NIRA_TAG_LEN);
|
||||
p += 2;
|
||||
/* Attribute Length: CipherVersion(1) + Nonce(8) + Tag(8) = 17 */
|
||||
*p++ = 17 & 0xFF;
|
||||
*p++ = (17 >> 8) & 0xFF;
|
||||
*p++ = NAN_NIRA_CIPHER_VER;
|
||||
memcpy(p, nonce, NAN_NIRA_NONCE_LEN);
|
||||
p += NAN_NIRA_NONCE_LEN;
|
||||
memcpy(p, tag, NAN_NIRA_TAG_LEN);
|
||||
p += NAN_NIRA_TAG_LEN;
|
||||
|
||||
return (int)(p - frm);
|
||||
}
|
||||
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/wpa_common.h"
|
||||
|
||||
#define NAN_PAIRING_FUP_MIN_ATTR_LEN 3
|
||||
#define NAN_PASN_KDE_OUI_TYPE_NIK 36
|
||||
#define NAN_PASN_KDE_OUI_TYPE_LIFETIME 37
|
||||
#define NAN_PASN_KEY_LIFETIME_NIK_BIT BIT(3)
|
||||
/* NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC is defined at file scope above. */
|
||||
#define NAN_ATTR_ID_SHARED_KEY_DESC 0x24
|
||||
#define NAN_PAIRING_NIK_FUP_TIMEOUT_SEC 2
|
||||
|
||||
struct nan_pairing_fup_ctx {
|
||||
uint8_t svc_id;
|
||||
uint8_t peer_svc_id;
|
||||
uint8_t peer_mac[MACADDR_LEN];
|
||||
size_t shared_key_attr_len;
|
||||
uint8_t shared_key_attr[];
|
||||
};
|
||||
|
||||
static struct peer_svc_info *nan_find_peer_svc_exact(uint8_t own_svc_id, uint8_t peer_svc_id,
|
||||
const uint8_t *peer_mac)
|
||||
{
|
||||
struct peer_svc_info *temp;
|
||||
|
||||
if (!own_svc_id || !peer_svc_id || !peer_mac) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ESP_WIFI_NAN_MAX_SVC_SUPPORTED; i++) {
|
||||
struct own_svc_info *own = &s_nan_ctx.own_svc[i];
|
||||
|
||||
if (own->svc_id != own_svc_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SLIST_FOREACH(temp, &(own->peer_list), next) {
|
||||
if (temp->svc_id == peer_svc_id &&
|
||||
memcmp(temp->peer_nmi, peer_mac, MACADDR_LEN) == 0) {
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void nan_pairing_nik_fup_timeout_cb(void *eloop_data, void *user_ctx)
|
||||
{
|
||||
struct own_svc_info *own = user_ctx;
|
||||
wifi_event_nan_pairing_complete_t evt = {0};
|
||||
|
||||
(void)eloop_data;
|
||||
|
||||
if (!own || !own->nik_fup_pending) {
|
||||
return;
|
||||
}
|
||||
|
||||
own->nik_fup_pending = false;
|
||||
evt.status = WIFI_NAN_PAIRING_STATUS_ACCEPTED;
|
||||
evt.reason_code = WIFI_NAN_PAIRING_REASON_NIK_FUP_TIMEOUT;
|
||||
MACADDR_COPY(evt.peer_nmi, own->nik_fup_pending_peer_nmi);
|
||||
nan_app_remove_paired_peer(own->nik_fup_pending_peer_nmi);
|
||||
struct peer_svc_info *peer = nan_find_peer_svc(own->svc_id, 0,
|
||||
own->nik_fup_pending_peer_nmi);
|
||||
esp_nan_complete_pairing(own->svc_id, peer ? peer->svc_id : 0);
|
||||
nan_app_post_event(WIFI_EVENT_NAN_PAIRING_CONFIRM, &evt, sizeof(evt));
|
||||
ESP_LOGW(TAG, "Pairing succeeded but NIK caching timed out for peer " MACSTR
|
||||
" (reason=%u)", MAC2STR(own->nik_fup_pending_peer_nmi), evt.reason_code);
|
||||
}
|
||||
|
||||
void nan_pairing_cancel_svc_pending(struct own_svc_info *own)
|
||||
{
|
||||
if (!own || !own->nik_fup_pending) {
|
||||
return;
|
||||
}
|
||||
|
||||
eloop_cancel_timeout(nan_pairing_nik_fup_timeout_cb, NULL, own);
|
||||
own->nik_fup_pending = false;
|
||||
}
|
||||
|
||||
static void nan_pairing_arm_pending(struct own_svc_info *own, const uint8_t *peer_mac)
|
||||
{
|
||||
if (!own || !peer_mac) {
|
||||
return;
|
||||
}
|
||||
|
||||
nan_pairing_cancel_svc_pending(own);
|
||||
MACADDR_COPY(own->nik_fup_pending_peer_nmi, peer_mac);
|
||||
own->nik_fup_pending = true;
|
||||
|
||||
if (eloop_register_timeout(NAN_PAIRING_NIK_FUP_TIMEOUT_SEC, 0,
|
||||
nan_pairing_nik_fup_timeout_cb, NULL,
|
||||
own) != 0) {
|
||||
own->nik_fup_pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the WFA OUI + GSP protocol header that prefixes a Generic Service
|
||||
* Protocol SSI (Wi-Fi Aware v4.0 §4.2.7). Ported from esp-nsd
|
||||
* @c add_ssi_gsp_attr (wa_sd.c).
|
||||
*/
|
||||
static int nan_pairing_add_ssi_gsp_attr(uint8_t *buf)
|
||||
{
|
||||
wifi_nan_wfa_ssi_t *wfa_ssi = (wifi_nan_wfa_ssi_t *)buf;
|
||||
static const uint8_t oui_wfa[WIFI_OUI_LEN] = { 0x50, 0x6F, 0x9A };
|
||||
|
||||
memcpy(wfa_ssi->wfa_oui, oui_wfa, WIFI_OUI_LEN);
|
||||
wfa_ssi->proto = WIFI_SVC_PROTO_GENERIC;
|
||||
|
||||
return sizeof(wifi_nan_wfa_ssi_t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a GSP SSI (WFA OUI + proto=Generic header only).
|
||||
*/
|
||||
static size_t nan_pairing_build_srv_ssi(uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
uint8_t *p = buf;
|
||||
|
||||
if (!buf || buf_len < sizeof(wifi_nan_wfa_ssi_t)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
p += nan_pairing_add_ssi_gsp_attr(p);
|
||||
|
||||
return (size_t)(p - buf);
|
||||
}
|
||||
|
||||
@@ -663,8 +594,7 @@ static esp_err_t nan_app_send_pairing_followup(uint8_t svc_id, uint8_t peer_svc_
|
||||
uint8_t key_desc[sizeof(struct wpa_eapol_key)] = {0};
|
||||
uint8_t shared_key_wrapped[sizeof(struct wpa_eapol_key) + sizeof(wrapped)] = {0};
|
||||
uint8_t nira_attr[NAN_NIRA_ATTR_LEN] = {0};
|
||||
uint8_t srv_ssi[NAN_PAIRING_SSI_BUF_LEN] = {0};
|
||||
uint8_t our_nmi[ETH_ALEN] = {0};
|
||||
wifi_nan_wfa_ssi_t srv_ssi = {0};
|
||||
uint8_t nik[NAN_PASN_NIK_LEN];
|
||||
size_t plain_len;
|
||||
size_t wrapped_len;
|
||||
@@ -680,9 +610,14 @@ static esp_err_t nan_app_send_pairing_followup(uint8_t svc_id, uint8_t peer_svc_
|
||||
(void)shared_key_attr;
|
||||
(void)shared_key_attr_len;
|
||||
|
||||
if (!peer_mac || os_get_random(nik, sizeof(nik)) != 0) {
|
||||
if (!peer_mac) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!s_nan_ctx.own_nik_valid) {
|
||||
ESP_LOGW(TAG, "Pairing follow-up: own NIK is not available");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
memcpy(nik, s_nan_ctx.own_nik, sizeof(nik));
|
||||
|
||||
saved = nan_pasn_get_saved_keys();
|
||||
if (!saved || !saved->kek_len) {
|
||||
@@ -699,7 +634,11 @@ static esp_err_t nan_app_send_pairing_followup(uint8_t svc_id, uint8_t peer_svc_
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
wrapped_len = plain_len + 8;
|
||||
if (aes_wrap(saved->kek, saved->kek_len, plain_len / 8, plain, wrapped) != 0) {
|
||||
if (!g_wifi_default_wpa_crypto_funcs.aes_wrap) {
|
||||
ESP_LOGE(TAG, "Pairing follow-up: aes_wrap not registered");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (g_wifi_default_wpa_crypto_funcs.aes_wrap(saved->kek, saved->kek_len, plain_len / 8, plain, wrapped) != 0) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -724,20 +663,17 @@ static esp_err_t nan_app_send_pairing_followup(uint8_t svc_id, uint8_t peer_svc_
|
||||
memcpy(w, wrapped, wrapped_len);
|
||||
w += wrapped_len;
|
||||
|
||||
/* SSI: GSP (WFA OUI + proto=Generic) carrying an SRV record so iPhone
|
||||
* has Transport Port + Instance Name to associate with this pairing. */
|
||||
srv_ssi_len = nan_pairing_build_srv_ssi(srv_ssi, sizeof(srv_ssi),
|
||||
NAN_PAIRING_SRV_HOSTNAME,
|
||||
NAN_PAIRING_SRV_PORT);
|
||||
/* SSI: GSP (WFA OUI + proto=Generic). */
|
||||
srv_ssi_len = nan_pairing_build_srv_ssi((uint8_t *)&srv_ssi, sizeof(srv_ssi));
|
||||
if (srv_ssi_len == 0) {
|
||||
ESP_LOGW(TAG, "Pairing follow-up: failed to build SRV SSI");
|
||||
ESP_LOGW(TAG, "Pairing follow-up: failed to build GSP SSI");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fup.inst_id = svc_id;
|
||||
fup.peer_inst_id = peer_svc_id;
|
||||
MACADDR_COPY(fup.peer_mac, peer_mac);
|
||||
fup.ssi = srv_ssi;
|
||||
fup.ssi = (uint8_t *)&srv_ssi;
|
||||
fup.ssi_len = (uint16_t)srv_ssi_len;
|
||||
|
||||
sk_attr_len = (size_t)(w - shared_key_wrapped);
|
||||
@@ -747,13 +683,9 @@ static esp_err_t nan_app_send_pairing_followup(uint8_t svc_id, uint8_t peer_svc_
|
||||
|
||||
/* NIRA proves possession of the NIK we just wrapped above; iPhone uses
|
||||
* it to bind the NIK to the sender and won't commit the pairing record
|
||||
* without it. */
|
||||
if (esp_wifi_get_mac(WIFI_IF_NAN, our_nmi) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Pairing follow-up: cannot read NAN NMI for NIRA");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
nira_len = nan_pairing_build_nira_attr(nira_attr, sizeof(nira_attr),
|
||||
nik, our_nmi);
|
||||
* without it. esp_nan_construct_nira() reuses the same cached nonce/tag we
|
||||
* advertise in sync discovery. */
|
||||
nira_len = (size_t)esp_nan_construct_nira(nira_attr);
|
||||
if (nira_len == 0) {
|
||||
ESP_LOGW(TAG, "Pairing follow-up: NIRA attribute build failed");
|
||||
return ESP_FAIL;
|
||||
@@ -773,6 +705,7 @@ static void nan_app_send_pairing_followup_eloop(void *eloop_data, void *user_dat
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
(void) nan_app_send_pairing_followup(ctx->svc_id, ctx->peer_svc_id,
|
||||
ctx->peer_mac,
|
||||
ctx->shared_key_attr,
|
||||
@@ -780,6 +713,142 @@ static void nan_app_send_pairing_followup_eloop(void *eloop_data, void *user_dat
|
||||
os_free(ctx);
|
||||
}
|
||||
|
||||
static void nan_pairing_key_installed_cb(const uint8_t *peer_nmi,
|
||||
uint8_t role,
|
||||
uint8_t ndp_csid,
|
||||
const uint8_t *nd_pmk,
|
||||
size_t nd_pmk_len,
|
||||
uint32_t nik_lifetime_sec)
|
||||
{
|
||||
if (!peer_nmi) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t lifetime_sec = nik_lifetime_sec ?
|
||||
nik_lifetime_sec : NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC;
|
||||
|
||||
/* Cache ND-PMK for future paired NDPs (Wi-Fi Aware v4.0 §7.6.4.2). */
|
||||
if (ndp_csid && nd_pmk && nd_pmk_len == ESP_WIFI_NAN_NDP_PMK_LEN) {
|
||||
(void)nan_app_register_paired_peer(peer_nmi, role, ndp_csid,
|
||||
nd_pmk, nd_pmk_len,
|
||||
lifetime_sec);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Pairing complete for " MACSTR
|
||||
": ND-PMK unavailable (csid=%u nd_pmk_len=%u); "
|
||||
"paired-peer cache not updated",
|
||||
MAC2STR(peer_nmi), ndp_csid, (unsigned)nd_pmk_len);
|
||||
}
|
||||
|
||||
struct peer_svc_info *peer = nan_find_peer_svc(0, 0, (uint8_t *)peer_nmi);
|
||||
struct own_svc_info *own = NULL;
|
||||
|
||||
if (peer) {
|
||||
own = nan_find_own_svc(peer->own_svc_id);
|
||||
}
|
||||
|
||||
if (own) {
|
||||
if (!own->pairing.npk_nik_caching) {
|
||||
wifi_event_nan_pairing_complete_t evt = {0};
|
||||
evt.status = WIFI_NAN_PAIRING_STATUS_ACCEPTED;
|
||||
evt.reason_code = 0;
|
||||
MACADDR_COPY(evt.peer_nmi, peer_nmi);
|
||||
esp_nan_complete_pairing(own->svc_id, peer->svc_id);
|
||||
nan_app_post_event(WIFI_EVENT_NAN_PAIRING_CONFIRM, &evt, sizeof(evt));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (role == NAN_ROLE_PAIRING_INITIATOR) {
|
||||
struct nan_pairing_fup_ctx *ctx = os_zalloc(sizeof(*ctx));
|
||||
if (!ctx) {
|
||||
ESP_LOGW(TAG, "Pairing key installed: failed to alloc fup ctx for " MACSTR,
|
||||
MAC2STR(peer_nmi));
|
||||
return;
|
||||
}
|
||||
|
||||
NAN_DATA_LOCK();
|
||||
|
||||
if (peer) {
|
||||
ctx->svc_id = peer->own_svc_id;
|
||||
ctx->peer_svc_id = peer->svc_id;
|
||||
}
|
||||
NAN_DATA_UNLOCK();
|
||||
|
||||
/* Without a peer service entry the follow-up would carry zero service
|
||||
* IDs; drop it rather than send an invalid frame. */
|
||||
if (!ctx->svc_id || !ctx->peer_svc_id) {
|
||||
ESP_LOGW(TAG, "Pairing key installed: peer service not found for " MACSTR
|
||||
", skipping initiator follow-up", MAC2STR(peer_nmi));
|
||||
os_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
MACADDR_COPY(ctx->peer_mac, peer_nmi);
|
||||
ctx->shared_key_attr_len = 0;
|
||||
|
||||
own = nan_find_own_svc(ctx->svc_id);
|
||||
if (own) {
|
||||
nan_pairing_arm_pending(own, peer_nmi);
|
||||
}
|
||||
|
||||
if (eloop_register_timeout(0, 0, nan_app_send_pairing_followup_eloop, NULL, ctx) != 0) {
|
||||
ESP_LOGW(TAG, "Pairing key installed: failed to schedule initiator follow-up");
|
||||
if (own) {
|
||||
nan_pairing_cancel_svc_pending(own);
|
||||
}
|
||||
os_free(ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (role == NAN_ROLE_PAIRING_RESPONDER) {
|
||||
NAN_DATA_LOCK();
|
||||
|
||||
if (peer) {
|
||||
own = nan_find_own_svc(peer->own_svc_id);
|
||||
}
|
||||
NAN_DATA_UNLOCK();
|
||||
|
||||
if (own) {
|
||||
nan_pairing_arm_pending(own, peer_nmi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert or refresh a (peer NIK, NPK) entry in the in-RAM credential cache used
|
||||
* for NIRA identity resolution. Caller holds NAN_DATA_LOCK. A @a npk of NULL
|
||||
* stores a zeroed key. When the cache is full the oldest entry (slot 0) is
|
||||
* reused. */
|
||||
static void nan_app_update_peer_creds(const uint8_t *peer_nik, const uint8_t *npk, uint8_t service_hash[6])
|
||||
{
|
||||
wifi_nan_peer_creds_t *slot = NULL;
|
||||
|
||||
/* Reuse the slot already holding this NIK, if any. */
|
||||
for (uint8_t i = 0; i < s_nan_ctx.num_peer_creds; i++) {
|
||||
if (s_nan_ctx.peer_creds[i].is_valid &&
|
||||
os_memcmp(s_nan_ctx.peer_creds[i].peer_nik, peer_nik, ESP_WIFI_NAN_NIK_LEN) == 0) {
|
||||
slot = &s_nan_ctx.peer_creds[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!slot) {
|
||||
if (s_nan_ctx.num_peer_creds < ESP_WIFI_NAN_MAX_PEER_CREDS) {
|
||||
slot = &s_nan_ctx.peer_creds[s_nan_ctx.num_peer_creds++];
|
||||
} else {
|
||||
slot = &s_nan_ctx.peer_creds[0];
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(slot->peer_nik, peer_nik, ESP_WIFI_NAN_NIK_LEN);
|
||||
memcpy(slot->service_hash, service_hash, 6);
|
||||
if (npk) {
|
||||
memcpy(slot->npk, npk, ESP_WIFI_NAN_NPK_LEN);
|
||||
} else {
|
||||
memset(slot->npk, 0, ESP_WIFI_NAN_NPK_LEN);
|
||||
}
|
||||
slot->is_valid = true;
|
||||
}
|
||||
|
||||
void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
|
||||
const uint8_t *peer_mac,
|
||||
const uint8_t *shared_key_attr,
|
||||
@@ -792,7 +861,6 @@ void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
|
||||
uint32_t lifetime_sec = 0;
|
||||
struct nan_pairing_fup_ctx *ctx;
|
||||
size_t alloc_len;
|
||||
|
||||
if (!shared_key_attr || !peer_mac) {
|
||||
return;
|
||||
}
|
||||
@@ -802,7 +870,6 @@ void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
|
||||
if (shared_key_attr[0] != NAN_ATTR_ID_SHARED_KEY_DESC) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16_t *attr_body_len_field = (const uint16_t *)&shared_key_attr[1];
|
||||
|
||||
attr_body_len = *attr_body_len_field;
|
||||
@@ -823,18 +890,69 @@ void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
|
||||
return;
|
||||
}
|
||||
|
||||
bool already_had_nik = false;
|
||||
bool pairing_completed = false;
|
||||
bool persist_creds = false;
|
||||
uint8_t persist_npk[ESP_WIFI_NAN_NPK_LEN] = {0};
|
||||
struct own_svc_info *own = NULL;
|
||||
|
||||
NAN_DATA_LOCK();
|
||||
struct peer_svc_info *p_peer_svc = nan_find_peer_svc_exact(svc_id, peer_svc_id, peer_mac);
|
||||
if (p_peer_svc) {
|
||||
already_had_nik = p_peer_svc->has_nik;
|
||||
memcpy(p_peer_svc->peer_nik, nik, NAN_APP_PEER_NIK_LEN);
|
||||
p_peer_svc->peer_nik_cipher_ver = cipher_ver;
|
||||
p_peer_svc->peer_nik_lifetime_sec = lifetime_sec;
|
||||
p_peer_svc->has_nik = true;
|
||||
ESP_LOGI(TAG, "Stored peer NIK from " MACSTR " (cipher_ver=%u, lifetime=%u s)",
|
||||
MAC2STR(peer_mac), cipher_ver, lifetime_sec);
|
||||
|
||||
/* Refresh the NIRA credential cache with this peer's NIK and, if the
|
||||
* pairing record is available, its NPK. */
|
||||
const struct nan_paired_peer *paired = nan_app_find_paired_peer(peer_mac);
|
||||
if (paired) {
|
||||
memcpy(persist_npk, paired->nd_pmk, ESP_WIFI_NAN_NPK_LEN);
|
||||
}
|
||||
|
||||
own = nan_find_own_svc(p_peer_svc->own_svc_id);
|
||||
|
||||
if (!already_had_nik) {
|
||||
pairing_completed = true;
|
||||
}
|
||||
|
||||
nan_app_update_peer_creds(nik, paired ? paired->nd_pmk : NULL, own ? own->svc_hash : NULL);
|
||||
persist_creds = s_nan_ctx.use_nvs_for_caching;
|
||||
}
|
||||
NAN_DATA_UNLOCK();
|
||||
|
||||
/* Persist outside the lock; NVS writes can block. */
|
||||
if (persist_creds) {
|
||||
esp_wifi_nan_save_creds_for_peer(nik, persist_npk, own ? own->svc_hash : NULL);
|
||||
}
|
||||
/* Invoke blocking calls outside NAN_DATA_LOCK to avoid deadlock. */
|
||||
if (pairing_completed) {
|
||||
wifi_event_nan_pairing_complete_t evt = {0};
|
||||
|
||||
if (own) {
|
||||
nan_pairing_cancel_svc_pending(own);
|
||||
}
|
||||
evt.status = WIFI_NAN_PAIRING_STATUS_ACCEPTED;
|
||||
evt.reason_code = 0;
|
||||
MACADDR_COPY(evt.peer_nmi, peer_mac);
|
||||
esp_nan_complete_pairing(p_peer_svc ? p_peer_svc->own_svc_id : 0,
|
||||
p_peer_svc ? p_peer_svc->svc_id : peer_svc_id);
|
||||
nan_app_post_event(WIFI_EVENT_NAN_PAIRING_CONFIRM, &evt, sizeof(evt));
|
||||
}
|
||||
|
||||
/* Only reply with our own NIK the first time we receive the peer's.
|
||||
* If has_nik was already true this is a redundant echo — don't reply
|
||||
* or we create an infinite ping-pong of follow-ups. */
|
||||
if (already_had_nik) {
|
||||
ESP_LOGD(TAG, "Pairing follow-up: NIK already known for " MACSTR ", skipping reply",
|
||||
MAC2STR(peer_mac));
|
||||
return;
|
||||
}
|
||||
|
||||
if (total_len > SIZE_MAX - sizeof(*ctx)) {
|
||||
return;
|
||||
}
|
||||
@@ -855,6 +973,51 @@ void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING && CONFIG_ESP_WIFI_PASN_SUPPORT && CONFIG_ESP_WIFI_NAN_SECURITY */
|
||||
bool esp_nan_verify_nira(uint8_t *peer_mac, uint8_t *nira_attr, uint16_t nira_attr_len)
|
||||
{
|
||||
uint8_t expected_tag[NAN_NIRA_TAG_LEN];
|
||||
const uint8_t *nonce;
|
||||
const uint8_t *received_tag;
|
||||
bool match = false;
|
||||
|
||||
if (!peer_mac || !nira_attr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nira_attr_len < NAN_NIRA_ATTR_LEN) {
|
||||
ESP_LOGW(TAG, "NIRA verify: attribute too short (%u < %u)",
|
||||
(unsigned)nira_attr_len, (unsigned)NAN_NIRA_ATTR_LEN);
|
||||
return false;
|
||||
}
|
||||
|
||||
nonce = nira_attr + 4;
|
||||
received_tag = nira_attr + 4 + NAN_NIRA_NONCE_LEN;
|
||||
|
||||
/* The peer derives its NIRA tag from one of its NIKs; the sending MAC may be
|
||||
* randomised, so resolve the identity by trying every cached peer NIK. */
|
||||
NAN_DATA_LOCK();
|
||||
for (uint8_t i = 0; i < s_nan_ctx.num_peer_creds; i++) {
|
||||
if (!s_nan_ctx.peer_creds[i].is_valid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nan_pairing_derive_nira_tag(s_nan_ctx.peer_creds[i].peer_nik, peer_mac,
|
||||
nonce, expected_tag) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (os_memcmp_const(expected_tag, received_tag, NAN_NIRA_TAG_LEN) == 0) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
NAN_DATA_UNLOCK();
|
||||
|
||||
if (match) {
|
||||
ESP_LOGD(TAG, "NIRA verify: OK for "MACSTR, MAC2STR(peer_mac));
|
||||
} else {
|
||||
ESP_LOGD(TAG, "NIRA verify: no matching NIK for "MACSTR, MAC2STR(peer_mac));
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
@@ -99,36 +99,6 @@ static bool nan_csid_bitmap_has_pasn(uint16_t csid_bitmap)
|
||||
return (csid_bitmap & WIFI_NAN_CSID_BIT_NCS_PK_PASN_128) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Service ID = first 6 bytes of SHA256(lowercase(service_name))
|
||||
* per Wi-Fi Aware v4.0 §5.1.5 (Service Name and Service ID).
|
||||
*/
|
||||
static bool nan_compute_service_id(const char *service_name, uint8_t service_id[6])
|
||||
{
|
||||
if (!service_name || !g_wifi_default_wpa_crypto_funcs.sha256_vector) {
|
||||
return false;
|
||||
}
|
||||
size_t name_len = strlen(service_name);
|
||||
char *lower = os_malloc(name_len + 1);
|
||||
if (!lower) {
|
||||
return false;
|
||||
}
|
||||
strlcpy(lower, service_name, name_len + 1);
|
||||
for (char *p = lower; *p; p++) {
|
||||
*p = tolower((unsigned char) * p);
|
||||
}
|
||||
uint8_t hash[32];
|
||||
const uint8_t *addr[1] = {(const uint8_t *)lower};
|
||||
size_t len[1] = {name_len};
|
||||
int ret = g_wifi_default_wpa_crypto_funcs.sha256_vector(1, addr, len, hash);
|
||||
os_free(lower);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
memcpy(service_id, hash, 6);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define NAN_SERVICE_ID_LEN 6
|
||||
|
||||
/*
|
||||
@@ -457,6 +427,91 @@ static bool nan_security_fill_from_paired_cache(struct ndl_info *ndl, const uint
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool nan_ndp_resp_resolve_pmk(struct ndl_info *ndl, const uint8_t *peer_nmi)
|
||||
{
|
||||
static const uint8_t zero_pmkid[ESP_WIFI_NAN_NDP_PMKID_LEN] = {0};
|
||||
static const uint8_t zero_pmk[ESP_WIFI_NAN_NDP_PMK_LEN] = {0};
|
||||
|
||||
if (!ndl || !peer_nmi) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool have_peer_pmkid = (memcmp(ndl->security_ctx.nd_pmkid, zero_pmkid,
|
||||
ESP_WIFI_NAN_NDP_PMKID_LEN) != 0);
|
||||
bool need_pmk = (ndl->security_ctx.type != WIFI_NAN_SECURITY_ENCRYPTED) ||
|
||||
(memcmp(ndl->security_ctx.nd_pmk, zero_pmk, ESP_WIFI_NAN_NDP_PMK_LEN) == 0);
|
||||
|
||||
if (!need_pmk) {
|
||||
return have_peer_pmkid;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ESP_WIFI_NAN_PAIRING)
|
||||
if (nan_security_fill_from_paired_cache(ndl, peer_nmi)) {
|
||||
return have_peer_pmkid;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!have_peer_pmkid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct own_svc_info *p_svc = nan_find_own_svc(ndl->publisher_id);
|
||||
int matched_idx = p_svc ? nan_match_pmkid(p_svc, ndl->security_ctx.nd_pmkid,
|
||||
ndl->peer_nmi, ndl->peer_ndi) : -1;
|
||||
if (matched_idx < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ndl->security_ctx.type = WIFI_NAN_SECURITY_ENCRYPTED;
|
||||
ndl->security_ctx.csid_bitmap = p_svc->derived_security[matched_idx].csid_bitmap;
|
||||
memcpy(ndl->security_ctx.nd_pmk,
|
||||
p_svc->derived_security[matched_idx].nd_pmk,
|
||||
ESP_WIFI_NAN_NDP_PMK_LEN);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t esp_nan_get_ndp_resp_num_pmkids(uint8_t ndp_id, const uint8_t *peer_nmi)
|
||||
{
|
||||
static const uint8_t zero_pmkid[ESP_WIFI_NAN_NDP_PMKID_LEN] = {0};
|
||||
|
||||
if (!peer_nmi) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NAN_DATA_LOCK();
|
||||
struct ndl_info *ndl = nan_find_ndl(ndp_id, (uint8_t *)peer_nmi);
|
||||
if (!ndl) {
|
||||
ndl = nan_find_ndl(0, (uint8_t *)peer_nmi);
|
||||
}
|
||||
uint8_t num = 0;
|
||||
if (ndl && memcmp(ndl->security_ctx.nd_pmkid, zero_pmkid, ESP_WIFI_NAN_NDP_PMKID_LEN) != 0) {
|
||||
num = 1;
|
||||
}
|
||||
NAN_DATA_UNLOCK();
|
||||
return num;
|
||||
}
|
||||
|
||||
uint32_t esp_nan_get_ndp_resp_shared_key_desc_len(uint8_t ndp_id, const uint8_t *peer_nmi)
|
||||
{
|
||||
if (!peer_nmi) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NAN_DATA_LOCK();
|
||||
struct ndl_info *ndl = nan_find_ndl(ndp_id, (uint8_t *)peer_nmi);
|
||||
if (!ndl) {
|
||||
ndl = nan_find_ndl(0, (uint8_t *)peer_nmi);
|
||||
}
|
||||
if (!ndl || ndl->handshake_state != NAN_HANDSHAKE_M1_RCVD ||
|
||||
!nan_ndp_resp_resolve_pmk(ndl, peer_nmi)) {
|
||||
NAN_DATA_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
NAN_DATA_UNLOCK();
|
||||
|
||||
return esp_nan_get_shared_key_desc_attr_len(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Build RSNA Key Descriptor payload (95-byte EAPOL-Key layout, see
|
||||
* IEEE 802.11-2020 §12.7.2). NAN carries this body inside the NAN
|
||||
@@ -1164,9 +1219,9 @@ int esp_nan_ndp_security_install_get_shared_desc_len(void)
|
||||
|
||||
int esp_nan_get_ndp_resp_shared_key_desc(uint8_t *buf, size_t buf_len, uint8_t ndp_id, const uint8_t *peer_nmi)
|
||||
{
|
||||
const uint32_t attr_len = esp_nan_get_shared_key_desc_attr_len(0);
|
||||
const uint32_t attr_len = esp_nan_get_ndp_resp_shared_key_desc_len(ndp_id, peer_nmi);
|
||||
|
||||
if (!buf || buf_len < attr_len || !peer_nmi) {
|
||||
if (!buf || !peer_nmi || attr_len == 0 || buf_len < attr_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1182,50 +1237,10 @@ int esp_nan_get_ndp_resp_shared_key_desc(uint8_t *buf, size_t buf_len, uint8_t n
|
||||
ESP_LOGW(TAG, "NDP Resp Key Desc: NDL not in M1_RCVD (state=%d)", ndl->handshake_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Resolve PMK from publish when: NDL not encrypted, or encrypted but nd_pmk not set */
|
||||
{
|
||||
static const uint8_t zero_pmkid[ESP_WIFI_NAN_NDP_PMKID_LEN] = {0};
|
||||
static const uint8_t zero_pmk[ESP_WIFI_NAN_NDP_PMK_LEN] = {0};
|
||||
bool have_peer_pmkid = (memcmp(ndl->security_ctx.nd_pmkid, zero_pmkid,
|
||||
ESP_WIFI_NAN_NDP_PMKID_LEN) != 0);
|
||||
bool need_pmk = (ndl->security_ctx.type != WIFI_NAN_SECURITY_ENCRYPTED) ||
|
||||
(memcmp(ndl->security_ctx.nd_pmk, zero_pmk, ESP_WIFI_NAN_NDP_PMK_LEN) == 0);
|
||||
|
||||
bool resolved_from_pairing_cache = false;
|
||||
#if defined(CONFIG_ESP_WIFI_NAN_PAIRING)
|
||||
if (need_pmk) {
|
||||
resolved_from_pairing_cache = nan_security_fill_from_paired_cache(ndl, peer_nmi);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (resolved_from_pairing_cache) {
|
||||
ESP_LOGD(TAG, "NDP Resp Key Desc: resolved PMK from paired-peer cache");
|
||||
} else if (need_pmk && have_peer_pmkid) {
|
||||
struct own_svc_info *p_svc = nan_find_own_svc(ndl->publisher_id);
|
||||
int matched_idx = p_svc ? nan_match_pmkid(p_svc, ndl->security_ctx.nd_pmkid,
|
||||
ndl->peer_nmi, ndl->peer_ndi) : -1;
|
||||
if (matched_idx >= 0) {
|
||||
ndl->security_ctx.type = WIFI_NAN_SECURITY_ENCRYPTED;
|
||||
ndl->security_ctx.csid_bitmap = p_svc->derived_security[matched_idx].csid_bitmap;
|
||||
memcpy(ndl->security_ctx.nd_pmk,
|
||||
p_svc->derived_security[matched_idx].nd_pmk,
|
||||
ESP_WIFI_NAN_NDP_PMK_LEN);
|
||||
ESP_LOGD(TAG, "NDP Resp Key Desc: resolved PMK from cred slot %d", matched_idx);
|
||||
} else if (ndl->security_ctx.type != WIFI_NAN_SECURITY_ENCRYPTED) {
|
||||
NAN_DATA_UNLOCK();
|
||||
ESP_LOGW(TAG, "NDP Resp Key Desc: NDL not encrypted; send NDP Response without Shared Key Descriptor");
|
||||
return 0;
|
||||
} else {
|
||||
NAN_DATA_UNLOCK();
|
||||
ESP_LOGW(TAG, "NDP Resp Key Desc: no PMK for peer PMKID; ensure matching credential on both devices");
|
||||
return 0;
|
||||
}
|
||||
} else if (ndl->security_ctx.type != WIFI_NAN_SECURITY_ENCRYPTED) {
|
||||
NAN_DATA_UNLOCK();
|
||||
ESP_LOGW(TAG, "NDP Resp Key Desc: NDL not encrypted; send NDP Response without Shared Key Descriptor");
|
||||
return 0;
|
||||
}
|
||||
if (!nan_ndp_resp_resolve_pmk(ndl, peer_nmi)) {
|
||||
NAN_DATA_UNLOCK();
|
||||
ESP_LOGW(TAG, "NDP Resp Key Desc: no PMK for peer PMKID; ensure matching credential on both devices");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generate SNonce and derive PTK if not yet done */
|
||||
|
||||
@@ -599,10 +599,6 @@ config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_PHY_DIG_REGS_MEM_SIZE
|
||||
int
|
||||
default 21
|
||||
|
||||
@@ -275,7 +275,6 @@
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (1) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (0) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
@@ -811,14 +811,6 @@ config SOC_COEX_HW_PTI
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_PHY_DIG_REGS_MEM_SIZE
|
||||
int
|
||||
default 21
|
||||
|
||||
@@ -361,8 +361,6 @@
|
||||
#define SOC_COEX_HW_PTI (1)
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (0) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (0) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
@@ -1335,10 +1335,6 @@ config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH
|
||||
int
|
||||
default 12
|
||||
|
||||
@@ -541,7 +541,6 @@
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (1) /*!< HARDWARE EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (0) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
// #define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
@@ -1071,10 +1071,6 @@ config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_PHY_DIG_REGS_MEM_SIZE
|
||||
int
|
||||
default 21
|
||||
|
||||
@@ -442,7 +442,6 @@
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (1) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (0) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
@@ -983,10 +983,6 @@ config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_PHY_DIG_REGS_MEM_SIZE
|
||||
int
|
||||
default 21
|
||||
|
||||
@@ -411,7 +411,6 @@
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (1) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (0) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
@@ -1079,10 +1079,6 @@ config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_PHY_DIG_REGS_MEM_SIZE
|
||||
int
|
||||
default 21
|
||||
|
||||
@@ -469,7 +469,6 @@
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (1) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (0) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
@@ -951,10 +951,6 @@ config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_PHY_DIG_REGS_MEM_SIZE
|
||||
int
|
||||
default 21
|
||||
|
||||
@@ -444,7 +444,6 @@
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (1) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (0) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
@@ -1127,10 +1127,6 @@ config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_PHY_DIG_REGS_MEM_SIZE
|
||||
int
|
||||
default 21
|
||||
|
||||
@@ -478,7 +478,6 @@
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (1) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (0) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*--------------- PHY REGISTER AND MEMORY SIZE CAPS --------------------------*/
|
||||
#define SOC_PHY_DIG_REGS_MEM_SIZE (21*4)
|
||||
|
||||
@@ -979,10 +979,6 @@ config SOC_COEX_HW_PTI
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -440,7 +440,6 @@
|
||||
// No contents
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (0) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (1) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/
|
||||
|
||||
@@ -1139,10 +1139,6 @@ config SOC_COEX_HW_PTI
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EXTERNAL_COEX_ADVANCE
|
||||
bool
|
||||
default n
|
||||
|
||||
config SOC_EXTERNAL_COEX_LEADER_TX_LINE
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -471,7 +471,6 @@
|
||||
#define SOC_COEX_HW_PTI (1)
|
||||
|
||||
/*-------------------------- EXTERNAL COEXISTENCE CAPS -------------------------------------*/
|
||||
#define SOC_EXTERNAL_COEX_ADVANCE (0) /*!< HARDWARE ADVANCED EXTERNAL COEXISTENCE CAPS */
|
||||
#define SOC_EXTERNAL_COEX_LEADER_TX_LINE (1) /*!< EXTERNAL COEXISTENCE TX LINE CAPS */
|
||||
|
||||
/*-------------------------- SDMMC CAPS -----------------------------------------*/
|
||||
|
||||
@@ -314,7 +314,11 @@ endif()
|
||||
if(CONFIG_ESP_WIFI_ENABLE_SAE_H2E)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SAE_H2E)
|
||||
endif()
|
||||
if(CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT)
|
||||
# PASN reuses the SAE module (PWE/crypto + comeback-token mechanism), so
|
||||
# CONFIG_SAE must be defined whenever SoftAP-SAE or PASN is enabled. AP-side SAE
|
||||
# authentication paths are additionally gated on CONFIG_ESP_WIFI_SOFTAP_SUPPORT
|
||||
# in the sources so they stay out of PASN-only (SoftAP-disabled) builds.
|
||||
if(CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT OR CONFIG_ESP_WIFI_PASN_SUPPORT)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SAE)
|
||||
endif()
|
||||
if(CONFIG_ESP_WIFI_WPA3_COMPATIBLE_SUPPORT)
|
||||
|
||||
@@ -64,14 +64,19 @@ enum nan_role {
|
||||
* @param role enum nan_role value for the local device.
|
||||
* @param ndp_csid NCS-SK CSID for paired-peer NDP (WIFI_NAN_CSID_NCS_SK_128
|
||||
* or _SK_256), 0 if no usable cipher mapping was available.
|
||||
* @param nd_pmk ND-PMK bytes (32) or NULL if KDK was absent.
|
||||
* @param nd_pmk_len Length of @a nd_pmk (32 when present, 0 otherwise).
|
||||
* @param nd_pmk ND-PMK bytes (32) or NULL if KDK was absent.
|
||||
* @param nd_pmk_len Length of @a nd_pmk (32 when present, 0 otherwise).
|
||||
* @param nik_lifetime_sec NIK / paired-peer cache lifetime in seconds, as supplied
|
||||
* to @ref esp_nan_supp_pasn_initiator_auth or
|
||||
* @ref esp_nan_supp_pasn_responder_init. The NAN app
|
||||
* substitutes 86400 s when this is 0.
|
||||
*/
|
||||
typedef void (*esp_nan_pairing_key_installed_cb_t)(const uint8_t *peer_nmi,
|
||||
uint8_t role,
|
||||
uint8_t ndp_csid,
|
||||
const uint8_t *nd_pmk,
|
||||
size_t nd_pmk_len);
|
||||
size_t nd_pmk_len,
|
||||
uint32_t nik_lifetime_sec);
|
||||
|
||||
/**
|
||||
* Last PASN key material after successful pairing (PMK + flattened PTK KCK|KEK|TK|KDK).
|
||||
@@ -98,11 +103,15 @@ struct nan_pasn_key_material {
|
||||
* pairing responder. Runs on the wpa_supplicant eloop thread.
|
||||
*
|
||||
* @param peer_nmi Peer NMI (6 bytes).
|
||||
* @param pincode 6-digit PIN (0..999999), or @c UINT32_MAX for the default PIN.
|
||||
* @param pincode 6-digit PIN (0..999999), or @c UINT32_MAX for the default PIN.
|
||||
* @param nik_lifetime_sec NIK lifetime in seconds; forwarded unchanged to
|
||||
* @c pairing_key_installed_cb (NAN app currently
|
||||
* passes 86400).
|
||||
* @param pairing_key_installed_cb Callback invoked after pairwise key installation with peer NMI.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int esp_nan_supp_pasn_responder_init(const uint8_t *peer_nmi, uint32_t pincode,
|
||||
uint32_t nik_lifetime_sec,
|
||||
esp_nan_pairing_key_installed_cb_t pairing_key_installed_cb);
|
||||
|
||||
/**
|
||||
@@ -113,11 +122,15 @@ int esp_nan_supp_pasn_responder_init(const uint8_t *peer_nmi, uint32_t pincode,
|
||||
* Runs on the wpa_supplicant eloop thread.
|
||||
*
|
||||
* @param peer_nmi Peer NMI (6 bytes).
|
||||
* @param pincode 6-digit PIN (0..999999), or @c UINT32_MAX for the default PIN.
|
||||
* @param pincode 6-digit PIN (0..999999), or @c UINT32_MAX for the default PIN.
|
||||
* @param nik_lifetime_sec NIK lifetime in seconds; forwarded unchanged to
|
||||
* @c pairing_key_installed_cb (NAN app currently
|
||||
* passes 86400).
|
||||
* @param pairing_key_installed_cb Callback invoked after pairwise key installation with peer NMI.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int esp_nan_supp_pasn_initiator_auth(const uint8_t *peer_nmi, uint32_t pincode,
|
||||
uint32_t nik_lifetime_sec,
|
||||
esp_nan_pairing_key_installed_cb_t pairing_key_installed_cb);
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,6 +43,7 @@ struct nan_pasn_data {
|
||||
size_t pasn_ptk_len;
|
||||
struct pasn_data *pasn;
|
||||
nan_pasn_pairing_key_installed_cb_t pairing_key_installed_cb;
|
||||
uint32_t nik_lifetime_sec;
|
||||
};
|
||||
|
||||
int nan_initiate_pasn_verify(struct nan_pasn_data *pd, const uint8_t *peer_addr,
|
||||
|
||||
@@ -1254,7 +1254,8 @@ static int nan_handle_pasn_auth(struct nan_pasn_data *nan,
|
||||
nan->pairing_key_installed_cb(pasn->peer_addr,
|
||||
(uint8_t)nan->dev_role,
|
||||
nan_pasn_pasn_cipher_to_ndp_csid(pasn->cipher),
|
||||
nd_pmk, nd_pmk_len);
|
||||
nd_pmk, nd_pmk_len,
|
||||
nan->nik_lifetime_sec);
|
||||
}
|
||||
forced_memzero(pasn_get_ptk(pasn), sizeof(pasn->ptk));
|
||||
nan_pasn_data_deinit(nan);
|
||||
@@ -1311,7 +1312,8 @@ int nan_pasn_auth_rx(struct nan_pasn_data *nan, const struct ieee80211_auth *mgm
|
||||
nan->pairing_key_installed_cb(pasn->peer_addr,
|
||||
(uint8_t)nan->dev_role,
|
||||
nan_pasn_pasn_cipher_to_ndp_csid(pasn->cipher),
|
||||
nd_pmk, nd_pmk_len);
|
||||
nd_pmk, nd_pmk_len,
|
||||
nan->nik_lifetime_sec);
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
@@ -1550,6 +1552,7 @@ int nan_pasn_auth_initiate(struct nan_pasn_data *pd, const uint8_t *peer_addr, i
|
||||
struct nan_pasn_eloop_ctx {
|
||||
uint8_t peer_addr[ETH_ALEN];
|
||||
uint32_t pincode;
|
||||
uint32_t nik_lifetime_sec;
|
||||
esp_nan_pairing_key_installed_cb_t pairing_key_installed_cb;
|
||||
};
|
||||
|
||||
@@ -1580,10 +1583,11 @@ static void nan_pasn_auth_eloop_cb(void *eloop_ctx, void *user_data)
|
||||
|
||||
esp_nan_app_set_pasn_data(pd);
|
||||
pd->pairing_key_installed_cb = ctx->pairing_key_installed_cb;
|
||||
pd->nik_lifetime_sec = ctx->nik_lifetime_sec;
|
||||
|
||||
if (ctx->pincode != UINT32_MAX) {
|
||||
n = os_snprintf(pin_digits, sizeof(pin_digits), "%06u",
|
||||
(unsigned)(ctx->pincode % 1000000U));
|
||||
(unsigned)ctx->pincode);
|
||||
if (os_snprintf_error(sizeof(pin_digits), n)) {
|
||||
nan_pasn_data_deinit(pd);
|
||||
os_free(ctx);
|
||||
@@ -1610,6 +1614,7 @@ static void nan_pasn_auth_eloop_cb(void *eloop_ctx, void *user_data)
|
||||
}
|
||||
|
||||
int esp_nan_supp_pasn_initiator_auth(const uint8_t *peer_nmi, uint32_t pincode,
|
||||
uint32_t nik_lifetime_sec,
|
||||
esp_nan_pairing_key_installed_cb_t pairing_key_installed_cb)
|
||||
{
|
||||
struct nan_pasn_eloop_ctx *ctx;
|
||||
@@ -1621,6 +1626,7 @@ int esp_nan_supp_pasn_initiator_auth(const uint8_t *peer_nmi, uint32_t pincode,
|
||||
|
||||
os_memcpy(ctx->peer_addr, peer_nmi, ETH_ALEN);
|
||||
ctx->pincode = pincode;
|
||||
ctx->nik_lifetime_sec = nik_lifetime_sec;
|
||||
ctx->pairing_key_installed_cb = pairing_key_installed_cb;
|
||||
|
||||
if (eloop_register_timeout(0, 0, nan_pasn_auth_eloop_cb, NULL, ctx) != 0) {
|
||||
@@ -1740,7 +1746,7 @@ int pasn_responder_init(const uint8_t *peer_addr, uint32_t pincode)
|
||||
|
||||
if (pincode != UINT32_MAX) {
|
||||
n = os_snprintf(pin_digits, sizeof(pin_digits), "%06u",
|
||||
(unsigned)(pincode % 1000000U));
|
||||
(unsigned)pincode);
|
||||
if (os_snprintf_error(sizeof(pin_digits), n)) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1773,6 +1779,7 @@ fail:
|
||||
struct pasn_responder_eloop_ctx {
|
||||
uint8_t peer_addr[ETH_ALEN];
|
||||
uint32_t pincode;
|
||||
uint32_t nik_lifetime_sec;
|
||||
esp_nan_pairing_key_installed_cb_t pairing_key_installed_cb;
|
||||
};
|
||||
|
||||
@@ -1789,12 +1796,14 @@ static void pasn_responder_init_eloop_cb(void *eloop_ctx, void *user_data)
|
||||
pd = esp_nan_app_get_pasn_data();
|
||||
if (pd) {
|
||||
pd->pairing_key_installed_cb = ctx->pairing_key_installed_cb;
|
||||
pd->nik_lifetime_sec = ctx->nik_lifetime_sec;
|
||||
}
|
||||
}
|
||||
os_free(ctx);
|
||||
}
|
||||
|
||||
int esp_nan_supp_pasn_responder_init(const uint8_t *peer_nmi, uint32_t pincode,
|
||||
uint32_t nik_lifetime_sec,
|
||||
esp_nan_pairing_key_installed_cb_t pairing_key_installed_cb)
|
||||
{
|
||||
struct pasn_responder_eloop_ctx *ctx;
|
||||
@@ -1805,6 +1814,7 @@ int esp_nan_supp_pasn_responder_init(const uint8_t *peer_nmi, uint32_t pincode,
|
||||
}
|
||||
|
||||
ctx->pincode = pincode;
|
||||
ctx->nik_lifetime_sec = nik_lifetime_sec;
|
||||
os_memcpy(ctx->peer_addr, peer_nmi, ETH_ALEN);
|
||||
ctx->pairing_key_installed_cb = pairing_key_installed_cb;
|
||||
|
||||
|
||||
@@ -240,6 +240,13 @@ typedef enum {
|
||||
NAN_KEY_NM_TK,
|
||||
} nan_key_type_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t peer_nik[ESP_WIFI_NAN_NIK_LEN]; /**< Peer's NAN Identity Key (16 bytes) */
|
||||
uint8_t npk[ESP_WIFI_NAN_NPK_LEN]; /**< NAN Pairwise Key / NCS-SK PMK (32 bytes) */
|
||||
uint8_t service_hash[6]; /**< Service Hash of the corresponding service */
|
||||
bool is_valid; /**< True if this credential entry is valid */
|
||||
} wifi_nan_peer_creds_t;
|
||||
|
||||
typedef wifi_scan_channel_bitmap_t channel_bitmap_t;
|
||||
|
||||
uint8_t *esp_wifi_ap_get_prof_pmk_internal(void);
|
||||
@@ -334,5 +341,12 @@ void esp_wifi_ap_set_group_mgmt_cipher_internal(wifi_cipher_type_t cipher);
|
||||
uint8_t esp_wifi_op_class_supported_internal(uint8_t op_class, uint8_t min_chan, uint8_t max_chan, uint8_t inc, uint8_t bw, channel_bitmap_t *non_pref_channels);
|
||||
bool esp_wifi_is_wpa3_compatible_mode_enabled(uint8_t if_index);
|
||||
uint8_t esp_wifi_ap_get_owe_config_internal(void);
|
||||
esp_err_t esp_nan_complete_pairing(uint8_t svc_id, uint8_t peer_svc_id);
|
||||
esp_err_t esp_wifi_nan_load_saved_creds(uint8_t own_nik[ESP_WIFI_NAN_NIK_LEN], bool *own_nik_valid,
|
||||
wifi_nan_peer_creds_t peer_creds[ESP_WIFI_NAN_MAX_PEER_CREDS], uint8_t *num_peer_creds);
|
||||
esp_err_t esp_wifi_nan_save_own_nik(const uint8_t own_nik[ESP_WIFI_NAN_NIK_LEN]);
|
||||
esp_err_t esp_wifi_nan_save_creds_for_peer(const uint8_t peer_nik[ESP_WIFI_NAN_NIK_LEN],
|
||||
const uint8_t npk[ESP_WIFI_NAN_NPK_LEN], const uint8_t service_hash[6]);
|
||||
esp_err_t esp_wifi_nan_erase_all_creds(void);
|
||||
|
||||
#endif /* _ESP_WIFI_DRIVER_H_ */
|
||||
|
||||
@@ -441,7 +441,11 @@ void esp_wifi_unregister_wpa3_cb(void)
|
||||
}
|
||||
#endif /* CONFIG_WPA3_SAE */
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
/* AP-side (hostap) SAE authentication. CONFIG_SAE may also be enabled for PASN
|
||||
* with SoftAP disabled, but this block both defines and calls SoftAP-only
|
||||
* primitives (esp_send_sae_auth_reply, handle_auth_sae), so additionally gate
|
||||
* it on CONFIG_ESP_WIFI_SOFTAP_SUPPORT. */
|
||||
#if defined(CONFIG_SAE) && defined(CONFIG_ESP_WIFI_SOFTAP_SUPPORT)
|
||||
|
||||
static TaskHandle_t g_wpa3_hostap_task_hdl = NULL;
|
||||
static QueueHandle_t g_wpa3_hostap_evt_queue = NULL;
|
||||
@@ -861,4 +865,4 @@ void esp_wifi_register_wpa3_ap_cb(struct wpa_funcs *wpa_cb)
|
||||
wpa_cb->wpa3_hostap_handle_auth = wpa3_hostap_handle_auth;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SAE */
|
||||
#endif /* CONFIG_SAE && CONFIG_ESP_WIFI_SOFTAP_SUPPORT */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef ESP_WPA3_H
|
||||
#define ESP_WPA3_H
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_wifi_driver.h"
|
||||
|
||||
#ifdef CONFIG_WPA3_SAE
|
||||
@@ -27,7 +28,10 @@ static inline void esp_wpa3_free_sae_data(void)
|
||||
|
||||
#endif /* CONFIG_WPA3_SAE */
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
/* AP-side (hostap) SAE definitions require SoftAP; CONFIG_SAE alone may be set
|
||||
* for PASN. The #else branch provides a no-op esp_wifi_register_wpa3_ap_cb()
|
||||
* stub so callers link in PASN-only (SoftAP-disabled) builds. */
|
||||
#if defined(CONFIG_SAE) && defined(CONFIG_ESP_WIFI_SOFTAP_SUPPORT)
|
||||
enum SIG_WPA3_TASK {
|
||||
SIG_WPA3_RX_COMMIT,
|
||||
SIG_WPA3_RX_CONFIRM,
|
||||
@@ -58,12 +62,12 @@ void esp_wifi_register_wpa3_ap_cb(struct wpa_funcs *wpa_cb);
|
||||
int wpa3_hostap_auth_init(void *data);
|
||||
bool wpa3_hostap_auth_deinit(void);
|
||||
|
||||
#else /* CONFIG_SAE */
|
||||
#else /* CONFIG_SAE && CONFIG_ESP_WIFI_SOFTAP_SUPPORT */
|
||||
|
||||
static inline void esp_wifi_register_wpa3_ap_cb(struct wpa_funcs *wpa_cb)
|
||||
{
|
||||
wpa_cb->wpa3_hostap_handle_auth = NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SAE */
|
||||
#endif /* CONFIG_SAE && CONFIG_ESP_WIFI_SOFTAP_SUPPORT */
|
||||
#endif /* ESP_WPA3_H */
|
||||
|
||||
@@ -28,7 +28,10 @@
|
||||
#define OWE_DH_GRP19 19
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
/* AP-side SAE authentication. Requires SoftAP: CONFIG_SAE may also be enabled
|
||||
* for PASN (SoftAP disabled), but this block calls SoftAP-only primitives
|
||||
* (e.g. esp_send_sae_auth_reply), so gate it on CONFIG_ESP_WIFI_SOFTAP_SUPPORT. */
|
||||
#if defined(CONFIG_SAE) && defined(CONFIG_ESP_WIFI_SOFTAP_SUPPORT)
|
||||
|
||||
static void sae_set_state(struct sta_info *sta, enum sae_state state,
|
||||
const char *reason)
|
||||
@@ -778,7 +781,7 @@ queued:
|
||||
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SAE */
|
||||
#endif /* CONFIG_SAE && CONFIG_ESP_WIFI_SOFTAP_SUPPORT */
|
||||
|
||||
u16 wpa_res_to_status_code(enum wpa_validate_result res)
|
||||
{
|
||||
|
||||
@@ -45,6 +45,8 @@ const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = {
|
||||
.ccmp_encrypt = (esp_ccmp_encrypt_t)ccmp_encrypt,
|
||||
.aes_gmac = (esp_aes_gmac_t)esp_aes_gmac,
|
||||
.sha256_vector = (esp_sha256_vector_t)sha256_vector,
|
||||
.aes_wrap = (esp_aes_wrap_t)aes_wrap,
|
||||
.aes_unwrap = (esp_aes_unwrap_t)aes_unwrap,
|
||||
};
|
||||
|
||||
const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs = {
|
||||
|
||||
@@ -54,7 +54,7 @@ void pasn_initiator_pmksa_cache_remove(struct rsn_pmksa_cache *pmksa,
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry;
|
||||
|
||||
entry = pmksa_cache_get(pmksa, bssid, NULL, NULL);
|
||||
entry = pmksa_cache_get(pmksa, bssid, NULL, NULL, NULL);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
@@ -68,7 +68,7 @@ int pasn_initiator_pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry;
|
||||
|
||||
entry = pmksa_cache_get(pmksa, bssid, NULL, NULL);
|
||||
entry = pmksa_cache_get(pmksa, bssid, NULL, NULL, NULL);
|
||||
if (entry) {
|
||||
os_memcpy(pmkid, entry->pmkid, PMKID_LEN);
|
||||
os_memcpy(pmk, entry->pmk, entry->pmk_len);
|
||||
@@ -627,7 +627,8 @@ static struct wpabuf * wpas_pasn_build_auth_1(struct pasn_data *pasn,
|
||||
} else if (wrapped_data != WPA_PASN_WRAPPED_DATA_NO) {
|
||||
struct rsn_pmksa_cache_entry *pmksa;
|
||||
|
||||
pmksa = pmksa_cache_get(pasn->pmksa, pasn->peer_addr, NULL, NULL);
|
||||
pmksa = pmksa_cache_get(pasn->pmksa, pasn->peer_addr, pasn->own_addr,
|
||||
NULL, NULL);
|
||||
if (pmksa && pasn->custom_pmkid_valid)
|
||||
pmkid = pasn->custom_pmkid;
|
||||
else if (pmksa)
|
||||
@@ -900,7 +901,7 @@ static int wpas_pasn_set_pmk(struct pasn_data *pasn,
|
||||
pmkid = rsn_data->pmkid;
|
||||
}
|
||||
|
||||
pmksa = pmksa_cache_get(pasn->pmksa, pasn->peer_addr,
|
||||
pmksa = pmksa_cache_get(pasn->pmksa, pasn->peer_addr, pasn->own_addr,
|
||||
pmkid, NULL);
|
||||
if (pmksa) {
|
||||
wpa_printf(MSG_DEBUG, "PASN: Using PMKSA");
|
||||
|
||||
Reference in New Issue
Block a user