Skip to content

Commit

Permalink
Bluetooth: Mesh: get rid of host dependency for dh key for mesh
Browse files Browse the repository at this point in the history
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
(zephyrproject-rtos#23292)

Signed-off-by: Aleksandr Khromykh <[email protected]>
  • Loading branch information
alxelax authored and carlescufi committed Apr 17, 2023
1 parent 3f08bd3 commit 77c72aa
Show file tree
Hide file tree
Showing 24 changed files with 51 additions and 207 deletions.
2 changes: 1 addition & 1 deletion subsys/bluetooth/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion subsys/bluetooth/mesh/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/adv_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include "net.h"
#include "foundation.h"
#include "beacon.h"
#include "host/ecc.h"
#include "prov.h"
#include "solicitation.h"

Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/beacon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/gatt_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

#include "test.h"
#include "adv.h"
#include "host/ecc.h"
#include "prov.h"
#include "provisioner.h"
#include "net.h"
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#include "foundation.h"
#include "beacon.h"
#include "settings.h"
#include "host/ecc.h"
#include "prov.h"
#include "cfg.h"

Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/pb_adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/pb_gatt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/pb_gatt_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 0 additions & 1 deletion subsys/bluetooth/mesh/pb_gatt_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
24 changes: 4 additions & 20 deletions subsys/bluetooth/mesh/prov.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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();
}
4 changes: 1 addition & 3 deletions subsys/bluetooth/mesh/prov.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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. */

Expand Down Expand Up @@ -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);

Expand Down
115 changes: 21 additions & 94 deletions subsys/bluetooth/mesh/prov_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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);
Expand Down Expand Up @@ -301,21 +291,16 @@ 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);
return;
}

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);
Expand All @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
Loading

0 comments on commit 77c72aa

Please sign in to comment.