Bluetooth: controller: Handle invalid enc. pause

Reject LL_PAUSE_ENC_REQ while the ACL is associated with a CIS that is
created.

Signed-off-by: Thomas Ebert Hansen <thoh@oticon.com>
This commit is contained in:
Thomas Ebert Hansen 2023-07-21 16:13:30 +02:00 committed by Carles Cufí
commit 8ae2eb53dc

View file

@ -705,10 +705,10 @@ static struct node_tx *llcp_rp_enc_tx(struct ll_conn *conn, struct proc_ctx *ctx
break;
case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
if (conn->llcp.fex.valid && feature_ext_rej_ind(conn)) {
llcp_pdu_encode_reject_ext_ind(pdu, PDU_DATA_LLCTRL_TYPE_ENC_REQ,
BT_HCI_ERR_PIN_OR_KEY_MISSING);
llcp_pdu_encode_reject_ext_ind(pdu, ctx->reject_ext_ind.reject_opcode,
ctx->reject_ext_ind.error_code);
} else {
llcp_pdu_encode_reject_ind(pdu, BT_HCI_ERR_PIN_OR_KEY_MISSING);
llcp_pdu_encode_reject_ind(pdu, ctx->reject_ext_ind.error_code);
}
break;
default:
@ -842,14 +842,30 @@ static void rp_enc_send_reject_ind(struct ll_conn *conn, struct proc_ctx *ctx, u
} else {
llcp_rp_enc_tx(conn, ctx, PDU_DATA_LLCTRL_TYPE_REJECT_IND);
llcp_rr_complete(conn);
ctx->state = RP_ENC_STATE_UNENCRYPTED;
/* Resume Tx data */
llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_ENCRYPTION);
/* Resume Rx data */
ull_conn_resume_rx_data(conn);
/* Resume possibly paused local procedure */
llcp_lr_resume(conn);
if (ctx->data.enc.error == BT_HCI_ERR_PIN_OR_KEY_MISSING) {
/* Start encryption rejected due to missing key.
*
* Resume paused data and local procedures.
*/
ctx->state = RP_ENC_STATE_UNENCRYPTED;
/* Resume Tx data */
llcp_tx_resume_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_ENCRYPTION);
/* Resume Rx data */
ull_conn_resume_rx_data(conn);
/* Resume possibly paused local procedure */
llcp_lr_resume(conn);
} else if (ctx->data.enc.error == BT_HCI_ERR_LMP_PDU_NOT_ALLOWED) {
/* Pause encryption rejected due to invalid behaviour.
*
* Nothing special needs to be done.
*/
} else {
/* Shouldn't happen */
LL_ASSERT(0);
}
}
}
@ -968,6 +984,9 @@ static void rp_enc_state_wait_ltk_reply(struct ll_conn *conn, struct proc_ctx *c
rp_enc_send_start_enc_req(conn, ctx, evt, param);
break;
case RP_ENC_EVT_LTK_REQ_NEG_REPLY:
ctx->data.enc.error = BT_HCI_ERR_PIN_OR_KEY_MISSING;
ctx->reject_ext_ind.reject_opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ;
ctx->reject_ext_ind.error_code = BT_HCI_ERR_PIN_OR_KEY_MISSING;
rp_enc_send_reject_ind(conn, ctx, evt, param);
break;
default:
@ -1046,6 +1065,26 @@ static void rp_enc_state_wait_rx_pause_enc_req(struct ll_conn *conn, struct proc
{
switch (evt) {
case RP_ENC_EVT_PAUSE_ENC_REQ:
#if defined(CONFIG_BT_CTLR_PERIPHERAL_ISO)
{
/* Central is not allowed to send a LL_PAUSE_ENC_REQ while the ACL is
* associated with a CIS that has been created.
*
* Handle this invalid case, by rejecting.
*/
struct ll_conn_iso_stream *cis = ll_conn_iso_stream_get_by_acl(conn, NULL);
if (cis) {
ctx->data.enc.error = BT_HCI_ERR_LMP_PDU_NOT_ALLOWED;
ctx->reject_ext_ind.reject_opcode =
PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ;
ctx->reject_ext_ind.error_code = BT_HCI_ERR_LMP_PDU_NOT_ALLOWED;
rp_enc_send_reject_ind(conn, ctx, evt, param);
break;
}
}
#endif /* CONFIG_BT_CTLR_PERIPHERAL_ISO */
/* Pause Tx data */
llcp_tx_pause_data(conn, LLCP_TX_QUEUE_PAUSE_DATA_ENCRYPTION);
/*