Files
esp-idf/components/bt/esp_ble_mesh/common/crypto_psa.c
T

714 lines
22 KiB
C

/*
* SPDX-FileCopyrightText: 2023 Nordic Semiconductor ASA
* SPDX-FileContributor: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "esp_random.h"
#include "psa/crypto.h"
#include "mesh/common.h"
#include "mesh/crypto.h"
#include "mesh/trace.h"
#include "mesh/config.h"
/* PSA Key ID range for BLE Mesh */
#define BT_MESH_PSA_KEY_ID_MIN 0x0001A000
#define BT_MESH_PSA_KEY_ID_RANGE_SIZE \
(2 * CONFIG_BLE_MESH_SUBNET_COUNT + 2 * CONFIG_BLE_MESH_APP_KEY_COUNT + 2)
/* Internal DH key pair storage
*
* PSA functions expect BIG-ENDIAN format.
*/
static struct {
bool is_ready;
psa_key_id_t priv_key_id;
uint8_t public_key[PUB_KEY_SIZE + 1]; /* Big-endian, PSA format: 0x04 + X + Y */
} dh_pair;
/* Bitmap for tracking allocated key IDs */
static uint32_t pst_keys[(BT_MESH_PSA_KEY_ID_RANGE_SIZE + 31) / 32];
static psa_key_id_t keyid_alloc(void)
{
for (int i = 0; i < BT_MESH_PSA_KEY_ID_RANGE_SIZE; i++) {
int word = i / 32;
int bit = i % 32;
if (!(pst_keys[word] & (1U << bit))) {
pst_keys[word] |= (1U << bit);
return BT_MESH_PSA_KEY_ID_MIN + i;
}
}
return PSA_KEY_ID_NULL;
}
static int keyid_free(psa_key_id_t key_id)
{
if (key_id >= BT_MESH_PSA_KEY_ID_MIN &&
key_id < BT_MESH_PSA_KEY_ID_MIN + BT_MESH_PSA_KEY_ID_RANGE_SIZE) {
int idx = key_id - BT_MESH_PSA_KEY_ID_MIN;
int word = idx / 32;
int bit = idx % 32;
pst_keys[word] &= ~(1U << bit);
return 0;
}
return -EIO;
}
static void keyid_assign(psa_key_id_t key_id)
{
if (key_id >= BT_MESH_PSA_KEY_ID_MIN &&
key_id < BT_MESH_PSA_KEY_ID_MIN + BT_MESH_PSA_KEY_ID_RANGE_SIZE) {
int idx = key_id - BT_MESH_PSA_KEY_ID_MIN;
int word = idx / 32;
int bit = idx % 32;
pst_keys[word] |= (1U << bit);
}
}
int bt_mesh_crypto_init(void)
{
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
BT_ERR("PSA crypto init failed: %d", status);
return -EIO;
}
dh_pair.is_ready = false;
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
memset(pst_keys, 0, sizeof(pst_keys));
return 0;
}
int bt_mesh_encrypt(const struct bt_mesh_key *key, const uint8_t plaintext[16],
uint8_t enc_data[16])
{
size_t output_len;
psa_status_t status;
status = psa_cipher_encrypt(key->key, PSA_ALG_ECB_NO_PADDING,
plaintext, 16, enc_data, 16, &output_len);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA cipher encrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
size_t output_len;
psa_status_t status;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, mic_size);
status = psa_aead_encrypt(key->key, alg, nonce, 13, aad, aad_len,
plaintext, len, enc_data, len + mic_size, &output_len);
if (status != PSA_SUCCESS || output_len != len + mic_size) {
BT_ERR("PSA AEAD encrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_decrypt(const struct bt_mesh_key *key, uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
size_t output_len;
psa_status_t status;
psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, mic_size);
status = psa_aead_decrypt(key->key, alg, nonce, 13, aad, aad_len,
enc_data, len + mic_size, plaintext, len, &output_len);
if (status != PSA_SUCCESS || output_len != len) {
BT_ERR("PSA AEAD decrypt failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_ccm_encrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *plaintext, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *enc_data, size_t mic_size)
{
struct bt_mesh_key mesh_key;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CCM, key, &mesh_key);
if (err) {
return err;
}
err = bt_mesh_ccm_encrypt(&mesh_key, nonce, plaintext, len, aad, aad_len,
enc_data, mic_size);
psa_destroy_key(mesh_key.key);
return err;
}
int bt_mesh_ccm_decrypt_raw_key(const uint8_t key[16], uint8_t nonce[13],
const uint8_t *enc_data, size_t len,
const uint8_t *aad, size_t aad_len,
uint8_t *plaintext, size_t mic_size)
{
struct bt_mesh_key mesh_key;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CCM, key, &mesh_key);
if (err) {
return err;
}
err = bt_mesh_ccm_decrypt(&mesh_key, nonce, enc_data, len, aad, aad_len,
plaintext, mic_size);
psa_destroy_key(mesh_key.key);
return err;
}
int bt_mesh_aes_cmac_mesh_key(const struct bt_mesh_key *key,
struct bt_mesh_sg *sg, size_t sg_len,
uint8_t mac[16])
{
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_status_t status;
size_t mac_len;
status = psa_mac_sign_setup(&operation, key->key, PSA_ALG_CMAC);
if (status != PSA_SUCCESS) {
BT_ERR("PSA MAC setup failed: %d", status);
return -EIO;
}
for (; sg_len; sg_len--, sg++) {
status = psa_mac_update(&operation, sg->data, sg->len);
if (status != PSA_SUCCESS) {
psa_mac_abort(&operation);
BT_ERR("PSA MAC update failed: %d", status);
return -EIO;
}
}
status = psa_mac_sign_finish(&operation, mac, 16, &mac_len);
if (status != PSA_SUCCESS || mac_len != 16) {
BT_ERR("PSA MAC finish failed: %d", status);
return -EIO;
}
return 0;
}
int bt_mesh_aes_cmac_raw_key(const uint8_t key[16], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[16])
{
struct bt_mesh_key key_id;
int err;
err = bt_mesh_key_import(BT_MESH_KEY_TYPE_CMAC, key, &key_id);
if (err) {
return err;
}
err = bt_mesh_aes_cmac_mesh_key(&key_id, sg, sg_len, mac);
psa_destroy_key(key_id.key);
return err;
}
int bt_mesh_sha256_hmac_raw_key(const uint8_t key[32], struct bt_mesh_sg *sg,
size_t sg_len, uint8_t mac[32])
{
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
size_t mac_len;
int err = 0;
/* Import HMAC key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, key, 32, &key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import HMAC key failed: %d", status);
return -EIO;
}
psa_reset_key_attributes(&attributes);
status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
if (status != PSA_SUCCESS) {
BT_ERR("PSA HMAC setup failed: %d", status);
err = -EIO;
goto end;
}
for (; sg_len; sg_len--, sg++) {
status = psa_mac_update(&operation, sg->data, sg->len);
if (status != PSA_SUCCESS) {
psa_mac_abort(&operation);
BT_ERR("PSA HMAC update failed: %d", status);
err = -EIO;
goto end;
}
}
status = psa_mac_sign_finish(&operation, mac, 32, &mac_len);
if (status != PSA_SUCCESS || mac_len != 32) {
BT_ERR("PSA HMAC finish failed: %d", status);
err = -EIO;
}
end:
psa_destroy_key(key_id);
return err;
}
int bt_mesh_pub_key_gen(void)
{
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
uint8_t private_key[PRIV_KEY_SIZE];
size_t key_len;
int err;
/* Destroy any existing key */
if (dh_pair.priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
}
dh_pair.is_ready = false;
/* Generate a random private key (in little-endian format for storage) */
do {
err = bt_mesh_rand(private_key, sizeof(private_key));
if (err) {
BT_ERR("Failed to generate random private key");
return err;
}
/* Ensure the private key is valid (non-zero first bytes in BE) */
} while (private_key[0] == 0 && private_key[1] == 0);
/* Configure key attributes for ECDH with P-256 */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attributes, 256);
/* Import the private key */
status = psa_import_key(&key_attributes, private_key, sizeof(private_key),
&dh_pair.priv_key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
psa_reset_key_attributes(&key_attributes);
return -EIO;
}
/* Export public key (PSA computes it from the private key) */
status = psa_export_public_key(dh_pair.priv_key_id, dh_pair.public_key,
sizeof(dh_pair.public_key), &key_len);
if (status != PSA_SUCCESS || key_len != PUB_KEY_SIZE + 1) {
BT_ERR("PSA export public key failed: %d", status);
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
psa_reset_key_attributes(&key_attributes);
return -EIO;
}
dh_pair.is_ready = true;
psa_reset_key_attributes(&key_attributes);
return 0;
}
const uint8_t *bt_mesh_pub_key_get_raw(void)
{
if (!dh_pair.is_ready) {
if (bt_mesh_pub_key_gen() != 0) {
return NULL;
}
}
return &dh_pair.public_key[1];
}
void bt_mesh_set_private_key_raw(const uint8_t pri_key[32])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
size_t key_len;
/* Destroy any existing key */
if (dh_pair.priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
}
dh_pair.is_ready = false;
/* Import the provided private key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, pri_key, PRIV_KEY_SIZE, &dh_pair.priv_key_id);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
psa_reset_key_attributes(&attributes);
return;
}
/* Export public key (PSA computes it from the private key) */
status = psa_export_public_key(dh_pair.priv_key_id, dh_pair.public_key,
sizeof(dh_pair.public_key), &key_len);
if (status != PSA_SUCCESS || key_len != PUB_KEY_SIZE + 1) {
BT_ERR("PSA export public key failed: %d", status);
psa_destroy_key(dh_pair.priv_key_id);
dh_pair.priv_key_id = PSA_KEY_ID_NULL;
psa_reset_key_attributes(&attributes);
return;
}
BT_DBG("Pubkey:%s", bt_hex(&dh_pair.public_key[1], PUB_KEY_SIZE));
BT_DBG("Privkey:%s", bt_hex(pri_key, PRIV_KEY_SIZE));
dh_pair.is_ready = true;
psa_reset_key_attributes(&attributes);
}
bool bt_mesh_check_public_key_raw(const uint8_t key[64])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
uint8_t pub_be[PUB_KEY_SIZE + 1];
/* PSA requires 0x04 prefix for uncompressed point */
pub_be[0] = 0x04;
/* Convert from little-endian to big-endian */
memcpy(&pub_be[1], key, 32);
memcpy(&pub_be[33], key + 32, 32);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, pub_be, sizeof(pub_be), &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
return false;
}
psa_destroy_key(key_id);
return true;
}
int bt_mesh_dhkey_gen_raw(const uint8_t *pub_key, const uint8_t *priv_key,
uint8_t *dhkey)
{
psa_key_id_t priv_key_id = PSA_KEY_ID_NULL;
uint8_t public_key_be[PUB_KEY_SIZE + 1];
psa_status_t status;
size_t dh_key_len;
int err = 0;
if (priv_key) {
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
/* Import custom private key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&attributes, PSA_ALG_ECDH);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&attributes, 256);
status = psa_import_key(&attributes, priv_key, PRIV_KEY_SIZE, &priv_key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import private key failed: %d", status);
return -EIO;
}
} else {
priv_key_id = dh_pair.priv_key_id;
}
/* Prepare public key with 0x04 prefix in big-endian format */
public_key_be[0] = 0x04;
/* Convert from little-endian to big-endian */
memcpy(public_key_be + 1, pub_key, 32);
memcpy(public_key_be + 33, pub_key + 32, 32);
/* Calculate shared secret */
status = psa_raw_key_agreement(PSA_ALG_ECDH, priv_key_id, public_key_be,
PUB_KEY_SIZE + 1, dhkey, DH_KEY_SIZE, &dh_key_len);
if (status != PSA_SUCCESS || dh_key_len != DH_KEY_SIZE) {
BT_ERR("PSA ECDH failed: %d", status);
err = -EIO;
}
if (priv_key && priv_key_id != PSA_KEY_ID_NULL) {
psa_destroy_key(priv_key_id);
}
return err;
}
int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16],
struct bt_mesh_key *out)
{
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
psa_key_id_t key_id = PSA_KEY_ID_NULL;
switch (type) {
case BT_MESH_KEY_TYPE_ECB:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECB_NO_PADDING);
break;
case BT_MESH_KEY_TYPE_CCM:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes,
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4));
break;
case BT_MESH_KEY_TYPE_CMAC:
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_CMAC);
break;
case BT_MESH_KEY_TYPE_NET:
#if CONFIG_BT_SETTINGS
key_id = keyid_alloc();
if (key_id == PSA_KEY_ID_NULL) {
return -ENOMEM;
}
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&key_attributes, key_id);
#else
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
#endif
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_EXPORT);
break;
case BT_MESH_KEY_TYPE_APP:
case BT_MESH_KEY_TYPE_DEV:
#if CONFIG_BT_SETTINGS
key_id = keyid_alloc();
if (key_id == PSA_KEY_ID_NULL) {
return -ENOMEM;
}
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_id(&key_attributes, key_id);
#else
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
#endif
psa_set_key_usage_flags(&key_attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&key_attributes,
PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 4));
break;
default:
return -EINVAL;
}
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&key_attributes, 128);
status = psa_import_key(&key_attributes, in, 16, &out->key);
if (status == PSA_ERROR_ALREADY_EXISTS) {
BT_WARN("Key 0x%04x already exists, destroying and reimporting", key_id);
psa_destroy_key(key_id);
status = psa_import_key(&key_attributes, in, 16, &out->key);
}
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
if (key_id != PSA_KEY_ID_NULL) {
keyid_free(key_id);
}
return -EIO;
}
return 0;
}
int bt_mesh_key_export(uint8_t out[16], const struct bt_mesh_key *in)
{
size_t data_length;
psa_status_t status;
status = psa_export_key(in->key, out, 16, &data_length);
if (status != PSA_SUCCESS || data_length != 16) {
BT_ERR("PSA export key failed: %d", status);
return -EIO;
}
return 0;
}
void bt_mesh_key_assign(struct bt_mesh_key *dst, const struct bt_mesh_key *src)
{
memcpy(dst, src, sizeof(struct bt_mesh_key));
#if CONFIG_BT_SETTINGS
keyid_assign(dst->key);
#endif
}
int bt_mesh_key_destroy(const struct bt_mesh_key *key)
{
psa_status_t status;
status = psa_destroy_key(key->key);
if (status != PSA_SUCCESS) {
BT_ERR("PSA destroy key failed: %d", status);
return -EIO;
}
#if CONFIG_BT_SETTINGS
return keyid_free(key->key);
#else
return 0;
#endif
}
int bt_mesh_key_compare(const uint8_t raw_key[16], const struct bt_mesh_key *key)
{
uint8_t out[16];
int err;
err = bt_mesh_key_export(out, key);
if (err) {
return err;
}
return memcmp(out, raw_key, 16);
}
int bt_mesh_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
uint8_t tmp[16];
size_t output_len;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
/* Swap key bytes (LE to BE) */
sys_memcpy_swap(tmp, key, 16);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
status = psa_import_key(&attributes, tmp, 16, &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
return -EINVAL;
}
/* Swap plaintext bytes and encrypt */
sys_memcpy_swap(tmp, plaintext, 16);
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
tmp, 16, enc_data, 16, &output_len);
psa_destroy_key(key_id);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA encrypt failed: %d", status);
return -EINVAL;
}
/* Swap result bytes (BE to LE) */
sys_mem_swap(enc_data, 16);
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
int bt_mesh_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
uint8_t enc_data[16])
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id;
psa_status_t status;
size_t output_len;
BT_DBG("key %s plaintext %s", bt_hex(key, 16), bt_hex(plaintext, 16));
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
status = psa_import_key(&attributes, key, 16, &key_id);
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
BT_ERR("PSA import key failed: %d", status);
return -EINVAL;
}
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
plaintext, 16, enc_data, 16, &output_len);
psa_destroy_key(key_id);
if (status != PSA_SUCCESS || output_len != 16) {
BT_ERR("PSA encrypt failed: %d", status);
return -EINVAL;
}
BT_DBG("enc_data %s", bt_hex(enc_data, 16));
return 0;
}
#if 0
int bt_mesh_rand(void *buf, size_t len)
{
psa_status_t status;
if (buf == NULL || len == 0) {
return -EINVAL;
}
status = psa_generate_random(buf, len);
return status == PSA_SUCCESS ? 0 : -EIO;
}
#endif