Skip to content

Commit

Permalink
Bluetooth: Controller: Fix missing Broadcast ISO Sync MIC failure
Browse files Browse the repository at this point in the history
Fix missing implementation to handle Broadcast ISO MIC
failure during Broadcast ISO establishment, and during an
already established Broadcast ISO sync.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
  • Loading branch information
cvinayak authored and carlescufi committed Aug 26, 2024
1 parent d5da582 commit f05d16d
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 9 deletions.
52 changes: 45 additions & 7 deletions subsys/bluetooth/controller/ll_sw/nordic/lll/lll_sync_iso.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <soc.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/util.h>
#include <zephyr/bluetooth/hci_types.h>

#include "hal/cpu.h"
#include "hal/ccm.h"
Expand Down Expand Up @@ -435,6 +436,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
static void isr_rx_estab(void *param)
{
struct event_done_extra *e;
struct lll_sync_iso *lll;
uint8_t trx_done;
uint8_t crc_ok;

Expand All @@ -454,6 +456,36 @@ static void isr_rx_estab(void *param)
/* Clear radio rx status and events */
lll_isr_rx_status_reset();

/* Get reference to LLL context */
lll = param;

/* Check for MIC failures for encrypted Broadcast ISO streams */
if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) && crc_ok && lll->enc) {
struct node_rx_pdu *node_rx;
struct pdu_bis *pdu;

/* By design, there shall always be one free node rx available when setting up radio
* for new PDU reception.
*/
node_rx = ull_iso_pdu_rx_alloc_peek(1U);
LL_ASSERT(node_rx);

/* Get reference to received PDU and validate MIC for non-empty PDU */
pdu = (void *)node_rx->pdu;
if (pdu->len) {
bool mic_failure;
uint32_t done;

done = radio_ccm_is_done();
LL_ASSERT(done);

mic_failure = !radio_ccm_mic_is_valid();
if (mic_failure) {
lll->term_reason = BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
}
}
}

if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
lll_prof_cputime_capture();
}
Expand All @@ -463,14 +495,11 @@ static void isr_rx_estab(void *param)
LL_ASSERT(e);

e->type = EVENT_DONE_EXTRA_TYPE_SYNC_ISO_ESTAB;
e->estab_failed = 0U;
e->estab_failed = lll->term_reason ? 1U : 0U;
e->trx_cnt = trx_cnt;
e->crc_valid = crc_ok;

if (trx_cnt) {
struct lll_sync_iso *lll;

lll = param;
e->drift.preamble_to_addr_us = addr_us_get(lll->phy);
e->drift.start_to_address_actual_us =
radio_tmr_aa_get() - radio_tmr_ready_get();
Expand All @@ -492,7 +521,6 @@ static void isr_rx_estab(void *param)
static void isr_rx(void *param)
{
struct lll_sync_iso_stream *stream;
struct node_rx_pdu *node_rx;
struct lll_sync_iso *lll;
uint8_t access_addr[4];
uint16_t data_chan_id;
Expand Down Expand Up @@ -562,6 +590,7 @@ static void isr_rx(void *param)
/* Check CRC and generate ISO Data PDU */
if (crc_ok) {
struct lll_sync_iso_stream *sync_stream;
struct node_rx_pdu *node_rx;
uint32_t payload_offset;
uint16_t payload_index;
uint16_t stream_handle;
Expand Down Expand Up @@ -631,14 +660,18 @@ static void isr_rx(void *param)

if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) &&
lll->enc) {
uint32_t mic_failure;
bool mic_failure;
uint32_t done;

done = radio_ccm_is_done();
LL_ASSERT(done);

mic_failure = !radio_ccm_mic_is_valid();
LL_ASSERT(!mic_failure);
if (mic_failure) {
lll->term_reason = BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;

goto isr_rx_mic_failure;
}
}

ull_iso_pdu_rx_alloc();
Expand Down Expand Up @@ -893,6 +926,7 @@ static void isr_rx(void *param)
goto isr_rx_next_subevent;
}

isr_rx_mic_failure:
isr_rx_done(param);

if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
Expand Down Expand Up @@ -972,6 +1006,8 @@ static void isr_rx(void *param)

payload_count = lll->payload_count - lll->bn;
if (bis) {
struct node_rx_pdu *node_rx;

payload_count += (lll->bn_curr - 1U) +
(lll->ptc_curr * lll->pto);

Expand Down Expand Up @@ -1000,6 +1036,8 @@ static void isr_rx(void *param)
struct pdu_bis *pdu;

if (bis) {
struct node_rx_pdu *node_rx;

/* By design, there shall always be one free node rx
* available for setting up radio for new PDU reception.
*/
Expand Down
12 changes: 10 additions & 2 deletions subsys/bluetooth/controller/ll_sw/ull_sync_iso.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,17 @@ void ull_sync_iso_estab_done(struct node_rx_event_done *done)
rx->hdr.handle = sync_iso_handle_get(sync_iso);
rx->rx_ftr.param = sync_iso;

/* status value is stored in the PDU member of the node rx */
se = (void *)rx->pdu;
se->status = done->extra.estab_failed ?
BT_HCI_ERR_CONN_FAIL_TO_ESTAB : BT_HCI_ERR_SUCCESS;
if (done->extra.estab_failed) {
if (sync_iso->lll.term_reason != BT_HCI_ERR_SUCCESS) {
se->status = sync_iso->lll.term_reason;
} else {
se->status = BT_HCI_ERR_CONN_FAIL_TO_ESTAB;
}
} else {
se->status = BT_HCI_ERR_SUCCESS;
}

ll_rx_put_sched(rx->hdr.link, rx);
}
Expand Down

0 comments on commit f05d16d

Please sign in to comment.