Bluetooth: Fix infinite recursion in host-based bt_rand

Fix infinite recursion in host-based bt_rand function. This would call
HCI LE Random Number command, which would in turn call bt_rand, causing
an infinite recursion.

bt_rand -> prng_reseed -> BT_HCI_OP_LE_RAND -> le_rand -> bt_rand

To solve this issue the controller should avoid doing calls into the
host, so all calls to bt_rand in the controller should be replaced with
a call to a controller function.

Fixes #22202

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
Joakim Andersson 2020-01-29 18:44:25 +01:00 committed by Carles Cufí
commit 291ebdd4e4
7 changed files with 36 additions and 29 deletions

View file

@ -4,33 +4,16 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <drivers/entropy.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER) #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_MODULE_NAME bt_ctlr_crypto #define LOG_MODULE_NAME bt_ctlr_crypto
#include "common/log.h" #include "common/log.h"
#include "../util/util.h"
#include "hal/ecb.h" #include "hal/ecb.h"
static struct device *entropy_driver;
int bt_rand(void *buf, size_t len) int bt_rand(void *buf, size_t len)
{ {
struct device *dev = entropy_driver; return util_rand(buf, len);
if (unlikely(!dev)) {
/* Only one entropy device exists, so this is safe even
* if the whole operation isn't atomic.
*/
dev = device_get_binding(CONFIG_ENTROPY_NAME);
__ASSERT((dev != NULL),
"Device driver for %s (CONFIG_ENTROPY_NAME) not found. "
"Check your build configuration!",
CONFIG_ENTROPY_NAME);
entropy_driver = dev;
}
return entropy_get_entropy(dev, (u8_t *)buf, len);
} }
int bt_encrypt_le(const u8_t key[16], const u8_t plaintext[16], int bt_encrypt_le(const u8_t key[16], const u8_t plaintext[16],

View file

@ -868,7 +868,7 @@ static void le_rand(struct net_buf *buf, struct net_buf **evt)
rp = hci_cmd_complete(evt, sizeof(*rp)); rp = hci_cmd_complete(evt, sizeof(*rp));
rp->status = 0x00; rp->status = 0x00;
bt_rand(rp->rand, count); util_rand(rp->rand, count);
} }
static void le_read_supp_states(struct net_buf *buf, struct net_buf **evt) static void le_read_supp_states(struct net_buf *buf, struct net_buf **evt)

View file

@ -6489,7 +6489,7 @@ again:
LL_ASSERT(retry); LL_ASSERT(retry);
retry--; retry--;
bt_rand(&access_addr, sizeof(u32_t)); util_rand(&access_addr, sizeof(u32_t));
bit_idx = 31U; bit_idx = 31U;
transitions = 0U; transitions = 0U;
@ -11992,7 +11992,7 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
conn->llcp_feature.features = LL_FEAT; conn->llcp_feature.features = LL_FEAT;
access_addr = access_addr_get(); access_addr = access_addr_get();
memcpy(&conn->access_addr[0], &access_addr, sizeof(conn->access_addr)); memcpy(&conn->access_addr[0], &access_addr, sizeof(conn->access_addr));
bt_rand(&conn->crc_init[0], 3); util_rand(&conn->crc_init[0], 3);
memcpy(&conn->data_chan_map[0], &_radio.data_chan_map[0], memcpy(&conn->data_chan_map[0], &_radio.data_chan_map[0],
sizeof(conn->data_chan_map)); sizeof(conn->data_chan_map));
conn->data_chan_count = _radio.data_chan_count; conn->data_chan_count = _radio.data_chan_count;
@ -12333,8 +12333,8 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
memcpy(enc_req->rand, rand, sizeof(enc_req->rand)); memcpy(enc_req->rand, rand, sizeof(enc_req->rand));
enc_req->ediv[0] = ediv[0]; enc_req->ediv[0] = ediv[0];
enc_req->ediv[1] = ediv[1]; enc_req->ediv[1] = ediv[1];
bt_rand(enc_req->skdm, sizeof(enc_req->skdm)); util_rand(enc_req->skdm, sizeof(enc_req->skdm));
bt_rand(enc_req->ivm, sizeof(enc_req->ivm)); util_rand(enc_req->ivm, sizeof(enc_req->ivm));
} else if (conn->enc_rx && conn->enc_tx) { } else if (conn->enc_rx && conn->enc_tx) {
memcpy(&conn->llcp_enc.rand[0], rand, memcpy(&conn->llcp_enc.rand[0], rand,
sizeof(conn->llcp_enc.rand)); sizeof(conn->llcp_enc.rand));

View file

@ -101,7 +101,7 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
access_addr_get(access_addr); access_addr_get(access_addr);
memcpy(conn_lll->access_addr, &access_addr, memcpy(conn_lll->access_addr, &access_addr,
sizeof(conn_lll->access_addr)); sizeof(conn_lll->access_addr));
bt_rand(&conn_lll->crc_init[0], 3); util_rand(&conn_lll->crc_init[0], 3);
conn_lll->handle = 0xFFFF; conn_lll->handle = 0xFFFF;
conn_lll->interval = interval; conn_lll->interval = interval;
@ -156,7 +156,7 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
conn_lll->data_chan_count = conn_lll->data_chan_count =
ull_conn_chan_map_cpy(conn_lll->data_chan_map); ull_conn_chan_map_cpy(conn_lll->data_chan_map);
bt_rand(&hop, sizeof(u8_t)); util_rand(&hop, sizeof(u8_t));
conn_lll->data_chan_hop = 5 + (hop % 12); conn_lll->data_chan_hop = 5 + (hop % 12);
conn_lll->data_chan_sel = 0; conn_lll->data_chan_sel = 0;
conn_lll->data_chan_use = 0; conn_lll->data_chan_use = 0;
@ -389,8 +389,8 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
memcpy(enc_req->rand, rand, sizeof(enc_req->rand)); memcpy(enc_req->rand, rand, sizeof(enc_req->rand));
enc_req->ediv[0] = ediv[0]; enc_req->ediv[0] = ediv[0];
enc_req->ediv[1] = ediv[1]; enc_req->ediv[1] = ediv[1];
bt_rand(enc_req->skdm, sizeof(enc_req->skdm)); util_rand(enc_req->skdm, sizeof(enc_req->skdm));
bt_rand(enc_req->ivm, sizeof(enc_req->ivm)); util_rand(enc_req->ivm, sizeof(enc_req->ivm));
} else if (conn->lll.enc_rx && conn->lll.enc_tx) { } else if (conn->lll.enc_rx && conn->lll.enc_tx) {
memcpy(&conn->llcp_enc.rand[0], rand, memcpy(&conn->llcp_enc.rand[0], rand,
sizeof(conn->llcp_enc.rand)); sizeof(conn->llcp_enc.rand));
@ -709,7 +709,7 @@ again:
LL_ASSERT(retry); LL_ASSERT(retry);
retry--; retry--;
bt_rand(access_addr, 4); util_rand(access_addr, 4);
aa = sys_get_le32(access_addr); aa = sys_get_le32(access_addr);
bit_idx = 31U; bit_idx = 31U;

View file

@ -6,6 +6,7 @@
*/ */
#include <zephyr/types.h> #include <zephyr/types.h>
#include <drivers/entropy.h>
#include "util.h" #include "util.h"
/** /**
@ -36,3 +37,21 @@ u8_t util_ones_count_get(u8_t *octets, u8_t octets_len)
return one_count; return one_count;
} }
int util_rand(void *buf, size_t len)
{
static struct device *dev;
if (unlikely(!dev)) {
/* Only one entropy device exists, so this is safe even
* if the whole operation isn't atomic.
*/
dev = device_get_binding(CONFIG_ENTROPY_NAME);
__ASSERT((dev != NULL),
"Device driver for %s (CONFIG_ENTROPY_NAME) not found. "
"Check your build configuration!",
CONFIG_ENTROPY_NAME);
}
return entropy_get_entropy(dev, (u8_t *)buf, len);
}

View file

@ -13,4 +13,8 @@
#define TRIPLE_BUFFER_SIZE 3 #define TRIPLE_BUFFER_SIZE 3
#endif #endif
#include <stddef.h>
u8_t util_ones_count_get(u8_t *octets, u8_t octets_len); u8_t util_ones_count_get(u8_t *octets, u8_t octets_len);
int util_rand(void *buf, size_t len);

View file

@ -14,6 +14,7 @@
#include <bluetooth/bluetooth.h> #include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h> #include <bluetooth/hci.h>
#include <bluetooth/conn.h> #include <bluetooth/conn.h>
#include <bluetooth/crypto.h>
#include <tinycrypt/constants.h> #include <tinycrypt/constants.h>
#include <tinycrypt/hmac_prng.h> #include <tinycrypt/hmac_prng.h>