diff --git a/examples/wifi/wifi_aware/nan_publisher/main/Kconfig.projbuild b/examples/wifi/wifi_aware/nan_publisher/main/Kconfig.projbuild index 1e410615f6a..55dd37874c5 100644 --- a/examples/wifi/wifi_aware/nan_publisher/main/Kconfig.projbuild +++ b/examples/wifi/wifi_aware/nan_publisher/main/Kconfig.projbuild @@ -23,4 +23,38 @@ menu "Example Configuration" help Send a reply to the Follow Up sent by a Subscriber + menu "Security Configuration" + config EXAMPLE_NAN_SECURITY_ENABLED + bool "Enable NAN Security" + depends on ESP_WIFI_NAN_SECURITY + default y + + choice EXAMPLE_NAN_SECURITY_METHOD + prompt "Security Method" + depends on EXAMPLE_NAN_SECURITY_ENABLED + default EXAMPLE_NAN_SEC_METHOD_PASSPHRASE + help + Choose the method for NAN discovery security. + + config EXAMPLE_NAN_SEC_METHOD_PASSPHRASE + bool "Passphrase-based (Password)" + config EXAMPLE_NAN_SEC_METHOD_PMK + bool "Direct PMK (32-byte hex)" + endchoice + + config EXAMPLE_NAN_PASSPHRASE + string "Passphrase" + depends on EXAMPLE_NAN_SEC_METHOD_PASSPHRASE + default "password" + help + Passphrase for NAN Discovery security. + + config EXAMPLE_NAN_PMK + string "Direct PMK (Hex)" + depends on EXAMPLE_NAN_SEC_METHOD_PMK + default "ee3585063056d164d15454ad39010d4e2640b0d82fb24a2d6899862d273c68bf" + help + 32-byte hex string representing the PMK. + endmenu + endmenu diff --git a/examples/wifi/wifi_aware/nan_publisher/main/publisher_main.c b/examples/wifi/wifi_aware/nan_publisher/main/publisher_main.c index fefb6956528..bf87c8b863d 100644 --- a/examples/wifi/wifi_aware/nan_publisher/main/publisher_main.c +++ b/examples/wifi/wifi_aware/nan_publisher/main/publisher_main.c @@ -11,6 +11,7 @@ software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ +#include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -37,6 +38,23 @@ static EventGroupHandle_t nan_event_group; static const char *TAG = "publisher"; +#ifdef CONFIG_EXAMPLE_NAN_SEC_METHOD_PMK +static bool decode_hex_string(const char *hex, uint8_t *out, size_t out_len) +{ + if (!hex || !out || strlen(hex) != out_len * 2) { + return false; + } + for (size_t i = 0; i < out_len; i++) { + unsigned int byte; + if (sscanf(hex + 2 * i, "%2x", &byte) != 1) { + return false; + } + out[i] = (uint8_t)byte; + } + return true; +} +#endif + static int NAN_RECEIVE = BIT0; uint8_t g_peer_inst_id; static uint8_t g_peer_mac[ETH_ALEN]; @@ -105,10 +123,30 @@ void wifi_nan_publish(void) .matching_filter = EXAMPLE_NAN_MATCHING_FILTER, .single_replied_event = 1, /* 0 - All incoming NDP requests will be internally accepted, - 1 - All incoming NDP requests raise NDP_INDICATION event and require esp_wifi_nan_datapath_resp to accept or reject. */ + 1 - All incoming NDP requests raise NDP_INDICATION event and require esp_wifi_nan_datapath_resp to accept or reject. + This example uses 1 to exercise nan_ndp_indication_event_handler(). */ .ndp_resp_needed = 1, .datapath_reqd = 1, +#ifdef CONFIG_EXAMPLE_NAN_SECURITY_ENABLED + .security_reqd = 1, + .security_cfg = { + .csid_bitmap = WIFI_NAN_CSID_BIT_NCS_SK_128, +#ifdef CONFIG_EXAMPLE_NAN_SEC_METHOD_PMK + .use_pmk = true, +#else + .use_pmk = false, + .passphrase = CONFIG_EXAMPLE_NAN_PASSPHRASE, +#endif + }, +#endif }; +#if defined(CONFIG_EXAMPLE_NAN_SECURITY_ENABLED) && defined(CONFIG_EXAMPLE_NAN_SEC_METHOD_PMK) + if (!decode_hex_string(CONFIG_EXAMPLE_NAN_PMK, publish_cfg.security_cfg.pmk, + sizeof(publish_cfg.security_cfg.pmk))) { + ESP_LOGE(TAG, "Failed to decode CONFIG_EXAMPLE_NAN_PMK"); + return; + } +#endif pub_id = esp_wifi_nan_publish_service(&publish_cfg); if (pub_id == 0) { diff --git a/examples/wifi/wifi_aware/nan_subscriber/main/Kconfig.projbuild b/examples/wifi/wifi_aware/nan_subscriber/main/Kconfig.projbuild index 0bba7d93381..be176366843 100644 --- a/examples/wifi/wifi_aware/nan_subscriber/main/Kconfig.projbuild +++ b/examples/wifi/wifi_aware/nan_subscriber/main/Kconfig.projbuild @@ -33,4 +33,38 @@ menu "Example Configuration" help Send a message to the Publisher using NAN Follow Up + menu "Security Configuration" + config EXAMPLE_NAN_SECURITY_ENABLED + bool "Enable NAN Security" + depends on ESP_WIFI_NAN_SECURITY + default y + + choice EXAMPLE_NAN_SECURITY_METHOD + prompt "Security Method" + depends on EXAMPLE_NAN_SECURITY_ENABLED + default EXAMPLE_NAN_SEC_METHOD_PASSPHRASE + help + Choose the method for NAN discovery security. + + config EXAMPLE_NAN_SEC_METHOD_PASSPHRASE + bool "Passphrase-based (Password)" + config EXAMPLE_NAN_SEC_METHOD_PMK + bool "Direct PMK (32-byte hex)" + endchoice + + config EXAMPLE_NAN_PASSPHRASE + string "Passphrase" + depends on EXAMPLE_NAN_SEC_METHOD_PASSPHRASE + default "password" + help + Passphrase for NAN Discovery security. Must match the publisher. + + config EXAMPLE_NAN_PMK + string "Direct PMK (Hex)" + depends on EXAMPLE_NAN_SEC_METHOD_PMK + default "ee3585063056d164d15454ad39010d4e2640b0d82fb24a2d6899862d273c68bf" + help + 32-byte hex string representing the PMK. Must match the publisher. + endmenu + endmenu diff --git a/examples/wifi/wifi_aware/nan_subscriber/main/subscriber_main.c b/examples/wifi/wifi_aware/nan_subscriber/main/subscriber_main.c index 2e72d1bcbde..e8caea7eb61 100644 --- a/examples/wifi/wifi_aware/nan_subscriber/main/subscriber_main.c +++ b/examples/wifi/wifi_aware/nan_subscriber/main/subscriber_main.c @@ -37,6 +37,29 @@ static const char *TAG = "subscriber"; +#ifdef CONFIG_EXAMPLE_NAN_SEC_METHOD_PMK +/* Decode lowercase hex string into a fixed-size byte buffer. Returns true on + * success. Mirrors the helper in the publisher example so both endpoints + * derive the same PMK from the same hex input. */ +static bool decode_hex_string(const char *hex, uint8_t *out, size_t out_len) +{ + if (!hex || !out) { + return false; + } + if (strlen(hex) != out_len * 2) { + return false; + } + for (size_t i = 0; i < out_len; i++) { + unsigned int byte; + if (sscanf(hex + 2 * i, "%2x", &byte) != 1) { + return false; + } + out[i] = (uint8_t)byte; + } + return true; +} +#endif + static EventGroupHandle_t nan_event_group; const int NAN_SERVICE_MATCH = BIT0; @@ -45,7 +68,7 @@ const int NDP_FAILED = BIT2; static wifi_event_nan_svc_match_t g_svc_match_evt; -static uint8_t s_ipv6_identifier[8] = {0}; +static uint8_t s_ipv6_identifier[NAN_IPV6_ADDR_ID_LEN] = {0}; static void nan_receive_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) @@ -60,6 +83,23 @@ static void nan_receive_event_handler(void *arg, esp_event_base_t event_base, #ifdef CONFIG_EXAMPLE_NAN_SEND_PING static uint8_t g_peer_ndi[ETH_ALEN]; +static void nan_ndp_confirmed_event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + wifi_event_ndp_confirm_t *evt = (wifi_event_ndp_confirm_t *)event_data; + + if (evt->status == NDP_STATUS_REJECTED) { + ESP_LOGE(TAG, "NDP request to Peer "MACSTR" rejected [NDP ID - %d]", MAC2STR(evt->peer_nmi), evt->ndp_id); + xEventGroupSetBits(nan_event_group, NDP_FAILED); + } else { + memcpy(g_peer_ndi, evt->peer_ndi, sizeof(g_peer_ndi)); + memcpy(s_ipv6_identifier, evt->ipv6_identifier, sizeof(evt->ipv6_identifier)); + xEventGroupSetBits(nan_event_group, NDP_CONFIRMED); + } +} +#endif + +#ifdef CONFIG_EXAMPLE_NAN_SEND_PING static void cmd_ping_on_ping_success(esp_ping_handle_t hdl, void *args) { uint8_t ttl; @@ -103,21 +143,6 @@ static void cmd_ping_on_ping_end(esp_ping_handle_t hdl, void *args) esp_ping_delete_session(hdl); } -static void nan_ndp_confirmed_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) -{ - wifi_event_ndp_confirm_t *evt = (wifi_event_ndp_confirm_t *)event_data; - - if (evt->status == NDP_STATUS_REJECTED) { - ESP_LOGE(TAG, "NDP request to Peer "MACSTR" rejected [NDP ID - %d]", MAC2STR(evt->peer_nmi), evt->ndp_id); - xEventGroupSetBits(nan_event_group, NDP_FAILED); - } else { - memcpy(g_peer_ndi, evt->peer_ndi, sizeof(g_peer_ndi)); - memcpy(s_ipv6_identifier, evt->ipv6_identifier, sizeof(evt->ipv6_identifier)); - xEventGroupSetBits(nan_event_group, NDP_CONFIRMED); - } -} - static void ping_nan_peer(esp_netif_t *netif) { esp_ping_config_t config = ESP_PING_DEFAULT_CONFIG(); @@ -196,7 +221,26 @@ void wifi_nan_subscribe(void) #endif .matching_filter = EXAMPLE_NAN_MATCHING_FILTER, .single_match_event = 1, +#ifdef CONFIG_EXAMPLE_NAN_SECURITY_ENABLED + .security_reqd = 1, + .security_cfg = { + .csid_bitmap = WIFI_NAN_CSID_BIT_NCS_SK_128, +#ifdef CONFIG_EXAMPLE_NAN_SEC_METHOD_PMK + .use_pmk = true, +#else + .use_pmk = false, + .passphrase = CONFIG_EXAMPLE_NAN_PASSPHRASE, +#endif + }, +#endif }; +#if defined(CONFIG_EXAMPLE_NAN_SECURITY_ENABLED) && defined(CONFIG_EXAMPLE_NAN_SEC_METHOD_PMK) + if (!decode_hex_string(CONFIG_EXAMPLE_NAN_PMK, subscribe_cfg.security_cfg.pmk, + sizeof(subscribe_cfg.security_cfg.pmk))) { + ESP_LOGE(TAG, "Failed to decode CONFIG_EXAMPLE_NAN_PMK"); + return; + } +#endif sub_id = esp_wifi_nan_subscribe_service(&subscribe_cfg); if (sub_id == 0) { @@ -231,7 +275,8 @@ void wifi_nan_subscribe(void) memcpy(ndp_req.peer_mac, g_svc_match_evt.pub_if_mac, sizeof(ndp_req.peer_mac)); esp_wifi_nan_datapath_req(&ndp_req); - EventBits_t bits_2 = xEventGroupWaitBits(nan_event_group, NDP_CONFIRMED, pdFALSE, pdFALSE, portMAX_DELAY); + EventBits_t bits_2 = xEventGroupWaitBits(nan_event_group, NDP_CONFIRMED | NDP_FAILED, + pdFALSE, pdFALSE, portMAX_DELAY); if (bits_2 & NDP_CONFIRMED) { vTaskDelay(5000 / portTICK_PERIOD_MS); ping_nan_peer(nan_netif);