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 <vich@nordicsemi.no>
This commit is contained in:
parent
0a892310d3
commit
48e5d9482a
3 changed files with 89 additions and 48 deletions
|
@ -2012,7 +2012,7 @@ static bool is_enc_req_pause_tx(struct ll_conn *conn)
|
|||
}
|
||||
|
||||
if (conn->llcp_req == conn->llcp_ack) {
|
||||
conn->llcp.encryption.initiate = 1U;
|
||||
conn->llcp.encryption.state = LLCP_ENC_STATE_INIT;
|
||||
|
||||
conn->llcp_type = LLCP_ENCRYPTION;
|
||||
conn->llcp_ack -= 2U;
|
||||
|
@ -2503,11 +2503,56 @@ static inline void event_enc_reject_prep(struct ll_conn *conn,
|
|||
|
||||
static inline void event_enc_prep(struct ll_conn *conn)
|
||||
{
|
||||
struct lll_conn *lll = &conn->lll;
|
||||
struct pdu_data *pdu_ctrl_tx;
|
||||
struct node_tx *tx;
|
||||
struct lll_conn *lll;
|
||||
|
||||
if (conn->llcp.encryption.initiate) {
|
||||
if (conn->llcp.encryption.state) {
|
||||
#if !defined(CONFIG_BT_CTLR_FAST_ENC)
|
||||
if (lll->role &&
|
||||
(conn->llcp.encryption.state == LLCP_ENC_STATE_INIT)) {
|
||||
struct node_rx_pdu *rx;
|
||||
struct pdu_data *pdu;
|
||||
u8_t err;
|
||||
|
||||
/* TODO BT Spec. text: may finalize the sending
|
||||
* of additional data channel PDUs queued in the
|
||||
* controller.
|
||||
*/
|
||||
err = enc_rsp_send(conn);
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* get a rx node for ULL->LL */
|
||||
rx = ll_pdu_rx_alloc();
|
||||
if (!rx) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* prepare enc req structure */
|
||||
rx->hdr.handle = conn->lll.handle;
|
||||
rx->hdr.type = NODE_RX_TYPE_DC_PDU;
|
||||
pdu = (void *)rx->pdu;
|
||||
pdu->ll_id = PDU_DATA_LLID_CTRL;
|
||||
pdu->len = offsetof(struct pdu_data_llctrl, enc_req) +
|
||||
sizeof(struct pdu_data_llctrl_enc_req);
|
||||
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ;
|
||||
memcpy(&pdu->llctrl.enc_req.rand[0],
|
||||
&conn->llcp_enc.rand[0],
|
||||
sizeof(pdu->llctrl.enc_req.rand));
|
||||
pdu->llctrl.enc_req.ediv[0] = conn->llcp_enc.ediv[0];
|
||||
pdu->llctrl.enc_req.ediv[1] = conn->llcp_enc.ediv[1];
|
||||
|
||||
/* enqueue enc req structure into rx queue */
|
||||
ll_rx_put(rx->hdr.link, rx);
|
||||
ll_rx_sched();
|
||||
|
||||
/* Wait for LTK reply */
|
||||
conn->llcp.encryption.state = LLCP_ENC_STATE_LTK_WAIT;
|
||||
}
|
||||
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2516,8 +2561,6 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
|||
return;
|
||||
}
|
||||
|
||||
lll = &conn->lll;
|
||||
|
||||
pdu_ctrl_tx = (void *)tx->pdu;
|
||||
|
||||
/* master sends encrypted enc start rsp in control priority */
|
||||
|
@ -2559,7 +2602,7 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
|||
#if defined(CONFIG_BT_CTLR_FAST_ENC)
|
||||
else {
|
||||
#else /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||
else if (!conn->llcp_enc.pause_tx || conn->llcp_enc.refresh) {
|
||||
else if (!lll->enc_rx) {
|
||||
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||
|
||||
/* place the reject ind packet as next in tx queue */
|
||||
|
@ -2570,22 +2613,6 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
|||
}
|
||||
/* place the start enc req packet as next in tx queue */
|
||||
else {
|
||||
|
||||
#if !defined(CONFIG_BT_CTLR_FAST_ENC)
|
||||
u8_t err;
|
||||
|
||||
/* TODO BT Spec. text: may finalize the sending
|
||||
* of additional data channel PDUs queued in the
|
||||
* controller.
|
||||
*/
|
||||
err = enc_rsp_send(conn);
|
||||
if (err) {
|
||||
mem_release(tx, &mem_conn_tx_ctrl.free);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||
|
||||
/* calc the Session Key */
|
||||
ecb_encrypt(&conn->llcp_enc.ltk[0],
|
||||
&conn->llcp.encryption.skd[0], NULL,
|
||||
|
@ -5146,8 +5173,28 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
if (nack) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Start Enc Req to be scheduled by LL api */
|
||||
conn->llcp.encryption.state = LLCP_ENC_STATE_LTK_WAIT;
|
||||
#else /* CONFIG_BT_CTLR_FAST_ENC */
|
||||
/* back up rand and ediv for deferred generation of Enc Req */
|
||||
memcpy(&conn->llcp_enc.rand[0],
|
||||
&pdu_rx->llctrl.enc_req.rand[0],
|
||||
sizeof(conn->llcp_enc.rand));
|
||||
conn->llcp_enc.ediv[0] = pdu_rx->llctrl.enc_req.ediv[0];
|
||||
conn->llcp_enc.ediv[1] = pdu_rx->llctrl.enc_req.ediv[1];
|
||||
|
||||
/* Enc rsp to be scheduled in master prepare */
|
||||
conn->llcp.encryption.state = LLCP_ENC_STATE_INIT;
|
||||
|
||||
/* Mark for buffer for release */
|
||||
(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
|
||||
#endif /* CONFIG_BT_CTLR_FAST_ENC */
|
||||
|
||||
/* Enc Setup state machine active */
|
||||
conn->llcp_type = LLCP_ENCRYPTION;
|
||||
conn->llcp_ack -= 2U;
|
||||
|
||||
/* things from master stored for session key calculation */
|
||||
memcpy(&conn->llcp.encryption.skd[0],
|
||||
&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,
|
|||
break;
|
||||
|
||||
case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ:
|
||||
if (conn->lll.role ||
|
||||
((conn->llcp_req != conn->llcp_ack) &&
|
||||
(conn->llcp_type != LLCP_ENCRYPTION)) ||
|
||||
if (conn->lll.role || (conn->llcp_req == conn->llcp_ack) ||
|
||||
(conn->llcp_type != LLCP_ENCRYPTION) ||
|
||||
!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_START_ENC_REQ,
|
||||
pdu_rx->len)) {
|
||||
goto ull_conn_rx_unknown_rsp_send;
|
||||
}
|
||||
|
||||
/* start enc rsp to be scheduled in master prepare */
|
||||
conn->llcp.encryption.initiate = 0U;
|
||||
if (conn->llcp_req == conn->llcp_ack) {
|
||||
conn->llcp_type = LLCP_ENCRYPTION;
|
||||
conn->llcp_ack -= 2U;
|
||||
}
|
||||
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
|
||||
|
||||
/* Mark for buffer for release */
|
||||
(*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,
|
|||
}
|
||||
|
||||
/* start enc rsp to be scheduled in slave prepare */
|
||||
conn->llcp.encryption.initiate = 0U;
|
||||
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
|
||||
if (conn->llcp_req == conn->llcp_ack) {
|
||||
conn->llcp_type = LLCP_ENCRYPTION;
|
||||
conn->llcp_ack -= 2U;
|
||||
}
|
||||
|
||||
#else /* CONFIG_BT_CTLR_FAST_ENC */
|
||||
nack = start_enc_rsp_send(conn, NULL);
|
||||
if (nack) {
|
||||
|
|
|
@ -119,7 +119,11 @@ struct ll_conn {
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
struct {
|
||||
u8_t initiate;
|
||||
enum {
|
||||
LLCP_ENC_STATE_INPROG,
|
||||
LLCP_ENC_STATE_INIT,
|
||||
LLCP_ENC_STATE_LTK_WAIT,
|
||||
} state:2 __packed;
|
||||
u8_t error_code;
|
||||
u8_t skd[16];
|
||||
} encryption;
|
||||
|
|
|
@ -386,7 +386,6 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
|
|||
u8_t const *const ltk)
|
||||
{
|
||||
struct ll_conn *conn;
|
||||
u8_t ret;
|
||||
|
||||
conn = ll_connected_get(handle);
|
||||
if (!conn) {
|
||||
|
@ -395,16 +394,13 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
|
|||
|
||||
if (error_code) {
|
||||
if (conn->llcp_enc.refresh == 0U) {
|
||||
ret = ull_conn_llcp_req(conn);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if ((conn->llcp_req == conn->llcp_ack) ||
|
||||
(conn->llcp_type != LLCP_ENCRYPTION)) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
conn->llcp.encryption.error_code = error_code;
|
||||
conn->llcp.encryption.initiate = 0U;
|
||||
|
||||
conn->llcp_type = LLCP_ENCRYPTION;
|
||||
conn->llcp_req++;
|
||||
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
|
||||
} else {
|
||||
if (conn->llcp_terminate.ack !=
|
||||
conn->llcp_terminate.req) {
|
||||
|
@ -416,18 +412,16 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
|
|||
conn->llcp_terminate.req++;
|
||||
}
|
||||
} else {
|
||||
ret = ull_conn_llcp_req(conn);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if ((conn->llcp_req == conn->llcp_ack) ||
|
||||
(conn->llcp_type != LLCP_ENCRYPTION)) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk));
|
||||
memcpy(&conn->llcp_enc.ltk[0], ltk,
|
||||
sizeof(conn->llcp_enc.ltk));
|
||||
|
||||
conn->llcp.encryption.error_code = 0U;
|
||||
conn->llcp.encryption.initiate = 0U;
|
||||
|
||||
conn->llcp_type = LLCP_ENCRYPTION;
|
||||
conn->llcp_req++;
|
||||
conn->llcp.encryption.state = LLCP_ENC_STATE_INPROG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue