bt-host: add option to use PSA APIs instead of TinyCrypt
By enabling CONFIG_BT_USE_PSA_API the user can specify to use PSA APIs instead of TinyCrypt for crypto operations in bluetooth host module. This commit also extends tests/bluetooth/gatt in order to add a PSA test. Signed-off-by: Valerio Setti <vsetti@baylibre.com>
This commit is contained in:
parent
9032f8d791
commit
814b2ed457
7 changed files with 293 additions and 28 deletions
|
@ -31,10 +31,13 @@ if(CONFIG_BT_HCI_HOST)
|
|||
CONFIG_BT_OBSERVER
|
||||
scan.c
|
||||
)
|
||||
zephyr_library_sources_ifdef(
|
||||
CONFIG_BT_HOST_CRYPTO
|
||||
crypto.c
|
||||
)
|
||||
|
||||
if(CONFIG_BT_USE_PSA_API)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_HOST_CRYPTO crypto_psa.c)
|
||||
else()
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_HOST_CRYPTO crypto_tc.c)
|
||||
endif()
|
||||
|
||||
zephyr_library_sources_ifdef(
|
||||
CONFIG_BT_ECC
|
||||
ecc.c
|
||||
|
@ -108,6 +111,13 @@ if(CONFIG_BT_CONN_DISABLE_SECURITY)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_USE_PSA_API)
|
||||
zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
|
||||
zephyr_library_include_directories_ifdef(CONFIG_BUILD_WITH_TFM
|
||||
$<TARGET_PROPERTY:tfm,TFM_BINARY_DIR>/api_ns/interface/include
|
||||
)
|
||||
endif()
|
||||
|
||||
# Bluetooth Mesh has test dependencies in the host.
|
||||
# In order to compile Bsim tests with these test features
|
||||
# and PSA enabled, the libraries must be linked.
|
||||
|
|
|
@ -139,8 +139,9 @@ rsource "../audio/Kconfig"
|
|||
config BT_HOST_CRYPTO
|
||||
bool "Use crypto functionality implemented in the Bluetooth host"
|
||||
default y if !BT_CTLR_CRYPTO
|
||||
select TINYCRYPT
|
||||
select TINYCRYPT_AES
|
||||
select TINYCRYPT if !BT_USE_PSA_API
|
||||
select TINYCRYPT_AES if !BT_USE_PSA_API
|
||||
select PSA_WANT_KEY_TYPE_AES if BT_USE_PSA_API
|
||||
help
|
||||
The option adds the AES encryption support using TinyCrypt
|
||||
library if this is not provided by the controller implementation.
|
||||
|
@ -148,9 +149,9 @@ config BT_HOST_CRYPTO
|
|||
config BT_HOST_CRYPTO_PRNG
|
||||
bool "Use Tinycrypt library for random number generation"
|
||||
default y
|
||||
select TINYCRYPT_SHA256
|
||||
select TINYCRYPT_SHA256_HMAC
|
||||
select TINYCRYPT_SHA256_HMAC_PRNG
|
||||
select TINYCRYPT_SHA256 if !BT_USE_PSA_API
|
||||
select TINYCRYPT_SHA256_HMAC if !BT_USE_PSA_API
|
||||
select TINYCRYPT_SHA256_HMAC_PRNG if !BT_USE_PSA_API
|
||||
depends on BT_HOST_CRYPTO
|
||||
help
|
||||
When selected, will use tinycrypt library for random number generation.
|
||||
|
|
|
@ -107,9 +107,11 @@ config BT_GATT_CACHING
|
|||
bool "GATT Caching support"
|
||||
default y
|
||||
depends on BT_GATT_SERVICE_CHANGED
|
||||
select TINYCRYPT
|
||||
select TINYCRYPT_AES
|
||||
select TINYCRYPT_AES_CMAC
|
||||
select TINYCRYPT if !BT_USE_PSA_API
|
||||
select TINYCRYPT_AES if !BT_USE_PSA_API
|
||||
select TINYCRYPT_AES_CMAC if !BT_USE_PSA_API
|
||||
select PSA_WANT_KEY_TYPE_AES if BT_USE_PSA_API
|
||||
select PSA_WANT_ALG_CMAC if BT_USE_PSA_API
|
||||
help
|
||||
This option enables support for GATT Caching. When enabled the stack
|
||||
will register Client Supported Features and Database Hash
|
||||
|
|
151
subsys/bluetooth/host/crypto_psa.c
Normal file
151
subsys/bluetooth/host/crypto_psa.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/sys/check.h>
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/crypto.h>
|
||||
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#include "common/bt_str.h"
|
||||
|
||||
#include "hci_core.h"
|
||||
|
||||
#define LOG_LEVEL CONFIG_BT_HCI_CORE_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(bt_host_crypto);
|
||||
|
||||
int prng_init(void)
|
||||
{
|
||||
if (psa_crypto_init() != PSA_SUCCESS) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_HOST_CRYPTO_PRNG)
|
||||
int bt_rand(void *buf, size_t len)
|
||||
{
|
||||
if (psa_generate_random(buf, len) == PSA_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
#else /* !CONFIG_BT_HOST_CRYPTO_PRNG */
|
||||
int bt_rand(void *buf, size_t len)
|
||||
{
|
||||
CHECKIF(buf == NULL || len == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bt_hci_le_rand(buf, len);
|
||||
}
|
||||
#endif /* CONFIG_BT_HOST_CRYPTO_PRNG */
|
||||
|
||||
int bt_encrypt_le(const uint8_t key[16], const uint8_t plaintext[16],
|
||||
uint8_t enc_data[16])
|
||||
{
|
||||
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_status_t status, destroy_status;
|
||||
size_t out_len;
|
||||
uint8_t tmp[16];
|
||||
|
||||
CHECKIF(key == NULL || plaintext == NULL || enc_data == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOG_DBG("key %s", bt_hex(key, 16));
|
||||
LOG_DBG("plaintext %s", bt_hex(plaintext, 16));
|
||||
|
||||
sys_memcpy_swap(tmp, key, 16);
|
||||
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_bits(&attr, 128);
|
||||
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT);
|
||||
psa_set_key_algorithm(&attr, PSA_ALG_ECB_NO_PADDING);
|
||||
if (psa_import_key(&attr, tmp, 16, &key_id) != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to import AES key");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sys_memcpy_swap(tmp, plaintext, 16);
|
||||
|
||||
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, tmp, 16,
|
||||
enc_data, 16, &out_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("AES encryption failed");
|
||||
}
|
||||
|
||||
destroy_status = psa_destroy_key(key_id);
|
||||
if (destroy_status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to destroy AES key");
|
||||
}
|
||||
|
||||
if ((status != PSA_SUCCESS) || (destroy_status != PSA_SUCCESS)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
sys_mem_swap(enc_data, 16);
|
||||
|
||||
LOG_DBG("enc_data %s", bt_hex(enc_data, 16));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
|
||||
uint8_t enc_data[16])
|
||||
{
|
||||
psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_status_t status, destroy_status;
|
||||
size_t out_len;
|
||||
|
||||
CHECKIF(key == NULL || plaintext == NULL || enc_data == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOG_DBG("key %s", bt_hex(key, 16));
|
||||
LOG_DBG("plaintext %s", bt_hex(plaintext, 16));
|
||||
|
||||
psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_bits(&attr, 128);
|
||||
psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT);
|
||||
psa_set_key_algorithm(&attr, PSA_ALG_ECB_NO_PADDING);
|
||||
if (psa_import_key(&attr, key, 16, &key_id) != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to import AES key");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
|
||||
plaintext, 16, enc_data, 16, &out_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
LOG_ERR("AES encryption failed");
|
||||
}
|
||||
|
||||
destroy_status = psa_destroy_key(key_id);
|
||||
if (destroy_status != PSA_SUCCESS) {
|
||||
LOG_ERR("Failed to destroy AES key");
|
||||
}
|
||||
|
||||
if ((status != PSA_SUCCESS) || (destroy_status != PSA_SUCCESS)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
LOG_DBG("enc_data %s", bt_hex(enc_data, 16));
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -21,11 +21,15 @@
|
|||
#include <zephyr/settings/settings.h>
|
||||
|
||||
#if defined(CONFIG_BT_GATT_CACHING)
|
||||
#if defined(CONFIG_BT_USE_PSA_API)
|
||||
#include "psa/crypto.h"
|
||||
#else /* CONFIG_BT_USE_PSA_API */
|
||||
#include <tinycrypt/constants.h>
|
||||
#include <tinycrypt/utils.h>
|
||||
#include <tinycrypt/aes.h>
|
||||
#include <tinycrypt/cmac_mode.h>
|
||||
#include <tinycrypt/ccm_mode.h>
|
||||
#endif /* CONFIG_BT_USE_PSA_API */
|
||||
#endif /* CONFIG_BT_GATT_CACHING */
|
||||
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
|
@ -693,11 +697,93 @@ static ssize_t cf_write(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
|||
return len;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_USE_PSA_API)
|
||||
struct gen_hash_state {
|
||||
struct tc_cmac_struct state;
|
||||
psa_mac_operation_t operation;
|
||||
psa_key_id_t key;
|
||||
int err;
|
||||
};
|
||||
|
||||
static int db_hash_setup(struct gen_hash_state *state, uint8_t *key)
|
||||
{
|
||||
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_bits(&key_attr, 128);
|
||||
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE);
|
||||
psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC);
|
||||
|
||||
if (psa_import_key(&key_attr, key, 16, &(state->key)) != PSA_SUCCESS) {
|
||||
LOG_ERR("Unable to import the key for AES CMAC");
|
||||
return -EIO;
|
||||
}
|
||||
state->operation = psa_mac_operation_init();
|
||||
if (psa_mac_sign_setup(&(state->operation), state->key,
|
||||
PSA_ALG_CMAC) != PSA_SUCCESS) {
|
||||
LOG_ERR("CMAC operation init failed");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int db_hash_update(struct gen_hash_state *state, uint8_t *data, size_t len)
|
||||
{
|
||||
if (psa_mac_update(&(state->operation), data, len) != PSA_SUCCESS) {
|
||||
LOG_ERR("CMAC update failed");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int db_hash_finish(struct gen_hash_state *state)
|
||||
{
|
||||
size_t mac_length;
|
||||
|
||||
if (psa_mac_sign_finish(&(state->operation), db_hash.hash, 16,
|
||||
&mac_length) != PSA_SUCCESS) {
|
||||
LOG_ERR("CMAC finish failed");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* CONFIG_BT_USE_PSA_API */
|
||||
struct gen_hash_state {
|
||||
struct tc_cmac_struct state;
|
||||
struct tc_aes_key_sched_struct sched;
|
||||
int err;
|
||||
};
|
||||
|
||||
static int db_hash_setup(struct gen_hash_state *state, uint8_t *key)
|
||||
{
|
||||
if (tc_cmac_setup(&(state->state), key, &(state->sched)) == TC_CRYPTO_FAIL) {
|
||||
LOG_ERR("CMAC setup failed");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int db_hash_update(struct gen_hash_state *state, uint8_t *data, size_t len)
|
||||
{
|
||||
if (tc_cmac_update(&state->state, data, len) == TC_CRYPTO_FAIL) {
|
||||
LOG_ERR("CMAC update failed");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int db_hash_finish(struct gen_hash_state *state)
|
||||
{
|
||||
if (tc_cmac_final(db_hash.hash, &(state->state)) == TC_CRYPTO_FAIL) {
|
||||
LOG_ERR("CMAC finish failed");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* CONFIG_BT_USE_PSA_API */
|
||||
|
||||
union hash_attr_value {
|
||||
/* Bluetooth Core Specification Version 5.3 | Vol 3, Part G
|
||||
* Table 3.1: Service declaration
|
||||
|
@ -755,15 +841,15 @@ static uint8_t gen_hash_m(const struct bt_gatt_attr *attr, uint16_t handle,
|
|||
case BT_UUID_GATT_CHRC_VAL:
|
||||
case BT_UUID_GATT_CEP_VAL:
|
||||
value = sys_cpu_to_le16(handle);
|
||||
if (tc_cmac_update(&state->state, (uint8_t *)&value,
|
||||
sizeof(handle)) == TC_CRYPTO_FAIL) {
|
||||
if (db_hash_update(state, (uint8_t *)&value,
|
||||
sizeof(handle)) != 0) {
|
||||
state->err = -EINVAL;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
value = sys_cpu_to_le16(u16->val);
|
||||
if (tc_cmac_update(&state->state, (uint8_t *)&value,
|
||||
sizeof(u16->val)) == TC_CRYPTO_FAIL) {
|
||||
if (db_hash_update(state, (uint8_t *)&value,
|
||||
sizeof(u16->val)) != 0) {
|
||||
state->err = -EINVAL;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -774,8 +860,7 @@ static uint8_t gen_hash_m(const struct bt_gatt_attr *attr, uint16_t handle,
|
|||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
if (tc_cmac_update(&state->state, data, len) ==
|
||||
TC_CRYPTO_FAIL) {
|
||||
if (db_hash_update(state, data, len) != 0) {
|
||||
state->err = -EINVAL;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
@ -788,18 +873,19 @@ static uint8_t gen_hash_m(const struct bt_gatt_attr *attr, uint16_t handle,
|
|||
case BT_UUID_GATT_CPF_VAL:
|
||||
case BT_UUID_GATT_CAF_VAL:
|
||||
value = sys_cpu_to_le16(handle);
|
||||
if (tc_cmac_update(&state->state, (uint8_t *)&value,
|
||||
sizeof(handle)) == TC_CRYPTO_FAIL) {
|
||||
if (db_hash_update(state, (uint8_t *)&value,
|
||||
sizeof(handle)) != 0) {
|
||||
state->err = -EINVAL;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
value = sys_cpu_to_le16(u16->val);
|
||||
if (tc_cmac_update(&state->state, (uint8_t *)&value,
|
||||
sizeof(u16->val)) == TC_CRYPTO_FAIL) {
|
||||
if (db_hash_update(state, (uint8_t *)&value,
|
||||
sizeof(u16->val)) != 0) {
|
||||
state->err = -EINVAL;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
|
@ -825,18 +911,15 @@ static void db_hash_store(void)
|
|||
static void db_hash_gen(void)
|
||||
{
|
||||
uint8_t key[16] = {};
|
||||
struct tc_aes_key_sched_struct sched;
|
||||
struct gen_hash_state state;
|
||||
|
||||
if (tc_cmac_setup(&state.state, key, &sched) == TC_CRYPTO_FAIL) {
|
||||
LOG_ERR("Unable to setup AES CMAC");
|
||||
if (db_hash_setup(&state, key) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bt_gatt_foreach_attr(0x0001, 0xffff, gen_hash_m, &state);
|
||||
|
||||
if (tc_cmac_final(db_hash.hash, &state.state) == TC_CRYPTO_FAIL) {
|
||||
LOG_ERR("Unable to calculate hash");
|
||||
if (db_hash_finish(&state) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,3 +14,21 @@ tests:
|
|||
tags:
|
||||
- bluetooth
|
||||
- gatt
|
||||
bluetooth.gatt.psa:
|
||||
filter: CONFIG_PSA_CRYPTO_CLIENT
|
||||
extra_args:
|
||||
- EXTRA_DTC_OVERLAY_FILE="test.overlay"
|
||||
platform_allow:
|
||||
- native_posix
|
||||
- native_posix/native/64
|
||||
- native_sim
|
||||
- native_sim/native/64
|
||||
- qemu_x86
|
||||
- qemu_cortex_m3
|
||||
- nrf5340dk/nrf5340/cpuapp/ns
|
||||
- nrf52840dk/nrf52840
|
||||
integration_platforms:
|
||||
- native_sim
|
||||
tags:
|
||||
- bluetooth
|
||||
- gatt
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue