Merge branch 'feat/support_bluedroid_host_smp_with_psa_tinycrypt_v5.4' into 'release/v5.4'

Feat/support bluedroid host smp with psa tinycrypt v5.4

See merge request espressif/esp-idf!44835
This commit is contained in:
Island
2026-01-07 14:16:31 +08:00
48 changed files with 3612 additions and 52 deletions
+6 -1
View File
@@ -693,7 +693,12 @@ if(CONFIG_BT_ENABLED)
)
endif()
if(NOT (CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS OR CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS))
# Compile TinyCrypt if:
# 1. Controller uses TinyCrypt (not mbedTLS), OR
# 2. NimBLE uses TinyCrypt (not mbedTLS), OR
# 3. Bluedroid Host SMP uses TinyCrypt
if(CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT OR
(NOT CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS AND NOT CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS))
list(APPEND include_dirs
common/tinycrypt/include
common/tinycrypt/port
+37
View File
@@ -6,6 +6,43 @@ config BT_ALARM_MAX_NUM
This option decides the maximum number of alarms which
could be used by Bluetooth host.
choice BT_SMP_CRYPTO_STACK
prompt "SMP cryptographic stack"
depends on (BT_BLE_SMP_ENABLE || BT_SMP_ENABLE || BT_NIMBLE_SECURITY_ENABLE)
default BT_SMP_CRYPTO_STACK_NATIVE
help
Select the cryptographic library to use for SMP operations (AES, AES-CMAC, ECDH P-256).
config BT_SMP_CRYPTO_STACK_NATIVE
bool "Native Bluedroid implementation"
depends on (BT_BLE_SMP_ENABLE || BT_SMP_ENABLE)
help
Use the built-in Bluedroid cryptographic implementation.
This provides compatibility with all features.
This option is only available for Bluedroid host.
config BT_SMP_CRYPTO_STACK_TINYCRYPT
bool "TinyCrypt"
help
Use TinyCrypt library for cryptographic operations.
TinyCrypt is a lightweight cryptographic library designed for constrained devices.
This can reduce code size compared to the native implementation.
This is the default option.
config BT_SMP_CRYPTO_STACK_MBEDTLS
bool "mbedTLS"
select MBEDTLS_AES_C
select MBEDTLS_CMAC_C
select MBEDTLS_ECDH_C
select MBEDTLS_ECP_C
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
help
Use mbedTLS library for cryptographic operations.
This can provide hardware acceleration on supported platforms and reduce code size
by sharing crypto implementations with other components.
endchoice
menu "BLE Log"
source "$IDF_PATH/components/bt/common/ble_log/Kconfig.in"
endmenu
+10
View File
@@ -326,6 +326,16 @@ config BT_GATTS_SECURITY_LEVELS_CHAR
help
Enable LE GATT Security Levels Characteristic
config BT_GATTS_KEY_MATERIAL_CHAR
bool "Enable Encrypted Data Key Material Characteristic"
depends on BT_GATTS_ENABLE
default n
help
Enable the Encrypted Data Key Material characteristic in GAP service.
This characteristic allows advertising data to be decrypted and authenticated
using the key material (session key + IV) as defined in Bluetooth Core
Specification Version 5.4. The characteristic requires encrypted link to read.
menuconfig BT_GATTC_ENABLE
bool "Include GATT client module(GATTC)"
depends on BT_BLE_ENABLED
@@ -440,6 +440,28 @@ esp_err_t esp_ble_gap_get_device_name(void)
return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
esp_err_t esp_ble_gap_set_key_material(const uint8_t session_key[16], const uint8_t iv[8])
{
btc_msg_t msg = {0};
btc_ble_gap_args_t arg;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
if (session_key == NULL || iv == NULL) {
return ESP_ERR_INVALID_ARG;
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_GAP_BLE;
msg.act = BTC_GAP_BLE_ACT_SET_KEY_MATERIAL;
memcpy(arg.set_key_material.session_key, session_key, 16);
memcpy(arg.set_key_material.iv, iv, 8);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
esp_err_t esp_ble_gap_get_local_used_addr(esp_bd_addr_t local_used_addr, uint8_t * addr_type)
{
if(esp_bluedroid_get_status() != (ESP_BLUEDROID_STATUS_ENABLED)) {
@@ -3120,6 +3120,25 @@ esp_err_t esp_ble_gap_set_device_name(const char *name);
*/
esp_err_t esp_ble_gap_get_device_name(void);
#if defined(CONFIG_BT_GATTS_KEY_MATERIAL_CHAR) && CONFIG_BT_GATTS_KEY_MATERIAL_CHAR
/**
* @brief Set the Encrypted Data Key Material in GAP service
*
* This function sets the session key and IV that will be exposed
* through the Key Material characteristic (UUID 0x2B88) in the GAP service.
* The Key Material allows central devices to decrypt encrypted advertising data.
*
* @param[in] session_key - 16-byte (128-bit) session key for AES-CCM encryption
* @param[in] iv - 8-byte (64-bit) initialization vector
*
* @return
* - ESP_OK : success
* - other : failed
*
*/
esp_err_t esp_ble_gap_set_key_material(const uint8_t session_key[16], const uint8_t iv[8]);
#endif // CONFIG_BT_GATTS_KEY_MATERIAL_CHAR
/**
* @brief This function is called to get local used address and address type.
* uint8_t *esp_bt_dev_get_address(void) get the public address
@@ -5406,6 +5406,22 @@ void bta_dm_ble_config_local_icon (tBTA_DM_MSG *p_data)
BTM_BleConfigLocalIcon (p_data->ble_local_icon.icon);
}
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
/*******************************************************************************
**
** Function bta_dm_ble_set_key_material
**
** Description This function sets the Encrypted Data Key Material.
**
**
*******************************************************************************/
void bta_dm_ble_set_key_material (tBTA_DM_MSG *p_data)
{
BTM_BleSetKeyMaterial (p_data->ble_key_material.session_key,
p_data->ble_key_material.iv);
}
#endif
#if (BLE_HOST_BLE_OBSERVE_EN == TRUE)
/*******************************************************************************
**
@@ -2223,6 +2223,41 @@ void BTA_DmBleConfigLocalIcon(uint16_t icon)
}
}
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
/*******************************************************************************
**
** Function BTA_DmBleSetKeyMaterial
**
** Description Set the Encrypted Data Key Material in GAP service
**
** Parameters: session_key - 16-byte session key (must not be NULL)
** iv - 8-byte initialization vector (must not be NULL)
**
** Returns void
**
*******************************************************************************/
void BTA_DmBleSetKeyMaterial(const uint8_t *session_key, const uint8_t *iv)
{
tBTA_DM_API_KEY_MATERIAL *p_msg;
if (session_key == NULL || iv == NULL) {
APPL_TRACE_ERROR("%s: NULL pointer parameter", __func__);
return;
}
if ((p_msg = (tBTA_DM_API_KEY_MATERIAL *) osi_malloc(sizeof(tBTA_DM_API_KEY_MATERIAL))) != NULL) {
memset(p_msg, 0, sizeof(tBTA_DM_API_KEY_MATERIAL));
p_msg->hdr.event = BTA_DM_API_KEY_MATERIAL_EVT;
memcpy(p_msg->session_key, session_key, 16);
memcpy(p_msg->iv, iv, 8);
bta_sys_sendmsg(p_msg);
} else {
APPL_TRACE_ERROR("%s: failed to allocate memory", __func__);
}
}
#endif
#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE)
/*******************************************************************************
**
@@ -170,6 +170,9 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {
bta_dm_ble_config_local_privacy, /* BTA_DM_API_LOCAL_PRIVACY_EVT */
#endif
bta_dm_ble_config_local_icon, /* BTA_DM_API_LOCAL_ICON_EVT */
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
bta_dm_ble_set_key_material, /* BTA_DM_API_KEY_MATERIAL_EVT */
#endif
#if (BLE_42_ADV_EN == TRUE)
bta_dm_ble_set_adv_params_all, /* BTA_DM_API_BLE_ADV_PARAM_All_EVT */
bta_dm_ble_set_adv_config, /* BTA_DM_API_BLE_SET_ADV_CONFIG_EVT */
@@ -159,6 +159,9 @@ enum {
BTA_DM_API_LOCAL_PRIVACY_EVT,
#endif
BTA_DM_API_LOCAL_ICON_EVT,
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
BTA_DM_API_KEY_MATERIAL_EVT,
#endif
/*******This event added by Yulong at 2016/10/20 to
support setting the ble advertising param by the APP******/
@@ -853,6 +856,14 @@ typedef struct {
uint16_t icon;
} tBTA_DM_API_LOCAL_ICON;
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
typedef struct {
BT_HDR hdr;
uint8_t session_key[16];
uint8_t iv[8];
} tBTA_DM_API_KEY_MATERIAL;
#endif
/* set scan parameter for BLE connections */
typedef struct {
BT_HDR hdr;
@@ -1900,6 +1911,9 @@ typedef union {
tBTA_DM_API_ENABLE_PRIVACY ble_remote_privacy;
tBTA_DM_API_LOCAL_PRIVACY ble_local_privacy;
tBTA_DM_API_LOCAL_ICON ble_local_icon;
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
tBTA_DM_API_KEY_MATERIAL ble_key_material;
#endif
tBTA_DM_API_BLE_ADV_PARAMS_ALL ble_set_adv_params_all;
tBTA_DM_API_SET_ADV_CONFIG ble_set_adv_data;
tBTA_DM_API_SET_ADV_CONFIG_RAW ble_set_adv_data_raw;
@@ -2504,6 +2518,9 @@ extern void bta_dm_ble_stop_advertising(tBTA_DM_MSG *p_data);
#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE)
extern void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_config_local_icon (tBTA_DM_MSG *p_data);
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
extern void bta_dm_ble_set_key_material (tBTA_DM_MSG *p_data);
#endif
extern void bta_dm_ble_set_adv_params_all(tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_adv_config_raw (tBTA_DM_MSG *p_data);
@@ -2939,6 +2939,22 @@ extern void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable, tBTA_SET_LOCAL_P
*******************************************************************************/
extern void BTA_DmBleConfigLocalIcon(uint16_t icon);
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
/*******************************************************************************
**
** Function BTA_DmBleSetKeyMaterial
**
** Description Set the Encrypted Data Key Material in GAP service
**
** Parameters: session_key - 16-byte session key
** iv - 8-byte initialization vector
**
** Returns void
**
*******************************************************************************/
extern void BTA_DmBleSetKeyMaterial(const uint8_t *session_key, const uint8_t *iv);
#endif
/*******************************************************************************
**
** Function BTA_DmBleEnableRemotePrivacy
@@ -3192,6 +3192,11 @@ void btc_gap_ble_call_handler(btc_msg_t *msg)
BTA_DmBleGapCsProcEnable(arg_5->cs_procedure_enable_params.conn_handle, arg_5->cs_procedure_enable_params.config_id, arg_5->cs_procedure_enable_params.enable);
break;
#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE)
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
case BTC_GAP_BLE_ACT_SET_KEY_MATERIAL:
BTA_DmBleSetKeyMaterial(arg->set_key_material.session_key, arg->set_key_material.iv);
break;
#endif
default:
break;
}
@@ -160,6 +160,9 @@ typedef enum {
BTC_GAP_BLE_CS_SET_PROCEDURE_PARAMS,
BTC_GAP_BLE_CS_PROCEDURE_ENABLE,
#endif // (BT_BLE_FEAT_CHANNEL_SOUNDING == TRUE)
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
BTC_GAP_BLE_ACT_SET_KEY_MATERIAL,
#endif
} btc_gap_ble_act_t;
/* btc_ble_gap_args_t */
@@ -215,6 +218,13 @@ typedef union {
struct cfg_local_icon_args {
uint16_t icon;
} cfg_local_icon;
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
//BTC_GAP_BLE_ACT_SET_KEY_MATERIAL
struct set_key_material_args {
uint8_t session_key[16];
uint8_t iv[8];
} set_key_material;
#endif
//BTC_GAP_BLE_ACT_UPDATE_WHITE_LIST
struct update_white_list_args {
bool add_remove;
@@ -436,6 +436,24 @@
#define UC_BT_BLE_SMP_BOND_NVS_FLASH FALSE
#endif
#ifdef CONFIG_BT_SMP_CRYPTO_STACK_NATIVE
#define UC_BT_SMP_CRYPTO_STACK_NATIVE TRUE
#else
#define UC_BT_SMP_CRYPTO_STACK_NATIVE FALSE
#endif
#ifdef CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS
#define UC_BT_SMP_CRYPTO_MBEDTLS TRUE
#else
#define UC_BT_SMP_CRYPTO_MBEDTLS FALSE
#endif
#ifdef CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT
#define UC_BT_SMP_CRYPTO_TINYCRYPT TRUE
#else
#define UC_BT_SMP_CRYPTO_TINYCRYPT FALSE
#endif
//Device Name Maximum Length
#ifdef CONFIG_BT_MAX_DEVICE_NAME_LEN
#define UC_MAX_LOC_BD_NAME_LEN CONFIG_BT_MAX_DEVICE_NAME_LEN
@@ -561,6 +579,12 @@
#define UC_BT_GATTS_SECURITY_LEVELS_CHAR FALSE
#endif
#ifdef CONFIG_BT_GATTS_KEY_MATERIAL_CHAR
#define UC_BT_GATTS_KEY_MATERIAL_CHAR CONFIG_BT_GATTS_KEY_MATERIAL_CHAR
#else
#define UC_BT_GATTS_KEY_MATERIAL_CHAR FALSE
#endif
#ifdef CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN
#define UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN
#else
@@ -494,6 +494,24 @@
#define BLE_SMP_BOND_NVS_FLASH FALSE
#endif
#if (UC_BT_SMP_CRYPTO_STACK_NATIVE)
#define SMP_CRYPTO_STACK_NATIVE TRUE
#else
#define SMP_CRYPTO_STACK_NATIVE FALSE
#endif /* UC_BT_SMP_CRYPTO_STACK_NATIVE */
#if (UC_BT_SMP_CRYPTO_MBEDTLS)
#define SMP_CRYPTO_MBEDTLS TRUE
#else
#define SMP_CRYPTO_MBEDTLS FALSE
#endif /* UC_BT_SMP_CRYPTO_MBEDTLS */
#if (UC_BT_SMP_CRYPTO_TINYCRYPT)
#define SMP_CRYPTO_TINYCRYPT TRUE
#else
#define SMP_CRYPTO_TINYCRYPT FALSE
#endif /* UC_BT_SMP_CRYPTO_TINYCRYPT */
#ifdef UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
#define BLE_ADV_REPORT_FLOW_CONTROL (UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP && BLE_INCLUDED)
#endif /* UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP */
@@ -771,6 +789,12 @@
#define BT_GATTS_SECURITY_LEVELS_CHAR FALSE
#endif
#if (UC_BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
#define BT_GATTS_KEY_MATERIAL_CHAR TRUE
#else
#define BT_GATTS_KEY_MATERIAL_CHAR FALSE
#endif
#ifdef UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN
#define BTM_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY UC_BT_BLE_ACT_SCAN_REP_ADV_SCAN
#endif
@@ -1164,6 +1164,39 @@ void BTM_BleConfigLocalIcon(uint16_t icon)
#endif
}
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
/*******************************************************************************
**
** Function BTM_BleSetKeyMaterial
**
** Description Set the Encrypted Data Key Material in GAP service
**
** Parameters session_key: 16-byte session key (must not be NULL)
** iv: 8-byte initialization vector (must not be NULL)
**
** Returns void
**
*******************************************************************************/
void BTM_BleSetKeyMaterial(const uint8_t *session_key, const uint8_t *iv)
{
#if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE && GATTS_INCLUDED == TRUE)
tGAP_BLE_ATTR_VALUE p_value;
if (session_key == NULL || iv == NULL) {
BTM_TRACE_ERROR("%s: NULL pointer parameter", __func__);
return;
}
memset(&p_value, 0, sizeof(tGAP_BLE_ATTR_VALUE));
memcpy(p_value.key_material.session_key, session_key, GAP_KEY_MATERIAL_SESSION_KEY_SIZE);
memcpy(p_value.key_material.iv, iv, GAP_KEY_MATERIAL_IV_SIZE);
GAP_BleAttrDBUpdate(GATT_UUID_GAP_KEY_MATERIAL, &p_value);
#else
BTM_TRACE_ERROR("%s\n", __func__);
#endif
}
#endif
/*******************************************************************************
**
** Function BTM_BleConfigConnParams
@@ -262,6 +262,13 @@ tGATT_STATUS gap_read_attr_value (UINT16 handle, tGATT_VALUE *p_value, BOOLEAN i
p_value->len = 2;
break;
#endif // (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE)
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
case GATT_UUID_GAP_KEY_MATERIAL:
ARRAY_TO_STREAM(p, p_db_attr->attr_value.key_material.session_key, GAP_KEY_MATERIAL_SESSION_KEY_SIZE);
ARRAY_TO_STREAM(p, p_db_attr->attr_value.key_material.iv, GAP_KEY_MATERIAL_IV_SIZE);
p_value->len = GAP_KEY_MATERIAL_SIZE;
break;
#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
}
return GATT_SUCCESS;
}
@@ -481,6 +488,20 @@ void gap_attr_db_init(void)
p_db_attr++;
#endif // (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE)
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
/* Add Encrypted Data Key Material Characteristic
* Per Bluetooth spec: readable only when authenticated and authorized,
* requires encrypted link to read.
*/
uuid.len = LEN_UUID_16;
uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_KEY_MATERIAL;
p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
GATT_PERM_READ_ENCRYPTED, GATT_CHAR_PROP_BIT_READ,
NULL, NULL);
memset(&p_db_attr->attr_value.key_material, 0, sizeof(tGAP_BLE_KEY_MATERIAL));
p_db_attr++;
#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
/* start service now */
memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
@@ -512,6 +533,11 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
GAP_TRACE_EVENT("GAP_BleAttrDBUpdate attr_uuid=0x%04x\n", attr_uuid);
if (p_value == NULL) {
GAP_TRACE_ERROR("GAP_BleAttrDBUpdate: NULL pointer parameter");
return;
}
for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++) {
if (p_db_attr->uuid == attr_uuid) {
GAP_TRACE_EVENT("Found attr_uuid=0x%04x\n", attr_uuid);
@@ -540,6 +566,13 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
break;
#endif // (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE)
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
case GATT_UUID_GAP_KEY_MATERIAL:
memcpy(&p_db_attr->attr_value.key_material, &p_value->key_material,
sizeof(tGAP_BLE_KEY_MATERIAL));
break;
#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
}
break;
}
@@ -93,7 +93,11 @@ typedef struct {
#if BLE_INCLUDED == TRUE
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
#define GAP_MAX_CHAR_NUM 6
#else
#define GAP_MAX_CHAR_NUM 5
#endif
typedef struct {
UINT16 handle;
@@ -2948,6 +2948,22 @@ BOOLEAN BTM_BleConfigPrivacy(BOOLEAN enable, tBTM_SET_LOCAL_PRIVACY_CBACK *set_l
*******************************************************************************/
void BTM_BleConfigLocalIcon(uint16_t icon);
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
/*******************************************************************************
**
** Function BTM_BleSetKeyMaterial
**
** Description Set the Encrypted Data Key Material in GAP service
**
** Parameters session_key: 16-byte session key
** iv: 8-byte initialization vector
**
** Returns void
**
*******************************************************************************/
void BTM_BleSetKeyMaterial(const uint8_t *session_key, const uint8_t *iv);
#endif
/*******************************************************************************
**
** Function BTM_BleConfigConnParams
@@ -113,6 +113,17 @@ typedef struct {
UINT16 sp_tout;
} tGAP_BLE_PREF_PARAM;
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
#define GAP_KEY_MATERIAL_SESSION_KEY_SIZE 16 /* 128-bit session key */
#define GAP_KEY_MATERIAL_IV_SIZE 8 /* 64-bit IV */
#define GAP_KEY_MATERIAL_SIZE (GAP_KEY_MATERIAL_SESSION_KEY_SIZE + GAP_KEY_MATERIAL_IV_SIZE)
typedef struct {
UINT8 session_key[GAP_KEY_MATERIAL_SESSION_KEY_SIZE];
UINT8 iv[GAP_KEY_MATERIAL_IV_SIZE];
} tGAP_BLE_KEY_MATERIAL;
#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
typedef union {
tGAP_BLE_PREF_PARAM conn_param;
BD_ADDR reconn_bda;
@@ -122,6 +133,9 @@ typedef union {
#if (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE)
UINT16 security_level;
#endif // (BT_GATTS_SECURITY_LEVELS_CHAR == TRUE)
#if (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
tGAP_BLE_KEY_MATERIAL key_material;
#endif // (BT_GATTS_KEY_MATERIAL_CHAR == TRUE)
} tGAP_BLE_ATTR_VALUE;
@@ -53,6 +53,7 @@
#define GATT_UUID_GAP_CENTRAL_ADDR_RESOL 0x2AA6
#define GATT_UUID_GAP_GATT_SECURITY_LEVELS 0x2BF5
#define GATT_UUID_GAP_KEY_MATERIAL 0x2B88 /* Encrypted Data Key Material */
/* Attribute Profile Attribute UUID */
#define GATT_UUID_GATT_SRV_CHGD 0x2A05
+5 -1
View File
@@ -48,6 +48,8 @@
/* add the target configuration to allow using internal data types and compilation options */
#include "common/bt_target.h"
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
/* define if you have fast 32-bit types on your system */
#if 1
# define HAVE_UINT_32T
@@ -569,7 +571,7 @@ return_type aes_set_key( const unsigned char key[], length_type keylen, aes_cont
/* Encrypt a single block of 16 bytes */
/* @breif change the name by snake for avoid the conflict with libcrypto */
/* @brief change the name by snake for avoid the conflict with libcrypto */
return_type bluedroid_aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] )
{
if ( ctx->rnd ) {
@@ -935,4 +937,6 @@ void bluedroid_aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char o
copy_and_key( out, s1, o_key );
}
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
#endif
@@ -31,6 +31,10 @@
#ifndef AES_H
#define AES_H
#include "common/bt_target.h"
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
#if 1
# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */
#endif
@@ -117,7 +121,7 @@ return_type aes_cbc_decrypt( const unsigned char *in,
The encryption subroutines take a key in an array of bytes in
key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
192, and 256 bits respectively. They then encrypts the input
data, in[] with this key and put the reult in the output array
data, in[] with this key and put the result in the output array
out[]. In addition, the second key array, o_key[L], is used
to output the key that is needed by the decryption subroutine
to reverse the encryption operation. The two key arrays can
@@ -159,4 +163,6 @@ void bluedroid_aes_decrypt_256( const unsigned char in[N_BLOCK],
unsigned char o_key[2 * N_BLOCK] );
#endif
#endif
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
#endif /* AES_H */
@@ -24,9 +24,12 @@
#pragma once
#include "p_256_multprecision.h"
#include "common/bt_target.h"
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
#include "p_256_multprecision.h"
typedef unsigned long DWORD;
typedef struct {
@@ -72,3 +75,5 @@ bool ECC_CheckPointIsInElliCur_P256(Point *p);
#define ECC_PointMult(q, p, n, keyLength) ECC_PointMult_Bin_NAF(q, p, n, keyLength)
void p_256_init_curve(UINT32 keyLength);
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
@@ -24,6 +24,9 @@
#pragma once
#include "stack/bt_types.h"
#include "common/bt_target.h"
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
/* Type definitions */
typedef unsigned long DWORD;
@@ -58,3 +61,5 @@ DWORD multiprecision_lshift(DWORD *c, DWORD *a, uint32_t keyLength);
void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
void multiprecision_fast_mod(DWORD *c, DWORD *a);
void multiprecision_fast_mod_P256(DWORD *c, DWORD *a);
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
@@ -23,6 +23,10 @@
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
#include "p_256_ecc_pp.h"
void p_256_init_curve(UINT32 keyLength)
@@ -76,3 +80,5 @@ void p_256_init_curve(UINT32 keyLength)
ec->G.y[0] = 0x37bf51f5;
}
}
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
@@ -24,9 +24,12 @@
//#include <stdio.h>
//#include <stdlib.h>
#include <string.h>
#include "common/bt_target.h"
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
#include "p_256_ecc_pp.h"
#include "p_256_multprecision.h"
#include "common/bt_target.h"
#if SMP_DYNAMIC_MEMORY == FALSE
elliptic_curve_t curve;
@@ -281,3 +284,5 @@ bool ECC_CheckPointIsInElliCur_P256(Point *p)
return true;
}
}
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
@@ -24,6 +24,9 @@
#include <string.h>
#include "common/bt_target.h"
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
#include "p_256_ecc_pp.h"
#include "p_256_multprecision.h"
@@ -365,7 +368,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
uint8_t UB;
uint8_t UC;
uint8_t UD;
uint8_t UE;
uint8_t U_E;
uint8_t UF;
uint8_t UG;
DWORD U;
@@ -381,7 +384,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
// E = a[8] + a[9];
E = a[8];
E += a[9];
UE = (E < a[9]);
U_E = (E < a[9]);
// F = a[9] + a[10];
F = a[9];
@@ -418,7 +421,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
c[0] = a[0];
c[0] += E;
U = (c[0] < E);
U += UE;
U += U_E;
U -= (c[0] < A);
U -= UA;
c[0] -= A;
@@ -479,7 +482,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
U -= (c[3] < a[15]);
c[3] -= a[15];
U -= (c[3] < E);
U -= UE;
U -= U_E;
c[3] -= E;
if (U & 0x80000000) {
@@ -546,7 +549,7 @@ void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
c[6] += a[15];
U += (c[6] < a[15]);
U -= (c[6] < E);
U -= UE;
U -= U_E;
c[6] -= E;
if (U & 0x80000000) {
@@ -645,3 +648,5 @@ void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength)
multiprecision_copy(aminus, C, keyLength);
}
}
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
@@ -22,7 +22,15 @@
#include "btm_int.h"
#include "stack/l2c_api.h"
#include "smp_int.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "mbedtls/ecp.h"
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
#include "tinycrypt/ecc_dh.h"
#include "tinycrypt/ecc.h"
#include "tinycrypt/constants.h"
#else
#include "p_256_ecc_pp.h"
#endif
//#include "utils/include/bt_utils.h"
#if SMP_INCLUDED == TRUE
@@ -771,10 +779,98 @@ void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
}
/* In order to prevent the x and y coordinates of the public key from being modified,
we need to check whether the x and y coordinates are on the given elliptic curve. */
#if (SMP_CRYPTO_MBEDTLS == TRUE)
{
/*
* mbedTLS validates the public key using mbedtls_ecp_check_pubkey.
*/
mbedtls_ecp_group grp = {0};
mbedtls_ecp_point pt = {0};
int rc;
UINT8 pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */
mbedtls_ecp_group_init(&grp);
mbedtls_ecp_point_init(&pt);
/* Load the group */
rc = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (rc != 0) {
SMP_TRACE_ERROR("%s, Invalid Public key. mbedtls_ecp_group_load failed: %d\n", __func__, rc);
mbedtls_ecp_point_free(&pt);
mbedtls_ecp_group_free(&grp);
reason = SMP_INVALID_PARAMETERS;
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
/* Construct peer public key in uncompressed format (0x04 || X || Y) */
pub_be[0] = 0x04;
for (int i = 0; i < BT_OCTET32_LEN; i++) {
pub_be[1 + i] = p_cb->peer_publ_key.x[BT_OCTET32_LEN - 1 - i];
pub_be[33 + i] = p_cb->peer_publ_key.y[BT_OCTET32_LEN - 1 - i];
}
/* Read public key */
rc = mbedtls_ecp_point_read_binary(&grp, &pt, pub_be, sizeof(pub_be));
if (rc != 0) {
SMP_TRACE_ERROR("%s, Invalid Public key. mbedtls_ecp_point_read_binary failed: %d\n", __func__, rc);
mbedtls_ecp_point_free(&pt);
mbedtls_ecp_group_free(&grp);
reason = SMP_INVALID_PARAMETERS;
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
/* Validate public key - check if it's on the curve */
rc = mbedtls_ecp_check_pubkey(&grp, &pt);
if (rc != 0) {
SMP_TRACE_ERROR("%s, Invalid Public key. mbedtls_ecp_check_pubkey failed: %d\n", __func__, rc);
mbedtls_ecp_point_free(&pt);
mbedtls_ecp_group_free(&grp);
reason = SMP_INVALID_PARAMETERS;
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
/* Key is valid, clean up */
mbedtls_ecp_point_free(&pt);
mbedtls_ecp_group_free(&grp);
}
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
{
/*
* TinyCrypt validates the public key using uECC_valid_public_key.
* TinyCrypt expects public key in format: X (32 bytes) || Y (32 bytes), no prefix.
*/
UINT8 pub_be[64]; /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */
/* Convert peer public key from little-endian to big-endian */
/* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
pub_be[i] = p_cb->peer_publ_key.x[BT_OCTET32_LEN - 1 - i];
pub_be[BT_OCTET32_LEN + i] = p_cb->peer_publ_key.y[BT_OCTET32_LEN - 1 - i];
}
/* Validate public key - TinyCrypt will check if it's on the curve */
/* uECC_valid_public_key returns 0 if valid, negative value if invalid */
if (uECC_valid_public_key(pub_be, uECC_secp256r1()) < 0) {
SMP_TRACE_ERROR("%s, Invalid Public key. uECC_valid_public_key failed\n", __func__);
reason = SMP_INVALID_PARAMETERS;
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
memset(pub_be, 0, sizeof(pub_be));
return;
}
/* Clear sensitive data from stack */
memset(pub_be, 0, sizeof(pub_be));
}
#else
if (!ECC_CheckPointIsInElliCur_P256((Point *)&p_cb->peer_publ_key)) {
SMP_TRACE_ERROR("%s, Invalid Public key.", __func__);
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
#endif /* SMP_CRYPTO_MBEDTLS */
p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY;
smp_wait_for_both_public_keys(p_cb, NULL);
@@ -35,7 +35,9 @@
#include "stack/hcimsgs.h"
#include "stack/btu.h"
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
#include "p_256_ecc_pp.h"
#endif
#include "osi/allocator.h"
/*******************************************************************************
@@ -51,12 +53,16 @@ void SMP_Init(void)
{
#if SMP_DYNAMIC_MEMORY
smp_cb_ptr = (tSMP_CB *)osi_malloc(sizeof(tSMP_CB));
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
curve_ptr = (elliptic_curve_t *)osi_malloc(sizeof(elliptic_curve_t));
curve_p256_ptr = (elliptic_curve_t *)osi_malloc(sizeof(elliptic_curve_t));
#endif
#endif
memset(&smp_cb, 0, sizeof(tSMP_CB));
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
memset(&curve, 0, sizeof(elliptic_curve_t));
memset(&curve_p256, 0, sizeof(elliptic_curve_t));
#endif
#if defined(SMP_INITIAL_TRACE_LEVEL)
smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
@@ -66,8 +72,10 @@ void SMP_Init(void)
SMP_TRACE_EVENT ("%s", __FUNCTION__);
smp_l2cap_if_init();
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
/* initialization of P-256 parameters */
p_256_init_curve(KEY_LENGTH_DWORDS_P256);
#endif
}
void SMP_Free(void)
@@ -75,8 +83,10 @@ void SMP_Free(void)
memset(&smp_cb, 0, sizeof(tSMP_CB));
#if SMP_DYNAMIC_MEMORY
FREE_AND_RESET(smp_cb_ptr);
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
FREE_AND_RESET(curve_ptr);
FREE_AND_RESET(curve_p256_ptr);
#endif
#endif /* #if SMP_DYNAMIC_MEMORY */
}
+195 -28
View File
@@ -32,7 +32,16 @@
#include "stack/btm_ble_api.h"
#include "smp_int.h"
#include "stack/hcimsgs.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "mbedtls/cipher.h"
#include "mbedtls/cmac.h"
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
#include "tinycrypt/aes.h"
#include "tinycrypt/cmac_mode.h"
#include "tinycrypt/constants.h"
#endif
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
typedef struct {
UINT8 *text;
UINT16 len;
@@ -46,6 +55,7 @@ const BT_OCTET16 const_Rb = {
0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
void print128(BT_OCTET16 x, const UINT8 *key_name)
{
@@ -75,6 +85,7 @@ void print128(BT_OCTET16 x, const UINT8 *key_name)
** Returns void
**
*******************************************************************************/
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
static void padding ( BT_OCTET16 dest, UINT8 length )
{
UINT8 i, *p = dest;
@@ -83,6 +94,7 @@ static void padding ( BT_OCTET16 dest, UINT8 length )
p[BT_OCTET16_LEN - i - 1] = ( i == length ) ? 0x80 : 0;
}
}
/*******************************************************************************
**
** Function leftshift_onebit
@@ -104,6 +116,8 @@ static void leftshift_onebit(UINT8 *input, UINT8 *output)
}
return;
}
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
/*******************************************************************************
**
** Function cmac_aes_cleanup
@@ -113,6 +127,7 @@ static void leftshift_onebit(UINT8 *input, UINT8 *output)
** Returns void
**
*******************************************************************************/
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
static void cmac_aes_cleanup(void)
{
if (cmac_cb.text != NULL) {
@@ -167,11 +182,12 @@ static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 t
return FALSE;
}
}
/*******************************************************************************
**
** Function cmac_prepare_last_block
**
** Description This function proceeed to prepare the last block of message
** Description This function proceed to prepare the last block of message
** Mn depending on the size of the message.
**
** Returns void
@@ -197,6 +213,8 @@ static void cmac_prepare_last_block (BT_OCTET16 k1, BT_OCTET16 k2)
smp_xor_128(&cmac_cb.text[0], k2);
}
}
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
/*******************************************************************************
**
** Function cmac_subkey_cont
@@ -206,6 +224,7 @@ static void cmac_prepare_last_block (BT_OCTET16 k1, BT_OCTET16 k2)
** Returns void
**
*******************************************************************************/
#if (SMP_CRYPTO_STACK_NATIVE == TRUE)
static void cmac_subkey_cont(tSMP_ENC *p)
{
UINT8 k1[BT_OCTET16_LEN], k2[BT_OCTET16_LEN];
@@ -262,6 +281,8 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
return ret;
}
#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */
/*******************************************************************************
**
** Function aes_cipher_msg_auth_code
@@ -271,7 +292,7 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
** Parameters key - CMAC key in little endian order, expect SRK when used by SMP.
** input - text to be signed in little endian byte order.
** length - length of the input in byte.
** tlen - lenth of mac desired
** tlen - length of mac desired
** p_signature - data pointer to where signed data to be stored, tlen long.
**
** Returns FALSE if out of resources, TRUE in other cases.
@@ -280,43 +301,189 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
UINT16 tlen, UINT8 *p_signature)
{
UINT16 len, diff;
UINT16 n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN; /* n is number of rounds */
BOOLEAN ret = FALSE;
SMP_TRACE_EVENT ("%s", __func__);
if (n == 0) {
n = 1;
#if (SMP_CRYPTO_MBEDTLS == TRUE)
{
/*
* mbedTLS CMAC implementation.
* Bluedroid and mbedTLS both use little-endian, so no byte order conversion needed.
*/
mbedtls_cipher_context_t ctx = {0};
const mbedtls_cipher_info_t *cipher_info;
int rc;
SMP_TRACE_DEBUG("AES128_CMAC (mbedTLS) started, length = %d", length);
mbedtls_cipher_init(&ctx);
cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
if (cipher_info == NULL) {
SMP_TRACE_ERROR("mbedtls_cipher_info_from_type failed");
mbedtls_cipher_free(&ctx);
return FALSE;
}
rc = mbedtls_cipher_setup(&ctx, cipher_info);
if (rc != 0) {
SMP_TRACE_ERROR("mbedtls_cipher_setup failed: %d", rc);
mbedtls_cipher_free(&ctx);
return FALSE;
}
rc = mbedtls_cipher_cmac_starts(&ctx, key, 128);
if (rc != 0) {
SMP_TRACE_ERROR("mbedtls_cipher_cmac_starts failed: %d", rc);
mbedtls_cipher_free(&ctx);
return FALSE;
}
if (length > 0 && input != NULL) {
rc = mbedtls_cipher_cmac_update(&ctx, input, length);
if (rc != 0) {
SMP_TRACE_ERROR("mbedtls_cipher_cmac_update failed: %d", rc);
mbedtls_cipher_free(&ctx);
return FALSE;
}
}
UINT8 mac[BT_OCTET16_LEN];
rc = mbedtls_cipher_cmac_finish(&ctx, mac);
mbedtls_cipher_free(&ctx);
if (rc != 0) {
SMP_TRACE_ERROR("mbedtls_cipher_cmac_finish failed: %d", rc);
/* Clear sensitive data from stack */
memset(mac, 0, sizeof(mac));
return FALSE;
}
/* Truncate to tlen bytes */
for (UINT16 i = 0; i < tlen && i < BT_OCTET16_LEN; i++) {
p_signature[i] = mac[i];
}
/* Clear sensitive data from stack */
memset(mac, 0, sizeof(mac));
ret = TRUE;
}
len = n * BT_OCTET16_LEN;
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
{
/*
* TinyCrypt CMAC implementation.
* Bluedroid uses little-endian, TinyCrypt uses big-endian.
* We reverse the key and input, then reverse the output.
*/
struct tc_aes_key_sched_struct sched;
struct tc_cmac_struct state;
UINT8 key_be[BT_OCTET16_LEN];
UINT8 *input_be = NULL;
UINT8 mac_be[BT_OCTET16_LEN];
SMP_TRACE_DEBUG("AES128_CMAC started, allocate buffer size = %d", len);
/* allocate a memory space of multiple of 16 bytes to hold text */
if ((cmac_cb.text = (UINT8 *)osi_malloc(len)) != NULL) {
cmac_cb.round = n;
SMP_TRACE_DEBUG("AES128_CMAC (TinyCrypt) started, length = %d", length);
memset(cmac_cb.text, 0, len);
diff = len - length;
/* Convert key from little-endian to big-endian */
for (int i = 0; i < BT_OCTET16_LEN; i++) {
key_be[i] = key[BT_OCTET16_LEN - 1 - i];
}
if (input != NULL && length > 0) {
memcpy(&cmac_cb.text[diff] , input, (int)length);
cmac_cb.len = length;
/* Setup CMAC */
if (tc_cmac_setup(&state, key_be, &sched) == TC_CRYPTO_FAIL) {
SMP_TRACE_ERROR("tc_cmac_setup failed");
memset(key_be, 0, sizeof(key_be));
memset(&sched, 0, sizeof(sched));
return FALSE;
}
/* Allocate and convert input from little-endian to big-endian */
if (length > 0) {
input_be = (UINT8 *)osi_malloc(length);
if (input_be == NULL) {
SMP_TRACE_ERROR("No resources for input_be");
tc_cmac_erase(&state);
memset(key_be, 0, sizeof(key_be));
memset(&sched, 0, sizeof(sched));
return FALSE;
}
for (UINT16 i = 0; i < length; i++) {
input_be[i] = input[length - 1 - i];
}
/* Update CMAC with input data */
if (tc_cmac_update(&state, input_be, length) == TC_CRYPTO_FAIL) {
SMP_TRACE_ERROR("tc_cmac_update failed");
osi_free(input_be);
tc_cmac_erase(&state);
memset(key_be, 0, sizeof(key_be));
memset(&sched, 0, sizeof(sched));
return FALSE;
}
osi_free(input_be);
}
/* Finalize CMAC */
if (tc_cmac_final(mac_be, &state) == TC_CRYPTO_FAIL) {
SMP_TRACE_ERROR("tc_cmac_final failed");
tc_cmac_erase(&state);
memset(key_be, 0, sizeof(key_be));
memset(&sched, 0, sizeof(sched));
return FALSE;
}
/* Convert MAC from big-endian to little-endian and truncate to tlen bytes */
for (UINT16 i = 0; i < tlen && i < BT_OCTET16_LEN; i++) {
p_signature[i] = mac_be[BT_OCTET16_LEN - 1 - i];
}
/* Clear sensitive data from stack */
tc_cmac_erase(&state);
memset(key_be, 0, sizeof(key_be));
memset(mac_be, 0, sizeof(mac_be));
memset(&sched, 0, sizeof(sched));
ret = TRUE;
}
#else
{
UINT16 len, diff;
UINT16 n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN;
if (n == 0) {
n = 1;
}
len = n * BT_OCTET16_LEN;
SMP_TRACE_DEBUG("AES128_CMAC started, allocate buffer size = %d", len);
/* allocate a memory space of multiple of 16 bytes to hold text */
if ((cmac_cb.text = (UINT8 *)osi_malloc(len)) != NULL) {
cmac_cb.round = n;
memset(cmac_cb.text, 0, len);
diff = len - length;
if (input != NULL && length > 0) {
memcpy(&cmac_cb.text[diff] , input, (int)length);
cmac_cb.len = length;
} else {
cmac_cb.len = 0;
}
/* prepare calculation for subkey s and last block of data */
if (cmac_generate_subkey(key)) {
/* start calculation */
ret = cmac_aes_k_calculate(key, p_signature, tlen);
}
/* clean up */
cmac_aes_cleanup();
} else {
cmac_cb.len = 0;
ret = FALSE;
SMP_TRACE_ERROR("No resources");
}
/* prepare calculation for subkey s and last block of data */
if (cmac_generate_subkey(key)) {
/* start calculation */
ret = cmac_aes_k_calculate(key, p_signature, tlen);
}
/* clean up */
cmac_aes_cleanup();
} else {
ret = FALSE;
SMP_TRACE_ERROR("No resources");
}
#endif /* SMP_CRYPTO_MBEDTLS */
return ret;
}
+305 -13
View File
@@ -34,8 +34,29 @@
#include "btm_int.h"
#include "btm_ble_int.h"
#include "stack/hcimsgs.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "mbedtls/aes.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/ecp.h"
#include "esp_random.h"
/* Random number generator function for mbedTLS ECP operations */
static int smp_mbedtls_rng(void *ctx, unsigned char *output, size_t len)
{
(void)ctx; /* Unused parameter */
esp_fill_random(output, len);
return 0;
}
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
#include "tinycrypt/aes.h"
#include "tinycrypt/cmac_mode.h"
#include "tinycrypt/ecc_dh.h"
#include "tinycrypt/ecc.h"
#include "tinycrypt/constants.h"
#else
#include "aes.h"
#include "p_256_ecc_pp.h"
#endif /* SMP_CRYPTO_MBEDTLS */
#include "device/controller.h"
#ifndef SMP_MAX_ENC_REPEAT
@@ -159,12 +180,11 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
UINT8 *plain_text, UINT8 pt_len,
tSMP_ENC *p_out)
{
aes_context ctx;
UINT8 *p_start = NULL;
UINT8 *p = NULL;
UINT8 *p_rev_data = NULL; /* input data in big endilan format */
UINT8 *p_rev_key = NULL; /* input key in big endilan format */
UINT8 *p_rev_output = NULL; /* encrypted output in big endilan format */
UINT8 *p_rev_data = NULL; /* input data in big endian format */
UINT8 *p_rev_key = NULL; /* input key in big endian format */
UINT8 *p_rev_output = NULL; /* encrypted output in big endian format */
SMP_TRACE_DEBUG ("%s\n", __func__);
if ( (p_out == NULL ) || (key_len != SMP_ENCRYT_KEY_SIZE) ) {
@@ -194,8 +214,64 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
smp_debug_print_nbyte_little_endian(p_start, (const UINT8 *)"Plain text", SMP_ENCRYT_DATA_SIZE);
#endif
p_rev_output = p;
aes_set_key(p_rev_key, SMP_ENCRYT_KEY_SIZE, &ctx);
bluedroid_aes_encrypt(p_rev_data, p, &ctx); /* outputs in byte 48 to byte 63 */
#if (SMP_CRYPTO_MBEDTLS == TRUE)
{
mbedtls_aes_context ctx = {0};
int rc;
mbedtls_aes_init(&ctx);
rc = mbedtls_aes_setkey_enc(&ctx, p_rev_key, 128);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_aes_setkey_enc failed: %d\n", __func__, rc);
mbedtls_aes_free(&ctx);
/* Clear sensitive data before freeing */
memset(p_start, 0, SMP_ENCRYT_DATA_SIZE * 4);
osi_free(p_start);
return FALSE;
}
rc = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, p_rev_data, p_rev_output);
mbedtls_aes_free(&ctx);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_aes_crypt_ecb failed: %d\n", __func__, rc);
/* Clear sensitive data before freeing */
memset(p_start, 0, SMP_ENCRYT_DATA_SIZE * 4);
osi_free(p_start);
return FALSE;
}
}
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
{
struct tc_aes_key_sched_struct sched;
/* TinyCrypt expects big-endian key and data */
if (tc_aes128_set_encrypt_key(&sched, p_rev_key) == TC_CRYPTO_FAIL) {
SMP_TRACE_ERROR("%s tc_aes128_set_encrypt_key failed\n", __func__);
memset(&sched, 0, sizeof(sched));
osi_free(p_start);
return FALSE;
}
if (tc_aes_encrypt(p_rev_output, p_rev_data, &sched) == TC_CRYPTO_FAIL) {
SMP_TRACE_ERROR("%s tc_aes_encrypt failed\n", __func__);
memset(&sched, 0, sizeof(sched));
osi_free(p_start);
return FALSE;
}
/* Clear sensitive data from key schedule */
memset(&sched, 0, sizeof(sched));
}
#else
{
aes_context ctx;
aes_set_key(p_rev_key, SMP_ENCRYT_KEY_SIZE, &ctx);
bluedroid_aes_encrypt(p_rev_data, p_rev_output, &ctx); /* outputs in byte 48 to byte 63 */
}
#endif /* SMP_CRYPTO_MBEDTLS */
p = p_out->param_buf;
REVERSE_ARRAY_TO_STREAM (p, p_rev_output, SMP_ENCRYT_DATA_SIZE);
@@ -207,6 +283,8 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
p_out->status = HCI_SUCCESS;
p_out->opcode = HCI_BLE_ENCRYPT;
/* Clear sensitive data (including key at byte 32-47) before freeing */
memset(p_start, 0, SMP_ENCRYT_DATA_SIZE * 4);
osi_free(p_start);
return TRUE;
@@ -1118,8 +1196,6 @@ void smp_continue_private_key_creation (tSMP_CB *p_cb, tBTM_RAND_ENC *p)
*******************************************************************************/
void smp_process_private_key(tSMP_CB *p_cb)
{
Point public_key;
BT_OCTET32 private_key;
tSMP_LOC_OOB_DATA *p_loc_oob = &p_cb->sc_oob_data.loc_oob_data;
SMP_TRACE_DEBUG ("%s", __FUNCTION__);
@@ -1131,10 +1207,101 @@ void smp_process_private_key(tSMP_CB *p_cb)
memcpy(p_cb->loc_publ_key.y, p_loc_oob->publ_key_used.y, BT_OCTET32_LEN);
memcpy(p_cb->local_random, p_loc_oob->randomizer, BT_OCTET16_LEN);
} else {
#if (SMP_CRYPTO_MBEDTLS == TRUE)
mbedtls_ecp_keypair keypair = {0};
int rc;
size_t olen;
mbedtls_ecp_keypair_init(&keypair);
/* Load the group */
rc = mbedtls_ecp_group_load(&keypair.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_ecp_group_load failed: %d\n", __FUNCTION__, rc);
goto mbedtls_pubkey_cleanup;
}
/* Import private key (little-endian) */
rc = mbedtls_mpi_read_binary(&keypair.MBEDTLS_PRIVATE(d), p_cb->private_key, BT_OCTET32_LEN);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_mpi_read_binary failed: %d\n", __FUNCTION__, rc);
goto mbedtls_pubkey_cleanup;
}
/* Validate private key */
rc = mbedtls_ecp_check_privkey(&keypair.MBEDTLS_PRIVATE(grp), &keypair.MBEDTLS_PRIVATE(d));
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_ecp_check_privkey failed: %d\n", __FUNCTION__, rc);
goto mbedtls_pubkey_cleanup;
}
/* Compute public key from private key */
/* mbedtls_ecp_keypair_calc_public requires a non-NULL RNG function for side-channel protection */
rc = mbedtls_ecp_keypair_calc_public(&keypair, smp_mbedtls_rng, NULL);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_ecp_keypair_calc_public failed: %d\n", __FUNCTION__, rc);
goto mbedtls_pubkey_cleanup;
}
/* Export public key in uncompressed format: 0x04 || X || Y */
UINT8 pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1];
rc = mbedtls_ecp_point_write_binary(&keypair.MBEDTLS_PRIVATE(grp), &keypair.MBEDTLS_PRIVATE(Q),
MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, pub_be, sizeof(pub_be));
if (rc != 0 || olen != sizeof(pub_be)) {
SMP_TRACE_ERROR("%s mbedtls_ecp_point_write_binary failed: %d\n", __FUNCTION__, rc);
goto mbedtls_pubkey_cleanup;
}
/* Convert X and Y from big-endian to little-endian */
/* pub_be: 0x04 || X (32 bytes) || Y (32 bytes) */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
p_cb->loc_publ_key.x[i] = pub_be[1 + BT_OCTET32_LEN - 1 - i];
p_cb->loc_publ_key.y[i] = pub_be[33 + BT_OCTET32_LEN - 1 - i];
}
mbedtls_pubkey_cleanup:
/* Clear sensitive data - mbedtls_ecp_keypair_free will zero the private key */
mbedtls_ecp_keypair_free(&keypair);
/* Note: pub_be contains public key data, no need to clear */
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
{
UINT8 pub_key[64]; /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */
UINT8 priv_be[BT_OCTET32_LEN];
/* Convert private key from little-endian to big-endian */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
priv_be[i] = p_cb->private_key[BT_OCTET32_LEN - 1 - i];
}
/* Compute public key from private key */
/* uECC_compute_public_key returns 1 if successful, 0 if failed */
if (uECC_compute_public_key(priv_be, pub_key, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) {
SMP_TRACE_ERROR("%s uECC_compute_public_key failed\n", __FUNCTION__);
memset(priv_be, 0, sizeof(priv_be));
memset(pub_key, 0, sizeof(pub_key));
return;
}
/* Convert X and Y from big-endian to little-endian */
/* TinyCrypt format: X (32 bytes) || Y (32 bytes) */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
p_cb->loc_publ_key.x[i] = pub_key[BT_OCTET32_LEN - 1 - i];
p_cb->loc_publ_key.y[i] = pub_key[BT_OCTET32_LEN + BT_OCTET32_LEN - 1 - i];
}
/* Clear sensitive data from stack */
memset(priv_be, 0, sizeof(priv_be));
memset(pub_key, 0, sizeof(pub_key));
}
#else
Point public_key;
BT_OCTET32 private_key;
memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN);
ECC_PointMult(&public_key, &(curve_p256.G), (DWORD *) private_key, KEY_LENGTH_DWORDS_P256);
memcpy(p_cb->loc_publ_key.x, public_key.x, BT_OCTET32_LEN);
memcpy(p_cb->loc_publ_key.y, public_key.y, BT_OCTET32_LEN);
#endif /* SMP_CRYPTO_MBEDTLS */
}
smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private",
@@ -1161,11 +1328,137 @@ void smp_process_private_key(tSMP_CB *p_cb)
*******************************************************************************/
void smp_compute_dhkey (tSMP_CB *p_cb)
{
SMP_TRACE_DEBUG ("%s\n", __FUNCTION__);
#if (SMP_CRYPTO_MBEDTLS == TRUE)
mbedtls_ecp_group grp = {0};
mbedtls_ecp_point Q = {0};
mbedtls_mpi d = {0};
mbedtls_mpi z = {0};
int rc;
UINT8 peer_pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */
mbedtls_ecp_group_init(&grp);
mbedtls_ecp_point_init(&Q);
mbedtls_mpi_init(&d);
mbedtls_mpi_init(&z);
/* Load the group */
rc = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_ecp_group_load failed: %d\n", __FUNCTION__, rc);
goto mbedtls_dhkey_cleanup;
}
/* Import private key (little-endian) */
rc = mbedtls_mpi_read_binary(&d, p_cb->private_key, BT_OCTET32_LEN);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_mpi_read_binary failed: %d\n", __FUNCTION__, rc);
goto mbedtls_dhkey_cleanup;
}
/* Construct peer public key in uncompressed format: 0x04 || X || Y */
peer_pub_be[0] = 0x04;
for (int i = 0; i < BT_OCTET32_LEN; i++) {
peer_pub_be[1 + i] = p_cb->peer_publ_key.x[BT_OCTET32_LEN - 1 - i];
peer_pub_be[33 + i] = p_cb->peer_publ_key.y[BT_OCTET32_LEN - 1 - i];
}
/* Read peer public key */
rc = mbedtls_ecp_point_read_binary(&grp, &Q, peer_pub_be, sizeof(peer_pub_be));
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_ecp_point_read_binary failed: %d\n", __FUNCTION__, rc);
goto mbedtls_dhkey_cleanup;
}
/* Validate peer public key */
rc = mbedtls_ecp_check_pubkey(&grp, &Q);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_ecp_check_pubkey failed: %d\n", __FUNCTION__, rc);
goto mbedtls_dhkey_cleanup;
}
/* Compute ECDH shared secret */
/* mbedtls_ecdh_compute_shared requires a non-NULL RNG function for side-channel protection */
rc = mbedtls_ecdh_compute_shared(&grp, &z, &Q, &d, smp_mbedtls_rng, NULL);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_ecdh_compute_shared failed: %d\n", __FUNCTION__, rc);
goto mbedtls_dhkey_cleanup;
}
/* Export shared secret (big-endian) and convert to little-endian for DHKey */
UINT8 shared_secret[BT_OCTET32_LEN];
rc = mbedtls_mpi_write_binary(&z, shared_secret, BT_OCTET32_LEN);
if (rc != 0) {
SMP_TRACE_ERROR("%s mbedtls_mpi_write_binary failed: %d\n", __FUNCTION__, rc);
goto mbedtls_dhkey_cleanup;
}
/* Convert shared secret from big-endian to little-endian for DHKey */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
p_cb->dhkey[i] = shared_secret[BT_OCTET32_LEN - 1 - i];
}
mbedtls_dhkey_cleanup:
/* Clear sensitive data - mbedtls_mpi_free will zero the memory */
mbedtls_mpi_free(&z);
mbedtls_mpi_free(&d);
mbedtls_ecp_point_free(&Q);
mbedtls_ecp_group_free(&grp);
/* Clear sensitive data from stack */
memset(shared_secret, 0, sizeof(shared_secret));
/* Note: peer_pub_be contains public key data, no need to clear */
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
{
UINT8 priv_be[BT_OCTET32_LEN];
UINT8 peer_pub_be[64]; /* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */
UINT8 shared_secret[BT_OCTET32_LEN];
/* Convert private key from little-endian to big-endian */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
priv_be[i] = p_cb->private_key[BT_OCTET32_LEN - 1 - i];
}
/* Convert peer public key from little-endian to big-endian */
/* TinyCrypt format: X (32 bytes) || Y (32 bytes), no prefix */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
peer_pub_be[i] = p_cb->peer_publ_key.x[BT_OCTET32_LEN - 1 - i];
peer_pub_be[BT_OCTET32_LEN + i] = p_cb->peer_publ_key.y[BT_OCTET32_LEN - 1 - i];
}
/* Validate peer public key */
/* uECC_valid_public_key returns 0 if valid, negative value if invalid */
if (uECC_valid_public_key(peer_pub_be, uECC_secp256r1()) < 0) {
SMP_TRACE_ERROR("%s Invalid peer public key\n", __FUNCTION__);
memset(priv_be, 0, sizeof(priv_be));
memset(peer_pub_be, 0, sizeof(peer_pub_be));
return;
}
/* Compute ECDH shared secret */
/* uECC_shared_secret returns TC_CRYPTO_SUCCESS (1) if successful, TC_CRYPTO_FAIL (0) if failed */
if (uECC_shared_secret(peer_pub_be, priv_be, shared_secret, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) {
SMP_TRACE_ERROR("%s uECC_shared_secret failed\n", __FUNCTION__);
memset(priv_be, 0, sizeof(priv_be));
memset(peer_pub_be, 0, sizeof(peer_pub_be));
memset(shared_secret, 0, sizeof(shared_secret));
return;
}
/* Convert shared secret from big-endian to little-endian for DHKey */
for (int i = 0; i < BT_OCTET32_LEN; i++) {
p_cb->dhkey[i] = shared_secret[BT_OCTET32_LEN - 1 - i];
}
/* Clear sensitive data from stack */
memset(priv_be, 0, sizeof(priv_be));
memset(peer_pub_be, 0, sizeof(peer_pub_be));
memset(shared_secret, 0, sizeof(shared_secret));
}
#else
Point peer_publ_key, new_publ_key;
BT_OCTET32 private_key;
SMP_TRACE_DEBUG ("%s\n", __FUNCTION__);
memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN);
memcpy(peer_publ_key.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN);
memcpy(peer_publ_key.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN);
@@ -1173,8 +1466,9 @@ void smp_compute_dhkey (tSMP_CB *p_cb)
ECC_PointMult(&new_publ_key, &peer_publ_key, (DWORD *) private_key, KEY_LENGTH_DWORDS_P256);
memcpy(p_cb->dhkey, new_publ_key.x, BT_OCTET32_LEN);
#endif /* SMP_CRYPTO_MBEDTLS */
smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"Old DHKey",
smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"DHKey",
BT_OCTET32_LEN);
smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private",
@@ -1183,8 +1477,6 @@ void smp_compute_dhkey (tSMP_CB *p_cb)
BT_OCTET32_LEN);
smp_debug_print_nbyte_little_endian (p_cb->peer_publ_key.y, (const UINT8 *)"rem public(y)",
BT_OCTET32_LEN);
smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"Reverted DHKey",
BT_OCTET32_LEN);
}
/*******************************************************************************