Bluetooth: Mesh: get rid of host dependency for dh key for mesh

Commit gets rid of host dependency to generate DH key.
Mesh uses its own function for it that has synchronous
behavior and correct endianism. It simplifies the provisioning
state machine since it doesn't require waiting for the host HCI
handler.
Also, it removes hidden cross-dependency between BLE Mesh and
SMP in the aspect of competition for the same DH key
(https://github.com/zephyrproject-rtos/zephyr/issues/23292)

Signed-off-by: Aleksandr Khromykh <aleksandr.khromykh@nordicsemi.no>
This commit is contained in:
Aleksandr Khromykh 2023-03-29 13:11:40 +02:00 committed by Carles Cufí
commit 77c72aa67b
24 changed files with 56 additions and 212 deletions

View file

@ -885,7 +885,7 @@ endif # BT_HCI_HOST
config BT_ECC
bool "ECDH key generation support"
default y if BT_MESH_PROV || (BT_SMP && !BT_SMP_OOB_LEGACY_PAIR_ONLY)
default y if BT_SMP && !BT_SMP_OOB_LEGACY_PAIR_ONLY
help
This option adds support for ECDH HCI commands.

View file

@ -8,6 +8,7 @@ menuconfig BT_MESH
select TINYCRYPT
select TINYCRYPT_AES
select TINYCRYPT_AES_CMAC
select TINYCRYPT_ECC_DH
select BT_HOST_CCM
depends on BT_OBSERVER && BT_BROADCASTER
help
@ -30,7 +31,6 @@ config BT_MESH_PROV_DEVICE
config BT_MESH_PROV_OOB_PUBLIC_KEY
bool "OOB Public key support"
select TINYCRYPT_ECC_DH
depends on BT_MESH_PROV_DEVICE
help
Enable this option if public key is to be exchanged via Out of Band (OOB) technology.

View file

@ -21,7 +21,6 @@
#include "net.h"
#include "foundation.h"
#include "beacon.h"
#include "host/ecc.h"
#include "prov.h"
#include "proxy.h"
#include "pb_gatt_srv.h"

View file

@ -23,7 +23,6 @@
#include "net.h"
#include "foundation.h"
#include "beacon.h"
#include "host/ecc.h"
#include "prov.h"
#include "solicitation.h"

View file

@ -19,7 +19,6 @@
#include "adv.h"
#include "mesh.h"
#include "net.h"
#include "host/ecc.h"
#include "prov.h"
#include "crypto.h"
#include "beacon.h"

View file

@ -22,7 +22,6 @@
#include "net.h"
#include "rpl.h"
#include "transport.h"
#include "host/ecc.h"
#include "prov.h"
#include "beacon.h"
#include "foundation.h"

View file

@ -19,7 +19,6 @@
#include "test.h"
#include "adv.h"
#include "host/ecc.h"
#include "prov.h"
#include "provisioner.h"
#include "net.h"

View file

@ -33,7 +33,6 @@
#include "foundation.h"
#include "beacon.h"
#include "settings.h"
#include "host/ecc.h"
#include "prov.h"
#include "cfg.h"

View file

@ -14,7 +14,6 @@
#include "adv.h"
#include "crypto.h"
#include "beacon.h"
#include "host/ecc.h"
#include "prov.h"
#include "common/bt_str.h"

View file

@ -9,7 +9,6 @@
#include "net.h"
#include "proxy.h"
#include "adv.h"
#include "host/ecc.h"
#include "prov.h"
#include "pb_gatt.h"
#include "proxy_msg.h"

View file

@ -20,7 +20,6 @@
#include "net.h"
#include "rpl.h"
#include "transport.h"
#include "host/ecc.h"
#include "prov.h"
#include "pb_gatt.h"
#include "beacon.h"

View file

@ -21,7 +21,6 @@
#include "net.h"
#include "rpl.h"
#include "transport.h"
#include "host/ecc.h"
#include "prov.h"
#include "pb_gatt.h"
#include "beacon.h"

View file

@ -17,9 +17,6 @@
#include <zephyr/bluetooth/mesh.h>
#include <zephyr/bluetooth/uuid.h>
#include "host/ecc.h"
#include "host/testing.h"
#include "crypto.h"
#include "mesh.h"
#include "net.h"
@ -38,29 +35,16 @@ const struct bt_mesh_prov *bt_mesh_prov;
BUILD_ASSERT(sizeof(bt_mesh_prov_link.conf_inputs) == 145,
"Confirmation inputs shall be 145 bytes");
static void pub_key_ready(const uint8_t *pkey)
{
if (!pkey) {
LOG_WRN("Public key not available");
return;
}
LOG_DBG("Local public key ready");
}
int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[BT_PUB_KEY_LEN]))
int bt_mesh_prov_reset_state(void)
{
int err;
static struct bt_pub_key_cb pub_key_cb;
const size_t offset = offsetof(struct bt_mesh_prov_link, auth);
pub_key_cb.func = func ? func : pub_key_ready;
atomic_clear(bt_mesh_prov_link.flags);
(void)memset((uint8_t *)&bt_mesh_prov_link + offset, 0,
sizeof(bt_mesh_prov_link) - offset);
err = bt_pub_key_gen(&pub_key_cb);
err = bt_mesh_pub_key_gen();
if (err) {
LOG_ERR("Failed to generate public key (%d)", err);
return err;
@ -450,7 +434,7 @@ void bt_mesh_prov_reset(void)
bt_mesh_pb_gatt_reset();
}
bt_mesh_prov_reset_state(NULL);
bt_mesh_prov_reset_state();
if (bt_mesh_prov->reset) {
bt_mesh_prov->reset();
@ -474,5 +458,5 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info)
bt_mesh_pb_gatt_init();
}
return bt_mesh_prov_reset_state(NULL);
return bt_mesh_prov_reset_state();
}

View file

@ -85,7 +85,6 @@
#endif
enum {
WAIT_PUB_KEY, /* Waiting for local PubKey to be generated */
LINK_ACTIVE, /* Link has been opened */
WAIT_NUMBER, /* Waiting for number input from user */
WAIT_STRING, /* Waiting for string input from user */
@ -98,7 +97,6 @@ enum {
WAIT_CONFIRM, /* Wait for send confirm */
WAIT_AUTH, /* Wait for auth response */
OOB_STATIC_KEY, /* OOB Static Authentication */
WAIT_DH_KEY, /* Wait for DH Key */
REPROVISION, /* The link was opened as a reprovision target */
COMPLETE, /* The provisioning process completed. */
@ -172,7 +170,7 @@ static inline uint8_t bt_mesh_prov_auth_size_get(void)
return bt_mesh_prov_link.algorithm == BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM ? 16 : 32;
}
int bt_mesh_prov_reset_state(void (*func)(const uint8_t key[PUB_KEY_SIZE]));
int bt_mesh_prov_reset_state(void);
bool bt_mesh_prov_active(void);

View file

@ -19,9 +19,6 @@
#include "common/bt_str.h"
#include "host/ecc.h"
#include "host/testing.h"
#include "crypto.h"
#include "adv.h"
#include "mesh.h"
@ -40,15 +37,8 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_mesh_prov_device);
static void send_pub_key(void);
static void pub_key_ready(const uint8_t *pkey);
static void reprovision_fail(void);
static int reset_state(void)
{
return bt_mesh_prov_reset_state(pub_key_ready);
}
static void prov_send_fail_msg(uint8_t err)
{
PROV_BUF(buf, PDU_LEN_FAILED);
@ -301,7 +291,7 @@ static void send_pub_key(void)
PROV_BUF(buf, PDU_LEN_PUB_KEY);
const uint8_t *key;
key = bt_pub_key_get();
key = bt_mesh_pub_key_get();
if (!key) {
LOG_ERR("No public key available");
prov_fail(PROV_ERR_UNEXP_ERR);
@ -309,13 +299,8 @@ static void send_pub_key(void)
}
bt_mesh_prov_buf_init(&buf, PROV_PUB_KEY);
/* Swap X and Y halves independently to big-endian */
sys_memcpy_swap(net_buf_simple_add(&buf, BT_PUB_KEY_COORD_LEN), key, BT_PUB_KEY_COORD_LEN);
sys_memcpy_swap(net_buf_simple_add(&buf, BT_PUB_KEY_COORD_LEN), &key[BT_PUB_KEY_COORD_LEN],
BT_PUB_KEY_COORD_LEN);
LOG_DBG("Local Public Key: %s", bt_hex(buf.data + 1, BT_PUB_KEY_LEN));
net_buf_simple_add_mem(&buf, key, PUB_KEY_SIZE);
LOG_DBG("Local Public Key: %s", bt_hex(buf.data + 1, PUB_KEY_SIZE));
/* PublicKeyDevice */
memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, &buf.data[1], PDU_LEN_PUB_KEY);
@ -328,70 +313,38 @@ static void send_pub_key(void)
start_auth();
}
static void dh_key_gen_complete(void)
{
LOG_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, BT_DH_KEY_LEN));
if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY) &&
atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) {
send_confirm();
} else if (!atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) {
send_pub_key();
}
}
static void prov_dh_key_cb(const uint8_t dhkey[BT_DH_KEY_LEN])
{
LOG_DBG("%p", dhkey);
if (!dhkey) {
LOG_ERR("DHKey generation failed");
prov_fail(PROV_ERR_UNEXP_ERR);
return;
}
sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, BT_DH_KEY_LEN);
dh_key_gen_complete();
}
static void prov_dh_key_gen(void)
{
const uint8_t *remote_pk;
uint8_t remote_pk_le[BT_PUB_KEY_LEN];
const uint8_t *remote_pub_key;
const uint8_t *remote_priv_key;
remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner;
remote_pub_key = bt_mesh_prov_link.conf_inputs.pub_key_provisioner;
if (IS_ENABLED(CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY) &&
atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) {
remote_priv_key = bt_mesh_prov->private_key_be;
} else {
remote_priv_key = NULL;
}
if (bt_mesh_dhkey_gen(remote_pk, bt_mesh_prov->private_key_be,
bt_mesh_prov_link.dhkey)) {
prov_fail(PROV_ERR_UNEXP_ERR);
return;
}
dh_key_gen_complete();
if (bt_mesh_dhkey_gen(remote_pub_key, remote_priv_key, bt_mesh_prov_link.dhkey)) {
LOG_ERR("Failed to generate DHKey");
prov_fail(PROV_ERR_UNEXP_ERR);
return;
}
/* Copy remote key in little-endian for bt_dh_key_gen().
* X and Y halves are swapped independently. The bt_dh_key_gen()
* will also take care of validating the remote public key.
*/
sys_memcpy_swap(remote_pk_le, remote_pk, BT_PUB_KEY_COORD_LEN);
sys_memcpy_swap(&remote_pk_le[BT_PUB_KEY_COORD_LEN], &remote_pk[BT_PUB_KEY_COORD_LEN],
BT_PUB_KEY_COORD_LEN);
LOG_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, DH_KEY_SIZE));
if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
LOG_ERR("Failed to generate DHKey");
prov_fail(PROV_ERR_UNEXP_ERR);
if (atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) {
start_auth();
} else {
send_pub_key();
}
}
static void prov_pub_key(const uint8_t *data)
{
LOG_DBG("Remote Public Key: %s", bt_hex(data, BT_PUB_KEY_LEN));
LOG_DBG("Remote Public Key: %s", bt_hex(data, PUB_KEY_SIZE));
/* PublicKeyProvisioner */
memcpy(bt_mesh_prov_link.conf_inputs.pub_key_provisioner, data, PDU_LEN_PUB_KEY);
@ -407,35 +360,11 @@ static void prov_pub_key(const uint8_t *data)
/* No swap needed since user provides public key in big-endian */
memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, bt_mesh_prov->public_key_be,
PDU_LEN_PUB_KEY);
atomic_set_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY);
start_auth();
} else if (!bt_pub_key_get()) {
/* Clear retransmit timer */
bt_mesh_prov_link.bearer->clear_tx();
atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
LOG_WRN("Waiting for local public key");
return;
}
prov_dh_key_gen();
}
static void pub_key_ready(const uint8_t *pkey)
{
if (!pkey) {
LOG_WRN("Public key not available");
return;
}
LOG_DBG("Local public key ready");
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
prov_dh_key_gen();
}
}
static void notify_input_complete(void)
{
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
@ -508,9 +437,7 @@ static void prov_confirm(const uint8_t *data)
memcpy(bt_mesh_prov_link.conf, data, conf_size);
notify_input_complete();
if (!atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_DH_KEY)) {
send_confirm();
}
send_confirm();
}
static inline bool is_pb_gatt(void)
@ -703,7 +630,7 @@ static void prov_link_closed(enum prov_bearer_link_status status)
bt_mesh_attention(NULL, 0);
}
reset_state();
bt_mesh_prov_reset_state();
}
static void prov_link_opened(void)

View file

@ -20,9 +20,6 @@
#include "common/bt_str.h"
#include "host/ecc.h"
#include "host/testing.h"
#include "crypto.h"
#include "adv.h"
#include "mesh.h"
@ -54,7 +51,6 @@ static struct {
static void send_pub_key(void);
static void prov_dh_key_gen(void);
static void pub_key_ready(const uint8_t *pkey);
static int reset_state(void)
{
@ -63,7 +59,7 @@ static int reset_state(void)
bt_mesh_cdb_node_del(prov_device.node, false);
}
return bt_mesh_prov_reset_state(pub_key_ready);
return bt_mesh_prov_reset_state();
}
static void prov_link_close(enum prov_bearer_link_status status)
@ -106,12 +102,7 @@ static void send_invite(void)
static void start_sent(int err, void *cb_data)
{
if (!bt_pub_key_get()) {
atomic_set_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY);
LOG_WRN("Waiting for local public key");
} else {
send_pub_key();
}
send_pub_key();
}
static void send_start(void)
@ -403,7 +394,7 @@ static void send_pub_key(void)
PROV_BUF(buf, PDU_LEN_PUB_KEY);
const uint8_t *key;
key = bt_pub_key_get();
key = bt_mesh_pub_key_get();
if (!key) {
LOG_ERR("No public key available");
prov_fail(PROV_ERR_UNEXP_ERR);
@ -411,13 +402,8 @@ static void send_pub_key(void)
}
bt_mesh_prov_buf_init(&buf, PROV_PUB_KEY);
/* Swap X and Y halves independently to big-endian */
sys_memcpy_swap(net_buf_simple_add(&buf, BT_PUB_KEY_COORD_LEN), key, BT_PUB_KEY_COORD_LEN);
sys_memcpy_swap(net_buf_simple_add(&buf, BT_PUB_KEY_COORD_LEN), &key[BT_PUB_KEY_COORD_LEN],
BT_PUB_KEY_COORD_LEN);
LOG_DBG("Local Public Key: %s", bt_hex(buf.data + 1, BT_PUB_KEY_LEN));
net_buf_simple_add_mem(&buf, key, PUB_KEY_SIZE);
LOG_DBG("Local Public Key: %s", bt_hex(buf.data + 1, PUB_KEY_SIZE));
/* PublicKeyProvisioner */
memcpy(bt_mesh_prov_link.conf_inputs.pub_key_provisioner, &buf.data[1], PDU_LEN_PUB_KEY);
@ -430,19 +416,30 @@ static void send_pub_key(void)
bt_mesh_prov_link.expect = PROV_PUB_KEY;
}
static void prov_dh_key_cb(const uint8_t dhkey[BT_DH_KEY_LEN])
static void prov_dh_key_gen(void)
{
LOG_DBG("%p", dhkey);
const uint8_t *remote_pk;
const uint8_t *local_pk;
if (!dhkey) {
LOG_ERR("DHKey generation failed");
prov_fail(PROV_ERR_UNEXP_ERR);
local_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner;
remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_device;
if (!memcmp(local_pk, remote_pk, PUB_KEY_SIZE)) {
LOG_ERR("Public keys are identical");
prov_fail(PROV_ERR_NVAL_FMT);
return;
}
sys_memcpy_swap(bt_mesh_prov_link.dhkey, dhkey, BT_DH_KEY_LEN);
if (bt_mesh_dhkey_gen(remote_pk, NULL, bt_mesh_prov_link.dhkey)) {
LOG_ERR("Failed to generate DHKey");
prov_fail(PROV_ERR_UNEXP_ERR);
}
LOG_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, BT_DH_KEY_LEN));
LOG_DBG("DHkey: %s", bt_hex(bt_mesh_prov_link.dhkey, DH_KEY_SIZE));
if (atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
bt_mesh_prov_link.expect = PROV_INPUT_COMPLETE;
}
if (atomic_test_bit(bt_mesh_prov_link.flags, WAIT_STRING) ||
atomic_test_bit(bt_mesh_prov_link.flags, WAIT_NUMBER) ||
@ -454,66 +451,19 @@ static void prov_dh_key_cb(const uint8_t dhkey[BT_DH_KEY_LEN])
send_confirm();
}
static void prov_dh_key_gen(void)
{
uint8_t remote_pk_le[BT_PUB_KEY_LEN];
const uint8_t *remote_pk;
const uint8_t *local_pk;
local_pk = bt_mesh_prov_link.conf_inputs.pub_key_provisioner;
remote_pk = bt_mesh_prov_link.conf_inputs.pub_key_device;
/* Copy remote key in little-endian for bt_dh_key_gen().
* X and Y halves are swapped independently. The bt_dh_key_gen()
* will also take care of validating the remote public key.
*/
sys_memcpy_swap(remote_pk_le, remote_pk, BT_PUB_KEY_COORD_LEN);
sys_memcpy_swap(&remote_pk_le[BT_PUB_KEY_COORD_LEN], &remote_pk[BT_PUB_KEY_COORD_LEN],
BT_PUB_KEY_COORD_LEN);
if (!memcmp(local_pk, remote_pk, BT_PUB_KEY_LEN)) {
LOG_ERR("Public keys are identical");
prov_fail(PROV_ERR_NVAL_FMT);
return;
}
if (bt_dh_key_gen(remote_pk_le, prov_dh_key_cb)) {
LOG_ERR("Failed to generate DHKey");
prov_fail(PROV_ERR_UNEXP_ERR);
}
if (atomic_test_bit(bt_mesh_prov_link.flags, NOTIFY_INPUT_COMPLETE)) {
bt_mesh_prov_link.expect = PROV_INPUT_COMPLETE;
}
}
static void prov_pub_key(const uint8_t *data)
{
LOG_DBG("Remote Public Key: %s", bt_hex(data, BT_PUB_KEY_LEN));
LOG_DBG("Remote Public Key: %s", bt_hex(data, PUB_KEY_SIZE));
atomic_set_bit(bt_mesh_prov_link.flags, REMOTE_PUB_KEY);
/* PublicKeyDevice */
memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, data, BT_PUB_KEY_LEN);
memcpy(bt_mesh_prov_link.conf_inputs.pub_key_device, data, PUB_KEY_SIZE);
bt_mesh_prov_link.bearer->clear_tx();
prov_dh_key_gen();
}
static void pub_key_ready(const uint8_t *pkey)
{
if (!pkey) {
LOG_WRN("Public key not available");
return;
}
LOG_DBG("Local public key ready");
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags, WAIT_PUB_KEY)) {
send_pub_key();
}
}
static void notify_input_complete(void)
{
if (atomic_test_and_clear_bit(bt_mesh_prov_link.flags,
@ -811,7 +761,7 @@ int bt_mesh_auth_method_set_none(void)
return 0;
}
int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[BT_PUB_KEY_LEN])
int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[PUB_KEY_SIZE])
{
if (public_key == NULL) {
return -EINVAL;

View file

@ -20,7 +20,6 @@
#include "net.h"
#include "rpl.h"
#include "transport.h"
#include "host/ecc.h"
#include "prov.h"
#include "beacon.h"
#include "foundation.h"

View file

@ -25,7 +25,6 @@
#include "net.h"
#include "rpl.h"
#include "transport.h"
#include "host/ecc.h"
#include "prov.h"
#include "beacon.h"
#include "foundation.h"

View file

@ -24,7 +24,6 @@
#include "net.h"
#include "rpl.h"
#include "transport.h"
#include "host/ecc.h"
#include "prov.h"
#include "beacon.h"
#include "foundation.h"

View file

@ -7,7 +7,6 @@
#include <zephyr/bluetooth/mesh.h>
#include <zephyr/bluetooth/conn.h>
#include <common/bt_str.h>
#include "host/ecc.h"
#include "access.h"
#include "prov.h"
#include "rpr.h"

View file

@ -14,7 +14,6 @@
#include <zephyr/bluetooth/mesh/sar_cfg.h>
#include "access.h"
#include "adv.h"
#include "host/ecc.h"
#include "prov.h"
#include "crypto.h"
#include "rpr.h"

View file

@ -34,7 +34,6 @@
#include "beacon.h"
#include "rpl.h"
#include "settings.h"
#include "host/ecc.h"
#include "prov.h"
#define LOG_LEVEL CONFIG_BT_MESH_KEYS_LOG_LEVEL

View file

@ -2,3 +2,4 @@ CONFIG_BT_EXT_ADV=n
CONFIG_BT_CTLR_ADVANCED_FEATURES=y
CONFIG_BT_CTLR_LOW_LAT=y
CONFIG_BT_TICKER_LOW_LAT=y
CONFIG_BT_MESH_FRIEND_ADV_LATENCY=2

View file

@ -52,7 +52,7 @@ void common_sar_conf(uint16_t addr)
*/
struct bt_mesh_sar_tx tx_set = {
.seg_int_step = 1,
.unicast_retrans_count = 2,
.unicast_retrans_count = 3,
.unicast_retrans_without_prog_count = 2,
.unicast_retrans_int_step = 7,
.unicast_retrans_int_inc = 1,