summaryrefslogtreecommitdiff
path: root/lib/bt/common
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bt/common')
-rw-r--r--lib/bt/common/Kconfig.in134
-rw-r--r--lib/bt/common/ble_log/ble_log_spi_out.c1247
-rw-r--r--lib/bt/common/ble_log/include/ble_log/ble_log_spi_out.h64
-rw-r--r--lib/bt/common/btc/core/btc_manage.c20
-rw-r--r--lib/bt/common/btc/core/btc_task.c89
-rw-r--r--lib/bt/common/btc/include/btc/btc_task.h18
-rw-r--r--lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c37
-rw-r--r--lib/bt/common/btc/profile/esp/blufi/blufi_prf.c24
-rw-r--r--lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h2
-rw-r--r--lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h1
-rw-r--r--lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c75
-rw-r--r--lib/bt/common/hci_log/bt_hci_log.c15
-rw-r--r--lib/bt/common/hci_log/include/hci_log/bt_hci_log.h1
-rw-r--r--lib/bt/common/include/bt_common.h30
-rw-r--r--lib/bt/common/include/bt_user_config.h31
-rw-r--r--lib/bt/common/osi/allocator.c48
-rw-r--r--lib/bt/common/osi/include/osi/allocator.h49
-rw-r--r--lib/bt/common/osi/include/osi/fixed_pkt_queue.h4
-rw-r--r--lib/bt/common/osi/include/osi/hash_map.h1
-rw-r--r--lib/bt/common/osi/pkt_queue.c1
-rw-r--r--lib/bt/common/osi/thread.c4
-rw-r--r--lib/bt/common/tinycrypt/AUTHORS15
-rw-r--r--lib/bt/common/tinycrypt/LICENSE61
-rw-r--r--lib/bt/common/tinycrypt/README70
-rw-r--r--lib/bt/common/tinycrypt/VERSION1
-rw-r--r--lib/bt/common/tinycrypt/documentation/tinycrypt.rst352
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/aes.h134
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/cbc_mode.h155
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/ccm_mode.h215
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/cmac_mode.h198
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/constants.h65
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/ctr_mode.h112
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/ctr_prng.h172
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/ecc.h551
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h135
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/ecc_dsa.h145
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/ecc_platform_specific.h85
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/hmac.h143
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/hmac_prng.h168
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/sha256.h135
-rw-r--r--lib/bt/common/tinycrypt/include/tinycrypt/utils.h101
-rw-r--r--lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c87
-rw-r--r--lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h15
-rw-r--r--lib/bt/common/tinycrypt/src/aes_decrypt.c170
-rw-r--r--lib/bt/common/tinycrypt/src/aes_encrypt.c197
-rw-r--r--lib/bt/common/tinycrypt/src/cbc_mode.c118
-rw-r--r--lib/bt/common/tinycrypt/src/ccm_mode.c272
-rw-r--r--lib/bt/common/tinycrypt/src/cmac_mode.c258
-rw-r--r--lib/bt/common/tinycrypt/src/ctr_mode.c91
-rw-r--r--lib/bt/common/tinycrypt/src/ctr_prng.c283
-rw-r--r--lib/bt/common/tinycrypt/src/ecc.c972
-rw-r--r--lib/bt/common/tinycrypt/src/ecc_dh.c204
-rw-r--r--lib/bt/common/tinycrypt/src/ecc_dsa.c298
-rw-r--r--lib/bt/common/tinycrypt/src/ecc_platform_specific.c110
-rw-r--r--lib/bt/common/tinycrypt/src/hmac.c152
-rw-r--r--lib/bt/common/tinycrypt/src/hmac_prng.c218
-rw-r--r--lib/bt/common/tinycrypt/src/sha256.c221
-rw-r--r--lib/bt/common/tinycrypt/src/utils.c80
58 files changed, 8524 insertions, 130 deletions
diff --git a/lib/bt/common/Kconfig.in b/lib/bt/common/Kconfig.in
index 6b19dd8e..ff1947a3 100644
--- a/lib/bt/common/Kconfig.in
+++ b/lib/bt/common/Kconfig.in
@@ -1,6 +1,140 @@
config BT_ALARM_MAX_NUM
int "Maximum number of Bluetooth alarms"
default 50
+ depends on (BT_BLUEDROID_ENABLED || BT_NIMBLE_ENABLED)
help
This option decides the maximum number of alarms which
could be used by Bluetooth host.
+
+config BT_BLE_LOG_SPI_OUT_ENABLED
+ bool "Output ble logs to SPI bus (Experimental)"
+ default n
+ help
+ Output ble logs to SPI bus
+
+config BT_BLE_LOG_SPI_OUT_UL_TASK_BUF_SIZE
+ int "SPI transaction buffer size for upper layer task logs"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default 512
+ help
+ SPI transaction buffer size for upper layer task logs.
+ There will be 2 SPI DMA buffers with the same size.
+
+config BT_BLE_LOG_SPI_OUT_HCI_ENABLED
+ bool "Enable HCI log output to SPI"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default n
+ help
+ Enable logging of HCI packets to the SPI bus when BLE SPI log output is enabled.
+
+config BT_BLE_LOG_SPI_OUT_HOST_ENABLED
+ bool "Enable Host log output to SPI"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default n
+ help
+ This configuration applies to the logs of both Bluedroid Host and NimBLE Host.
+ When BLE SPI log output is enabled, this option allows host logs to be transmitted via SPI.
+
+config BT_BLE_LOG_SPI_OUT_LL_ENABLED
+ bool "Enable Controller log output to SPI"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED
+ default n
+ help
+ Enable controller log output to SPI bus.
+
+config BT_BLE_LOG_SPI_OUT_LL_TASK_BUF_SIZE
+ int "SPI transaction buffer size for lower layer task logs"
+ depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED
+ default 1024
+ help
+ SPI transaction buffer size for lower layer task logs.
+ There will be 2 SPI DMA buffers with the same size.
+
+config BT_BLE_LOG_SPI_OUT_LL_ISR_BUF_SIZE
+ int "SPI transaction buffer size for lower layer ISR logs"
+ depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED
+ default 512
+ help
+ SPI transaction buffer size for lower layer ISR logs.
+ There will be 2 SPI DMA buffers with the same size.
+
+config BT_BLE_LOG_SPI_OUT_LL_HCI_BUF_SIZE
+ int "SPI transaction buffer size for lower layer HCI logs"
+ depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED
+ default 512
+ help
+ SPI transaction buffer size for upper layer HCI logs.
+ There will be 2 SPI DMA buffers with the same size
+
+config BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM
+ int "GPIO number of SPI MOSI"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default 0
+ help
+ GPIO number of SPI MOSI
+
+config BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM
+ int "GPIO number of SPI SCLK"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default 1
+ help
+ GPIO number of SPI SCLK
+
+config BT_BLE_LOG_SPI_OUT_CS_IO_NUM
+ int "GPIO number of SPI CS"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default 2
+ help
+ GPIO number of SPI CS
+
+config BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
+ bool "Enable ble log & logic analyzer log time sync"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default y
+ help
+ Enable ble log & logic analyzer log time sync
+
+config BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM
+ int "GPIO number of SYNC IO"
+ depends on BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
+ default 3
+ help
+ GPIO number of SYNC IO
+
+config BT_BLE_LOG_SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ bool "Enable ble log & logic analyzer log time sync sleep support"
+ depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED
+ default n
+ help
+ Enable ble log & logic analyzer log time sync sleep support
+
+config BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED
+ bool "Enable periodic buffer flush out"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default n
+ help
+ Enable periodic buffer flush out
+ Not recommended when SPI receiver is unavailable
+
+config BT_BLE_LOG_SPI_OUT_FLUSH_TIMEOUT
+ int "Buffer flush out period in unit of ms"
+ depends on BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED
+ default 1000
+ help
+ Buffer flush out period in unit of ms
+
+config BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
+ bool "Enable LE Audio log output to SPI"
+ depends on BT_BLE_LOG_SPI_OUT_ENABLED
+ default n
+ help
+ Enable LE Audio log output to SPI
+
+config BT_BLE_LOG_SPI_OUT_LE_AUDIO_BUF_SIZE
+ int "SPI transaction buffer size for LE Audio logs"
+ depends on BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
+ default 1024
+ help
+ SPI transaction buffer size for LE Audio logs.
+ There will be 2 SPI DMA buffers with the same size.
diff --git a/lib/bt/common/ble_log/ble_log_spi_out.c b/lib/bt/common/ble_log/ble_log_spi_out.c
new file mode 100644
index 00000000..3ee7f511
--- /dev/null
+++ b/lib/bt/common/ble_log/ble_log_spi_out.c
@@ -0,0 +1,1247 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "ble_log/ble_log_spi_out.h"
+
+#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
+
+// Private includes
+#include "esp_bt.h"
+
+// sdkconfig defines
+#define SPI_OUT_UL_TASK_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_UL_TASK_BUF_SIZE
+#define SPI_OUT_LL_ENABLED CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED
+#define SPI_OUT_LL_TASK_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_LL_TASK_BUF_SIZE
+#define SPI_OUT_LL_ISR_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_LL_ISR_BUF_SIZE
+#define SPI_OUT_LL_HCI_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_LL_HCI_BUF_SIZE
+#define SPI_OUT_MOSI_IO_NUM CONFIG_BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM
+#define SPI_OUT_SCLK_IO_NUM CONFIG_BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM
+#define SPI_OUT_CS_IO_NUM CONFIG_BT_BLE_LOG_SPI_OUT_CS_IO_NUM
+#define SPI_OUT_TS_SYNC_ENABLED CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
+#define SPI_OUT_SYNC_IO_NUM CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM
+#define SPI_OUT_TS_SYNC_SLEEP_SUPPORT CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+#define SPI_OUT_FLUSH_TIMER_ENABLED CONFIG_BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED
+#define SPI_OUT_FLUSH_TIMEOUT_US (CONFIG_BT_BLE_LOG_SPI_OUT_FLUSH_TIMEOUT * 1000)
+#define SPI_OUT_LE_AUDIO_ENABLED CONFIG_BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
+#define SPI_OUT_LE_AUDIO_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_LE_AUDIO_BUF_SIZE
+
+// Private defines
+#define BLE_LOG_TAG "BLE_LOG"
+#define SPI_OUT_BUS SPI2_HOST
+#define SPI_OUT_MAX_TRANSFER_SIZE (10240)
+#define SPI_OUT_FRAME_HEAD_LEN (4)
+#define SPI_OUT_FRAME_TAIL_LEN (4)
+#define SPI_OUT_FRAME_OVERHEAD (8)
+#define SPI_OUT_PACKET_LOSS_FRAME_SIZE (6)
+#define SPI_OUT_TRANS_ITVL_MIN_US (30)
+#define SPI_OUT_UL_LOG_STR_BUF_SIZE (100)
+#define SPI_OUT_MALLOC(size) heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
+
+#if SPI_OUT_TS_SYNC_ENABLED
+#define SPI_OUT_TS_SYNC_TIMEOUT (1000 * 1000)
+#endif // SPI_OUT_TS_SYNC_ENABLED
+
+// Queue size defines
+#define SPI_OUT_PING_PONG_BUF_CNT (2)
+#define SPI_OUT_UL_QUEUE_SIZE (SPI_OUT_PING_PONG_BUF_CNT)
+
+#if SPI_OUT_LL_ENABLED
+#define SPI_OUT_LL_QUEUE_SIZE (3 * SPI_OUT_PING_PONG_BUF_CNT)
+#else
+#define SPI_OUT_LL_QUEUE_SIZE (0)
+#endif // SPI_OUT_LL_ENABLED
+
+#define SPI_OUT_SPI_MASTER_QUEUE_SIZE (SPI_OUT_UL_QUEUE_SIZE +\
+ SPI_OUT_LL_QUEUE_SIZE)
+
+// Private typedefs
+typedef struct {
+ // CRITICAL: 0 for available, 1 for need queue (ISR), 2 for in queue
+ // This flag is for multithreading, must be a word, do not modify
+ volatile uint32_t flag;
+ uint16_t buf_size;
+ uint16_t length;
+ spi_transaction_t trans;
+} spi_out_trans_cb_t;
+
+typedef struct {
+ spi_out_trans_cb_t *trans_cb[2];
+ uint8_t trans_cb_idx;
+ uint8_t frame_sn;
+ uint16_t lost_frame_cnt;
+ uint32_t lost_bytes_cnt;
+ uint8_t type;
+} spi_out_log_cb_t;
+
+typedef struct {
+ uint16_t length;
+ uint8_t source;
+ uint8_t frame_sn;
+} __attribute__((packed)) frame_head_t;
+
+typedef struct {
+ uint8_t type;
+ uint16_t lost_frame_cnt;
+ uint32_t lost_bytes_cnt;
+} __attribute__((packed)) loss_payload_t;
+
+typedef struct {
+ uint8_t io_level;
+ uint32_t lc_ts;
+ uint32_t esp_ts;
+} __attribute__((packed)) ts_sync_data_t;
+
+// Private enums
+enum {
+ TRANS_CB_FLAG_AVAILABLE = 0,
+ TRANS_CB_FLAG_NEED_QUEUE,
+ TRANS_CB_FLAG_IN_QUEUE,
+};
+
+enum {
+ LOG_CB_TYPE_UL = 0,
+ LOG_CB_TYPE_LL_TASK,
+ LOG_CB_TYPE_LL_ISR,
+ LOG_CB_TYPE_LL_HCI,
+ LOG_CB_TYPE_LE_AUDIO,
+};
+
+enum {
+ LL_LOG_FLAG_CONTINUE = 0,
+ LL_LOG_FLAG_END,
+ LL_LOG_FLAG_TASK,
+ LL_LOG_FLAG_ISR,
+ LL_LOG_FLAG_HCI,
+ LL_LOG_FLAG_RAW,
+};
+
+enum {
+ LL_EV_FLAG_ISR_APPEND = 0,
+ LL_EV_FLAG_FLUSH_LOG,
+};
+
+// Private variables
+static bool spi_out_inited = false;
+static bool spi_out_enabled = false;
+static spi_device_handle_t spi_handle = NULL;
+static uint32_t last_tx_done_ts = 0;
+
+static bool ul_log_inited = false;
+static SemaphoreHandle_t ul_log_mutex = NULL;
+static spi_out_log_cb_t *ul_log_cb = NULL;
+static uint8_t *ul_log_str_buf = NULL;
+
+#if SPI_OUT_LL_ENABLED
+static bool ll_log_inited = false;
+static spi_out_log_cb_t *ll_task_log_cb = NULL;
+static spi_out_log_cb_t *ll_isr_log_cb = NULL;
+static spi_out_log_cb_t *ll_hci_log_cb = NULL;
+static uint32_t ll_ev_flags = 0;
+#endif // SPI_OUT_LL_ENABLED
+
+#if SPI_OUT_TS_SYNC_ENABLED
+static bool ts_sync_inited = false;
+static bool ts_sync_enabled = false;
+static ts_sync_data_t ts_sync_data = {0};
+
+#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+static esp_timer_handle_t ts_sync_timer = NULL;
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+#endif // SPI_OUT_TS_SYNC_ENABLED
+
+#if SPI_OUT_FLUSH_TIMER_ENABLED
+static esp_timer_handle_t flush_timer = NULL;
+#endif // SPI_OUT_FLUSH_TIMER_ENABLED
+
+#if SPI_OUT_LE_AUDIO_ENABLED
+static bool le_audio_log_inited = false;
+static spi_out_log_cb_t *le_audio_log_cb = NULL;
+#endif // SPI_OUT_LE_AUDIO_ENABLED
+
+// Extern function declarations
+extern void esp_panic_handler_feed_wdts(void);
+
+// Private function declarations
+static int spi_out_init_trans(spi_out_trans_cb_t **trans_cb, uint16_t buf_size);
+static void spi_out_deinit_trans(spi_out_trans_cb_t **trans_cb);
+static void spi_out_tx_done_cb(spi_transaction_t *ret_trans);
+static inline void spi_out_append_trans(spi_out_trans_cb_t *trans_cb);
+
+static int spi_out_log_cb_init(spi_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type);
+static void spi_out_log_cb_deinit(spi_out_log_cb_t **log_cb);
+static inline bool spi_out_log_cb_check_trans(spi_out_log_cb_t *log_cb, uint16_t len, bool *need_append);
+static inline void spi_out_log_cb_append_trans(spi_out_log_cb_t *log_cb);
+static inline void spi_out_log_cb_flush_trans(spi_out_log_cb_t *log_cb);
+static bool spi_out_log_cb_write(spi_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len,
+ const uint8_t *addr_append, uint16_t len_append, uint8_t source,
+ bool with_checksum);
+static void spi_out_log_cb_write_loss(spi_out_log_cb_t *log_cb);
+static void spi_out_log_cb_dump(spi_out_log_cb_t *log_cb);
+static void spi_out_log_flush(void);
+
+static int spi_out_ul_log_init(void);
+static void spi_out_ul_log_deinit(void);
+static void spi_out_ul_log_write(uint8_t source, const uint8_t *addr, uint16_t len, bool with_ts);
+static bool spi_out_ul_log_printf(uint8_t source, const char *format, va_list args, int offset);
+
+#if SPI_OUT_LL_ENABLED
+static int spi_out_ll_log_init(void);
+static void spi_out_ll_log_deinit(void);
+static void spi_out_ll_log_flush(void);
+
+#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\
+ defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21)
+extern void r_ble_log_simple_put_ev(void);
+#define SPI_OUT_LL_PUT_EV r_ble_log_simple_put_ev()
+#elif defined(CONFIG_IDF_TARGET_ESP32C2)
+extern void ble_log_simple_put_ev(void);
+#define SPI_OUT_LL_PUT_EV ble_log_simple_put_ev()
+#else
+#define SPI_OUT_LL_PUT_EV
+#endif
+#endif // SPI_OUT_LL_ENABLED
+
+#if SPI_OUT_TS_SYNC_ENABLED
+static int spi_out_ts_sync_init(void);
+static void spi_out_ts_sync_deinit(void);
+static void spi_out_ts_sync_enable(bool enable);
+static void spi_out_ts_sync_toggle(void);
+
+#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\
+ defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21)
+extern uint32_t r_ble_lll_timer_current_tick_get(void);
+#define SPI_OUT_GET_LC_TIME r_ble_lll_timer_current_tick_get()
+#elif defined(CONFIG_IDF_TARGET_ESP32C2)
+extern uint32_t r_os_cputime_get32(void);
+#define SPI_OUT_GET_LC_TIME r_os_cputime_get32()
+#else
+#define SPI_OUT_GET_LC_TIME 0
+#endif
+
+#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+static void esp_timer_cb_ts_sync(void);
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+#endif // SPI_OUT_TS_SYNC_ENABLED
+
+#if SPI_OUT_LE_AUDIO_ENABLED
+static int spi_out_le_audio_log_init(void);
+static void spi_out_le_audio_log_deinit(void);
+#endif // SPI_OUT_LE_AUDIO_ENABLED
+
+// Private functions
+static int spi_out_init_trans(spi_out_trans_cb_t **trans_cb, uint16_t buf_size)
+{
+ // Memory allocations
+ *trans_cb = (spi_out_trans_cb_t *)SPI_OUT_MALLOC(sizeof(spi_out_trans_cb_t));
+ if (!(*trans_cb)) {
+ return -1;
+ }
+ memset(*trans_cb, 0, sizeof(spi_out_trans_cb_t));
+
+ uint8_t *buf = (uint8_t *)SPI_OUT_MALLOC((size_t)buf_size);
+ if (!buf) {
+ free(*trans_cb);
+ *trans_cb = NULL;
+ return -1;
+ }
+
+ // Initialization
+ (*trans_cb)->buf_size = buf_size;
+ (*trans_cb)->trans.tx_buffer = buf;
+ (*trans_cb)->trans.user = (void *)(*trans_cb);
+ return 0;
+}
+
+static void spi_out_deinit_trans(spi_out_trans_cb_t **trans_cb)
+{
+ if (!(*trans_cb)) {
+ return;
+ }
+ if ((*trans_cb)->trans.tx_buffer) {
+ free((uint8_t *)(*trans_cb)->trans.tx_buffer);
+ (*trans_cb)->trans.tx_buffer = NULL;
+ }
+
+ free(*trans_cb);
+ *trans_cb = NULL;
+ return;
+}
+
+IRAM_ATTR static void spi_out_tx_done_cb(spi_transaction_t *ret_trans)
+{
+ last_tx_done_ts = esp_timer_get_time();
+ spi_out_trans_cb_t *trans_cb = (spi_out_trans_cb_t *)ret_trans->user;
+ trans_cb->length = 0;
+ trans_cb->flag = TRANS_CB_FLAG_AVAILABLE;
+}
+
+IRAM_ATTR static void spi_out_pre_tx_cb(spi_transaction_t *ret_trans)
+{
+ // SPI slave continuous transaction workaround
+ while (esp_timer_get_time() - last_tx_done_ts < SPI_OUT_TRANS_ITVL_MIN_US) {}
+}
+
+IRAM_ATTR static inline void spi_out_append_trans(spi_out_trans_cb_t *trans_cb)
+{
+ if (trans_cb->flag != TRANS_CB_FLAG_NEED_QUEUE || !trans_cb->length) {
+ return;
+ }
+
+ // Note: To support dump log when disabled
+ if (!spi_out_enabled) {
+ goto recycle;
+ }
+
+ // CRITICAL: Length unit conversion from bytes to bits
+ trans_cb->trans.length = trans_cb->length * 8;
+ trans_cb->trans.rxlength = 0;
+ trans_cb->flag = TRANS_CB_FLAG_IN_QUEUE;
+ if (spi_device_queue_trans(spi_handle, &(trans_cb->trans), 0) != ESP_OK) {
+ goto recycle;
+ }
+ return;
+
+recycle:
+ trans_cb->length = 0;
+ trans_cb->flag = TRANS_CB_FLAG_AVAILABLE;
+ return;
+}
+
+static int spi_out_log_cb_init(spi_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type)
+{
+ // Initialize log control block
+ *log_cb = (spi_out_log_cb_t *)SPI_OUT_MALLOC(sizeof(spi_out_log_cb_t));
+ if (!(*log_cb)) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control block!");
+ return -1;
+ }
+ memset(*log_cb, 0, sizeof(spi_out_log_cb_t));
+
+ // Initialize transactions
+ int ret = 0;
+ for (uint8_t i = 0; i < 2; i++) {
+ ret |= spi_out_init_trans(&((*log_cb)->trans_cb[i]), buf_size);
+ }
+ if (ret != 0) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize SPI transactions!");
+ spi_out_log_cb_deinit(log_cb);
+ return -1;
+ }
+
+ (*log_cb)->type = type;
+ return 0;
+}
+
+static void spi_out_log_cb_deinit(spi_out_log_cb_t **log_cb)
+{
+ if (!(*log_cb)) {
+ return;
+ }
+
+ for (uint8_t i = 0; i < 2; i++) {
+ if ((*log_cb)->trans_cb[i]) {
+ spi_out_deinit_trans(&((*log_cb)->trans_cb[i]));
+ }
+ }
+ free(*log_cb);
+ *log_cb = NULL;
+ return;
+}
+
+IRAM_ATTR static inline bool spi_out_log_cb_check_trans(spi_out_log_cb_t *log_cb, uint16_t len, bool *need_append)
+{
+ spi_out_trans_cb_t *trans_cb;
+ uint16_t frame_len = len + SPI_OUT_FRAME_OVERHEAD;
+ *need_append = false;
+ for (uint8_t i = 0; i < 2; i++) {
+ trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
+ if (frame_len > trans_cb->buf_size) {
+ goto failed;
+ }
+ if (trans_cb->flag == TRANS_CB_FLAG_AVAILABLE) {
+ if ((trans_cb->buf_size - trans_cb->length) >= frame_len) {
+ return true;
+ } else {
+ trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
+ *need_append = true;
+ }
+ }
+ log_cb->trans_cb_idx = !(log_cb->trans_cb_idx);
+ }
+failed:
+ log_cb->lost_bytes_cnt += frame_len;
+ log_cb->lost_frame_cnt++;
+ log_cb->frame_sn++;
+ return false;
+}
+
+// CRITICAL: Shall not be called from ISR!
+IRAM_ATTR static inline void spi_out_log_cb_append_trans(spi_out_log_cb_t *log_cb)
+{
+ spi_out_trans_cb_t *trans_cb;
+ uint8_t idx = !log_cb->trans_cb_idx;
+ for (uint8_t i = 0; i < 2; i++) {
+ trans_cb = log_cb->trans_cb[idx];
+ if (trans_cb->flag == TRANS_CB_FLAG_NEED_QUEUE) {
+ spi_out_append_trans(trans_cb);
+ }
+ idx = !idx;
+ }
+}
+
+IRAM_ATTR static inline void spi_out_log_cb_flush_trans(spi_out_log_cb_t *log_cb)
+{
+ spi_out_trans_cb_t *trans_cb;
+ for (uint8_t i = 0; i < 2; i++) {
+ trans_cb = log_cb->trans_cb[i];
+ if (trans_cb->length && (trans_cb->flag == TRANS_CB_FLAG_AVAILABLE)) {
+ trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
+ }
+ }
+}
+
+// Return value: Need append
+IRAM_ATTR static bool spi_out_log_cb_write(spi_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len,
+ const uint8_t *addr_append, uint16_t len_append, uint8_t source,
+ bool with_checksum)
+{
+ spi_out_trans_cb_t *trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
+
+ uint8_t *buf = (uint8_t *)trans_cb->trans.tx_buffer + trans_cb->length;
+ uint16_t total_length = len + len_append;
+ frame_head_t head = {
+ .length = total_length,
+ .source = source,
+ .frame_sn = log_cb->frame_sn,
+ };
+ uint32_t checksum = 0;
+ if (with_checksum) {
+ for (int i = 0; i < len; i++) {
+ checksum += addr[i];
+ }
+ for (int i = 0; i < len_append; i++) {
+ checksum += addr_append[i];
+ }
+ }
+
+ memcpy(buf, (const uint8_t *)&head, SPI_OUT_FRAME_HEAD_LEN);
+ memcpy(buf + SPI_OUT_FRAME_HEAD_LEN, addr, len);
+ if (len_append && addr_append) {
+ memcpy(buf + SPI_OUT_FRAME_HEAD_LEN + len, addr_append, len_append);
+ }
+ memcpy(buf + SPI_OUT_FRAME_HEAD_LEN + total_length, &checksum, SPI_OUT_FRAME_TAIL_LEN);
+
+ trans_cb->length += total_length + SPI_OUT_FRAME_OVERHEAD;
+ log_cb->frame_sn++;
+ if ((trans_cb->buf_size - trans_cb->length) <= SPI_OUT_FRAME_OVERHEAD) {
+ trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE;
+ return true;
+ }
+ return false;
+}
+
+IRAM_ATTR static void spi_out_log_cb_write_loss(spi_out_log_cb_t *log_cb)
+{
+ if (!log_cb->lost_bytes_cnt || !log_cb->lost_frame_cnt) {
+ return;
+ }
+ bool need_append;
+ if (spi_out_log_cb_check_trans(log_cb, sizeof(loss_payload_t), &need_append)) {
+ loss_payload_t payload = {
+ .type = log_cb->type,
+ .lost_frame_cnt = log_cb->lost_frame_cnt,
+ .lost_bytes_cnt = log_cb->lost_bytes_cnt,
+ };
+ spi_out_log_cb_write(log_cb, (const uint8_t *)&payload, sizeof(loss_payload_t),
+ NULL, 0, BLE_LOG_SPI_OUT_SOURCE_LOSS, true);
+
+ log_cb->lost_frame_cnt = 0;
+ log_cb->lost_bytes_cnt = 0;
+ }
+}
+
+static void spi_out_log_cb_dump(spi_out_log_cb_t *log_cb)
+{
+ spi_out_trans_cb_t *trans_cb;
+ uint8_t *buf;
+ for (uint8_t i = 0; i < 2; i++) {
+ // Dump the last transaction before dumping the current transaction
+ log_cb->trans_cb_idx = !(log_cb->trans_cb_idx);
+ trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx];
+ buf = (uint8_t *)trans_cb->trans.tx_buffer;
+ for (uint16_t j = 0; j < trans_cb->buf_size; j++) {
+ esp_rom_printf("%02x ", buf[j]);
+
+ // Feed watchdogs periodically to avoid wdts timeout
+ if ((j % 100) == 0) {
+ esp_panic_handler_feed_wdts();
+ }
+ }
+ }
+}
+
+static void spi_out_log_flush(void)
+{
+ // Flush ul log
+ xSemaphoreTake(ul_log_mutex, portMAX_DELAY);
+ spi_out_log_cb_flush_trans(ul_log_cb);
+ spi_out_log_cb_append_trans(ul_log_cb);
+ xSemaphoreGive(ul_log_mutex);
+
+#if SPI_OUT_LL_ENABLED
+ if (esp_bt_controller_get_status() >= ESP_BT_CONTROLLER_STATUS_INITED) {
+ ll_ev_flags |= BIT(LL_EV_FLAG_FLUSH_LOG);
+ SPI_OUT_LL_PUT_EV;
+ }
+#endif // SPI_OUT_LL_ENABLED
+}
+
+#if SPI_OUT_FLUSH_TIMER_ENABLED
+// Context: ESP timer
+static void esp_timer_cb_log_flush(void)
+{
+ spi_out_log_flush();
+ esp_timer_start_once(flush_timer, SPI_OUT_FLUSH_TIMEOUT_US);
+}
+#endif // SPI_OUT_FLUSH_TIMER_ENABLED
+
+static int spi_out_ul_log_init(void)
+{
+ if (ul_log_inited) {
+ return 0;
+ }
+
+ // Initialize mutex
+ ul_log_mutex = xSemaphoreCreateMutex();
+ if (!ul_log_mutex) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to create mutex for upper layer task log!");
+ goto mutex_init_failed;
+ }
+
+ // Initialize string buffer
+ ul_log_str_buf = (uint8_t *)SPI_OUT_MALLOC(SPI_OUT_UL_LOG_STR_BUF_SIZE);
+ if (!ul_log_str_buf) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize string buffer for upper layer task log!");
+ goto str_buf_init_failed;
+ }
+
+ // Initialize log control block
+ if (spi_out_log_cb_init(&ul_log_cb, SPI_OUT_UL_TASK_BUF_SIZE, LOG_CB_TYPE_UL) != 0) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for upper layer task log!");
+ goto log_cb_init_failed;
+ }
+
+ // Initialization done
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize upper layer task log!");
+ ul_log_inited = true;
+ return 0;
+
+log_cb_init_failed:
+ if (ul_log_str_buf) {
+ free(ul_log_str_buf);
+ ul_log_str_buf = NULL;
+ }
+str_buf_init_failed:
+ vSemaphoreDelete(ul_log_mutex);
+mutex_init_failed:
+ return -1;
+}
+
+static void spi_out_ul_log_deinit(void)
+{
+ if (!ul_log_inited) {
+ return;
+ }
+ ul_log_inited = false;
+
+ xSemaphoreTake(ul_log_mutex, portMAX_DELAY);
+ if (ul_log_str_buf) {
+ free(ul_log_str_buf);
+ ul_log_str_buf = NULL;
+ }
+ spi_out_log_cb_deinit(&ul_log_cb);
+ xSemaphoreGive(ul_log_mutex);
+
+ vSemaphoreDelete(ul_log_mutex);
+ ul_log_mutex = NULL;
+
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize upper layer log!");
+ return;
+}
+
+static void spi_out_ul_log_write(uint8_t source, const uint8_t *addr, uint16_t len, bool with_ts)
+{
+ uint16_t total_len = with_ts? (len + sizeof(uint32_t)): len;
+ bool need_append;
+ if (spi_out_log_cb_check_trans(ul_log_cb, total_len, &need_append)) {
+ if (with_ts) {
+ uint32_t esp_ts = esp_timer_get_time();
+ need_append |= spi_out_log_cb_write(ul_log_cb, (const uint8_t *)&esp_ts,
+ sizeof(uint32_t), addr, len, source, true);
+ } else {
+ need_append |= spi_out_log_cb_write(ul_log_cb, addr, len, NULL, 0, source, true);
+ }
+ }
+ if (need_append) {
+ spi_out_log_cb_append_trans(ul_log_cb);
+ }
+ spi_out_log_cb_write_loss(ul_log_cb);
+}
+
+static bool spi_out_ul_log_printf(uint8_t source, const char *format, va_list args, int offset)
+{
+ int len = vsnprintf((char *)(ul_log_str_buf + offset),
+ SPI_OUT_UL_LOG_STR_BUF_SIZE - offset, format, args);
+ if (len < 0) {
+ return false;
+ }
+ len += offset;
+
+ // Truncate string if overflowed
+ if (len >= SPI_OUT_UL_LOG_STR_BUF_SIZE) {
+ len = SPI_OUT_UL_LOG_STR_BUF_SIZE - 1;
+ ul_log_str_buf[len] = '\0';
+ }
+
+ spi_out_ul_log_write(source, ul_log_str_buf, len, true);
+ return true;
+}
+
+#if SPI_OUT_LL_ENABLED
+static int spi_out_ll_log_init(void)
+{
+ if (ll_log_inited) {
+ return 0;
+ }
+
+ // Initialize log control blocks for controller task & ISR logs
+ if (spi_out_log_cb_init(&ll_task_log_cb, SPI_OUT_LL_TASK_BUF_SIZE, LOG_CB_TYPE_LL_TASK) != 0) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for controller task!");
+ goto task_log_cb_init_failed;
+ }
+ if (spi_out_log_cb_init(&ll_isr_log_cb, SPI_OUT_LL_ISR_BUF_SIZE, LOG_CB_TYPE_LL_ISR) != 0) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for controller ISR!");
+ goto isr_log_cb_init_failed;
+ }
+ if (spi_out_log_cb_init(&ll_hci_log_cb, SPI_OUT_LL_HCI_BUF_SIZE, LOG_CB_TYPE_LL_HCI) != 0) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for controller ISR!");
+ goto hci_log_cb_init_failed;
+ }
+
+ // Initialization done
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize log control blocks for controller task & ISR!");
+ ll_log_inited = true;
+ return 0;
+
+hci_log_cb_init_failed:
+ spi_out_log_cb_deinit(&ll_isr_log_cb);
+isr_log_cb_init_failed:
+ spi_out_log_cb_deinit(&ll_task_log_cb);
+task_log_cb_init_failed:
+ return -1;
+}
+
+static void spi_out_ll_log_deinit(void)
+{
+ if (!ll_log_inited) {
+ return;
+ }
+
+ spi_out_log_cb_deinit(&ll_hci_log_cb);
+ spi_out_log_cb_deinit(&ll_isr_log_cb);
+ spi_out_log_cb_deinit(&ll_task_log_cb);
+
+ // Deinitialization done
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize controller log!");
+ ll_log_inited = false;
+ return;
+}
+
+// Context: LL task
+static void spi_out_ll_log_flush(void)
+{
+ // Flush task log and hci log buffer
+ spi_out_log_cb_flush_trans(ll_task_log_cb);
+ spi_out_log_cb_flush_trans(ll_hci_log_cb);
+
+ // Race condition for isr log buffer
+ portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
+ portENTER_CRITICAL_SAFE(&spinlock);
+ spi_out_log_cb_flush_trans(ll_isr_log_cb);
+ portEXIT_CRITICAL_SAFE(&spinlock);
+
+ // Note: Save SPI transfer start time
+ spi_out_log_cb_append_trans(ll_task_log_cb);
+ spi_out_log_cb_append_trans(ll_hci_log_cb);
+ spi_out_log_cb_append_trans(ll_isr_log_cb);
+}
+#endif // SPI_OUT_LL_ENABLED
+
+#if SPI_OUT_TS_SYNC_ENABLED
+static int spi_out_ts_sync_init(void)
+{
+ if (ts_sync_inited) {
+ return 0;
+ }
+
+#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ // Initialize sync timer
+ esp_timer_create_args_t timer_args = {
+ .callback = (esp_timer_cb_t)esp_timer_cb_ts_sync,
+ .dispatch_method = ESP_TIMER_TASK
+ };
+ if (esp_timer_create(&timer_args, &ts_sync_timer) != ESP_OK) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize timestamp synchronizer timer!");
+ goto timer_init_failed;
+ }
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+
+ // Initialize sync IO
+ gpio_config_t io_conf = {
+ .intr_type = GPIO_INTR_DISABLE,
+ .mode = GPIO_MODE_OUTPUT,
+ .pin_bit_mask = BIT(SPI_OUT_SYNC_IO_NUM),
+ .pull_down_en = 0,
+ .pull_up_en = 0
+ };
+ if (gpio_config(&io_conf) != ESP_OK) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize timestamp synchronizer IO!");
+ goto gpio_init_failed;
+ }
+
+ // Initialization done
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize timestamp synchronizer!");
+ ts_sync_inited = true;
+ return 0;
+
+gpio_init_failed:
+#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ esp_timer_delete(ts_sync_timer);
+ ts_sync_timer = NULL;
+timer_init_failed:
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ return -1;
+}
+
+static void spi_out_ts_sync_deinit(void)
+{
+ if (!ts_sync_inited) {
+ return;
+ }
+
+#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ // Deinitialize timestamp synchronizer
+ esp_timer_stop(ts_sync_timer);
+ esp_timer_delete(ts_sync_timer);
+ ts_sync_timer = NULL;
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+
+ // Deinitialize sync IO
+ spi_out_ts_sync_enable(false);
+ gpio_reset_pin(SPI_OUT_SYNC_IO_NUM);
+
+ // Deinitialization done
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize timestamp synchronizer!");
+ ts_sync_inited = false;
+ return;
+}
+
+static void spi_out_ts_sync_enable(bool enable)
+{
+ // Update ts sync status
+ ts_sync_enabled = enable;
+ if (enable) {
+#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ // Start timestamp sync timer
+ if (ts_sync_timer) {
+ if (!esp_timer_is_active(ts_sync_timer)) {
+ esp_timer_start_periodic(ts_sync_timer, SPI_OUT_TS_SYNC_TIMEOUT);
+ }
+ }
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ } else {
+#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ // Stop timestamp sync timer
+ if (ts_sync_timer) {
+ if (esp_timer_is_active(ts_sync_timer)) {
+ esp_timer_stop(ts_sync_timer);
+ }
+ }
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ if (!ts_sync_data.io_level) {
+ gpio_set_level(SPI_OUT_SYNC_IO_NUM, 1);
+ }
+ }
+ ts_sync_data.io_level = 0;
+ gpio_set_level(SPI_OUT_SYNC_IO_NUM, (uint32_t)ts_sync_data.io_level);
+}
+
+static void spi_out_ts_sync_toggle(void)
+{
+ // Toggle sync IO
+ ts_sync_data.io_level = !ts_sync_data.io_level;
+
+ // Enter critical
+ portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
+ portENTER_CRITICAL(&spinlock);
+
+ // Get LC timestamp
+ ts_sync_data.lc_ts = SPI_OUT_GET_LC_TIME;
+
+ // Set sync IO level
+ gpio_set_level(SPI_OUT_SYNC_IO_NUM, (uint32_t)ts_sync_data.io_level);
+
+ // Get ESP timestamp
+ ts_sync_data.esp_ts = esp_timer_get_time();
+ portEXIT_CRITICAL(&spinlock);
+ // Exit critical
+}
+
+#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+// CRITICAL: This function is called in ESP Timer task
+static void esp_timer_cb_ts_sync(void)
+{
+ spi_out_ts_sync_toggle();
+ ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_SYNC, (const uint8_t *)&ts_sync_data,
+ sizeof(ts_sync_data_t));
+}
+#else
+
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+#endif // SPI_OUT_TS_SYNC_ENABLED
+
+#if SPI_OUT_LE_AUDIO_ENABLED
+static int spi_out_le_audio_log_init(void)
+{
+ if (le_audio_log_inited) {
+ return 0;
+ }
+
+ // Initialize log control blocks for controller task & ISR logs
+ if (spi_out_log_cb_init(&le_audio_log_cb, SPI_OUT_LE_AUDIO_BUF_SIZE, LOG_CB_TYPE_LE_AUDIO) != 0) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for LE audio!");
+ return -1;
+ }
+
+ // Initialization done
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize log control blocks for LE Audio!");
+ le_audio_log_inited = true;
+ return 0;
+}
+
+static void spi_out_le_audio_log_deinit(void)
+{
+ if (!le_audio_log_inited) {
+ return;
+ }
+
+ spi_out_log_cb_deinit(&le_audio_log_cb);
+
+ // Deinitialization done
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize LE audio log!");
+ le_audio_log_inited = false;
+ return;
+}
+#endif // SPI_OUT_LE_AUDIO_ENABLED
+
+// Public functions
+int ble_log_spi_out_init(void)
+{
+ // Avoid double init
+ if (spi_out_inited) {
+ return 0;
+ }
+
+ // Initialize SPI
+ spi_bus_config_t bus_config = {
+ .miso_io_num = -1,
+ .mosi_io_num = SPI_OUT_MOSI_IO_NUM,
+ .sclk_io_num = SPI_OUT_SCLK_IO_NUM,
+ .quadwp_io_num = -1,
+ .quadhd_io_num = -1,
+ .max_transfer_sz = SPI_OUT_MAX_TRANSFER_SIZE,
+#if CONFIG_SPI_MASTER_ISR_IN_IRAM
+ .intr_flags = ESP_INTR_FLAG_IRAM
+#endif // CONFIG_SPI_MASTER_ISR_IN_IRAM
+ };
+ spi_device_interface_config_t dev_config = {
+ .clock_speed_hz = SPI_MASTER_FREQ_20M,
+ .mode = 0,
+ .spics_io_num = SPI_OUT_CS_IO_NUM,
+ .queue_size = SPI_OUT_SPI_MASTER_QUEUE_SIZE,
+ .post_cb = spi_out_tx_done_cb,
+ .pre_cb = spi_out_pre_tx_cb,
+ .flags = SPI_DEVICE_NO_RETURN_RESULT
+ };
+ if (spi_bus_initialize(SPI_OUT_BUS, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize SPI bus!");
+ goto spi_bus_init_failed;
+ }
+ if (spi_bus_add_device(SPI_OUT_BUS, &dev_config, &spi_handle) != ESP_OK) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to add device to SPI bus!");
+ goto spi_device_add_failed;
+ }
+
+ if (spi_out_ul_log_init() != 0) {
+ goto ul_log_init_failed;
+ }
+
+#if SPI_OUT_LL_ENABLED
+ if (spi_out_ll_log_init() != 0) {
+ goto ll_log_init_failed;
+ }
+#endif // SPI_OUT_LL_ENABLED
+
+#if SPI_OUT_TS_SYNC_ENABLED
+ if (spi_out_ts_sync_init() != 0) {
+ goto ts_sync_init_failed;
+ }
+#endif // SPI_OUT_TS_SYNC_ENABLED
+
+#if SPI_OUT_LE_AUDIO_ENABLED
+ if (spi_out_le_audio_log_init() != 0) {
+ goto le_audio_init_failed;
+ }
+#endif // SPI_OUT_LE_AUDIO_ENABLED
+
+#if SPI_OUT_FLUSH_TIMER_ENABLED
+ esp_timer_create_args_t timer_args = {
+ .callback = (esp_timer_cb_t)esp_timer_cb_log_flush,
+ .dispatch_method = ESP_TIMER_TASK
+ };
+ if (esp_timer_create(&timer_args, &flush_timer) != ESP_OK) {
+ ESP_LOGE(BLE_LOG_TAG, "Failed to initialize flush timer!");
+ goto timer_init_failed;
+ }
+#endif // SPI_OUT_FLUSH_TIMER_ENABLED
+
+ // Initialization done
+ ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize BLE log SPI output interface!");
+ spi_out_inited = true;
+ spi_out_enabled = true;
+
+#if SPI_OUT_FLUSH_TIMER_ENABLED
+ esp_timer_start_once(flush_timer, SPI_OUT_FLUSH_TIMEOUT_US);
+#endif // SPI_OUT_FLUSH_TIMER_ENABLED
+ return 0;
+
+#if SPI_OUT_FLUSH_TIMER_ENABLED
+timer_init_failed:
+#endif // SPI_OUT_FLUSH_TIMER_ENABLED
+#if SPI_OUT_LE_AUDIO_ENABLED
+ spi_out_le_audio_log_deinit();
+le_audio_init_failed:
+#endif // SPI_OUT_LE_AUDIO_ENABLED
+#if SPI_OUT_TS_SYNC_ENABLED
+ spi_out_ts_sync_deinit();
+ts_sync_init_failed:
+#endif // SPI_OUT_TS_SYNC_ENABLED
+#if SPI_OUT_LL_ENABLED
+ spi_out_ll_log_deinit();
+ll_log_init_failed:
+#endif // SPI_OUT_LL_ENABLED
+ spi_out_ul_log_deinit();
+ul_log_init_failed:
+ spi_bus_remove_device(spi_handle);
+ spi_handle = NULL;
+spi_device_add_failed:
+ spi_bus_free(SPI_OUT_BUS);
+spi_bus_init_failed:
+ return -1;
+}
+
+void ble_log_spi_out_deinit(void)
+{
+ // Avoid double deinit
+ if (!spi_out_inited) {
+ return;
+ }
+
+#if SPI_OUT_FLUSH_TIMER_ENABLED
+ esp_timer_stop(flush_timer);
+ esp_timer_delete(flush_timer);
+ flush_timer = NULL;
+#endif // SPI_OUT_FLUSH_TIMER_ENABLED
+
+ // Drain all queued transactions
+ assert(spi_device_acquire_bus(spi_handle, portMAX_DELAY) == ESP_OK);
+ spi_device_release_bus(spi_handle);
+
+ // Remove SPI master
+ spi_bus_remove_device(spi_handle);
+ spi_handle = NULL;
+ spi_bus_free(SPI_OUT_BUS);
+
+#if SPI_OUT_TS_SYNC_ENABLED
+ spi_out_ts_sync_deinit();
+#endif // SPI_OUT_TS_SYNC_ENABLED
+
+#if SPI_OUT_LL_ENABLED
+ spi_out_ll_log_deinit();
+#endif // SPI_OUT_LL_ENABLED
+
+ spi_out_ul_log_deinit();
+
+ // Reset init flag
+ spi_out_inited = false;
+ spi_out_enabled = false;
+}
+
+#if SPI_OUT_TS_SYNC_ENABLED
+void ble_log_spi_out_ts_sync_start(void)
+{
+ // Check if SPI out is initialized
+ if (!spi_out_inited) {
+ return;
+ }
+ spi_out_ts_sync_enable(true);
+}
+
+void ble_log_spi_out_ts_sync_stop(void)
+{
+ // Check if SPI out is initialized
+ if (!spi_out_inited) {
+ return;
+ }
+ spi_out_ts_sync_enable(false);
+}
+#endif // SPI_OUT_TS_SYNC_ENABLED
+
+#if SPI_OUT_LL_ENABLED
+// Only LL task has access to this API
+IRAM_ATTR void ble_log_spi_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,
+ const uint8_t *addr_append, uint32_t flag)
+{
+ // Raw logs will come in case of assert, shall be printed to console directly
+ if (flag & BIT(LL_LOG_FLAG_RAW)) {
+ if (len && addr) {
+ for (uint32_t i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); }
+ }
+ if (len_append && addr_append) {
+ for (uint32_t i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); }
+ }
+ if (flag & BIT(LL_LOG_FLAG_END)) { esp_rom_printf("\n"); }
+ }
+
+ if (!ll_log_inited) {
+ return;
+ }
+
+ bool in_isr = false;
+ uint8_t source;
+ spi_out_log_cb_t *log_cb;
+ if (flag & BIT(LL_LOG_FLAG_ISR)) {
+ log_cb = ll_isr_log_cb;
+ source = BLE_LOG_SPI_OUT_SOURCE_ESP_ISR;
+ in_isr = true;
+ } else if (flag & BIT(LL_LOG_FLAG_HCI)) {
+ log_cb = ll_hci_log_cb;
+ source = BLE_LOG_SPI_OUT_SOURCE_LL_HCI;
+ } else {
+ log_cb = ll_task_log_cb;
+ source = BLE_LOG_SPI_OUT_SOURCE_ESP;
+ }
+
+ bool need_append;
+ if (spi_out_log_cb_check_trans(log_cb, (uint16_t)(len + len_append), &need_append)) {
+ need_append |= spi_out_log_cb_write(log_cb, addr, (uint16_t)len, addr_append,
+ (uint16_t)len_append, source, true);
+ }
+ if (need_append) {
+ if (in_isr) {
+ ll_ev_flags |= BIT(LL_EV_FLAG_ISR_APPEND);
+ SPI_OUT_LL_PUT_EV;
+ } else {
+ spi_out_log_cb_append_trans(log_cb);
+
+#if SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ if (ts_sync_inited && ts_sync_enabled) {
+ if (last_tx_done_ts >= (SPI_OUT_TS_SYNC_TIMEOUT + ts_sync_data.esp_ts)) {
+ if (spi_out_log_cb_check_trans(ll_task_log_cb, sizeof(ts_sync_data_t), &need_append)) {
+ spi_out_ts_sync_toggle();
+ spi_out_log_cb_write(ll_task_log_cb, (const uint8_t *)&ts_sync_data,
+ sizeof(ts_sync_data_t), NULL, 0, BLE_LOG_SPI_OUT_SOURCE_SYNC, true);
+ }
+ }
+ }
+#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT
+ }
+ }
+ spi_out_log_cb_write_loss(log_cb);
+}
+
+IRAM_ATTR void ble_log_spi_out_ll_log_ev_proc(void)
+{
+ if (!ll_log_inited) {
+ return;
+ }
+
+ if (ll_ev_flags & BIT(LL_EV_FLAG_ISR_APPEND)) {
+ spi_out_log_cb_append_trans(ll_isr_log_cb);
+ ll_ev_flags &= ~BIT(LL_EV_FLAG_ISR_APPEND);
+ }
+
+ if (ll_ev_flags & BIT(LL_EV_FLAG_FLUSH_LOG)) {
+ spi_out_ll_log_flush();
+ ll_ev_flags &= ~BIT(LL_EV_FLAG_FLUSH_LOG);
+ }
+
+ ll_ev_flags = 0;
+}
+#endif // SPI_OUT_LL_ENABLED
+
+int ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len)
+{
+ if (!ul_log_inited) {
+ return -1;
+ }
+
+ xSemaphoreTake(ul_log_mutex, portMAX_DELAY);
+ spi_out_ul_log_write(source, addr, len, false);
+ xSemaphoreGive(ul_log_mutex);
+ return 0;
+}
+
+int ble_log_spi_out_printf(uint8_t source, const char *format, ...)
+{
+ if (!ul_log_inited) {
+ return -1;
+ }
+
+ if (!format) {
+ return -1;
+ }
+
+ // Get arguments
+ va_list args;
+ va_start(args, format);
+
+ va_list args_copy;
+ va_copy(args_copy, args);
+
+ xSemaphoreTake(ul_log_mutex, portMAX_DELAY);
+ bool ret = spi_out_ul_log_printf(source, format, args_copy, 0);
+ xSemaphoreGive(ul_log_mutex);
+
+ va_end(args_copy);
+ va_end(args);
+ return ret? 0: -1;
+}
+
+int ble_log_spi_out_printf_enh(uint8_t source, uint8_t level, const char *tag, const char *format, ...)
+{
+ if (!ul_log_inited) {
+ return -1;
+ }
+
+ if (!tag || !format) {
+ return -1;
+ }
+
+ va_list args;
+ va_start(args, format);
+
+ va_list args_copy;
+ va_copy(args_copy, args);
+
+ // Create log prefix in the format: "[level][tag] "
+ bool ret = false;
+ xSemaphoreTake(ul_log_mutex, portMAX_DELAY);
+ int prefix_len = snprintf((char *)ul_log_str_buf, SPI_OUT_UL_LOG_STR_BUF_SIZE,
+ "[%d][%s]", level, tag? tag: "NULL");
+ if ((prefix_len < 0) || (prefix_len >= SPI_OUT_UL_LOG_STR_BUF_SIZE)) {
+ goto exit;
+ }
+ ret = spi_out_ul_log_printf(source, format, args_copy, prefix_len);
+exit:
+ xSemaphoreGive(ul_log_mutex);
+ va_end(args_copy);
+ va_end(args);
+ return ret? 0: -1;
+}
+
+int ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len)
+{
+ if (!ul_log_inited) {
+ return -1;
+ }
+
+ xSemaphoreTake(ul_log_mutex, portMAX_DELAY);
+ spi_out_ul_log_write(source, addr, len, true);
+ xSemaphoreGive(ul_log_mutex);
+ return 0;
+}
+
+void ble_log_spi_out_dump_all(void)
+{
+ portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
+ portENTER_CRITICAL_SAFE(&spinlock);
+
+#if SPI_OUT_LL_ENABLED
+ if (ll_log_inited) {
+ // Dump lower layer log buffer
+ esp_rom_printf("[LL_ISR_LOG_DUMP_START:\n");
+ spi_out_log_cb_dump(ll_isr_log_cb);
+ esp_rom_printf("\n:LL_ISR_LOG_DUMP_END]\n\n");
+
+ esp_rom_printf("[LL_TASK_LOG_DUMP_START:\n");
+ spi_out_log_cb_dump(ll_task_log_cb);
+ esp_rom_printf("\n:LL_TASK_LOG_DUMP_END]\n\n");
+
+ esp_rom_printf("[LL_HCI_LOG_DUMP_START:\n");
+ spi_out_log_cb_dump(ll_hci_log_cb);
+ esp_rom_printf("\n:LL_HCI_LOG_DUMP_END]\n\n");
+ }
+#endif // SPI_OUT_LL_ENABLED
+
+ if (ul_log_inited) {
+ // Dump upper layer log buffer
+ esp_rom_printf("[UL_LOG_DUMP_START:\n");
+ spi_out_log_cb_dump(ul_log_cb);
+ esp_rom_printf("\n:UL_LOG_DUMP_END]\n\n");
+ }
+ portEXIT_CRITICAL_SAFE(&spinlock);
+}
+
+void ble_log_spi_out_enable(bool enable)
+{
+ spi_out_enabled = enable;
+
+ if (!enable) {
+#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
+ ble_log_spi_out_ts_sync_stop();
+#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED
+ }
+}
+
+void ble_log_spi_out_flush(void)
+{
+ if (!spi_out_enabled) {
+ return;
+ }
+
+ spi_out_log_flush();
+}
+
+#if CONFIG_BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
+IRAM_ATTR void ble_log_spi_out_le_audio_write(const uint8_t *addr, uint16_t len)
+{
+ if (!le_audio_log_inited) {
+ return;
+ }
+
+ bool need_append;
+ if (spi_out_log_cb_check_trans(le_audio_log_cb, len, &need_append)) {
+ need_append |= spi_out_log_cb_write(le_audio_log_cb, addr, len, NULL, 0,
+ BLE_LOG_SPI_OUT_SOURCE_LE_AUDIO, false);
+ }
+ if (need_append) {
+ spi_out_log_cb_append_trans(le_audio_log_cb);
+ }
+ spi_out_log_cb_write_loss(le_audio_log_cb);
+ return;
+}
+#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED
+#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED
diff --git a/lib/bt/common/ble_log/include/ble_log/ble_log_spi_out.h b/lib/bt/common/ble_log/include/ble_log/ble_log_spi_out.h
new file mode 100644
index 00000000..3a4f8d90
--- /dev/null
+++ b/lib/bt/common/ble_log/include/ble_log/ble_log_spi_out.h
@@ -0,0 +1,64 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef __BT_SPI_OUT_H__
+#define __BT_SPI_OUT_H__
+
+#include <stdarg.h>
+#include <string.h>
+#include "driver/spi_master.h"
+#include "driver/gpio.h"
+#include "esp_timer.h"
+#include "esp_log.h"
+#include "freertos/semphr.h"
+#include "esp_heap_caps.h"
+
+// Public enums
+enum {
+ BLE_LOG_SPI_OUT_SOURCE_ESP = 0,
+ BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY,
+ BLE_LOG_SPI_OUT_SOURCE_BLUEDROID,
+ BLE_LOG_SPI_OUT_SOURCE_NIMBLE,
+ BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM,
+ BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM,
+ BLE_LOG_SPI_OUT_SOURCE_ESP_ISR,
+ BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY_ISR,
+ BLE_LOG_SPI_OUT_SOURCE_LL_HCI,
+ BLE_LOG_SPI_OUT_SOURCE_LE_AUDIO,
+ BLE_LOG_SPI_OUT_SOURCE_USER = 0x10,
+ BLE_LOG_SPI_OUT_SOURCE_SSC = 0xFD,
+ BLE_LOG_SPI_OUT_SOURCE_SYNC,
+ BLE_LOG_SPI_OUT_SOURCE_LOSS,
+};
+
+enum {
+ BLE_LOG_SPI_OUT_LEVEL_NONE = 0,
+ BLE_LOG_SPI_OUT_LEVEL_ERROR,
+ BLE_LOG_SPI_OUT_LEVEL_WARN,
+ BLE_LOG_SPI_OUT_LEVEL_INFO,
+ BLE_LOG_SPI_OUT_LEVEL_DEBUG,
+ BLE_LOG_SPI_OUT_LEVEL_VERBOSE,
+ BLE_LOG_SPI_OUT_LEVEL_MAX,
+};
+
+// Public functions
+int ble_log_spi_out_init(void);
+void ble_log_spi_out_deinit(void);
+void ble_log_spi_out_timer_control(bool enable);
+int ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len);
+void ble_log_spi_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,\
+ const uint8_t *addr_append, uint32_t flag);
+void ble_log_spi_out_ll_log_ev_proc(void);
+void ble_log_spi_out_ts_sync_start(void);
+void ble_log_spi_out_ts_sync_stop(void);
+int ble_log_spi_out_printf(uint8_t source, const char *format, ...);
+int ble_log_spi_out_printf_enh(uint8_t source, uint8_t level, const char *tag, const char *format, ...);
+int ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len);
+void ble_log_spi_out_dump_all(void);
+void ble_log_spi_out_enable(bool enable);
+void ble_log_spi_out_flush(void);
+void ble_log_spi_out_le_audio_write(const uint8_t *addr, uint16_t len);
+
+#endif // __BT_SPI_OUT_H__
diff --git a/lib/bt/common/btc/core/btc_manage.c b/lib/bt/common/btc/core/btc_manage.c
index 52aa837b..e65e1079 100644
--- a/lib/bt/common/btc/core/btc_manage.c
+++ b/lib/bt/common/btc/core/btc_manage.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -16,6 +16,12 @@ void **btc_profile_cb_tab;
void esp_profile_cb_reset(void)
{
+ #if BTC_DYNAMIC_MEMORY == TRUE
+ if (btc_profile_cb_tab == NULL) {
+ return;
+ }
+ #endif
+
int i;
for (i = 0; i < BTC_PID_NUM; i++) {
@@ -25,6 +31,12 @@ void esp_profile_cb_reset(void)
int btc_profile_cb_set(btc_pid_t profile_id, void *cb)
{
+ #if BTC_DYNAMIC_MEMORY == TRUE
+ if (btc_profile_cb_tab == NULL) {
+ return -1;
+ }
+ #endif
+
if (profile_id < 0 || profile_id >= BTC_PID_NUM) {
return -1;
}
@@ -36,6 +48,12 @@ int btc_profile_cb_set(btc_pid_t profile_id, void *cb)
void *btc_profile_cb_get(btc_pid_t profile_id)
{
+ #if BTC_DYNAMIC_MEMORY == TRUE
+ if (btc_profile_cb_tab == NULL) {
+ return NULL;
+ }
+ #endif
+
if (profile_id < 0 || profile_id >= BTC_PID_NUM) {
return NULL;
}
diff --git a/lib/bt/common/btc/core/btc_task.c b/lib/bt/common/btc/core/btc_task.c
index 0f2b6bc0..c240004a 100644
--- a/lib/bt/common/btc/core/btc_task.c
+++ b/lib/bt/common/btc/core/btc_task.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -24,6 +24,8 @@
#include "btc_gattc.h"
#include "btc_gatt_common.h"
#include "btc_gap_ble.h"
+#include "btc_iso_ble.h"
+#include "btc_ble_cte.h"
#include "btc/btc_dm.h"
#include "bta/bta_gatt_api.h"
#if CLASSIC_BT_INCLUDED
@@ -42,9 +44,9 @@
#if (BTC_L2CAP_INCLUDED == TRUE)
#include "btc_l2cap.h"
#endif /* #if (BTC_L2CAP_INCLUDED == TRUE) */
-#if (BTC_SDP_INCLUDED == TRUE)
+#if (BTC_SDP_COMMON_INCLUDED == TRUE)
#include "btc_sdp.h"
-#endif /* #if (BTC_SDP_INCLUDED == TRUE) */
+#endif /* #if (BTC_SDP_COMMON_INCLUDED == TRUE) */
#if BTC_HF_INCLUDED
#include "btc_hf_ag.h"
#endif/* #if BTC_HF_INCLUDED */
@@ -57,6 +59,9 @@
#if BTC_HH_INCLUDED == TRUE
#include "btc_hh.h"
#endif /* BTC_HH_INCLUDED */
+#if BTC_PBA_CLIENT_INCLUDED
+#include "btc_pba_client.h"
+#endif
#endif /* #if CLASSIC_BT_INCLUDED */
#endif
@@ -69,6 +74,12 @@
#include "btc_ble_mesh_prov.h"
#include "btc_ble_mesh_health_model.h"
#include "btc_ble_mesh_config_model.h"
+#include "btc_ble_mesh_generic_model.h"
+#include "btc_ble_mesh_lighting_model.h"
+#include "btc_ble_mesh_sensor_model.h"
+#include "btc_ble_mesh_time_scene_model.h"
+#if CONFIG_BLE_MESH_V11_SUPPORT
+#include "btc_ble_mesh_mbt_model.h"
#include "btc_ble_mesh_agg_model.h"
#include "btc_ble_mesh_brc_model.h"
#include "btc_ble_mesh_df_model.h"
@@ -78,11 +89,7 @@
#include "btc_ble_mesh_rpr_model.h"
#include "btc_ble_mesh_sar_model.h"
#include "btc_ble_mesh_srpl_model.h"
-#include "btc_ble_mesh_generic_model.h"
-#include "btc_ble_mesh_lighting_model.h"
-#include "btc_ble_mesh_sensor_model.h"
-#include "btc_ble_mesh_time_scene_model.h"
-#include "btc_ble_mesh_mbt_model.h"
+#endif /* CONFIG_BLE_MESH_V11_SUPPORT */
#endif /* #if CONFIG_BLE_MESH */
#define BTC_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
@@ -138,9 +145,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
#if (BTC_L2CAP_INCLUDED == TRUE)
[BTC_PID_L2CAP] = {btc_l2cap_call_handler, btc_l2cap_cb_handler },
#endif /* #if (BTC_L2CAP_INCLUDED == TRUE) */
-#if (BTC_SDP_INCLUDED == TRUE)
+#if (BTC_SDP_COMMON_INCLUDED == TRUE)
[BTC_PID_SDP] = {btc_sdp_call_handler, btc_sdp_cb_handler },
-#endif /* #if (BTC_SDP_INCLUDED == TRUE) */
+#endif /* #if (BTC_SDP_COMMON_INCLUDED == TRUE) */
#if BTC_HF_INCLUDED
[BTC_PID_HF] = {btc_hf_call_handler, btc_hf_cb_handler},
#endif /* #if BTC_HF_INCLUDED */
@@ -153,6 +160,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
#if BTC_HH_INCLUDED
[BTC_PID_HH] = {btc_hh_call_handler, btc_hh_cb_handler },
#endif
+#if BTC_PBA_CLIENT_INCLUDED
+ [BTC_PID_PBA_CLIENT] = {btc_pba_client_call_handler, btc_pba_client_cb_handler},
+#endif
#endif /* #if CLASSIC_BT_INCLUDED */
#endif
#if CONFIG_BLE_MESH
@@ -208,7 +218,7 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
[BTC_PID_RPR_CLIENT] = {btc_ble_mesh_rpr_client_call_handler, btc_ble_mesh_rpr_client_cb_handler },
#endif /* CONFIG_BLE_MESH_RPR_CLI */
#if CONFIG_BLE_MESH_RPR_SRV
- [BTC_PID_RPR_SERVER] = {NULL, btc_ble_mesh_rpr_server_cb_handler },
+ [BTC_PID_RPR_SERVER] = {btc_ble_mesh_rpr_server_call_handler, btc_ble_mesh_rpr_server_cb_handler },
#endif /* CONFIG_BLE_MESH_RPR_SRV */
#if CONFIG_BLE_MESH_SAR_CLI
[BTC_PID_SAR_CLIENT] = {btc_ble_mesh_sar_client_call_handler, btc_ble_mesh_sar_client_cb_handler },
@@ -252,10 +262,16 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
#if CONFIG_BLE_MESH_MBT_SRV
[BTC_PID_MBT_SERVER] = {btc_ble_mesh_mbt_server_call_handler, btc_ble_mesh_mbt_server_cb_handler },
#endif /* CONFIG_BLE_MESH_MBT_SRV */
-#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT
+#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50
[BTC_PID_BLE_MESH_BLE_COEX] = {btc_ble_mesh_ble_call_handler, btc_ble_mesh_ble_cb_handler },
-#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */
+#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 */
#endif /* #if CONFIG_BLE_MESH */
+#if (BLE_FEAT_ISO_EN == TRUE)
+ [BTC_PID_ISO_BLE] = {btc_iso_ble_call_handler, btc_iso_ble_cb_handler },
+#endif // #if (BLE_FEAT_ISO_EN == TRUE)
+#if (BLE_FEAT_CTE_EN == TRUE)
+ [BTC_PID_BLE_CTE] = {btc_ble_cte_call_handler, btc_ble_cte_cb_handler },
+#endif // #if (BLE_FEAT_CTE_EN == TRUE)
};
/*****************************************************************************
@@ -295,8 +311,8 @@ static bt_status_t btc_task_post(btc_msg_t *msg, uint32_t timeout)
/**
* transfer an message to another module in the different task.
* @param msg message
- * @param arg paramter
- * @param arg_len length of paramter
+ * @param arg parameter
+ * @param arg_len length of parameter
* @param copy_func deep copy function
* @param free_func deep free function
* @return BT_STATUS_SUCCESS: success
@@ -342,7 +358,7 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg
}
/**
- * transfer an message to another module in tha same task.
+ * transfer an message to another module in the same task.
* @param msg message
* @return BT_STATUS_SUCCESS: success
* others: fail
@@ -380,7 +396,8 @@ static void btc_deinit_mem(void) {
btc_profile_cb_tab = NULL;
}
-#if (BLE_INCLUDED == TRUE)
+#if (BLE_42_FEATURE_SUPPORT == TRUE)
+#if (BLE_42_ADV_EN == TRUE)
if (gl_bta_adv_data_ptr) {
osi_free(gl_bta_adv_data_ptr);
gl_bta_adv_data_ptr = NULL;
@@ -390,7 +407,8 @@ static void btc_deinit_mem(void) {
osi_free(gl_bta_scan_rsp_data_ptr);
gl_bta_scan_rsp_data_ptr = NULL;
}
-#endif ///BLE_INCLUDED == TRUE
+#endif // #if (BLE_42_ADV_EN == TRUE)
+#endif // BLE_42_FEATURE_SUPPORT
#if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE
if (btc_creat_tab_env_ptr) {
@@ -442,7 +460,9 @@ static bt_status_t btc_init_mem(void) {
}
memset((void *)btc_profile_cb_tab, 0, sizeof(void *) * BTC_PID_NUM);
-#if (BLE_INCLUDED == TRUE)
+#if BTC_DYNAMIC_MEMORY == TRUE
+#if (BLE_42_FEATURE_SUPPORT == TRUE)
+#if (BLE_42_ADV_EN == TRUE)
if ((gl_bta_adv_data_ptr = (tBTA_BLE_ADV_DATA *)osi_malloc(sizeof(tBTA_BLE_ADV_DATA))) == NULL) {
goto error_exit;
}
@@ -452,7 +472,9 @@ static bt_status_t btc_init_mem(void) {
goto error_exit;
}
memset((void *)gl_bta_scan_rsp_data_ptr, 0, sizeof(tBTA_BLE_ADV_DATA));
-#endif ///BLE_INCLUDED == TRUE
+#endif // #if (BLE_42_ADV_EN == TRUE)
+#endif // (BLE_42_FEATURE_SUPPORT == TRUE)
+#endif // BTC_DYNAMIC_MEMORY == TRUE
#if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE
if ((btc_creat_tab_env_ptr = (esp_btc_creat_tab_t *)osi_malloc(sizeof(esp_btc_creat_tab_t))) == NULL) {
@@ -514,21 +536,30 @@ bt_status_t btc_init(void)
return BT_STATUS_NOMEM;
}
#endif
+#if BTC_GAP_BT_INCLUDED
+ btc_gap_bt_init();
+#endif
#if (BLE_INCLUDED == TRUE)
btc_gap_callback_init();
+#if (BLE_FEAT_ISO_EN == TRUE)
+ btc_iso_callback_init();
+#endif // #if (BLE_FEAT_ISO_EN == TRUE)
+#if (BLE_FEAT_CTE_EN == TRUE)
+ btc_cte_callback_init();
+#endif // #if (BLE_FEAT_CTE_EN == TRUE)
btc_gap_ble_init();
#endif ///BLE_INCLUDED == TRUE
-#if SCAN_QUEUE_CONGEST_CHECK
- btc_adv_list_init();
-#endif
/* TODO: initial the profile_tab */
return BT_STATUS_SUCCESS;
}
void btc_deinit(void)
{
+#if BTC_GAP_BT_INCLUDED
+ btc_gap_bt_deinit();
+#endif
#if BTC_DYNAMIC_MEMORY
btc_deinit_mem();
#endif
@@ -538,18 +569,6 @@ void btc_deinit(void)
#if (BLE_INCLUDED == TRUE)
btc_gap_ble_deinit();
#endif ///BLE_INCLUDED == TRUE
-#if SCAN_QUEUE_CONGEST_CHECK
- btc_adv_list_deinit();
-#endif
-}
-
-bool btc_check_queue_is_congest(void)
-{
- if (osi_thread_queue_wait_size(btc_thread, 0) >= BT_QUEUE_CONGEST_SIZE) {
- return true;
- }
-
- return false;
}
int get_btc_work_queue_size(void)
diff --git a/lib/bt/common/btc/include/btc/btc_task.h b/lib/bt/common/btc/include/btc/btc_task.h
index 232186b5..04365582 100644
--- a/lib/bt/common/btc/include/btc/btc_task.h
+++ b/lib/bt/common/btc/include/btc/btc_task.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -67,6 +67,9 @@ typedef enum {
#if (BTC_HF_CLIENT_INCLUDED == TRUE)
BTC_PID_HF_CLIENT,
#endif /* BTC_HF_CLIENT_INCLUDED */
+#if (BTC_PBA_CLIENT_INCLUDED == TRUE)
+ BTC_PID_PBA_CLIENT,
+#endif /* BTC_PBA_CLIENT_INCLUDED */
#endif /* CLASSIC_BT_INCLUDED */
#if CONFIG_BLE_MESH
BTC_PID_PROV,
@@ -105,6 +108,12 @@ typedef enum {
BTC_PID_MBT_SERVER,
BTC_PID_BLE_MESH_BLE_COEX,
#endif /* CONFIG_BLE_MESH */
+#if (BLE_FEAT_ISO_EN == TRUE)
+ BTC_PID_ISO_BLE,
+#endif // #if (BLE_FEAT_ISO_EN == TRUE)
+#if (BLE_FEAT_CTE_EN == TRUE)
+ BTC_PID_BLE_CTE,
+#endif // #if (BLE_FEAT_CTE_EN == TRUE)
BTC_PID_NUM,
} btc_pid_t; //btc profile id
@@ -123,8 +132,8 @@ extern "C" {
/**
* transfer an message to another module in the different task.
* @param msg message
- * @param arg paramter
- * @param arg_len length of paramter
+ * @param arg parameter
+ * @param arg_len length of parameter
* @param copy_func deep copy function
* @param free_func deep free function
* @return BT_STATUS_SUCCESS: success
@@ -134,7 +143,7 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg
btc_arg_deep_free_t free_func);
/**
- * transfer an message to another module in tha same task.
+ * transfer an message to another module in the same task.
* @param msg message
* @return BT_STATUS_SUCCESS: success
* others: fail
@@ -143,7 +152,6 @@ bt_status_t btc_inter_profile_call(btc_msg_t *msg);
bt_status_t btc_init(void);
void btc_deinit(void);
-bool btc_check_queue_is_congest(void);
int get_btc_work_queue_size(void);
/**
diff --git a/lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c b/lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c
index 47022992..f0c0aa4a 100644
--- a/lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c
+++ b/lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -160,20 +160,31 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
if (p_data->req_data.p_data->write_req.is_prep) {
tBTA_GATT_STATUS status = GATT_SUCCESS;
- if (blufi_env.prepare_buf == NULL) {
- blufi_env.prepare_buf = osi_malloc(BLUFI_PREPAIR_BUF_MAX_SIZE);
- blufi_env.prepare_len = 0;
- if (blufi_env.prepare_buf == NULL) {
- BLUFI_TRACE_ERROR("Blufi prep no mem\n");
- status = GATT_NO_RESOURCES;
+ do {
+ if (p_data->req_data.p_data->write_req.offset > BLUFI_PREPARE_BUF_MAX_SIZE) {
+ status = ESP_GATT_INVALID_OFFSET;
+ break;
}
- } else {
- if (p_data->req_data.p_data->write_req.offset > BLUFI_PREPAIR_BUF_MAX_SIZE) {
- status = GATT_INVALID_OFFSET;
- } else if ((p_data->req_data.p_data->write_req.offset + p_data->req_data.p_data->write_req.len) > BLUFI_PREPAIR_BUF_MAX_SIZE) {
- status = GATT_INVALID_ATTR_LEN;
+
+ if ((p_data->req_data.p_data->write_req.offset + p_data->req_data.p_data->write_req.len) > BLUFI_PREPARE_BUF_MAX_SIZE) {
+ status = ESP_GATT_INVALID_ATTR_LEN;
+ break;
}
- }
+
+ if (blufi_env.prepare_buf == NULL) {
+ if (p_data->req_data.p_data->write_req.offset != 0) {
+ status = GATT_INVALID_OFFSET;
+ break;
+ }
+ blufi_env.prepare_buf = osi_malloc(BLUFI_PREPARE_BUF_MAX_SIZE);
+ blufi_env.prepare_len = 0;
+ if (blufi_env.prepare_buf == NULL) {
+ BLUFI_TRACE_ERROR("Blufi prep no mem\n");
+ status = GATT_NO_RESOURCES;
+ break;
+ }
+ }
+ } while (0);
memset(&rsp, 0, sizeof(tGATTS_RSP));
rsp.attr_value.handle = p_data->req_data.p_data->write_req.handle;
diff --git a/lib/bt/common/btc/profile/esp/blufi/blufi_prf.c b/lib/bt/common/btc/profile/esp/blufi/blufi_prf.c
index 2c7be212..81bb0308 100644
--- a/lib/bt/common/btc/profile/esp/blufi/blufi_prf.c
+++ b/lib/bt/common/btc/profile/esp/blufi/blufi_prf.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -95,7 +95,29 @@ void btc_blufi_report_error(esp_blufi_error_state_t state)
void btc_blufi_recv_handler(uint8_t *data, int len)
{
+ if (len < sizeof(struct blufi_hdr)) {
+ BTC_TRACE_ERROR("%s invalid data length: %d", __func__, len);
+ btc_blufi_report_error(ESP_BLUFI_DATA_FORMAT_ERROR);
+ return;
+ }
+
struct blufi_hdr *hdr = (struct blufi_hdr *)data;
+
+ // Verify if the received data length matches the expected length based on the BLUFI protocol
+ int target_data_len;
+
+ if (BLUFI_FC_IS_CHECK(hdr->fc)) {
+ target_data_len = hdr->data_len + 4 + 2; // Data + (Type + Frame Control + Sequence Number + Data Length) + Checksum
+ } else {
+ target_data_len = hdr->data_len + 4; // Data + (Type + Frame Control + Sequence Number + Data Length)
+ }
+
+ if (len != target_data_len) {
+ BTC_TRACE_ERROR("%s: Invalid data length: %d, expected: %d", __func__, len, target_data_len);
+ btc_blufi_report_error(ESP_BLUFI_DATA_FORMAT_ERROR);
+ return;
+ }
+
uint16_t checksum, checksum_pkt;
int ret;
diff --git a/lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h b/lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h
index e85ad73d..a7f4f292 100644
--- a/lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h
+++ b/lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h
@@ -36,7 +36,9 @@ typedef struct {
UINT32 trans_id;
UINT8 congest;
UINT16 frag_size;
+// Deprecated: This macro will be removed in the future
#define BLUFI_PREPAIR_BUF_MAX_SIZE 1024
+#define BLUFI_PREPARE_BUF_MAX_SIZE 1024
uint8_t *prepare_buf;
int prepare_len;
/* Control reference */
diff --git a/lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h b/lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h
index db2203b1..862f7bf0 100644
--- a/lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h
+++ b/lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h
@@ -44,6 +44,7 @@ void esp_blufi_gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *a
/* Initialise gatt server */
int esp_blufi_gatt_svr_init(void);
+int esp_blufi_gatt_svr_deinit(void);
void esp_blufi_btc_init(void);
void esp_blufi_btc_deinit(void);
#endif
diff --git a/lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c b/lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c
index 67a83951..d40a4f4c 100644
--- a/lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c
+++ b/lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -124,7 +124,31 @@ static size_t write_value(uint16_t conn_handle, uint16_t attr_handle,
}
}
- btc_blufi_recv_handler(&ctxt->om->om_data[0], ctxt->om->om_len);
+ /* Data may come in linked om. So retrieve all data */
+ if (SLIST_NEXT(ctxt->om, om_next) != NULL) {
+ uint8_t *fw_buf = (uint8_t *)malloc(517 * sizeof(uint8_t));
+ memset(fw_buf, 0x0, 517);
+
+ memcpy(fw_buf, &ctxt->om->om_data[0], ctxt->om->om_len);
+ struct os_mbuf *last;
+ last = ctxt->om;
+ uint32_t offset = ctxt->om->om_len;
+
+ while (SLIST_NEXT(last, om_next) != NULL) {
+ struct os_mbuf *temp = SLIST_NEXT(last, om_next);
+ memcpy(fw_buf + offset , &temp->om_data[0], temp->om_len);
+ offset += temp->om_len;
+ last = SLIST_NEXT(last, om_next);
+ temp = NULL;
+ }
+ btc_blufi_recv_handler(fw_buf, offset);
+
+ free(fw_buf);
+ }
+ else {
+ btc_blufi_recv_handler(&ctxt->om->om_data[0], ctxt->om->om_len);
+ }
+
rc = ble_hs_mbuf_to_flat(ctxt->om, value->buf->om_data,
value->buf->om_len, &len);
if (rc != 0) {
@@ -216,6 +240,32 @@ static void init_gatt_values(void)
}
+static void deinit_gatt_values(void)
+{
+ int i = 0;
+ const struct ble_gatt_svc_def *svc;
+ const struct ble_gatt_chr_def *chr;
+ const struct ble_gatt_dsc_def *dsc;
+
+ for (svc = gatt_svr_svcs; svc && svc->uuid; svc++) {
+ for (chr = svc->characteristics; chr && chr->uuid; chr++) {
+ if (i < SERVER_MAX_VALUES && gatt_values[i].buf != NULL) {
+ os_mbuf_free(gatt_values[i].buf); /* Free the buffer */
+ gatt_values[i].buf = NULL; /* Nullify the pointer to avoid dangling references */
+ }
+ ++i;
+
+ for (dsc = chr->descriptors; dsc && dsc->uuid; dsc++) {
+ if (i < SERVER_MAX_VALUES && gatt_values[i].buf != NULL) {
+ os_mbuf_free(gatt_values[i].buf); /* Free the buffer */
+ gatt_values[i].buf = NULL; /* Nullify the pointer to avoid dangling references */
+ }
+ ++i;
+ }
+ }
+ }
+}
+
int esp_blufi_gatt_svr_init(void)
{
int rc;
@@ -236,6 +286,18 @@ int esp_blufi_gatt_svr_init(void)
return 0;
}
+int esp_blufi_gatt_svr_deinit(void)
+{
+ deinit_gatt_values();
+
+ ble_gatts_free_svcs();
+ /* Deinitialize BLE GATT and GAP services */
+ ble_svc_gatt_deinit();
+ ble_svc_gap_deinit();
+
+ return 0;
+}
+
static int
esp_blufi_gap_event(struct ble_gap_event *event, void *arg)
{
@@ -418,8 +480,10 @@ uint8_t esp_blufi_init(void)
void esp_blufi_deinit(void)
{
blufi_env.enabled = false;
- btc_msg_t msg;
esp_blufi_cb_param_t param;
+ btc_msg_t msg;
+ memset (&msg, 0x0, sizeof (msg));
+ msg.sig = BTC_SIG_API_CB;
msg.pid = BTC_PID_BLUFI;
msg.act = ESP_BLUFI_EVENT_DEINIT_FINISH;
param.deinit_finish.state = ESP_BLUFI_DEINIT_OK;
@@ -447,7 +511,10 @@ void esp_blufi_disconnect(void)
ble_gap_terminate(blufi_env.conn_id, BLE_ERR_REM_USER_CONN_TERM);
}
-void esp_blufi_adv_stop(void) {}
+void esp_blufi_adv_stop(void)
+{
+ ble_gap_adv_stop();
+}
void esp_blufi_send_encap(void *arg)
{
diff --git a/lib/bt/common/hci_log/bt_hci_log.c b/lib/bt/common/hci_log/bt_hci_log.c
index e35bf1a7..ef0d2294 100644
--- a/lib/bt/common/hci_log/bt_hci_log.c
+++ b/lib/bt/common/hci_log/bt_hci_log.c
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -124,6 +124,11 @@ static char IRAM_ATTR *bt_data_type_to_str(uint8_t data_type)
// self-defining data
tag = "S";
break;
+ case HCI_LOG_DATA_TYPE_ISO_DATA:
+ // 5.2 iso data
+ tag = "I";
+ break;
+ break;
default:
// unknown data type
tag = "U";
@@ -305,19 +310,27 @@ void bt_hci_log_data_show(bt_hci_log_t *p_hci_log_ctl)
osi_mutex_unlock(&mutex_lock);
}
+static bool enable_hci_log_flag = true;
+void bt_hci_log_record_hci_enable(bool enable)
+{
+ enable_hci_log_flag = enable;
+}
esp_err_t IRAM_ATTR bt_hci_log_record_hci_data(uint8_t data_type, uint8_t *data, uint8_t data_len)
{
+ if (!enable_hci_log_flag) return ESP_OK;
return bt_hci_log_record_data(&g_bt_hci_log_data_ctl, NULL, data_type, data, data_len);
}
esp_err_t IRAM_ATTR bt_hci_log_record_custom_data(char *string, uint8_t *data, uint8_t data_len)
{
+ if (!enable_hci_log_flag) return ESP_OK;
return bt_hci_log_record_data(&g_bt_hci_log_data_ctl, string, HCI_LOG_DATA_TYPE_SELF_DEFINE, data, data_len);
}
esp_err_t IRAM_ATTR bt_hci_log_record_hci_adv(uint8_t data_type, uint8_t *data, uint8_t data_len)
{
+ if (!enable_hci_log_flag) return ESP_OK;
return bt_hci_log_record_data(&g_bt_hci_log_adv_ctl, NULL, data_type, data, data_len);
}
diff --git a/lib/bt/common/hci_log/include/hci_log/bt_hci_log.h b/lib/bt/common/hci_log/include/hci_log/bt_hci_log.h
index 512a307e..2c11729f 100644
--- a/lib/bt/common/hci_log/include/hci_log/bt_hci_log.h
+++ b/lib/bt/common/hci_log/include/hci_log/bt_hci_log.h
@@ -21,6 +21,7 @@ extern "C" {
#define HCI_LOG_DATA_TYPE_ADV (5)
#define HCI_LOG_DATA_TYPE_SELF_DEFINE (6)
#define HCI_LOG_DATA_TYPE_C2H_ACL (7)
+#define HCI_LOG_DATA_TYPE_ISO_DATA (8)
/**
*
diff --git a/lib/bt/common/include/bt_common.h b/lib/bt/common/include/bt_common.h
index f3c5ba0e..300bbc6d 100644
--- a/lib/bt/common/include/bt_common.h
+++ b/lib/bt/common/include/bt_common.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -46,6 +46,7 @@
#define OSI_INITIAL_TRACE_LEVEL UC_BT_LOG_OSI_TRACE_LEVEL
#define BLUFI_INITIAL_TRACE_LEVEL UC_BT_LOG_BLUFI_TRACE_LEVEL
+// MEMORY
#if UC_BT_BLE_DYNAMIC_ENV_MEMORY
#define BT_BLE_DYNAMIC_ENV_MEMORY TRUE
#define BTC_DYNAMIC_MEMORY TRUE
@@ -64,12 +65,39 @@
#define BT_BLE_DYNAMIC_ENV_MEMORY FALSE
#endif
+#if UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST
+#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST TRUE
+#else
+#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST FALSE
+#endif
+
+#if UC_BT_ABORT_WHEN_ALLOCATION_FAILS
+#define HEAP_ALLOCATION_FAILS_ABORT TRUE
+#else
+#define HEAP_ALLOCATION_FAILS_ABORT FALSE
+#endif
+
+// HCI LOG
#if UC_BT_HCI_LOG_DEBUG_EN
#define BT_HCI_LOG_INCLUDED UC_BT_HCI_LOG_DEBUG_EN
#else
#define BT_HCI_LOG_INCLUDED FALSE
#endif
+// HCI LOG TO SPI
+#if UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED
+#define BT_BLE_LOG_SPI_OUT_HCI_ENABLED UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED
+#else
+#define BT_BLE_LOG_SPI_OUT_HCI_ENABLED FALSE
+#endif
+
+// BLURDROID LOG TO SPI
+#if UC_BT_BLE_LOG_SPI_OUT_HOST_ENABLED
+#define BT_BLE_LOG_SPI_OUT_HOST_ENABLED UC_BT_BLE_LOG_SPI_OUT_HOST_ENABLED
+#else
+#define BT_BLE_LOG_SPI_OUT_HOST_ENABLED FALSE
+#endif
+
#if UC_BT_HCI_LOG_DATA_BUFFER_SIZE
#define HCI_LOG_DATA_BUFFER_SIZE UC_BT_HCI_LOG_DATA_BUFFER_SIZE
#else
diff --git a/lib/bt/common/include/bt_user_config.h b/lib/bt/common/include/bt_user_config.h
index 029766b7..5632b5fe 100644
--- a/lib/bt/common/include/bt_user_config.h
+++ b/lib/bt/common/include/bt_user_config.h
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -100,19 +100,46 @@
#define UC_BT_BLUFI_ENABLE FALSE
#endif
-//MEMORY DEBUG
+//MEMORY
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG
#define UC_BT_BLUEDROID_MEM_DEBUG TRUE
#else
#define UC_BT_BLUEDROID_MEM_DEBUG FALSE
#endif
+#ifdef CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST
+#define UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST
+#else
+#define UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST FALSE
+#endif
+
+#ifdef CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS
+#define UC_BT_ABORT_WHEN_ALLOCATION_FAILS CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS
+#else
+#define UC_BT_ABORT_WHEN_ALLOCATION_FAILS FALSE
+#endif
+
+//HCI LOG
#ifdef CONFIG_BT_HCI_LOG_DEBUG_EN
#define UC_BT_HCI_LOG_DEBUG_EN TRUE
#else
#define UC_BT_HCI_LOG_DEBUG_EN FALSE
#endif
+//HCI LOG TO SPI
+#ifdef CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED
+#define UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED TRUE
+#else
+#define UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED FALSE
+#endif
+
+//BLUEDROID LOG TO SPI
+#ifdef CONFIG_BT_BLE_LOG_SPI_OUT_HOST_ENABLED
+#define UC_BT_BLE_LOG_SPI_OUT_HOST_ENABLED TRUE
+#else
+#define UC_BT_BLE_LOG_SPI_OUT_HOST_ENABLED FALSE
+#endif
+
#ifdef CONFIG_BT_HCI_LOG_DATA_BUFFER_SIZE
#define UC_BT_HCI_LOG_DATA_BUFFER_SIZE CONFIG_BT_HCI_LOG_DATA_BUFFER_SIZE
#else
diff --git a/lib/bt/common/osi/allocator.c b/lib/bt/common/osi/allocator.c
index 4d10e10f..86fb705b 100644
--- a/lib/bt/common/osi/allocator.c
+++ b/lib/bt/common/osi/allocator.c
@@ -213,42 +213,30 @@ char *osi_strdup(const char *str)
void *osi_malloc_func(size_t size)
{
-#if HEAP_MEMORY_DEBUG
- void *p;
-#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
- p = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
-#else
- p = malloc(size);
-#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
- osi_mem_dbg_record(p, size, __func__, __LINE__);
+ void *p = osi_malloc_base(size);
+
+ if (size != 0 && p == NULL) {
+ OSI_TRACE_ERROR("malloc failed (caller=%p size=%u)\n", __builtin_return_address(0), size);
+#if HEAP_ALLOCATION_FAILS_ABORT
+ assert(0);
+#endif
+ }
+
return p;
-#else
-#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
- return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
-#else
- return malloc(size);
-#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
-#endif /* #if HEAP_MEMORY_DEBUG */
}
void *osi_calloc_func(size_t size)
{
-#if HEAP_MEMORY_DEBUG
- void *p;
-#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
- p = heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
-#else
- p = calloc(1, size);
-#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
- osi_mem_dbg_record(p, size, __func__, __LINE__);
+ void *p = osi_calloc_base(size);
+
+ if (size != 0 && p == NULL) {
+ OSI_TRACE_ERROR("calloc failed (caller=%p size=%u)\n", __builtin_return_address(0), size);
+#if HEAP_ALLOCATION_FAILS_ABORT
+ assert(0);
+#endif
+ }
+
return p;
-#else
-#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
- return heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
-#else
- return calloc(1, size);
-#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
-#endif /* #if HEAP_MEMORY_DEBUG */
}
void osi_free_func(void *ptr)
diff --git a/lib/bt/common/osi/include/osi/allocator.h b/lib/bt/common/osi/include/osi/allocator.h
index 579f2b2b..d9504053 100644
--- a/lib/bt/common/osi/include/osi/allocator.h
+++ b/lib/bt/common/osi/include/osi/allocator.h
@@ -29,6 +29,15 @@ void *osi_malloc_func(size_t size);
void *osi_calloc_func(size_t size);
void osi_free_func(void *ptr);
+// Memory alloc function without print and assertion
+#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
+#define osi_malloc_base(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
+#define osi_calloc_base(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
+#else
+#define osi_malloc_base(size) malloc((size))
+#define osi_calloc_base(size) calloc(1, (size))
+#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
+
#if HEAP_MEMORY_DEBUG
void osi_mem_dbg_init(void);
@@ -41,13 +50,10 @@ void osi_men_dbg_set_section_start(uint8_t index);
void osi_men_dbg_set_section_end(uint8_t index);
uint32_t osi_mem_dbg_get_max_size_section(uint8_t index);
-#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
#define osi_malloc(size) \
({ \
void *p; \
- p = heap_caps_malloc_prefer(size, 2, \
- MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, \
- MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \
+ p = osi_malloc_base(size); \
osi_mem_dbg_record(p, size, __func__, __LINE__); \
(void *)p; \
})
@@ -55,34 +61,11 @@ uint32_t osi_mem_dbg_get_max_size_section(uint8_t index);
#define osi_calloc(size) \
({ \
void *p; \
- p = heap_caps_calloc_prefer(1, size, 2, \
- MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, \
- MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \
- osi_mem_dbg_record(p, size, __func__, __LINE__); \
- (void *)p; \
-})
-
-#else
-
-#define osi_malloc(size) \
-({ \
- void *p; \
- p = malloc((size)); \
+ p = osi_calloc_base(size); \
osi_mem_dbg_record(p, size, __func__, __LINE__); \
(void *)p; \
})
-#define osi_calloc(size) \
-({ \
- void *p; \
- p = calloc(1, (size)); \
- osi_mem_dbg_record(p, size, __func__, __LINE__); \
- (void *)p; \
-})
-
-#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
-
-
#if 0
#define osi_malloc(size) \
do { \
@@ -122,13 +105,9 @@ do { \
#else
-#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
-#define osi_malloc(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
-#define osi_calloc(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
-#else
-#define osi_malloc(size) malloc((size))
-#define osi_calloc(size) calloc(1, (size))
-#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
+// Memory alloc function with print and assertion when fails
+#define osi_malloc(size) osi_malloc_func((size))
+#define osi_calloc(size) osi_calloc_func((size))
#define osi_free(p) free((p))
#endif /* HEAP_MEMORY_DEBUG */
diff --git a/lib/bt/common/osi/include/osi/fixed_pkt_queue.h b/lib/bt/common/osi/include/osi/fixed_pkt_queue.h
index f4235ca5..e121235e 100644
--- a/lib/bt/common/osi/include/osi/fixed_pkt_queue.h
+++ b/lib/bt/common/osi/include/osi/fixed_pkt_queue.h
@@ -76,4 +76,8 @@ void fixed_pkt_queue_unregister_dequeue(fixed_pkt_queue_t *queue);
void fixed_pkt_queue_process(fixed_pkt_queue_t *queue);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/lib/bt/common/osi/include/osi/hash_map.h b/lib/bt/common/osi/include/osi/hash_map.h
index fea1e021..a26eda61 100644
--- a/lib/bt/common/osi/include/osi/hash_map.h
+++ b/lib/bt/common/osi/include/osi/hash_map.h
@@ -20,6 +20,7 @@
#define _HASH_MAP_H_
#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
struct hash_map_t;
diff --git a/lib/bt/common/osi/pkt_queue.c b/lib/bt/common/osi/pkt_queue.c
index 81abd1f0..4c149be2 100644
--- a/lib/bt/common/osi/pkt_queue.c
+++ b/lib/bt/common/osi/pkt_queue.c
@@ -25,6 +25,7 @@ struct pkt_queue *pkt_queue_create(void)
}
if (osi_mutex_new(&queue->lock) != 0) {
osi_free(queue);
+ return NULL;
}
struct pkt_queue_header *p = &queue->header;
STAILQ_INIT(p);
diff --git a/lib/bt/common/osi/thread.c b/lib/bt/common/osi/thread.c
index f53eadb6..91bc7906 100644
--- a/lib/bt/common/osi/thread.c
+++ b/lib/bt/common/osi/thread.c
@@ -271,10 +271,10 @@ _err:
}
for (int i = 0; i < thread->work_queue_num; i++) {
- if (thread->work_queues[i]) {
+ if (thread->work_queues && thread->work_queues[i]) {
osi_work_queue_delete(thread->work_queues[i]);
+ thread->work_queues[i] = NULL;
}
- thread->work_queues[i] = NULL;
}
if (thread->work_queues) {
diff --git a/lib/bt/common/tinycrypt/AUTHORS b/lib/bt/common/tinycrypt/AUTHORS
new file mode 100644
index 00000000..bd1c1a1f
--- /dev/null
+++ b/lib/bt/common/tinycrypt/AUTHORS
@@ -0,0 +1,15 @@
+Architect:
+Rafael Misoczki <rafael.misoczki@intel.com>
+
+Open Source Maintainer:
+Constanza Heath <constanza.m.heath@intel.com>
+Rafael Misoczki <rafael.misoczki@intel.com>
+
+Contributors:
+Constanza Heath <constanza.m.heath@intel.com>
+Rafael Misoczki <rafael.misoczki@intel.com>
+Flavio Santes <flavio.santes@intel.com>
+Jarkko Sakkinen <jarkko.sakkinen@intel.com>
+Chris Morrison
+Marti Bolivar
+Colin Ian King
diff --git a/lib/bt/common/tinycrypt/LICENSE b/lib/bt/common/tinycrypt/LICENSE
new file mode 100644
index 00000000..b3c55243
--- /dev/null
+++ b/lib/bt/common/tinycrypt/LICENSE
@@ -0,0 +1,61 @@
+
+================================================================================
+
+ TinyCrypt Cryptographic Library
+
+================================================================================
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ - Neither the name of the Intel Corporation nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
+Copyright (c) 2014, Kenneth MacKay
+All rights reserved.
+
+https://github.com/kmackay/micro-ecc
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
diff --git a/lib/bt/common/tinycrypt/README b/lib/bt/common/tinycrypt/README
new file mode 100644
index 00000000..48bdf9ba
--- /dev/null
+++ b/lib/bt/common/tinycrypt/README
@@ -0,0 +1,70 @@
+
+================================================================================
+
+ TinyCrypt Cryptographic Library
+
+================================================================================
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ - Neither the name of the Intel Corporation nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+================================================================================
+
+Overview:
+
+The TinyCrypt Library provides an implementation for constrained devices of a
+minimal set of standard cryptography primitives.
+
+Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported
+cryptographic primitives and the limitations of TinyCrypt library. For usage,
+security and technicalities, please see the corresponding header file of each
+cryptographic primitive.
+
+================================================================================
+
+Organization:
+
+/lib: C source code of the cryptographic primitives.
+/lib/include/tinycrypt: C header files of the cryptographic primitives.
+/tests: Test vectors of the cryptographic primitives.
+/doc: Documentation of TinyCrypt.
+
+================================================================================
+
+Building:
+
+1) In Makefile.conf set:
+ - CFLAGS for compiler flags.
+ - CC for compiler.
+ - ENABLE_TESTS for enabling (true) or disabling (false) tests compilation.
+2) In lib/Makefile select the primitives required by your project.
+3) In tests/Makefile select the corresponding tests of the selected primitives.
+4) make
+5) run tests in tests/
+
+================================================================================
diff --git a/lib/bt/common/tinycrypt/VERSION b/lib/bt/common/tinycrypt/VERSION
new file mode 100644
index 00000000..a45be462
--- /dev/null
+++ b/lib/bt/common/tinycrypt/VERSION
@@ -0,0 +1 @@
+0.2.8
diff --git a/lib/bt/common/tinycrypt/documentation/tinycrypt.rst b/lib/bt/common/tinycrypt/documentation/tinycrypt.rst
new file mode 100644
index 00000000..356c099a
--- /dev/null
+++ b/lib/bt/common/tinycrypt/documentation/tinycrypt.rst
@@ -0,0 +1,352 @@
+
+TinyCrypt Cryptographic Library
+###############################
+Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+
+Overview
+********
+The TinyCrypt Library provides an implementation for targeting constrained devices
+with a minimal set of standard cryptography primitives, as listed below. To better
+serve applications targeting constrained devices, TinyCrypt implementations differ
+from the standard specifications (see the Important Remarks section for some
+important differences). Certain cryptographic primitives depend on other
+primitives, as mentioned in the list below.
+
+Aside from the Important Remarks section below, valuable information on the usage,
+security and technicalities of each cryptographic primitive are found in the
+corresponding header file.
+
+* SHA-256:
+
+ * Type of primitive: Hash function.
+ * Standard Specification: NIST FIPS PUB 180-4.
+ * Requires: --
+
+* HMAC-SHA256:
+
+ * Type of primitive: Message authentication code.
+ * Standard Specification: RFC 2104.
+ * Requires: SHA-256
+
+* HMAC-PRNG:
+
+ * Type of primitive: Pseudo-random number generator (256-bit strength).
+ * Standard Specification: NIST SP 800-90A.
+ * Requires: SHA-256 and HMAC-SHA256.
+
+* AES-128:
+
+ * Type of primitive: Block cipher.
+ * Standard Specification: NIST FIPS PUB 197.
+ * Requires: --
+
+* AES-CBC mode:
+
+ * Type of primitive: Encryption mode of operation.
+ * Standard Specification: NIST SP 800-38A.
+ * Requires: AES-128.
+
+* AES-CTR mode:
+
+ * Type of primitive: Encryption mode of operation.
+ * Standard Specification: NIST SP 800-38A.
+ * Requires: AES-128.
+
+* AES-CMAC mode:
+
+ * Type of primitive: Message authentication code.
+ * Standard Specification: NIST SP 800-38B.
+ * Requires: AES-128.
+
+* AES-CCM mode:
+
+ * Type of primitive: Authenticated encryption.
+ * Standard Specification: NIST SP 800-38C.
+ * Requires: AES-128.
+
+* CTR-PRNG:
+
+ * Type of primitive: Pseudo-random number generator (128-bit strength).
+ * Standard Specification: NIST SP 800-90A.
+ * Requires: AES-128.
+
+* ECC-DH:
+
+ * Type of primitive: Key exchange based on curve NIST p-256.
+ * Standard Specification: RFC 6090.
+ * Requires: ECC auxiliary functions (ecc.h/c).
+
+* ECC-DSA:
+
+ * Type of primitive: Digital signature based on curve NIST p-256.
+ * Standard Specification: RFC 6090.
+ * Requires: ECC auxiliary functions (ecc.h/c).
+
+Design Goals
+************
+
+* Minimize the code size of each cryptographic primitive. This means minimize
+ the size of a platform-independent implementation, as presented in TinyCrypt.
+ Note that various applications may require further features, optimizations with
+ respect to other metrics and countermeasures for particular threats. These
+ peculiarities would increase the code size and thus are not considered here.
+
+* Minimize the dependencies among the cryptographic primitives. This means
+ that it is unnecessary to build and allocate object code for more primitives
+ than the ones strictly required by the intended application. In other words,
+ one can select and compile only the primitives required by the application.
+
+
+Important Remarks
+*****************
+
+The cryptographic implementations in TinyCrypt library have some limitations.
+Some of these limitations are inherent to the cryptographic primitives
+themselves, while others are specific to TinyCrypt. These limitations were accepted
+in order to meet its design goals (in special, minimal code size) and to better
+serve applications targeting constrained devices in general. Some of these
+limitations are discussed in-depth below.
+
+General Remarks
+***************
+
+* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the
+ variety of side-channel attacks, many of them only relevant to certain
+ platforms. In this sense, instead of penalizing all library users with
+ side-channel countermeasures such as increasing the overall code size,
+ TinyCrypt only implements certain generic timing-attack countermeasures.
+
+Specific Remarks
+****************
+
+* SHA-256:
+
+ * The number of bits_hashed in the state is not checked for overflow. Note
+ however that this will only be a problem if you intend to hash more than
+ 2^64 bits, which is an extremely large window.
+
+* HMAC:
+
+ * The HMAC verification process is assumed to be performed by the application.
+ This compares the computed tag with some given tag.
+ Note that conventional memory-comparison methods (such as memcmp function)
+ might be vulnerable to timing attacks; thus be sure to use a constant-time
+ memory comparison function (such as compare_constant_time
+ function provided in lib/utils.c).
+
+ * The tc_hmac_final function, responsible for computing the message tag,
+ cleans the state context before exiting. Thus, applications do not need to
+ clean the TCHmacState_t ctx after calling tc_hmac_final. This should not
+ be changed in future versions of the library as there are applications
+ currently relying on this good-practice/feature of TinyCrypt.
+
+* HMAC-PRNG:
+
+ * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed.
+ PRNGs only stretch the seed into a seemingly random output of arbitrary
+ length. The security of the output is exactly equal to the
+ unpredictability of the seed.
+
+ * NIST SP 800-90A requires three items as seed material in the initialization
+ step: entropy seed, personalization and a nonce (which is not implemented).
+ TinyCrypt requires the personalization byte array and automatically creates
+ the entropy seed using a mandatory call to the re-seed function.
+
+* AES-128:
+
+ * The current implementation does not support other key-lengths (such as 256
+ bits). Note that if you need AES-256, it doesn't sound as though your
+ application is running in a constrained environment. AES-256 requires keys
+ twice the size as for AES-128, and the key schedule is 40% larger.
+
+* CTR mode:
+
+ * The AES-CTR mode limits the size of a data message they encrypt to 2^32
+ blocks. If you need to encrypt larger data sets, your application would
+ need to replace the key after 2^32 block encryptions.
+
+* CTR-PRNG:
+
+ * Before using CTR-PRNG, you *must* find an entropy source to produce a seed.
+ PRNGs only stretch the seed into a seemingly random output of arbitrary
+ length. The security of the output is exactly equal to the
+ unpredictability of the seed.
+
+* CBC mode:
+
+ * TinyCrypt CBC decryption assumes that the iv and the ciphertext are
+ contiguous (as produced by TinyCrypt CBC encryption). This allows for a
+ very efficient decryption algorithm that would not otherwise be possible.
+
+* CMAC mode:
+
+ * AES128-CMAC mode of operation offers 64 bits of security against collision
+ attacks. Note however that an external attacker cannot generate the tags
+ him/herself without knowing the MAC key. In this sense, to attack the
+ collision property of AES128-CMAC, an external attacker would need the
+ cooperation of the legal user to produce an exponentially high number of
+ tags (e.g. 2^64) to finally be able to look for collisions and benefit
+ from them. As an extra precaution, the current implementation allows to at
+ most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup
+ (allowing a new key to be set), as suggested in Appendix B of SP 800-38B.
+
+* CCM mode:
+
+ * There are a few tradeoffs for the selection of the parameters of CCM mode.
+ In special, there is a tradeoff between the maximum number of invocations
+ of CCM under a given key and the maximum payload length for those
+ invocations. Both things are related to the parameter 'q' of CCM mode. The
+ maximum number of invocations of CCM under a given key is determined by
+ the nonce size, which is: 15-q bytes. The maximum payload length for those
+ invocations is defined as 2^(8q) bytes.
+
+ To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2,
+ which is a quite reasonable choice for constrained applications. The
+ implications of this choice are:
+
+ The nonce size is: 13 bytes.
+
+ The maximum payload length is: 2^16 bytes = 65 KB.
+
+ The mac size parameter is an important parameter to estimate the security
+ against collision attacks (that aim at finding different messages that
+ produce the same authentication tag). TinyCrypt CCM implementation
+ accepts any even integer between 4 and 16, as suggested in SP 800-38C.
+
+ * TinyCrypt CCM implementation accepts associated data of any length between
+ 0 and (2^16 - 2^8) = 65280 bytes.
+
+ * TinyCrypt CCM implementation accepts:
+
+ * Both non-empty payload and associated data (it encrypts and
+ authenticates the payload and only authenticates the associated data);
+
+ * Non-empty payload and empty associated data (it encrypts and
+ authenticates the payload);
+
+ * Non-empty associated data and empty payload (it degenerates to an
+ authentication-only mode on the associated data).
+
+ * RFC-3610, which also specifies CCM, presents a few relevant security
+ suggestions, such as: it is recommended for most applications to use a
+ mac size greater than 8. Besides, it is emphasized that the usage of the
+ same nonce for two different messages which are encrypted with the same
+ key obviously destroys the security properties of CCM mode.
+
+* ECC-DH and ECC-DSA:
+
+ * TinyCrypt ECC implementation is based on micro-ecc (see
+ https://github.com/kmackay/micro-ecc). In the original micro-ecc
+ documentation, there is an important remark about the way integers are
+ represented:
+
+ "Integer representation: To reduce code size, all large integers are
+ represented using little-endian words - so the least significant word is
+ first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()'
+ functions to convert between the native integer representation and the
+ standardized octet representation."
+
+ Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32},
+ {95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli)
+ consisting of 4 unsigned integers (as an example).
+
+ * A cryptographically-secure PRNG function must be set (using uECC_set_rng())
+ before calling uECC_make_key() or uECC_sign().
+
+Examples of Applications
+************************
+It is possible to do useful cryptography with only the given small set of
+primitives. With this list of primitives it becomes feasible to support a range
+of cryptography usages:
+
+ * Measurement of code, data structures, and other digital artifacts (SHA256);
+
+ * Generate commitments (SHA256);
+
+ * Construct keys (HMAC-SHA256);
+
+ * Extract entropy from strings containing some randomness (HMAC-SHA256);
+
+ * Construct random mappings (HMAC-SHA256);
+
+ * Construct nonces and challenges (HMAC-PRNG, CTR-PRNG);
+
+ * Authenticate using a shared secret (HMAC-SHA256);
+
+ * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG);
+
+ * Authenticated encryption (AES-128 + AES-CCM);
+
+ * Key-exchange (EC-DH);
+
+ * Digital signature (EC-DSA);
+
+Test Vectors
+************
+
+The library provides a test program for each cryptographic primitive (see 'test'
+folder). Besides illustrating how to use the primitives, these tests evaluate
+the correctness of the implementations by checking the results against
+well-known publicly validated test vectors.
+
+For the case of the HMAC-PRNG, due to the necessity of performing an extensive
+battery test to produce meaningful conclusions, we suggest the user to evaluate
+the unpredictability of the implementation by using the NIST Statistical Test
+Suite (see References).
+
+For the case of the EC-DH and EC-DSA implementations, most of the test vectors
+were obtained from the site of the NIST Cryptographic Algorithm Validation
+Program (CAVP), see References.
+
+References
+**********
+
+* `NIST FIPS PUB 180-4 (SHA-256)`_
+
+.. _NIST FIPS PUB 180-4 (SHA-256):
+ http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
+
+* `NIST FIPS PUB 197 (AES-128)`_
+
+.. _NIST FIPS PUB 197 (AES-128):
+ http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+
+* `NIST SP800-90A (HMAC-PRNG)`_
+
+.. _NIST SP800-90A (HMAC-PRNG):
+ http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
+
+* `NIST SP 800-38A (AES-CBC and AES-CTR)`_
+
+.. _NIST SP 800-38A (AES-CBC and AES-CTR):
+ http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
+
+* `NIST SP 800-38B (AES-CMAC)`_
+
+.. _NIST SP 800-38B (AES-CMAC):
+ http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
+
+* `NIST SP 800-38C (AES-CCM)`_
+
+.. _NIST SP 800-38C (AES-CCM):
+ http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
+
+* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_
+
+.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG):
+ http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html
+
+* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_
+
+.. _NIST Cryptographic Algorithm Validation Program (CAVP) site:
+ http://csrc.nist.gov/groups/STM/cavp/
+
+* `RFC 2104 (HMAC-SHA256)`_
+
+.. _RFC 2104 (HMAC-SHA256):
+ https://www.ietf.org/rfc/rfc2104.txt
+
+* `RFC 6090 (ECC-DH and ECC-DSA)`_
+
+.. _RFC 6090 (ECC-DH and ECC-DSA):
+ https://www.ietf.org/rfc/rfc6090.txt
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/aes.h b/lib/bt/common/tinycrypt/include/tinycrypt/aes.h
new file mode 100644
index 00000000..04f6de50
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/aes.h
@@ -0,0 +1,134 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to an AES-128 implementation.
+ *
+ * Overview: AES-128 is a NIST approved block cipher specified in
+ * FIPS 197. Block ciphers are deterministic algorithms that
+ * perform a transformation specified by a symmetric key in fixed-
+ * length data sets, also called blocks.
+ *
+ * Security: AES-128 provides approximately 128 bits of security.
+ *
+ * Usage: 1) call tc_aes128_set_encrypt/decrypt_key to set the key.
+ *
+ * 2) call tc_aes_encrypt/decrypt to process the data.
+ */
+
+#ifndef __TC_AES_H__
+#define __TC_AES_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define Nb (4) /* number of columns (32-bit words) comprising the state */
+#define Nk (4) /* number of 32-bit words comprising the key */
+#define Nr (10) /* number of rounds */
+#define TC_AES_BLOCK_SIZE (Nb*Nk)
+#define TC_AES_KEY_SIZE (Nb*Nk)
+
+typedef struct tc_aes_key_sched_struct {
+ unsigned int words[Nb*(Nr+1)];
+} *TCAesKeySched_t;
+
+/**
+ * @brief Set AES-128 encryption key
+ * Uses key k to initialize s
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
+ * @note This implementation skips the additional steps required for keys
+ * larger than 128 bits, and must not be used for AES-192 or
+ * AES-256 key schedule -- see FIPS 197 for details
+ * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct
+ * @param k IN -- points to the AES key
+ */
+int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k);
+
+/**
+ * @brief AES-128 Encryption procedure
+ * Encrypts contents of in buffer into out buffer under key;
+ * schedule s
+ * @note Assumes s was initialized by aes_set_encrypt_key;
+ * out and in point to 16 byte buffers
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL
+ * @param out IN/OUT -- buffer to receive ciphertext block
+ * @param in IN -- a plaintext block to encrypt
+ * @param s IN -- initialized AES key schedule
+ */
+int tc_aes_encrypt(uint8_t *out, const uint8_t *in,
+ const TCAesKeySched_t s);
+
+/**
+ * @brief Set the AES-128 decryption key
+ * Uses key k to initialize s
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
+ * @note This is the implementation of the straightforward inverse cipher
+ * using the cipher documented in FIPS-197 figure 12, not the
+ * equivalent inverse cipher presented in Figure 15
+ * @warning This routine skips the additional steps required for keys larger
+ * than 128, and must not be used for AES-192 or AES-256 key
+ * schedule -- see FIPS 197 for details
+ * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct
+ * @param k IN -- points to the AES key
+ */
+int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k);
+
+/**
+ * @brief AES-128 Encryption procedure
+ * Decrypts in buffer into out buffer under key schedule s
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL
+ * @note Assumes s was initialized by aes_set_encrypt_key
+ * out and in point to 16 byte buffers
+ * @param out IN/OUT -- buffer to receive ciphertext block
+ * @param in IN -- a plaintext block to encrypt
+ * @param s IN -- initialized AES key schedule
+ */
+int tc_aes_decrypt(uint8_t *out, const uint8_t *in,
+ const TCAesKeySched_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_AES_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/cbc_mode.h b/lib/bt/common/tinycrypt/include/tinycrypt/cbc_mode.h
new file mode 100644
index 00000000..dadc59fc
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/cbc_mode.h
@@ -0,0 +1,155 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CBC mode implementation.
+ *
+ * Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of
+ * operation defined in SP 800-38a. It can be used with any block
+ * cipher to provide confidentiality of strings whose lengths are
+ * multiples of the block_size of the underlying block cipher.
+ * TinyCrypt hard codes AES as the block cipher.
+ *
+ * Security: CBC mode provides data confidentiality given that the maximum
+ * number q of blocks encrypted under a single key satisfies
+ * q < 2^63, which is not a practical constraint (it is considered a
+ * good practice to replace the encryption when q == 2^56). CBC mode
+ * provides NO data integrity.
+ *
+ * CBC mode assumes that the IV value input into the
+ * tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library
+ * provides HMAC-PRNG module, which generates suitable IVs. Other
+ * methods for generating IVs are acceptable, provided that the
+ * values of the IVs generated appear random to any adversary,
+ * including someone with complete knowledge of the system design.
+ *
+ * The randomness property on which CBC mode's security depends is
+ * the unpredictability of the IV. Since it is unpredictable, this
+ * means in practice that CBC mode requires that the IV is stored
+ * somehow with the ciphertext in order to recover the plaintext.
+ *
+ * TinyCrypt CBC encryption prepends the IV to the ciphertext,
+ * because this affords a more efficient (few buffers) decryption.
+ * Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always
+ * 16 bytes larger than the plaintext buffer.
+ *
+ * Requires: AES-128
+ *
+ * Usage: 1) call tc_cbc_mode_encrypt to encrypt data.
+ *
+ * 2) call tc_cbc_mode_decrypt to decrypt data.
+ *
+ */
+
+#ifndef __TC_CBC_MODE_H__
+#define __TC_CBC_MODE_H__
+
+#include <tinycrypt/aes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief CBC encryption procedure
+ * CBC encrypts inlen bytes of the in buffer into the out buffer
+ * using the encryption key schedule provided, prepends iv to out
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * out == NULL or
+ * in == NULL or
+ * ctr == NULL or
+ * sched == NULL or
+ * inlen == 0 or
+ * (inlen % TC_AES_BLOCK_SIZE) != 0 or
+ * (outlen % TC_AES_BLOCK_SIZE) != 0 or
+ * outlen != inlen + TC_AES_BLOCK_SIZE
+ * @note Assumes: - sched has been configured by aes_set_encrypt_key
+ * - iv contains a 16 byte random string
+ * - out buffer is large enough to hold the ciphertext + iv
+ * - out buffer is a contiguous buffer
+ * - in holds the plaintext and is a contiguous buffer
+ * - inlen gives the number of bytes in the in buffer
+ * @param out IN/OUT -- buffer to receive the ciphertext
+ * @param outlen IN -- length of ciphertext buffer in bytes
+ * @param in IN -- plaintext to encrypt
+ * @param inlen IN -- length of plaintext buffer in bytes
+ * @param iv IN -- the IV for the this encrypt/decrypt
+ * @param sched IN -- AES key schedule for this encrypt
+ */
+int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+ unsigned int inlen, const uint8_t *iv,
+ const TCAesKeySched_t sched);
+
+/**
+ * @brief CBC decryption procedure
+ * CBC decrypts inlen bytes of the in buffer into the out buffer
+ * using the provided encryption key schedule
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * out == NULL or
+ * in == NULL or
+ * sched == NULL or
+ * inlen == 0 or
+ * outlen == 0 or
+ * (inlen % TC_AES_BLOCK_SIZE) != 0 or
+ * (outlen % TC_AES_BLOCK_SIZE) != 0 or
+ * outlen != inlen + TC_AES_BLOCK_SIZE
+ * @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are
+ * contiguous. This allows for a very efficient decryption
+ * algorithm that would not otherwise be possible
+ * - sched was configured by aes_set_decrypt_key
+ * - out buffer is large enough to hold the decrypted plaintext
+ * and is a contiguous buffer
+ * - inlen gives the number of bytes in the in buffer
+ * @param out IN/OUT -- buffer to receive decrypted data
+ * @param outlen IN -- length of plaintext buffer in bytes
+ * @param in IN -- ciphertext to decrypt, including IV
+ * @param inlen IN -- length of ciphertext buffer in bytes
+ * @param iv IN -- the IV for the this encrypt/decrypt
+ * @param sched IN -- AES key schedule for this decrypt
+ *
+ */
+int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+ unsigned int inlen, const uint8_t *iv,
+ const TCAesKeySched_t sched);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CBC_MODE_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ccm_mode.h b/lib/bt/common/tinycrypt/include/tinycrypt/ccm_mode.h
new file mode 100644
index 00000000..af9d79ba
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/ccm_mode.h
@@ -0,0 +1,215 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CCM mode implementation.
+ *
+ * Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of
+ * operation defined in SP 800-38C.
+ *
+ * TinyCrypt CCM implementation accepts:
+ *
+ * 1) Both non-empty payload and associated data (it encrypts and
+ * authenticates the payload and also authenticates the associated
+ * data);
+ * 2) Non-empty payload and empty associated data (it encrypts and
+ * authenticates the payload);
+ * 3) Non-empty associated data and empty payload (it degenerates to
+ * an authentication mode on the associated data).
+ *
+ * TinyCrypt CCM implementation accepts associated data of any length
+ * between 0 and (2^16 - 2^8) bytes.
+ *
+ * Security: The mac length parameter is an important parameter to estimate the
+ * security against collision attacks (that aim at finding different
+ * messages that produce the same authentication tag). TinyCrypt CCM
+ * implementation accepts any even integer between 4 and 16, as
+ * suggested in SP 800-38C.
+ *
+ * RFC-3610, which also specifies CCM, presents a few relevant
+ * security suggestions, such as: it is recommended for most
+ * applications to use a mac length greater than 8. Besides, the
+ * usage of the same nonce for two different messages which are
+ * encrypted with the same key destroys the security of CCM mode.
+ *
+ * Requires: AES-128
+ *
+ * Usage: 1) call tc_ccm_config to configure.
+ *
+ * 2) call tc_ccm_mode_encrypt to encrypt data and generate tag.
+ *
+ * 3) call tc_ccm_mode_decrypt to decrypt data and verify tag.
+ */
+
+#ifndef __TC_CCM_MODE_H__
+#define __TC_CCM_MODE_H__
+
+#include <tinycrypt/aes.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */
+#define TC_CCM_AAD_MAX_BYTES 0xff00
+
+/* max message size in bytes: 2^(8L) = 2^16 = 65536 */
+#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000
+
+/* struct tc_ccm_mode_struct represents the state of a CCM computation */
+typedef struct tc_ccm_mode_struct {
+ TCAesKeySched_t sched; /* AES key schedule */
+ uint8_t *nonce; /* nonce required by CCM */
+ unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */
+} *TCCcmMode_t;
+
+/**
+ * @brief CCM configuration procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * c == NULL or
+ * sched == NULL or
+ * nonce == NULL or
+ * mlen != {4, 6, 8, 10, 12, 16}
+ * @param c -- CCM state
+ * @param sched IN -- AES key schedule
+ * @param nonce IN - nonce
+ * @param nlen -- nonce length in bytes
+ * @param mlen -- mac length in bytes (parameter t in SP-800 38C)
+ */
+int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
+ unsigned int nlen, unsigned int mlen);
+
+/**
+ * @brief CCM tag generation and encryption procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * out == NULL or
+ * c == NULL or
+ * ((plen > 0) and (payload == NULL)) or
+ * ((alen > 0) and (associated_data == NULL)) or
+ * (alen >= TC_CCM_AAD_MAX_BYTES) or
+ * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
+ * (olen < plen + maclength)
+ *
+ * @param out OUT -- encrypted data
+ * @param olen IN -- output length in bytes
+ * @param associated_data IN -- associated data
+ * @param alen IN -- associated data length in bytes
+ * @param payload IN -- payload
+ * @param plen IN -- payload length in bytes
+ * @param c IN -- CCM state
+ *
+ * @note: out buffer should be at least (plen + c->mlen) bytes long.
+ *
+ * @note: The sequence b for encryption is formatted as follows:
+ * b = [FLAGS | nonce | counter ], where:
+ * FLAGS is 1 byte long
+ * nonce is 13 bytes long
+ * counter is 2 bytes long
+ * The byte FLAGS is composed by the following 8 bits:
+ * 0-2 bits: used to represent the value of q-1
+ * 3-7 btis: always 0's
+ *
+ * @note: The sequence b for authentication is formatted as follows:
+ * b = [FLAGS | nonce | length(mac length)], where:
+ * FLAGS is 1 byte long
+ * nonce is 13 bytes long
+ * length(mac length) is 2 bytes long
+ * The byte FLAGS is composed by the following 8 bits:
+ * 0-2 bits: used to represent the value of q-1
+ * 3-5 bits: mac length (encoded as: (mlen-2)/2)
+ * 6: Adata (0 if alen == 0, and 1 otherwise)
+ * 7: always 0
+ */
+int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
+ const uint8_t *associated_data,
+ unsigned int alen, const uint8_t *payload,
+ unsigned int plen, TCCcmMode_t c);
+
+/**
+ * @brief CCM decryption and tag verification procedure
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * out == NULL or
+ * c == NULL or
+ * ((plen > 0) and (payload == NULL)) or
+ * ((alen > 0) and (associated_data == NULL)) or
+ * (alen >= TC_CCM_AAD_MAX_BYTES) or
+ * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
+ * (olen < plen - c->mlen)
+ *
+ * @param out OUT -- decrypted data
+ * @param associated_data IN -- associated data
+ * @param alen IN -- associated data length in bytes
+ * @param payload IN -- payload
+ * @param plen IN -- payload length in bytes
+ * @param c IN -- CCM state
+ *
+ * @note: out buffer should be at least (plen - c->mlen) bytes long.
+ *
+ * @note: The sequence b for encryption is formatted as follows:
+ * b = [FLAGS | nonce | counter ], where:
+ * FLAGS is 1 byte long
+ * nonce is 13 bytes long
+ * counter is 2 bytes long
+ * The byte FLAGS is composed by the following 8 bits:
+ * 0-2 bits: used to represent the value of q-1
+ * 3-7 btis: always 0's
+ *
+ * @note: The sequence b for authentication is formatted as follows:
+ * b = [FLAGS | nonce | length(mac length)], where:
+ * FLAGS is 1 byte long
+ * nonce is 13 bytes long
+ * length(mac length) is 2 bytes long
+ * The byte FLAGS is composed by the following 8 bits:
+ * 0-2 bits: used to represent the value of q-1
+ * 3-5 bits: mac length (encoded as: (mlen-2)/2)
+ * 6: Adata (0 if alen == 0, and 1 otherwise)
+ * 7: always 0
+ */
+int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
+ const uint8_t *associated_data,
+ unsigned int alen, const uint8_t *payload, unsigned int plen,
+ TCCcmMode_t c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CCM_MODE_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/cmac_mode.h b/lib/bt/common/tinycrypt/include/tinycrypt/cmac_mode.h
new file mode 100644
index 00000000..e1cf7d56
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/cmac_mode.h
@@ -0,0 +1,198 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CMAC implementation.
+ *
+ * Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm
+ * for computing a MAC using a block cipher. It can compute the MAC
+ * for a byte string of any length. It is distinguished from CBC-MAC
+ * in the processing of the final message block; CMAC uses a
+ * different technique to compute the final message block is full
+ * size or only partial, while CBC-MAC uses the same technique for
+ * both. This difference permits CMAC to be applied to variable
+ * length messages, while all messages authenticated by CBC-MAC must
+ * be the same length.
+ *
+ * Security: AES128-CMAC mode of operation offers 64 bits of security against
+ * collision attacks. Note however that an external attacker cannot
+ * generate the tags him/herself without knowing the MAC key. In this
+ * sense, to attack the collision property of AES128-CMAC, an
+ * external attacker would need the cooperation of the legal user to
+ * produce an exponentially high number of tags (e.g. 2^64) to
+ * finally be able to look for collisions and benefit from them. As
+ * an extra precaution, the current implementation allows to at most
+ * 2^48 calls to the tc_cmac_update function before re-calling
+ * tc_cmac_setup (allowing a new key to be set), as suggested in
+ * Appendix B of SP 800-38B.
+ *
+ * Requires: AES-128
+ *
+ * Usage: This implementation provides a "scatter-gather" interface, so that
+ * the CMAC value can be computed incrementally over a message
+ * scattered in different segments throughout memory. Experience shows
+ * this style of interface tends to minimize the burden of programming
+ * correctly. Like all symmetric key operations, it is session
+ * oriented.
+ *
+ * To begin a CMAC session, use tc_cmac_setup to initialize a struct
+ * tc_cmac_struct with encryption key and buffer. Our implementation
+ * always assume that the AES key to be the same size as the block
+ * cipher block size. Once setup, this data structure can be used for
+ * many CMAC computations.
+ *
+ * Once the state has been setup with a key, computing the CMAC of
+ * some data requires three steps:
+ *
+ * (1) first use tc_cmac_init to initialize a new CMAC computation.
+ * (2) next mix all of the data into the CMAC computation state using
+ * tc_cmac_update. If all of the data resides in a single data
+ * segment then only one tc_cmac_update call is needed; if data
+ * is scattered throughout memory in n data segments, then n calls
+ * will be needed. CMAC IS ORDER SENSITIVE, to be able to detect
+ * attacks that swap bytes, so the order in which data is mixed
+ * into the state is critical!
+ * (3) Once all of the data for a message has been mixed, use
+ * tc_cmac_final to compute the CMAC tag value.
+ *
+ * Steps (1)-(3) can be repeated as many times as you want to CMAC
+ * multiple messages. A practical limit is 2^48 1K messages before you
+ * have to change the key.
+ *
+ * Once you are done computing CMAC with a key, it is a good idea to
+ * destroy the state so an attacker cannot recover the key; use
+ * tc_cmac_erase to accomplish this.
+ */
+
+#ifndef __TC_CMAC_MODE_H__
+#define __TC_CMAC_MODE_H__
+
+#include <tinycrypt/aes.h>
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* padding for last message block */
+#define TC_CMAC_PADDING 0x80
+
+/* struct tc_cmac_struct represents the state of a CMAC computation */
+typedef struct tc_cmac_struct {
+/* initialization vector */
+ uint8_t iv[TC_AES_BLOCK_SIZE];
+/* used if message length is a multiple of block_size bytes */
+ uint8_t K1[TC_AES_BLOCK_SIZE];
+/* used if message length isn't a multiple block_size bytes */
+ uint8_t K2[TC_AES_BLOCK_SIZE];
+/* where to put bytes that didn't fill a block */
+ uint8_t leftover[TC_AES_BLOCK_SIZE];
+/* identifies the encryption key */
+ unsigned int keyid;
+/* next available leftover location */
+ unsigned int leftover_offset;
+/* AES key schedule */
+ TCAesKeySched_t sched;
+/* calls to tc_cmac_update left before re-key */
+ uint64_t countdown;
+} *TCCmacState_t;
+
+/**
+ * @brief Configures the CMAC state to use the given AES key
+ * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
+ * returns TC_CRYPTO_FAIL (0) if:
+ * s == NULL or
+ * key == NULL
+ *
+ * @param s IN/OUT -- the state to set up
+ * @param key IN -- the key to use
+ * @param sched IN -- AES key schedule
+ */
+int tc_cmac_setup(TCCmacState_t s, const uint8_t *key,
+ TCAesKeySched_t sched);
+
+/**
+ * @brief Erases the CMAC state
+ * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
+ * returns TC_CRYPTO_FAIL (0) if:
+ * s == NULL
+ *
+ * @param s IN/OUT -- the state to erase
+ */
+int tc_cmac_erase(TCCmacState_t s);
+
+/**
+ * @brief Initializes a new CMAC computation
+ * @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state
+ * returns TC_CRYPTO_FAIL (0) if:
+ * s == NULL
+ *
+ * @param s IN/OUT -- the state to initialize
+ */
+int tc_cmac_init(TCCmacState_t s);
+
+/**
+ * @brief Incrementally computes CMAC over the next data segment
+ * @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state
+ * returns TC_CRYPTO_FAIL (0) if:
+ * s == NULL or
+ * if data == NULL when dlen > 0
+ *
+ * @param s IN/OUT -- the CMAC state
+ * @param data IN -- the next data segment to MAC
+ * @param dlen IN -- the length of data in bytes
+ */
+int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen);
+
+/**
+ * @brief Generates the tag from the CMAC state
+ * @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag
+ * returns TC_CRYPTO_FAIL (0) if:
+ * tag == NULL or
+ * s == NULL
+ *
+ * @param tag OUT -- the CMAC tag
+ * @param s IN -- CMAC state
+ */
+int tc_cmac_final(uint8_t *tag, TCCmacState_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CMAC_MODE_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/constants.h b/lib/bt/common/tinycrypt/include/tinycrypt/constants.h
new file mode 100644
index 00000000..3abe98db
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/constants.h
@@ -0,0 +1,65 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to constants.
+ *
+ */
+
+#ifndef __TC_CONSTANTS_H__
+#define __TC_CONSTANTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define TC_CRYPTO_SUCCESS 1
+#define TC_CRYPTO_FAIL 0
+
+#define TC_ZERO_BYTE 0x00
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CONSTANTS_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ctr_mode.h b/lib/bt/common/tinycrypt/include/tinycrypt/ctr_mode.h
new file mode 100644
index 00000000..1b0bab43
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/ctr_mode.h
@@ -0,0 +1,112 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to CTR mode.
+ *
+ * Overview: CTR (pronounced "counter") mode is a NIST approved mode of
+ * operation defined in SP 800-38a. It can be used with any
+ * block cipher to provide confidentiality of strings of any
+ * length. TinyCrypt hard codes AES128 as the block cipher.
+ *
+ * Security: CTR mode achieves confidentiality only if the counter value is
+ * never reused with a same encryption key. If the counter is
+ * repeated, than an adversary might be able to defeat the scheme.
+ *
+ * A usual method to ensure different counter values refers to
+ * initialize the counter in a given value (0, for example) and
+ * increases it every time a new block is enciphered. This naturally
+ * leaves to a limitation on the number q of blocks that can be
+ * enciphered using a same key: q < 2^(counter size).
+ *
+ * TinyCrypt uses a counter of 32 bits. This means that after 2^32
+ * block encryptions, the counter will be reused (thus losing CBC
+ * security). 2^32 block encryptions should be enough for most of
+ * applications targeting constrained devices. Applications intended
+ * to encrypt a larger number of blocks must replace the key after
+ * 2^32 block encryptions.
+ *
+ * CTR mode provides NO data integrity.
+ *
+ * Requires: AES-128
+ *
+ * Usage: 1) call tc_ctr_mode to process the data to encrypt/decrypt.
+ *
+ */
+
+#ifndef __TC_CTR_MODE_H__
+#define __TC_CTR_MODE_H__
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/constants.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief CTR mode encryption/decryption procedure.
+ * CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * out == NULL or
+ * in == NULL or
+ * ctr == NULL or
+ * sched == NULL or
+ * inlen == 0 or
+ * outlen == 0 or
+ * inlen != outlen
+ * @note Assumes:- The current value in ctr has NOT been used with sched
+ * - out points to inlen bytes
+ * - in points to inlen bytes
+ * - ctr is an integer counter in littleEndian format
+ * - sched was initialized by aes_set_encrypt_key
+ * @param out OUT -- produced ciphertext (plaintext)
+ * @param outlen IN -- length of ciphertext buffer in bytes
+ * @param in IN -- data to encrypt (or decrypt)
+ * @param inlen IN -- length of input data in bytes
+ * @param ctr IN/OUT -- the current counter value
+ * @param sched IN -- an initialized AES key schedule
+ */
+int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+ unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CTR_MODE_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ctr_prng.h b/lib/bt/common/tinycrypt/include/tinycrypt/ctr_prng.h
new file mode 100644
index 00000000..ecff008d
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/ctr_prng.h
@@ -0,0 +1,172 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */
+
+/*
+ * Copyright (c) 2016, Chris Morrison
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a CTR-PRNG implementation.
+ *
+ * Overview: A pseudo-random number generator (PRNG) generates a sequence
+ * of numbers that have a distribution close to the one expected
+ * for a sequence of truly random numbers. The NIST Special
+ * Publication 800-90A specifies several mechanisms to generate
+ * sequences of pseudo random numbers, including the CTR-PRNG one
+ * which is based on AES. TinyCrypt implements CTR-PRNG with
+ * AES-128.
+ *
+ * Security: A cryptographically secure PRNG depends on the existence of an
+ * entropy source to provide a truly random seed as well as the
+ * security of the primitives used as the building blocks (AES-128
+ * in this instance).
+ *
+ * Requires: - AES-128
+ *
+ * Usage: 1) call tc_ctr_prng_init to seed the prng context
+ *
+ * 2) call tc_ctr_prng_reseed to mix in additional entropy into
+ * the prng context
+ *
+ * 3) call tc_ctr_prng_generate to output the pseudo-random data
+ *
+ * 4) call tc_ctr_prng_uninstantiate to zero out the prng context
+ */
+
+#ifndef __TC_CTR_PRNG_H__
+#define __TC_CTR_PRNG_H__
+
+#include <tinycrypt/aes.h>
+
+#define TC_CTR_PRNG_RESEED_REQ -1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ /* updated each time another BLOCKLEN_BYTES bytes are produced */
+ uint8_t V[TC_AES_BLOCK_SIZE];
+
+ /* updated whenever the PRNG is reseeded */
+ struct tc_aes_key_sched_struct key;
+
+ /* number of requests since initialization/reseeding */
+ uint64_t reseedCount;
+} TCCtrPrng_t;
+
+
+/**
+ * @brief CTR-PRNG initialization procedure
+ * Initializes prng context with entropy and personalization string (if any)
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * ctx == NULL,
+ * entropy == NULL,
+ * entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
+ * @note Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of
+ * both the entropy and personalization inputs are used -
+ * supplying additional bytes has no effect.
+ * @param ctx IN/OUT -- the PRNG context to initialize
+ * @param entropy IN -- entropy used to seed the PRNG
+ * @param entropyLen IN -- entropy length in bytes
+ * @param personalization IN -- personalization string used to seed the PRNG
+ * (may be null)
+ * @param plen IN -- personalization length in bytes
+ *
+ */
+int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
+ uint8_t const * const entropy,
+ unsigned int entropyLen,
+ uint8_t const * const personalization,
+ unsigned int pLen);
+
+/**
+ * @brief CTR-PRNG reseed procedure
+ * Mixes entropy and additional_input into the prng context
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * ctx == NULL,
+ * entropy == NULL,
+ * entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
+ * @note It is better to reseed an existing prng context rather than
+ * re-initialise, so that any existing entropy in the context is
+ * presereved. This offers some protection against undetected failures
+ * of the entropy source.
+ * @note Assumes tc_ctr_prng_init has been called for ctx
+ * @param ctx IN/OUT -- the PRNG state
+ * @param entropy IN -- entropy to mix into the prng
+ * @param entropylen IN -- length of entropy in bytes
+ * @param additional_input IN -- additional input to the prng (may be null)
+ * @param additionallen IN -- additional input length in bytes
+ */
+int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
+ uint8_t const * const entropy,
+ unsigned int entropyLen,
+ uint8_t const * const additional_input,
+ unsigned int additionallen);
+
+/**
+ * @brief CTR-PRNG generate procedure
+ * Generates outlen pseudo-random bytes into out buffer, updates prng
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed
+ * returns TC_CRYPTO_FAIL (0) if:
+ * ctx == NULL,
+ * out == NULL,
+ * outlen >= 2^16
+ * @note Assumes tc_ctr_prng_init has been called for ctx
+ * @param ctx IN/OUT -- the PRNG context
+ * @param additional_input IN -- additional input to the prng (may be null)
+ * @param additionallen IN -- additional input length in bytes
+ * @param out IN/OUT -- buffer to receive output
+ * @param outlen IN -- size of out buffer in bytes
+ */
+int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
+ uint8_t const * const additional_input,
+ unsigned int additionallen,
+ uint8_t * const out,
+ unsigned int outlen);
+
+/**
+ * @brief CTR-PRNG uninstantiate procedure
+ * Zeroes the internal state of the supplied prng context
+ * @return none
+ * @param ctx IN/OUT -- the PRNG context
+ */
+void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_CTR_PRNG_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ecc.h b/lib/bt/common/tinycrypt/include/tinycrypt/ecc.h
new file mode 100644
index 00000000..d963ae3c
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/ecc.h
@@ -0,0 +1,551 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* ecc.h - TinyCrypt interface to common ECC functions */
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to common ECC functions.
+ *
+ * Overview: This software is an implementation of common functions
+ * necessary to elliptic curve cryptography. This implementation uses
+ * curve NIST p-256.
+ *
+ * Security: The curve NIST p-256 provides approximately 128 bits of security.
+ *
+ */
+
+#ifndef __TC_UECC_H__
+#define __TC_UECC_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Word size (4 bytes considering 32-bits architectures) */
+#define uECC_WORD_SIZE 4
+
+/* setting max number of calls to prng: */
+#ifndef uECC_RNG_MAX_TRIES
+#define uECC_RNG_MAX_TRIES 64
+#endif
+
+/* defining data types to store word and bit counts: */
+typedef int8_t wordcount_t;
+typedef int16_t bitcount_t;
+/* defining data type for comparison result: */
+typedef int8_t cmpresult_t;
+/* defining data type to store ECC coordinate/point in 32bits words: */
+typedef unsigned int uECC_word_t;
+/* defining data type to store an ECC coordinate/point in 64bits words: */
+typedef uint64_t uECC_dword_t;
+
+/* defining masks useful for ecc computations: */
+#define HIGH_BIT_SET 0x80000000
+#define uECC_WORD_BITS 32
+#define uECC_WORD_BITS_SHIFT 5
+#define uECC_WORD_BITS_MASK 0x01F
+
+/* Number of words of 32 bits to represent an element of the the curve p-256: */
+#define NUM_ECC_WORDS 8
+/* Number of bytes to represent an element of the the curve p-256: */
+#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS)
+
+/* structure that represents an elliptic curve (e.g. p256):*/
+struct uECC_Curve_t;
+typedef const struct uECC_Curve_t * uECC_Curve;
+struct uECC_Curve_t {
+ wordcount_t num_words;
+ wordcount_t num_bytes;
+ bitcount_t num_n_bits;
+ uECC_word_t p[NUM_ECC_WORDS];
+ uECC_word_t n[NUM_ECC_WORDS];
+ uECC_word_t G[NUM_ECC_WORDS * 2];
+ uECC_word_t b[NUM_ECC_WORDS];
+ void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1,
+ uECC_Curve curve);
+ void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
+ void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
+};
+
+/*
+ * @brief computes doubling of point ion jacobian coordinates, in place.
+ * @param X1 IN/OUT -- x coordinate
+ * @param Y1 IN/OUT -- y coordinate
+ * @param Z1 IN/OUT -- z coordinate
+ * @param curve IN -- elliptic curve
+ */
+void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
+ uECC_word_t * Z1, uECC_Curve curve);
+
+/*
+ * @brief Computes x^3 + ax + b. result must not overlap x.
+ * @param result OUT -- x^3 + ax + b
+ * @param x IN -- value of x
+ * @param curve IN -- elliptic curve
+ */
+void x_side_default(uECC_word_t *result, const uECC_word_t *x,
+ uECC_Curve curve);
+
+/*
+ * @brief Computes result = product % curve_p
+ * from http://www.nsa.gov/ia/_files/nist-routines.pdf
+ * @param result OUT -- product % curve_p
+ * @param product IN -- value to be reduced mod curve_p
+ */
+void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product);
+
+/* Bytes to words ordering: */
+#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
+#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
+#define BITS_TO_WORDS(num_bits) \
+ ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
+#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
+
+/* definition of curve NIST p-256: */
+static const struct uECC_Curve_t curve_secp256r1 = {
+ NUM_ECC_WORDS,
+ NUM_ECC_BYTES,
+ 256, /* num_n_bits */ {
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
+ BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
+ }, {
+ BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
+ BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
+ BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
+ BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
+ }, {
+ BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
+ BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
+ BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
+ BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
+
+ BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
+ BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
+ BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
+ BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
+ }, {
+ BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
+ BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
+ BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
+ BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
+ },
+ &double_jacobian_default,
+ &x_side_default,
+ &vli_mmod_fast_secp256r1
+};
+
+uECC_Curve uECC_secp256r1(void);
+
+/*
+ * @brief Generates a random integer in the range 0 < random < top.
+ * Both random and top have num_words words.
+ * @param random OUT -- random integer in the range 0 < random < top
+ * @param top IN -- upper limit
+ * @param num_words IN -- number of words
+ * @return a random integer in the range 0 < random < top
+ */
+int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
+ wordcount_t num_words);
+
+
+/* uECC_RNG_Function type
+ * The RNG function should fill 'size' random bytes into 'dest'. It should
+ * return 1 if 'dest' was filled with random data, or 0 if the random data could
+ * not be generated. The filled-in values should be either truly random, or from
+ * a cryptographically-secure PRNG.
+ *
+ * A correctly functioning RNG function must be set (using uECC_set_rng())
+ * before calling uECC_make_key() or uECC_sign().
+ *
+ * Setting a correctly functioning RNG function improves the resistance to
+ * side-channel attacks for uECC_shared_secret().
+ *
+ * A correct RNG function is set by default. If you are building on another
+ * POSIX-compliant system that supports /dev/random or /dev/urandom, you can
+ * define uECC_POSIX to use the predefined RNG.
+ */
+typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size);
+
+/*
+ * @brief Set the function that will be used to generate random bytes. The RNG
+ * function should return 1 if the random data was generated, or 0 if the random
+ * data could not be generated.
+ *
+ * @note On platforms where there is no predefined RNG function, this must be
+ * called before uECC_make_key() or uECC_sign() are used.
+ *
+ * @param rng_function IN -- function that will be used to generate random bytes
+ */
+void uECC_set_rng(uECC_RNG_Function rng_function);
+
+/*
+ * @brief provides current uECC_RNG_Function.
+ * @return Returns the function that will be used to generate random bytes.
+ */
+uECC_RNG_Function uECC_get_rng(void);
+
+/*
+ * @brief computes the size of a private key for the curve in bytes.
+ * @param curve IN -- elliptic curve
+ * @return size of a private key for the curve in bytes.
+ */
+int uECC_curve_private_key_size(uECC_Curve curve);
+
+/*
+ * @brief computes the size of a public key for the curve in bytes.
+ * @param curve IN -- elliptic curve
+ * @return the size of a public key for the curve in bytes.
+ */
+int uECC_curve_public_key_size(uECC_Curve curve);
+
+/*
+ * @brief Compute the corresponding public key for a private key.
+ * @param private_key IN -- The private key to compute the public key for
+ * @param public_key OUT -- Will be filled in with the corresponding public key
+ * @param curve
+ * @return Returns 1 if key was computed successfully, 0 if an error occurred.
+ */
+int uECC_compute_public_key(const uint8_t *private_key,
+ uint8_t *public_key, uECC_Curve curve);
+
+/*
+ * @brief Compute public-key.
+ * @return corresponding public-key.
+ * @param result OUT -- public-key
+ * @param private_key IN -- private-key
+ * @param curve IN -- elliptic curve
+ */
+uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
+ uECC_word_t *private_key, uECC_Curve curve);
+
+/*
+ * @brief Regularize the bitcount for the private key so that attackers cannot
+ * use a side channel attack to learn the number of leading zeros.
+ * @return Regularized k
+ * @param k IN -- private-key
+ * @param k0 IN/OUT -- regularized k
+ * @param k1 IN/OUT -- regularized k
+ * @param curve IN -- elliptic curve
+ */
+uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
+ uECC_word_t *k1, uECC_Curve curve);
+
+/*
+ * @brief Point multiplication algorithm using Montgomery's ladder with co-Z
+ * coordinates. See http://eprint.iacr.org/2011/338.pdf.
+ * @note Result may overlap point.
+ * @param result OUT -- returns scalar*point
+ * @param point IN -- elliptic curve point
+ * @param scalar IN -- scalar
+ * @param initial_Z IN -- initial value for z
+ * @param num_bits IN -- number of bits in scalar
+ * @param curve IN -- elliptic curve
+ */
+void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
+ const uECC_word_t * scalar, const uECC_word_t * initial_Z,
+ bitcount_t num_bits, uECC_Curve curve);
+
+/*
+ * @brief Constant-time comparison to zero - secure way to compare long integers
+ * @param vli IN -- very long integer
+ * @param num_words IN -- number of words in the vli
+ * @return 1 if vli == 0, 0 otherwise.
+ */
+uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
+
+/*
+ * @brief Check if 'point' is the point at infinity
+ * @param point IN -- elliptic curve point
+ * @param curve IN -- elliptic curve
+ * @return if 'point' is the point at infinity, 0 otherwise.
+ */
+uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve);
+
+/*
+ * @brief computes the sign of left - right, in constant time.
+ * @param left IN -- left term to be compared
+ * @param right IN -- right term to be compared
+ * @param num_words IN -- number of words
+ * @return the sign of left - right
+ */
+cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
+ wordcount_t num_words);
+
+/*
+ * @brief computes sign of left - right, not in constant time.
+ * @note should not be used if inputs are part of a secret
+ * @param left IN -- left term to be compared
+ * @param right IN -- right term to be compared
+ * @param num_words IN -- number of words
+ * @return the sign of left - right
+ */
+cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right,
+ wordcount_t num_words);
+
+/*
+ * @brief Computes result = (left - right) % mod.
+ * @note Assumes that (left < mod) and (right < mod), and that result does not
+ * overlap mod.
+ * @param result OUT -- (left - right) % mod
+ * @param left IN -- leftright term in modular subtraction
+ * @param right IN -- right term in modular subtraction
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, const uECC_word_t *mod,
+ wordcount_t num_words);
+
+/*
+ * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or
+ * P => P', Q => P + Q
+ * @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z)
+ * @param X1 IN -- x coordinate of P
+ * @param Y1 IN -- y coordinate of P
+ * @param X2 IN -- x coordinate of Q
+ * @param Y2 IN -- y coordinate of Q
+ * @param curve IN -- elliptic curve
+ */
+void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2,
+ uECC_word_t * Y2, uECC_Curve curve);
+
+/*
+ * @brief Computes (x1 * z^2, y1 * z^3)
+ * @param X1 IN -- previous x1 coordinate
+ * @param Y1 IN -- previous y1 coordinate
+ * @param Z IN -- z value
+ * @param curve IN -- elliptic curve
+ */
+void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
+ uECC_Curve curve);
+
+/*
+ * @brief Check if bit is set.
+ * @return Returns nonzero if bit 'bit' of vli is set.
+ * @warning It is assumed that the value provided in 'bit' is within the
+ * boundaries of the word-array 'vli'.
+ * @note The bit ordering layout assumed for vli is: {31, 30, ..., 0},
+ * {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting
+ * of 4 uECC_word_t elements.
+ */
+uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
+
+/*
+ * @brief Computes result = product % mod, where product is 2N words long.
+ * @param result OUT -- product % mod
+ * @param mod IN -- module
+ * @param num_words IN -- number of words
+ * @warning Currently only designed to work for curve_p or curve_n.
+ */
+void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
+ const uECC_word_t *mod, wordcount_t num_words);
+
+/*
+ * @brief Computes modular product (using curve->mmod_fast)
+ * @param result OUT -- (left * right) mod % curve_p
+ * @param left IN -- left term in product
+ * @param right IN -- right term in product
+ * @param curve IN -- elliptic curve
+ */
+void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, uECC_Curve curve);
+
+/*
+ * @brief Computes result = left - right.
+ * @note Can modify in place.
+ * @param result OUT -- left - right
+ * @param left IN -- left term in subtraction
+ * @param right IN -- right term in subtraction
+ * @param num_words IN -- number of words
+ * @return borrow
+ */
+uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, wordcount_t num_words);
+
+/*
+ * @brief Constant-time comparison function(secure way to compare long ints)
+ * @param left IN -- left term in comparison
+ * @param right IN -- right term in comparison
+ * @param num_words IN -- number of words
+ * @return Returns 0 if left == right, 1 otherwise.
+ */
+uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
+ wordcount_t num_words);
+
+/*
+ * @brief Computes (left * right) % mod
+ * @param result OUT -- (left * right) % mod
+ * @param left IN -- left term in product
+ * @param right IN -- right term in product
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, const uECC_word_t *mod,
+ wordcount_t num_words);
+
+/*
+ * @brief Computes (1 / input) % mod
+ * @note All VLIs are the same size.
+ * @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide"
+ * @param result OUT -- (1 / input) % mod
+ * @param input IN -- value to be modular inverted
+ * @param mod IN -- mod
+ * @param num_words -- number of words
+ */
+void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
+ const uECC_word_t *mod, wordcount_t num_words);
+
+/*
+ * @brief Sets dest = src.
+ * @param dest OUT -- destination buffer
+ * @param src IN -- origin buffer
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
+ wordcount_t num_words);
+
+/*
+ * @brief Computes (left + right) % mod.
+ * @note Assumes that (left < mod) and right < mod), and that result does not
+ * overlap mod.
+ * @param result OUT -- (left + right) % mod.
+ * @param left IN -- left term in addition
+ * @param right IN -- right term in addition
+ * @param mod IN -- mod
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, const uECC_word_t *mod,
+ wordcount_t num_words);
+
+/*
+ * @brief Counts the number of bits required to represent vli.
+ * @param vli IN -- very long integer
+ * @param max_words IN -- number of words
+ * @return number of bits in given vli
+ */
+bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
+ const wordcount_t max_words);
+
+/*
+ * @brief Erases (set to 0) vli
+ * @param vli IN -- very long integer
+ * @param num_words IN -- number of words
+ */
+void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
+
+/*
+ * @brief check if it is a valid point in the curve
+ * @param point IN -- point to be checked
+ * @param curve IN -- elliptic curve
+ * @return 0 if point is valid
+ * @exception returns -1 if it is a point at infinity
+ * @exception returns -2 if x or y is smaller than p,
+ * @exception returns -3 if y^2 != x^3 + ax + b.
+ */
+int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
+
+/*
+ * @brief Check if a public key is valid.
+ * @param public_key IN -- The public key to be checked.
+ * @return returns 0 if the public key is valid
+ * @exception returns -1 if it is a point at infinity
+ * @exception returns -2 if x or y is smaller than p,
+ * @exception returns -3 if y^2 != x^3 + ax + b.
+ * @exception returns -4 if public key is the group generator.
+ *
+ * @note Note that you are not required to check for a valid public key before
+ * using any other uECC functions. However, you may wish to avoid spending CPU
+ * time computing a shared secret or verifying a signature using an invalid
+ * public key.
+ */
+int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
+
+ /*
+ * @brief Converts an integer in uECC native format to big-endian bytes.
+ * @param bytes OUT -- bytes representation
+ * @param num_bytes IN -- number of bytes
+ * @param native IN -- uECC native representation
+ */
+void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
+ const unsigned int *native);
+
+/*
+ * @brief Converts big-endian bytes to an integer in uECC native format.
+ * @param native OUT -- uECC native representation
+ * @param bytes IN -- bytes representation
+ * @param num_bytes IN -- number of bytes
+ */
+void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
+ int num_bytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_UECC_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h
new file mode 100644
index 00000000..e28e8a65
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h
@@ -0,0 +1,135 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to EC-DH implementation.
+ *
+ * Overview: This software is an implementation of EC-DH. This implementation
+ * uses curve NIST p-256.
+ *
+ * Security: The curve NIST p-256 provides approximately 128 bits of security.
+ */
+
+#ifndef __TC_ECC_DH_H__
+#define __TC_ECC_DH_H__
+
+#include <tinycrypt/ecc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Create a public/private key pair.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully
+ * returns TC_CRYPTO_FAIL (0) if error while generating key pair
+ *
+ * @param p_public_key OUT -- Will be filled in with the public key. Must be at
+ * least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
+ * must be 64 bytes long.
+ * @param p_private_key OUT -- Will be filled in with the private key. Must be as
+ * long as the curve order (for secp256r1, p_private_key must be 32 bytes long).
+ *
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ * @warning A cryptographically-secure PRNG function must be set (using
+ * uECC_set_rng()) before calling uECC_make_key().
+ */
+int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve);
+
+#ifdef ENABLE_TESTS
+
+/**
+ * @brief Create a public/private key pair given a specific d.
+ *
+ * @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to
+ * uECC_make_key() function for real applications.
+ */
+int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key,
+ unsigned int *d, uECC_Curve curve);
+#endif
+
+/**
+ * @brief Compute a shared secret given your secret key and someone else's
+ * public key.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully
+ * returns TC_CRYPTO_FAIL (0) otherwise
+ *
+ * @param p_secret OUT -- Will be filled in with the shared secret value. Must be
+ * the same size as the curve size (for curve secp256r1, secret must be 32 bytes
+ * long.
+ * @param p_public_key IN -- The public key of the remote party.
+ * @param p_private_key IN -- Your private key.
+ *
+ * @warning It is recommended to use the output of uECC_shared_secret() as the
+ * input of a recommended Key Derivation Function (see NIST SP 800-108) in
+ * order to produce a cryptographically secure symmetric key.
+ */
+int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key,
+ uint8_t *p_secret, uECC_Curve curve);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_ECC_DH_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dsa.h b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dsa.h
new file mode 100644
index 00000000..76181088
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dsa.h
@@ -0,0 +1,145 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief -- Interface to EC-DSA implementation.
+ *
+ * Overview: This software is an implementation of EC-DSA. This implementation
+ * uses curve NIST p-256.
+ *
+ * Security: The curve NIST p-256 provides approximately 128 bits of security.
+ *
+ * Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is
+ * recommended) and pass it in to ecdsa_sign function along with your
+ * private key and a random number. You must use a new non-predictable
+ * random number to generate each new signature.
+ * - To verify a signature: Compute the hash of the signed data using
+ * the same hash as the signer and pass it to this function along with
+ * the signer's public key and the signature values (r and s).
+ */
+
+#ifndef __TC_ECC_DSA_H__
+#define __TC_ECC_DSA_H__
+
+#include <tinycrypt/ecc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Generate an ECDSA signature for a given hash value.
+ * @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully
+ * returns TC_CRYPTO_FAIL (0) if an error occurred.
+ *
+ * @param p_private_key IN -- Your private key.
+ * @param p_message_hash IN -- The hash of the message to sign.
+ * @param p_hash_size IN -- The size of p_message_hash in bytes.
+ * @param p_signature OUT -- Will be filled in with the signature value. Must be
+ * at least 2 * curve size long (for secp256r1, signature must be 64 bytes long).
+ *
+ * @warning A cryptographically-secure PRNG function must be set (using
+ * uECC_set_rng()) before calling uECC_sign().
+ * @note Usage: Compute a hash of the data you wish to sign (SHA-2 is
+ * recommended) and pass it in to this function along with your private key.
+ * @note side-channel countermeasure: algorithm strengthened against timing
+ * attack.
+ */
+int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash,
+ unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve);
+
+#ifdef ENABLE_TESTS
+/*
+ * THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY.
+ * Refer to uECC_sign() function for real applications.
+ */
+int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
+ unsigned int hash_size, uECC_word_t *k, uint8_t *signature,
+ uECC_Curve curve);
+#endif
+
+/**
+ * @brief Verify an ECDSA signature.
+ * @return returns TC_SUCCESS (1) if the signature is valid
+ * returns TC_FAIL (0) if the signature is invalid.
+ *
+ * @param p_public_key IN -- The signer's public key.
+ * @param p_message_hash IN -- The hash of the signed data.
+ * @param p_hash_size IN -- The size of p_message_hash in bytes.
+ * @param p_signature IN -- The signature values.
+ *
+ * @note Usage: Compute the hash of the signed data using the same hash as the
+ * signer and pass it to this function along with the signer's public key and
+ * the signature values (hash_size and signature).
+ */
+int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash,
+ unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_ECC_DSA_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ecc_platform_specific.h b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_platform_specific.h
new file mode 100644
index 00000000..553c8a03
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_platform_specific.h
@@ -0,0 +1,85 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * uECC_platform_specific.h -- Interface to platform specific functions
+ */
+
+#ifndef __UECC_PLATFORM_SPECIFIC_H_
+#define __UECC_PLATFORM_SPECIFIC_H_
+
+/*
+ * The RNG function should fill 'size' random bytes into 'dest'. It should
+ * return 1 if 'dest' was filled with random data, or 0 if the random data could
+ * not be generated. The filled-in values should be either truly random, or from
+ * a cryptographically-secure PRNG.
+ *
+ * A cryptographically-secure PRNG function must be set (using uECC_set_rng())
+ * before calling uECC_make_key() or uECC_sign().
+ *
+ * Setting a cryptographically-secure PRNG function improves the resistance to
+ * side-channel attacks for uECC_shared_secret().
+ *
+ * A correct PRNG function is set by default (default_RNG_defined = 1) and works
+ * for some platforms, such as Unix and Linux. For other platforms, you may need
+ * to provide another PRNG function.
+*/
+#define default_RNG_defined 0
+
+int default_CSPRNG(uint8_t *dest, unsigned int size);
+
+#endif /* __UECC_PLATFORM_SPECIFIC_H_ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/hmac.h b/lib/bt/common/tinycrypt/include/tinycrypt/hmac.h
new file mode 100644
index 00000000..1f624ef8
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/hmac.h
@@ -0,0 +1,143 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to an HMAC implementation.
+ *
+ * Overview: HMAC is a message authentication code based on hash functions.
+ * TinyCrypt hard codes SHA-256 as the hash function. A message
+ * authentication code based on hash functions is also called a
+ * keyed cryptographic hash function since it performs a
+ * transformation specified by a key in an arbitrary length data
+ * set into a fixed length data set (also called tag).
+ *
+ * Security: The security of the HMAC depends on the length of the key and
+ * on the security of the hash function. Note that HMAC primitives
+ * are much less affected by collision attacks than their
+ * corresponding hash functions.
+ *
+ * Requires: SHA-256
+ *
+ * Usage: 1) call tc_hmac_set_key to set the HMAC key.
+ *
+ * 2) call tc_hmac_init to initialize a struct hash_state before
+ * processing the data.
+ *
+ * 3) call tc_hmac_update to process the next input segment;
+ * tc_hmac_update can be called as many times as needed to process
+ * all of the segments of the input; the order is important.
+ *
+ * 4) call tc_hmac_final to out put the tag.
+ */
+
+#ifndef __TC_HMAC_H__
+#define __TC_HMAC_H__
+
+#include <tinycrypt/sha256.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct tc_hmac_state_struct {
+ /* the internal state required by h */
+ struct tc_sha256_state_struct hash_state;
+ /* HMAC key schedule */
+ uint8_t key[2*TC_SHA256_BLOCK_SIZE];
+};
+typedef struct tc_hmac_state_struct *TCHmacState_t;
+
+/**
+ * @brief HMAC set key procedure
+ * Configures ctx to use key
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if
+ * ctx == NULL or
+ * key == NULL or
+ * key_size == 0
+ * @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial
+ * @param key IN -- the HMAC key to configure
+ * @param key_size IN -- the HMAC key size
+ */
+int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
+ unsigned int key_size);
+
+/**
+ * @brief HMAC init procedure
+ * Initializes ctx to begin the next HMAC operation
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
+ * @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init
+ */
+int tc_hmac_init(TCHmacState_t ctx);
+
+/**
+ * @brief HMAC update procedure
+ * Mixes data_length bytes addressed by data into state
+ * @return returns TC_CRYPTO_SUCCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
+ * @note Assumes state has been initialized by tc_hmac_init
+ * @param ctx IN/OUT -- state of HMAC computation so far
+ * @param data IN -- data to incorporate into state
+ * @param data_length IN -- size of data in bytes
+ */
+int tc_hmac_update(TCHmacState_t ctx, const void *data,
+ unsigned int data_length);
+
+/**
+ * @brief HMAC final procedure
+ * Writes the HMAC tag into the tag buffer
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * tag == NULL or
+ * ctx == NULL or
+ * key == NULL or
+ * taglen != TC_SHA256_DIGEST_SIZE
+ * @note ctx is erased before exiting. This should never be changed/removed.
+ * @note Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes
+ * state has been initialized by tc_hmac_init
+ * @param tag IN/OUT -- buffer to receive computed HMAC tag
+ * @param taglen IN -- size of tag in bytes
+ * @param ctx IN/OUT -- the HMAC state for computing tag
+ */
+int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__TC_HMAC_H__*/
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/hmac_prng.h b/lib/bt/common/tinycrypt/include/tinycrypt/hmac_prng.h
new file mode 100644
index 00000000..98c2e70c
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/hmac_prng.h
@@ -0,0 +1,168 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to an HMAC-PRNG implementation.
+ *
+ * Overview: A pseudo-random number generator (PRNG) generates a sequence
+ * of numbers that have a distribution close to the one expected
+ * for a sequence of truly random numbers. The NIST Special
+ * Publication 800-90A specifies several mechanisms to generate
+ * sequences of pseudo random numbers, including the HMAC-PRNG one
+ * which is based on HMAC. TinyCrypt implements HMAC-PRNG with
+ * certain modifications from the NIST SP 800-90A spec.
+ *
+ * Security: A cryptographically secure PRNG depends on the existence of an
+ * entropy source to provide a truly random seed as well as the
+ * security of the primitives used as the building blocks (HMAC and
+ * SHA256, for TinyCrypt).
+ *
+ * The NIST SP 800-90A standard tolerates a null personalization,
+ * while TinyCrypt requires a non-null personalization. This is
+ * because a personalization string (the host name concatenated
+ * with a time stamp, for example) is easily computed and might be
+ * the last line of defense against failure of the entropy source.
+ *
+ * Requires: - SHA-256
+ * - HMAC
+ *
+ * Usage: 1) call tc_hmac_prng_init to set the HMAC key and process the
+ * personalization data.
+ *
+ * 2) call tc_hmac_prng_reseed to process the seed and additional
+ * input.
+ *
+ * 3) call tc_hmac_prng_generate to out put the pseudo-random data.
+ */
+
+#ifndef __TC_HMAC_PRNG_H__
+#define __TC_HMAC_PRNG_H__
+
+#include <tinycrypt/sha256.h>
+#include <tinycrypt/hmac.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TC_HMAC_PRNG_RESEED_REQ -1
+
+struct tc_hmac_prng_struct {
+ /* the HMAC instance for this PRNG */
+ struct tc_hmac_state_struct h;
+ /* the PRNG key */
+ uint8_t key[TC_SHA256_DIGEST_SIZE];
+ /* PRNG state */
+ uint8_t v[TC_SHA256_DIGEST_SIZE];
+ /* calls to tc_hmac_prng_generate left before re-seed */
+ unsigned int countdown;
+};
+
+typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
+
+/**
+ * @brief HMAC-PRNG initialization procedure
+ * Initializes prng with personalization, disables tc_hmac_prng_generate
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * prng == NULL,
+ * personalization == NULL,
+ * plen > MAX_PLEN
+ * @note Assumes: - personalization != NULL.
+ * The personalization is a platform unique string (e.g., the host
+ * name) and is the last line of defense against failure of the
+ * entropy source
+ * @warning NIST SP 800-90A specifies 3 items as seed material during
+ * initialization: entropy seed, personalization, and an optional
+ * nonce. TinyCrypts requires instead a non-null personalization
+ * (which is easily computed) and indirectly requires an entropy
+ * seed (since the reseed function is mandatorily called after
+ * init)
+ * @param prng IN/OUT -- the PRNG state to initialize
+ * @param personalization IN -- personalization string
+ * @param plen IN -- personalization length in bytes
+ */
+int tc_hmac_prng_init(TCHmacPrng_t prng,
+ const uint8_t *personalization,
+ unsigned int plen);
+
+/**
+ * @brief HMAC-PRNG reseed procedure
+ * Mixes seed into prng, enables tc_hmac_prng_generate
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * prng == NULL,
+ * seed == NULL,
+ * seedlen < MIN_SLEN,
+ * seendlen > MAX_SLEN,
+ * additional_input != (const uint8_t *) 0 && additionallen == 0,
+ * additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN
+ * @note Assumes:- tc_hmac_prng_init has been called for prng
+ * - seed has sufficient entropy.
+ *
+ * @param prng IN/OUT -- the PRNG state
+ * @param seed IN -- entropy to mix into the prng
+ * @param seedlen IN -- length of seed in bytes
+ * @param additional_input IN -- additional input to the prng
+ * @param additionallen IN -- additional input length in bytes
+ */
+int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed,
+ unsigned int seedlen, const uint8_t *additional_input,
+ unsigned int additionallen);
+
+/**
+ * @brief HMAC-PRNG generate procedure
+ * Generates outlen pseudo-random bytes into out buffer, updates prng
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed
+ * returns TC_CRYPTO_FAIL (0) if:
+ * out == NULL,
+ * prng == NULL,
+ * outlen == 0,
+ * outlen >= MAX_OUT
+ * @note Assumes tc_hmac_prng_init has been called for prng
+ * @param out IN/OUT -- buffer to receive output
+ * @param outlen IN -- size of out buffer in bytes
+ * @param prng IN/OUT -- the PRNG state
+ */
+int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_HMAC_PRNG_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/sha256.h b/lib/bt/common/tinycrypt/include/tinycrypt/sha256.h
new file mode 100644
index 00000000..860665ee
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/sha256.h
@@ -0,0 +1,135 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* sha256.h - TinyCrypt interface to a SHA-256 implementation */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to a SHA-256 implementation.
+ *
+ * Overview: SHA-256 is a NIST approved cryptographic hashing algorithm
+ * specified in FIPS 180. A hash algorithm maps data of arbitrary
+ * size to data of fixed length.
+ *
+ * Security: SHA-256 provides 128 bits of security against collision attacks
+ * and 256 bits of security against pre-image attacks. SHA-256 does
+ * NOT behave like a random oracle, but it can be used as one if
+ * the string being hashed is prefix-free encoded before hashing.
+ *
+ * Usage: 1) call tc_sha256_init to initialize a struct
+ * tc_sha256_state_struct before hashing a new string.
+ *
+ * 2) call tc_sha256_update to hash the next string segment;
+ * tc_sha256_update can be called as many times as needed to hash
+ * all of the segments of a string; the order is important.
+ *
+ * 3) call tc_sha256_final to out put the digest from a hashing
+ * operation.
+ */
+
+#ifndef __TC_SHA256_H__
+#define __TC_SHA256_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TC_SHA256_BLOCK_SIZE (64)
+#define TC_SHA256_DIGEST_SIZE (32)
+#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4)
+
+struct tc_sha256_state_struct {
+ unsigned int iv[TC_SHA256_STATE_BLOCKS];
+ uint64_t bits_hashed;
+ uint8_t leftover[TC_SHA256_BLOCK_SIZE];
+ size_t leftover_offset;
+};
+
+typedef struct tc_sha256_state_struct *TCSha256State_t;
+
+/**
+ * @brief SHA256 initialization procedure
+ * Initializes s
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if s == NULL
+ * @param s Sha256 state struct
+ */
+int tc_sha256_init(TCSha256State_t s);
+
+/**
+ * @brief SHA256 update procedure
+ * Hashes data_length bytes addressed by data into state s
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * s == NULL,
+ * s->iv == NULL,
+ * data == NULL
+ * @note Assumes s has been initialized by tc_sha256_init
+ * @warning The state buffer 'leftover' is left in memory after processing
+ * If your application intends to have sensitive data in this
+ * buffer, remind to erase it after the data has been processed
+ * @param s Sha256 state struct
+ * @param data message to hash
+ * @param datalen length of message to hash
+ */
+int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen);
+
+/**
+ * @brief SHA256 final procedure
+ * Inserts the completed hash computation into digest
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * s == NULL,
+ * s->iv == NULL,
+ * digest == NULL
+ * @note Assumes: s has been initialized by tc_sha256_init
+ * digest points to at least TC_SHA256_DIGEST_SIZE bytes
+ * @warning The state buffer 'leftover' is left in memory after processing
+ * If your application intends to have sensitive data in this
+ * buffer, remind to erase it after the data has been processed
+ * @param digest unsigned eight bit integer
+ * @param Sha256 state struct
+ */
+int tc_sha256_final(uint8_t *digest, TCSha256State_t s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_SHA256_H__ */
diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/utils.h b/lib/bt/common/tinycrypt/include/tinycrypt/utils.h
new file mode 100644
index 00000000..18224c89
--- /dev/null
+++ b/lib/bt/common/tinycrypt/include/tinycrypt/utils.h
@@ -0,0 +1,101 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* utils.h - TinyCrypt interface to platform-dependent run-time operations */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief Interface to platform-dependent run-time operations.
+ *
+ */
+
+#ifndef __TC_UTILS_H__
+#define __TC_UTILS_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Copy the the buffer 'from' to the buffer 'to'.
+ * @return returns TC_CRYPTO_SUCCESS (1)
+ * returns TC_CRYPTO_FAIL (0) if:
+ * from_len > to_len.
+ *
+ * @param to OUT -- destination buffer
+ * @param to_len IN -- length of destination buffer
+ * @param from IN -- origin buffer
+ * @param from_len IN -- length of origin buffer
+ */
+unsigned int _copy(uint8_t *to, unsigned int to_len,
+ const uint8_t *from, unsigned int from_len);
+
+/**
+ * @brief Set the value 'val' into the buffer 'to', 'len' times.
+ *
+ * @param to OUT -- destination buffer
+ * @param val IN -- value to be set in 'to'
+ * @param len IN -- number of times the value will be copied
+ */
+void _set(void *to, uint8_t val, unsigned int len);
+
+/*
+ * @brief AES specific doubling function, which utilizes
+ * the finite field used by AES.
+ * @return Returns a^2
+ *
+ * @param a IN/OUT -- value to be doubled
+ */
+uint8_t _double_byte(uint8_t a);
+
+/*
+ * @brief Constant-time algorithm to compare if two sequences of bytes are equal
+ * @return Returns 0 if equal, and non-zero otherwise
+ *
+ * @param a IN -- sequence of bytes a
+ * @param b IN -- sequence of bytes b
+ * @param size IN -- size of sequences a and b
+ */
+int _compare(const uint8_t *a, const uint8_t *b, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TC_UTILS_H__ */
diff --git a/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c b/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c
new file mode 100644
index 00000000..c4424c56
--- /dev/null
+++ b/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c
@@ -0,0 +1,87 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "esp_tinycrypt_port.h"
+
+#include "esp_crypto_lock.h"
+#include "esp_private/esp_crypto_lock_internal.h"
+
+#if SOC_ECC_SUPPORTED
+#include "hal/ecc_hal.h"
+#include "hal/ecc_ll.h"
+#endif /* SOC_ECC_SUPPORTED */
+
+
+#if SOC_ECC_SUPPORTED
+static void esp_tinycrypt_acquire_ecc_hardware(void)
+{
+ esp_crypto_ecc_lock_acquire();
+
+ ECC_RCC_ATOMIC() {
+ ecc_ll_enable_bus_clock(true);
+ ecc_ll_power_up();
+ ecc_ll_reset_register();
+ }
+}
+
+static void esp_tinycrypt_release_ecc_hardware(void)
+{
+ ECC_RCC_ATOMIC() {
+ ecc_ll_enable_bus_clock(false);
+ ecc_ll_power_down();
+ }
+
+ esp_crypto_ecc_lock_release();
+}
+
+int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length)
+{
+ int result;
+
+ esp_tinycrypt_acquire_ecc_hardware();
+
+ ecc_hal_write_verify_param(pk_x, pk_y, length);
+ ecc_hal_set_mode(ECC_MODE_VERIFY);
+ ecc_hal_start_calc();
+ while (!ecc_hal_is_calc_finished());
+ result = ecc_hal_read_verify_result();
+
+ esp_tinycrypt_release_ecc_hardware();
+
+ if (result == 1) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar,
+ uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first)
+{
+ int ret = -1;
+ ecc_mode_t work_mode = verify_first ? ECC_MODE_VERIFY_THEN_POINT_MUL : ECC_MODE_POINT_MUL;
+
+ esp_tinycrypt_acquire_ecc_hardware();
+
+ ecc_hal_write_mul_param(scalar, p_x, p_y, num_bytes);
+ ecc_hal_set_mode(work_mode);
+ /*
+ * Enable constant-time point multiplication operations for the ECC hardware accelerator,
+ * if supported for the given target. This protects the ECC multiplication operation from
+ * timing attacks. This increases the time taken (by almost 50%) for some point
+ * multiplication operations performed by the ECC hardware accelerator.
+ */
+ ecc_hal_enable_constant_time_point_mul(true);
+ ecc_hal_start_calc();
+
+ while (!ecc_hal_is_calc_finished());
+
+ ret = ecc_hal_read_mul_result(r_x, r_y, num_bytes);
+
+ esp_tinycrypt_release_ecc_hardware();
+
+ return ret;
+}
+#endif /* SOC_ECC_SUPPORTED */
diff --git a/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h b/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h
new file mode 100644
index 00000000..4fdf82c2
--- /dev/null
+++ b/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h
@@ -0,0 +1,15 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include "soc/soc_caps.h"
+
+#if SOC_ECC_SUPPORTED
+int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length);
+
+int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar,
+ uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first);
+#endif /* SOC_ECC_SUPPORTED */
diff --git a/lib/bt/common/tinycrypt/src/aes_decrypt.c b/lib/bt/common/tinycrypt/src/aes_decrypt.c
new file mode 100644
index 00000000..7da52349
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/aes_decrypt.c
@@ -0,0 +1,170 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static const uint8_t inv_sbox[256] = {
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
+ 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
+ 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
+ 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
+ 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
+ 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
+ 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
+ 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
+ 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
+ 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
+ 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
+ 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
+ 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
+ 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
+ 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
+ 0x55, 0x21, 0x0c, 0x7d
+};
+
+int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k)
+{
+ return tc_aes128_set_encrypt_key(s, k);
+}
+
+#define mult8(a)(_double_byte(_double_byte(_double_byte(a))))
+#define mult9(a)(mult8(a)^(a))
+#define multb(a)(mult8(a)^_double_byte(a)^(a))
+#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a))
+#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a))
+
+static inline void mult_row_column(uint8_t *out, const uint8_t *in)
+{
+ out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]);
+ out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]);
+ out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]);
+ out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]);
+}
+
+static inline void inv_mix_columns(uint8_t *s)
+{
+ uint8_t t[Nb*Nk];
+
+ mult_row_column(t, s);
+ mult_row_column(&t[Nb], s+Nb);
+ mult_row_column(&t[2*Nb], s+(2*Nb));
+ mult_row_column(&t[3*Nb], s+(3*Nb));
+ (void)_copy(s, sizeof(t), t, sizeof(t));
+}
+
+static inline void add_round_key(uint8_t *s, const unsigned int *k)
+{
+ s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
+ s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
+ s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
+ s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
+ s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
+ s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
+ s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
+ s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
+}
+
+static inline void inv_sub_bytes(uint8_t *s)
+{
+ unsigned int i;
+
+ for (i = 0; i < (Nb*Nk); ++i) {
+ s[i] = inv_sbox[s[i]];
+ }
+}
+
+/*
+ * This inv_shift_rows also implements the matrix flip required for
+ * inv_mix_columns, but performs it here to reduce the number of memory
+ * operations.
+ */
+static inline void inv_shift_rows(uint8_t *s)
+{
+ uint8_t t[Nb*Nk];
+
+ t[0] = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7];
+ t[4] = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11];
+ t[8] = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15];
+ t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3];
+ (void)_copy(s, sizeof(t), t, sizeof(t));
+}
+
+int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
+{
+ uint8_t state[Nk*Nb];
+ unsigned int i;
+
+ if (out == (uint8_t *) 0) {
+ return TC_CRYPTO_FAIL;
+ } else if (in == (const uint8_t *) 0) {
+ return TC_CRYPTO_FAIL;
+ } else if (s == (TCAesKeySched_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ (void)_copy(state, sizeof(state), in, sizeof(state));
+
+ add_round_key(state, s->words + Nb*Nr);
+
+ for (i = Nr - 1; i > 0; --i) {
+ inv_shift_rows(state);
+ inv_sub_bytes(state);
+ add_round_key(state, s->words + Nb*i);
+ inv_mix_columns(state);
+ }
+
+ inv_shift_rows(state);
+ inv_sub_bytes(state);
+ add_round_key(state, s->words);
+
+ (void)_copy(out, sizeof(state), state, sizeof(state));
+
+ /*zeroing out the state buffer */
+ _set(state, TC_ZERO_BYTE, sizeof(state));
+
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/lib/bt/common/tinycrypt/src/aes_encrypt.c b/lib/bt/common/tinycrypt/src/aes_encrypt.c
new file mode 100644
index 00000000..7095695d
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/aes_encrypt.c
@@ -0,0 +1,197 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+
+static const uint8_t sbox[256] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
+ 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+ 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
+ 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
+ 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+ 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
+ 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
+ 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+ 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
+ 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
+ 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+ 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
+ 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
+ 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+ 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
+ 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
+ 0xb0, 0x54, 0xbb, 0x16
+};
+
+static inline unsigned int rotword(unsigned int a)
+{
+ return (((a) >> 24)|((a) << 8));
+}
+
+#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o))
+#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0))
+
+int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k)
+{
+ const unsigned int rconst[11] = {
+ 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
+ 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
+ };
+ unsigned int i;
+ unsigned int t;
+
+ if (s == (TCAesKeySched_t) 0) {
+ return TC_CRYPTO_FAIL;
+ } else if (k == (const uint8_t *) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ for (i = 0; i < Nk; ++i) {
+ s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) |
+ (k[Nb*i+2]<<8) | (k[Nb*i+3]);
+ }
+
+ for (; i < (Nb * (Nr + 1)); ++i) {
+ t = s->words[i-1];
+ if ((i % Nk) == 0) {
+ t = subword(rotword(t)) ^ rconst[i/Nk];
+ }
+ s->words[i] = s->words[i-Nk] ^ t;
+ }
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+static inline void add_round_key(uint8_t *s, const unsigned int *k)
+{
+ s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
+ s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
+ s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
+ s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
+ s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
+ s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
+ s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
+ s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
+}
+
+static inline void sub_bytes(uint8_t *s)
+{
+ unsigned int i;
+
+ for (i = 0; i < (Nb * Nk); ++i) {
+ s[i] = sbox[s[i]];
+ }
+}
+
+#define triple(a)(_double_byte(a)^(a))
+
+static inline void mult_row_column(uint8_t *out, const uint8_t *in)
+{
+ out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3];
+ out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3];
+ out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]);
+ out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]);
+}
+
+static inline void mix_columns(uint8_t *s)
+{
+ uint8_t t[Nb*Nk];
+
+ mult_row_column(t, s);
+ mult_row_column(&t[Nb], s+Nb);
+ mult_row_column(&t[2 * Nb], s + (2 * Nb));
+ mult_row_column(&t[3 * Nb], s + (3 * Nb));
+ (void) _copy(s, sizeof(t), t, sizeof(t));
+}
+
+/*
+ * This shift_rows also implements the matrix flip required for mix_columns, but
+ * performs it here to reduce the number of memory operations.
+ */
+static inline void shift_rows(uint8_t *s)
+{
+ uint8_t t[Nb * Nk];
+
+ t[0] = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15];
+ t[4] = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3];
+ t[8] = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7];
+ t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11];
+ (void) _copy(s, sizeof(t), t, sizeof(t));
+}
+
+int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
+{
+ uint8_t state[Nk*Nb];
+ unsigned int i;
+
+ if (out == (uint8_t *) 0) {
+ return TC_CRYPTO_FAIL;
+ } else if (in == (const uint8_t *) 0) {
+ return TC_CRYPTO_FAIL;
+ } else if (s == (TCAesKeySched_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ (void)_copy(state, sizeof(state), in, sizeof(state));
+ add_round_key(state, s->words);
+
+ for (i = 0; i < (Nr - 1); ++i) {
+ sub_bytes(state);
+ shift_rows(state);
+ mix_columns(state);
+ add_round_key(state, s->words + Nb*(i+1));
+ }
+
+ sub_bytes(state);
+ shift_rows(state);
+ add_round_key(state, s->words + Nb*(i+1));
+
+ (void)_copy(out, sizeof(state), state, sizeof(state));
+
+ /* zeroing out the state buffer */
+ _set(state, TC_ZERO_BYTE, sizeof(state));
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/lib/bt/common/tinycrypt/src/cbc_mode.c b/lib/bt/common/tinycrypt/src/cbc_mode.c
new file mode 100644
index 00000000..86a00c8d
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/cbc_mode.c
@@ -0,0 +1,118 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/cbc_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+ unsigned int inlen, const uint8_t *iv,
+ const TCAesKeySched_t sched)
+{
+
+ uint8_t buffer[TC_AES_BLOCK_SIZE];
+ unsigned int n, m;
+
+ /* input sanity check: */
+ if (out == (uint8_t *) 0 ||
+ in == (const uint8_t *) 0 ||
+ sched == (TCAesKeySched_t) 0 ||
+ inlen == 0 ||
+ outlen == 0 ||
+ (inlen % TC_AES_BLOCK_SIZE) != 0 ||
+ (outlen % TC_AES_BLOCK_SIZE) != 0 ||
+ outlen != inlen + TC_AES_BLOCK_SIZE) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /* copy iv to the buffer */
+ (void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
+ /* copy iv to the output buffer */
+ (void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
+ out += TC_AES_BLOCK_SIZE;
+
+ for (n = m = 0; n < inlen; ++n) {
+ buffer[m++] ^= *in++;
+ if (m == TC_AES_BLOCK_SIZE) {
+ (void)tc_aes_encrypt(buffer, buffer, sched);
+ (void)_copy(out, TC_AES_BLOCK_SIZE,
+ buffer, TC_AES_BLOCK_SIZE);
+ out += TC_AES_BLOCK_SIZE;
+ m = 0;
+ }
+ }
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
+ unsigned int inlen, const uint8_t *iv,
+ const TCAesKeySched_t sched)
+{
+
+ uint8_t buffer[TC_AES_BLOCK_SIZE];
+ const uint8_t *p;
+ unsigned int n, m;
+
+ /* sanity check the inputs */
+ if (out == (uint8_t *) 0 ||
+ in == (const uint8_t *) 0 ||
+ sched == (TCAesKeySched_t) 0 ||
+ inlen == 0 ||
+ outlen == 0 ||
+ (inlen % TC_AES_BLOCK_SIZE) != 0 ||
+ (outlen % TC_AES_BLOCK_SIZE) != 0 ||
+ outlen != inlen - TC_AES_BLOCK_SIZE) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /*
+ * Note that in == iv + ciphertext, i.e. the iv and the ciphertext are
+ * contiguous. This allows for a very efficient decryption algorithm
+ * that would not otherwise be possible.
+ */
+ p = iv;
+ for (n = m = 0; n < inlen; ++n) {
+ if ((n % TC_AES_BLOCK_SIZE) == 0) {
+ (void)tc_aes_decrypt(buffer, in, sched);
+ in += TC_AES_BLOCK_SIZE;
+ m = 0;
+ }
+ *out++ = buffer[m++] ^ *p++;
+ }
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/lib/bt/common/tinycrypt/src/ccm_mode.c b/lib/bt/common/tinycrypt/src/ccm_mode.c
new file mode 100644
index 00000000..4017d249
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/ccm_mode.c
@@ -0,0 +1,272 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* ccm_mode.c - TinyCrypt implementation of CCM mode */
+
+#include <tinycrypt/ccm_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+#include <stdio.h>
+
+int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
+ unsigned int nlen, unsigned int mlen)
+{
+
+ /* input sanity check: */
+ if (c == (TCCcmMode_t) 0 ||
+ sched == (TCAesKeySched_t) 0 ||
+ nonce == (uint8_t *) 0) {
+ return TC_CRYPTO_FAIL;
+ } else if (nlen != 13) {
+ return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/
+ } else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
+ return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
+ }
+
+ c->mlen = mlen;
+ c->sched = sched;
+ c->nonce = nonce;
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+/**
+ * Variation of CBC-MAC mode used in CCM.
+ */
+static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen,
+ unsigned int flag, TCAesKeySched_t sched)
+{
+
+ unsigned int i;
+
+ if (flag > 0) {
+ T[0] ^= (uint8_t)(dlen >> 8);
+ T[1] ^= (uint8_t)(dlen);
+ dlen += 2; i = 2;
+ } else {
+ i = 0;
+ }
+
+ while (i < dlen) {
+ T[i++ % (Nb * Nk)] ^= *data++;
+ if (((i % (Nb * Nk)) == 0) || dlen == i) {
+ (void) tc_aes_encrypt(T, T, sched);
+ }
+ }
+}
+
+/**
+ * Variation of CTR mode used in CCM.
+ * The CTR mode used by CCM is slightly different than the conventional CTR
+ * mode (the counter is increased before encryption, instead of after
+ * encryption). Besides, it is assumed that the counter is stored in the last
+ * 2 bytes of the nonce.
+ */
+static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+ unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
+{
+
+ uint8_t buffer[TC_AES_BLOCK_SIZE];
+ uint8_t nonce[TC_AES_BLOCK_SIZE];
+ uint16_t block_num;
+ unsigned int i;
+
+ /* input sanity check: */
+ if (out == (uint8_t *) 0 ||
+ in == (uint8_t *) 0 ||
+ ctr == (uint8_t *) 0 ||
+ sched == (TCAesKeySched_t) 0 ||
+ inlen == 0 ||
+ outlen == 0 ||
+ outlen != inlen) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /* copy the counter to the nonce */
+ (void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
+
+ /* select the last 2 bytes of the nonce to be incremented */
+ block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
+ for (i = 0; i < inlen; ++i) {
+ if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
+ block_num++;
+ nonce[14] = (uint8_t)(block_num >> 8);
+ nonce[15] = (uint8_t)(block_num);
+ if (!tc_aes_encrypt(buffer, nonce, sched)) {
+ return TC_CRYPTO_FAIL;
+ }
+ }
+ /* update the output */
+ *out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
+ }
+
+ /* update the counter */
+ ctr[14] = nonce[14]; ctr[15] = nonce[15];
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
+ const uint8_t *associated_data,
+ unsigned int alen, const uint8_t *payload,
+ unsigned int plen, TCCcmMode_t c)
+{
+
+ /* input sanity check: */
+ if ((out == (uint8_t *) 0) ||
+ (c == (TCCcmMode_t) 0) ||
+ ((plen > 0) && (payload == (uint8_t *) 0)) ||
+ ((alen > 0) && (associated_data == (uint8_t *) 0)) ||
+ (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
+ (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
+ (olen < (plen + c->mlen))) { /* invalid output buffer size */
+ return TC_CRYPTO_FAIL;
+ }
+
+ uint8_t b[Nb * Nk];
+ uint8_t tag[Nb * Nk];
+ unsigned int i;
+
+ /* GENERATING THE AUTHENTICATION TAG: */
+
+ /* formatting the sequence b for authentication: */
+ b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
+ for (i = 1; i <= 13; ++i) {
+ b[i] = c->nonce[i - 1];
+ }
+ b[14] = (uint8_t)(plen >> 8);
+ b[15] = (uint8_t)(plen);
+
+ /* computing the authentication tag using cbc-mac: */
+ (void) tc_aes_encrypt(tag, b, c->sched);
+ if (alen > 0) {
+ ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
+ }
+ if (plen > 0) {
+ ccm_cbc_mac(tag, payload, plen, 0, c->sched);
+ }
+
+ /* ENCRYPTION: */
+
+ /* formatting the sequence b for encryption: */
+ b[0] = 1; /* q - 1 = 2 - 1 = 1 */
+ b[14] = b[15] = TC_ZERO_BYTE;
+
+ /* encrypting payload using ctr mode: */
+ ccm_ctr_mode(out, plen, payload, plen, b, c->sched);
+
+ b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/
+
+ /* encrypting b and adding the tag to the output: */
+ (void) tc_aes_encrypt(b, b, c->sched);
+ out += plen;
+ for (i = 0; i < c->mlen; ++i) {
+ *out++ = tag[i] ^ b[i];
+ }
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
+ const uint8_t *associated_data,
+ unsigned int alen, const uint8_t *payload,
+ unsigned int plen, TCCcmMode_t c)
+{
+
+ /* input sanity check: */
+ if ((out == (uint8_t *) 0) ||
+ (c == (TCCcmMode_t) 0) ||
+ ((plen > 0) && (payload == (uint8_t *) 0)) ||
+ ((alen > 0) && (associated_data == (uint8_t *) 0)) ||
+ (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
+ (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
+ (olen < plen - c->mlen)) { /* invalid output buffer size */
+ return TC_CRYPTO_FAIL;
+ }
+
+ uint8_t b[Nb * Nk];
+ uint8_t tag[Nb * Nk];
+ unsigned int i;
+
+ /* DECRYPTION: */
+
+ /* formatting the sequence b for decryption: */
+ b[0] = 1; /* q - 1 = 2 - 1 = 1 */
+ for (i = 1; i < 14; ++i) {
+ b[i] = c->nonce[i - 1];
+ }
+ b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */
+
+ /* decrypting payload using ctr mode: */
+ ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);
+
+ b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */
+
+ /* encrypting b and restoring the tag from input: */
+ (void) tc_aes_encrypt(b, b, c->sched);
+ for (i = 0; i < c->mlen; ++i) {
+ tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
+ }
+
+ /* VERIFYING THE AUTHENTICATION TAG: */
+
+ /* formatting the sequence b for authentication: */
+ b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
+ for (i = 1; i < 14; ++i) {
+ b[i] = c->nonce[i - 1];
+ }
+ b[14] = (uint8_t)((plen - c->mlen) >> 8);
+ b[15] = (uint8_t)(plen - c->mlen);
+
+ /* computing the authentication tag using cbc-mac: */
+ (void) tc_aes_encrypt(b, b, c->sched);
+ if (alen > 0) {
+ ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
+ }
+ if (plen > 0) {
+ ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
+ }
+
+ /* comparing the received tag and the computed one: */
+ if (_compare(b, tag, c->mlen) == 0) {
+ return TC_CRYPTO_SUCCESS;
+ } else {
+ /* erase the decrypted buffer in case of mac validation failure: */
+ _set(out, 0, plen - c->mlen);
+ return TC_CRYPTO_FAIL;
+ }
+}
diff --git a/lib/bt/common/tinycrypt/src/cmac_mode.c b/lib/bt/common/tinycrypt/src/cmac_mode.c
new file mode 100644
index 00000000..c3e2c4ee
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/cmac_mode.c
@@ -0,0 +1,258 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/aes.h>
+#include <tinycrypt/cmac_mode.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+/* max number of calls until change the key (2^48).*/
+const static uint64_t MAX_CALLS = ((uint64_t)1 << 48);
+
+/*
+ * gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte
+ * array with byte 0 the most significant and byte 15 the least significant.
+ * High bit carry reduction is based on the primitive polynomial
+ *
+ * X^128 + X^7 + X^2 + X + 1,
+ *
+ * which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed,
+ * since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since
+ * addition of polynomials with coefficients in Z/Z(2) is just XOR, we can
+ * add X^128 to both sides to get
+ *
+ * X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1)
+ *
+ * and the coefficients of the polynomial on the right hand side form the
+ * string 1000 0111 = 0x87, which is the value of gf_wrap.
+ *
+ * This gets used in the following way. Doubling in GF(2^128) is just a left
+ * shift by 1 bit, except when the most significant bit is 1. In the latter
+ * case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit
+ * that overflows beyond 128 bits can be replaced by addition of
+ * X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition
+ * in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87
+ * into the low order byte after a left shift when the starting high order
+ * bit is 1.
+ */
+const unsigned char gf_wrap = 0x87;
+
+/*
+ * assumes: out != NULL and points to a GF(2^n) value to receive the
+ * doubled value;
+ * in != NULL and points to a 16 byte GF(2^n) value
+ * to double;
+ * the in and out buffers do not overlap.
+ * effects: doubles the GF(2^n) value pointed to by "in" and places
+ * the result in the GF(2^n) value pointed to by "out."
+ */
+void gf_double(uint8_t *out, uint8_t *in)
+{
+
+ /* start with low order byte */
+ uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1);
+
+ /* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */
+ uint8_t carry = (in[0] >> 7) ? gf_wrap : 0;
+
+ out += (TC_AES_BLOCK_SIZE - 1);
+ for (;;) {
+ *out-- = (*x << 1) ^ carry;
+ if (x == in) {
+ break;
+ }
+ carry = *x-- >> 7;
+ }
+}
+
+int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched)
+{
+
+ /* input sanity check: */
+ if (s == (TCCmacState_t) 0 ||
+ key == (const uint8_t *) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /* put s into a known state */
+ _set(s, 0, sizeof(*s));
+ s->sched = sched;
+
+ /* configure the encryption key used by the underlying block cipher */
+ tc_aes128_set_encrypt_key(s->sched, key);
+
+ /* compute s->K1 and s->K2 from s->iv using s->keyid */
+ _set(s->iv, 0, TC_AES_BLOCK_SIZE);
+ tc_aes_encrypt(s->iv, s->iv, s->sched);
+ gf_double (s->K1, s->iv);
+ gf_double (s->K2, s->K1);
+
+ /* reset s->iv to 0 in case someone wants to compute now */
+ tc_cmac_init(s);
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_erase(TCCmacState_t s)
+{
+ if (s == (TCCmacState_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /* destroy the current state */
+ _set(s, 0, sizeof(*s));
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_init(TCCmacState_t s)
+{
+ /* input sanity check: */
+ if (s == (TCCmacState_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /* CMAC starts with an all zero initialization vector */
+ _set(s->iv, 0, TC_AES_BLOCK_SIZE);
+
+ /* and the leftover buffer is empty */
+ _set(s->leftover, 0, TC_AES_BLOCK_SIZE);
+ s->leftover_offset = 0;
+
+ /* Set countdown to max number of calls allowed before re-keying: */
+ s->countdown = MAX_CALLS;
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
+{
+ unsigned int i;
+
+ /* input sanity check: */
+ if (s == (TCCmacState_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+ if (data_length == 0) {
+ return TC_CRYPTO_SUCCESS;
+ }
+ if (data == (const uint8_t *) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ if (s->countdown == 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ s->countdown--;
+
+ if (s->leftover_offset > 0) {
+ /* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */
+ size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset;
+
+ if (data_length < remaining_space) {
+ /* still not enough data to encrypt this time either */
+ _copy(&s->leftover[s->leftover_offset], data_length, data, data_length);
+ s->leftover_offset += data_length;
+ return TC_CRYPTO_SUCCESS;
+ }
+ /* leftover block is now full; encrypt it first */
+ _copy(&s->leftover[s->leftover_offset],
+ remaining_space,
+ data,
+ remaining_space);
+ data_length -= remaining_space;
+ data += remaining_space;
+ s->leftover_offset = 0;
+
+ for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+ s->iv[i] ^= s->leftover[i];
+ }
+ tc_aes_encrypt(s->iv, s->iv, s->sched);
+ }
+
+ /* CBC encrypt each (except the last) of the data blocks */
+ while (data_length > TC_AES_BLOCK_SIZE) {
+ for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+ s->iv[i] ^= data[i];
+ }
+ tc_aes_encrypt(s->iv, s->iv, s->sched);
+ data += TC_AES_BLOCK_SIZE;
+ data_length -= TC_AES_BLOCK_SIZE;
+ }
+
+ if (data_length > 0) {
+ /* save leftover data for next time */
+ _copy(s->leftover, data_length, data, data_length);
+ s->leftover_offset = data_length;
+ }
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_cmac_final(uint8_t *tag, TCCmacState_t s)
+{
+ uint8_t *k;
+ unsigned int i;
+
+ /* input sanity check: */
+ if (tag == (uint8_t *) 0 ||
+ s == (TCCmacState_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ if (s->leftover_offset == TC_AES_BLOCK_SIZE) {
+ /* the last message block is a full-sized block */
+ k = (uint8_t *) s->K1;
+ } else {
+ /* the final message block is not a full-sized block */
+ size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset;
+
+ _set(&s->leftover[s->leftover_offset], 0, remaining);
+ s->leftover[s->leftover_offset] = TC_CMAC_PADDING;
+ k = (uint8_t *) s->K2;
+ }
+ for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
+ s->iv[i] ^= s->leftover[i] ^ k[i];
+ }
+
+ tc_aes_encrypt(tag, s->iv, s->sched);
+
+ /* erasing state: */
+ tc_cmac_erase(s);
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/lib/bt/common/tinycrypt/src/ctr_mode.c b/lib/bt/common/tinycrypt/src/ctr_mode.c
new file mode 100644
index 00000000..96d03a5b
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/ctr_mode.c
@@ -0,0 +1,91 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* ctr_mode.c - TinyCrypt CTR mode implementation */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ctr_mode.h>
+#include <tinycrypt/utils.h>
+
+int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
+ unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
+{
+
+ uint8_t buffer[TC_AES_BLOCK_SIZE];
+ uint8_t nonce[TC_AES_BLOCK_SIZE];
+ unsigned int block_num;
+ unsigned int i;
+
+ /* input sanity check: */
+ if (out == (uint8_t *) 0 ||
+ in == (uint8_t *) 0 ||
+ ctr == (uint8_t *) 0 ||
+ sched == (TCAesKeySched_t) 0 ||
+ inlen == 0 ||
+ outlen == 0 ||
+ outlen != inlen) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /* copy the ctr to the nonce */
+ (void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
+
+ /* select the last 4 bytes of the nonce to be incremented */
+ block_num = (nonce[12] << 24) | (nonce[13] << 16) |
+ (nonce[14] << 8) | (nonce[15]);
+ for (i = 0; i < inlen; ++i) {
+ if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
+ /* encrypt data using the current nonce */
+ if (tc_aes_encrypt(buffer, nonce, sched)) {
+ block_num++;
+ nonce[12] = (uint8_t)(block_num >> 24);
+ nonce[13] = (uint8_t)(block_num >> 16);
+ nonce[14] = (uint8_t)(block_num >> 8);
+ nonce[15] = (uint8_t)(block_num);
+ } else {
+ return TC_CRYPTO_FAIL;
+ }
+ }
+ /* update the output */
+ *out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++;
+ }
+
+ /* update the counter */
+ ctr[12] = nonce[12]; ctr[13] = nonce[13];
+ ctr[14] = nonce[14]; ctr[15] = nonce[15];
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/lib/bt/common/tinycrypt/src/ctr_prng.c b/lib/bt/common/tinycrypt/src/ctr_prng.c
new file mode 100644
index 00000000..009c7de2
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/ctr_prng.c
@@ -0,0 +1,283 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2016, Chris Morrison
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/ctr_prng.h>
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+#include <string.h>
+
+/*
+ * This PRNG is based on the CTR_DRBG described in Recommendation for Random
+ * Number Generation Using Deterministic Random Bit Generators,
+ * NIST SP 800-90A Rev. 1.
+ *
+ * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps
+ * described in that document.
+ *
+ */
+
+/**
+ * @brief Array incrementer
+ * Treats the supplied array as one contiguous number (MSB in arr[0]), and
+ * increments it by one
+ * @return none
+ * @param arr IN/OUT -- array to be incremented
+ * @param len IN -- size of arr in bytes
+ */
+static void arrInc(uint8_t arr[], unsigned int len)
+{
+ unsigned int i;
+ if (0 != arr) {
+ for (i = len; i > 0U; i--) {
+ if (++arr[i-1] != 0U) {
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * @brief CTR PRNG update
+ * Updates the internal state of supplied the CTR PRNG context
+ * increments it by one
+ * @return none
+ * @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long
+ * @param ctx IN/OUT -- CTR PRNG state
+ * @param providedData IN -- data used when updating the internal state
+ */
+static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData)
+{
+ if (0 != ctx) {
+ /* 10.2.1.2 step 1 */
+ uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+ unsigned int len = 0U;
+
+ /* 10.2.1.2 step 2 */
+ while (len < sizeof temp) {
+ unsigned int blocklen = sizeof(temp) - len;
+ uint8_t output_block[TC_AES_BLOCK_SIZE];
+
+ /* 10.2.1.2 step 2.1 */
+ arrInc(ctx->V, sizeof ctx->V);
+
+ /* 10.2.1.2 step 2.2 */
+ if (blocklen > TC_AES_BLOCK_SIZE) {
+ blocklen = TC_AES_BLOCK_SIZE;
+ }
+ (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
+
+ /* 10.2.1.2 step 2.3/step 3 */
+ memcpy(&(temp[len]), output_block, blocklen);
+
+ len += blocklen;
+ }
+
+ /* 10.2.1.2 step 4 */
+ if (0 != providedData) {
+ unsigned int i;
+ for (i = 0U; i < sizeof temp; i++) {
+ temp[i] ^= providedData[i];
+ }
+ }
+
+ /* 10.2.1.2 step 5 */
+ (void)tc_aes128_set_encrypt_key(&ctx->key, temp);
+
+ /* 10.2.1.2 step 6 */
+ memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE);
+ }
+}
+
+int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
+ uint8_t const * const entropy,
+ unsigned int entropyLen,
+ uint8_t const * const personalization,
+ unsigned int pLen)
+{
+ int result = TC_CRYPTO_FAIL;
+ unsigned int i;
+ uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+ uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+ uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U};
+
+ if (0 != personalization) {
+ /* 10.2.1.3.1 step 1 */
+ unsigned int len = pLen;
+ if (len > sizeof personalization_buf) {
+ len = sizeof personalization_buf;
+ }
+
+ /* 10.2.1.3.1 step 2 */
+ memcpy(personalization_buf, personalization, len);
+ }
+
+ if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) {
+ /* 10.2.1.3.1 step 3 */
+ memcpy(seed_material, entropy, sizeof seed_material);
+ for (i = 0U; i < sizeof seed_material; i++) {
+ seed_material[i] ^= personalization_buf[i];
+ }
+
+ /* 10.2.1.3.1 step 4 */
+ (void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr);
+
+ /* 10.2.1.3.1 step 5 */
+ memset(ctx->V, 0x00, sizeof ctx->V);
+
+ /* 10.2.1.3.1 step 6 */
+ tc_ctr_prng_update(ctx, seed_material);
+
+ /* 10.2.1.3.1 step 7 */
+ ctx->reseedCount = 1U;
+
+ result = TC_CRYPTO_SUCCESS;
+ }
+ return result;
+}
+
+int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
+ uint8_t const * const entropy,
+ unsigned int entropyLen,
+ uint8_t const * const additional_input,
+ unsigned int additionallen)
+{
+ unsigned int i;
+ int result = TC_CRYPTO_FAIL;
+ uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+ uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
+
+ if (0 != additional_input) {
+ /* 10.2.1.4.1 step 1 */
+ unsigned int len = additionallen;
+ if (len > sizeof additional_input_buf) {
+ len = sizeof additional_input_buf;
+ }
+
+ /* 10.2.1.4.1 step 2 */
+ memcpy(additional_input_buf, additional_input, len);
+ }
+
+ unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE;
+ if ((0 != ctx) && (entropyLen >= seedlen)) {
+ /* 10.2.1.4.1 step 3 */
+ memcpy(seed_material, entropy, sizeof seed_material);
+ for (i = 0U; i < sizeof seed_material; i++) {
+ seed_material[i] ^= additional_input_buf[i];
+ }
+
+ /* 10.2.1.4.1 step 4 */
+ tc_ctr_prng_update(ctx, seed_material);
+
+ /* 10.2.1.4.1 step 5 */
+ ctx->reseedCount = 1U;
+
+ result = TC_CRYPTO_SUCCESS;
+ }
+ return result;
+}
+
+int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
+ uint8_t const * const additional_input,
+ unsigned int additionallen,
+ uint8_t * const out,
+ unsigned int outlen)
+{
+ /* 2^48 - see section 10.2.1 */
+ static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL;
+
+ /* 2^19 bits - see section 10.2.1 */
+ static const unsigned int MAX_BYTES_PER_REQ = 65536U;
+
+ unsigned int result = TC_CRYPTO_FAIL;
+
+ if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) {
+ /* 10.2.1.5.1 step 1 */
+ if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) {
+ result = TC_CTR_PRNG_RESEED_REQ;
+ } else {
+ uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
+ if (0 != additional_input) {
+ /* 10.2.1.5.1 step 2 */
+ unsigned int len = additionallen;
+ if (len > sizeof additional_input_buf) {
+ len = sizeof additional_input_buf;
+ }
+ memcpy(additional_input_buf, additional_input, len);
+ tc_ctr_prng_update(ctx, additional_input_buf);
+ }
+
+ /* 10.2.1.5.1 step 3 - implicit */
+
+ /* 10.2.1.5.1 step 4 */
+ unsigned int len = 0U;
+ while (len < outlen) {
+ unsigned int blocklen = outlen - len;
+ uint8_t output_block[TC_AES_BLOCK_SIZE];
+
+ /* 10.2.1.5.1 step 4.1 */
+ arrInc(ctx->V, sizeof ctx->V);
+
+ /* 10.2.1.5.1 step 4.2 */
+ (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
+
+ /* 10.2.1.5.1 step 4.3/step 5 */
+ if (blocklen > TC_AES_BLOCK_SIZE) {
+ blocklen = TC_AES_BLOCK_SIZE;
+ }
+ memcpy(&(out[len]), output_block, blocklen);
+
+ len += blocklen;
+ }
+
+ /* 10.2.1.5.1 step 6 */
+ tc_ctr_prng_update(ctx, additional_input_buf);
+
+ /* 10.2.1.5.1 step 7 */
+ ctx->reseedCount++;
+
+ /* 10.2.1.5.1 step 8 */
+ result = TC_CRYPTO_SUCCESS;
+ }
+ }
+
+ return result;
+}
+
+void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx)
+{
+ if (0 != ctx) {
+ memset(ctx->key.words, 0x00, sizeof ctx->key.words);
+ memset(ctx->V, 0x00, sizeof ctx->V);
+ ctx->reseedCount = 0U;
+ }
+}
diff --git a/lib/bt/common/tinycrypt/src/ecc.c b/lib/bt/common/tinycrypt/src/ecc.c
new file mode 100644
index 00000000..1027c9a2
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/ecc.c
@@ -0,0 +1,972 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_platform_specific.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "esp_tinycrypt_port.h"
+
+/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
+ * has access to enough entropy in order to feed the PRNG regularly. */
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+void uECC_set_rng(uECC_RNG_Function rng_function)
+{
+ g_rng_function = rng_function;
+}
+
+uECC_RNG_Function uECC_get_rng(void)
+{
+ return g_rng_function;
+}
+
+int uECC_curve_private_key_size(uECC_Curve curve)
+{
+ return BITS_TO_BYTES(curve->num_n_bits);
+}
+
+int uECC_curve_public_key_size(uECC_Curve curve)
+{
+ return 2 * curve->num_bytes;
+}
+
+void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words)
+{
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ vli[i] = 0;
+ }
+}
+
+uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words)
+{
+ uECC_word_t bits = 0;
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ bits |= vli[i];
+ }
+ return (bits == 0);
+}
+
+uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
+{
+ return (vli[bit >> uECC_WORD_BITS_SHIFT] &
+ ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
+}
+
+/* Counts the number of words in vli. */
+static wordcount_t vli_numDigits(const uECC_word_t *vli,
+ const wordcount_t max_words)
+{
+
+ wordcount_t i;
+ /* Search from the end until we find a non-zero digit. We do it in reverse
+ * because we expect that most digits will be nonzero. */
+ for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
+ }
+
+ return (i + 1);
+}
+
+bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
+ const wordcount_t max_words)
+{
+
+ uECC_word_t i;
+ uECC_word_t digit;
+
+ wordcount_t num_digits = vli_numDigits(vli, max_words);
+ if (num_digits == 0) {
+ return 0;
+ }
+
+ digit = vli[num_digits - 1];
+ for (i = 0; digit; ++i) {
+ digit >>= 1;
+ }
+
+ return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
+}
+
+void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
+ wordcount_t num_words)
+{
+ wordcount_t i;
+
+ for (i = 0; i < num_words; ++i) {
+ dest[i] = src[i];
+ }
+}
+
+cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
+ const uECC_word_t *right,
+ wordcount_t num_words)
+{
+ wordcount_t i;
+
+ for (i = num_words - 1; i >= 0; --i) {
+ if (left[i] > right[i]) {
+ return 1;
+ } else if (left[i] < right[i]) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
+ wordcount_t num_words)
+{
+
+ uECC_word_t diff = 0;
+ wordcount_t i;
+
+ for (i = num_words - 1; i >= 0; --i) {
+ diff |= (left[i] ^ right[i]);
+ }
+ return !(diff == 0);
+}
+
+uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
+{
+ return (p_true*(cond)) | (p_false*(!cond));
+}
+
+/* Computes result = left - right, returning borrow, in constant time.
+ * Can modify in place. */
+uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, wordcount_t num_words)
+{
+ uECC_word_t borrow = 0;
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ uECC_word_t diff = left[i] - right[i] - borrow;
+ uECC_word_t val = (diff > left[i]);
+ borrow = cond_set(val, borrow, (diff != left[i]));
+
+ result[i] = diff;
+ }
+ return borrow;
+}
+
+/* Computes result = left + right, returning carry, in constant time.
+ * Can modify in place. */
+static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, wordcount_t num_words)
+{
+ uECC_word_t carry = 0;
+ wordcount_t i;
+ for (i = 0; i < num_words; ++i) {
+ uECC_word_t sum = left[i] + right[i] + carry;
+ uECC_word_t val = (sum < left[i]);
+ carry = cond_set(val, carry, (sum != left[i]));
+ result[i] = sum;
+ }
+ return carry;
+}
+
+cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
+ wordcount_t num_words)
+{
+ uECC_word_t tmp[NUM_ECC_WORDS];
+ uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
+ uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
+ return (!equal - 2 * neg);
+}
+
+/* Computes vli = vli >> 1. */
+static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words)
+{
+ uECC_word_t *end = vli;
+ uECC_word_t carry = 0;
+
+ vli += num_words;
+ while (vli-- > end) {
+ uECC_word_t temp = *vli;
+ *vli = (temp >> 1) | carry;
+ carry = temp << (uECC_WORD_BITS - 1);
+ }
+}
+
+static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0,
+ uECC_word_t *r1, uECC_word_t *r2)
+{
+
+ uECC_dword_t p = (uECC_dword_t)a * b;
+ uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
+ r01 += p;
+ *r2 += (r01 < p);
+ *r1 = r01 >> uECC_WORD_BITS;
+ *r0 = (uECC_word_t)r01;
+
+}
+
+/* Computes result = left * right. Result must be 2 * num_words long. */
+static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, wordcount_t num_words)
+{
+
+ uECC_word_t r0 = 0;
+ uECC_word_t r1 = 0;
+ uECC_word_t r2 = 0;
+ wordcount_t i, k;
+
+ /* Compute each digit of result in sequence, maintaining the carries. */
+ for (k = 0; k < num_words; ++k) {
+
+ for (i = 0; i <= k; ++i) {
+ muladd(left[i], right[k - i], &r0, &r1, &r2);
+ }
+
+ result[k] = r0;
+ r0 = r1;
+ r1 = r2;
+ r2 = 0;
+ }
+
+ for (k = num_words; k < num_words * 2 - 1; ++k) {
+
+ for (i = (k + 1) - num_words; i < num_words; ++i) {
+ muladd(left[i], right[k - i], &r0, &r1, &r2);
+ }
+ result[k] = r0;
+ r0 = r1;
+ r1 = r2;
+ r2 = 0;
+ }
+ result[num_words * 2 - 1] = r0;
+}
+
+void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, const uECC_word_t *mod,
+ wordcount_t num_words)
+{
+ uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
+ if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
+ /* result > mod (result = mod + remainder), so subtract mod to get
+ * remainder. */
+ uECC_vli_sub(result, result, mod, num_words);
+ }
+}
+
+void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, const uECC_word_t *mod,
+ wordcount_t num_words)
+{
+ uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
+ if (l_borrow) {
+ /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
+ * we can get the correct result from result + mod (with overflow). */
+ uECC_vli_add(result, result, mod, num_words);
+ }
+}
+
+/* Computes result = product % mod, where product is 2N words long. */
+/* Currently only designed to work for curve_p or curve_n. */
+void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
+ const uECC_word_t *mod, wordcount_t num_words)
+{
+ uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
+ uECC_word_t tmp[2 * NUM_ECC_WORDS];
+ uECC_word_t *v[2] = {tmp, product};
+ uECC_word_t index;
+
+ /* Shift mod so its highest set bit is at the maximum position. */
+ bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
+ uECC_vli_numBits(mod, num_words);
+ wordcount_t word_shift = shift / uECC_WORD_BITS;
+ wordcount_t bit_shift = shift % uECC_WORD_BITS;
+ uECC_word_t carry = 0;
+ uECC_vli_clear(mod_multiple, word_shift);
+ if (bit_shift > 0) {
+ for(index = 0; index < (uECC_word_t)num_words; ++index) {
+ mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
+ carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
+ }
+ } else {
+ uECC_vli_set(mod_multiple + word_shift, mod, num_words);
+ }
+
+ for (index = 1; shift >= 0; --shift) {
+ uECC_word_t borrow = 0;
+ wordcount_t i;
+ for (i = 0; i < num_words * 2; ++i) {
+ uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
+ if (diff != v[index][i]) {
+ borrow = (diff > v[index][i]);
+ }
+ v[1 - index][i] = diff;
+ }
+ /* Swap the index if there was no borrow */
+ index = !(index ^ borrow);
+ uECC_vli_rshift1(mod_multiple, num_words);
+ mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
+ (uECC_WORD_BITS - 1);
+ uECC_vli_rshift1(mod_multiple + num_words, num_words);
+ }
+ uECC_vli_set(result, v[index], num_words);
+}
+
+void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, const uECC_word_t *mod,
+ wordcount_t num_words)
+{
+ uECC_word_t product[2 * NUM_ECC_WORDS];
+ uECC_vli_mult(product, left, right, num_words);
+ uECC_vli_mmod(result, product, mod, num_words);
+}
+
+void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
+ const uECC_word_t *right, uECC_Curve curve)
+{
+ uECC_word_t product[2 * NUM_ECC_WORDS];
+ uECC_vli_mult(product, left, right, curve->num_words);
+
+ curve->mmod_fast(result, product);
+}
+
+static void uECC_vli_modSquare_fast(uECC_word_t *result,
+ const uECC_word_t *left,
+ uECC_Curve curve)
+{
+ uECC_vli_modMult_fast(result, left, left, curve);
+}
+
+
+#define EVEN(vli) (!(vli[0] & 1))
+
+static void vli_modInv_update(uECC_word_t *uv,
+ const uECC_word_t *mod,
+ wordcount_t num_words)
+{
+
+ uECC_word_t carry = 0;
+
+ if (!EVEN(uv)) {
+ carry = uECC_vli_add(uv, uv, mod, num_words);
+ }
+ uECC_vli_rshift1(uv, num_words);
+ if (carry) {
+ uv[num_words - 1] |= HIGH_BIT_SET;
+ }
+}
+
+void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
+ const uECC_word_t *mod, wordcount_t num_words)
+{
+ uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
+ uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
+ cmpresult_t cmpResult;
+
+ if (uECC_vli_isZero(input, num_words)) {
+ uECC_vli_clear(result, num_words);
+ return;
+ }
+
+ uECC_vli_set(a, input, num_words);
+ uECC_vli_set(b, mod, num_words);
+ uECC_vli_clear(u, num_words);
+ u[0] = 1;
+ uECC_vli_clear(v, num_words);
+ while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
+ if (EVEN(a)) {
+ uECC_vli_rshift1(a, num_words);
+ vli_modInv_update(u, mod, num_words);
+ } else if (EVEN(b)) {
+ uECC_vli_rshift1(b, num_words);
+ vli_modInv_update(v, mod, num_words);
+ } else if (cmpResult > 0) {
+ uECC_vli_sub(a, a, b, num_words);
+ uECC_vli_rshift1(a, num_words);
+ if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
+ uECC_vli_add(u, u, mod, num_words);
+ }
+ uECC_vli_sub(u, u, v, num_words);
+ vli_modInv_update(u, mod, num_words);
+ } else {
+ uECC_vli_sub(b, b, a, num_words);
+ uECC_vli_rshift1(b, num_words);
+ if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
+ uECC_vli_add(v, v, mod, num_words);
+ }
+ uECC_vli_sub(v, v, u, num_words);
+ vli_modInv_update(v, mod, num_words);
+ }
+ }
+ uECC_vli_set(result, u, num_words);
+}
+
+/* ------ Point operations ------ */
+
+void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
+ uECC_word_t * Z1, uECC_Curve curve)
+{
+ /* t1 = X, t2 = Y, t3 = Z */
+ uECC_word_t t4[NUM_ECC_WORDS];
+ uECC_word_t t5[NUM_ECC_WORDS];
+ wordcount_t num_words = curve->num_words;
+
+ if (uECC_vli_isZero(Z1, num_words)) {
+ return;
+ }
+
+ uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
+ uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
+ uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
+ uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
+ uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
+
+ uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
+ uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
+ uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
+ uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
+
+ uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
+ uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
+ if (uECC_vli_testBit(X1, 0)) {
+ uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
+ uECC_vli_rshift1(X1, num_words);
+ X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
+ } else {
+ uECC_vli_rshift1(X1, num_words);
+ }
+
+ /* t1 = 3/2*(x1^2 - z1^4) = B */
+ uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
+ uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
+ uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
+ uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
+ uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
+ /* t4 = B * (A - x3) - y1^4 = y3: */
+ uECC_vli_modSub(t4, X1, t4, curve->p, num_words);
+
+ uECC_vli_set(X1, Z1, num_words);
+ uECC_vli_set(Z1, Y1, num_words);
+ uECC_vli_set(Y1, t4, num_words);
+}
+
+void x_side_default(uECC_word_t *result,
+ const uECC_word_t *x,
+ uECC_Curve curve)
+{
+ uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
+ wordcount_t num_words = curve->num_words;
+
+ uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
+ uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
+ uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
+ /* r = x^3 - 3x + b: */
+ uECC_vli_modAdd(result, result, curve->b, curve->p, num_words);
+}
+
+uECC_Curve uECC_secp256r1(void)
+{
+ return &curve_secp256r1;
+}
+
+void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
+{
+ unsigned int tmp[NUM_ECC_WORDS];
+ int carry;
+
+ /* t */
+ uECC_vli_set(result, product, NUM_ECC_WORDS);
+
+ /* s1 */
+ tmp[0] = tmp[1] = tmp[2] = 0;
+ tmp[3] = product[11];
+ tmp[4] = product[12];
+ tmp[5] = product[13];
+ tmp[6] = product[14];
+ tmp[7] = product[15];
+ carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
+ carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+ /* s2 */
+ tmp[3] = product[12];
+ tmp[4] = product[13];
+ tmp[5] = product[14];
+ tmp[6] = product[15];
+ tmp[7] = 0;
+ carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
+ carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+ /* s3 */
+ tmp[0] = product[8];
+ tmp[1] = product[9];
+ tmp[2] = product[10];
+ tmp[3] = tmp[4] = tmp[5] = 0;
+ tmp[6] = product[14];
+ tmp[7] = product[15];
+ carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+ /* s4 */
+ tmp[0] = product[9];
+ tmp[1] = product[10];
+ tmp[2] = product[11];
+ tmp[3] = product[13];
+ tmp[4] = product[14];
+ tmp[5] = product[15];
+ tmp[6] = product[13];
+ tmp[7] = product[8];
+ carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
+
+ /* d1 */
+ tmp[0] = product[11];
+ tmp[1] = product[12];
+ tmp[2] = product[13];
+ tmp[3] = tmp[4] = tmp[5] = 0;
+ tmp[6] = product[8];
+ tmp[7] = product[10];
+ carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+ /* d2 */
+ tmp[0] = product[12];
+ tmp[1] = product[13];
+ tmp[2] = product[14];
+ tmp[3] = product[15];
+ tmp[4] = tmp[5] = 0;
+ tmp[6] = product[9];
+ tmp[7] = product[11];
+ carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+ /* d3 */
+ tmp[0] = product[13];
+ tmp[1] = product[14];
+ tmp[2] = product[15];
+ tmp[3] = product[8];
+ tmp[4] = product[9];
+ tmp[5] = product[10];
+ tmp[6] = 0;
+ tmp[7] = product[12];
+ carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+ /* d4 */
+ tmp[0] = product[14];
+ tmp[1] = product[15];
+ tmp[2] = 0;
+ tmp[3] = product[9];
+ tmp[4] = product[10];
+ tmp[5] = product[11];
+ tmp[6] = 0;
+ tmp[7] = product[13];
+ carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
+
+ if (carry < 0) {
+ do {
+ carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
+ }
+ while (carry < 0);
+ } else {
+ while (carry ||
+ uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) {
+ carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
+ }
+ }
+}
+
+uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve)
+{
+ return uECC_vli_isZero(point, curve->num_words * 2);
+}
+
+void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
+ uECC_Curve curve)
+{
+ uECC_word_t t1[NUM_ECC_WORDS];
+
+ uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */
+ uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
+ uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */
+ uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
+}
+
+#if !SOC_ECC_SUPPORTED
+/* P = (x1, y1) => 2P, (x2, y2) => P' */
+static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
+ uECC_word_t * X2, uECC_word_t * Y2,
+ const uECC_word_t * const initial_Z,
+ uECC_Curve curve)
+{
+ uECC_word_t z[NUM_ECC_WORDS];
+ wordcount_t num_words = curve->num_words;
+ if (initial_Z) {
+ uECC_vli_set(z, initial_Z, num_words);
+ } else {
+ uECC_vli_clear(z, num_words);
+ z[0] = 1;
+ }
+
+ uECC_vli_set(X2, X1, num_words);
+ uECC_vli_set(Y2, Y1, num_words);
+
+ apply_z(X1, Y1, z, curve);
+ curve->double_jacobian(X1, Y1, z, curve);
+ apply_z(X2, Y2, z, curve);
+}
+
+
+/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
+ Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
+ or P => P - Q, Q => P + Q
+ */
+static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
+ uECC_word_t * X2, uECC_word_t * Y2,
+ uECC_Curve curve)
+{
+ /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+ uECC_word_t t5[NUM_ECC_WORDS];
+ uECC_word_t t6[NUM_ECC_WORDS];
+ uECC_word_t t7[NUM_ECC_WORDS];
+ wordcount_t num_words = curve->num_words;
+
+ uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
+ uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
+ uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
+ uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
+ uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
+ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
+
+ uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
+ uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
+ uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
+ uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
+ uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
+
+ uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
+ uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
+ /* t4 = (y2 - y1)*(B - x3) - E = y3: */
+ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words);
+
+ uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
+ uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
+ uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
+ uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
+ /* t2 = (y2+y1)*(x3' - B) - E = y3': */
+ uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words);
+
+ uECC_vli_set(X1, t7, num_words);
+}
+#endif /* !SOC_ECC_SUPPORTED */
+
+void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
+ uECC_word_t * X2, uECC_word_t * Y2,
+ uECC_Curve curve)
+{
+ /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
+ uECC_word_t t5[NUM_ECC_WORDS];
+ wordcount_t num_words = curve->num_words;
+
+ uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
+ uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
+ uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
+ uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
+ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
+ uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
+
+ uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
+ uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
+ uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
+ uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
+ uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
+ uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
+ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
+
+ uECC_vli_set(X2, t5, num_words);
+}
+
+void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
+ const uECC_word_t * scalar,
+ const uECC_word_t * initial_Z,
+ bitcount_t num_bits, uECC_Curve curve)
+{
+#if SOC_ECC_SUPPORTED
+ wordcount_t num_words = curve->num_words;
+
+ /* Only p256r1 is supported currently. */
+ assert (curve == uECC_secp256r1());
+
+ esp_tinycrypt_calc_ecc_mult((const uint8_t *)&point[0], (const uint8_t *)&point[num_words],
+ (uint8_t *)scalar, (uint8_t *)&result[0], (uint8_t *)&result[num_words],
+ num_words * uECC_WORD_SIZE, false);
+#else
+ /* R0 and R1 */
+ uECC_word_t Rx[2][NUM_ECC_WORDS];
+ uECC_word_t Ry[2][NUM_ECC_WORDS];
+ uECC_word_t z[NUM_ECC_WORDS];
+ bitcount_t i;
+ uECC_word_t nb;
+ wordcount_t num_words = curve->num_words;
+
+ uECC_vli_set(Rx[1], point, num_words);
+ uECC_vli_set(Ry[1], point + num_words, num_words);
+
+ XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
+
+ for (i = num_bits - 2; i > 0; --i) {
+ nb = !uECC_vli_testBit(scalar, i);
+ XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
+ XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
+ }
+
+ nb = !uECC_vli_testBit(scalar, 0);
+ XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
+
+ /* Find final 1/Z value. */
+ uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
+ uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
+ uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
+ uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/
+ /* yP / (xP * Yb * (X1 - X0)) */
+ uECC_vli_modMult_fast(z, z, point + num_words, curve);
+ /* Xb * yP / (xP * Yb * (X1 - X0)) */
+ uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve);
+ /* End 1/Z calculation */
+
+ XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
+ apply_z(Rx[0], Ry[0], z, curve);
+
+ uECC_vli_set(result, Rx[0], num_words);
+ uECC_vli_set(result + num_words, Ry[0], num_words);
+#endif /* SOC_ECC_SUPPORTED */
+}
+
+uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
+ uECC_word_t *k1, uECC_Curve curve)
+{
+
+ wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+
+ bitcount_t num_n_bits = curve->num_n_bits;
+
+ uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
+ (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
+ uECC_vli_testBit(k0, num_n_bits));
+
+ uECC_vli_add(k1, k0, curve->n, num_n_words);
+
+ return carry;
+}
+
+uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
+ uECC_word_t *private_key,
+ uECC_Curve curve)
+{
+
+ uECC_word_t tmp1[NUM_ECC_WORDS];
+ uECC_word_t tmp2[NUM_ECC_WORDS];
+ uECC_word_t *p2[2] = {tmp1, tmp2};
+ uECC_word_t carry;
+
+ /* Regularize the bitcount for the private key so that attackers cannot
+ * use a side channel attack to learn the number of leading zeros. */
+ carry = regularize_k(private_key, tmp1, tmp2, curve);
+
+ EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
+
+ if (EccPoint_isZero(result, curve)) {
+ return 0;
+ }
+ return 1;
+}
+
+/* Converts an integer in uECC native format to big-endian bytes. */
+void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
+ const unsigned int *native)
+{
+ wordcount_t i;
+ for (i = 0; i < num_bytes; ++i) {
+ unsigned b = num_bytes - 1 - i;
+ bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
+ }
+}
+
+/* Converts big-endian bytes to an integer in uECC native format. */
+void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
+ int num_bytes)
+{
+ wordcount_t i;
+ uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
+ for (i = 0; i < num_bytes; ++i) {
+ unsigned b = num_bytes - 1 - i;
+ native[b / uECC_WORD_SIZE] |=
+ (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
+ }
+}
+
+int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
+ wordcount_t num_words)
+{
+ uECC_word_t mask = (uECC_word_t)-1;
+ uECC_word_t tries;
+ bitcount_t num_bits = uECC_vli_numBits(top, num_words);
+
+ if (!g_rng_function) {
+ return 0;
+ }
+
+ for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+ if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
+ return 0;
+ }
+ random[num_words - 1] &=
+ mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
+ if (!uECC_vli_isZero(random, num_words) &&
+ uECC_vli_cmp(top, random, num_words) == 1) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
+{
+ wordcount_t num_words = curve->num_words;
+
+ /* The point at infinity is invalid. */
+ if (EccPoint_isZero(point, curve)) {
+ return -1;
+ }
+
+ /* x and y must be smaller than p. */
+ if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
+ uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
+ return -2;
+ }
+
+#if SOC_ECC_SUPPORTED
+ /* Only p256r1 is supported currently. */
+ if (curve != uECC_secp256r1()) {
+ return -5;
+ }
+
+ if (esp_tinycrypt_verify_ecc_point((const uint8_t *)&point[0],
+ (const uint8_t *)&point[num_words],
+ num_words * uECC_WORD_SIZE)) {
+ return -3;
+ }
+#else
+ uECC_word_t tmp1[NUM_ECC_WORDS];
+ uECC_word_t tmp2[NUM_ECC_WORDS];
+
+ uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
+ curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
+
+ /* Make sure that y^2 == x^3 + ax + b */
+ if (uECC_vli_equal(tmp1, tmp2, num_words) != 0)
+ return -3;
+#endif /* SOC_ECC_SUPPORTED */
+
+ return 0;
+}
+
+int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
+{
+ uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+ uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
+ uECC_vli_bytesToNative(
+ _public + curve->num_words,
+ public_key + curve->num_bytes,
+ curve->num_bytes);
+
+ if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) {
+ return -4;
+ }
+
+ return uECC_valid_point(_public, curve);
+}
+
+int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
+ uECC_Curve curve)
+{
+ uECC_word_t _private[NUM_ECC_WORDS];
+ uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+ uECC_vli_bytesToNative(
+ _private,
+ private_key,
+ BITS_TO_BYTES(curve->num_n_bits));
+
+ /* Make sure the private key is in the range [1, n-1]. */
+ if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
+ return 0;
+ }
+
+ if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
+ return 0;
+ }
+
+ /* Compute public key. */
+ if (!EccPoint_compute_public_key(_public, _private, curve)) {
+ return 0;
+ }
+
+ uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
+ uECC_vli_nativeToBytes(
+ public_key +
+ curve->num_bytes, curve->num_bytes, _public + curve->num_words);
+ return 1;
+}
diff --git a/lib/bt/common/tinycrypt/src/ecc_dh.c b/lib/bt/common/tinycrypt/src/ecc_dh.c
new file mode 100644
index 00000000..fab692da
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/ecc_dh.c
@@ -0,0 +1,204 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_dh.h>
+#include <string.h>
+
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
+ unsigned int *d, uECC_Curve curve)
+{
+
+ uECC_word_t _private[NUM_ECC_WORDS];
+ uECC_word_t _public[NUM_ECC_WORDS * 2];
+
+ /* This function is designed for test purposes-only (such as validating NIST
+ * test vectors) as it uses a provided value for d instead of generating
+ * it uniformly at random. */
+ memcpy (_private, d, NUM_ECC_BYTES);
+
+ /* Computing public-key from private: */
+ if (EccPoint_compute_public_key(_public, _private, curve)) {
+
+ /* Converting buffers to correct bit order: */
+ uECC_vli_nativeToBytes(private_key,
+ BITS_TO_BYTES(curve->num_n_bits),
+ _private);
+ uECC_vli_nativeToBytes(public_key,
+ curve->num_bytes,
+ _public);
+ uECC_vli_nativeToBytes(public_key + curve->num_bytes,
+ curve->num_bytes,
+ _public + curve->num_words);
+
+ /* erasing temporary buffer used to store secret: */
+ memset(_private, 0, NUM_ECC_BYTES);
+
+ return 1;
+ }
+ return 0;
+}
+
+int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve)
+{
+
+ uECC_word_t _random[NUM_ECC_WORDS * 2];
+ uECC_word_t _private[NUM_ECC_WORDS];
+ uECC_word_t _public[NUM_ECC_WORDS * 2];
+ uECC_word_t tries;
+
+ for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+ /* Generating _private uniformly at random: */
+ uECC_RNG_Function rng_function = uECC_get_rng();
+ if (!rng_function ||
+ !rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
+ return 0;
+ }
+
+ /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
+ uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
+
+ /* Computing public-key from private: */
+ if (EccPoint_compute_public_key(_public, _private, curve)) {
+
+ /* Converting buffers to correct bit order: */
+ uECC_vli_nativeToBytes(private_key,
+ BITS_TO_BYTES(curve->num_n_bits),
+ _private);
+ uECC_vli_nativeToBytes(public_key,
+ curve->num_bytes,
+ _public);
+ uECC_vli_nativeToBytes(public_key + curve->num_bytes,
+ curve->num_bytes,
+ _public + curve->num_words);
+
+ /* erasing temporary buffer that stored secret: */
+ memset(_private, 0, NUM_ECC_BYTES);
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
+ uint8_t *secret, uECC_Curve curve)
+{
+
+ uECC_word_t _public[NUM_ECC_WORDS * 2];
+ uECC_word_t _private[NUM_ECC_WORDS];
+
+ uECC_word_t tmp[NUM_ECC_WORDS];
+ uECC_word_t *p2[2] = {_private, tmp};
+ uECC_word_t *initial_Z = 0;
+ uECC_word_t carry;
+ wordcount_t num_words = curve->num_words;
+ wordcount_t num_bytes = curve->num_bytes;
+ int r;
+
+ /* Converting buffers to correct bit order: */
+ uECC_vli_bytesToNative(_private,
+ private_key,
+ BITS_TO_BYTES(curve->num_n_bits));
+ uECC_vli_bytesToNative(_public,
+ public_key,
+ num_bytes);
+ uECC_vli_bytesToNative(_public + num_words,
+ public_key + num_bytes,
+ num_bytes);
+
+ /* Regularize the bitcount for the private key so that attackers cannot use a
+ * side channel attack to learn the number of leading zeros. */
+ carry = regularize_k(_private, _private, tmp, curve);
+
+ /* If an RNG function was specified, try to get a random initial Z value to
+ * improve protection against side-channel attacks. */
+ if (g_rng_function) {
+ if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
+ r = 0;
+ goto clear_and_out;
+ }
+ initial_Z = p2[carry];
+ }
+
+ EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
+ curve);
+
+ uECC_vli_nativeToBytes(secret, num_bytes, _public);
+ r = !EccPoint_isZero(_public, curve);
+
+clear_and_out:
+ /* erasing temporary buffer used to store secret: */
+ memset(p2, 0, sizeof(p2));
+ __asm__ __volatile__("" :: "g"(p2) : "memory");
+ memset(tmp, 0, sizeof(tmp));
+ __asm__ __volatile__("" :: "g"(tmp) : "memory");
+ memset(_private, 0, sizeof(_private));
+ __asm__ __volatile__("" :: "g"(_private) : "memory");
+
+ return r;
+}
diff --git a/lib/bt/common/tinycrypt/src/ecc_dsa.c b/lib/bt/common/tinycrypt/src/ecc_dsa.c
new file mode 100644
index 00000000..03a91f09
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/ecc_dsa.c
@@ -0,0 +1,298 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/constants.h>
+#include <tinycrypt/ecc.h>
+#include <tinycrypt/ecc_dsa.h>
+
+#if default_RNG_defined
+static uECC_RNG_Function g_rng_function = &default_CSPRNG;
+#else
+static uECC_RNG_Function g_rng_function = 0;
+#endif
+
+static void bits2int(uECC_word_t *native, const uint8_t *bits,
+ unsigned bits_size, uECC_Curve curve)
+{
+ unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
+ unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+ int shift;
+ uECC_word_t carry;
+ uECC_word_t *ptr;
+
+ if (bits_size > num_n_bytes) {
+ bits_size = num_n_bytes;
+ }
+
+ uECC_vli_clear(native, num_n_words);
+ uECC_vli_bytesToNative(native, bits, bits_size);
+ if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
+ return;
+ }
+ shift = bits_size * 8 - curve->num_n_bits;
+ carry = 0;
+ ptr = native + num_n_words;
+ while (ptr-- > native) {
+ uECC_word_t temp = *ptr;
+ *ptr = (temp >> shift) | carry;
+ carry = temp << (uECC_WORD_BITS - shift);
+ }
+
+ /* Reduce mod curve_n */
+ if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
+ uECC_vli_sub(native, native, curve->n, num_n_words);
+ }
+}
+
+int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
+ unsigned hash_size, uECC_word_t *k, uint8_t *signature,
+ uECC_Curve curve)
+{
+
+ uECC_word_t tmp[NUM_ECC_WORDS];
+ uECC_word_t s[NUM_ECC_WORDS];
+ uECC_word_t *k2[2] = {tmp, s};
+ uECC_word_t p[NUM_ECC_WORDS * 2];
+ uECC_word_t carry;
+ wordcount_t num_words = curve->num_words;
+ wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+ bitcount_t num_n_bits = curve->num_n_bits;
+
+ /* Make sure 0 < k < curve_n */
+ if (uECC_vli_isZero(k, num_words) ||
+ uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
+ return 0;
+ }
+
+ carry = regularize_k(k, tmp, s, curve);
+ EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
+ if (uECC_vli_isZero(p, num_words)) {
+ return 0;
+ }
+
+ /* If an RNG function was specified, get a random number
+ to prevent side channel analysis of k. */
+ if (!g_rng_function) {
+ uECC_vli_clear(tmp, num_n_words);
+ tmp[0] = 1;
+ }
+ else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
+ return 0;
+ }
+
+ /* Prevent side channel analysis of uECC_vli_modInv() to determine
+ bits of k / the private key by premultiplying by a random number */
+ uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
+ uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */
+ uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
+
+ uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
+
+ /* tmp = d: */
+ uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
+
+ s[num_n_words - 1] = 0;
+ uECC_vli_set(s, p, num_words);
+ uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
+
+ bits2int(tmp, message_hash, hash_size, curve);
+ uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
+ uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
+ if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
+ return 0;
+ }
+
+ uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
+ return 1;
+}
+
+int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
+ unsigned hash_size, uint8_t *signature, uECC_Curve curve)
+{
+ uECC_word_t _random[2*NUM_ECC_WORDS];
+ uECC_word_t k[NUM_ECC_WORDS];
+ uECC_word_t tries;
+
+ for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
+ /* Generating _random uniformly at random: */
+ uECC_RNG_Function rng_function = uECC_get_rng();
+ if (!rng_function ||
+ !rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
+ return 0;
+ }
+
+ // computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
+ uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
+
+ if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature,
+ curve)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static bitcount_t smax(bitcount_t a, bitcount_t b)
+{
+ return (a > b ? a : b);
+}
+
+int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash,
+ unsigned hash_size, const uint8_t *signature,
+ uECC_Curve curve)
+{
+
+ uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS];
+ uECC_word_t z[NUM_ECC_WORDS];
+ uECC_word_t sum[NUM_ECC_WORDS * 2];
+ uECC_word_t rx[NUM_ECC_WORDS];
+ uECC_word_t ry[NUM_ECC_WORDS];
+ uECC_word_t tx[NUM_ECC_WORDS];
+ uECC_word_t ty[NUM_ECC_WORDS];
+ uECC_word_t tz[NUM_ECC_WORDS];
+ const uECC_word_t *points[4];
+ const uECC_word_t *point;
+ bitcount_t num_bits;
+ bitcount_t i;
+
+ uECC_word_t _public[NUM_ECC_WORDS * 2];
+ uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS];
+ wordcount_t num_words = curve->num_words;
+ wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
+
+ rx[num_n_words - 1] = 0;
+ r[num_n_words - 1] = 0;
+ s[num_n_words - 1] = 0;
+
+ uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
+ uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes,
+ curve->num_bytes);
+ uECC_vli_bytesToNative(r, signature, curve->num_bytes);
+ uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
+
+ /* r, s must not be 0. */
+ if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
+ return 0;
+ }
+
+ /* r, s must be < n. */
+ if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
+ uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
+ return 0;
+ }
+
+ /* Calculate u1 and u2. */
+ uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
+ u1[num_n_words - 1] = 0;
+ bits2int(u1, message_hash, hash_size, curve);
+ uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
+ uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
+
+ /* Calculate sum = G + Q. */
+ uECC_vli_set(sum, _public, num_words);
+ uECC_vli_set(sum + num_words, _public + num_words, num_words);
+ uECC_vli_set(tx, curve->G, num_words);
+ uECC_vli_set(ty, curve->G + num_words, num_words);
+ uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
+ XYcZ_add(tx, ty, sum, sum + num_words, curve);
+ uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
+ apply_z(sum, sum + num_words, z, curve);
+
+ /* Use Shamir's trick to calculate u1*G + u2*Q */
+ points[0] = 0;
+ points[1] = curve->G;
+ points[2] = _public;
+ points[3] = sum;
+ num_bits = smax(uECC_vli_numBits(u1, num_n_words),
+ uECC_vli_numBits(u2, num_n_words));
+
+ point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
+ ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
+ uECC_vli_set(rx, point, num_words);
+ uECC_vli_set(ry, point + num_words, num_words);
+ uECC_vli_clear(z, num_words);
+ z[0] = 1;
+
+ for (i = num_bits - 2; i >= 0; --i) {
+ uECC_word_t index;
+ curve->double_jacobian(rx, ry, z, curve);
+
+ index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
+ point = points[index];
+ if (point) {
+ uECC_vli_set(tx, point, num_words);
+ uECC_vli_set(ty, point + num_words, num_words);
+ apply_z(tx, ty, z, curve);
+ uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
+ XYcZ_add(tx, ty, rx, ry, curve);
+ uECC_vli_modMult_fast(z, z, tz, curve);
+ }
+ }
+
+ uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
+ apply_z(rx, ry, z, curve);
+
+ /* v = x1 (mod n) */
+ if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
+ uECC_vli_sub(rx, rx, curve->n, num_n_words);
+ }
+
+ /* Accept only if v == r. */
+ return (int)(uECC_vli_equal(rx, r, num_words) == 0);
+}
diff --git a/lib/bt/common/tinycrypt/src/ecc_platform_specific.c b/lib/bt/common/tinycrypt/src/ecc_platform_specific.c
new file mode 100644
index 00000000..b76ea994
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/ecc_platform_specific.c
@@ -0,0 +1,110 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* uECC_platform_specific.c - Implementation of platform specific functions*/
+
+/* Copyright (c) 2014, Kenneth MacKay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.*/
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * uECC_platform_specific.c -- Implementation of platform specific functions
+ */
+
+
+#if defined(unix) || defined(__linux__) || defined(__unix__) || \
+ defined(__unix) | (defined(__APPLE__) && defined(__MACH__)) || \
+ defined(uECC_POSIX)
+
+/* Some POSIX-like system with /dev/urandom or /dev/random. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdint.h>
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+int default_CSPRNG(uint8_t *dest, unsigned int size) {
+
+ /* input sanity check: */
+ if (dest == (uint8_t *) 0 || (size <= 0))
+ return 0;
+
+ int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
+ if (fd == -1) {
+ return 0;
+ }
+ }
+
+ char *ptr = (char *)dest;
+ size_t left = (size_t) size;
+ while (left > 0) {
+ ssize_t bytes_read = read(fd, ptr, left);
+ if (bytes_read <= 0) { // read failed
+ close(fd);
+ return 0;
+ }
+ left -= bytes_read;
+ ptr += bytes_read;
+ }
+
+ close(fd);
+ return 1;
+}
+
+#endif /* platform */
diff --git a/lib/bt/common/tinycrypt/src/hmac.c b/lib/bt/common/tinycrypt/src/hmac.c
new file mode 100644
index 00000000..77232434
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/hmac.c
@@ -0,0 +1,152 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/hmac.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size)
+{
+ const uint8_t inner_pad = (uint8_t) 0x36;
+ const uint8_t outer_pad = (uint8_t) 0x5c;
+ unsigned int i;
+
+ for (i = 0; i < key_size; ++i) {
+ key[i] = inner_pad ^ new_key[i];
+ key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i];
+ }
+ for (; i < TC_SHA256_BLOCK_SIZE; ++i) {
+ key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad;
+ }
+}
+
+int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
+ unsigned int key_size)
+{
+
+ /* input sanity check: */
+ if (ctx == (TCHmacState_t) 0 ||
+ key == (const uint8_t *) 0 ||
+ key_size == 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ const uint8_t dummy_key[key_size];
+ struct tc_hmac_state_struct dummy_state;
+
+ if (key_size <= TC_SHA256_BLOCK_SIZE) {
+ /*
+ * The next three lines consist of dummy calls just to avoid
+ * certain timing attacks. Without these dummy calls,
+ * adversaries would be able to learn whether the key_size is
+ * greater than TC_SHA256_BLOCK_SIZE by measuring the time
+ * consumed in this process.
+ */
+ (void)tc_sha256_init(&dummy_state.hash_state);
+ (void)tc_sha256_update(&dummy_state.hash_state,
+ dummy_key,
+ key_size);
+ (void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE],
+ &dummy_state.hash_state);
+
+ /* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */
+ rekey(ctx->key, key, key_size);
+ } else {
+ (void)tc_sha256_init(&ctx->hash_state);
+ (void)tc_sha256_update(&ctx->hash_state, key, key_size);
+ (void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE],
+ &ctx->hash_state);
+ rekey(ctx->key,
+ &ctx->key[TC_SHA256_DIGEST_SIZE],
+ TC_SHA256_DIGEST_SIZE);
+ }
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_init(TCHmacState_t ctx)
+{
+
+ /* input sanity check: */
+ if (ctx == (TCHmacState_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ (void) tc_sha256_init(&ctx->hash_state);
+ (void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE);
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_update(TCHmacState_t ctx,
+ const void *data,
+ unsigned int data_length)
+{
+
+ /* input sanity check: */
+ if (ctx == (TCHmacState_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ (void)tc_sha256_update(&ctx->hash_state, data, data_length);
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx)
+{
+
+ /* input sanity check: */
+ if (tag == (uint8_t *) 0 ||
+ taglen != TC_SHA256_DIGEST_SIZE ||
+ ctx == (TCHmacState_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ (void) tc_sha256_final(tag, &ctx->hash_state);
+
+ (void)tc_sha256_init(&ctx->hash_state);
+ (void)tc_sha256_update(&ctx->hash_state,
+ &ctx->key[TC_SHA256_BLOCK_SIZE],
+ TC_SHA256_BLOCK_SIZE);
+ (void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE);
+ (void)tc_sha256_final(tag, &ctx->hash_state);
+
+ /* destroy the current state */
+ _set(ctx, 0, sizeof(*ctx));
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/lib/bt/common/tinycrypt/src/hmac_prng.c b/lib/bt/common/tinycrypt/src/hmac_prng.c
new file mode 100644
index 00000000..1e3a52fb
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/hmac_prng.c
@@ -0,0 +1,218 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */
+
+#include <tinycrypt/hmac_prng.h>
+#include <tinycrypt/hmac.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+/*
+ * min bytes in the seed string.
+ * MIN_SLEN*8 must be at least the expected security level.
+ */
+static const unsigned int MIN_SLEN = 32;
+
+/*
+ * max bytes in the seed string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_SLEN = UINT32_MAX;
+
+/*
+ * max bytes in the personalization string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_PLEN = UINT32_MAX;
+
+/*
+ * max bytes in the additional_info string;
+ * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
+ */
+static const unsigned int MAX_ALEN = UINT32_MAX;
+
+/*
+ * max number of generates between re-seeds;
+ * TinyCrypt accepts up to (2^32 - 1) which is the maximal value of
+ * a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48.
+ */
+static const unsigned int MAX_GENS = UINT32_MAX;
+
+/*
+ * maximum bytes per generate call;
+ * SP800-90A specifies a maximum up to 2^19.
+ */
+static const unsigned int MAX_OUT = (1 << 19);
+
+/*
+ * Assumes: prng != NULL, e != NULL, len >= 0.
+ */
+static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
+{
+ const uint8_t separator0 = 0x00;
+ const uint8_t separator1 = 0x01;
+
+ /* use current state, e and separator 0 to compute a new prng key: */
+ (void)tc_hmac_init(&prng->h);
+ (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+ (void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0));
+ (void)tc_hmac_update(&prng->h, e, len);
+ (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
+ /* configure the new prng key into the prng's instance of hmac */
+ (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+
+ /* use the new key to compute a new state variable v */
+ (void)tc_hmac_init(&prng->h);
+ (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+ (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+
+ /* use current state, e and separator 1 to compute a new prng key: */
+ (void)tc_hmac_init(&prng->h);
+ (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+ (void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1));
+ (void)tc_hmac_update(&prng->h, e, len);
+ (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
+ /* configure the new prng key into the prng's instance of hmac */
+ (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+
+ /* use the new key to compute a new state variable v */
+ (void)tc_hmac_init(&prng->h);
+ (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+ (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+}
+
+int tc_hmac_prng_init(TCHmacPrng_t prng,
+ const uint8_t *personalization,
+ unsigned int plen)
+{
+
+ /* input sanity check: */
+ if (prng == (TCHmacPrng_t) 0 ||
+ personalization == (uint8_t *) 0 ||
+ plen > MAX_PLEN) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /* put the generator into a known state: */
+ _set(prng->key, 0x00, sizeof(prng->key));
+ _set(prng->v, 0x01, sizeof(prng->v));
+ tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
+ /* update assumes SOME key has been configured into HMAC */
+
+ update(prng, personalization, plen);
+
+ /* force a reseed before allowing tc_hmac_prng_generate to succeed: */
+ prng->countdown = 0;
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_prng_reseed(TCHmacPrng_t prng,
+ const uint8_t *seed,
+ unsigned int seedlen,
+ const uint8_t *additional_input,
+ unsigned int additionallen)
+{
+
+ /* input sanity check: */
+ if (prng == (TCHmacPrng_t) 0 ||
+ seed == (const uint8_t *) 0 ||
+ seedlen < MIN_SLEN ||
+ seedlen > MAX_SLEN) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ if (additional_input != (const uint8_t *) 0) {
+ /*
+ * Abort if additional_input is provided but has inappropriate
+ * length
+ */
+ if (additionallen == 0 ||
+ additionallen > MAX_ALEN) {
+ return TC_CRYPTO_FAIL;
+ } else {
+ /* call update for the seed and additional_input */
+ update(prng, seed, seedlen);
+ update(prng, additional_input, additionallen);
+ }
+ } else {
+ /* call update only for the seed */
+ update(prng, seed, seedlen);
+ }
+
+ /* ... and enable hmac_prng_generate */
+ prng->countdown = MAX_GENS;
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng)
+{
+ unsigned int bufferlen;
+
+ /* input sanity check: */
+ if (out == (uint8_t *) 0 ||
+ prng == (TCHmacPrng_t) 0 ||
+ outlen == 0 ||
+ outlen > MAX_OUT) {
+ return TC_CRYPTO_FAIL;
+ } else if (prng->countdown == 0) {
+ return TC_HMAC_PRNG_RESEED_REQ;
+ }
+
+ prng->countdown--;
+
+ while (outlen != 0) {
+ /* operate HMAC in OFB mode to create "random" outputs */
+ (void)tc_hmac_init(&prng->h);
+ (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
+ (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
+
+ bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ?
+ outlen : TC_SHA256_DIGEST_SIZE;
+ (void)_copy(out, bufferlen, prng->v, bufferlen);
+
+ out += bufferlen;
+ outlen = (outlen > TC_SHA256_DIGEST_SIZE) ?
+ (outlen - TC_SHA256_DIGEST_SIZE) : 0;
+ }
+
+ /* block future PRNG compromises from revealing past state */
+ update(prng, prng->v, TC_SHA256_DIGEST_SIZE);
+
+ return TC_CRYPTO_SUCCESS;
+}
diff --git a/lib/bt/common/tinycrypt/src/sha256.c b/lib/bt/common/tinycrypt/src/sha256.c
new file mode 100644
index 00000000..53fd6191
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/sha256.c
@@ -0,0 +1,221 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <tinycrypt/sha256.h>
+#include <tinycrypt/constants.h>
+#include <tinycrypt/utils.h>
+
+static void compress(unsigned int *iv, const uint8_t *data);
+
+int tc_sha256_init(TCSha256State_t s)
+{
+ /* input sanity check: */
+ if (s == (TCSha256State_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ /*
+ * Setting the initial state values.
+ * These values correspond to the first 32 bits of the fractional parts
+ * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17
+ * and 19.
+ */
+ _set((uint8_t *) s, 0x00, sizeof(*s));
+ s->iv[0] = 0x6a09e667;
+ s->iv[1] = 0xbb67ae85;
+ s->iv[2] = 0x3c6ef372;
+ s->iv[3] = 0xa54ff53a;
+ s->iv[4] = 0x510e527f;
+ s->iv[5] = 0x9b05688c;
+ s->iv[6] = 0x1f83d9ab;
+ s->iv[7] = 0x5be0cd19;
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen)
+{
+ /* input sanity check: */
+ if (s == (TCSha256State_t) 0 ||
+ data == (void *) 0) {
+ return TC_CRYPTO_FAIL;
+ } else if (datalen == 0) {
+ return TC_CRYPTO_SUCCESS;
+ }
+
+ while (datalen-- > 0) {
+ s->leftover[s->leftover_offset++] = *(data++);
+ if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) {
+ compress(s->iv, s->leftover);
+ s->leftover_offset = 0;
+ s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3);
+ }
+ }
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+int tc_sha256_final(uint8_t *digest, TCSha256State_t s)
+{
+ unsigned int i;
+
+ /* input sanity check: */
+ if (digest == (uint8_t *) 0 ||
+ s == (TCSha256State_t) 0) {
+ return TC_CRYPTO_FAIL;
+ }
+
+ s->bits_hashed += (s->leftover_offset << 3);
+
+ s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */
+ if (s->leftover_offset > (sizeof(s->leftover) - 8)) {
+ /* there is not room for all the padding in this block */
+ _set(s->leftover + s->leftover_offset, 0x00,
+ sizeof(s->leftover) - s->leftover_offset);
+ compress(s->iv, s->leftover);
+ s->leftover_offset = 0;
+ }
+
+ /* add the padding and the length in big-Endian format */
+ _set(s->leftover + s->leftover_offset, 0x00,
+ sizeof(s->leftover) - 8 - s->leftover_offset);
+ s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed);
+ s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8);
+ s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16);
+ s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24);
+ s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32);
+ s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40);
+ s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48);
+ s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56);
+
+ /* hash the padding and length */
+ compress(s->iv, s->leftover);
+
+ /* copy the iv out to digest */
+ for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) {
+ unsigned int t = *((unsigned int *) &s->iv[i]);
+ *digest++ = (uint8_t)(t >> 24);
+ *digest++ = (uint8_t)(t >> 16);
+ *digest++ = (uint8_t)(t >> 8);
+ *digest++ = (uint8_t)(t);
+ }
+
+ /* destroy the current state */
+ _set(s, 0, sizeof(*s));
+
+ return TC_CRYPTO_SUCCESS;
+}
+
+/*
+ * Initializing SHA-256 Hash constant words K.
+ * These values correspond to the first 32 bits of the fractional parts of the
+ * cube roots of the first 64 primes between 2 and 311.
+ */
+static const unsigned int k256[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+static inline unsigned int ROTR(unsigned int a, unsigned int n)
+{
+ return (((a) >> n) | ((a) << (32 - n)));
+}
+
+#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22))
+#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25))
+#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3))
+#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10))
+
+#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c)))
+#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
+
+static inline unsigned int BigEndian(const uint8_t **c)
+{
+ unsigned int n = 0;
+
+ n = (((unsigned int)(*((*c)++))) << 24);
+ n |= ((unsigned int)(*((*c)++)) << 16);
+ n |= ((unsigned int)(*((*c)++)) << 8);
+ n |= ((unsigned int)(*((*c)++)));
+ return n;
+}
+
+static void compress(unsigned int *iv, const uint8_t *data)
+{
+ unsigned int a, b, c, d, e, f, g, h;
+ unsigned int s0, s1;
+ unsigned int t1, t2;
+ unsigned int work_space[16];
+ unsigned int n;
+ unsigned int i;
+
+ a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3];
+ e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7];
+
+ for (i = 0; i < 16; ++i) {
+ n = BigEndian(&data);
+ t1 = work_space[i] = n;
+ t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
+ t2 = Sigma0(a) + Maj(a, b, c);
+ h = g; g = f; f = e; e = d + t1;
+ d = c; c = b; b = a; a = t1 + t2;
+ }
+
+ for ( ; i < 64; ++i) {
+ s0 = work_space[(i+1)&0x0f];
+ s0 = sigma0(s0);
+ s1 = work_space[(i+14)&0x0f];
+ s1 = sigma1(s1);
+
+ t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf];
+ t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
+ t2 = Sigma0(a) + Maj(a, b, c);
+ h = g; g = f; f = e; e = d + t1;
+ d = c; c = b; b = a; a = t1 + t2;
+ }
+
+ iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d;
+ iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h;
+}
diff --git a/lib/bt/common/tinycrypt/src/utils.c b/lib/bt/common/tinycrypt/src/utils.c
new file mode 100644
index 00000000..8f8278bb
--- /dev/null
+++ b/lib/bt/common/tinycrypt/src/utils.c
@@ -0,0 +1,80 @@
+/*
+ * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ * Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* utils.c - TinyCrypt platform-dependent run-time operations */
+
+#include <tinycrypt/utils.h>
+#include <tinycrypt/constants.h>
+
+#include <string.h>
+
+#define MASK_TWENTY_SEVEN 0x1b
+
+unsigned int _copy(uint8_t *to, unsigned int to_len,
+ const uint8_t *from, unsigned int from_len)
+{
+ if (from_len <= to_len) {
+ (void)memcpy(to, from, from_len);
+ return from_len;
+ } else {
+ return TC_CRYPTO_FAIL;
+ }
+}
+
+void _set(void *to, uint8_t val, unsigned int len)
+{
+ (void)memset(to, val, len);
+}
+
+/*
+ * Doubles the value of a byte for values up to 127.
+ */
+uint8_t _double_byte(uint8_t a)
+{
+ return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN));
+}
+
+int _compare(const uint8_t *a, const uint8_t *b, size_t size)
+{
+ const uint8_t *tempa = a;
+ const uint8_t *tempb = b;
+ uint8_t result = 0;
+
+ for (unsigned int i = 0; i < size; i++) {
+ result |= tempa[i] ^ tempb[i];
+ }
+ return result;
+}