Bluetooth: host: Introduce a new bt_hci_le_rand() call

In order to get rid of the duplication of the code that we had until now
in the tree, consolidate the handling of multiple calls to
bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, ...) in a single location,
namely in hci_core.

This allows all of the users of this HCI command to use a single
implementation of the iterated sending of the HCI command to fill a
buffer with random bytes.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
Carles Cufi 2022-03-31 18:52:47 +02:00 committed by Carles Cufí
commit 00636682ca
4 changed files with 56 additions and 82 deletions

View file

@ -20,31 +20,11 @@ static int entropy_bt_init(const struct device *dev)
static int entropy_bt_get_entropy(const struct device *dev,
uint8_t *buffer, uint16_t length)
{
struct bt_hci_rp_le_rand *rp;
struct net_buf *rsp;
int req, ret;
if (!bt_is_ready()) {
return -EAGAIN;
}
while (length > 0) {
/* Number of bytes to fill on this iteration */
req = MIN(length, sizeof(rp->rand));
/* Request the next 8 bytes over HCI */
ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
if (ret) {
return ret;
}
/* Copy random data into buffer */
rp = (void *)rsp->data;
memcpy(buffer, rp->rand, req);
net_buf_unref(rsp);
buffer += req;
length -= req;
}
return 0;
return bt_hci_le_rand(buffer, length);
}
/* HCI commands cannot be run from an interrupt context */

View file

@ -2873,6 +2873,22 @@ typedef bool bt_hci_vnd_evt_cb_t(struct net_buf_simple *buf);
*/
int bt_hci_register_vnd_evt_cb(bt_hci_vnd_evt_cb_t cb);
/** @brief Get Random bytes from the LE Controller.
*
* Send the HCI_LE_Rand to the LE Controller as many times as required to
* fill the provided @p buffer.
*
* @note This function is provided as a helper to gather an arbitrary number of
* random bytes from an LE Controller using the HCI_LE_Rand command.
*
* @param buffer Buffer to fill with random bytes.
* @param len Length of the buffer in bytes.
*
* @return 0 on success or negative error value on failure.
*/
int bt_hci_le_rand(void *buffer, size_t len);
#ifdef __cplusplus
}
#endif

View file

@ -33,22 +33,11 @@ static int prng_reseed(struct tc_hmac_prng_struct *h)
{
uint8_t seed[32];
int64_t extra;
size_t i;
int ret;
for (i = 0; i < (sizeof(seed) / 8); i++) {
struct bt_hci_rp_le_rand *rp;
struct net_buf *rsp;
ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
if (ret) {
return ret;
}
rp = (void *)rsp->data;
memcpy(&seed[i * 8], rp->rand, 8);
net_buf_unref(rsp);
ret = bt_hci_le_rand(seed, sizeof(seed));
if (ret) {
return ret;
}
extra = k_uptime_get();
@ -65,26 +54,15 @@ static int prng_reseed(struct tc_hmac_prng_struct *h)
int prng_init(void)
{
struct bt_hci_rp_le_rand *rp;
struct net_buf *rsp;
uint8_t perso[8];
int ret;
/* Check first that HCI_LE_Rand is supported */
if (!BT_CMD_TEST(bt_dev.supported_commands, 27, 7)) {
return -ENOTSUP;
}
ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
ret = bt_hci_le_rand(perso, sizeof(perso));
if (ret) {
return ret;
}
rp = (void *)rsp->data;
ret = tc_hmac_prng_init(&prng, rp->rand, sizeof(rp->rand));
net_buf_unref(rsp);
ret = tc_hmac_prng_init(&prng, perso, sizeof(perso));
if (ret == TC_CRYPTO_FAIL) {
BT_ERR("Failed to initialize PRNG");
return -EIO;
@ -118,39 +96,7 @@ int bt_rand(void *buf, size_t len)
#else /* !CONFIG_BT_HOST_CRYPTO_PRNG */
int bt_rand(void *buf, size_t len)
{
int ret, size;
size_t i = 0;
/* Check first that HCI_LE_Rand is supported */
if (!BT_CMD_TEST(bt_dev.supported_commands, 27, 7)) {
return -ENOTSUP;
}
while (len) {
struct bt_hci_rp_le_rand *rp;
struct net_buf *rsp;
ret = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
if (ret) {
return ret;
}
rp = (void *)rsp->data;
if (rp->status) {
return -EIO;
}
size = MIN(len, sizeof(rp->rand));
(void)memcpy((uint8_t *)buf + i, rp->rand, size);
net_buf_unref(rsp);
i += size;
len -= size;
}
return 0;
return bt_hci_le_rand(buf, len);
}
#endif /* CONFIG_BT_HOST_CRYPTO_PRNG */

View file

@ -331,6 +331,38 @@ int bt_hci_cmd_send_sync(uint16_t opcode, struct net_buf *buf,
return 0;
}
int bt_hci_le_rand(void *buffer, size_t len)
{
struct bt_hci_rp_le_rand *rp;
struct net_buf *rsp;
size_t count;
int err;
/* Check first that HCI_LE_Rand is supported */
if (!BT_CMD_TEST(bt_dev.supported_commands, 27, 7)) {
return -ENOTSUP;
}
while (len > 0) {
/* Number of bytes to fill on this iteration */
count = MIN(len, sizeof(rp->rand));
/* Request the next 8 bytes over HCI */
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_RAND, NULL, &rsp);
if (err) {
return err;
}
/* Copy random data into buffer */
rp = (void *)rsp->data;
memcpy(buffer, rp->rand, count);
net_buf_unref(rsp);
buffer = (uint8_t *)buffer + count;
len -= count;
}
return 0;
}
static int hci_le_read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time)
{
struct bt_hci_rp_le_read_max_data_len *rp;