mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
fix(blufi): support DH negotiation on SoCs without hardware MPI
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -33,9 +33,131 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_blufi.h"
|
||||
#include <esp_gap_ble_api.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if (BLUFI_INCLUDED == TRUE)
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
#define BLUFI_RX_QUEUE_LEN 8
|
||||
#define BLUFI_RX_TASK_STACK_SIZE 4096
|
||||
#define BLUFI_RX_TASK_PRIO (tskIDLE_PRIORITY + 1)
|
||||
|
||||
typedef struct {
|
||||
uint8_t *data;
|
||||
uint16_t len;
|
||||
} blufi_rx_item_t;
|
||||
|
||||
static QueueHandle_t s_blufi_rx_queue;
|
||||
static TaskHandle_t s_blufi_rx_task_hdl;
|
||||
|
||||
static void blufi_rx_task(void *arg)
|
||||
{
|
||||
blufi_rx_item_t item;
|
||||
|
||||
while (xQueueReceive(s_blufi_rx_queue, &item, portMAX_DELAY) == pdTRUE) {
|
||||
if (item.data == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
btc_blufi_recv_handler(item.data, item.len);
|
||||
free(item.data);
|
||||
}
|
||||
|
||||
s_blufi_rx_task_hdl = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static int blufi_rx_worker_start(void)
|
||||
{
|
||||
if (s_blufi_rx_queue != NULL && s_blufi_rx_task_hdl != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s_blufi_rx_queue != NULL && s_blufi_rx_task_hdl == NULL) {
|
||||
blufi_rx_item_t item;
|
||||
while (xQueueReceive(s_blufi_rx_queue, &item, 0) == pdTRUE) {
|
||||
free(item.data);
|
||||
}
|
||||
vQueueDelete(s_blufi_rx_queue);
|
||||
s_blufi_rx_queue = NULL;
|
||||
}
|
||||
|
||||
s_blufi_rx_queue = xQueueCreate(BLUFI_RX_QUEUE_LEN, sizeof(blufi_rx_item_t));
|
||||
if (s_blufi_rx_queue == NULL) {
|
||||
BTC_TRACE_ERROR("failed to create BLUFI RX queue");
|
||||
return -1;
|
||||
}
|
||||
|
||||
BaseType_t ret = xTaskCreate(blufi_rx_task, "blufi_rx", BLUFI_RX_TASK_STACK_SIZE,
|
||||
NULL, BLUFI_RX_TASK_PRIO, &s_blufi_rx_task_hdl);
|
||||
if (ret != pdPASS) {
|
||||
BTC_TRACE_ERROR("failed to create BLUFI RX task");
|
||||
vQueueDelete(s_blufi_rx_queue);
|
||||
s_blufi_rx_queue = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void blufi_rx_worker_stop(void)
|
||||
{
|
||||
if (s_blufi_rx_queue == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
blufi_rx_item_t stop = { .data = NULL, .len = 0 };
|
||||
if (xQueueSend(s_blufi_rx_queue, &stop, 0) != pdTRUE) {
|
||||
blufi_rx_item_t item;
|
||||
while (xQueueReceive(s_blufi_rx_queue, &item, 0) == pdTRUE) {
|
||||
free(item.data);
|
||||
}
|
||||
(void)xQueueSend(s_blufi_rx_queue, &stop, 0);
|
||||
}
|
||||
|
||||
while (s_blufi_rx_task_hdl != NULL) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
blufi_rx_item_t item;
|
||||
while (xQueueReceive(s_blufi_rx_queue, &item, 0) == pdTRUE) {
|
||||
free(item.data);
|
||||
}
|
||||
|
||||
vQueueDelete(s_blufi_rx_queue);
|
||||
s_blufi_rx_queue = NULL;
|
||||
}
|
||||
|
||||
static bool blufi_rx_enqueue(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
if (len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s_blufi_rx_queue == NULL) {
|
||||
if (blufi_rx_worker_start() != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *copy = malloc(len);
|
||||
if (copy == NULL) {
|
||||
return false;
|
||||
}
|
||||
memcpy(copy, data, len);
|
||||
|
||||
blufi_rx_item_t item = { .data = copy, .len = len };
|
||||
if (xQueueSend(s_blufi_rx_queue, &item, 0) != pdTRUE) {
|
||||
free(copy);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif /* !SOC_MPI_SUPPORTED */
|
||||
|
||||
static uint8_t server_if;
|
||||
static uint16_t conn_id;
|
||||
static uint8_t blufi_service_uuid128[32] = {
|
||||
@@ -241,7 +363,6 @@ void blufi_create_service(void)
|
||||
|
||||
uint8_t esp_blufi_init(void)
|
||||
{
|
||||
|
||||
/* register the BLUFI profile to the BTA_GATTS module*/
|
||||
BTA_GATTS_AppRegister(&blufi_app_uuid, blufi_profile_cb);
|
||||
return GATT_SUCCESS;
|
||||
@@ -363,8 +484,15 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
}
|
||||
|
||||
if (p_data->req_data.p_data->write_req.handle == blufi_env.handle_char_p2e) {
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
if (!blufi_rx_enqueue(&p_data->req_data.p_data->write_req.value[0],
|
||||
p_data->req_data.p_data->write_req.len)) {
|
||||
BLUFI_TRACE_ERROR("failed to enqueue BLUFI RX data");
|
||||
}
|
||||
#else
|
||||
btc_blufi_recv_handler(&p_data->req_data.p_data->write_req.value[0],
|
||||
p_data->req_data.p_data->write_req.len);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -375,7 +503,13 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
|
||||
GATT_SUCCESS, NULL);
|
||||
|
||||
if (blufi_env.prepare_buf && p_data->req_data.p_data->exec_write == GATT_PREP_WRITE_EXEC) {
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
if (!blufi_rx_enqueue(blufi_env.prepare_buf, blufi_env.prepare_len)) {
|
||||
BLUFI_TRACE_ERROR("failed to enqueue BLUFI RX exec data");
|
||||
}
|
||||
#else
|
||||
btc_blufi_recv_handler(blufi_env.prepare_buf, blufi_env.prepare_len);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (blufi_env.prepare_buf) {
|
||||
@@ -523,6 +657,9 @@ void esp_blufi_send_notify(void *arg)
|
||||
|
||||
void esp_blufi_deinit(void)
|
||||
{
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_rx_worker_stop();
|
||||
#endif
|
||||
BTA_GATTS_StopService(blufi_env.handle_srvc);
|
||||
BTA_GATTS_DeleteService(blufi_env.handle_srvc);
|
||||
/* register the BLUFI profile to the BTA_GATTS module*/
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#include "esp_blufi.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "console/console.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
/*nimBLE Host*/
|
||||
#include "nimble/nimble_port.h"
|
||||
@@ -29,6 +32,7 @@
|
||||
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
#include "services/gatt/ble_svc_gatt.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if (BLUFI_INCLUDED == TRUE)
|
||||
|
||||
@@ -37,6 +41,104 @@ static uint8_t own_addr_type;
|
||||
struct gatt_value gatt_values[SERVER_MAX_VALUES];
|
||||
const static char *TAG = "BLUFI_EXAMPLE";
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
#define BLUFI_RX_QUEUE_LEN 8
|
||||
#define BLUFI_RX_TASK_STACK_SIZE 8192
|
||||
#define BLUFI_RX_TASK_PRIO (tskIDLE_PRIORITY + 1)
|
||||
|
||||
typedef struct {
|
||||
uint8_t *data;
|
||||
uint16_t len;
|
||||
} blufi_rx_item_t;
|
||||
|
||||
static QueueHandle_t s_blufi_rx_queue;
|
||||
static TaskHandle_t s_blufi_rx_task_hdl;
|
||||
|
||||
static void blufi_rx_task(void *arg)
|
||||
{
|
||||
blufi_rx_item_t item;
|
||||
|
||||
while (xQueueReceive(s_blufi_rx_queue, &item, portMAX_DELAY) == pdTRUE) {
|
||||
if (item.data == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
btc_blufi_recv_handler(item.data, item.len);
|
||||
free(item.data);
|
||||
}
|
||||
|
||||
s_blufi_rx_task_hdl = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static int blufi_rx_worker_start(void)
|
||||
{
|
||||
if (s_blufi_rx_queue != NULL && s_blufi_rx_task_hdl != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s_blufi_rx_queue != NULL && s_blufi_rx_task_hdl == NULL) {
|
||||
/* Recover from partial state: stale queue left after worker exit. */
|
||||
blufi_rx_item_t item;
|
||||
while (xQueueReceive(s_blufi_rx_queue, &item, 0) == pdTRUE) {
|
||||
free(item.data);
|
||||
}
|
||||
vQueueDelete(s_blufi_rx_queue);
|
||||
s_blufi_rx_queue = NULL;
|
||||
}
|
||||
|
||||
s_blufi_rx_queue = xQueueCreate(BLUFI_RX_QUEUE_LEN, sizeof(blufi_rx_item_t));
|
||||
if (s_blufi_rx_queue == NULL) {
|
||||
ESP_LOGE(TAG, "failed to create BLUFI RX queue");
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
BaseType_t ret = xTaskCreate(blufi_rx_task, "blufi_rx", BLUFI_RX_TASK_STACK_SIZE,
|
||||
NULL, BLUFI_RX_TASK_PRIO, &s_blufi_rx_task_hdl);
|
||||
if (ret != pdPASS) {
|
||||
ESP_LOGE(TAG, "failed to create BLUFI RX task");
|
||||
vQueueDelete(s_blufi_rx_queue);
|
||||
s_blufi_rx_queue = NULL;
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void blufi_rx_worker_stop(void)
|
||||
{
|
||||
if (s_blufi_rx_queue == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
blufi_rx_item_t stop = {
|
||||
.data = NULL,
|
||||
.len = 0,
|
||||
};
|
||||
if (xQueueSend(s_blufi_rx_queue, &stop, 0) != pdTRUE) {
|
||||
/* Queue is full; free pending packets and resend stop marker. */
|
||||
blufi_rx_item_t item;
|
||||
while (xQueueReceive(s_blufi_rx_queue, &item, 0) == pdTRUE) {
|
||||
free(item.data);
|
||||
}
|
||||
(void)xQueueSend(s_blufi_rx_queue, &stop, 0);
|
||||
}
|
||||
|
||||
while (s_blufi_rx_task_hdl != NULL) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
}
|
||||
|
||||
/* Drain and free any queued packets before deleting the queue. */
|
||||
blufi_rx_item_t item;
|
||||
while (xQueueReceive(s_blufi_rx_queue, &item, 0) == pdTRUE) {
|
||||
free(item.data);
|
||||
}
|
||||
|
||||
vQueueDelete(s_blufi_rx_queue);
|
||||
s_blufi_rx_queue = NULL;
|
||||
}
|
||||
#endif /* !SOC_MPI_SUPPORTED */
|
||||
|
||||
enum {
|
||||
GATT_VALUE_TYPE_CHR,
|
||||
GATT_VALUE_TYPE_DSC,
|
||||
@@ -142,13 +244,30 @@ static size_t write_value(uint16_t conn_handle, uint16_t attr_handle,
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
|
||||
btc_blufi_recv_handler(flat_buf, pkt_len);
|
||||
|
||||
if (value->buf != NULL) {
|
||||
os_mbuf_free_chain(value->buf);
|
||||
value->buf = NULL;
|
||||
}
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
if (s_blufi_rx_queue == NULL) {
|
||||
free(flat_buf);
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
|
||||
if (pkt_len > 0) {
|
||||
blufi_rx_item_t item = {
|
||||
.data = flat_buf,
|
||||
.len = pkt_len,
|
||||
};
|
||||
if (xQueueSend(s_blufi_rx_queue, &item, 0) != pdTRUE) {
|
||||
free(flat_buf);
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
} else {
|
||||
free(flat_buf);
|
||||
}
|
||||
#else /* SOC_MPI_SUPPORTED */
|
||||
value->buf = os_msys_get(0, 0);
|
||||
if (value->buf == NULL) {
|
||||
free(flat_buf);
|
||||
@@ -164,7 +283,9 @@ static size_t write_value(uint16_t conn_handle, uint16_t attr_handle,
|
||||
}
|
||||
}
|
||||
|
||||
btc_blufi_recv_handler(flat_buf, pkt_len);
|
||||
free(flat_buf);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -278,16 +399,30 @@ static void deinit_gatt_values(void)
|
||||
int esp_blufi_gatt_svr_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
rc = blufi_rx_worker_start();
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
ble_svc_gap_init();
|
||||
ble_svc_gatt_init();
|
||||
|
||||
rc = ble_gatts_count_cfg(gatt_svr_svcs);
|
||||
if (rc != 0) {
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_rx_worker_stop();
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ble_gatts_add_svcs(gatt_svr_svcs);
|
||||
if (rc != 0) {
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_rx_worker_stop();
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -297,6 +432,10 @@ int esp_blufi_gatt_svr_init(void)
|
||||
|
||||
int esp_blufi_gatt_svr_deinit(void)
|
||||
{
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_rx_worker_stop();
|
||||
#endif
|
||||
|
||||
deinit_gatt_values();
|
||||
|
||||
ble_gatts_free_svcs();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#define BLUFI_EXAMPLE_TAG "BLUFI_EXAMPLE"
|
||||
#define BLUFI_INFO(fmt, ...) ESP_LOGI(BLUFI_EXAMPLE_TAG, fmt, ##__VA_ARGS__)
|
||||
#define BLUFI_ERROR(fmt, ...) ESP_LOGE(BLUFI_EXAMPLE_TAG, fmt, ##__VA_ARGS__)
|
||||
@@ -18,6 +20,11 @@ uint16_t blufi_crc_checksum(uint8_t iv8, uint8_t *data, int len);
|
||||
|
||||
int blufi_security_init(void);
|
||||
void blufi_security_deinit(void);
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
void blufi_dh_pregen_start(void);
|
||||
void blufi_dh_pregen_start_with_cb(void (*done_cb)(void));
|
||||
void blufi_dh_pregen_wait(void);
|
||||
#endif
|
||||
int esp_blufi_gap_register_callback(void);
|
||||
esp_err_t esp_blufi_host_init(void);
|
||||
esp_err_t esp_blufi_host_and_cb_init(esp_blufi_callbacks_t *callbacks);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -312,8 +312,9 @@ static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_para
|
||||
switch (event) {
|
||||
case ESP_BLUFI_EVENT_INIT_FINISH:
|
||||
BLUFI_INFO("BLUFI init finish\n");
|
||||
|
||||
#if SOC_MPI_SUPPORTED
|
||||
esp_blufi_adv_start();
|
||||
#endif
|
||||
break;
|
||||
case ESP_BLUFI_EVENT_DEINIT_FINISH:
|
||||
BLUFI_INFO("BLUFI deinit finish\n");
|
||||
@@ -336,7 +337,11 @@ static void example_event_callback(esp_blufi_cb_event_t event, esp_blufi_cb_para
|
||||
BLUFI_INFO("BLUFI ble disconnect\n");
|
||||
ble_is_connected = false;
|
||||
blufi_security_deinit();
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_dh_pregen_start_with_cb(esp_blufi_adv_start);
|
||||
#else
|
||||
esp_blufi_adv_start();
|
||||
#endif
|
||||
break;
|
||||
case ESP_BLUFI_EVENT_SET_WIFI_OPMODE:
|
||||
BLUFI_INFO("BLUFI Set WIFI opmode %d\n", param->wifi_mode.op_mode);
|
||||
@@ -531,5 +536,11 @@ void app_main(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_dh_pregen_start();
|
||||
blufi_dh_pregen_wait();
|
||||
esp_blufi_adv_start();
|
||||
#endif
|
||||
|
||||
BLUFI_INFO("BLUFI VERSION %04x\n", esp_blufi_get_version());
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_random.h"
|
||||
#if CONFIG_BT_CONTROLLER_ENABLED || !CONFIG_BT_NIMBLE_ENABLED
|
||||
@@ -25,6 +27,7 @@
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "esp_crc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
/*
|
||||
The SEC_TYPE_xxx is for self-defined packet data type in the procedure of "BLUFI negotiate key"
|
||||
@@ -43,6 +46,13 @@
|
||||
#define BLUFI_ENC_DOMAIN_STR "blufi_enc"
|
||||
#define BLUFI_DEC_DOMAIN_STR "blufi_dec"
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
#define BLUFI_DH_PREGEN_STACK_SIZE 4096
|
||||
#define BLUFI_DH_PREGEN_PRIO (tskIDLE_PRIORITY + 1)
|
||||
#define BLUFI_DH_PREGEN_WAIT_MS 30000
|
||||
#define BLUFI_DH_HEAVY_CRYPTO_WDT_MS 30000
|
||||
#endif
|
||||
|
||||
struct blufi_security {
|
||||
#define DH_PARAM_LEN_MAX 1024
|
||||
#define DH_SELF_PUB_KEY_LEN 384 /* Support 3072-bit DH key (3072/8 = 384 bytes) */
|
||||
@@ -109,6 +119,135 @@ static void blufi_cleanup_negotiation(bool abort_enc, bool abort_dec)
|
||||
blufi_cleanup_dh_param();
|
||||
}
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
/*
|
||||
* DH keypair pre-generation: overlap the expensive G^X mod P computation
|
||||
* with BLE advertising so only key agreement remains on the critical path
|
||||
* when the phone sends its DH parameters.
|
||||
*/
|
||||
static psa_key_id_t s_pregen_private_key;
|
||||
static uint8_t s_pregen_public_key[DH_SELF_PUB_KEY_LEN];
|
||||
static size_t s_pregen_public_key_len;
|
||||
static SemaphoreHandle_t s_pregen_done;
|
||||
static bool s_pregen_ok;
|
||||
static TaskHandle_t s_pregen_task_hdl;
|
||||
static void (*s_pregen_complete_cb)(void);
|
||||
|
||||
static void blufi_wdt_set_timeout(uint32_t timeout_ms)
|
||||
{
|
||||
esp_task_wdt_config_t cfg = {
|
||||
.timeout_ms = timeout_ms,
|
||||
.idle_core_mask = (1 << portNUM_PROCESSORS) - 1,
|
||||
.trigger_panic = true,
|
||||
};
|
||||
esp_task_wdt_reconfigure(&cfg);
|
||||
}
|
||||
|
||||
static void blufi_dh_pregen_task(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
blufi_wdt_set_timeout(BLUFI_DH_HEAVY_CRYPTO_WDT_MS);
|
||||
|
||||
psa_key_attributes_t attr = psa_key_attributes_init();
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919));
|
||||
psa_set_key_bits(&attr, 3072);
|
||||
psa_set_key_algorithm(&attr, PSA_ALG_FFDH);
|
||||
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
|
||||
|
||||
psa_status_t status = psa_generate_key(&attr, &s_pregen_private_key);
|
||||
if (status == PSA_SUCCESS) {
|
||||
status = psa_export_public_key(s_pregen_private_key,
|
||||
s_pregen_public_key, DH_SELF_PUB_KEY_LEN,
|
||||
&s_pregen_public_key_len);
|
||||
}
|
||||
psa_reset_key_attributes(&attr);
|
||||
|
||||
s_pregen_ok = (status == PSA_SUCCESS);
|
||||
if (!s_pregen_ok && s_pregen_private_key != 0) {
|
||||
psa_destroy_key(s_pregen_private_key);
|
||||
s_pregen_private_key = 0;
|
||||
}
|
||||
|
||||
BLUFI_INFO("DH keypair pre-generation %s", s_pregen_ok ? "done" : "FAILED");
|
||||
|
||||
blufi_wdt_set_timeout(CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000);
|
||||
|
||||
xSemaphoreGive(s_pregen_done);
|
||||
|
||||
if (s_pregen_complete_cb) {
|
||||
void (*cb)(void) = s_pregen_complete_cb;
|
||||
s_pregen_complete_cb = NULL;
|
||||
cb();
|
||||
}
|
||||
|
||||
vTaskSuspend(NULL);
|
||||
}
|
||||
|
||||
static void blufi_dh_pregen_start_impl(void (*done_cb)(void))
|
||||
{
|
||||
if (s_pregen_done != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
s_pregen_private_key = 0;
|
||||
s_pregen_public_key_len = 0;
|
||||
s_pregen_ok = false;
|
||||
s_pregen_task_hdl = NULL;
|
||||
s_pregen_complete_cb = done_cb;
|
||||
s_pregen_done = xSemaphoreCreateBinary();
|
||||
if (s_pregen_done == NULL) {
|
||||
BLUFI_ERROR("Failed to create pre-gen semaphore");
|
||||
return;
|
||||
}
|
||||
|
||||
if (xTaskCreate(blufi_dh_pregen_task, "blufi_pregen",
|
||||
BLUFI_DH_PREGEN_STACK_SIZE, NULL,
|
||||
BLUFI_DH_PREGEN_PRIO, &s_pregen_task_hdl) != pdPASS) {
|
||||
BLUFI_ERROR("Failed to create pre-gen task");
|
||||
vSemaphoreDelete(s_pregen_done);
|
||||
s_pregen_done = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void blufi_dh_pregen_start(void)
|
||||
{
|
||||
blufi_dh_pregen_start_impl(NULL);
|
||||
}
|
||||
|
||||
void blufi_dh_pregen_start_with_cb(void (*done_cb)(void))
|
||||
{
|
||||
blufi_dh_pregen_start_impl(done_cb);
|
||||
}
|
||||
|
||||
void blufi_dh_pregen_wait(void)
|
||||
{
|
||||
if (s_pregen_done == NULL) {
|
||||
return;
|
||||
}
|
||||
xSemaphoreTake(s_pregen_done, portMAX_DELAY);
|
||||
xSemaphoreGive(s_pregen_done);
|
||||
}
|
||||
|
||||
static void blufi_dh_pregen_cleanup(void)
|
||||
{
|
||||
if (s_pregen_done != NULL) {
|
||||
xSemaphoreTake(s_pregen_done, portMAX_DELAY);
|
||||
vSemaphoreDelete(s_pregen_done);
|
||||
s_pregen_done = NULL;
|
||||
}
|
||||
if (s_pregen_task_hdl != NULL) {
|
||||
vTaskDelete(s_pregen_task_hdl);
|
||||
s_pregen_task_hdl = NULL;
|
||||
}
|
||||
if (s_pregen_private_key != 0) {
|
||||
psa_destroy_key(s_pregen_private_key);
|
||||
s_pregen_private_key = 0;
|
||||
}
|
||||
s_pregen_ok = false;
|
||||
}
|
||||
#endif /* !SOC_MPI_SUPPORTED */
|
||||
|
||||
void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free)
|
||||
{
|
||||
if (data == NULL || len < 3) {
|
||||
@@ -234,39 +373,114 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
|
||||
return;
|
||||
}
|
||||
|
||||
psa_key_type_t key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
|
||||
psa_algorithm_t alg = PSA_ALG_FFDH;
|
||||
psa_key_attributes_t attributes = psa_key_attributes_init();
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
psa_set_key_algorithm(&attributes, alg);
|
||||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
|
||||
|
||||
psa_key_id_t private_key = 0;
|
||||
psa_status_t status = psa_generate_key(&attributes, &private_key);
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_generate_key failed %d\n", __func__, status);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
blufi_cleanup_dh_param();
|
||||
return;
|
||||
}
|
||||
|
||||
psa_reset_key_attributes(&attributes);
|
||||
size_t public_key_len = 0;
|
||||
status = psa_export_public_key(private_key, blufi_sec->self_public_key, DH_SELF_PUB_KEY_LEN, &public_key_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_export_public_key failed %d\n", __func__, status);
|
||||
psa_destroy_key(private_key);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
blufi_cleanup_dh_param();
|
||||
return;
|
||||
psa_status_t status;
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
/* On SoCs without hardware MPI, 3072-bit modular exponentiation takes
|
||||
* ~12s in software. Use the pre-generated keypair, free all possible
|
||||
* heap before key agreement, and widen the task WDT window. */
|
||||
bool used_pregen = false;
|
||||
|
||||
if (s_pregen_done != NULL &&
|
||||
xSemaphoreTake(s_pregen_done, pdMS_TO_TICKS(BLUFI_DH_PREGEN_WAIT_MS)) == pdTRUE) {
|
||||
xSemaphoreGive(s_pregen_done);
|
||||
if (s_pregen_ok && s_pregen_private_key != 0) {
|
||||
private_key = s_pregen_private_key;
|
||||
s_pregen_private_key = 0;
|
||||
memcpy(blufi_sec->self_public_key, s_pregen_public_key, s_pregen_public_key_len);
|
||||
public_key_len = s_pregen_public_key_len;
|
||||
used_pregen = true;
|
||||
BLUFI_INFO("Using pre-generated DH keypair");
|
||||
}
|
||||
}
|
||||
|
||||
status = psa_raw_key_agreement(alg, private_key, param, pub_len, blufi_sec->share_key, SHARE_KEY_LEN, &blufi_sec->share_len);
|
||||
if (!used_pregen) {
|
||||
BLUFI_INFO("Pre-gen unavailable, generating DH keypair inline");
|
||||
blufi_wdt_set_timeout(BLUFI_DH_HEAVY_CRYPTO_WDT_MS);
|
||||
|
||||
psa_key_attributes_t keygen_attr = psa_key_attributes_init();
|
||||
psa_set_key_type(&keygen_attr, PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919));
|
||||
psa_set_key_bits(&keygen_attr, key_bits);
|
||||
psa_set_key_algorithm(&keygen_attr, alg);
|
||||
psa_set_key_usage_flags(&keygen_attr, PSA_KEY_USAGE_DERIVE);
|
||||
|
||||
status = psa_generate_key(&keygen_attr, &private_key);
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_generate_key failed %d\n", __func__, status);
|
||||
blufi_wdt_set_timeout(CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
blufi_cleanup_dh_param();
|
||||
return;
|
||||
}
|
||||
psa_reset_key_attributes(&keygen_attr);
|
||||
|
||||
status = psa_export_public_key(private_key, blufi_sec->self_public_key,
|
||||
DH_SELF_PUB_KEY_LEN, &public_key_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_export_public_key failed %d\n", __func__, status);
|
||||
blufi_wdt_set_timeout(CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000);
|
||||
psa_destroy_key(private_key);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
blufi_cleanup_dh_param();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t peer_pub[DH_SELF_PUB_KEY_LEN];
|
||||
memcpy(peer_pub, param, pub_len);
|
||||
blufi_cleanup_dh_param();
|
||||
|
||||
if (s_pregen_task_hdl != NULL) {
|
||||
vTaskDelete(s_pregen_task_hdl);
|
||||
s_pregen_task_hdl = NULL;
|
||||
}
|
||||
|
||||
blufi_wdt_set_timeout(BLUFI_DH_HEAVY_CRYPTO_WDT_MS);
|
||||
status = psa_raw_key_agreement(alg, private_key, peer_pub, pub_len,
|
||||
blufi_sec->share_key, SHARE_KEY_LEN,
|
||||
&blufi_sec->share_len);
|
||||
psa_destroy_key(private_key);
|
||||
blufi_wdt_set_timeout(CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000);
|
||||
#else /* SOC_MPI_SUPPORTED */
|
||||
{
|
||||
psa_key_attributes_t keygen_attr = psa_key_attributes_init();
|
||||
psa_set_key_type(&keygen_attr, PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919));
|
||||
psa_set_key_bits(&keygen_attr, key_bits);
|
||||
psa_set_key_algorithm(&keygen_attr, alg);
|
||||
psa_set_key_usage_flags(&keygen_attr, PSA_KEY_USAGE_DERIVE);
|
||||
|
||||
status = psa_generate_key(&keygen_attr, &private_key);
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_generate_key failed %d\n", __func__, status);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
blufi_cleanup_dh_param();
|
||||
return;
|
||||
}
|
||||
psa_reset_key_attributes(&keygen_attr);
|
||||
|
||||
status = psa_export_public_key(private_key, blufi_sec->self_public_key,
|
||||
DH_SELF_PUB_KEY_LEN, &public_key_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_export_public_key failed %d\n", __func__, status);
|
||||
psa_destroy_key(private_key);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
blufi_cleanup_dh_param();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
status = psa_raw_key_agreement(alg, private_key, param, pub_len,
|
||||
blufi_sec->share_key, SHARE_KEY_LEN,
|
||||
&blufi_sec->share_len);
|
||||
psa_destroy_key(private_key);
|
||||
blufi_cleanup_dh_param();
|
||||
#endif /* !SOC_MPI_SUPPORTED */
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_raw_key_agreement failed %d\n", __func__, status);
|
||||
blufi_cleanup_dh_param();
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR);
|
||||
return;
|
||||
}
|
||||
@@ -292,7 +506,7 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
|
||||
blufi_cleanup_aes_session(true, true);
|
||||
|
||||
/* Import AES key for CTR mode */
|
||||
attributes = psa_key_attributes_init();
|
||||
psa_key_attributes_t attributes = psa_key_attributes_init();
|
||||
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_bits(&attributes, PSK_LEN * 8);
|
||||
psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
|
||||
@@ -386,7 +600,6 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
|
||||
*output_data = &blufi_sec->self_public_key[0];
|
||||
*output_len = public_key_len;
|
||||
*need_free = false;
|
||||
|
||||
}
|
||||
break;
|
||||
case SEC_TYPE_DH_P:
|
||||
@@ -512,6 +725,10 @@ esp_err_t blufi_security_init(void)
|
||||
blufi_sec->enc_operation = psa_cipher_operation_init();
|
||||
blufi_sec->dec_operation = psa_cipher_operation_init();
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_dh_pregen_start();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -521,6 +738,10 @@ void blufi_security_deinit(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#if !SOC_MPI_SUPPORTED
|
||||
blufi_dh_pregen_cleanup();
|
||||
#endif
|
||||
|
||||
/* Clean up all resources */
|
||||
blufi_cleanup_negotiation(true, true);
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ CONFIG_BT_NIMBLE_BLUFI_ENABLE=y
|
||||
# CONFIG_BT_BLE_SMP_ENABLE is not set
|
||||
# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set
|
||||
CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y
|
||||
CONFIG_BT_LE_50_FEATURE_SUPPORT=n
|
||||
CONFIG_BT_LE_MSYS_2_BLOCK_COUNT=12
|
||||
CONFIG_BT_LE_HCI_EVT_BUF_SIZE=70
|
||||
# The config items for NIMBLE HOST
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
CONFIG_BT_NIMBLE_ROLE_CENTRAL=n
|
||||
|
||||
Reference in New Issue
Block a user