diff --git a/subsys/bluetooth/controller/hal/nrf5/rand.c b/subsys/bluetooth/controller/hal/nrf5/rand.c index 3795934a5c9..f573da0dc0d 100644 --- a/subsys/bluetooth/controller/hal/nrf5/rand.c +++ b/subsys/bluetooth/controller/hal/nrf5/rand.c @@ -12,36 +12,55 @@ #include "common/log.h" #include "hal/debug.h" -#define RAND_RESERVED (4) - struct rand { u8_t count; + u8_t threshold; u8_t first; u8_t last; u8_t rand[1]; }; -static struct rand *rng; +static struct rand *rng_isr; +static struct rand *rng_thr; -void rand_init(u8_t *context, u8_t context_len) +static void init(struct rand **rng, u8_t *context, u8_t len, u8_t threshold) { - LL_ASSERT(context_len > sizeof(struct rand)); + struct rand *p; - rng = (struct rand *)context; - rng->count = context_len - sizeof(struct rand) + 1; - rng->first = rng->last = 0; + LL_ASSERT(len > (offsetof(struct rand, rand) + threshold)); - NRF_RNG->CONFIG = RNG_CONFIG_DERCEN_Msk; - NRF_RNG->EVENTS_VALRDY = 0; - NRF_RNG->INTENSET = RNG_INTENSET_VALRDY_Msk; + *rng = (struct rand *)context; - NRF_RNG->TASKS_START = 1; + p = *rng; + p->count = len - offsetof(struct rand, rand); + p->threshold = threshold; + p->first = p->last = 0; + + if (!rng_isr || !rng_thr) { + NRF_RNG->CONFIG = RNG_CONFIG_DERCEN_Msk; + NRF_RNG->EVENTS_VALRDY = 0; + NRF_RNG->INTENSET = RNG_INTENSET_VALRDY_Msk; + + NRF_RNG->TASKS_START = 1; + } } -size_t rand_get(size_t octets, u8_t *rand) +void rand_init(u8_t *context, u8_t context_len, u8_t threshold) +{ + init(&rng_thr, context, context_len, threshold); +} + +void rand_isr_init(u8_t *context, u8_t context_len, u8_t threshold) +{ + init(&rng_isr, context, context_len, threshold); +} + +static size_t get(struct rand *rng, size_t octets, u8_t *rand) { - u8_t reserved; u8_t first; + u8_t avail; + + LL_ASSERT(rng); while (octets) { if (rng->first == rng->last) { @@ -57,59 +76,83 @@ size_t rand_get(size_t octets, u8_t *rand) rng->first = first; } - reserved = RAND_RESERVED; - first = rng->first; - while (reserved--) { - if (first == rng->last) { - NRF_RNG->TASKS_START = 1; + if (rng->first <= rng->last) { + avail = rng->last - rng->first; + } else { + avail = rng->count - rng->first + rng->last; + } - break; - } - - first++; - if (first == rng->count) { - first = 0; - } + if (avail < rng->threshold) { + NRF_RNG->TASKS_START = 1; } return octets; } +size_t rand_get(size_t octets, u8_t *rand) +{ + return get(rng_thr, octets, rand); +} + +size_t rand_isr_get(size_t octets, u8_t *rand) +{ + return get(rng_isr, octets, rand); +} + +static int isr(struct rand *rng, bool store) +{ + u8_t last; + + if (!rng) { + return -ENOBUFS; + } + + last = rng->last + 1; + if (last == rng->count) { + last = 0; + } + + if (last == rng->first) { + /* this condition should not happen, but due to probable race, + * new value could be generated before NRF_RNG task is stopped. + */ + return -ENOBUFS; + } + + if (!store) { + return -EBUSY; + } + + rng->rand[rng->last] = NRF_RNG->VALUE; + rng->last = last; + + last = rng->last + 1; + if (last == rng->count) { + last = 0; + } + + if (last == rng->first) { + return 0; + } + + return -EBUSY; +} + void isr_rand(void *param) { ARG_UNUSED(param); if (NRF_RNG->EVENTS_VALRDY) { - u8_t last; + u8_t ret; - last = rng->last + 1; - if (last == rng->count) { - last = 0; - } - - if (last == rng->first) { - /* this condition should not happen - * , but due to probable bug in HW - * , new value could be generated - * before task is stopped. - */ - NRF_RNG->TASKS_STOP = 1; - NRF_RNG->EVENTS_VALRDY = 0; - - return; - } - - rng->rand[rng->last] = NRF_RNG->VALUE; - rng->last = last; - - last = rng->last + 1; - if (last == rng->count) { - last = 0; + ret = isr(rng_isr, true); + if (ret != -EBUSY) { + ret = isr(rng_thr, (ret == -ENOBUFS)); } NRF_RNG->EVENTS_VALRDY = 0; - if (last == rng->first) { + if (ret != -EBUSY) { NRF_RNG->TASKS_STOP = 1; } } diff --git a/subsys/bluetooth/controller/hal/rand.h b/subsys/bluetooth/controller/hal/rand.h index a09c2dec69a..128edfafc2f 100644 --- a/subsys/bluetooth/controller/hal/rand.h +++ b/subsys/bluetooth/controller/hal/rand.h @@ -8,8 +8,10 @@ #ifndef _RAND_H_ #define _RAND_H_ -void rand_init(u8_t *context, u8_t context_len); +void rand_init(u8_t *context, u8_t context_len, u8_t threshold); +void rand_isr_init(u8_t *context, u8_t context_len, u8_t threshold); size_t rand_get(size_t octets, u8_t *rand); +size_t rand_isr_get(size_t octets, u8_t *rand); void isr_rand(void *param); #endif /* _RAND_H_ */ diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index b01b178a1b4..c13389af780 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -3227,8 +3227,9 @@ static inline u32_t isr_close_adv(void) u32_t ticker_status; u8_t random_delay; - /** @todo use random 0-10 */ - random_delay = 10; + rand_isr_get(sizeof(random_delay), &random_delay); + random_delay %= 10; + random_delay += 1; /* Call to ticker_update can fail under the race * condition where in the Adv role is being stopped but @@ -8095,12 +8096,11 @@ static void enc_req_reused_send(struct connection *conn, conn->llcp.encryption.ediv[0]; pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.ediv[1] = conn->llcp.encryption.ediv[1]; - /** @todo */ - memset(&pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.skdm[0], 0xcc, - sizeof(pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.skdm)); - /** @todo */ - memset(&pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.ivm[0], 0xdd, - sizeof(pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.ivm)); + /* NOTE: if not sufficient random numbers, ignore waiting */ + rand_isr_get(sizeof(pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.skdm), + pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.skdm); + rand_isr_get(sizeof(pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.ivm), + pdu_ctrl_tx->payload.llctrl.ctrldata.enc_req.ivm); } static void enc_rsp_send(struct connection *conn) @@ -8117,12 +8117,11 @@ static void enc_rsp_send(struct connection *conn) pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, ctrldata) + sizeof(struct pdu_data_llctrl_enc_rsp); pdu_ctrl_tx->payload.llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_RSP; - /** @todo */ - memset(&pdu_ctrl_tx->payload.llctrl.ctrldata.enc_rsp.skds[0], 0xaa, - sizeof(pdu_ctrl_tx->payload.llctrl.ctrldata.enc_rsp.skds)); - /** @todo */ - memset(&pdu_ctrl_tx->payload.llctrl.ctrldata.enc_rsp.ivs[0], 0xbb, - sizeof(pdu_ctrl_tx->payload.llctrl.ctrldata.enc_rsp.ivs)); + /* NOTE: if not sufficient random numbers, ignore waiting */ + rand_isr_get(sizeof(pdu_ctrl_tx->payload.llctrl.ctrldata.enc_rsp.skds), + pdu_ctrl_tx->payload.llctrl.ctrldata.enc_rsp.skds); + rand_isr_get(sizeof(pdu_ctrl_tx->payload.llctrl.ctrldata.enc_rsp.ivs), + pdu_ctrl_tx->payload.llctrl.ctrldata.enc_rsp.ivs); /* things from slave stored for session key calculation */ memcpy(&conn->llcp.encryption.skd[8], @@ -9342,30 +9341,21 @@ u32_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk) sizeof(conn->llcp.encryption.ltk)); if ((conn->enc_rx == 0) && (conn->enc_tx == 0)) { + struct pdu_data_llctrl_enc_req *enc_req; + pdu_data_tx->ll_id = PDU_DATA_LLID_CTRL; pdu_data_tx->len = offsetof(struct pdu_data_llctrl, ctrldata) + sizeof(struct pdu_data_llctrl_enc_req); pdu_data_tx->payload.llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ; - memcpy(&pdu_data_tx->payload.llctrl.ctrldata. - enc_req.rand[0], rand, - sizeof(pdu_data_tx->payload.llctrl.ctrldata. - enc_req.rand)); - pdu_data_tx->payload.llctrl.ctrldata.enc_req.ediv[0] = - ediv[0]; - pdu_data_tx->payload.llctrl.ctrldata.enc_req.ediv[1] = - ediv[1]; - memset(&pdu_data_tx->payload.llctrl.ctrldata.enc_req. - skdm[0], 0xcc, - /** @todo */ - sizeof(pdu_data_tx->payload.llctrl.ctrldata. - enc_req.skdm)); - memset(&pdu_data_tx->payload.llctrl.ctrldata.enc_req. - ivm[0], 0xdd, - /** @todo */ - sizeof(pdu_data_tx->payload.llctrl.ctrldata. - enc_req.ivm)); + enc_req = (void *) + &pdu_data_tx->payload.llctrl.ctrldata.enc_req; + memcpy(enc_req->rand, rand, sizeof(enc_req->rand)); + enc_req->ediv[0] = ediv[0]; + enc_req->ediv[1] = ediv[1]; + bt_rand(enc_req->skdm, sizeof(enc_req->skdm)); + bt_rand(enc_req->ivm, sizeof(enc_req->ivm)); } else if ((conn->enc_rx != 0) && (conn->enc_tx != 0)) { memcpy(&conn->llcp.encryption.rand[0], rand, sizeof(conn->llcp.encryption.rand)); diff --git a/subsys/bluetooth/controller/ll_sw/ll.c b/subsys/bluetooth/controller/ll_sw/ll.c index c7a6ba8278b..d3e697a6506 100644 --- a/subsys/bluetooth/controller/ll_sw/ll.c +++ b/subsys/bluetooth/controller/ll_sw/ll.c @@ -41,7 +41,10 @@ /* Global singletons */ /* memory for storing Random number */ -static u8_t MALIGN(4) _rand_context[3 + 4 + 1]; +#define RAND_THREAD_THRESHOLD 4 /* atleast access address */ +#define RAND_ISR_THRESHOLD 12 /* atleast encryption div. and iv */ +static u8_t MALIGN(4) rand_context[4 + RAND_THREAD_THRESHOLD + 1]; +static u8_t MALIGN(4) rand_isr_context[4 + RAND_ISR_THRESHOLD + 1]; #if defined(CONFIG_SOC_FLASH_NRF5_RADIO_SYNC) #define FLASH_TICKER_NODES 1 /* No. of tickers reserved for flashing */ @@ -198,7 +201,9 @@ int ll_init(struct k_sem *sem_rx) sem_recv = sem_rx; /* TODO: bind and use RNG driver */ - rand_init(_rand_context, sizeof(_rand_context)); + rand_init(rand_context, sizeof(rand_context), RAND_THREAD_THRESHOLD); + rand_isr_init(rand_isr_context, sizeof(rand_isr_context), + RAND_ISR_THRESHOLD); clk_k32 = device_get_binding(CONFIG_CLOCK_CONTROL_NRF5_K32SRC_DRV_NAME); if (!clk_k32) {