feat(nan): Add aes_wrap/unwrap crypto callbacks

- Use crypto callbacks instead of calling internal API's
- Clean up of unused code, flags. Re-arrange functions
This commit is contained in:
Nachiket Kukade
2026-06-23 22:08:06 +05:30
committed by Akshat Agrawal
parent c4b1e06057
commit d36416980c
7 changed files with 64 additions and 111 deletions
@@ -78,26 +78,26 @@ typedef int (*esp_aes_128_encrypt_t)(const unsigned char *key, const unsigned ch
typedef int (*esp_aes_128_decrypt_t)(const unsigned char *key, const unsigned char *iv, unsigned char *data, int data_len);
/**
* @brief The AES wrap callback function used by esp_wifi.
* @brief The AES key wrap (RFC 3394) callback function used by esp_wifi.
*
* @param kek 16-octet Key encryption key (KEK).
* @param kek Key encryption key (KEK).
* @param kek_len Length of the KEK in bytes.
* @param n Length of the plaintext key in 64-bit units;
* @param plain Plaintext key to be wrapped, n * 64 bits
* @param cipher Wrapped key, (n + 1) * 64 bits
*
*/
typedef int (*esp_aes_wrap_t)(const unsigned char *kek, int n, const unsigned char *plain, unsigned char *cipher);
typedef int (*esp_aes_wrap_t)(const unsigned char *kek, size_t kek_len, int n, const unsigned char *plain, unsigned char *cipher);
/**
* @brief The AES unwrap callback function used by esp_wifi.
* @brief The AES key unwrap (RFC 3394) callback function used by esp_wifi.
*
* @param kek 16-octet Key decryption key (KEK).
* @param kek Key encryption key (KEK).
* @param kek_len Length of the KEK in bytes.
* @param n Length of the plaintext key in 64-bit units;
* @param cipher Wrapped key to be unwrapped, (n + 1) * 64 bits
* @param plain Plaintext key, n * 64 bits
*
*/
typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, int n, const unsigned char *cipher, unsigned char *plain);
typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, size_t kek_len, int n, const unsigned char *cipher, unsigned char *plain);
/**
* @brief The SHA256 callback function used by esp_wifi.
@@ -404,6 +404,8 @@ typedef struct wpa_crypto_funcs_t {
esp_ccmp_encrypt_t ccmp_encrypt; /**< Encrypt data callback function using CCMP */
esp_aes_gmac_t aes_gmac; /**< One-Key GMAC hash callback function with AES for MIC computation */
esp_sha256_vector_t sha256_vector; /**< SHA256 hash callback function for data vector */
esp_aes_wrap_t aes_wrap; /**< The AES key wrap (RFC 3394) callback function used by esp_wifi */
esp_aes_unwrap_t aes_unwrap; /**< The AES key unwrap (RFC 3394) callback function used by esp_wifi */
} wpa_crypto_funcs_t;
/**
@@ -78,26 +78,28 @@ typedef int (*esp_aes_128_encrypt_t)(const unsigned char *key, const unsigned ch
typedef int (*esp_aes_128_decrypt_t)(const unsigned char *key, const unsigned char *iv, unsigned char *data, int data_len);
/**
* @brief The AES wrap callback function used by esp_wifi.
* @brief The AES key wrap (RFC 3394) callback function used by esp_wifi.
*
* @param kek 16-octet Key encryption key (KEK).
* @param kek Key encryption key (KEK).
* @param kek_len Length of the KEK in bytes.
* @param n Length of the plaintext key in 64-bit units;
* @param plain Plaintext key to be wrapped, n * 64 bits
* @param cipher Wrapped key, (n + 1) * 64 bits
*
* Returns: 0 on success, -1 on failure
*/
typedef int (*esp_aes_wrap_t)(const unsigned char *kek, int n, const unsigned char *plain, unsigned char *cipher);
typedef int (*esp_aes_wrap_t)(const unsigned char *kek, size_t kek_len, int n, const unsigned char *plain, unsigned char *cipher);
/**
* @brief The AES unwrap callback function used by esp_wifi.
* @brief The AES key unwrap (RFC 3394) callback function used by esp_wifi.
*
* @param kek 16-octet Key decryption key (KEK).
* @param kek Key encryption key (KEK).
* @param kek_len Length of the KEK in bytes.
* @param n Length of the plaintext key in 64-bit units;
* @param cipher Wrapped key to be unwrapped, (n + 1) * 64 bits
* @param plain Plaintext key, n * 64 bits
*
* Returns: 0 on success, -1 on failure
*/
typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, int n, const unsigned char *cipher, unsigned char *plain);
typedef int (*esp_aes_unwrap_t)(const unsigned char *kek, size_t kek_len, int n, const unsigned char *cipher, unsigned char *plain);
/**
* @brief The SHA256 callback function used by esp_wifi.
@@ -404,6 +406,8 @@ typedef struct wpa_crypto_funcs_t {
esp_ccmp_encrypt_t ccmp_encrypt; /**< Encrypt data callback function using CCMP */
esp_aes_gmac_t aes_gmac; /**< One-Key GMAC hash callback function with AES for MIC computation */
esp_sha256_vector_t sha256_vector; /**< SHA256 hash callback function for data vector */
esp_aes_wrap_t aes_wrap; /**< The AES key wrap (RFC 3394) callback function used by esp_wifi */
esp_aes_unwrap_t aes_unwrap; /**< The AES key unwrap (RFC 3394) callback function used by esp_wifi */
} wpa_crypto_funcs_t;
/**
@@ -24,30 +24,6 @@
#include "esp_private/esp_nan_usd.h"
#endif /* CONFIG_ESP_WIFI_NAN_USD_ENABLE */
bool esp_nan_ndp_info_present(void)
{
return true;
}
uint32_t esp_nan_ndp_get_info_len(void)
{
return 12;
}
int esp_nan_construct_ndp_info(uint8_t *frm)
{
static const uint8_t ndp_info_attr[] = {
0x01, 0x09, 0x00, 0x50, 0x6f, 0x9a, 0x02, 0x00, 0x02, 0x00, 0x05, 0x0d
};
if (!frm) {
return 0;
}
memcpy(frm, ndp_info_attr, sizeof(ndp_info_attr));
return sizeof(ndp_info_attr);
}
#if !CONFIG_ESP_WIFI_NAN_PAIRING
uint32_t esp_nan_get_nira_len(void)
{
@@ -774,7 +750,7 @@ void nan_app_post_event(int32_t event_id, void* event_data, size_t event_data_si
g_wifi_osi_funcs._event_post(WIFI_EVENT, event_id, event_data, event_data_size, OSI_FUNCS_TIME_BLOCKING);
}
void nan_app_service_match_cb(uint8_t sub_id, struct nan_cb_peer_info *peer_info,
static void nan_app_service_match_cb(uint8_t sub_id, struct nan_cb_peer_info *peer_info,
struct nan_cb_npba_t *npba)
{
if (!peer_info) {
@@ -886,7 +862,7 @@ void nan_app_service_match_cb(uint8_t sub_id, struct nan_cb_peer_info *peer_info
os_free(evt);
}
void nan_app_replied_cb(uint8_t pub_id, struct nan_cb_peer_info *peer_info)
static void nan_app_replied_cb(uint8_t pub_id, struct nan_cb_peer_info *peer_info)
{
if (!peer_info) {
return;
@@ -925,7 +901,7 @@ void nan_app_replied_cb(uint8_t pub_id, struct nan_cb_peer_info *peer_info)
os_free(evt);
}
void nan_app_receive_cb(uint8_t svc_id, struct nan_cb_peer_info *peer_info,
static void nan_app_receive_cb(uint8_t svc_id, struct nan_cb_peer_info *peer_info,
uint8_t *shared_key_attr, uint16_t shared_key_attr_buf_len,
struct nan_cb_npba_t *npba)
{
@@ -978,7 +954,7 @@ void nan_app_receive_cb(uint8_t svc_id, struct nan_cb_peer_info *peer_info,
os_free(evt);
}
void nan_app_ndp_indication_cb(uint8_t pub_id, struct ndp_cb_peer_info *peer_info, uint32_t device_caps)
static void nan_app_ndp_indication_cb(uint8_t pub_id, struct ndp_cb_peer_info *peer_info, uint32_t device_caps)
{
/*
* Responder-side NDP indication. Security parsers (CSIA/SCIA/
@@ -1109,7 +1085,7 @@ void nan_app_ndp_indication_cb(uint8_t pub_id, struct ndp_cb_peer_info *peer_inf
os_free(evt);
}
void nan_app_ndp_response_indication_cb(struct ndp_cb_peer_info *peer_info)
static void nan_app_ndp_response_indication_cb(struct ndp_cb_peer_info *peer_info)
{
if (!peer_info) {
return;
@@ -1159,7 +1135,7 @@ static void nan_ndp_confirm_teardown(const uint8_t peer_nmi[6], uint8_t ndp_id)
os_event_group_set_bits(nan_event_group, NDP_REJECTED);
}
void nan_app_ndp_confirm_cb(uint8_t status, struct ndp_cb_peer_info *peer_info,
static void nan_app_ndp_confirm_cb(uint8_t status, struct ndp_cb_peer_info *peer_info,
uint8_t own_ndi[6], uint8_t ipv6_identifier[8])
{
if (!peer_info) {
@@ -1296,7 +1272,7 @@ done:
return;
}
void nan_app_ndp_terminated_cb(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[6])
static void nan_app_ndp_terminated_cb(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[6])
{
NAN_DATA_LOCK();
if (s_nan_ctx.nan_netif && !nan_is_datapath_active()) {
@@ -1322,7 +1298,7 @@ void nan_app_ndp_terminated_cb(uint8_t reason, uint8_t ndp_id, uint8_t init_ndi[
os_event_group_set_bits(nan_event_group, NDP_TERMINATED);
}
void nan_action_txdone_cb(uint32_t context, bool tx_status)
static void nan_action_txdone_cb(uint32_t context, bool tx_status)
{
if (nan_event_group && s_fup_context == context) {
if (tx_status) {
@@ -1333,7 +1309,7 @@ void nan_action_txdone_cb(uint32_t context, bool tx_status)
}
}
void esp_nan_ndp_tx_done_cb(uint8_t ndp_id, const uint8_t *peer_nmi, uint8_t msg_type, bool tx_status)
static void esp_nan_ndp_tx_done_cb(uint8_t ndp_id, const uint8_t *peer_nmi, uint8_t msg_type, bool tx_status)
{
NAN_DATA_LOCK();
@@ -329,37 +329,6 @@ 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);
bool nan_compute_service_id(const char *service_name, uint8_t service_id[6]);
/* === nan_secure_dp_funcs initializer targets === */
/* Always-present (defined in nan_app.c) */
void esp_nan_ndp_tx_done_cb(uint8_t ndp_id, const uint8_t *peer_nmi,
uint8_t msg_type, bool tx_status);
#ifdef CONFIG_ESP_WIFI_NAN_PAIRING
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
void nan_app_post_event(int32_t event_id, void *event_data, size_t event_data_size);
struct peer_svc_info *nan_find_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[]);
EventGroupHandle_t nan_pairing_get_event_group(void);
uint32_t *nan_pairing_get_fup_context(void);
const uint8_t *nan_pairing_get_null_mac(void);
bool nan_pairing_validate_publish_bootstrapping(uint16_t bootstrapping_methods);
bool nan_pairing_validate_subscribe_bootstrapping(uint16_t bootstrapping_methods);
uint16_t nan_app_parse_npba_from_publish(const struct nan_cb_npba_t *npba);
void nan_app_bootstrap_indication(uint8_t peer_svc_id, uint8_t pub_id,
uint8_t peer_nmi[6], uint16_t selected_method);
void nan_app_bootstrap_completed(uint8_t status, uint8_t peer_svc_id, uint8_t sub_id,
uint8_t peer_nmi[6], uint16_t matched_method,
uint8_t reason_code);
bool nan_app_parse_npba_from_receive(uint8_t own_svc_id, uint8_t peer_svc_id,
uint8_t peer_nmi[6], const struct nan_cb_npba_t *npba);
void nan_pairing_cancel_svc_pending(struct own_svc_info *own);
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING */
#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);
@@ -465,13 +434,33 @@ bool nan_security_service_match(const struct own_svc_info *own_svc,
const wifi_nan_peer_sdf_security_t *peer_sec);
#endif /* CONFIG_ESP_WIFI_NAN_SECURITY */
#if CONFIG_ESP_WIFI_NAN_PAIRING
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
void nan_app_post_event(int32_t event_id, void *event_data, size_t event_data_size);
struct peer_svc_info *nan_find_peer_svc(uint8_t own_svc_id, uint8_t peer_svc_id, uint8_t peer_nmi[]);
EventGroupHandle_t nan_pairing_get_event_group(void);
uint32_t *nan_pairing_get_fup_context(void);
const uint8_t *nan_pairing_get_null_mac(void);
bool nan_pairing_validate_publish_bootstrapping(uint16_t bootstrapping_methods);
bool nan_pairing_validate_subscribe_bootstrapping(uint16_t bootstrapping_methods);
uint16_t nan_app_parse_npba_from_publish(const struct nan_cb_npba_t *npba);
void nan_app_bootstrap_indication(uint8_t peer_svc_id, uint8_t pub_id,
uint8_t peer_nmi[6], uint16_t selected_method);
void nan_app_bootstrap_completed(uint8_t status, uint8_t peer_svc_id, uint8_t sub_id,
uint8_t peer_nmi[6], uint16_t matched_method,
uint8_t reason_code);
bool nan_app_parse_npba_from_receive(uint8_t own_svc_id, uint8_t peer_svc_id,
uint8_t peer_nmi[6], const struct nan_cb_npba_t *npba);
void nan_pairing_cancel_svc_pending(struct own_svc_info *own);
void nan_app_receive_pairing_followup(uint8_t svc_id, uint8_t peer_svc_id,
const uint8_t *peer_mac,
const uint8_t *shared_key_attr,
size_t shared_key_attr_buf_len);
#endif
#ifdef CONFIG_ESP_WIFI_NAN_SECURITY
/*
* Paired-peer cache API. Called from nan_pairing.c after the PASN install
* callback fires; consumed by the NDP security layer to source ND-PMK + cipher
@@ -491,7 +480,7 @@ const struct nan_paired_peer *nan_app_find_paired_peer(const uint8_t *peer_nmi);
void nan_app_remove_paired_peer(const uint8_t *peer_nmi);
void nan_app_clear_paired_peers(void);
#endif /* CONFIG_ESP_WIFI_NAN_SECURITY */
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING */
#ifdef __cplusplus
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -23,10 +23,8 @@
#include "utils/common.h"
#include "utils/eloop.h"
#if defined(CONFIG_ESP_WIFI_PASN_SUPPORT)
#include "esp_private/esp_supp_nan.h"
#include "apps_private/wifi_apps_private.h"
#endif
static const char *TAG = "nan_pairing";
@@ -35,7 +33,6 @@ static const char *TAG = "nan_pairing";
* Shared Key Descriptor (Wi-Fi Aware v4.0 §7.6.4.2). */
#define NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC 86400U
#if defined(CONFIG_ESP_WIFI_PASN_SUPPORT)
struct nan_pasn_data *esp_nan_app_get_pasn_data(void)
{
return s_nan_ctx.nan_pasn_data;
@@ -52,7 +49,6 @@ static void nan_pairing_key_installed_cb(const uint8_t *peer_nmi,
const uint8_t *nd_pmk,
size_t nd_pmk_len,
uint32_t nik_lifetime_sec);
#endif
bool nan_pairing_validate_publish_bootstrapping(uint16_t bootstrapping_methods)
{
@@ -254,7 +250,6 @@ esp_err_t esp_wifi_nan_pairing_start(wifi_nan_pairing_config_t *cfg)
return ESP_ERR_INVALID_ARG;
}
#if defined(CONFIG_ESP_WIFI_PASN_SUPPORT)
if (cfg->cred.pincode != UINT32_MAX &&
cfg->cred.pincode > NAN_PAIRING_PINCODE_MAX) {
ESP_LOGE(TAG, "Invalid pincode %u (valid range %u..%u or UINT32_MAX for default)",
@@ -288,10 +283,6 @@ esp_err_t esp_wifi_nan_pairing_start(wifi_nan_pairing_config_t *cfg)
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
#else
ESP_LOGE(TAG, "NAN PASN support not enabled");
return ESP_ERR_NOT_SUPPORTED;
#endif
}
/* NIRA: ID(1) + Len(2) + CipherVersion(1) + Nonce(8) + Tag(8) = 20 */
@@ -407,10 +398,6 @@ int esp_nan_construct_nira(uint8_t *frm)
return (int)(p - frm);
}
#if defined(CONFIG_ESP_WIFI_NAN_PAIRING) && defined(CONFIG_ESP_WIFI_PASN_SUPPORT) && defined(CONFIG_ESP_WIFI_NAN_SECURITY)
#include "crypto/sha256.h"
#include "crypto/aes_wrap.h"
#include "common/ieee802_11_defs.h"
#include "common/wpa_common.h"
@@ -507,9 +494,7 @@ static void nan_pairing_nik_fup_timeout_cb(void *eloop_data, void *user_ctx)
evt.status = WIFI_NAN_PAIRING_STATUS_ACCEPTED;
evt.reason_code = WIFI_NAN_PAIRING_REASON_NIK_FUP_TIMEOUT;
MACADDR_COPY(evt.peer_nmi, own->nik_fup_pending_peer_nmi);
#if defined(CONFIG_ESP_WIFI_NAN_SECURITY)
nan_app_remove_paired_peer(own->nik_fup_pending_peer_nmi);
#endif
struct peer_svc_info *peer = nan_find_peer_svc(own->svc_id, 0,
own->nik_fup_pending_peer_nmi);
esp_nan_complete_pairing(own->svc_id, peer ? peer->svc_id : 0);
@@ -689,7 +674,11 @@ static esp_err_t nan_app_send_pairing_followup(uint8_t svc_id, uint8_t peer_svc_
return ESP_ERR_INVALID_SIZE;
}
wrapped_len = plain_len + 8;
if (aes_wrap(saved->kek, saved->kek_len, plain_len / 8, plain, wrapped) != 0) {
if (!g_wifi_default_wpa_crypto_funcs.aes_wrap) {
ESP_LOGE(TAG, "Pairing follow-up: aes_wrap not registered");
return ESP_FAIL;
}
if (g_wifi_default_wpa_crypto_funcs.aes_wrap(saved->kek, saved->kek_len, plain_len / 8, plain, wrapped) != 0) {
return ESP_FAIL;
}
@@ -778,7 +767,6 @@ static void nan_pairing_key_installed_cb(const uint8_t *peer_nmi,
return;
}
#if defined(CONFIG_ESP_WIFI_NAN_SECURITY)
uint32_t lifetime_sec = nik_lifetime_sec ?
nik_lifetime_sec : NAN_PAIRING_DEFAULT_NIK_LIFETIME_SEC;
@@ -793,12 +781,6 @@ static void nan_pairing_key_installed_cb(const uint8_t *peer_nmi,
"paired-peer cache not updated",
MAC2STR(peer_nmi), ndp_csid, (unsigned)nd_pmk_len);
}
#else
(void)ndp_csid;
(void)nd_pmk;
(void)nd_pmk_len;
(void)nik_lifetime_sec;
#endif
struct peer_svc_info *peer = nan_find_peer_svc(0, 0, (uint8_t *)peer_nmi);
struct own_svc_info *own = NULL;
@@ -1081,6 +1063,4 @@ bool esp_nan_verify_nira(uint8_t *peer_mac, uint8_t *nira_attr, uint16_t nira_at
return match;
}
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING && CONFIG_ESP_WIFI_PASN_SUPPORT && CONFIG_ESP_WIFI_NAN_SECURITY */
#endif /* CONFIG_ESP_WIFI_NAN_PAIRING */
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -45,6 +45,8 @@ const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = {
.ccmp_encrypt = (esp_ccmp_encrypt_t)ccmp_encrypt,
.aes_gmac = (esp_aes_gmac_t)esp_aes_gmac,
.sha256_vector = (esp_sha256_vector_t)sha256_vector,
.aes_wrap = (esp_aes_wrap_t)aes_wrap,
.aes_unwrap = (esp_aes_unwrap_t)aes_unwrap,
};
const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs = {