Skip to content

Commit fff35bd

Browse files
cvinayaknashif
authored andcommitted
Bluetooth: controller: Fix encryption setup to be queueable
Fix the controller implementation to make start encryption queueable if there is any control procedure in progress. The context related to encryption procedure is now shared so that it will be used after the ongoing procedure completes. The fix here maintains the old functionality of serializing the queued data and LL Encryption Request PDU, so that data queued before start encryption is acknowledged. Fixes #15012. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
1 parent e81acd8 commit fff35bd

File tree

2 files changed

+100
-39
lines changed

2 files changed

+100
-39
lines changed

subsys/bluetooth/controller/ll_sw/ctrl.c

Lines changed: 88 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,6 +1876,9 @@ static inline u32_t isr_rx_conn_pkt_ack(struct pdu_data *pdu_data_tx,
18761876
*/
18771877
_radio.conn_curr->procedure_expire =
18781878
_radio.conn_curr->procedure_reload;
1879+
1880+
/* Reset enc req queued state */
1881+
_radio.conn_curr->llcp_enc.ack = _radio.conn_curr->llcp_enc.req;
18791882
break;
18801883

18811884
case PDU_DATA_LLCTRL_TYPE_ENC_RSP:
@@ -2643,14 +2646,10 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx,
26432646
break;
26442647

26452648
case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ:
2646-
if (!((_radio.conn_curr->llcp_req ==
2647-
_radio.conn_curr->llcp_ack) ||
2648-
(_radio.conn_curr->llcp_type == LLCP_ENCRYPTION))) {
2649-
goto isr_rx_conn_unknown_rsp_send;
2650-
}
2651-
2652-
26532649
if (_radio.conn_curr->role ||
2650+
((_radio.conn_curr->llcp_req !=
2651+
_radio.conn_curr->llcp_ack) &&
2652+
(_radio.conn_curr->llcp_type != LLCP_ENCRYPTION)) ||
26542653
!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_START_ENC_REQ,
26552654
pdu_data_rx->len)) {
26562655
goto isr_rx_conn_unknown_rsp_send;
@@ -2670,10 +2669,9 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *node_rx,
26702669

26712670
if (_radio.role == ROLE_SLAVE) {
26722671
#if !defined(CONFIG_BT_CTLR_FAST_ENC)
2673-
if (!((_radio.conn_curr->llcp_req ==
2674-
_radio.conn_curr->llcp_ack) ||
2675-
(_radio.conn_curr->llcp_type ==
2676-
LLCP_ENCRYPTION))) {
2672+
if ((_radio.conn_curr->llcp_req !=
2673+
_radio.conn_curr->llcp_ack) &&
2674+
(_radio.conn_curr->llcp_type != LLCP_ENCRYPTION)) {
26772675
goto isr_rx_conn_unknown_rsp_send;
26782676
}
26792677

@@ -7407,7 +7405,7 @@ static inline void event_enc_prep(struct connection *conn)
74077405
/* master sends encrypted enc start rsp in control priority */
74087406
if (!conn->role) {
74097407
/* calc the Session Key */
7410-
ecb_encrypt(&conn->llcp.encryption.ltk[0],
7408+
ecb_encrypt(&conn->llcp_enc.ltk[0],
74117409
&conn->llcp.encryption.skd[0],
74127410
NULL, &conn->ccm_rx.key[0]);
74137411

@@ -7467,7 +7465,7 @@ static inline void event_enc_prep(struct connection *conn)
74677465
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
74687466

74697467
/* calc the Session Key */
7470-
ecb_encrypt(&conn->llcp.encryption.ltk[0],
7468+
ecb_encrypt(&conn->llcp_enc.ltk[0],
74717469
&conn->llcp.encryption.skd[0], NULL,
74727470
&conn->ccm_rx.key[0]);
74737471

@@ -9262,6 +9260,55 @@ static struct pdu_data *empty_tx_enqueue(struct connection *conn)
92629260
return pdu_data_tx;
92639261
}
92649262

9263+
#if defined(CONFIG_BT_CTLR_LE_ENC)
9264+
static bool is_enc_req_pause_tx(struct connection *conn)
9265+
{
9266+
struct pdu_data *pdu_data_tx;
9267+
9268+
pdu_data_tx = (void *)conn->pkt_tx_head->pdu_data;
9269+
if ((pdu_data_tx->ll_id == PDU_DATA_LLID_CTRL) &&
9270+
(pdu_data_tx->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_ENC_REQ)) {
9271+
if ((conn->llcp_req != conn->llcp_ack) ||
9272+
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
9273+
(conn->llcp_conn_param.ack != conn->llcp_conn_param.req) ||
9274+
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
9275+
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
9276+
(conn->llcp_length.ack != conn->llcp_length.req) ||
9277+
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
9278+
#if defined(CONFIG_BT_CTLR_PHY)
9279+
(conn->llcp_phy.ack != conn->llcp_phy.req) ||
9280+
#endif /* CONFIG_BT_CTLR_PHY */
9281+
0) {
9282+
struct radio_pdu_node_tx *node_tx;
9283+
9284+
/* if we have control packets enqueued after this PDU
9285+
* bring it ahead, and move the enc_req to last of
9286+
* ctrl queue.
9287+
*/
9288+
node_tx = conn->pkt_tx_head;
9289+
if ((node_tx->next != NULL) &&
9290+
(node_tx->next == conn->pkt_tx_ctrl)) {
9291+
conn->pkt_tx_head = node_tx->next;
9292+
node_tx->next = conn->pkt_tx_ctrl_last->next;
9293+
conn->pkt_tx_ctrl_last->next = node_tx;
9294+
conn->pkt_tx_data = node_tx;
9295+
if (!conn->pkt_tx_last) {
9296+
conn->pkt_tx_last = node_tx;
9297+
}
9298+
}
9299+
return true;
9300+
}
9301+
9302+
conn->llcp.encryption.initiate = 1U;
9303+
9304+
conn->llcp_type = LLCP_ENCRYPTION;
9305+
conn->llcp_ack--;
9306+
}
9307+
9308+
return false;
9309+
}
9310+
#endif /* CONFIG_BT_CTLR_LE_ENC */
9311+
92659312
static void prepare_pdu_data_tx(struct connection *conn,
92669313
struct pdu_data **pdu_data_tx)
92679314
{
@@ -9272,7 +9319,11 @@ static void prepare_pdu_data_tx(struct connection *conn,
92729319
/* no ctrl or data packet */
92739320
!conn->pkt_tx_head ||
92749321
/* data tx paused, only control packets allowed */
9275-
((conn->pause_tx ||
9322+
((
9323+
#if defined(CONFIG_BT_CTLR_LE_ENC)
9324+
conn->pause_tx ||
9325+
is_enc_req_pause_tx(conn) ||
9326+
#endif /* CONFIG_BT_CTLR_LE_ENC */
92769327
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
92779328
conn->llcp_length.pause_tx ||
92789329
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
@@ -9821,12 +9872,12 @@ static void enc_req_reused_send(struct connection *conn,
98219872
sizeof(struct pdu_data_llctrl_enc_req);
98229873
pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ;
98239874
memcpy(&pdu_ctrl_tx->llctrl.enc_req.rand[0],
9824-
&conn->llcp.encryption.rand[0],
9875+
&conn->llcp_enc.rand[0],
98259876
sizeof(pdu_ctrl_tx->llctrl.enc_req.rand));
98269877
pdu_ctrl_tx->llctrl.enc_req.ediv[0] =
9827-
conn->llcp.encryption.ediv[0];
9878+
conn->llcp_enc.ediv[0];
98289879
pdu_ctrl_tx->llctrl.enc_req.ediv[1] =
9829-
conn->llcp.encryption.ediv[1];
9880+
conn->llcp_enc.ediv[1];
98309881

98319882
/*
98329883
* Take advantage of the fact that ivm and skdm fields, which both have
@@ -10632,6 +10683,11 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
1063210683
conn->llcp_terminate.reason_peer = 0U;
1063310684
conn->llcp_terminate.radio_pdu_node_rx.hdr.link = link;
1063410685

10686+
#if defined(CONFIG_BT_CTLR_LE_ENC)
10687+
conn->llcp_enc.req = 0U;
10688+
conn->llcp_enc.ack = 0U;
10689+
#endif /* CONFIG_BT_CTLR_LE_ENC */
10690+
1063510691
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
1063610692
conn->llcp_conn_param.req = 0U;
1063710693
conn->llcp_conn_param.ack = 0U;
@@ -11164,6 +11220,11 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
1116411220
conn->llcp_terminate.reason_peer = 0U;
1116511221
conn->llcp_terminate.radio_pdu_node_rx.hdr.link = link;
1116611222

11223+
#if defined(CONFIG_BT_CTLR_LE_ENC)
11224+
conn->llcp_enc.req = 0U;
11225+
conn->llcp_enc.ack = 0U;
11226+
#endif /* CONFIG_BT_CTLR_LE_ENC */
11227+
1116711228
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
1116811229
conn->llcp_conn_param.req = 0U;
1116911230
conn->llcp_conn_param.ack = 0U;
@@ -11387,12 +11448,7 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
1138711448
return BT_HCI_ERR_UNKNOWN_CONN_ID;
1138811449
}
1138911450

11390-
#if defined(CONFIG_BT_CTLR_PHY)
11391-
if ((conn->llcp_req != conn->llcp_ack) ||
11392-
(conn->llcp_phy.req != conn->llcp_phy.ack)) {
11393-
#else /* CONFIG_BT_CTLR_PHY */
11394-
if (conn->llcp_req != conn->llcp_ack) {
11395-
#endif /* CONFIG_BT_CTLR_PHY */
11451+
if (conn->llcp_enc.req != conn->llcp_enc.ack) {
1139611452
return BT_HCI_ERR_CMD_DISALLOWED;
1139711453
}
1139811454

@@ -11402,8 +11458,7 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
1140211458

1140311459
pdu_data_tx = (void *)node_tx->pdu_data;
1140411460

11405-
memcpy(&conn->llcp.encryption.ltk[0], ltk,
11406-
sizeof(conn->llcp.encryption.ltk));
11461+
memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk));
1140711462

1140811463
if ((conn->enc_rx == 0) && (conn->enc_tx == 0)) {
1140911464
struct pdu_data_llctrl_enc_req *enc_req;
@@ -11422,11 +11477,11 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
1142211477
bt_rand(enc_req->skdm, sizeof(enc_req->skdm));
1142311478
bt_rand(enc_req->ivm, sizeof(enc_req->ivm));
1142411479
} else if ((conn->enc_rx != 0) && (conn->enc_tx != 0)) {
11425-
memcpy(&conn->llcp.encryption.rand[0], rand,
11426-
sizeof(conn->llcp.encryption.rand));
11480+
memcpy(&conn->llcp_enc.rand[0], rand,
11481+
sizeof(conn->llcp_enc.rand));
1142711482

11428-
conn->llcp.encryption.ediv[0] = ediv[0];
11429-
conn->llcp.encryption.ediv[1] = ediv[1];
11483+
conn->llcp_enc.ediv[0] = ediv[0];
11484+
conn->llcp_enc.ediv[1] = ediv[1];
1143011485

1143111486
pdu_data_tx->ll_id = PDU_DATA_LLID_CTRL;
1143211487
pdu_data_tx->len = offsetof(struct pdu_data_llctrl,
@@ -11445,10 +11500,7 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
1144511500
return BT_HCI_ERR_CMD_DISALLOWED;
1144611501
}
1144711502

11448-
conn->llcp.encryption.initiate = 1U;
11449-
11450-
conn->llcp_type = LLCP_ENCRYPTION;
11451-
conn->llcp_req++;
11503+
conn->llcp_enc.req++;
1145211504

1145311505
return 0;
1145411506
}
@@ -11488,13 +11540,13 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
1148811540
conn->llcp_terminate.req++;
1148911541
}
1149011542
} else {
11491-
memcpy(&conn->llcp.encryption.ltk[0], ltk,
11492-
sizeof(conn->llcp.encryption.ltk));
11493-
1149411543
if (conn->llcp_req != conn->llcp_ack) {
1149511544
return BT_HCI_ERR_CMD_DISALLOWED;
1149611545
}
1149711546

11547+
memcpy(&conn->llcp_enc.ltk[0], ltk,
11548+
sizeof(conn->llcp_enc.ltk));
11549+
1149811550
conn->llcp.encryption.error_code = 0U;
1149911551
conn->llcp.encryption.initiate = 0U;
1150011552

subsys/bluetooth/controller/ll_sw/ctrl_internal.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,13 @@ struct connection {
164164
} phy_upd_ind;
165165
#endif /* CONFIG_BT_CTLR_PHY */
166166

167+
#if defined(CONFIG_BT_CTLR_LE_ENC)
167168
struct {
168169
u8_t initiate;
169170
u8_t error_code;
170-
u8_t rand[8];
171-
u8_t ediv[2];
172-
u8_t ltk[16];
173171
u8_t skd[16];
174172
} encryption;
173+
#endif /* CONFIG_BT_CTLR_LE_ENC */
175174
} llcp;
176175

177176
u32_t llcp_features;
@@ -195,6 +194,16 @@ struct connection {
195194
} radio_pdu_node_rx;
196195
} llcp_terminate;
197196

197+
#if defined(CONFIG_BT_CTLR_LE_ENC)
198+
struct {
199+
u8_t req;
200+
u8_t ack;
201+
u8_t ediv[2];
202+
u8_t rand[8];
203+
u8_t ltk[16];
204+
} llcp_enc;
205+
#endif /* CONFIG_BT_CTLR_LE_ENC */
206+
198207
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
199208
struct {
200209
u8_t req;

0 commit comments

Comments
 (0)