Skip to content

Commit 57f0990

Browse files
committed
nimble/ll: Add CS Security Start procedure
Implements LE CS Security Enable command.
1 parent f297a41 commit 57f0990

File tree

5 files changed

+151
-2
lines changed

5 files changed

+151
-2
lines changed

nimble/controller/include/controller/ble_ll_cs.h

+3
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@ void ble_ll_cs_reset(void);
3333

3434
void ble_ll_cs_capabilities_pdu_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
3535
void ble_ll_cs_config_req_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
36+
void ble_ll_cs_security_req_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
3637

3738
int ble_ll_cs_rx_capabilities_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspbuf);
3839
void ble_ll_cs_rx_capabilities_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
3940
int ble_ll_cs_rx_fae_req(struct ble_ll_conn_sm *connsm, uint8_t *rspbuf);
4041
void ble_ll_cs_rx_fae_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
4142
int ble_ll_cs_rx_config_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspbuf);
4243
void ble_ll_cs_rx_config_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
44+
int ble_ll_cs_rx_security_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspbuf);
45+
void ble_ll_cs_rx_security_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr);
4346

4447
/* HCI handlers */
4548
int ble_ll_cs_hci_rd_loc_supp_cap(uint8_t *rspbuf, uint8_t *rsplen);

nimble/controller/include/controller/ble_ll_ctrl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ extern "C" {
4646
#define BLE_LL_CTRL_PROC_CS_CAP_XCHG (14)
4747
#define BLE_LL_CTRL_PROC_CS_FAE_REQ (15)
4848
#define BLE_LL_CTRL_PROC_CS_CONF (16)
49-
#define BLE_LL_CTRL_PROC_NUM (17)
49+
#define BLE_LL_CTRL_PROC_CS_SEC_START (17)
50+
#define BLE_LL_CTRL_PROC_NUM (18)
5051
#define BLE_LL_CTRL_PROC_IDLE (255)
5152

5253
/* Checks if a particular control procedure is running */

nimble/controller/src/ble_ll_cs.c

+127-1
Original file line numberDiff line numberDiff line change
@@ -279,10 +279,136 @@ ble_ll_cs_hci_wr_cached_rem_supp_cap(const uint8_t *cmdbuf, uint8_t cmdlen,
279279
return BLE_ERR_SUCCESS;
280280
}
281281

282+
static void
283+
rej_ext_ind_make(uint8_t rej_opcode, uint8_t err, uint8_t *ctrdata)
284+
{
285+
ctrdata[0] = rej_opcode;
286+
ctrdata[1] = err;
287+
}
288+
289+
int
290+
ble_ll_cs_rx_security_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
291+
uint8_t *rspbuf)
292+
{
293+
uint8_t *iv = connsm->cssm->drbg_ctx.iv;
294+
uint8_t *in = connsm->cssm->drbg_ctx.in;
295+
uint8_t *pv = connsm->cssm->drbg_ctx.pv;
296+
297+
if (!connsm->flags.encrypted) {
298+
rej_ext_ind_make(BLE_LL_CTRL_CS_SEC_REQ, BLE_ERR_INSUFFICIENT_SEC,
299+
rspbuf);
300+
301+
return BLE_LL_CTRL_REJECT_IND_EXT;
302+
}
303+
304+
/* Vectors concatenation is done in the follwing manner:
305+
* CS_IV = CS_IV_P || CS_IV_C
306+
* The CS_IV_C is concatenated with the CS_IV_P. The least significant
307+
* octet of CS_IV_C becomes the least significant octet of CS_IV. The most
308+
* significant octet of CS_IV_P becomes the most significant octet of CS_IV.
309+
*/
310+
311+
/* Save Central's vector */
312+
memcpy(iv, dptr, 8);
313+
memcpy(in, dptr + 8, 4);
314+
memcpy(pv, dptr + 12, 8);
315+
316+
/* Generate Peripheral's vector */
317+
ble_ll_rand_data_get(iv + 8, 8);
318+
ble_ll_rand_data_get(in + 4, 4);
319+
ble_ll_rand_data_get(pv + 8, 8);
320+
321+
memcpy(rspbuf, iv + 8, 8);
322+
memcpy(rspbuf + 8, in + 4, 4);
323+
memcpy(rspbuf + 12, pv + 8, 8);
324+
325+
ble_ll_cs_drbg_init(&connsm->cssm->drbg_ctx);
326+
327+
return BLE_LL_CTRL_CS_SEC_RSP;
328+
}
329+
330+
static void
331+
ble_ll_cs_ev_sec_enable_complete(struct ble_ll_conn_sm *connsm, uint8_t status)
332+
{
333+
struct ble_hci_ev_le_subev_cs_sec_enable_complete *ev;
334+
struct ble_hci_ev *hci_ev;
335+
336+
if (ble_ll_hci_is_le_event_enabled(
337+
BLE_HCI_LE_SUBEV_CS_SEC_ENABLE_COMPLETE)) {
338+
hci_ev = ble_transport_alloc_evt(0);
339+
if (hci_ev) {
340+
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
341+
hci_ev->length = sizeof(*ev);
342+
ev = (void *) hci_ev->data;
343+
344+
ev->subev_code = BLE_HCI_LE_SUBEV_CS_SEC_ENABLE_COMPLETE;
345+
ev->status = status;
346+
ev->conn_handle = htole16(connsm->conn_handle);
347+
348+
ble_ll_hci_event_send(hci_ev);
349+
}
350+
}
351+
}
352+
353+
void
354+
ble_ll_cs_rx_security_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
355+
{
356+
int rc = 0;
357+
struct ble_ll_cs_drbg_ctx *drbg_ctx = &connsm->cssm->drbg_ctx;
358+
359+
if (!IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CS_SEC_START)) {
360+
/* Should never happen */
361+
return;
362+
}
363+
364+
/* Save Peripheral's vector */
365+
memcpy(drbg_ctx->iv + 8, dptr, 8);
366+
memcpy(drbg_ctx->in + 4, dptr + 8, 4);
367+
memcpy(drbg_ctx->pv + 8, dptr + 12, 8);
368+
369+
rc = ble_ll_cs_drbg_init(drbg_ctx);
370+
371+
/* Stop the control procedure and send an event to the host */
372+
ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CS_SEC_START);
373+
ble_ll_cs_ev_sec_enable_complete(connsm, rc ? BLE_ERR_INV_LMP_LL_PARM :
374+
BLE_ERR_SUCCESS);
375+
}
376+
377+
void
378+
ble_ll_cs_security_req_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
379+
{
380+
uint8_t *iv = connsm->cssm->drbg_ctx.iv;
381+
uint8_t *in = connsm->cssm->drbg_ctx.in;
382+
uint8_t *pv = connsm->cssm->drbg_ctx.pv;
383+
384+
/* Generate Central's vector */
385+
ble_ll_rand_data_get(iv, 8);
386+
ble_ll_rand_data_get(in, 4);
387+
ble_ll_rand_data_get(pv, 8);
388+
389+
memcpy(dptr, iv, 8);
390+
memcpy(dptr + 8, in, 4);
391+
memcpy(dptr + 12, pv, 8);
392+
}
393+
282394
int
283395
ble_ll_cs_hci_sec_enable(const uint8_t *cmdbuf, uint8_t cmdlen)
284396
{
285-
return BLE_ERR_UNSUPPORTED;
397+
const struct ble_hci_le_cs_sec_enable_cp *cmd = (const void *)cmdbuf;
398+
struct ble_ll_conn_sm *connsm;
399+
400+
connsm = ble_ll_conn_find_by_handle(le16toh(cmd->conn_handle));
401+
if (!connsm) {
402+
return BLE_ERR_UNK_CONN_ID;
403+
}
404+
405+
if (!connsm->flags.encrypted) {
406+
return BLE_ERR_INSUFFICIENT_SEC;
407+
}
408+
409+
ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CS_SEC_START, NULL);
410+
411+
return BLE_ERR_SUCCESS;
286412
}
287413

288414
int

nimble/controller/src/ble_ll_cs_priv.h

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ struct ble_ll_cs_sm {
107107
/* Arguments for ble_ll_cs_config_req_make */
108108
uint8_t config_req_id;
109109
uint8_t config_req_action;
110+
111+
/* DRBG context, initialized onece per LE Connection */
112+
struct ble_ll_cs_drbg_ctx drbg_ctx;
110113
};
111114

112115
#ifdef __cplusplus

nimble/controller/src/ble_ll_ctrl.c

+16
Original file line numberDiff line numberDiff line change
@@ -2582,6 +2582,12 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data)
25822582
opcode = BLE_LL_CTRL_CS_CONFIG_REQ;
25832583
ble_ll_cs_config_req_make(connsm, ctrdata);
25842584
break;
2585+
#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
2586+
case BLE_LL_CTRL_PROC_CS_SEC_START:
2587+
opcode = BLE_LL_CTRL_CS_SEC_REQ;
2588+
ble_ll_cs_security_req_make(connsm, ctrdata);
2589+
break;
2590+
#endif
25852591
#endif
25862592
default:
25872593
BLE_LL_ASSERT(0);
@@ -3063,6 +3069,16 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
30633069
case BLE_LL_CTRL_CS_CONFIG_RSP:
30643070
ble_ll_cs_rx_config_rsp(connsm, dptr);
30653071
break;
3072+
#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL)
3073+
case BLE_LL_CTRL_CS_SEC_REQ:
3074+
rsp_opcode = ble_ll_cs_rx_security_req(connsm, dptr, rspdata);
3075+
break;
3076+
#endif
3077+
#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
3078+
case BLE_LL_CTRL_CS_SEC_RSP:
3079+
ble_ll_cs_rx_security_rsp(connsm, dptr);
3080+
break;
3081+
#endif
30663082
#endif
30673083
default:
30683084
/* Nothing to do here */

0 commit comments

Comments
 (0)