From c986469bbdb2110498498cd2795e73b0ebd9ffe6 Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Mon, 22 Dec 2025 12:01:09 +0800 Subject: [PATCH] feat(ble/bluedroid): Supported Bludroid host encryption using TinyCrypt --- components/bt/CMakeLists.txt | 7 +- components/bt/host/bluedroid/Kconfig.in | 45 +++++--- .../include/common/bluedroid_user_config.h | 16 ++- .../common/include/common/bt_target.h | 12 ++ components/bt/host/bluedroid/stack/smp/aes.c | 4 +- .../bt/host/bluedroid/stack/smp/include/aes.h | 4 +- .../stack/smp/include/p_256_ecc_pp.h | 4 +- .../stack/smp/include/p_256_multprecision.h | 4 +- .../bluedroid/stack/smp/p_256_curvepara.c | 4 +- .../host/bluedroid/stack/smp/p_256_ecc_pp.c | 4 +- .../bluedroid/stack/smp/p_256_multprecision.c | 4 +- .../bt/host/bluedroid/stack/smp/smp_act.c | 32 ++++++ .../bt/host/bluedroid/stack/smp/smp_api.c | 10 +- .../bt/host/bluedroid/stack/smp/smp_cmac.c | 96 +++++++++++++++- .../bt/host/bluedroid/stack/smp/smp_keys.c | 107 +++++++++++++++++- 15 files changed, 312 insertions(+), 41 deletions(-) diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 57007eb0d2..dd3cde9aff 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -725,7 +725,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 diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index fdcd30a662..e1a0b7165e 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -457,26 +457,43 @@ 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" +choice BT_SMP_CRYPTO_STACK + prompt "SMP cryptographic stack" 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 + default BT_SMP_CRYPTO_STACK_NATIVE 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. + Select the cryptographic library to use for SMP operations (AES, AES-CMAC, ECDH P-256). Note: This option is not compatible with BLE Mesh, as BLE Mesh uses the native Bluedroid ECC implementation directly. + config BT_SMP_CRYPTO_STACK_NATIVE + bool "Native Bluedroid implementation" + help + Use the built-in Bluedroid cryptographic implementation. + This is the default option and provides compatibility with all features. + + 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. + + 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 + 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 diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 602042bdab..52b82891e2 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -467,12 +467,24 @@ #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 +#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 diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 6f58d12930..36b596fb39 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -517,12 +517,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 */ diff --git a/components/bt/host/bluedroid/stack/smp/aes.c b/components/bt/host/bluedroid/stack/smp/aes.c index 0a4bcdd747..6555b6af97 100644 --- a/components/bt/host/bluedroid/stack/smp/aes.c +++ b/components/bt/host/bluedroid/stack/smp/aes.c @@ -48,7 +48,7 @@ /* add the target configuration to allow using internal data types and compilation options */ #include "common/bt_target.h" -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) /* define if you have fast 32-bit types on your system */ #if 1 @@ -937,6 +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 /* SMP_CRYPTO_STACK_NATIVE == TRUE */ #endif diff --git a/components/bt/host/bluedroid/stack/smp/include/aes.h b/components/bt/host/bluedroid/stack/smp/include/aes.h index 508ab59796..9c14e22dcf 100644 --- a/components/bt/host/bluedroid/stack/smp/include/aes.h +++ b/components/bt/host/bluedroid/stack/smp/include/aes.h @@ -33,7 +33,7 @@ #include "common/bt_target.h" -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) #if 1 # define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ @@ -163,6 +163,6 @@ void bluedroid_aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char o_key[2 * N_BLOCK] ); #endif -#endif /* SMP_CRYPTO_MBEDTLS == FALSE */ +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ #endif /* AES_H */ diff --git a/components/bt/host/bluedroid/stack/smp/include/p_256_ecc_pp.h b/components/bt/host/bluedroid/stack/smp/include/p_256_ecc_pp.h index acf1af8b3c..7c2f7279eb 100644 --- a/components/bt/host/bluedroid/stack/smp/include/p_256_ecc_pp.h +++ b/components/bt/host/bluedroid/stack/smp/include/p_256_ecc_pp.h @@ -26,7 +26,7 @@ #include "common/bt_target.h" -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) #include "p_256_multprecision.h" @@ -76,4 +76,4 @@ bool ECC_CheckPointIsInElliCur_P256(Point *p); void p_256_init_curve(UINT32 keyLength); -#endif /* SMP_CRYPTO_MBEDTLS == FALSE */ +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/include/p_256_multprecision.h b/components/bt/host/bluedroid/stack/smp/include/p_256_multprecision.h index 6bf4c32289..83b7f1876f 100644 --- a/components/bt/host/bluedroid/stack/smp/include/p_256_multprecision.h +++ b/components/bt/host/bluedroid/stack/smp/include/p_256_multprecision.h @@ -26,7 +26,7 @@ #include "stack/bt_types.h" #include "common/bt_target.h" -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) /* Type definitions */ typedef unsigned long DWORD; @@ -62,4 +62,4 @@ 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 */ +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c b/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c index b284237f70..b3fca522de 100644 --- a/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c +++ b/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c @@ -25,7 +25,7 @@ #include #include "common/bt_target.h" -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) #include "p_256_ecc_pp.h" @@ -81,4 +81,4 @@ void p_256_init_curve(UINT32 keyLength) } } -#endif /* SMP_CRYPTO_MBEDTLS == FALSE */ +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/p_256_ecc_pp.c b/components/bt/host/bluedroid/stack/smp/p_256_ecc_pp.c index 1bba53bca5..d3b9452c1e 100644 --- a/components/bt/host/bluedroid/stack/smp/p_256_ecc_pp.c +++ b/components/bt/host/bluedroid/stack/smp/p_256_ecc_pp.c @@ -26,7 +26,7 @@ #include #include "common/bt_target.h" -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) #include "p_256_ecc_pp.h" #include "p_256_multprecision.h" @@ -285,4 +285,4 @@ bool ECC_CheckPointIsInElliCur_P256(Point *p) } } -#endif /* SMP_CRYPTO_MBEDTLS == FALSE */ +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c b/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c index 6416f8ff22..92291d98b3 100644 --- a/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c +++ b/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c @@ -25,7 +25,7 @@ #include #include "common/bt_target.h" -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) #include "p_256_ecc_pp.h" #include "p_256_multprecision.h" @@ -649,4 +649,4 @@ void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength) } } -#endif /* SMP_CRYPTO_MBEDTLS == FALSE */ +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ diff --git a/components/bt/host/bluedroid/stack/smp/smp_act.c b/components/bt/host/bluedroid/stack/smp/smp_act.c index d630b3ee36..4dbb0fa6c8 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_act.c +++ b/components/bt/host/bluedroid/stack/smp/smp_act.c @@ -24,6 +24,10 @@ #include "smp_int.h" #if (SMP_CRYPTO_MBEDTLS == TRUE) #include "psa/crypto.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 @@ -812,6 +816,34 @@ void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) /* Key is valid, clean up */ psa_destroy_key(key_id); } +#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__); diff --git a/components/bt/host/bluedroid/stack/smp/smp_api.c b/components/bt/host/bluedroid/stack/smp/smp_api.c index 2284d33ee7..0b00bf151c 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_api.c +++ b/components/bt/host/bluedroid/stack/smp/smp_api.c @@ -35,7 +35,7 @@ #include "stack/hcimsgs.h" #include "stack/btu.h" -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) #include "p_256_ecc_pp.h" #endif #include "osi/allocator.h" @@ -53,13 +53,13 @@ void SMP_Init(void) { #if SMP_DYNAMIC_MEMORY smp_cb_ptr = (tSMP_CB *)osi_malloc(sizeof(tSMP_CB)); -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#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_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) memset(&curve, 0, sizeof(elliptic_curve_t)); memset(&curve_p256, 0, sizeof(elliptic_curve_t)); #endif @@ -72,7 +72,7 @@ void SMP_Init(void) SMP_TRACE_EVENT ("%s", __FUNCTION__); smp_l2cap_if_init(); -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) /* initialization of P-256 parameters */ p_256_init_curve(KEY_LENGTH_DWORDS_P256); #endif @@ -83,7 +83,7 @@ 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) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) FREE_AND_RESET(curve_ptr); FREE_AND_RESET(curve_p256_ptr); #endif diff --git a/components/bt/host/bluedroid/stack/smp/smp_cmac.c b/components/bt/host/bluedroid/stack/smp/smp_cmac.c index 39aeccf23e..9d290af559 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_cmac.c +++ b/components/bt/host/bluedroid/stack/smp/smp_cmac.c @@ -34,9 +34,13 @@ #include "stack/hcimsgs.h" #if (SMP_CRYPTO_MBEDTLS == TRUE) #include "psa/crypto.h" +#elif (SMP_CRYPTO_TINYCRYPT == TRUE) +#include "tinycrypt/aes.h" +#include "tinycrypt/cmac_mode.h" +#include "tinycrypt/constants.h" #endif -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) typedef struct { UINT8 *text; UINT16 len; @@ -50,7 +54,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 */ +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ void print128(BT_OCTET16 x, const UINT8 *key_name) { @@ -80,7 +84,7 @@ void print128(BT_OCTET16 x, const UINT8 *key_name) ** Returns void ** *******************************************************************************/ -#if (SMP_CRYPTO_MBEDTLS == FALSE) +#if (SMP_CRYPTO_STACK_NATIVE == TRUE) static void padding ( BT_OCTET16 dest, UINT8 length ) { UINT8 i, *p = dest; @@ -89,6 +93,7 @@ static void padding ( BT_OCTET16 dest, UINT8 length ) p[BT_OCTET16_LEN - i - 1] = ( i == length ) ? 0x80 : 0; } } + /******************************************************************************* ** ** Function leftshift_onebit @@ -110,6 +115,8 @@ static void leftshift_onebit(UINT8 *input, UINT8 *output) } return; } +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ + /******************************************************************************* ** ** Function cmac_aes_cleanup @@ -119,6 +126,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) { @@ -173,6 +181,7 @@ static BOOLEAN cmac_aes_k_calculate(BT_OCTET16 key, UINT8 *p_signature, UINT16 t return FALSE; } } + /******************************************************************************* ** ** Function cmac_prepare_last_block @@ -203,6 +212,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 @@ -212,6 +223,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]; @@ -268,7 +280,7 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key) return ret; } -#endif /* SMP_CRYPTO_MBEDTLS == FALSE */ +#endif /* SMP_CRYPTO_STACK_NATIVE == TRUE */ /******************************************************************************* ** @@ -381,6 +393,82 @@ BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length, /* Clear sensitive data from stack */ memset(key_be, 0, sizeof(key_be)); + ret = TRUE; + } +#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 (TinyCrypt) 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]; + } + + /* 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 diff --git a/components/bt/host/bluedroid/stack/smp/smp_keys.c b/components/bt/host/bluedroid/stack/smp/smp_keys.c index 23fe56714b..8cb553a782 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_keys.c +++ b/components/bt/host/bluedroid/stack/smp/smp_keys.c @@ -36,10 +36,16 @@ #include "stack/hcimsgs.h" #if (SMP_CRYPTO_MBEDTLS == TRUE) #include "psa/crypto.h" +#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" -#endif /* SMP_CRYPTO_MBEDTLS */ #include "p_256_ecc_pp.h" +#endif /* SMP_CRYPTO_MBEDTLS */ #include "device/controller.h" #ifndef SMP_MAX_ENC_REPEAT @@ -228,6 +234,28 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len, 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; @@ -1214,6 +1242,36 @@ psa_pubkey_cleanup: psa_destroy_key(key_id); /* Clear sensitive data from stack */ memset(priv_be, 0, sizeof(priv_be)); +#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; @@ -1303,6 +1361,53 @@ psa_dhkey_cleanup: /* Clear sensitive data from stack */ memset(priv_be, 0, sizeof(priv_be)); memset(shared_secret, 0, sizeof(shared_secret)); +#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;