Skip to content

Commit dca0769

Browse files
committed
Bluetooth: controller: legacy: 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 3c57e7c commit dca0769

File tree

2 files changed

+91
-41
lines changed

2 files changed

+91
-41
lines changed

subsys/bluetooth/controller/ll_sw/ctrl.c

Lines changed: 86 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2766,7 +2766,30 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx,
27662766
if (nack) {
27672767
break;
27682768
}
2769-
#endif /* CONFIG_BT_CTLR_FAST_ENC */
2769+
2770+
/* enqueue the enc req */
2771+
*rx_enqueue = 1U;
2772+
2773+
/* Start Enc Req to be scheduled by LL api */
2774+
_radio.conn_curr->llcp.encryption.state =
2775+
LLCP_ENC_STATE_LTK_WAIT;
2776+
#else /* !CONFIG_BT_CTLR_FAST_ENC */
2777+
/* back up rand and ediv for deferred generation of Enc Req */
2778+
memcpy(&_radio.conn_curr->llcp_enc.rand[0],
2779+
&pdu_data_rx->llctrl.enc_req.rand[0],
2780+
sizeof(_radio.conn_curr->llcp_enc.rand));
2781+
_radio.conn_curr->llcp_enc.ediv[0] =
2782+
pdu_data_rx->llctrl.enc_req.ediv[0];
2783+
_radio.conn_curr->llcp_enc.ediv[1] =
2784+
pdu_data_rx->llctrl.enc_req.ediv[1];
2785+
2786+
/* Enc rsp to be scheduled in master prepare */
2787+
_radio.conn_curr->llcp.encryption.state = LLCP_ENC_STATE_INIT;
2788+
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
2789+
2790+
/* Enc Setup requested */
2791+
_radio.conn_curr->llcp_type = LLCP_ENCRYPTION;
2792+
_radio.conn_curr->llcp_ack--;
27702793

27712794
/* things from master stored for session key calculation */
27722795
memcpy(&_radio.conn_curr->llcp.encryption.skd[0],
@@ -2782,9 +2805,6 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx,
27822805
*/
27832806
_radio.conn_curr->procedure_expire =
27842807
_radio.conn_curr->procedure_reload;
2785-
2786-
/* enqueue the enc req */
2787-
*rx_enqueue = 1U;
27882808
break;
27892809

27902810
case PDU_DATA_LLCTRL_TYPE_ENC_RSP:
@@ -2806,18 +2826,16 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx,
28062826

28072827
case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ:
28082828
if (_radio.conn_curr->role ||
2809-
((_radio.conn_curr->llcp_req !=
2810-
_radio.conn_curr->llcp_ack) &&
2811-
(_radio.conn_curr->llcp_type != LLCP_ENCRYPTION)) ||
2829+
(_radio.conn_curr->llcp_req ==
2830+
_radio.conn_curr->llcp_ack) ||
2831+
(_radio.conn_curr->llcp_type != LLCP_ENCRYPTION) ||
28122832
!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_START_ENC_REQ,
28132833
pdu_data_rx->len)) {
28142834
goto isr_rx_conn_unknown_rsp_send;
28152835
}
28162836

28172837
/* start enc rsp to be scheduled in master prepare */
2818-
_radio.conn_curr->llcp.encryption.initiate = 0U;
2819-
_radio.conn_curr->llcp_type = LLCP_ENCRYPTION;
2820-
_radio.conn_curr->llcp_ack--;
2838+
_radio.conn_curr->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
28212839
break;
28222840

28232841
case PDU_DATA_LLCTRL_TYPE_START_ENC_RSP:
@@ -2835,7 +2853,8 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx,
28352853
}
28362854

28372855
/* start enc rsp to be scheduled in slave prepare */
2838-
_radio.conn_curr->llcp.encryption.initiate = 0U;
2856+
_radio.conn_curr->llcp.encryption.state =
2857+
LLCP_ENC_STATE_INPROG;
28392858
_radio.conn_curr->llcp_type = LLCP_ENCRYPTION;
28402859
_radio.conn_curr->llcp_ack--;
28412860
#else /* CONFIG_BT_CTLR_FAST_ENC */
@@ -7671,7 +7690,54 @@ static inline void event_enc_prep(struct connection *conn)
76717690
struct radio_pdu_node_tx *node_tx;
76727691
struct pdu_data *pdu_ctrl_tx;
76737692

7674-
if (conn->llcp.encryption.initiate) {
7693+
if (conn->llcp.encryption.state) {
7694+
#if !defined(CONFIG_BT_CTLR_FAST_ENC) && defined(CONFIG_BT_PERIPHERAL)
7695+
if (conn->role &&
7696+
(conn->llcp.encryption.state == LLCP_ENC_STATE_INIT)) {
7697+
struct radio_pdu_node_rx *node_rx;
7698+
struct pdu_data *pdu_ctrl_rx;
7699+
u8_t err;
7700+
7701+
/* TODO BT Spec. text: may finalize the sending
7702+
* of additional data channel PDUs queued in the
7703+
* controller.
7704+
*/
7705+
err = enc_rsp_send(conn);
7706+
if (err) {
7707+
return;
7708+
}
7709+
7710+
/* Prepare the rx packet structure */
7711+
node_rx = packet_rx_reserve_get(2);
7712+
LL_ASSERT(node_rx);
7713+
7714+
node_rx->hdr.handle = conn->handle;
7715+
node_rx->hdr.type = NODE_RX_TYPE_DC_PDU;
7716+
7717+
/* prepare enc req structure */
7718+
pdu_ctrl_rx = (void *)node_rx->pdu_data;
7719+
pdu_ctrl_rx->ll_id = PDU_DATA_LLID_CTRL;
7720+
pdu_ctrl_rx->len =
7721+
offsetof(struct pdu_data_llctrl, enc_req) +
7722+
sizeof(struct pdu_data_llctrl_enc_req);
7723+
pdu_ctrl_rx->llctrl.opcode =
7724+
PDU_DATA_LLCTRL_TYPE_ENC_REQ;
7725+
memcpy(&pdu_ctrl_rx->llctrl.enc_req.rand[0],
7726+
&conn->llcp_enc.rand[0],
7727+
sizeof(pdu_ctrl_rx->llctrl.enc_req.rand));
7728+
pdu_ctrl_rx->llctrl.enc_req.ediv[0] =
7729+
conn->llcp_enc.ediv[0];
7730+
pdu_ctrl_rx->llctrl.enc_req.ediv[1] =
7731+
conn->llcp_enc.ediv[1];
7732+
7733+
/* enqueue enc req structure into rx queue */
7734+
packet_rx_enqueue();
7735+
7736+
/* Wait for LTK reply */
7737+
conn->llcp.encryption.state = LLCP_ENC_STATE_LTK_WAIT;
7738+
}
7739+
#endif /* !CONFIG_BT_CTLR_FAST_ENC && CONFIG_BT_PERIPHERAL */
7740+
76757741
return;
76767742
}
76777743

@@ -7719,7 +7785,7 @@ static inline void event_enc_prep(struct connection *conn)
77197785
#if defined(CONFIG_BT_CTLR_FAST_ENC)
77207786
else {
77217787
#else /* !CONFIG_BT_CTLR_FAST_ENC */
7722-
else if (!conn->pause_tx || conn->refresh) {
7788+
else if (!conn->enc_rx) {
77237789
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
77247790

77257791
/* place the reject ind packet as next in tx queue */
@@ -7728,22 +7794,6 @@ static inline void event_enc_prep(struct connection *conn)
77287794
}
77297795
/* place the start enc req packet as next in tx queue */
77307796
else {
7731-
7732-
#if !defined(CONFIG_BT_CTLR_FAST_ENC)
7733-
u8_t err;
7734-
7735-
/* TODO BT Spec. text: may finalize the sending
7736-
* of additional data channel PDUs queued in the
7737-
* controller.
7738-
*/
7739-
err = enc_rsp_send(conn);
7740-
if (err) {
7741-
mem_release(node_tx, &_radio.pkt_tx_ctrl_free);
7742-
7743-
return;
7744-
}
7745-
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
7746-
77477797
/* calc the Session Key */
77487798
ecb_encrypt(&conn->llcp_enc.ltk[0],
77497799
&conn->llcp.encryption.skd[0], NULL,
@@ -9912,7 +9962,7 @@ static bool is_enc_req_pause_tx(struct connection *conn)
99129962
}
99139963

99149964
if (conn->llcp_req == conn->llcp_ack) {
9915-
conn->llcp.encryption.initiate = 1U;
9965+
conn->llcp.encryption.state = LLCP_ENC_STATE_INIT;
99169966

99179967
conn->llcp_type = LLCP_ENCRYPTION;
99189968
conn->llcp_ack--;
@@ -12279,15 +12329,13 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
1227912329

1228012330
if (error_code) {
1228112331
if (conn->refresh == 0) {
12282-
if (conn->llcp_req != conn->llcp_ack) {
12332+
if ((conn->llcp_req == conn->llcp_ack) ||
12333+
(conn->llcp_type != LLCP_ENCRYPTION)) {
1228312334
return BT_HCI_ERR_CMD_DISALLOWED;
1228412335
}
1228512336

1228612337
conn->llcp.encryption.error_code = error_code;
12287-
conn->llcp.encryption.initiate = 0U;
12288-
12289-
conn->llcp_type = LLCP_ENCRYPTION;
12290-
conn->llcp_req++;
12338+
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
1229112339
} else {
1229212340
if (conn->llcp_terminate.ack !=
1229312341
conn->llcp_terminate.req) {
@@ -12299,18 +12347,16 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
1229912347
conn->llcp_terminate.req++;
1230012348
}
1230112349
} else {
12302-
if (conn->llcp_req != conn->llcp_ack) {
12350+
if ((conn->llcp_req == conn->llcp_ack) ||
12351+
(conn->llcp_type != LLCP_ENCRYPTION)) {
1230312352
return BT_HCI_ERR_CMD_DISALLOWED;
1230412353
}
1230512354

1230612355
memcpy(&conn->llcp_enc.ltk[0], ltk,
1230712356
sizeof(conn->llcp_enc.ltk));
1230812357

1230912358
conn->llcp.encryption.error_code = 0U;
12310-
conn->llcp.encryption.initiate = 0U;
12311-
12312-
conn->llcp_type = LLCP_ENCRYPTION;
12313-
conn->llcp_req++;
12359+
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
1231412360
}
1231512361

1231612362
return 0;

subsys/bluetooth/controller/ll_sw/ctrl_internal.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,11 @@ struct connection {
159159

160160
#if defined(CONFIG_BT_CTLR_LE_ENC)
161161
struct {
162-
u8_t initiate:1;
162+
enum {
163+
LLCP_ENC_STATE_INPROG,
164+
LLCP_ENC_STATE_INIT,
165+
LLCP_ENC_STATE_LTK_WAIT,
166+
} state:2 __packed;
163167
u8_t error_code;
164168
u8_t skd[16];
165169
} encryption;

0 commit comments

Comments
 (0)