feat(ble/bluedroid): Supported Bludroid host encryption using mbedtls

This commit is contained in:
zhiweijian
2025-12-18 14:31:03 +08:00
parent e4d066cea1
commit 1906584c89
14 changed files with 417 additions and 51 deletions
+20
View File
@@ -464,6 +464,26 @@ config BT_BLE_SMP_BOND_NVS_FLASH
help
This select can save SMP bonding keys to nvs flash
config BT_SMP_CRYPTO_MBEDTLS
bool "Use mbedTLS for SMP cryptographic functions"
depends on BT_BLE_SMP_ENABLE
depends on !BLE_MESH
select MBEDTLS_AES_C
select MBEDTLS_CMAC_C
select MBEDTLS_ECDH_C
select MBEDTLS_ECP_C
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
default n
help
If enabled, the SMP layer will use mbedTLS library for cryptographic
operations (AES, AES-CMAC, ECDH P-256) instead of the built-in
Bluedroid implementation. This can provide hardware acceleration
on supported platforms and reduce code size by sharing crypto
implementations with other components.
Note: This option is not compatible with BLE Mesh, as BLE Mesh
uses the native Bluedroid ECC implementation directly.
config BT_BLE_RPA_SUPPORTED
bool "Update RPA to Controller"
depends on (BT_BLE_SMP_ENABLE && ((BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR
@@ -467,6 +467,12 @@
#define UC_BT_BLE_SMP_BOND_NVS_FLASH FALSE
#endif
#ifdef CONFIG_BT_SMP_CRYPTO_MBEDTLS
#define UC_BT_SMP_CRYPTO_MBEDTLS CONFIG_BT_SMP_CRYPTO_MBEDTLS
#else
#define UC_BT_SMP_CRYPTO_MBEDTLS 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
@@ -517,6 +517,12 @@
#define BLE_SMP_BOND_NVS_FLASH FALSE
#endif
#if (UC_BT_SMP_CRYPTO_MBEDTLS)
#define SMP_CRYPTO_MBEDTLS TRUE
#else
#define SMP_CRYPTO_MBEDTLS FALSE
#endif /* UC_BT_SMP_CRYPTO_MBEDTLS */
#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 */
+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_MBEDTLS == FALSE)
/* 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_MBEDTLS == FALSE */
#endif
@@ -31,6 +31,10 @@
#ifndef AES_H
#define AES_H
#include "common/bt_target.h"
#if (SMP_CRYPTO_MBEDTLS == FALSE)
#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_MBEDTLS == FALSE */
#endif /* AES_H */
@@ -24,9 +24,12 @@
#pragma once
#include "p_256_multprecision.h"
#include "common/bt_target.h"
#if (SMP_CRYPTO_MBEDTLS == FALSE)
#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_MBEDTLS == FALSE */
@@ -24,6 +24,9 @@
#pragma once
#include "stack/bt_types.h"
#include "common/bt_target.h"
#if (SMP_CRYPTO_MBEDTLS == FALSE)
/* 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_MBEDTLS == FALSE */
@@ -23,6 +23,10 @@
******************************************************************************/
#include <string.h>
#include "common/bt_target.h"
#if (SMP_CRYPTO_MBEDTLS == FALSE)
#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_MBEDTLS == FALSE */
@@ -24,9 +24,12 @@
//#include <stdio.h>
//#include <stdlib.h>
#include <string.h>
#include "common/bt_target.h"
#if (SMP_CRYPTO_MBEDTLS == FALSE)
#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_MBEDTLS == FALSE */
@@ -24,6 +24,9 @@
#include <string.h>
#include "common/bt_target.h"
#if (SMP_CRYPTO_MBEDTLS == FALSE)
#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_MBEDTLS == FALSE */
@@ -22,7 +22,11 @@
#include "btm_int.h"
#include "stack/l2c_api.h"
#include "smp_int.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "psa/crypto.h"
#else
#include "p_256_ecc_pp.h"
#endif
//#include "utils/include/bt_utils.h"
#if SMP_INCLUDED == TRUE
@@ -775,10 +779,50 @@ 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)
{
/*
* PSA Crypto validates the public key when importing.
* We try to import the peer's public key as a ECC public key.
* If import fails, the key is invalid.
*/
psa_status_t status;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
UINT8 pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */
/* 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];
}
/* Try to import as public key - PSA will validate it's on the curve */
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attributes, 256);
psa_set_key_usage_flags(&key_attributes, 0); /* No usage needed, just validating */
status = psa_import_key(&key_attributes, pub_be, sizeof(pub_be), &key_id);
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("%s, Invalid Public key. psa_import_key failed: %d\n", __func__, status);
reason = SMP_INVALID_PARAMETERS;
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
/* Key is valid, clean up */
psa_destroy_key(key_id);
}
#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_MBEDTLS == FALSE)
#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_MBEDTLS == FALSE)
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_MBEDTLS == FALSE)
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_MBEDTLS == FALSE)
/* 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_MBEDTLS == FALSE)
FREE_AND_RESET(curve_ptr);
FREE_AND_RESET(curve_p256_ptr);
#endif
#endif /* #if SMP_DYNAMIC_MEMORY */
}
+132 -28
View File
@@ -32,7 +32,11 @@
#include "stack/btm_ble_api.h"
#include "smp_int.h"
#include "stack/hcimsgs.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "psa/crypto.h"
#endif
#if (SMP_CRYPTO_MBEDTLS == FALSE)
typedef struct {
UINT8 *text;
UINT16 len;
@@ -46,6 +50,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_MBEDTLS == FALSE */
void print128(BT_OCTET16 x, const UINT8 *key_name)
{
@@ -75,6 +80,7 @@ void print128(BT_OCTET16 x, const UINT8 *key_name)
** Returns void
**
*******************************************************************************/
#if (SMP_CRYPTO_MBEDTLS == FALSE)
static void padding ( BT_OCTET16 dest, UINT8 length )
{
UINT8 i, *p = dest;
@@ -171,7 +177,7 @@ static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 t
**
** 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
@@ -262,6 +268,8 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
return ret;
}
#endif /* SMP_CRYPTO_MBEDTLS == FALSE */
/*******************************************************************************
**
** Function aes_cipher_msg_auth_code
@@ -271,7 +279,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 +288,139 @@ 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)
{
/*
* PSA Crypto CMAC implementation.
* Bluedroid uses little-endian, PSA uses big-endian.
* We reverse the key and input, then reverse the output.
*/
psa_status_t status;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
UINT8 key_be[BT_OCTET16_LEN];
UINT8 *input_be = NULL;
UINT8 mac_be[BT_OCTET16_LEN];
size_t mac_len = 0;
SMP_TRACE_DEBUG("AES128_CMAC (PSA) started, length = %d", 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];
}
/* 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");
return FALSE;
}
for (UINT16 i = 0; i < length; i++) {
input_be[i] = input[length - 1 - i];
}
}
/* Import the key */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_CMAC);
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&key_attributes, 128);
status = psa_import_key(&key_attributes, key_be, BT_OCTET16_LEN, &key_id);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("psa_import_key failed: %d", status);
if (input_be) osi_free(input_be);
return FALSE;
}
psa_reset_key_attributes(&key_attributes);
/* Setup MAC operation */
status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_CMAC);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("psa_mac_sign_setup failed: %d", status);
psa_destroy_key(key_id);
if (input_be) osi_free(input_be);
return FALSE;
}
/* Update with input data */
if (length > 0 && input_be != NULL) {
status = psa_mac_update(&operation, input_be, length);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("psa_mac_update failed: %d", status);
psa_mac_abort(&operation);
psa_destroy_key(key_id);
osi_free(input_be);
return FALSE;
}
osi_free(input_be);
}
/* Finish and get MAC */
status = psa_mac_sign_finish(&operation, mac_be, sizeof(mac_be), &mac_len);
psa_destroy_key(key_id);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("psa_mac_sign_finish failed: %d", status);
psa_mac_abort(&operation);
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 */
memset(key_be, 0, sizeof(key_be));
ret = TRUE;
}
len = n * BT_OCTET16_LEN;
#else
{
UINT16 len, diff;
UINT16 n = (length + BT_OCTET16_LEN - 1) / 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;
if (n == 0) {
n = 1;
}
len = n * BT_OCTET16_LEN;
memset(cmac_cb.text, 0, len);
diff = len - length;
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;
if (input != NULL && length > 0) {
memcpy(&cmac_cb.text[diff] , input, (int)length);
cmac_cb.len = length;
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;
}
+153 -13
View File
@@ -34,7 +34,11 @@
#include "btm_int.h"
#include "btm_ble_int.h"
#include "stack/hcimsgs.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "psa/crypto.h"
#else
#include "aes.h"
#endif /* SMP_CRYPTO_MBEDTLS */
#include "p_256_ecc_pp.h"
#include "device/controller.h"
@@ -159,12 +163,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 +197,44 @@ 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)
{
psa_status_t status;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
size_t output_len = 0;
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&key_attributes, 128);
status = psa_import_key(&key_attributes, p_rev_key, SMP_ENCRYT_KEY_SIZE, &key_id);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("%s psa_import_key failed: %d\n", __func__, status);
osi_free(p_start);
return FALSE;
}
psa_reset_key_attributes(&key_attributes);
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, p_rev_data,
SMP_ENCRYT_DATA_SIZE, p_rev_output, SMP_ENCRYT_DATA_SIZE, &output_len);
psa_destroy_key(key_id);
if (status != PSA_SUCCESS || output_len != SMP_ENCRYT_DATA_SIZE) {
SMP_TRACE_ERROR("%s psa_cipher_encrypt failed: %d\n", __func__, status);
osi_free(p_start);
return FALSE;
}
}
#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 +246,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 +1159,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 +1170,59 @@ 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)
psa_status_t status;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
UINT8 priv_be[BT_OCTET32_LEN];
UINT8 pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */
size_t pub_len = 0;
/* 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];
}
/* Import the private key */
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attributes, 256);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
status = psa_import_key(&key_attributes, priv_be, BT_OCTET32_LEN, &key_id);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("%s psa_import_key failed: %d\n", __FUNCTION__, status);
goto psa_pubkey_cleanup;
}
psa_reset_key_attributes(&key_attributes);
/* Export public key */
status = psa_export_public_key(key_id, pub_be, sizeof(pub_be), &pub_len);
if (status != PSA_SUCCESS || pub_len != (BT_OCTET32_LEN + BT_OCTET32_LEN + 1)) {
SMP_TRACE_ERROR("%s psa_export_public_key failed: %d\n", __FUNCTION__, status);
goto psa_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];
}
psa_pubkey_cleanup:
psa_destroy_key(key_id);
/* Clear sensitive data from stack */
memset(priv_be, 0, sizeof(priv_be));
#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 +1249,64 @@ 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)
psa_status_t status;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
UINT8 priv_be[BT_OCTET32_LEN];
UINT8 peer_pub_be[BT_OCTET32_LEN + BT_OCTET32_LEN + 1]; /* 0x04 || X (32 bytes) || Y (32 bytes) */
UINT8 shared_secret[BT_OCTET32_LEN];
size_t output_len = 0;
/* 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];
}
/* Import the private key */
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attributes, 256);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
status = psa_import_key(&key_attributes, priv_be, BT_OCTET32_LEN, &key_id);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("%s psa_import_key failed: %d\n", __FUNCTION__, status);
goto psa_dhkey_cleanup;
}
psa_reset_key_attributes(&key_attributes);
/* 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];
}
/* Compute ECDH shared secret */
status = psa_raw_key_agreement(PSA_ALG_ECDH, key_id, peer_pub_be, sizeof(peer_pub_be),
shared_secret, sizeof(shared_secret), &output_len);
if (status != PSA_SUCCESS || output_len != BT_OCTET32_LEN) {
SMP_TRACE_ERROR("%s psa_raw_key_agreement failed: %d\n", __FUNCTION__, status);
goto psa_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];
}
psa_dhkey_cleanup:
psa_destroy_key(key_id);
/* Clear sensitive data from stack */
memset(priv_be, 0, sizeof(priv_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 +1314,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 +1325,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);
}
/*******************************************************************************