Bluetooth: host: Remove dependency on host emulation for debug ECC keys
Remove the depency on host emulation of ECC for the Use debug keys option. This allows the application to use debug keys without shifting the ECC from the controller to the host, which could potentially alter the behavior of the application and make debugging this way less useful. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
parent
e0787bf31b
commit
4a25fb7136
5 changed files with 141 additions and 63 deletions
|
@ -429,7 +429,6 @@ config BT_FIXED_PASSKEY
|
|||
|
||||
config BT_USE_DEBUG_KEYS
|
||||
bool "Enable Security Manager Debug Mode"
|
||||
depends on BT_TINYCRYPT_ECC
|
||||
help
|
||||
This option places Security Manager in a Debug Mode. In this mode
|
||||
predefined Diffie-Hellman private/public key pair is used as described
|
||||
|
|
|
@ -21,6 +21,17 @@ struct bt_pub_key_cb {
|
|||
struct bt_pub_key_cb *_next;
|
||||
};
|
||||
|
||||
/* @brief Check if public key is equal to the debug public key.
|
||||
*
|
||||
* Compare the Public key to the Bluetooth specification defined debug public
|
||||
* key.
|
||||
*
|
||||
* @param pub_key The public key to compare.
|
||||
*
|
||||
* @return True if the public key is the debug public key.
|
||||
*/
|
||||
bool bt_pub_key_is_debug(uint8_t *pub_key);
|
||||
|
||||
/* @brief Generate a new Public Key.
|
||||
*
|
||||
* Generate a new ECC Public Key. The callback will persist even after the
|
||||
|
|
|
@ -9312,6 +9312,24 @@ int bt_br_set_discoverable(bool enable)
|
|||
#endif /* CONFIG_BT_BREDR */
|
||||
|
||||
#if defined(CONFIG_BT_ECC)
|
||||
static const uint8_t debug_public_key[64] = {
|
||||
/* X */
|
||||
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
|
||||
0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
|
||||
0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
|
||||
0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
|
||||
/* Y */
|
||||
0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
|
||||
0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
|
||||
0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
|
||||
0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc
|
||||
};
|
||||
|
||||
bool bt_pub_key_is_debug(uint8_t *pub_key)
|
||||
{
|
||||
return memcmp(pub_key, debug_public_key, 64) == 0;
|
||||
}
|
||||
|
||||
int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
|
||||
{
|
||||
int err;
|
||||
|
@ -9328,6 +9346,16 @@ int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS)) {
|
||||
if (!BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
|
||||
BT_WARN("ECC Debug keys HCI command not available");
|
||||
} else {
|
||||
atomic_set_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY);
|
||||
new_cb->func(debug_public_key);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
new_cb->_next = pub_key_cb;
|
||||
pub_key_cb = new_cb;
|
||||
|
||||
|
@ -9350,6 +9378,11 @@ int bt_pub_key_gen(struct bt_pub_key_cb *new_cb)
|
|||
|
||||
const uint8_t *bt_pub_key_get(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS) &&
|
||||
BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
|
||||
return debug_public_key;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(bt_dev.flags, BT_DEV_HAS_PUB_KEY)) {
|
||||
return pub_key;
|
||||
}
|
||||
|
@ -9357,10 +9390,41 @@ const uint8_t *bt_pub_key_get(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb)
|
||||
static int hci_generate_dhkey_v1(const uint8_t *remote_pk)
|
||||
{
|
||||
struct bt_hci_cp_le_generate_dhkey *cp;
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY, sizeof(*cp));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
cp = net_buf_add(buf, sizeof(*cp));
|
||||
memcpy(cp->key, remote_pk, sizeof(cp->key));
|
||||
|
||||
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY, buf, NULL);
|
||||
}
|
||||
|
||||
static int hci_generate_dhkey_v2(const uint8_t *remote_pk, uint8_t key_type)
|
||||
{
|
||||
struct bt_hci_cp_le_generate_dhkey_v2 *cp;
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY_V2, sizeof(*cp));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
cp = net_buf_add(buf, sizeof(*cp));
|
||||
memcpy(cp->key, remote_pk, sizeof(cp->key));
|
||||
cp->key_type = key_type;
|
||||
|
||||
return bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY_V2, buf, NULL);
|
||||
}
|
||||
|
||||
int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (dh_key_cb == cb) {
|
||||
|
@ -9377,18 +9441,17 @@ int bt_dh_key_gen(const uint8_t remote_pk[64], bt_dh_key_cb_t cb)
|
|||
|
||||
dh_key_cb = cb;
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_GENERATE_DHKEY, sizeof(*cp));
|
||||
if (!buf) {
|
||||
dh_key_cb = NULL;
|
||||
return -ENOBUFS;
|
||||
if (IS_ENABLED(CONFIG_BT_USE_DEBUG_KEYS) &&
|
||||
BT_CMD_TEST(bt_dev.supported_commands, 41, 2)) {
|
||||
err = hci_generate_dhkey_v2(remote_pk,
|
||||
BT_HCI_LE_KEY_TYPE_DEBUG);
|
||||
} else {
|
||||
err = hci_generate_dhkey_v1(remote_pk);
|
||||
}
|
||||
|
||||
cp = net_buf_add(buf, sizeof(*cp));
|
||||
memcpy(cp->key, remote_pk, sizeof(cp->key));
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_GENERATE_DHKEY, buf, NULL);
|
||||
if (err) {
|
||||
dh_key_cb = NULL;
|
||||
BT_WARN("Failed to generate DHKey (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,21 +46,12 @@ static const uint8_t debug_private_key_be[32] = {
|
|||
0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_USE_DEBUG_KEYS)
|
||||
static const uint8_t debug_public_key[64] = {
|
||||
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac,
|
||||
0x11, 0x91, 0xf4, 0xef, 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
|
||||
0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, 0x8b, 0xd2, 0x89, 0x15,
|
||||
0xd0, 0x8e, 0x1c, 0x74, 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
|
||||
0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, 0x6d, 0xeb, 0x2a, 0x65,
|
||||
0x49, 0x9c, 0x80, 0xdc
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
PENDING_PUB_KEY,
|
||||
PENDING_DHKEY,
|
||||
|
||||
USE_DEBUG_KEY,
|
||||
|
||||
/* Total number of flags - must be at the end of the enum */
|
||||
NUM_FLAGS,
|
||||
};
|
||||
|
@ -107,7 +98,6 @@ static void send_cmd_status(uint16_t opcode, uint8_t status)
|
|||
|
||||
static uint8_t generate_keys(void)
|
||||
{
|
||||
#if !defined(CONFIG_BT_USE_DEBUG_KEYS)
|
||||
do {
|
||||
int rc;
|
||||
|
||||
|
@ -120,11 +110,7 @@ static uint8_t generate_keys(void)
|
|||
|
||||
/* make sure generated key isn't debug key */
|
||||
} while (memcmp(ecc.private_key_be, debug_private_key_be, 32) == 0);
|
||||
#else
|
||||
sys_memcpy_swap(ecc.public_key_be, debug_public_key, 32);
|
||||
sys_memcpy_swap(&ecc.public_key_be[32], &debug_public_key[32], 32);
|
||||
memcpy(ecc.private_key_be, debug_private_key_be, 32);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -180,7 +166,11 @@ static void emulate_le_generate_dhkey(void)
|
|||
BT_ERR("public key is not valid (ret %d)", ret);
|
||||
ret = TC_CRYPTO_FAIL;
|
||||
} else {
|
||||
ret = uECC_shared_secret(ecc.public_key_be, ecc.private_key_be,
|
||||
bool use_debug = atomic_test_bit(flags, USE_DEBUG_KEY);
|
||||
|
||||
ret = uECC_shared_secret(ecc.public_key_be,
|
||||
use_debug ? debug_private_key_be :
|
||||
ecc.private_key_be,
|
||||
ecc.dhkey_be, &curve_secp256r1);
|
||||
}
|
||||
|
||||
|
@ -240,40 +230,58 @@ static void clear_ecc_events(struct net_buf *buf)
|
|||
cmd->events[1] &= ~0x01; /* LE Generate DHKey Compl Event */
|
||||
}
|
||||
|
||||
static void le_gen_dhkey(struct net_buf *buf)
|
||||
static uint8_t le_gen_dhkey(uint8_t *key, uint8_t key_type)
|
||||
{
|
||||
if (atomic_test_bit(flags, PENDING_PUB_KEY)) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
if (key_type > BT_HCI_LE_KEY_TYPE_DEBUG) {
|
||||
return BT_HCI_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (atomic_test_and_set_bit(flags, PENDING_DHKEY)) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Convert X and Y coordinates from little-endian HCI to
|
||||
* big-endian (expected by the crypto API).
|
||||
*/
|
||||
sys_memcpy_swap(ecc.public_key_be, key, 32);
|
||||
sys_memcpy_swap(&ecc.public_key_be[32], &key[32], 32);
|
||||
|
||||
atomic_set_bit_to(flags, USE_DEBUG_KEY,
|
||||
key_type == BT_HCI_LE_KEY_TYPE_DEBUG);
|
||||
|
||||
k_sem_give(&cmd_sem);
|
||||
|
||||
return BT_HCI_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static void le_gen_dhkey_v1(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_cp_le_generate_dhkey *cmd;
|
||||
uint8_t status;
|
||||
|
||||
if (atomic_test_bit(flags, PENDING_PUB_KEY)) {
|
||||
status = BT_HCI_ERR_CMD_DISALLOWED;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
if (buf->len < sizeof(struct bt_hci_cp_le_generate_dhkey)) {
|
||||
status = BT_HCI_ERR_INVALID_PARAM;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
if (atomic_test_and_set_bit(flags, PENDING_DHKEY)) {
|
||||
status = BT_HCI_ERR_CMD_DISALLOWED;
|
||||
goto send_status;
|
||||
}
|
||||
|
||||
cmd = (void *)buf->data;
|
||||
/* Convert X and Y coordinates from little-endian HCI to
|
||||
* big-endian (expected by the crypto API).
|
||||
*/
|
||||
sys_memcpy_swap(ecc.public_key_be, cmd->key, 32);
|
||||
sys_memcpy_swap(&ecc.public_key_be[32], &cmd->key[32], 32);
|
||||
k_sem_give(&cmd_sem);
|
||||
status = BT_HCI_ERR_SUCCESS;
|
||||
status = le_gen_dhkey(cmd->key, BT_HCI_LE_KEY_TYPE_GENERATED);
|
||||
|
||||
send_status:
|
||||
net_buf_unref(buf);
|
||||
send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY, status);
|
||||
}
|
||||
|
||||
static void le_gen_dhkey_v2(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_cp_le_generate_dhkey_v2 *cmd;
|
||||
uint8_t status;
|
||||
|
||||
cmd = (void *)buf->data;
|
||||
status = le_gen_dhkey(cmd->key, cmd->key_type);
|
||||
|
||||
net_buf_unref(buf);
|
||||
send_cmd_status(BT_HCI_OP_LE_GENERATE_DHKEY_V2, status);
|
||||
}
|
||||
|
||||
static void le_p256_pub_key(struct net_buf *buf)
|
||||
{
|
||||
uint8_t status;
|
||||
|
@ -304,7 +312,11 @@ int bt_hci_ecc_send(struct net_buf *buf)
|
|||
return 0;
|
||||
case BT_HCI_OP_LE_GENERATE_DHKEY:
|
||||
net_buf_pull(buf, sizeof(*chdr));
|
||||
le_gen_dhkey(buf);
|
||||
le_gen_dhkey_v1(buf);
|
||||
return 0;
|
||||
case BT_HCI_OP_LE_GENERATE_DHKEY_V2:
|
||||
net_buf_pull(buf, sizeof(*chdr));
|
||||
le_gen_dhkey_v2(buf);
|
||||
return 0;
|
||||
case BT_HCI_OP_LE_SET_EVENT_MASK:
|
||||
clear_ecc_events(buf);
|
||||
|
@ -323,6 +335,8 @@ void bt_hci_ecc_supported_commands(uint8_t *supported_commands)
|
|||
supported_commands[34] |= BIT(1);
|
||||
/* LE Generate DH Key v1 */
|
||||
supported_commands[34] |= BIT(2);
|
||||
/* LE Generate DH Key v2 */
|
||||
supported_commands[41] |= BIT(2);
|
||||
}
|
||||
|
||||
int default_CSPRNG(uint8_t *dst, unsigned int len)
|
||||
|
|
|
@ -236,15 +236,6 @@ static const uint8_t gen_method_sc[5 /* remote */][5 /* local */] = {
|
|||
};
|
||||
#endif /* !CONFIG_BT_SMP_OOB_LEGACY_PAIR_ONLY */
|
||||
|
||||
static const uint8_t sc_debug_public_key[64] = {
|
||||
0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, 0xdb, 0xfd, 0xf4, 0xac,
|
||||
0x11, 0x91, 0xf4, 0xef, 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
|
||||
0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20, 0x8b, 0xd2, 0x89, 0x15,
|
||||
0xd0, 0x8e, 0x1c, 0x74, 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
|
||||
0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63, 0x6d, 0xeb, 0x2a, 0x65,
|
||||
0x49, 0x9c, 0x80, 0xdc
|
||||
};
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
/* SMP over BR/EDR channel specific context */
|
||||
struct bt_smp_br {
|
||||
|
@ -4159,7 +4150,7 @@ static uint8_t smp_public_key(struct bt_smp *smp, struct net_buf *buf)
|
|||
memcpy(&smp->pkey[32], req->y, 32);
|
||||
|
||||
/* mark key as debug if remote is using it */
|
||||
if (memcmp(smp->pkey, sc_debug_public_key, 64) == 0) {
|
||||
if (bt_pub_key_is_debug(smp->pkey)) {
|
||||
BT_INFO("Remote is using Debug Public key");
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_SC_DEBUG_KEY);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue