mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
fix(nan): clear group keys on NAN stop and peer NDP teardown
Fix group-key lifecycle gaps on the secured NDP path: - On NAN stop, reset the device-global IGTK/BIGTK state via new nan_security_reset_own_group_keys() so the next start regenerates fresh keys. Previously the one-shot nan_ensure_own_igtk/bigtk kept own_*_set, so restart re-installed the stale key with IPN/BIPN=0, resetting the blob's monotonic replay counter (and reusing keys if the NMI changed). - On peer teardown (nan_app_clear_one_peer_tks), remove the peer RX IGTK/BIGTK from the blob (they were installed against the peer NMI at NDP confirm) and scrub ndl->igtk/bigtk + flags. Previously only the GTK was removed, leaving stale BIP keys installed and key bytes in memory. - Copy the GTK Key RSC into the descriptor only when a GTK KDE is present, matching the comment and avoiding stale RSC on an IGTK/BIGTK-only path.
This commit is contained in:
@@ -272,11 +272,28 @@ static void nan_app_clear_one_peer_tks(const uint8_t *peer_nmi)
|
||||
key_rsc, sizeof(key_rsc),
|
||||
NULL, 0, NAN_KEY_ND_GTK);
|
||||
|
||||
/* Drop the peer's RX IGTK/BIGTK (BIP-CMAC-128, installed against the
|
||||
* peer NMI at NDP confirm) so no stale BIP keys linger in the blob. */
|
||||
if (ndl->igtk_set) {
|
||||
esp_wifi_set_nan_key_internal(NAN_WIFI_WPA_ALG_BIP_CMAC_128,
|
||||
(uint8_t *)peer_nmi, ndl->igtk_keyid, 0,
|
||||
key_rsc, 6,
|
||||
NULL, 0, NAN_KEY_ND_IGTK);
|
||||
}
|
||||
if (ndl->bigtk_set) {
|
||||
esp_wifi_set_nan_key_internal(NAN_WIFI_WPA_ALG_BIP_CMAC_128,
|
||||
(uint8_t *)peer_nmi, ndl->bigtk_keyid, 0,
|
||||
key_rsc, 6,
|
||||
NULL, 0, NAN_KEY_ND_BIGTK);
|
||||
}
|
||||
|
||||
forced_memzero(ndl->nd_tk, sizeof(ndl->nd_tk));
|
||||
forced_memzero(ndl->nd_kck, sizeof(ndl->nd_kck));
|
||||
forced_memzero(ndl->nd_kek, sizeof(ndl->nd_kek));
|
||||
forced_memzero(ndl->gtk, sizeof(ndl->gtk));
|
||||
forced_memzero(ndl->own_gtk, sizeof(ndl->own_gtk));
|
||||
forced_memzero(ndl->igtk, sizeof(ndl->igtk));
|
||||
forced_memzero(ndl->bigtk, sizeof(ndl->bigtk));
|
||||
ndl->ptk_set = 0;
|
||||
ndl->tk_len = 0;
|
||||
ndl->kck_len = 0;
|
||||
@@ -285,6 +302,10 @@ static void nan_app_clear_one_peer_tks(const uint8_t *peer_nmi)
|
||||
ndl->own_gtk_set = 0;
|
||||
ndl->gtk_len = 0;
|
||||
ndl->own_gtk_len = 0;
|
||||
ndl->igtk_set = 0;
|
||||
ndl->bigtk_set = 0;
|
||||
ndl->igtk_len = 0;
|
||||
ndl->bigtk_len = 0;
|
||||
}
|
||||
|
||||
/* Fallback when no NDL slot tracks peer_ndi yet. */
|
||||
@@ -1868,6 +1889,13 @@ void esp_nan_action_stop(void)
|
||||
nan_app_clear_paired_peers();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
/* Drop the device-global IGTK/BIGTK so the next start regenerates fresh
|
||||
* keys instead of re-installing a stale key with IPN/BIPN=0 (which would
|
||||
* reset the blob's replay counter) — see nan_security_reset_own_group_keys. */
|
||||
nan_security_reset_own_group_keys();
|
||||
#endif
|
||||
|
||||
esp_nan_internal_register_callbacks(NULL);
|
||||
os_event_group_clear_bits(nan_event_group, NAN_STARTED_BIT);
|
||||
os_event_group_set_bits(nan_event_group, NAN_STOPPED_BIT);
|
||||
|
||||
@@ -529,6 +529,12 @@ esp_err_t nan_security_populate_initiator_ndl(struct ndl_info *ndl,
|
||||
* Call once at NAN start; never per-NDP (would reset the blob's BIPN counter). */
|
||||
void nan_security_install_own_group_integrity_keys(void);
|
||||
|
||||
/* Clear the device-global IGTK/BIGTK state on NAN stop so the next NAN start
|
||||
* regenerates fresh keys. Prevents re-installing a stale key with IPN/BIPN=0
|
||||
* (which resets the blob's monotonic replay counter) and key reuse if the NMI
|
||||
* is re-randomized on restart. */
|
||||
void nan_security_reset_own_group_keys(void);
|
||||
|
||||
/*
|
||||
* Match subscriber discovery security to a publisher's params.
|
||||
* NCS-SK: Compare locally derived ND-PMKID (subscriber passphrase, publisher NMI) to
|
||||
|
||||
@@ -765,6 +765,19 @@ void nan_security_install_own_group_integrity_keys(void)
|
||||
}
|
||||
}
|
||||
|
||||
void nan_security_reset_own_group_keys(void)
|
||||
{
|
||||
forced_memzero(s_nan_ctx.own_igtk, sizeof(s_nan_ctx.own_igtk));
|
||||
memset(s_nan_ctx.own_igtk_ipn, 0, sizeof(s_nan_ctx.own_igtk_ipn));
|
||||
s_nan_ctx.own_igtk_keyid = 0;
|
||||
s_nan_ctx.own_igtk_set = false;
|
||||
|
||||
forced_memzero(s_nan_ctx.own_bigtk, sizeof(s_nan_ctx.own_bigtk));
|
||||
memset(s_nan_ctx.own_bigtk_bipn, 0, sizeof(s_nan_ctx.own_bigtk_bipn));
|
||||
s_nan_ctx.own_bigtk_keyid = 0;
|
||||
s_nan_ctx.own_bigtk_set = false;
|
||||
}
|
||||
|
||||
/* NAN KDE header (802.11 Fig 12-34: DD len OUI(3) DataType(1)); mirrors hostap
|
||||
* nan_add_kde_hdr(). data_len excludes the DD/len/OUI/type bytes. */
|
||||
static uint8_t *nan_kde_put_hdr(uint8_t *p, uint8_t data_type, uint8_t data_len)
|
||||
@@ -962,8 +975,10 @@ static int nan_append_own_group_kdes(struct ndl_info *ndl, uint8_t *key_desc, si
|
||||
key_desc[NAN_KEY_DESC_DATA_LEN_OFF] = (wrapped_len >> 8) & 0xFF;
|
||||
key_desc[NAN_KEY_DESC_DATA_LEN_OFF + 1] = wrapped_len & 0xFF;
|
||||
|
||||
/* Key RSC carries the GTK's RSC when a GTK KDE is present (§7.1.3.5). */
|
||||
memcpy(&key_desc[NAN_KEY_DESC_RSC_OFF], ndl->own_gtk_rsc, NAN_KEY_RSC_LEN);
|
||||
/* Key RSC carries the GTK's RSC only when a GTK KDE is present (§7.1.3.5). */
|
||||
if (want_gtk) {
|
||||
memcpy(&key_desc[NAN_KEY_DESC_RSC_OFF], ndl->own_gtk_rsc, NAN_KEY_RSC_LEN);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Group Key Data wrapped: %u plain -> %u wrapped bytes, KDEs=[%s%s%s]",
|
||||
(unsigned)plain_len, (unsigned)wrapped_len,
|
||||
|
||||
Reference in New Issue
Block a user