fix(ble/bluedroid): Replaced the psa_ api with the mbedtls_ api

This commit is contained in:
zhiweijian
2026-01-05 11:23:31 +08:00
parent fe7b658652
commit a48590a9f4
5 changed files with 281 additions and 307 deletions

View File

@@ -23,7 +23,7 @@
#include "stack/l2c_api.h"
#include "smp_int.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "psa/crypto.h"
#include "mbedtls/ecp.h"
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
#include "tinycrypt/ecc_dh.h"
#include "tinycrypt/ecc.h"
@@ -786,15 +786,27 @@ void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
#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.
* mbedTLS validates the public key using mbedtls_ecp_check_pubkey.
*/
psa_status_t status;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
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++) {
@@ -802,23 +814,31 @@ void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
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 */
/* 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;
}
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);
/* 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 */
psa_destroy_key(key_id);
mbedtls_ecp_point_free(&pt);
mbedtls_ecp_group_free(&grp);
}
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
{

View File

@@ -33,7 +33,8 @@
#include "smp_int.h"
#include "stack/hcimsgs.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "psa/crypto.h"
#include "mbedtls/cipher.h"
#include "mbedtls/cmac.h"
#elif (SMP_CRYPTO_TINYCRYPT == TRUE)
#include "tinycrypt/aes.h"
#include "tinycrypt/cmac_mode.h"
@@ -307,92 +308,65 @@ BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
#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.
* mbedTLS CMAC implementation.
* Bluedroid and mbedTLS both use little-endian, so no byte order conversion needed.
*/
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;
mbedtls_cipher_context_t ctx = {0};
const mbedtls_cipher_info_t *cipher_info;
int rc;
SMP_TRACE_DEBUG("AES128_CMAC (PSA) started, length = %d", length);
SMP_TRACE_DEBUG("AES128_CMAC (mbedTLS) 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];
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;
}
/* 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");
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;
}
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);
UINT8 mac[BT_OCTET16_LEN];
rc = mbedtls_cipher_cmac_finish(&ctx, mac);
mbedtls_cipher_free(&ctx);
status = psa_import_key(&key_attributes, key_be, BT_OCTET16_LEN, &key_id);
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("psa_import_key failed: %d", status);
if (input_be) osi_free(input_be);
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;
}
/* 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 */
/* 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];
p_signature[i] = mac[i];
}
/* Clear sensitive data from stack */
memset(key_be, 0, sizeof(key_be));
memset(mac, 0, sizeof(mac));
ret = TRUE;
}

View File

@@ -35,7 +35,18 @@
#include "btm_ble_int.h"
#include "stack/hcimsgs.h"
#if (SMP_CRYPTO_MBEDTLS == TRUE)
#include "psa/crypto.h"
#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"
@@ -206,31 +217,28 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
#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;
mbedtls_aes_context ctx = {0};
int rc;
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);
mbedtls_aes_init(&ctx);
status = psa_import_key(&key_attributes, p_rev_key, SMP_ENCRYT_KEY_SIZE, &key_id);
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("%s psa_import_key failed: %d\n", __func__, status);
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;
}
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);
rc = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, p_rev_data, p_rev_output);
mbedtls_aes_free(&ctx);
if (status != PSA_SUCCESS || output_len != SMP_ENCRYT_DATA_SIZE) {
SMP_TRACE_ERROR("%s psa_cipher_encrypt failed: %d\n", __func__, status);
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;
}
@@ -1200,37 +1208,48 @@ void smp_process_private_key(tSMP_CB *p_cb)
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;
mbedtls_ecp_keypair keypair = {0};
int rc;
size_t olen;
/* 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];
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 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);
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("%s psa_import_key failed: %d\n", __FUNCTION__, status);
goto psa_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;
}
/* 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;
/* 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 */
@@ -1240,10 +1259,10 @@ void smp_process_private_key(tSMP_CB *p_cb)
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));
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 */
@@ -1312,31 +1331,30 @@ 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];
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) */
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];
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 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);
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
SMP_TRACE_ERROR("%s psa_import_key failed: %d\n", __FUNCTION__, status);
goto psa_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 */
@@ -1346,12 +1364,34 @@ void smp_compute_dhkey (tSMP_CB *p_cb)
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 */
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;
/* 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 */
@@ -1359,11 +1399,15 @@ void smp_compute_dhkey (tSMP_CB *p_cb)
p_cb->dhkey[i] = shared_secret[BT_OCTET32_LEN - 1 - i];
}
psa_dhkey_cleanup:
psa_destroy_key(key_id);
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(priv_be, 0, sizeof(priv_be));
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];

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,7 +18,7 @@
#include "tinycrypt/ccm_mode.h"
#include "tinycrypt/constants.h"
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
#include "psa/crypto.h"
#include "mbedtls/ccm.h"
#else
#error "Please select either CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT or CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS"
#endif
@@ -129,11 +129,8 @@ static int ble_aes_ccm_encrypt(const uint8_t *key, const uint8_t *nonce,
return 0;
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_len);
size_t output_length = 0;
mbedtls_ccm_context ctx = {0};
int ret;
/* Validate inputs */
if (key == NULL || nonce == NULL || ciphertext == NULL) {
@@ -141,43 +138,30 @@ static int ble_aes_ccm_encrypt(const uint8_t *key, const uint8_t *nonce,
return -1;
}
/* Set key attributes */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, BLE_EAD_KEY_SIZE * 8);
mbedtls_ccm_init(&ctx);
/* Import key */
status = psa_import_key(&attributes, key, BLE_EAD_KEY_SIZE, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_import_key failed: %d", status);
psa_reset_key_attributes(&attributes);
/* Set encryption key */
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, BLE_EAD_KEY_SIZE * 8);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ccm_setkey failed: %d", ret);
mbedtls_ccm_free(&ctx);
return -1;
}
psa_reset_key_attributes(&attributes);
/* Encrypt and authenticate */
/* PSA AEAD encrypt outputs: ciphertext || tag */
status = psa_aead_encrypt(key_id, alg,
nonce, BLE_EAD_NONCE_SIZE,
aad, aad_len,
plaintext, plaintext_len,
ciphertext, plaintext_len + tag_len,
&output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_aead_encrypt failed: %d", status);
psa_destroy_key(key_id);
/* mbedtls_ccm_encrypt_and_tag outputs: ciphertext || tag */
ret = mbedtls_ccm_encrypt_and_tag(&ctx, plaintext_len,
nonce, BLE_EAD_NONCE_SIZE,
aad, aad_len,
plaintext, ciphertext,
ciphertext + plaintext_len, tag_len);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ccm_encrypt_and_tag failed: %d", ret);
mbedtls_ccm_free(&ctx);
return -1;
}
if (output_length != plaintext_len + tag_len) {
ESP_LOGE(TAG, "psa_aead_encrypt output length mismatch: expected %zu, got %zu",
plaintext_len + tag_len, output_length);
psa_destroy_key(key_id);
return -1;
}
psa_destroy_key(key_id);
mbedtls_ccm_free(&ctx);
return 0;
#else
#error "No crypto library selected"
@@ -253,11 +237,8 @@ static int ble_aes_ccm_decrypt(const uint8_t *key, const uint8_t *nonce,
return 0;
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_len);
size_t output_length = 0;
mbedtls_ccm_context ctx = {0};
int ret;
/* ciphertext_len here includes both ciphertext and tag */
size_t plaintext_len;
@@ -275,44 +256,31 @@ static int ble_aes_ccm_decrypt(const uint8_t *key, const uint8_t *nonce,
plaintext_len = ciphertext_len - tag_len;
/* Set key attributes */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, BLE_EAD_KEY_SIZE * 8);
mbedtls_ccm_init(&ctx);
/* Import key */
status = psa_import_key(&attributes, key, BLE_EAD_KEY_SIZE, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_import_key failed: %d", status);
psa_reset_key_attributes(&attributes);
/* Set decryption key */
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, BLE_EAD_KEY_SIZE * 8);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ccm_setkey failed: %d", ret);
mbedtls_ccm_free(&ctx);
return -1;
}
psa_reset_key_attributes(&attributes);
/* Decrypt and verify */
/* PSA AEAD decrypt expects: ciphertext || tag */
/* mbedtls_ccm_auth_decrypt expects: ciphertext || tag */
/* ciphertext_len here already includes tag length */
status = psa_aead_decrypt(key_id, alg,
nonce, BLE_EAD_NONCE_SIZE,
aad, aad_len,
ciphertext, ciphertext_len,
plaintext, plaintext_len,
&output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_aead_decrypt failed: %d", status);
psa_destroy_key(key_id);
ret = mbedtls_ccm_auth_decrypt(&ctx, plaintext_len,
nonce, BLE_EAD_NONCE_SIZE,
aad, aad_len,
ciphertext, plaintext,
ciphertext + plaintext_len, tag_len);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ccm_auth_decrypt failed: %d", ret);
mbedtls_ccm_free(&ctx);
return -1;
}
if (output_length != plaintext_len) {
ESP_LOGE(TAG, "psa_aead_decrypt output length mismatch: expected %zu, got %zu",
plaintext_len, output_length);
psa_destroy_key(key_id);
return -1;
}
psa_destroy_key(key_id);
mbedtls_ccm_free(&ctx);
return 0;
#else
#error "No crypto library selected"
@@ -407,7 +375,7 @@ int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE],
/* Ciphertext + MIC follows the randomizer */
ciphertext = &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE];
/* ciphertext_len includes both ciphertext and MIC (tag) for PSA API */
/* ciphertext_len includes both ciphertext and MIC (tag) for mbedTLS API */
ciphertext_len = encrypted_payload_size - BLE_EAD_RANDOMIZER_SIZE;
/* Generate nonce from randomizer and IV */

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,7 +18,7 @@
#include "tinycrypt/ccm_mode.h"
#include "tinycrypt/constants.h"
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
#include "psa/crypto.h"
#include "mbedtls/ccm.h"
#else
#error "Please select either CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT or CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS"
#endif
@@ -129,49 +129,33 @@ static int ble_aes_ccm_encrypt(const uint8_t *key, const uint8_t *nonce,
return 0;
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_len);
size_t output_length = 0;
mbedtls_ccm_context ctx = {0};
int ret;
/* Set key attributes */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, BLE_EAD_KEY_SIZE * 8);
mbedtls_ccm_init(&ctx);
/* Import key */
status = psa_import_key(&attributes, key, BLE_EAD_KEY_SIZE, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_import_key failed: %d", status);
psa_reset_key_attributes(&attributes);
/* Set encryption key */
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, BLE_EAD_KEY_SIZE * 8);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ccm_setkey failed: %d", ret);
mbedtls_ccm_free(&ctx);
return -1;
}
psa_reset_key_attributes(&attributes);
/* Encrypt and authenticate */
/* PSA AEAD encrypt outputs: ciphertext || tag */
status = psa_aead_encrypt(key_id, alg,
nonce, BLE_EAD_NONCE_SIZE,
aad, aad_len,
plaintext, plaintext_len,
ciphertext, plaintext_len + tag_len,
&output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_aead_encrypt failed: %d", status);
psa_destroy_key(key_id);
/* mbedtls_ccm_encrypt_and_tag outputs: ciphertext || tag */
ret = mbedtls_ccm_encrypt_and_tag(&ctx, plaintext_len,
nonce, BLE_EAD_NONCE_SIZE,
aad, aad_len,
plaintext, ciphertext,
ciphertext + plaintext_len, tag_len);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ccm_encrypt_and_tag failed: %d", ret);
mbedtls_ccm_free(&ctx);
return -1;
}
if (output_length != plaintext_len + tag_len) {
ESP_LOGE(TAG, "psa_aead_encrypt output length mismatch: expected %zu, got %zu",
plaintext_len + tag_len, output_length);
psa_destroy_key(key_id);
return -1;
}
psa_destroy_key(key_id);
mbedtls_ccm_free(&ctx);
return 0;
#else
#error "No crypto library selected"
@@ -247,11 +231,8 @@ static int ble_aes_ccm_decrypt(const uint8_t *key, const uint8_t *nonce,
return 0;
#elif defined(CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS)
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_len);
size_t output_length = 0;
mbedtls_ccm_context ctx = {0};
int ret;
/* ciphertext_len here includes both ciphertext and tag */
size_t plaintext_len;
@@ -269,43 +250,30 @@ static int ble_aes_ccm_decrypt(const uint8_t *key, const uint8_t *nonce,
plaintext_len = ciphertext_len - tag_len;
/* Set key attributes */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, BLE_EAD_KEY_SIZE * 8);
mbedtls_ccm_init(&ctx);
/* Import key */
status = psa_import_key(&attributes, key, BLE_EAD_KEY_SIZE, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_import_key failed: %d", status);
psa_reset_key_attributes(&attributes);
/* Set decryption key */
ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, BLE_EAD_KEY_SIZE * 8);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ccm_setkey failed: %d", ret);
mbedtls_ccm_free(&ctx);
return -1;
}
psa_reset_key_attributes(&attributes);
/* Decrypt and verify */
/* PSA AEAD decrypt expects: ciphertext || tag */
status = psa_aead_decrypt(key_id, alg,
nonce, BLE_EAD_NONCE_SIZE,
aad, aad_len,
ciphertext, ciphertext_len,
plaintext, plaintext_len,
&output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "psa_aead_decrypt failed: %d", status);
psa_destroy_key(key_id);
/* mbedtls_ccm_auth_decrypt expects: ciphertext || tag */
ret = mbedtls_ccm_auth_decrypt(&ctx, plaintext_len,
nonce, BLE_EAD_NONCE_SIZE,
aad, aad_len,
ciphertext, plaintext,
ciphertext + plaintext_len, tag_len);
if (ret != 0) {
ESP_LOGE(TAG, "mbedtls_ccm_auth_decrypt failed: %d", ret);
mbedtls_ccm_free(&ctx);
return -1;
}
if (output_length != plaintext_len) {
ESP_LOGE(TAG, "psa_aead_decrypt output length mismatch: expected %zu, got %zu",
plaintext_len, output_length);
psa_destroy_key(key_id);
return -1;
}
psa_destroy_key(key_id);
mbedtls_ccm_free(&ctx);
return 0;
#else
#error "No crypto library selected"
@@ -400,7 +368,7 @@ int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE],
/* Ciphertext + MIC follows the randomizer */
ciphertext = &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE];
/* ciphertext_len includes both ciphertext and MIC (tag) for PSA API */
/* ciphertext_len includes both ciphertext and MIC (tag) for mbedTLS API */
ciphertext_len = encrypted_payload_size - BLE_EAD_RANDOMIZER_SIZE;
/* Generate nonce from randomizer and IV */