mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
fix(nan): Add service hash to NVS to maintain pairing states after reset
This commit is contained in:
@@ -479,6 +479,7 @@ 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));
|
||||
@@ -499,13 +500,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;
|
||||
}
|
||||
@@ -1624,9 +1626,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 "
|
||||
@@ -1758,6 +1774,17 @@ 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,
|
||||
@@ -1781,7 +1808,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);
|
||||
}
|
||||
@@ -1805,6 +1832,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 "
|
||||
@@ -1905,6 +1933,18 @@ 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->pairing)) {
|
||||
ESP_LOGE(TAG, "No free service slot");
|
||||
@@ -1918,7 +1958,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;
|
||||
|
||||
@@ -232,6 +232,7 @@ struct own_svc_info {
|
||||
bool nik_fup_pending;
|
||||
uint8_t nik_fup_pending_peer_nmi[MACADDR_LEN];
|
||||
#endif
|
||||
uint8_t svc_hash[6];
|
||||
};
|
||||
|
||||
/* Per-NDP link state */
|
||||
@@ -486,6 +487,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);
|
||||
bool nan_compute_service_id(const char *service_name, uint8_t service_id[6]);
|
||||
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_SECURITY */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -868,7 +868,7 @@ static void nan_pairing_key_installed_cb(const uint8_t *peer_nmi,
|
||||
* 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)
|
||||
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;
|
||||
|
||||
@@ -889,6 +889,7 @@ static void nan_app_update_peer_creds(const uint8_t *peer_nik, const uint8_t *np
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -940,9 +941,9 @@ void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
|
||||
|
||||
bool already_had_nik = false;
|
||||
bool pairing_completed = false;
|
||||
uint8_t own_svc_id_to_disable = 0;
|
||||
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);
|
||||
@@ -961,33 +962,33 @@ void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
|
||||
if (paired) {
|
||||
memcpy(persist_npk, paired->nd_pmk, ESP_WIFI_NAN_NPK_LEN);
|
||||
}
|
||||
nan_app_update_peer_creds(nik, paired ? paired->nd_pmk : NULL);
|
||||
persist_creds = s_nan_ctx.use_nvs_for_caching;
|
||||
|
||||
own = nan_find_own_svc(p_peer_svc->own_svc_id);
|
||||
|
||||
if (!already_had_nik) {
|
||||
pairing_completed = true;
|
||||
own_svc_id_to_disable = p_peer_svc->own_svc_id;
|
||||
}
|
||||
|
||||
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);
|
||||
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};
|
||||
|
||||
struct own_svc_info *own = nan_find_own_svc(own_svc_id_to_disable);
|
||||
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(own_svc_id_to_disable);
|
||||
esp_nan_complete_pairing(p_peer_svc ? p_peer_svc->own_svc_id : 0);
|
||||
nan_app_post_event(WIFI_EVENT_NAN_PAIRING_CONFIRM, &evt, sizeof(evt));
|
||||
}
|
||||
|
||||
@@ -1047,6 +1048,7 @@ bool esp_nan_verify_nira(uint8_t *peer_mac, uint8_t *nira_attr, uint16_t nira_at
|
||||
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;
|
||||
@@ -1061,7 +1063,7 @@ bool esp_nan_verify_nira(uint8_t *peer_mac, uint8_t *nira_attr, uint16_t nira_at
|
||||
if (match) {
|
||||
ESP_LOGD(TAG, "NIRA verify: OK for "MACSTR, MAC2STR(peer_mac));
|
||||
} else {
|
||||
ESP_LOGW(TAG, "NIRA verify: no matching NIK for "MACSTR, MAC2STR(peer_mac));
|
||||
ESP_LOGD(TAG, "NIRA verify: no matching NIK for "MACSTR, MAC2STR(peer_mac));
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ static bool nan_csid_bitmap_has_pasn(uint16_t csid_bitmap)
|
||||
* 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])
|
||||
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;
|
||||
|
||||
@@ -243,6 +243,7 @@ typedef enum {
|
||||
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];
|
||||
bool is_valid;
|
||||
} wifi_nan_peer_creds_t;
|
||||
|
||||
@@ -345,7 +346,7 @@ esp_err_t esp_wifi_nan_load_saved_creds(uint8_t own_nik[ESP_WIFI_NAN_NIK_LEN], b
|
||||
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 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_ */
|
||||
|
||||
Reference in New Issue
Block a user