mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
Reference in New Issue
Block a user