Skip to content

Commit 48e5d94

Browse files
cvinayakcarlescufi
authored andcommitted
Bluetooth: controller: split: Fix the slow Enc Setup alternative
Fix the implementation of slow encryption setup design alternative to send ENC_RSP PDU before sending REJECT_IND or REJECT_EXT_IND PDU. Fixes #19917. Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent 0a89231 commit 48e5d94

File tree

3 files changed

+89
-48
lines changed

3 files changed

+89
-48
lines changed

subsys/bluetooth/controller/ll_sw/ull_conn.c

Lines changed: 74 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,7 @@ static bool is_enc_req_pause_tx(struct ll_conn *conn)
20122012
}
20132013

20142014
if (conn->llcp_req == conn->llcp_ack) {
2015-
conn->llcp.encryption.initiate = 1U;
2015+
conn->llcp.encryption.state = LLCP_ENC_STATE_INIT;
20162016

20172017
conn->llcp_type = LLCP_ENCRYPTION;
20182018
conn->llcp_ack -= 2U;
@@ -2503,11 +2503,56 @@ static inline void event_enc_reject_prep(struct ll_conn *conn,
25032503

25042504
static inline void event_enc_prep(struct ll_conn *conn)
25052505
{
2506+
struct lll_conn *lll = &conn->lll;
25062507
struct pdu_data *pdu_ctrl_tx;
25072508
struct node_tx *tx;
2508-
struct lll_conn *lll;
25092509

2510-
if (conn->llcp.encryption.initiate) {
2510+
if (conn->llcp.encryption.state) {
2511+
#if !defined(CONFIG_BT_CTLR_FAST_ENC)
2512+
if (lll->role &&
2513+
(conn->llcp.encryption.state == LLCP_ENC_STATE_INIT)) {
2514+
struct node_rx_pdu *rx;
2515+
struct pdu_data *pdu;
2516+
u8_t err;
2517+
2518+
/* TODO BT Spec. text: may finalize the sending
2519+
* of additional data channel PDUs queued in the
2520+
* controller.
2521+
*/
2522+
err = enc_rsp_send(conn);
2523+
if (err) {
2524+
return;
2525+
}
2526+
2527+
/* get a rx node for ULL->LL */
2528+
rx = ll_pdu_rx_alloc();
2529+
if (!rx) {
2530+
return;
2531+
}
2532+
2533+
/* prepare enc req structure */
2534+
rx->hdr.handle = conn->lll.handle;
2535+
rx->hdr.type = NODE_RX_TYPE_DC_PDU;
2536+
pdu = (void *)rx->pdu;
2537+
pdu->ll_id = PDU_DATA_LLID_CTRL;
2538+
pdu->len = offsetof(struct pdu_data_llctrl, enc_req) +
2539+
sizeof(struct pdu_data_llctrl_enc_req);
2540+
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ;
2541+
memcpy(&pdu->llctrl.enc_req.rand[0],
2542+
&conn->llcp_enc.rand[0],
2543+
sizeof(pdu->llctrl.enc_req.rand));
2544+
pdu->llctrl.enc_req.ediv[0] = conn->llcp_enc.ediv[0];
2545+
pdu->llctrl.enc_req.ediv[1] = conn->llcp_enc.ediv[1];
2546+
2547+
/* enqueue enc req structure into rx queue */
2548+
ll_rx_put(rx->hdr.link, rx);
2549+
ll_rx_sched();
2550+
2551+
/* Wait for LTK reply */
2552+
conn->llcp.encryption.state = LLCP_ENC_STATE_LTK_WAIT;
2553+
}
2554+
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
2555+
25112556
return;
25122557
}
25132558

@@ -2516,8 +2561,6 @@ static inline void event_enc_prep(struct ll_conn *conn)
25162561
return;
25172562
}
25182563

2519-
lll = &conn->lll;
2520-
25212564
pdu_ctrl_tx = (void *)tx->pdu;
25222565

25232566
/* master sends encrypted enc start rsp in control priority */
@@ -2559,7 +2602,7 @@ static inline void event_enc_prep(struct ll_conn *conn)
25592602
#if defined(CONFIG_BT_CTLR_FAST_ENC)
25602603
else {
25612604
#else /* !CONFIG_BT_CTLR_FAST_ENC */
2562-
else if (!conn->llcp_enc.pause_tx || conn->llcp_enc.refresh) {
2605+
else if (!lll->enc_rx) {
25632606
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
25642607

25652608
/* place the reject ind packet as next in tx queue */
@@ -2570,22 +2613,6 @@ static inline void event_enc_prep(struct ll_conn *conn)
25702613
}
25712614
/* place the start enc req packet as next in tx queue */
25722615
else {
2573-
2574-
#if !defined(CONFIG_BT_CTLR_FAST_ENC)
2575-
u8_t err;
2576-
2577-
/* TODO BT Spec. text: may finalize the sending
2578-
* of additional data channel PDUs queued in the
2579-
* controller.
2580-
*/
2581-
err = enc_rsp_send(conn);
2582-
if (err) {
2583-
mem_release(tx, &mem_conn_tx_ctrl.free);
2584-
2585-
return;
2586-
}
2587-
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
2588-
25892616
/* calc the Session Key */
25902617
ecb_encrypt(&conn->llcp_enc.ltk[0],
25912618
&conn->llcp.encryption.skd[0], NULL,
@@ -5146,8 +5173,28 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
51465173
if (nack) {
51475174
break;
51485175
}
5176+
5177+
/* Start Enc Req to be scheduled by LL api */
5178+
conn->llcp.encryption.state = LLCP_ENC_STATE_LTK_WAIT;
5179+
#else /* CONFIG_BT_CTLR_FAST_ENC */
5180+
/* back up rand and ediv for deferred generation of Enc Req */
5181+
memcpy(&conn->llcp_enc.rand[0],
5182+
&pdu_rx->llctrl.enc_req.rand[0],
5183+
sizeof(conn->llcp_enc.rand));
5184+
conn->llcp_enc.ediv[0] = pdu_rx->llctrl.enc_req.ediv[0];
5185+
conn->llcp_enc.ediv[1] = pdu_rx->llctrl.enc_req.ediv[1];
5186+
5187+
/* Enc rsp to be scheduled in master prepare */
5188+
conn->llcp.encryption.state = LLCP_ENC_STATE_INIT;
5189+
5190+
/* Mark for buffer for release */
5191+
(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
51495192
#endif /* CONFIG_BT_CTLR_FAST_ENC */
51505193

5194+
/* Enc Setup state machine active */
5195+
conn->llcp_type = LLCP_ENCRYPTION;
5196+
conn->llcp_ack -= 2U;
5197+
51515198
/* things from master stored for session key calculation */
51525199
memcpy(&conn->llcp.encryption.skd[0],
51535200
&pdu_rx->llctrl.enc_req.skdm[0], 8);
@@ -5185,20 +5232,15 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
51855232
break;
51865233

51875234
case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ:
5188-
if (conn->lll.role ||
5189-
((conn->llcp_req != conn->llcp_ack) &&
5190-
(conn->llcp_type != LLCP_ENCRYPTION)) ||
5235+
if (conn->lll.role || (conn->llcp_req == conn->llcp_ack) ||
5236+
(conn->llcp_type != LLCP_ENCRYPTION) ||
51915237
!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_START_ENC_REQ,
51925238
pdu_rx->len)) {
51935239
goto ull_conn_rx_unknown_rsp_send;
51945240
}
51955241

51965242
/* start enc rsp to be scheduled in master prepare */
5197-
conn->llcp.encryption.initiate = 0U;
5198-
if (conn->llcp_req == conn->llcp_ack) {
5199-
conn->llcp_type = LLCP_ENCRYPTION;
5200-
conn->llcp_ack -= 2U;
5201-
}
5243+
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
52025244

52035245
/* Mark for buffer for release */
52045246
(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
@@ -5219,11 +5261,12 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
52195261
}
52205262

52215263
/* start enc rsp to be scheduled in slave prepare */
5222-
conn->llcp.encryption.initiate = 0U;
5264+
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
52235265
if (conn->llcp_req == conn->llcp_ack) {
52245266
conn->llcp_type = LLCP_ENCRYPTION;
52255267
conn->llcp_ack -= 2U;
52265268
}
5269+
52275270
#else /* CONFIG_BT_CTLR_FAST_ENC */
52285271
nack = start_enc_rsp_send(conn, NULL);
52295272
if (nack) {

subsys/bluetooth/controller/ll_sw/ull_conn_types.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ struct ll_conn {
119119

120120
#if defined(CONFIG_BT_CTLR_LE_ENC)
121121
struct {
122-
u8_t initiate;
122+
enum {
123+
LLCP_ENC_STATE_INPROG,
124+
LLCP_ENC_STATE_INIT,
125+
LLCP_ENC_STATE_LTK_WAIT,
126+
} state:2 __packed;
123127
u8_t error_code;
124128
u8_t skd[16];
125129
} encryption;

subsys/bluetooth/controller/ll_sw/ull_slave.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,6 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
386386
u8_t const *const ltk)
387387
{
388388
struct ll_conn *conn;
389-
u8_t ret;
390389

391390
conn = ll_connected_get(handle);
392391
if (!conn) {
@@ -395,16 +394,13 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
395394

396395
if (error_code) {
397396
if (conn->llcp_enc.refresh == 0U) {
398-
ret = ull_conn_llcp_req(conn);
399-
if (ret) {
400-
return ret;
397+
if ((conn->llcp_req == conn->llcp_ack) ||
398+
(conn->llcp_type != LLCP_ENCRYPTION)) {
399+
return BT_HCI_ERR_CMD_DISALLOWED;
401400
}
402401

403402
conn->llcp.encryption.error_code = error_code;
404-
conn->llcp.encryption.initiate = 0U;
405-
406-
conn->llcp_type = LLCP_ENCRYPTION;
407-
conn->llcp_req++;
403+
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
408404
} else {
409405
if (conn->llcp_terminate.ack !=
410406
conn->llcp_terminate.req) {
@@ -416,18 +412,16 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
416412
conn->llcp_terminate.req++;
417413
}
418414
} else {
419-
ret = ull_conn_llcp_req(conn);
420-
if (ret) {
421-
return ret;
415+
if ((conn->llcp_req == conn->llcp_ack) ||
416+
(conn->llcp_type != LLCP_ENCRYPTION)) {
417+
return BT_HCI_ERR_CMD_DISALLOWED;
422418
}
423419

424-
memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk));
420+
memcpy(&conn->llcp_enc.ltk[0], ltk,
421+
sizeof(conn->llcp_enc.ltk));
425422

426423
conn->llcp.encryption.error_code = 0U;
427-
conn->llcp.encryption.initiate = 0U;
428-
429-
conn->llcp_type = LLCP_ENCRYPTION;
430-
conn->llcp_req++;
424+
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
431425
}
432426

433427
return 0;

0 commit comments

Comments
 (0)