mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
Merge branch 'feat/nan_encrypted_data_path' into 'master'
feat(wifi): support encrypted data path in WiFi Aware (NAN) See merge request espressif/esp-idf!45270
This commit is contained in:
@@ -36,7 +36,7 @@ ic_reset_extra_softap_rx_ba = 0x2f800c78;
|
||||
ieee80211_align_eb = 0x2f800c7c;
|
||||
ieee80211_ampdu_reorder = 0x2f800c80;
|
||||
ieee80211_ampdu_start_age_timer = 0x2f800c84;
|
||||
ieee80211_encap_esfbuf = 0x2f800c88;
|
||||
/*ieee80211_encap_esfbuf = 0x2f800c88;*/
|
||||
ieee80211_is_tx_allowed = 0x2f800c8c;
|
||||
ieee80211_output_pending_eb = 0x2f800c90;
|
||||
ieee80211_output_process = 0x2f800c94;
|
||||
|
||||
@@ -70,6 +70,9 @@ if(CONFIG_ESP_WIFI_ENABLED OR CONFIG_ESP_HOST_WIFI_ENABLED)
|
||||
|
||||
if(CONFIG_ESP_WIFI_NAN_SYNC_ENABLE OR CONFIG_ESP_WIFI_NAN_USD_ENABLE)
|
||||
list(APPEND srcs "wifi_apps/nan_app/src/nan_app.c")
|
||||
if(CONFIG_ESP_WIFI_NAN_SECURITY)
|
||||
list(APPEND srcs "wifi_apps/nan_app/src/nan_security.c")
|
||||
endif()
|
||||
endif()
|
||||
if(CONFIG_ESP_WIFI_ENABLE_ROAMING_APP)
|
||||
list(APPEND srcs "wifi_apps/roaming_app/src/roaming_app.c")
|
||||
|
||||
@@ -593,6 +593,23 @@ menu "Wi-Fi"
|
||||
help
|
||||
Enable Wi-Fi Aware: Synchronization feature (NAN-Sync).
|
||||
|
||||
config ESP_WIFI_NAN_SECURITY
|
||||
bool "Enable Wi-Fi Aware: Encrypted Pairwise Datapath (NDP Security)"
|
||||
depends on ESP_WIFI_NAN_SYNC_ENABLE && IDF_EXPERIMENTAL_FEATURES && ESP_WIFI_MBEDTLS_CRYPTO
|
||||
select MBEDTLS_PKCS5_C
|
||||
select MBEDTLS_SHA256_C
|
||||
default n
|
||||
help
|
||||
Enable encrypted pairwise datapath for Wi-Fi Aware (NAN).
|
||||
Adds PBKDF2 key derivation (mbedTLS PKCS#5), 4-way handshake (M1-M4),
|
||||
PTK derivation, and CCMP key installation for secured NAN
|
||||
data links. Disable to save code size when only open
|
||||
datapaths are needed.
|
||||
|
||||
Requires ESP_WIFI_MBEDTLS_CRYPTO + MBEDTLS_PKCS5_C + MBEDTLS_SHA256_C
|
||||
for ND-PMK derivation via pbkdf2_sha256() (MBEDTLS_MD_C is pulled in
|
||||
transitively by MBEDTLS_PKCS5_C).
|
||||
|
||||
config ESP_WIFI_NAN_USD_ENABLE
|
||||
bool "Enable Wi-Fi Aware: Unsynchronized service discovery (NAN-USD)"
|
||||
depends on IDF_EXPERIMENTAL_FEATURES
|
||||
|
||||
@@ -34,41 +34,310 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WIFI_MAC_ADDR_LEN 6 /**< Length of an 802.11 MAC address in octets */
|
||||
#ifndef NAN_IPV6_IDENTIFIER_LEN
|
||||
#define NAN_IPV6_IDENTIFIER_LEN 8 /**< Length of a NAN IPv6 interface identifier in octets */
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
QueueHandle_t handle; /**< FreeRTOS queue handler */
|
||||
void *storage; /**< storage for FreeRTOS queue */
|
||||
} wifi_static_queue_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Datapath Security Type (Wi-Fi Aware v4.0 §9.5.16.1 Table 85, "Security Present" bit)
|
||||
*/
|
||||
typedef enum {
|
||||
WIFI_NAN_SECURITY_OPEN = 0, /**< NDP does not require security */
|
||||
WIFI_NAN_SECURITY_ENCRYPTED = 1, /**< NDP requires security */
|
||||
} wifi_nan_security_type_t;
|
||||
|
||||
/**
|
||||
* @brief NAN single-PMKID security parameters
|
||||
*
|
||||
* @note Holds one derived ND-PMK + ND-PMKID per spec §7.1.3.5. Used both for
|
||||
* the blob's per-service derived cache (own-side Publish SDF SCIA TX)
|
||||
* and for the host's per-NDL handshake state (M1-M4). Single PMKID is
|
||||
* sufficient because every spec key derivation step yields exactly one
|
||||
* PMKID for a given (PMK, peer NMIs, Service ID) tuple.
|
||||
* Shared between WiFi libraries and NAN app layer.
|
||||
*/
|
||||
typedef struct {
|
||||
wifi_nan_security_type_t type; /**< Security Type (Open/Encrypted) */
|
||||
uint16_t csid_bitmap; /**< Selected Cipher Suite ID bit (WIFI_NAN_CSID_BIT_*) */
|
||||
uint8_t nd_pmk[ESP_WIFI_NAN_NDP_PMK_LEN]; /**< ND-PMK */
|
||||
uint8_t nd_pmkid[ESP_WIFI_NAN_NDP_PMKID_LEN]; /**< ND-PMKID */
|
||||
uint8_t group_data_prot: 1; /**< Group addressed data frame protection. Reserved: not supported right now. */
|
||||
uint8_t group_mgmt_prot: 1; /**< Group addressed management frame protection. Reserved: not supported right now. */
|
||||
uint8_t reserved: 6; /**< Reserved */
|
||||
} wifi_nan_security_params_t;
|
||||
|
||||
/**
|
||||
* @brief NAN peer security material parsed from Publish/Subscribe SDF SCIA
|
||||
*
|
||||
* @note Per Wi-Fi Aware v4.0 §7.1.3.5, a publisher SDF SCIA may advertise
|
||||
* multiple ND-PMKIDs (one per cached PMK). The receiver stores them
|
||||
* and matches against locally-derived PMKID at NDP-initiation time.
|
||||
* Internal only — not part of the public API. Shared between WiFi
|
||||
* libraries and NAN app layer.
|
||||
*/
|
||||
#define NAN_PEER_MAX_PMKIDS 2 /**< Internal cap; can grow without API impact */
|
||||
typedef struct {
|
||||
uint16_t csid_bitmap; /**< Peer's advertised Cipher Suite ID bitmap */
|
||||
uint8_t num_pmkids; /**< Number of parsed PMKIDs */
|
||||
uint8_t pmkids[NAN_PEER_MAX_PMKIDS][ESP_WIFI_NAN_NDP_PMKID_LEN]; /**< Parsed ND-PMKIDs */
|
||||
uint8_t group_data_prot: 1; /**< Peer advertises group data frame protection */
|
||||
uint8_t group_mgmt_prot: 1; /**< Peer advertises group mgmt frame protection */
|
||||
uint8_t reserved: 6; /**< Reserved */
|
||||
} wifi_nan_peer_sdf_security_t;
|
||||
|
||||
/* NAN Peer info parsed from SDF */
|
||||
struct nan_cb_peer_info {
|
||||
uint8_t peer_mac[6]; /**< Peer NMI / interface MAC */
|
||||
uint8_t peer_mac[WIFI_MAC_ADDR_LEN]; /**< Peer NMI / interface MAC */
|
||||
uint8_t peer_svc_id; /**< Peer's service instance ID */
|
||||
uint16_t sdea; /**< SDEA control field bits */
|
||||
uint32_t device_caps; /**< NAN device capabilities */
|
||||
uint8_t ssi_ver; /**< SSI version (service_match) */
|
||||
uint8_t *ssi; /**< Service-specific information */
|
||||
uint16_t ssi_len; /**< SSI length in bytes */
|
||||
wifi_nan_peer_sdf_security_t *peer_security_params; /**< Peer's discovery security params parsed from SDF */
|
||||
nan_vendor_ie_t *vendor_ie; /**< Vendor-specific IE, if any */
|
||||
};
|
||||
|
||||
/* NDP Peer info parsed from NAF */
|
||||
/* NDP Peer info parsed from NAF. */
|
||||
struct ndp_cb_peer_info {
|
||||
uint8_t ndp_id;
|
||||
uint8_t peer_nmi[6];
|
||||
uint8_t peer_ndi[6];
|
||||
uint8_t peer_nmi[WIFI_MAC_ADDR_LEN];
|
||||
uint8_t peer_ndi[WIFI_MAC_ADDR_LEN];
|
||||
uint8_t *ssi;
|
||||
uint16_t ssi_len;
|
||||
};
|
||||
|
||||
/* Host-side callbacks the closed-source NAN blob fires up into nan_app.
|
||||
* Registered once at nan_app init; all callbacks run in blob/WiFi-task
|
||||
* context, so handlers must be non-blocking and avoid heavy work. */
|
||||
struct nan_sync_callbacks {
|
||||
/* Subscriber side: a Publish SDF matching the local subscribe was
|
||||
* received from a peer.
|
||||
* sub_id -- local subscribe service instance ID
|
||||
* peer_info -- publisher details (see struct nan_cb_peer_info) */
|
||||
void (* service_match)(uint8_t sub_id, struct nan_cb_peer_info *peer_info);
|
||||
|
||||
/* Publisher side: a Solicited Publish SDF was just transmitted in
|
||||
* response to a Subscribe match. Fires once per recipient.
|
||||
* pub_id -- local publish service instance ID
|
||||
* peer_info -- subscriber MAC and its service instance ID */
|
||||
void (* replied)(uint8_t pub_id, struct nan_cb_peer_info *peer_info);
|
||||
|
||||
/* Either side: a Follow-up SDF was received for an existing service
|
||||
* match (post-discovery messaging).
|
||||
* svc_id -- local service instance ID this Follow-up targets
|
||||
* peer_info -- sender MAC and SSI payload */
|
||||
void (* receive)(uint8_t svc_id, struct nan_cb_peer_info *peer_info);
|
||||
|
||||
/* Publisher side (NDP Responder): an NDP Request (M1) was received.
|
||||
* Host either auto-accepts or waits for esp_wifi_nan_datapath_resp()
|
||||
* depending on the publish-time ndp_resp_needed flag.
|
||||
* pub_id -- local publish instance bound to this request
|
||||
* peer_info -- initiator's ndp_id, NMI, NDI, SSI
|
||||
* device_caps -- initiator's NAN device capabilities */
|
||||
void (* ndp_indication)(uint8_t pub_id, struct ndp_cb_peer_info *peer_info, uint32_t device_caps);
|
||||
|
||||
/* Either side: NDP setup completed (success or rejection).
|
||||
* status -- NDP_STATUS_ACCEPTED / NDP_STATUS_REJECTED
|
||||
* peer_info -- peer ndp_id, NMI, NDI
|
||||
* own_ndi -- locally-assigned NDI for this NDP
|
||||
* ipv6_identifier -- 8-byte IPv6 interface identifier learnt from
|
||||
* the peer; all-zero if the peer did not
|
||||
* advertise one (host then derives it from the
|
||||
* peer NDI). */
|
||||
void (* ndp_confirm)(uint8_t status, struct ndp_cb_peer_info *peer_info,
|
||||
uint8_t own_ndi[6], uint8_t ipv6_identifier[8]);
|
||||
void (* ndp_terminated)(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[6]);
|
||||
uint8_t own_ndi[WIFI_MAC_ADDR_LEN],
|
||||
uint8_t ipv6_identifier[NAN_IPV6_IDENTIFIER_LEN]);
|
||||
|
||||
/* Either side: an established NDP was torn down.
|
||||
* reason -- termination reason code (peer-initiated, timeout, ...)
|
||||
* ndp_id -- NDP identifier of the terminated path
|
||||
* init_ndi -- initiator's NDI for this NDP */
|
||||
void (* ndp_terminated)(uint8_t reason, uint8_t ndp_id,
|
||||
uint8_t init_ndi[WIFI_MAC_ADDR_LEN]);
|
||||
|
||||
/* TX completion for a host-queued NAN action frame (Follow-up, etc.).
|
||||
* context -- opaque tag matching the original TX request
|
||||
* tx_status -- true on transmit success, false on failure */
|
||||
void (* action_txdone)(uint32_t context, bool tx_status);
|
||||
|
||||
/* Initiator-side M2 RX indication. Blob fires this after parsing the
|
||||
* Responder NDI from the M2 NDP attribute (Wi-Fi Aware v4.0 §9.5.16.1
|
||||
* Table 82) and before invoking esp_nan_verify_ndp_resp_mic, so the
|
||||
* host can populate ndl->peer_ndi for spec-correct PTK derivation
|
||||
* (§7.1.3.5: PTK uses Data Interface addresses). */
|
||||
void (* ndp_response_indication)(struct ndp_cb_peer_info *peer_info);
|
||||
};
|
||||
|
||||
/* Host helpers for NAN encrypted-datapath, registered via
|
||||
* esp_nan_internal_register_secure_dp_funcs() at nan_app init.
|
||||
* Security-gated fields are NULL when CONFIG_ESP_WIFI_NAN_SECURITY=n. */
|
||||
struct nan_secure_dp_funcs {
|
||||
/* === Always-present helpers === */
|
||||
|
||||
/* Fired by the blob after a host-built NDP setup frame (M2/M4) is
|
||||
* transmitted, so the host can advance its NDP setup state machine.
|
||||
* msg_type -- 0x01 = M2 (NDP Response), 0x02 = M4 (Security Install)
|
||||
* tx_status -- true on TX success, false on failure */
|
||||
void (*ndp_tx_done_cb)(uint8_t ndp_id, const uint8_t *peer_nmi,
|
||||
uint8_t msg_type, bool tx_status);
|
||||
|
||||
/* === Security-gated helpers (NULL when SECURITY=n) === */
|
||||
|
||||
/* --- Length getters: callers use these to size TX buffers before
|
||||
* invoking the matching construct_*() / get_*_key_desc helper. --- */
|
||||
|
||||
/* Byte length of the CSIA emitted for the union of the two cipher
|
||||
* suite bitmaps (Wi-Fi Aware v4.0 §9.5.21.2). */
|
||||
uint32_t (*get_csia_len)(uint16_t own_csid_bitmap, uint16_t peer_csid_bitmap);
|
||||
|
||||
/* Byte length of a SCIA carrying @c num_pmkids 16-octet ND-PMKIDs
|
||||
* (§9.5.21.4). */
|
||||
uint32_t (*get_scia_len)(uint8_t num_pmkids);
|
||||
|
||||
/* Byte length of a NAN Shared Key Descriptor attribute (§9.5.21.5)
|
||||
* with the given Key Data field length. */
|
||||
uint32_t (*get_shared_key_desc_attr_len)(uint16_t key_data_len);
|
||||
|
||||
/* Byte length of the M4 Shared Key Descriptor including any
|
||||
* encrypted KDE payload (GTK/IGTK/BIGTK). */
|
||||
int (*ndp_security_install_get_shared_desc_len)(void);
|
||||
|
||||
/* --- CSIA / SCIA construction. Each writes a complete NAN
|
||||
* attribute (header + body) at @c frm and returns bytes
|
||||
* written, or -1 on error. --- */
|
||||
|
||||
/* Build CSIA from the negotiated own/peer cipher suite bitmaps. */
|
||||
int (*construct_csia)(uint8_t *frm, uint8_t pub_id,
|
||||
uint16_t own_csid_bitmap, uint16_t peer_csid_bitmap);
|
||||
|
||||
/* Build SCIA for a Publish SDF: emits one SCID per provisioned
|
||||
* ND-PMKID so subscribers can recognise themselves (§9.5.21.4). */
|
||||
int (*construct_scia_publish)(uint8_t *frm, uint8_t pub_id,
|
||||
uint8_t num_pmkids,
|
||||
const uint8_t pmkids[][ESP_WIFI_NAN_NDP_PMKID_LEN]);
|
||||
|
||||
/* Build SCIA for an NDP Request (M1): single SCID matching the
|
||||
* (ndp_id, peer_nmi) credential the initiator selected. */
|
||||
int (*construct_scia_ndp_req)(uint8_t *frm, uint8_t ndp_id,
|
||||
const uint8_t *peer_nmi);
|
||||
|
||||
/* Build SCIA for an NDP Response (M2): echoes the SCID accepted
|
||||
* by the responder. */
|
||||
int (*construct_scia_ndp_resp)(uint8_t *frm, uint8_t ndp_id,
|
||||
const uint8_t *peer_nmi);
|
||||
|
||||
/* --- Shared Key Descriptor builders (M1 / M2 / M3 / M4).
|
||||
* Each writes the full NAN Shared Key Descriptor attribute
|
||||
* (§9.5.21.5) into @c buf; the MIC field is left zeroed and
|
||||
* must be populated by the matching update_*_mic helper after
|
||||
* the rest of the frame body is in place. Return bytes
|
||||
* written, -1 on error. --- */
|
||||
|
||||
/* M1 (NDP Request): Nonce = INonce, no MIC required. */
|
||||
int (*get_ndp_req_shared_key_desc)(uint8_t *buf, size_t buf_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* M2 (NDP Response): Nonce = RNonce, MIC over M2 body. */
|
||||
int (*get_ndp_resp_shared_key_desc)(uint8_t *buf, size_t buf_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* M3 (NDP Confirm): MIC over (Auth_Token || M3 body). */
|
||||
int (*get_ndp_confirm_shared_key_desc)(uint8_t *buf, size_t buf_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* M4 (Security Install): install bit set; carries any GTK / IGTK /
|
||||
* BIGTK KDEs encrypted under ND-KEK. */
|
||||
int (*get_ndp_security_install_key_desc)(uint8_t *buf, size_t buf_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* Compute and cache SHA-256(M1_body)[0:16] in the (ndp_id, peer_nmi)
|
||||
* NDL slot. The cached Authentication Token is later prepended when
|
||||
* computing/verifying the M3 MIC (Wi-Fi Aware v4.0 §7.1.3.5). */
|
||||
int (*capture_m1_auth_token)(const uint8_t *m1_body, size_t body_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* --- MIC compute (TX path). Fill the Key MIC field in
|
||||
* @c key_desc_attr (which sits inside @c m*_body) using
|
||||
* ND-KCK derived for this NDP. Return 0 on success. --- */
|
||||
|
||||
/* M2 MIC: HMAC over the entire M2 body. */
|
||||
int (*update_ndp_resp_mic)(uint8_t *m2_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* M3 MIC: HMAC over (cached M1 Auth_Token || M3 body). */
|
||||
int (*update_ndp_confirm_mic)(uint8_t *m3_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* M4 MIC: HMAC over the entire M4 body. */
|
||||
int (*update_ndp_security_install_mic)(uint8_t *m4_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* --- MIC verify (RX path). Recompute the expected Key MIC over
|
||||
* the same input as the matching update_* helper and compare
|
||||
* against the value in @c key_desc_attr. Return 0 on pass,
|
||||
* -1 on mismatch -- caller tears down the NDP on -1. --- */
|
||||
|
||||
/* M2 MIC verify (initiator). */
|
||||
int (*verify_ndp_resp_mic)(uint8_t *m2_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* M3 MIC verify (responder; uses cached M1 Auth_Token). */
|
||||
int (*verify_ndp_confirm_mic)(uint8_t *m3_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* M4 MIC verify (initiator). */
|
||||
int (*verify_ndp_security_install_mic)(uint8_t *m4_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* --- RX-path attribute parsers. --- */
|
||||
|
||||
/* Parse CSIA from a received NDP setup frame and populate the
|
||||
* negotiated cipher-suite bitmap in @c param. */
|
||||
void (*parse_ndp_csia)(void *frm, size_t buf_len, wifi_nan_security_params_t *param);
|
||||
|
||||
/* Parse SCIA from a received NDP setup frame and populate the
|
||||
* selected ND-PMKID + Publish ID in @c param. */
|
||||
void (*parse_ndp_scia)(void *frm, size_t buf_len, wifi_nan_security_params_t *param);
|
||||
|
||||
/* Parse the NAN Shared Key Descriptor attribute from a received
|
||||
* M2/M3/M4 frame: advances the NDL replay counter, captures the
|
||||
* peer Nonce, decrypts KDE payloads, and installs GTK/IGTK/BIGTK
|
||||
* as applicable. */
|
||||
void (*parse_ndp_key_desc)(void *frm, size_t buf_len, uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* Parse security-related attributes from an inbound Publish SDF
|
||||
* (CSIA + SCIA list) and populate @c security so the subscriber
|
||||
* state machine can pick a compatible credential. */
|
||||
esp_err_t (*parse_publish_security)(const uint8_t *attrs, size_t attrs_len,
|
||||
wifi_nan_peer_sdf_security_t *security);
|
||||
|
||||
/* Derives ND-PMK + ND-PMKID for each credential in sec_cfg->creds[] and
|
||||
* writes one entry per credential into out_derived[0..num_credentials).
|
||||
* Caller passes service_name + the original publish/subscribe security
|
||||
* cfg. out_derived must point at an array of at least
|
||||
* ESP_WIFI_NAN_MAX_CREDS_PER_SVC entries. All inputs are treated as
|
||||
* read-only. Returns ESP_FAIL or NULL when CONFIG_ESP_WIFI_NAN_SECURITY=n. */
|
||||
esp_err_t (*derive_security_params)(const char *service_name,
|
||||
const wifi_nan_discovery_security_params_t *sec_cfg,
|
||||
wifi_nan_security_params_t *out_derived);
|
||||
|
||||
/* Returns the cipher-suite bitmap negotiated for an in-flight NDP,
|
||||
* or 0 if the NDP is open. Used by RX/TX paths to decide whether
|
||||
* to apply CCMP/GCMP and which key length to use. */
|
||||
uint16_t (*get_ndp_security_csid)(uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -810,6 +1079,36 @@ esp_err_t esp_nan_internal_datapath_end(wifi_nan_datapath_end_req_t *req);
|
||||
*/
|
||||
esp_err_t esp_nan_internal_register_callbacks(struct nan_sync_callbacks *cb);
|
||||
|
||||
/**
|
||||
* @brief Register the NAN secure-datapath helper table with the WiFi libraries.
|
||||
*
|
||||
* Pass a pointer to a static struct populated by the host; pass NULL to
|
||||
* deregister at deinit time.
|
||||
*
|
||||
* @param fns Pointer to populated nan_secure_dp_funcs (or NULL to deregister)
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_nan_internal_register_secure_dp_funcs(struct nan_secure_dp_funcs *fns);
|
||||
|
||||
/**
|
||||
* @brief Install NAN pairwise/group key into Wi-Fi firmware key table
|
||||
*
|
||||
|
||||
* @param[in] alg Cipher algorithm identifier (for CCMP use 3)
|
||||
* @param[in] addr Peer address used for key lookup (NDI for NAN data path)
|
||||
* @param[in] key_idx Key index (use 0 for pairwise key)
|
||||
* @param[in] set_tx Set key as TX key when non-zero
|
||||
* @param[in] seq Initial sequence/RSC value (typically 8 bytes)
|
||||
* @param[in] seq_len Length of seq in bytes
|
||||
* @param[in] key Key material
|
||||
* @param[in] key_len Key length in bytes
|
||||
* @param[in] key_flag Key usage flags bitmask
|
||||
*
|
||||
* @return 0 on success, negative value on failure
|
||||
*/
|
||||
int esp_wifi_set_nan_key_internal(int alg, uint8_t *addr, int key_idx, int set_tx,
|
||||
uint8_t *seq, size_t seq_len, uint8_t *key, size_t key_len, int key_flag);
|
||||
|
||||
/**
|
||||
* @brief Connect WiFi station to the AP.
|
||||
*
|
||||
|
||||
@@ -17,6 +17,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define WIFI_AP_DEFAULT_MAX_IDLE_PERIOD 292 /**< Default timeout for SoftAP BSS Max Idle. Unit: 1000TUs >**/
|
||||
#define MAX_SSID_LEN 32 /**< Maximum length of SSID */
|
||||
#define MAX_PASSPHRASE_LEN 64 /**< Maximum length of passphrase */
|
||||
|
||||
/**
|
||||
* @brief Wi-Fi mode type
|
||||
@@ -864,6 +866,10 @@ typedef struct {
|
||||
#define ESP_WIFI_NDP_ROLE_INITIATOR 1 /**< Initiator role for NAN Data Path */
|
||||
#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_NDP_PMKID_LEN 16 /**< Length of NAN Datapath PMKID */
|
||||
#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 */
|
||||
#define ESP_WIFI_MAX_FILTER_LEN 256 /**< Maximum length of NAN service filter */
|
||||
#define ESP_WIFI_MAX_SVC_INFO_LEN 64 /**< Maximum length of NAN service info */
|
||||
@@ -905,6 +911,64 @@ typedef enum {
|
||||
NAN_SUBSCRIBE_PASSIVE, /**< Passively listens to Publish frames */
|
||||
} wifi_nan_service_type_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Cipher Suite IDs (Wi-Fi Aware v4.0 §4.1.1 & §6.1.1)
|
||||
*
|
||||
* @note Only WIFI_NAN_CSID_NCS_SK_128 is currently supported by the firmware.
|
||||
* The other values are reserved for future support; selecting any of
|
||||
* them via csid_bitmap will cause esp_wifi_nan_publish_service() and
|
||||
* esp_wifi_nan_subscribe_service() to fail.
|
||||
*/
|
||||
typedef enum {
|
||||
WIFI_NAN_CSID_NCS_SK_128 = 1, /**< NCS-SK-128 (PSK/Passphrase) */
|
||||
WIFI_NAN_CSID_NCS_SK_256 = 2, /**< NCS-SK-256 (PSK/Passphrase). Reserved: not supported right now. */
|
||||
WIFI_NAN_CSID_NCS_PK_2WDH_128 = 3, /**< NCS-PK-2WDH-128. Reserved: not supported right now. */
|
||||
WIFI_NAN_CSID_NCS_PK_2WDH_256 = 4, /**< NCS-PK-2WDH-256. Reserved: not supported right now. */
|
||||
WIFI_NAN_CSID_NCS_PK_PASN_128 = 7, /**< NCS-PK-PASN-128. Reserved: not supported right now. */
|
||||
WIFI_NAN_CSID_NCS_PK_PASN_256 = 8, /**< NCS-PK-PASN-256. Reserved: not supported right now. */
|
||||
} wifi_nan_cipher_suite_id_t;
|
||||
|
||||
#define WIFI_NAN_CSID_BIT_NCS_SK_128 (1 << WIFI_NAN_CSID_NCS_SK_128)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_SK_256 (1 << WIFI_NAN_CSID_NCS_SK_256)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_PK_2WDH_128 (1 << WIFI_NAN_CSID_NCS_PK_2WDH_128)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_PK_2WDH_256 (1 << WIFI_NAN_CSID_NCS_PK_2WDH_256)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_PK_PASN_128 (1 << WIFI_NAN_CSID_NCS_PK_PASN_128)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_PK_PASN_256 (1 << WIFI_NAN_CSID_NCS_PK_PASN_256)
|
||||
|
||||
/**
|
||||
* @brief NAN security credential - one passphrase or raw PMK + the cipher it's bound to.
|
||||
*
|
||||
* Per Wi-Fi Aware v4.0 §7.1.3.5 the PMKID derivation formula is cipher-specific
|
||||
* (NCS-SK-128 uses HMAC-SHA-256; NCS-SK-256 uses HMAC-SHA-384), so each
|
||||
* credential must carry the cipher it was provisioned for.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t csid; /**< Cipher Suite ID this credential is for (wifi_nan_cipher_suite_id_t value) */
|
||||
uint8_t use_pmk: 1; /**< 0 - Use passphrase, 1 - Use PMK directly */
|
||||
uint8_t reserved: 7; /**< Reserved */
|
||||
char passphrase[MAX_PASSPHRASE_LEN]; /**< NCS-SK passphrase (use_pmk=0). NUL-terminated. */
|
||||
uint8_t pmk[ESP_WIFI_NAN_NDP_PMK_LEN]; /**< NCS-SK PMK (use_pmk=1). Raw bytes, not NUL-terminated. */
|
||||
} wifi_nan_credential_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Discovery security parameters (Wi-Fi Aware v4.0 §4.1.1 - Publish/Subscribe)
|
||||
*
|
||||
* Per Wi-Fi Aware v4.0 §9.5.21.4 (SCIA) and §7.1.3.5 the Publish/Subscribe SDF
|
||||
* may advertise multiple ND-PMKIDs (one per provisioned ND-PMK). Applications
|
||||
* provide one or more credentials in @c creds; the stack derives PMK + PMKID
|
||||
* per credential and emits the multi-SCID list. Subscriber-side, the library
|
||||
* walks an incoming publisher's SCID list and matches against any of the
|
||||
* locally-provisioned credentials. The CSIA cipher bitmap advertised on air
|
||||
* is computed by the stack as the union of each credential's @c csid.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t group_data_prot: 1; /**< Group addressed data frame protection. Reserved: not supported right now. */
|
||||
uint8_t group_mgmt_prot: 1; /**< Group addressed management frame protection. Reserved: not supported right now. */
|
||||
uint8_t reserved: 6; /**< Reserved */
|
||||
uint8_t num_credentials; /**< Number of valid entries in @c creds (0..ESP_WIFI_NAN_MAX_CREDS_PER_SVC). 0 = open service. */
|
||||
wifi_nan_credential_t creds[ESP_WIFI_NAN_MAX_CREDS_PER_SVC]; /**< Credentials list. */
|
||||
} wifi_nan_discovery_security_params_t;
|
||||
|
||||
/**
|
||||
* @brief USD specific configuration parameters
|
||||
*
|
||||
@@ -924,9 +988,9 @@ typedef struct {
|
||||
* @brief NAN Vendor Specific Attribute format
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t vendor_oui[3]; /**< Vendor identifier (OUI) */
|
||||
uint16_t body_len; /**< Length of body payload (max NAN_VENDOR_IE_MAX_BODY_LEN bytes) */
|
||||
uint8_t *body; /**< Vendor specific body payload */
|
||||
uint8_t vendor_oui[WIFI_OUI_LEN]; /**< Vendor identifier (OUI) */
|
||||
uint16_t body_len; /**< Length of body payload (max 255 bytes) */
|
||||
uint8_t *body; /**< Vendor specific body payload */
|
||||
} nan_vendor_ie_t;
|
||||
|
||||
/**
|
||||
@@ -943,12 +1007,16 @@ typedef struct {
|
||||
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
|
||||
uint8_t ndp_resp_needed: 1; /**< 0 - Auto-Accept NDP Requests, 1 - Require explicit response with esp_wifi_nan_datapath_resp */
|
||||
uint8_t usd_discovery_flag: 1; /**< 0 - NAN Synchronization for Discovery, 1 - USD for Discovery. 'NAN Discovery flag' from specification */
|
||||
uint8_t reserved: 2; /**< Reserved */
|
||||
uint8_t security_reqd: 1; /**< Security: 0 - Open, 1 - Required (NDP Security) */
|
||||
uint8_t reserved: 1; /**< Reserved */
|
||||
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_SVC_SSI_LEN */
|
||||
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
|
||||
unsigned int ttl; /**< Run publish function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
|
||||
only one Publish message is transmitted */
|
||||
wifi_nan_usd_config_t usd_publish_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
|
||||
wifi_nan_discovery_security_params_t *security_cfg; /**< Security configuration parameters. Used when security_reqd is set, NULL otherwise.
|
||||
The driver makes a private copy during esp_wifi_nan_publish_service();
|
||||
the caller may free this immediately after the call returns. */
|
||||
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in publish frames */
|
||||
} wifi_nan_publish_cfg_t;
|
||||
|
||||
@@ -965,12 +1033,16 @@ typedef struct {
|
||||
uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */
|
||||
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
|
||||
uint8_t usd_discovery_flag: 1; /**< 0 - NAN Synchronization for Discovery, 1 - USD for Discovery. 'NAN Discovery flag' from specification */
|
||||
uint8_t reserved: 3; /**< Reserved */
|
||||
uint8_t security_reqd: 1; /**< Security: 0 - Open, 1 - Required (NDP Security) */
|
||||
uint8_t reserved: 2; /**< Reserved */
|
||||
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_SVC_SSI_LEN */
|
||||
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
|
||||
unsigned int ttl; /**< Run subscribe function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
|
||||
the subscriber listens until the first service match is reported. */
|
||||
wifi_nan_usd_config_t usd_subscribe_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
|
||||
wifi_nan_discovery_security_params_t *security_cfg; /**< Security configuration parameters. Used when security_reqd is set, NULL otherwise.
|
||||
The driver makes a private copy during esp_wifi_nan_subscribe_service();
|
||||
the caller may free this immediately after the call returns. */
|
||||
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in subscribe frames */
|
||||
} wifi_nan_subscribe_cfg_t;
|
||||
|
||||
@@ -990,16 +1062,41 @@ typedef struct {
|
||||
/**
|
||||
* @brief NAN Datapath Request parameters
|
||||
*
|
||||
* @note Datapath security is governed by the security_cfg passed to
|
||||
* esp_wifi_nan_subscribe_service(); the NAN library derives ND-PMK,
|
||||
* ND-PMKID and cipher selection internally from that subscribe-time
|
||||
* configuration and applies them to every NDP initiated against the
|
||||
* matched publisher. Per-NDP security parameters are not exposed on
|
||||
* this struct: the caller never handles raw key material.
|
||||
*
|
||||
* @note NCS-SK only. For pairing-based cipher suites (NCS-PK-PASN), the
|
||||
* per-peer ND-PMK is derived from a cached NPKSA and will be
|
||||
* installed via a separate pairing API; this struct will remain
|
||||
* unchanged.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t pub_id; /**< Publisher's service instance id */
|
||||
uint8_t peer_mac[6]; /**< Peer's MAC address */
|
||||
bool confirm_required; /**< NDP Confirm frame required */
|
||||
bool confirm_required; /**< NDP Confirm frame required. Always used for the secure NDP handshake. */
|
||||
} wifi_nan_datapath_req_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Datapath Response parameters
|
||||
*
|
||||
* @note Datapath security is governed by the security_cfg passed to
|
||||
* esp_wifi_nan_publish_service(); the NAN library derives ND-PMK,
|
||||
* ND-PMKID and cipher selection internally from that publish-time
|
||||
* configuration and applies them to every NDP this responder
|
||||
* accepts. Per-NDP security parameters are not exposed on this
|
||||
* struct: the caller never handles raw key material.
|
||||
*
|
||||
* @note NCS-SK only. For pairing-based cipher suites (NCS-PK-PASN), the
|
||||
* per-peer ND-PMK is derived from a cached NPKSA and will be
|
||||
* installed via a separate pairing API; this struct will remain
|
||||
* unchanged. The responder must already have the PMK cached at
|
||||
* M1 receive time (PMKID lookup happens before the indication
|
||||
* event), so per-NDP credential injection at response time is
|
||||
* not viable.
|
||||
*/
|
||||
typedef struct {
|
||||
bool accept; /**< True - Accept incoming NDP, False - Reject it */
|
||||
@@ -1230,8 +1327,6 @@ typedef enum {
|
||||
WPS_FAIL_REASON_MAX /**< Max WPS fail reason */
|
||||
} wifi_event_sta_wps_fail_reason_t;
|
||||
|
||||
#define MAX_SSID_LEN 32 /**< Maximum length of SSID */
|
||||
#define MAX_PASSPHRASE_LEN 64 /**< Maximum length of passphrase */
|
||||
#define MAX_WPS_AP_CRED 3 /**< Maximum number of AP credentials received from WPS handshake */
|
||||
|
||||
/**
|
||||
@@ -1412,7 +1507,8 @@ typedef struct {
|
||||
uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */
|
||||
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
|
||||
uint8_t ndpe_support: 1; /**< NDPE supported by peer */
|
||||
uint8_t reserved: 4; /**< Reserved */
|
||||
uint8_t security_reqd: 1; /**< Security: 0 - Open, 1 - Required (NDP Security) */
|
||||
uint8_t reserved: 3; /**< Reserved */
|
||||
uint32_t reserved_1; /**< Reserved */
|
||||
uint32_t reserved_2; /**< Reserved */
|
||||
uint8_t ssi_version; /**< Indicates version of SSI in Publish instance, 0 if not available */
|
||||
|
||||
+1
-1
Submodule components/esp_wifi/lib updated: 4bc9760929...bf7ccb11fe
@@ -572,6 +572,23 @@ config WIFI_RMT_NAN_SYNC_ENABLE
|
||||
help
|
||||
Enable Wi-Fi Aware: Synchronization feature (NAN-Sync).
|
||||
|
||||
config WIFI_RMT_NAN_SECURITY
|
||||
bool "Enable Wi-Fi Aware: Encrypted Pairwise Datapath (NDP Security)"
|
||||
depends on WIFI_RMT_NAN_SYNC_ENABLE && IDF_EXPERIMENTAL_FEATURES && WIFI_RMT_MBEDTLS_CRYPTO
|
||||
select MBEDTLS_PKCS5_C
|
||||
select MBEDTLS_SHA256_C
|
||||
default n
|
||||
help
|
||||
Enable encrypted pairwise datapath for Wi-Fi Aware (NAN).
|
||||
Adds PBKDF2 key derivation (mbedTLS PKCS#5), 4-way handshake (M1-M4),
|
||||
PTK derivation, and CCMP key installation for secured NAN
|
||||
data links. Disable to save code size when only open
|
||||
datapaths are needed.
|
||||
|
||||
Requires WIFI_RMT_MBEDTLS_CRYPTO + MBEDTLS_PKCS5_C + MBEDTLS_SHA256_C
|
||||
for ND-PMK derivation via pbkdf2_sha256() (MBEDTLS_MD_C is pulled in
|
||||
transitively by MBEDTLS_PKCS5_C).
|
||||
|
||||
config WIFI_RMT_NAN_USD_ENABLE
|
||||
bool "Enable Wi-Fi Aware: Unsynchronized service discovery (NAN-USD)"
|
||||
depends on IDF_EXPERIMENTAL_FEATURES
|
||||
|
||||
@@ -290,6 +290,13 @@ if WIFI_RMT_NAN_SYNC_ENABLE
|
||||
default WIFI_RMT_NAN_SYNC_ENABLE
|
||||
endif
|
||||
|
||||
if WIFI_RMT_NAN_SECURITY
|
||||
config ESP_WIFI_NAN_SECURITY # ignore: multiple-definition
|
||||
bool
|
||||
depends on WIFI_RMT_NAN_SYNC_ENABLE && IDF_EXPERIMENTAL_FEATURES && WIFI_RMT_MBEDTLS_CRYPTO
|
||||
default WIFI_RMT_NAN_SECURITY
|
||||
endif
|
||||
|
||||
if WIFI_RMT_NAN_USD_ENABLE
|
||||
config ESP_WIFI_NAN_USD_ENABLE # ignore: multiple-definition
|
||||
bool
|
||||
|
||||
@@ -17,6 +17,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define WIFI_AP_DEFAULT_MAX_IDLE_PERIOD 292 /**< Default timeout for SoftAP BSS Max Idle. Unit: 1000TUs >**/
|
||||
#define MAX_SSID_LEN 32 /**< Maximum length of SSID */
|
||||
#define MAX_PASSPHRASE_LEN 64 /**< Maximum length of passphrase */
|
||||
|
||||
/**
|
||||
* @brief Wi-Fi mode type
|
||||
@@ -864,6 +866,10 @@ typedef struct {
|
||||
#define ESP_WIFI_NDP_ROLE_INITIATOR 1 /**< Initiator role for NAN Data Path */
|
||||
#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_NDP_PMKID_LEN 16 /**< Length of NAN Datapath PMKID */
|
||||
#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 */
|
||||
#define ESP_WIFI_MAX_FILTER_LEN 256 /**< Maximum length of NAN service filter */
|
||||
#define ESP_WIFI_MAX_SVC_INFO_LEN 64 /**< Maximum length of NAN service info */
|
||||
@@ -905,6 +911,64 @@ typedef enum {
|
||||
NAN_SUBSCRIBE_PASSIVE, /**< Passively listens to Publish frames */
|
||||
} wifi_nan_service_type_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Cipher Suite IDs (Wi-Fi Aware v4.0 §4.1.1 & §6.1.1)
|
||||
*
|
||||
* @note Only WIFI_NAN_CSID_NCS_SK_128 is currently supported by the firmware.
|
||||
* The other values are reserved for future support; selecting any of
|
||||
* them via csid_bitmap will cause esp_wifi_nan_publish_service() and
|
||||
* esp_wifi_nan_subscribe_service() to fail.
|
||||
*/
|
||||
typedef enum {
|
||||
WIFI_NAN_CSID_NCS_SK_128 = 1, /**< NCS-SK-128 (PSK/Passphrase) */
|
||||
WIFI_NAN_CSID_NCS_SK_256 = 2, /**< NCS-SK-256 (PSK/Passphrase). Reserved: not supported right now. */
|
||||
WIFI_NAN_CSID_NCS_PK_2WDH_128 = 3, /**< NCS-PK-2WDH-128. Reserved: not supported right now. */
|
||||
WIFI_NAN_CSID_NCS_PK_2WDH_256 = 4, /**< NCS-PK-2WDH-256. Reserved: not supported right now. */
|
||||
WIFI_NAN_CSID_NCS_PK_PASN_128 = 7, /**< NCS-PK-PASN-128. Reserved: not supported right now. */
|
||||
WIFI_NAN_CSID_NCS_PK_PASN_256 = 8, /**< NCS-PK-PASN-256. Reserved: not supported right now. */
|
||||
} wifi_nan_cipher_suite_id_t;
|
||||
|
||||
#define WIFI_NAN_CSID_BIT_NCS_SK_128 (1 << WIFI_NAN_CSID_NCS_SK_128)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_SK_256 (1 << WIFI_NAN_CSID_NCS_SK_256)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_PK_2WDH_128 (1 << WIFI_NAN_CSID_NCS_PK_2WDH_128)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_PK_2WDH_256 (1 << WIFI_NAN_CSID_NCS_PK_2WDH_256)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_PK_PASN_128 (1 << WIFI_NAN_CSID_NCS_PK_PASN_128)
|
||||
#define WIFI_NAN_CSID_BIT_NCS_PK_PASN_256 (1 << WIFI_NAN_CSID_NCS_PK_PASN_256)
|
||||
|
||||
/**
|
||||
* @brief NAN security credential - one passphrase or raw PMK + the cipher it's bound to.
|
||||
*
|
||||
* Per Wi-Fi Aware v4.0 §7.1.3.5 the PMKID derivation formula is cipher-specific
|
||||
* (NCS-SK-128 uses HMAC-SHA-256; NCS-SK-256 uses HMAC-SHA-384), so each
|
||||
* credential must carry the cipher it was provisioned for.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t csid; /**< Cipher Suite ID this credential is for (wifi_nan_cipher_suite_id_t value) */
|
||||
uint8_t use_pmk: 1; /**< 0 - Use passphrase, 1 - Use PMK directly */
|
||||
uint8_t reserved: 7; /**< Reserved */
|
||||
char passphrase[MAX_PASSPHRASE_LEN]; /**< NCS-SK passphrase (use_pmk=0). NUL-terminated. */
|
||||
uint8_t pmk[ESP_WIFI_NAN_NDP_PMK_LEN]; /**< NCS-SK PMK (use_pmk=1). Raw bytes, not NUL-terminated. */
|
||||
} wifi_nan_credential_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Discovery security parameters (Wi-Fi Aware v4.0 §4.1.1 - Publish/Subscribe)
|
||||
*
|
||||
* Per Wi-Fi Aware v4.0 §9.5.21.4 (SCIA) and §7.1.3.5 the Publish/Subscribe SDF
|
||||
* may advertise multiple ND-PMKIDs (one per provisioned ND-PMK). Applications
|
||||
* provide one or more credentials in @c creds; the stack derives PMK + PMKID
|
||||
* per credential and emits the multi-SCID list. Subscriber-side, the library
|
||||
* walks an incoming publisher's SCID list and matches against any of the
|
||||
* locally-provisioned credentials. The CSIA cipher bitmap advertised on air
|
||||
* is computed by the stack as the union of each credential's @c csid.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t group_data_prot: 1; /**< Group addressed data frame protection. Reserved: not supported right now. */
|
||||
uint8_t group_mgmt_prot: 1; /**< Group addressed management frame protection. Reserved: not supported right now. */
|
||||
uint8_t reserved: 6; /**< Reserved */
|
||||
uint8_t num_credentials; /**< Number of valid entries in @c creds (0..ESP_WIFI_NAN_MAX_CREDS_PER_SVC). 0 = open service. */
|
||||
wifi_nan_credential_t creds[ESP_WIFI_NAN_MAX_CREDS_PER_SVC]; /**< Credentials list. */
|
||||
} wifi_nan_discovery_security_params_t;
|
||||
|
||||
/**
|
||||
* @brief USD specific configuration parameters
|
||||
*
|
||||
@@ -924,9 +988,9 @@ typedef struct {
|
||||
* @brief NAN Vendor Specific Attribute format
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t vendor_oui[3]; /**< Vendor identifier (OUI) */
|
||||
uint16_t body_len; /**< Length of body payload (max NAN_VENDOR_IE_MAX_BODY_LEN bytes) */
|
||||
uint8_t *body; /**< Vendor specific body payload */
|
||||
uint8_t vendor_oui[WIFI_OUI_LEN]; /**< Vendor identifier (OUI) */
|
||||
uint16_t body_len; /**< Length of body payload (max 255 bytes) */
|
||||
uint8_t *body; /**< Vendor specific body payload */
|
||||
} nan_vendor_ie_t;
|
||||
|
||||
/**
|
||||
@@ -943,12 +1007,16 @@ typedef struct {
|
||||
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
|
||||
uint8_t ndp_resp_needed: 1; /**< 0 - Auto-Accept NDP Requests, 1 - Require explicit response with esp_wifi_nan_datapath_resp */
|
||||
uint8_t usd_discovery_flag: 1; /**< 0 - NAN Synchronization for Discovery, 1 - USD for Discovery. 'NAN Discovery flag' from specification */
|
||||
uint8_t reserved: 2; /**< Reserved */
|
||||
uint8_t security_reqd: 1; /**< Security: 0 - Open, 1 - Required (NDP Security) */
|
||||
uint8_t reserved: 1; /**< Reserved */
|
||||
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_SVC_SSI_LEN */
|
||||
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
|
||||
unsigned int ttl; /**< Run publish function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
|
||||
only one Publish message is transmitted */
|
||||
wifi_nan_usd_config_t usd_publish_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
|
||||
wifi_nan_discovery_security_params_t *security_cfg; /**< Security configuration parameters. Used when security_reqd is set, NULL otherwise.
|
||||
The driver makes a private copy during esp_wifi_nan_publish_service();
|
||||
the caller may free this immediately after the call returns. */
|
||||
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in publish frames */
|
||||
} wifi_nan_publish_cfg_t;
|
||||
|
||||
@@ -965,12 +1033,16 @@ typedef struct {
|
||||
uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */
|
||||
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
|
||||
uint8_t usd_discovery_flag: 1; /**< 0 - NAN Synchronization for Discovery, 1 - USD for Discovery. 'NAN Discovery flag' from specification */
|
||||
uint8_t reserved: 3; /**< Reserved */
|
||||
uint8_t security_reqd: 1; /**< Security: 0 - Open, 1 - Required (NDP Security) */
|
||||
uint8_t reserved: 2; /**< Reserved */
|
||||
uint16_t ssi_len; /**< Length of service specific info, maximum allowed length - ESP_WIFI_MAX_SVC_SSI_LEN */
|
||||
uint8_t *ssi; /**< Service Specific Info of type wifi_nan_wfa_ssi_t for WFA defined protocols, otherwise proprietary and defined by Applications */
|
||||
unsigned int ttl; /**< Run subscribe function for a given time interval in seconds. If ttl=0 and usd_discovery_flag is enabled,
|
||||
the subscriber listens until the first service match is reported. */
|
||||
wifi_nan_usd_config_t usd_subscribe_config; /**< USD configuration parameters. Relevant only when 'usd_discovery_flag' is set. */
|
||||
wifi_nan_discovery_security_params_t *security_cfg; /**< Security configuration parameters. Used when security_reqd is set, NULL otherwise.
|
||||
The driver makes a private copy during esp_wifi_nan_subscribe_service();
|
||||
the caller may free this immediately after the call returns. */
|
||||
nan_vendor_ie_t *vendor_ie; /**< Vendor specific IE to be added in subscribe frames */
|
||||
} wifi_nan_subscribe_cfg_t;
|
||||
|
||||
@@ -990,16 +1062,41 @@ typedef struct {
|
||||
/**
|
||||
* @brief NAN Datapath Request parameters
|
||||
*
|
||||
* @note Datapath security is governed by the security_cfg passed to
|
||||
* esp_wifi_nan_subscribe_service(); the NAN library derives ND-PMK,
|
||||
* ND-PMKID and cipher selection internally from that subscribe-time
|
||||
* configuration and applies them to every NDP initiated against the
|
||||
* matched publisher. Per-NDP security parameters are not exposed on
|
||||
* this struct: the caller never handles raw key material.
|
||||
*
|
||||
* @note NCS-SK only. For pairing-based cipher suites (NCS-PK-PASN), the
|
||||
* per-peer ND-PMK is derived from a cached NPKSA and will be
|
||||
* installed via a separate pairing API; this struct will remain
|
||||
* unchanged.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t pub_id; /**< Publisher's service instance id */
|
||||
uint8_t peer_mac[6]; /**< Peer's MAC address */
|
||||
bool confirm_required; /**< NDP Confirm frame required */
|
||||
bool confirm_required; /**< NDP Confirm frame required. Always used for the secure NDP handshake. */
|
||||
} wifi_nan_datapath_req_t;
|
||||
|
||||
/**
|
||||
* @brief NAN Datapath Response parameters
|
||||
*
|
||||
* @note Datapath security is governed by the security_cfg passed to
|
||||
* esp_wifi_nan_publish_service(); the NAN library derives ND-PMK,
|
||||
* ND-PMKID and cipher selection internally from that publish-time
|
||||
* configuration and applies them to every NDP this responder
|
||||
* accepts. Per-NDP security parameters are not exposed on this
|
||||
* struct: the caller never handles raw key material.
|
||||
*
|
||||
* @note NCS-SK only. For pairing-based cipher suites (NCS-PK-PASN), the
|
||||
* per-peer ND-PMK is derived from a cached NPKSA and will be
|
||||
* installed via a separate pairing API; this struct will remain
|
||||
* unchanged. The responder must already have the PMK cached at
|
||||
* M1 receive time (PMKID lookup happens before the indication
|
||||
* event), so per-NDP credential injection at response time is
|
||||
* not viable.
|
||||
*/
|
||||
typedef struct {
|
||||
bool accept; /**< True - Accept incoming NDP, False - Reject it */
|
||||
@@ -1230,8 +1327,6 @@ typedef enum {
|
||||
WPS_FAIL_REASON_MAX /**< Max WPS fail reason */
|
||||
} wifi_event_sta_wps_fail_reason_t;
|
||||
|
||||
#define MAX_SSID_LEN 32 /**< Maximum length of SSID */
|
||||
#define MAX_PASSPHRASE_LEN 64 /**< Maximum length of passphrase */
|
||||
#define MAX_WPS_AP_CRED 3 /**< Maximum number of AP credentials received from WPS handshake */
|
||||
|
||||
/**
|
||||
@@ -1412,7 +1507,8 @@ typedef struct {
|
||||
uint8_t fsd_reqd: 1; /**< Further Service Discovery(FSD) required */
|
||||
uint8_t fsd_gas: 1; /**< 0 - Follow-up used for FSD, 1 - GAS used for FSD */
|
||||
uint8_t ndpe_support: 1; /**< NDPE supported by peer */
|
||||
uint8_t reserved: 4; /**< Reserved */
|
||||
uint8_t security_reqd: 1; /**< Security: 0 - Open, 1 - Required (NDP Security) */
|
||||
uint8_t reserved: 3; /**< Reserved */
|
||||
uint32_t reserved_1; /**< Reserved */
|
||||
uint32_t reserved_2; /**< Reserved */
|
||||
uint8_t ssi_version; /**< Indicates version of SSI in Publish instance, 0 if not available */
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(COMPONENTS main)
|
||||
|
||||
project(nan_crypto_test)
|
||||
@@ -0,0 +1,32 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | --------- |
|
||||
|
||||
# NAN Crypto Test Application
|
||||
|
||||
This test application validates the NAN ND-PMK derivation implementation against
|
||||
official Wi-Fi Aware Specification v4.0 test vectors (Appendix M.1).
|
||||
|
||||
## Building
|
||||
|
||||
```bash
|
||||
cd components/esp_wifi/test_apps/nan_crypto_test
|
||||
idf.py build
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
```bash
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
## Test Vectors
|
||||
|
||||
The application tests three official test vectors:
|
||||
1. Passphrase: "NAN"
|
||||
2. Passphrase: "NAN2"
|
||||
3. Passphrase: "NAN-Testvector-Phrase"
|
||||
|
||||
All use:
|
||||
- Cipher ID: 0x01 (NCS-SK-128)
|
||||
- Service ID: 2b9c450f6671
|
||||
- NMI: 02904c12d001
|
||||
@@ -0,0 +1,6 @@
|
||||
idf_component_register(SRCS "nan_pmk_test.c"
|
||||
"test_main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity esp_wifi nvs_flash esp_netif esp_event
|
||||
PRIV_REQUIRES wpa_supplicant
|
||||
PRIV_INCLUDE_DIRS ../../../../wpa_supplicant/src/)
|
||||
@@ -0,0 +1,4 @@
|
||||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# NAN Crypto Test Configuration
|
||||
#
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/*
|
||||
* NAN ND-PMK Derivation Test Vectors
|
||||
*
|
||||
* Test vectors from Wi-Fi Aware Specification v4.0
|
||||
* Appendix M.1 - Example test vectors for pass-phrase to ND-PMK conversion
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wifi_types.h"
|
||||
#include "utils/common.h" /* u8 typedef used by sha256.h */
|
||||
#include "crypto/sha256.h" /* mbedTLS-backed pbkdf2_sha256 from wpa_supplicant */
|
||||
|
||||
static const char *TAG = "nan_pmk_test";
|
||||
|
||||
typedef struct {
|
||||
const char *passphrase;
|
||||
uint8_t cipher_id;
|
||||
uint8_t service_id[6];
|
||||
uint8_t nmi[6];
|
||||
uint8_t expected_pmk[32];
|
||||
bool use_pmk;
|
||||
uint8_t input_pmk[32];
|
||||
const char *description;
|
||||
} test_vector_t;
|
||||
|
||||
/* Test Vector 1 */
|
||||
static const test_vector_t test_vector_1 = {
|
||||
.passphrase = "NAN",
|
||||
.cipher_id = 0x01,
|
||||
.service_id = {0x2b, 0x9c, 0x45, 0x0f, 0x66, 0x71},
|
||||
.nmi = {0x02, 0x90, 0x4c, 0x12, 0xd0, 0x01},
|
||||
.expected_pmk = {
|
||||
0xee, 0x35, 0x85, 0x06, 0x30, 0x56, 0xd1, 0x64,
|
||||
0xd1, 0x54, 0x54, 0xad, 0x39, 0x01, 0x0d, 0x4e,
|
||||
0x26, 0x40, 0xb0, 0xd8, 0x2f, 0xb2, 0x4a, 0x2d,
|
||||
0x68, 0x99, 0x86, 0x2d, 0x27, 0x3c, 0x68, 0xbf
|
||||
},
|
||||
.description = "Test Vector 1: Passphrase 'NAN'"
|
||||
};
|
||||
|
||||
/* Test Vector 2 */
|
||||
static const test_vector_t test_vector_2 = {
|
||||
.passphrase = "NAN2",
|
||||
.cipher_id = 0x01,
|
||||
.service_id = {0x2b, 0x9c, 0x45, 0x0f, 0x66, 0x71},
|
||||
.nmi = {0x02, 0x90, 0x4c, 0x12, 0xd0, 0x01},
|
||||
.expected_pmk = {
|
||||
0x87, 0x53, 0x4f, 0xa7, 0x74, 0xb1, 0x73, 0x2d,
|
||||
0xb0, 0x42, 0x66, 0xc4, 0x2c, 0x5d, 0x08, 0xd0,
|
||||
0x9e, 0x58, 0x63, 0xd1, 0xda, 0x11, 0xce, 0x25,
|
||||
0x76, 0xa8, 0xf1, 0x55, 0xfe, 0x26, 0xcd, 0x2a
|
||||
},
|
||||
.description = "Test Vector 2: Passphrase 'NAN2'"
|
||||
};
|
||||
|
||||
/* Test Vector 3 */
|
||||
static const test_vector_t test_vector_3 = {
|
||||
.passphrase = "NAN-Testvector-Phrase",
|
||||
.cipher_id = 0x01,
|
||||
.service_id = {0x2b, 0x9c, 0x45, 0x0f, 0x66, 0x71},
|
||||
.nmi = {0x02, 0x90, 0x4c, 0x12, 0xd0, 0x01},
|
||||
.expected_pmk = {
|
||||
0x4d, 0xc8, 0x6c, 0xcd, 0xa8, 0x04, 0xf4, 0xe2,
|
||||
0xe1, 0x39, 0xfc, 0xa5, 0xdd, 0xd2, 0x1b, 0xa5,
|
||||
0xc0, 0xb1, 0xb6, 0xed, 0x31, 0xff, 0xd7, 0x00,
|
||||
0x5e, 0x2d, 0x56, 0xf1, 0xe7, 0xbf, 0x51, 0x87
|
||||
},
|
||||
.description = "Test Vector 3: Passphrase 'NAN-Testvector-Phrase'"
|
||||
};
|
||||
|
||||
/* Test Vector 4: Direct PMK */
|
||||
static const test_vector_t test_vector_4 = {
|
||||
.use_pmk = true,
|
||||
.input_pmk = {
|
||||
0xee, 0x35, 0x85, 0x06, 0x30, 0x56, 0xd1, 0x64,
|
||||
0xd1, 0x54, 0x54, 0xad, 0x39, 0x01, 0x0d, 0x4e,
|
||||
0x26, 0x40, 0xb0, 0xd8, 0x2f, 0xb2, 0x4a, 0x2d,
|
||||
0x68, 0x99, 0x86, 0x2d, 0x27, 0x3c, 0x68, 0xbf
|
||||
},
|
||||
.expected_pmk = {
|
||||
0xee, 0x35, 0x85, 0x06, 0x30, 0x56, 0xd1, 0x64,
|
||||
0xd1, 0x54, 0x54, 0xad, 0x39, 0x01, 0x0d, 0x4e,
|
||||
0x26, 0x40, 0xb0, 0xd8, 0x2f, 0xb2, 0x4a, 0x2d,
|
||||
0x68, 0x99, 0x86, 0x2d, 0x27, 0x3c, 0x68, 0xbf
|
||||
},
|
||||
.description = "Test Vector 4: Direct PMK (using PMK from Vector 1)"
|
||||
};
|
||||
|
||||
static void print_hex(const char *label, const uint8_t *data, size_t len)
|
||||
{
|
||||
printf("%s: ", label);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
printf("%02x", data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static bool run_test_vector(const test_vector_t *tv)
|
||||
{
|
||||
uint8_t salt[14];
|
||||
uint8_t pmk[32];
|
||||
|
||||
ESP_LOGI(TAG, "\n=== %s ===", tv->description);
|
||||
|
||||
if (tv->use_pmk) {
|
||||
ESP_LOGI(TAG, "(Direct PMK Mode)");
|
||||
memcpy(pmk, tv->input_pmk, 32);
|
||||
} else {
|
||||
/* Construct Salt = Salt_Version || Cipher_Suite_ID || Service_ID || Publisher_NMI */
|
||||
salt[0] = 0x00; /* Salt Version */
|
||||
salt[1] = tv->cipher_id;
|
||||
memcpy(&salt[2], tv->service_id, 6);
|
||||
memcpy(&salt[8], tv->nmi, 6);
|
||||
|
||||
print_hex("Passphrase", (const uint8_t *)tv->passphrase, strlen(tv->passphrase));
|
||||
print_hex("Salt", salt, sizeof(salt));
|
||||
|
||||
/* Derive PMK using PBKDF2-SHA256 */
|
||||
if (pbkdf2_sha256(tv->passphrase, salt, sizeof(salt), 4096, pmk, 32) != 0) {
|
||||
ESP_LOGE(TAG, "PBKDF2-SHA256 derivation failed!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
print_hex("Derived PMK ", pmk, 32);
|
||||
print_hex("Expected PMK ", tv->expected_pmk, 32);
|
||||
|
||||
/* Compare with expected PMK */
|
||||
if (memcmp(pmk, tv->expected_pmk, 32) == 0) {
|
||||
ESP_LOGI(TAG, "✓ TEST PASSED");
|
||||
return true;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "✗ TEST FAILED - PMK mismatch!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void nan_pmk_run_test_vectors(void)
|
||||
{
|
||||
int passed = 0;
|
||||
int total = 4;
|
||||
|
||||
ESP_LOGI(TAG, "\n");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, " NAN ND-PMK Derivation Test Vectors");
|
||||
ESP_LOGI(TAG, " Wi-Fi Aware Spec v4.0 - Appendix M.1");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
|
||||
if (run_test_vector(&test_vector_1)) {
|
||||
passed++;
|
||||
}
|
||||
if (run_test_vector(&test_vector_2)) {
|
||||
passed++;
|
||||
}
|
||||
if (run_test_vector(&test_vector_3)) {
|
||||
passed++;
|
||||
}
|
||||
if (run_test_vector(&test_vector_4)) {
|
||||
passed++;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "\n");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, " Test Results: %d/%d PASSED", passed, total);
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "\n");
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/*
|
||||
* NAN ND-PMK Test Vector Header
|
||||
*/
|
||||
|
||||
#ifndef NAN_PMK_TEST_H
|
||||
#define NAN_PMK_TEST_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Run NAN ND-PMK derivation test vectors
|
||||
*
|
||||
* Tests the PBKDF2 derivation against official Wi-Fi Aware Specification
|
||||
* test vectors (Appendix M.1)
|
||||
*/
|
||||
void nan_pmk_run_test_vectors(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NAN_PMK_TEST_H */
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
/*
|
||||
* NAN Crypto Test Main
|
||||
*
|
||||
* Test application for NAN ND-PMK derivation
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nan_pmk_test.h"
|
||||
|
||||
static const char *TAG = "nan_test";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* Initialize NVS */
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
/* Initialize Wi-Fi (needed for crypto funcs) */
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, " NAN ND-PMK Derivation Test");
|
||||
ESP_LOGI(TAG, "========================================\n");
|
||||
|
||||
/* Run test vectors */
|
||||
nan_pmk_run_test_vectors();
|
||||
|
||||
ESP_LOGI(TAG, "\n========================================");
|
||||
ESP_LOGI(TAG, " All tests completed");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
CONFIG_ESP_WIFI_NAN_SYNC_ENABLE=y
|
||||
@@ -30,10 +30,12 @@ extern "C" {
|
||||
#define NAN_MAX_PEERS_RECORD 15
|
||||
#define ESP_NAN_PUBLISH 2
|
||||
#define ESP_NAN_SUBSCRIBE 1
|
||||
#define NAN_IPV6_ADDR_ID_LEN 8
|
||||
#ifndef NAN_IPV6_IDENTIFIER_LEN
|
||||
#define NAN_IPV6_IDENTIFIER_LEN 8
|
||||
#endif
|
||||
|
||||
#define IS_ZERO_NAN_ADDR_ID(a) (!((a)[0] | (a)[1] | (a)[2] | (a)[3] | \
|
||||
(a)[4] | (a)[5] | (a)[6] | (a)[7]))
|
||||
#define IS_ZERO_NAN_IPV6_IDENTIFIER(a) (!((a)[0] | (a)[1] | (a)[2] | (a)[3] | \
|
||||
(a)[4] | (a)[5] | (a)[6] | (a)[7]))
|
||||
|
||||
#define ESP_NAN_SET_IPV6_LINKLOCAL_FROM_IDENTIFIER(_target_addr, _identifier) \
|
||||
do { \
|
||||
@@ -42,7 +44,7 @@ extern "C" {
|
||||
(_target_addr).u_addr.ip6.addr[1] = 0; \
|
||||
memcpy(&(_target_addr).u_addr.ip6.addr[2], \
|
||||
(_identifier), \
|
||||
NAN_IPV6_ADDR_ID_LEN); \
|
||||
NAN_IPV6_IDENTIFIER_LEN); \
|
||||
} while (0)
|
||||
|
||||
/** Parameters of a peer service record */
|
||||
@@ -85,7 +87,7 @@ esp_err_t esp_wifi_nan_sync_stop(void);
|
||||
*
|
||||
* @attention This API should be called by the Subscriber after a match occurs with a Publisher.
|
||||
*
|
||||
* @param req NAN Datapath Request parameters.
|
||||
* @param req NAN Datapath Request parameters
|
||||
*
|
||||
* @return
|
||||
* - non-zero NAN Datapath identifier: If NAN datapath req was accepted by publisher
|
||||
@@ -99,7 +101,7 @@ uint8_t esp_wifi_nan_datapath_req(wifi_nan_datapath_req_t *req);
|
||||
* @attention This API should be called if ndp_resp_needed is set 1 in wifi_nan_publish_cfg_t and
|
||||
* a WIFI_EVENT_NDP_INDICATION event is received due to an incoming NDP request.
|
||||
*
|
||||
* @param resp NAN Datapath Response parameters.
|
||||
* @param resp NAN Datapath Response parameters
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Internal declarations shared between nan_app.c and nan_security.c.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/queue.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_wifi_types_generic.h"
|
||||
#include "esp_private/wifi.h"
|
||||
#include "esp_nan.h"
|
||||
#include "os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macros */
|
||||
#ifndef MACADDR_LEN
|
||||
#define MACADDR_LEN 6
|
||||
#endif
|
||||
#define MACADDR_EQUAL(a1, a2) (memcmp(a1, a2, MACADDR_LEN) == 0)
|
||||
#define MACADDR_COPY(dst, src) (memcpy(dst, src, MACADDR_LEN))
|
||||
|
||||
/*
|
||||
* Shared lock used by both files.
|
||||
*
|
||||
* NAN_DATA_LOCK contract
|
||||
* ----------------------
|
||||
* s_nan_data_lock guards s_nan_ctx (NDL[], own_svc[], state, event,
|
||||
* netif). Anything that reads or mutates these fields takes the lock.
|
||||
*
|
||||
* !!! MUST NOT be held across any esp_nan_internal_* call !!!
|
||||
*
|
||||
* The blob-side esp_nan_internal_* entry points (datapath_req,
|
||||
* datapath_resp, datapath_end, publish_service, subscribe_service,
|
||||
* send_followup, register_callbacks) re-enter host code from the WiFi
|
||||
* task to:
|
||||
* - assemble M1 / M2 / M3 / M4 NDP frames (esp_nan_get_ndp_*_key_desc,
|
||||
* esp_nan_construct_csia / scia, esp_nan_capture_m1_auth_token,
|
||||
* esp_nan_update_ndp_*_mic, esp_nan_verify_ndp_*_mic)
|
||||
* - parse inbound NDP frames (esp_nan_parse_ndp_*)
|
||||
* - fire indication / confirm / response_indication / terminated
|
||||
* callbacks (nan_app_ndp_*_cb)
|
||||
*
|
||||
* All of those re-entry points take NAN_DATA_LOCK themselves. Holding
|
||||
* the lock around the blob call deadlocks the WiFi task as soon as it
|
||||
* tries to call back. Pattern:
|
||||
*
|
||||
* NAN_DATA_LOCK();
|
||||
* ... mutate / capture state needed by the call ...
|
||||
* NAN_DATA_UNLOCK();
|
||||
* err = esp_nan_internal_datapath_req(...);
|
||||
* NAN_DATA_LOCK();
|
||||
* ... record result ...
|
||||
* NAN_DATA_UNLOCK();
|
||||
*
|
||||
* Several past bug-fix commits on this branch (`fix(nan): release
|
||||
* NAN_DATA_LOCK before initiator datapath_req`, `fix(nan): unlock
|
||||
* NAN_DATA on all paths in ndp_indication_cb`) trace back to forgotten
|
||||
* unlocks; new sites that call the blob must follow this pattern.
|
||||
*/
|
||||
extern void *s_nan_data_lock;
|
||||
#define NAN_DATA_LOCK() os_mutex_lock(s_nan_data_lock)
|
||||
#define NAN_DATA_UNLOCK() os_mutex_unlock(s_nan_data_lock)
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
/* NAN 4-way handshake constants (RSNA key descriptor layout) */
|
||||
#define NAN_NONCE_LEN 32
|
||||
#define NAN_REPLAY_COUNTER_LEN 8
|
||||
#define NAN_KEY_RSC_LEN 8
|
||||
#define NAN_KEY_MIC_LEN 16
|
||||
/* KCK/KEK/TK buffer sizes are sized for the largest cipher suite the host
|
||||
* could potentially run (NCS-SK-256 KCK=24, KEK=32, TK=32). Only NCS-SK-128
|
||||
* is wired through M1–M4 today (see nan_get_first_csid) so the *_set fields
|
||||
* mark the live length in the buffer. */
|
||||
#define NAN_ND_KCK_MAX_LEN 24
|
||||
#define NAN_ND_KEK_MAX_LEN 32
|
||||
#define NAN_ND_TK_MAX_LEN 32
|
||||
#define NAN_GTK_MAX_LEN 32
|
||||
#define NAN_AUTH_TOKEN_MAX_LEN 24
|
||||
|
||||
/* RSNA Key Descriptor offsets (same as 802.11 EAPOL-Key) */
|
||||
#define NAN_KEY_DESC_TYPE_OFF 0
|
||||
#define NAN_KEY_DESC_KEY_INFO_OFF 1
|
||||
#define NAN_KEY_DESC_KEY_LEN_OFF 3
|
||||
#define NAN_KEY_DESC_REPLAY_OFF 5
|
||||
#define NAN_KEY_DESC_NONCE_OFF 13
|
||||
#define NAN_KEY_DESC_IV_OFF 45
|
||||
#define NAN_KEY_DESC_RSC_OFF 61
|
||||
#define NAN_KEY_DESC_KEY_ID_OFF 69
|
||||
#define NAN_KEY_DESC_MIC_OFF 77
|
||||
#define NAN_KEY_DESC_DATA_LEN_OFF 93
|
||||
#define NAN_KEY_DESC_DATA_OFF 95
|
||||
#define NAN_KEY_DESC_MIN_LEN 95
|
||||
|
||||
/* Key Descriptor Type (same as 802.11 EAPOL-Key) */
|
||||
#define NAN_KEY_DESC_TYPE_RSN 2
|
||||
|
||||
/* Security Context Identifier (SCID) types (Table 123) */
|
||||
#define NAN_SEC_CTX_TYPE_ND_PMKID 1
|
||||
|
||||
/* Key Info bits (same semantics as RSNA) */
|
||||
#define NAN_KEY_INFO_MIC BIT(8)
|
||||
#define NAN_KEY_INFO_SECURE BIT(9)
|
||||
#define NAN_KEY_INFO_INSTALL BIT(6)
|
||||
#define NAN_KEY_INFO_ACK BIT(7)
|
||||
#define NAN_KEY_INFO_ENC_KEY BIT(12)
|
||||
#define NAN_KEY_INFO_KEY_TYPE BIT(3) /* 1=Pairwise, 0=Group */
|
||||
|
||||
/* NCS-SK-128 only for now (Table 21): KCK 128 bits, KEK 128 bits, TK 128 bits, MIC 16 bytes */
|
||||
#define NAN_NCS_SK_128_KCK_LEN 16
|
||||
#define NAN_NCS_SK_128_KEK_LEN 16
|
||||
#define NAN_NCS_SK_128_TK_LEN 16
|
||||
#define NAN_NCS_SK_128_MIC_LEN 16
|
||||
#define NAN_NCS_SK_128_PTK_LEN (NAN_NCS_SK_128_KCK_LEN + NAN_NCS_SK_128_KEK_LEN + NAN_NCS_SK_128_TK_LEN)
|
||||
|
||||
/* Internal key-install constants matching esp_wifi_set_sta_key_internal semantics. */
|
||||
#define NAN_WIFI_WPA_ALG_CCMP 3
|
||||
#define NAN_KEY_FLAG_RX BIT(2)
|
||||
#define NAN_KEY_FLAG_TX BIT(3)
|
||||
#define NAN_KEY_FLAG_PAIRWISE BIT(5)
|
||||
|
||||
/* Handshake state */
|
||||
enum nan_handshake_state {
|
||||
NAN_HANDSHAKE_IDLE = 0,
|
||||
NAN_HANDSHAKE_M1_SENT, /* Initiator: sent NDP Request (M1) */
|
||||
NAN_HANDSHAKE_M1_RCVD,
|
||||
NAN_HANDSHAKE_M2_SENT,
|
||||
NAN_HANDSHAKE_M2_RCVD,
|
||||
NAN_HANDSHAKE_M3_SENT,
|
||||
NAN_HANDSHAKE_M3_PENDING_VERIFY, /* Responder: M3 parsed, awaits Auth_Token||body MIC verify */
|
||||
NAN_HANDSHAKE_M3_RCVD,
|
||||
NAN_HANDSHAKE_M4_RCVD,
|
||||
NAN_HANDSHAKE_COMPLETE
|
||||
};
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_SECURITY */
|
||||
|
||||
/* Per-peer service info */
|
||||
struct peer_svc_info {
|
||||
SLIST_ENTRY(peer_svc_info) next;
|
||||
uint8_t peer_svc_info[ESP_WIFI_MAX_SVC_INFO_LEN];
|
||||
uint8_t svc_id;
|
||||
uint8_t own_svc_id;
|
||||
uint8_t type;
|
||||
uint8_t peer_nmi[MACADDR_LEN];
|
||||
uint32_t device_caps;
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
/* Per-(own_svc, peer) result of subscriber-side PMKID match at SDF RX.
|
||||
* 0xFF = no match; otherwise the index into own_svc->user_cfg.creds[]
|
||||
* whose ND-PMKID matched the publisher SCIA. The initiator NDP-req path
|
||||
* uses this to pick the right credential for M1's pair-PMKID. */
|
||||
uint8_t matched_cred_idx;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Own (locally registered) service info */
|
||||
struct own_svc_info {
|
||||
char svc_name[ESP_WIFI_MAX_SVC_NAME_LEN];
|
||||
uint8_t svc_id;
|
||||
uint8_t type;
|
||||
|
||||
bool ndp_resp_needed;
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
/* App-provided input (creds[] / csid_bitmap / group prot flags). */
|
||||
wifi_nan_discovery_security_params_t user_cfg;
|
||||
/* Derived material — one ND-PMK + ND-PMKID per credential. Mirrors the
|
||||
* 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];
|
||||
#endif
|
||||
uint8_t num_peer_records;
|
||||
SLIST_HEAD(peer_list_t, peer_svc_info) peer_list;
|
||||
};
|
||||
|
||||
/* Per-NDP link state */
|
||||
struct ndl_info {
|
||||
uint8_t ndp_id;
|
||||
uint8_t peer_ndi[MACADDR_LEN];
|
||||
uint8_t peer_nmi[MACADDR_LEN];
|
||||
uint8_t publisher_id;
|
||||
uint8_t own_role;
|
||||
uint32_t device_caps;
|
||||
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
|
||||
wifi_nan_security_params_t security_ctx;
|
||||
|
||||
uint8_t anonce[NAN_NONCE_LEN];
|
||||
uint8_t snonce[NAN_NONCE_LEN];
|
||||
|
||||
uint8_t nd_kck[NAN_ND_KCK_MAX_LEN];
|
||||
uint8_t nd_kek[NAN_ND_KEK_MAX_LEN];
|
||||
uint8_t nd_tk[NAN_ND_TK_MAX_LEN];
|
||||
uint8_t kck_len;
|
||||
uint8_t kek_len;
|
||||
uint8_t tk_len;
|
||||
uint8_t ptk_set: 1;
|
||||
uint8_t ptk_reserved: 7;
|
||||
|
||||
uint8_t tx_replay_counter[NAN_REPLAY_COUNTER_LEN];
|
||||
uint8_t rx_replay_counter[NAN_REPLAY_COUNTER_LEN];
|
||||
uint8_t rx_replay_counter_set: 1;
|
||||
uint8_t replay_reserved: 7;
|
||||
|
||||
uint8_t auth_token[NAN_AUTH_TOKEN_MAX_LEN];
|
||||
uint8_t auth_token_len;
|
||||
|
||||
uint8_t handshake_state;
|
||||
|
||||
/* Group key state (unsupported -- pairwise-only M1-M4 flow today;
|
||||
* fields kept to match the spec-defined RSNA key descriptor layout
|
||||
* and stay forward-compatible). */
|
||||
uint8_t gtk[NAN_GTK_MAX_LEN];
|
||||
uint8_t igtk[NAN_GTK_MAX_LEN];
|
||||
uint8_t bigtk[NAN_GTK_MAX_LEN];
|
||||
uint8_t gtk_len;
|
||||
uint8_t igtk_len;
|
||||
uint8_t bigtk_len;
|
||||
uint8_t gtk_set: 1;
|
||||
uint8_t igtk_set: 1;
|
||||
uint8_t bigtk_set: 1;
|
||||
uint8_t group_keys_reserved: 5;
|
||||
|
||||
uint8_t key_rsc[NAN_KEY_RSC_LEN];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* NAN context shared between files */
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t event;
|
||||
struct ndl_info ndl[ESP_WIFI_NAN_DATAPATH_MAX_PEERS];
|
||||
struct own_svc_info own_svc[ESP_WIFI_NAN_MAX_SVC_SUPPORTED];
|
||||
esp_netif_t *nan_netif;
|
||||
} nan_ctx_t;
|
||||
|
||||
extern nan_ctx_t s_nan_ctx;
|
||||
|
||||
/* Helpers defined in nan_app.c, used by nan_security.c */
|
||||
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_SECURITY
|
||||
/* Security-gated (defined in nan_security.c) */
|
||||
uint32_t esp_nan_get_csia_len(uint16_t own_csid_bitmap, uint16_t peer_csid_bitmap);
|
||||
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);
|
||||
|
||||
int esp_nan_construct_csia(uint8_t *frm, uint8_t pub_id,
|
||||
uint16_t own_csid_bitmap, uint16_t peer_csid_bitmap);
|
||||
int esp_nan_construct_scia_publish(uint8_t *frm, uint8_t pub_id,
|
||||
uint8_t num_pmkids,
|
||||
const uint8_t pmkids[][ESP_WIFI_NAN_NDP_PMKID_LEN]);
|
||||
int esp_nan_construct_scia_ndp_req(uint8_t *frm, uint8_t ndp_id,
|
||||
const uint8_t *peer_nmi);
|
||||
int esp_nan_construct_scia_ndp_resp(uint8_t *frm, uint8_t ndp_id,
|
||||
const uint8_t *peer_nmi);
|
||||
|
||||
int esp_nan_get_ndp_req_shared_key_desc(uint8_t *buf, size_t buf_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
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);
|
||||
int esp_nan_get_ndp_confirm_shared_key_desc(uint8_t *buf, size_t buf_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
int esp_nan_get_ndp_security_install_key_desc(uint8_t *buf, size_t buf_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
int esp_nan_capture_m1_auth_token(const uint8_t *m1_body, size_t body_len,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
int esp_nan_update_ndp_resp_mic(uint8_t *m2_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
int esp_nan_update_ndp_confirm_mic(uint8_t *m3_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
int esp_nan_update_ndp_security_install_mic(uint8_t *m4_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
int esp_nan_verify_ndp_resp_mic(uint8_t *m2_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
int esp_nan_verify_ndp_confirm_mic(uint8_t *m3_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
int esp_nan_verify_ndp_security_install_mic(uint8_t *m4_body, size_t body_len,
|
||||
uint8_t *key_desc_attr,
|
||||
uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
void esp_nan_parse_ndp_csia(void *frm, size_t buf_len, wifi_nan_security_params_t *param);
|
||||
void esp_nan_parse_ndp_scia(void *frm, size_t buf_len, wifi_nan_security_params_t *param);
|
||||
void esp_nan_parse_ndp_key_desc(void *frm, size_t buf_len, uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
esp_err_t esp_nan_parse_publish_security(const uint8_t *attrs, size_t attrs_len,
|
||||
wifi_nan_peer_sdf_security_t *security);
|
||||
|
||||
/* Helpers defined in nan_security.c, used by nan_app.c */
|
||||
|
||||
/*
|
||||
* Apply any pending CSIA/SCIA/M1 state captured by the NDP key-desc parser
|
||||
* onto the freshly-created NDL. Called from nan_app_ndp_indication_cb once
|
||||
* (ndp_id, peer_nmi, peer_ndi, p_own_svc) are all known.
|
||||
*/
|
||||
void nan_security_apply_pending(struct ndl_info *ndl,
|
||||
struct own_svc_info *p_own_svc,
|
||||
uint8_t pub_id,
|
||||
const uint8_t *peer_nmi,
|
||||
const uint8_t *peer_ndi);
|
||||
|
||||
/* PMK / PMKID derivation entry point used by the publish path. Derives from
|
||||
* (service_name, sec_cfg) (passphrase or PMK) and writes the result into
|
||||
* out_derived. */
|
||||
esp_err_t nan_derive_security_params(const char *service_name,
|
||||
const wifi_nan_discovery_security_params_t *sec_cfg,
|
||||
wifi_nan_security_params_t *out_derived);
|
||||
|
||||
/* Blob-side gate query: returns ndl->security_ctx.csid_bitmap for the NDP
|
||||
* keyed on (ndp_id, peer_nmi), or 0 if no NDL match. ndp_id=0 is valid for
|
||||
* the initiator pre-claim window (peer-only lookup). */
|
||||
uint16_t nan_get_ndp_security_csid(uint8_t ndp_id, const uint8_t *peer_nmi);
|
||||
|
||||
/* Subscribe path: populate the initiator NDL's security_ctx (cipher + pair-PMKID +
|
||||
* ND-PMK) from the local subscribe's own_svc and the SDF-time matched credential
|
||||
* recorded on peer_svc. The blob's CSIA / SCIA / Shared-Key-Descriptor builder
|
||||
* callbacks look up security keyed by (ndp_id, peer_nmi). No-op if the local
|
||||
* subscribe didn't request encrypted datapath. */
|
||||
esp_err_t nan_security_populate_initiator_ndl(struct ndl_info *ndl,
|
||||
const struct own_svc_info *own_svc,
|
||||
const struct peer_svc_info *peer_svc,
|
||||
const uint8_t *peer_nmi);
|
||||
|
||||
/*
|
||||
* Compare locally derived ND-PMKID (subscriber passphrase, publisher NMI) to
|
||||
* peer discovery security params. own_svc identifies the local subscribe
|
||||
* (service_name + creds[]) and peer_svc is updated with matched_cred_idx on
|
||||
* success. Returns true if any local cred's PMKID matches a peer-advertised one.
|
||||
*/
|
||||
bool nan_security_service_match(const struct own_svc_info *own_svc,
|
||||
struct peer_svc_info *peer_svc,
|
||||
const uint8_t *publisher_nmi,
|
||||
const wifi_nan_peer_sdf_security_t *peer_sec);
|
||||
#else
|
||||
static inline esp_err_t nan_derive_security_params(const char *service_name,
|
||||
const wifi_nan_discovery_security_params_t *sec_cfg,
|
||||
wifi_nan_security_params_t *out_derived)
|
||||
{
|
||||
(void)service_name;
|
||||
(void)sec_cfg;
|
||||
(void)out_derived;
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* CONFIG_ESP_WIFI_NAN_SECURITY */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1117,6 +1117,30 @@ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
|
||||
}
|
||||
#endif /* defined(CONFIG_MBEDTLS_SHA1_C) || defined(CONFIG_MBEDTLS_HARDWARE_SHA) */
|
||||
|
||||
#if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_MD_C)
|
||||
#include "mbedtls/private/pkcs5.h"
|
||||
|
||||
#if defined(MBEDTLS_SHA256_C)
|
||||
int pbkdf2_sha256(const char *passphrase, const u8 *salt, size_t salt_len,
|
||||
int iterations, u8 *buf, size_t buflen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!passphrase || !salt || !buf || !salt_len || !buflen || iterations <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA256,
|
||||
(const u8 *) passphrase,
|
||||
os_strlen(passphrase),
|
||||
salt, salt_len,
|
||||
(unsigned int) iterations, (uint32_t) buflen, buf);
|
||||
return ret == 0 ? 0 : -1;
|
||||
}
|
||||
#endif /* MBEDTLS_SHA256_C */
|
||||
|
||||
#endif /* MBEDTLS_PKCS5_C && MBEDTLS_MD_C */
|
||||
|
||||
#ifdef MBEDTLS_DES_C
|
||||
int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
||||
{
|
||||
|
||||
@@ -26,5 +26,7 @@ int tls_prf_sha256(const u8 *secret, size_t secret_len,
|
||||
int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
|
||||
const char *label, const u8 *seed, size_t seed_len,
|
||||
u8 *out, size_t outlen);
|
||||
int pbkdf2_sha256(const char *passphrase, const u8 *salt, size_t salt_len,
|
||||
int iterations, u8 *buf, size_t buflen);
|
||||
|
||||
#endif /* SHA256_H */
|
||||
|
||||
Reference in New Issue
Block a user