From 83b50f6bee763917da3ce4eae1be7417d98af8c7 Mon Sep 17 00:00:00 2001 From: Mariusz Skamra Date: Fri, 19 Jul 2019 15:14:11 +0200 Subject: [PATCH] Bluetooth: Mesh: Fix rejecting invalid remote public key The code was already rejecting the key, however that rejection happened only after we had already sent our public key as response, which got interpreted as acceptance by the tester (PTS). This fixes issue that d4fd267086a56c270a793114e7575afae9a9befa supposed to fix. The problem is bt_dh_key_gen is async. Local public key cannot be sent from the same context the bt_dh_key_gen is called because we don't know yet if remote key is valid. Fixes MESH/NODE/PROV/BI-13-C. Signed-off-by: Mariusz Skamra --- subsys/bluetooth/mesh/prov.c | 84 +++++++++++++++--------------------- 1 file changed, 35 insertions(+), 49 deletions(-) diff --git a/subsys/bluetooth/mesh/prov.c b/subsys/bluetooth/mesh/prov.c index 1816a17d6ea..a72a72e5c53 100644 --- a/subsys/bluetooth/mesh/prov.c +++ b/subsys/bluetooth/mesh/prov.c @@ -108,7 +108,6 @@ enum { REMOTE_PUB_KEY, /* Remote key has been received */ LINK_ACTIVE, /* Link has been opened */ - HAVE_DHKEY, /* DHKey has been calculated */ SEND_CONFIRM, /* Waiting to send Confirm value */ WAIT_NUMBER, /* Waiting for number input from user */ WAIT_STRING, /* Waiting for string input from user */ @@ -838,10 +837,6 @@ int bt_mesh_input_number(u32_t num) send_input_complete(); - if (!atomic_test_bit(link.flags, HAVE_DHKEY)) { - return 0; - } - if (atomic_test_and_clear_bit(link.flags, SEND_CONFIRM)) { send_confirm(); } @@ -861,10 +856,6 @@ int bt_mesh_input_string(const char *str) send_input_complete(); - if (!atomic_test_bit(link.flags, HAVE_DHKEY)) { - return 0; - } - if (atomic_test_and_clear_bit(link.flags, SEND_CONFIRM)) { send_confirm(); } @@ -872,37 +863,23 @@ int bt_mesh_input_string(const char *str) return 0; } -static void prov_dh_key_cb(const u8_t key[32]) +static void send_pub_key(const u8_t dhkey[32]) { - BT_DBG("%p", key); + PROV_BUF(buf, 65); + const u8_t *key; - if (!key) { + BT_DBG("%p", dhkey); + + if (!dhkey) { BT_ERR("DHKey generation failed"); prov_send_fail_msg(PROV_ERR_UNEXP_ERR); return; } - sys_memcpy_swap(link.dhkey, key, 32); + sys_memcpy_swap(link.dhkey, dhkey, 32); BT_DBG("DHkey: %s", bt_hex(link.dhkey, 32)); - atomic_set_bit(link.flags, HAVE_DHKEY); - - if (atomic_test_bit(link.flags, WAIT_NUMBER) || - atomic_test_bit(link.flags, WAIT_STRING)) { - return; - } - - if (atomic_test_and_clear_bit(link.flags, SEND_CONFIRM)) { - send_confirm(); - } -} - -static void send_pub_key(void) -{ - PROV_BUF(buf, 65); - const u8_t *key; - key = bt_pub_key_get(); if (!key) { BT_ERR("No public key available"); @@ -912,20 +889,6 @@ static void send_pub_key(void) BT_DBG("Local Public Key: %s", bt_hex(key, 64)); - /* Copy remote key in little-endian for bt_dh_key_gen(). - * X and Y halves are swapped independently. Use response - * buffer as a temporary storage location. The bt_dh_key_gen() - * will also take care of validating the remote public key. - */ - sys_memcpy_swap(buf.data, &link.conf_inputs[17], 32); - sys_memcpy_swap(&buf.data[32], &link.conf_inputs[49], 32); - - if (bt_dh_key_gen(buf.data, prov_dh_key_cb)) { - BT_ERR("Failed to generate DHKey"); - prov_send_fail_msg(PROV_ERR_UNEXP_ERR); - return; - } - prov_buf_init(&buf, PROV_PUB_KEY); /* Swap X and Y halves independently to big-endian */ @@ -939,9 +902,28 @@ static void send_pub_key(void) return; } + atomic_set_bit(link.flags, SEND_CONFIRM); link.expect = PROV_CONFIRM; } +static void prov_dh_key_gen(void) +{ + u8_t remote_pk[64]; + + /* Copy remote key in little-endian for bt_dh_key_gen(). + * X and Y halves are swapped independently. Use response + * buffer as a temporary storage location. The bt_dh_key_gen() + * will also take care of validating the remote public key. + */ + sys_memcpy_swap(remote_pk, &link.conf_inputs[17], 32); + sys_memcpy_swap(&remote_pk[32], &link.conf_inputs[49], 32); + + if (bt_dh_key_gen(remote_pk, send_pub_key)) { + BT_ERR("Failed to generate DHKey"); + prov_send_fail_msg(PROV_ERR_UNEXP_ERR); + } +} + static void prov_pub_key(const u8_t *data) { BT_DBG("Remote Public Key: %s", bt_hex(data, 64)); @@ -958,7 +940,7 @@ static void prov_pub_key(const u8_t *data) return; } - send_pub_key(); + prov_dh_key_gen(); } static void pub_key_ready(const u8_t *pkey) @@ -971,7 +953,7 @@ static void pub_key_ready(const u8_t *pkey) BT_DBG("Local public key ready"); if (atomic_test_and_clear_bit(link.flags, REMOTE_PUB_KEY)) { - send_pub_key(); + prov_dh_key_gen(); } } @@ -986,12 +968,16 @@ static void prov_confirm(const u8_t *data) memcpy(link.conf, data, 16); - if (!atomic_test_bit(link.flags, HAVE_DHKEY)) { + if (atomic_test_bit(link.flags, WAIT_NUMBER) || + atomic_test_bit(link.flags, WAIT_STRING)) { + /* Clear retransmit timer */ #if defined(CONFIG_BT_MESH_PB_ADV) prov_clear_tx(); #endif - atomic_set_bit(link.flags, SEND_CONFIRM); - } else { + return; + } + + if (atomic_test_and_clear_bit(link.flags, SEND_CONFIRM)) { send_confirm(); } }