diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index 929e539919..1c762a559a 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -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 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 70e967b44b..602042bdab 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,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 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 412ca9dd06..6f58d12930 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -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 */ diff --git a/components/bt/host/bluedroid/stack/smp/aes.c b/components/bt/host/bluedroid/stack/smp/aes.c index 18b56b877d..0a4bcdd747 100644 --- a/components/bt/host/bluedroid/stack/smp/aes.c +++ b/components/bt/host/bluedroid/stack/smp/aes.c @@ -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 diff --git a/components/bt/host/bluedroid/stack/smp/include/aes.h b/components/bt/host/bluedroid/stack/smp/include/aes.h index 48495bb174..508ab59796 100644 --- a/components/bt/host/bluedroid/stack/smp/include/aes.h +++ b/components/bt/host/bluedroid/stack/smp/include/aes.h @@ -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 */ 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 3b28e0c99a..acf1af8b3c 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 @@ -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 */ 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 0a33b4e24f..6bf4c32289 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 @@ -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 */ 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 abf9a8eecc..b284237f70 100644 --- a/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c +++ b/components/bt/host/bluedroid/stack/smp/p_256_curvepara.c @@ -23,6 +23,10 @@ ******************************************************************************/ #include +#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 */ 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 1f49c652bd..1bba53bca5 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 @@ -24,9 +24,12 @@ //#include //#include #include +#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 */ 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 1dbca13756..6416f8ff22 100644 --- a/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c +++ b/components/bt/host/bluedroid/stack/smp/p_256_multprecision.c @@ -24,6 +24,9 @@ #include #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 */ diff --git a/components/bt/host/bluedroid/stack/smp/smp_act.c b/components/bt/host/bluedroid/stack/smp/smp_act.c index b467a1c13d..e0a55a5771 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_act.c +++ b/components/bt/host/bluedroid/stack/smp/smp_act.c @@ -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); diff --git a/components/bt/host/bluedroid/stack/smp/smp_api.c b/components/bt/host/bluedroid/stack/smp/smp_api.c index b99c94abd8..c95dd5d739 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_api.c +++ b/components/bt/host/bluedroid/stack/smp/smp_api.c @@ -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 */ } diff --git a/components/bt/host/bluedroid/stack/smp/smp_cmac.c b/components/bt/host/bluedroid/stack/smp/smp_cmac.c index e47c56b71f..39aeccf23e 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_cmac.c +++ b/components/bt/host/bluedroid/stack/smp/smp_cmac.c @@ -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; } diff --git a/components/bt/host/bluedroid/stack/smp/smp_keys.c b/components/bt/host/bluedroid/stack/smp/smp_keys.c index 24ef814279..01652fd89f 100644 --- a/components/bt/host/bluedroid/stack/smp/smp_keys.c +++ b/components/bt/host/bluedroid/stack/smp/smp_keys.c @@ -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); } /*******************************************************************************