nimble/phy/nrf5x: Add workaround to allow encrypted ISO on nRF52840

nRF52840 does not allow to change mask for PDU header for keystream
generation, but we can workaround this by masking bits out manually and
then restoring original header byte after keystream is generated. This
only works for TX (e.g. ISO Broadcaster) but it may still be useful.
This commit is contained in:
Andrzej Kaczmarek
2023-02-02 23:25:32 +01:00
parent 5f7ca70628
commit f5c918d1b5
3 changed files with 57 additions and 0 deletions
+43
View File
@@ -140,6 +140,10 @@ struct ble_phy_obj
uint8_t phy_transition_late;
uint8_t phy_rx_started;
uint8_t phy_encrypted;
#if PHY_USE_HEADERMASK_WORKAROUND
uint8_t phy_headermask;
uint8_t phy_headerbyte;
#endif
uint8_t phy_privacy;
uint8_t phy_tx_pyld_len;
uint8_t phy_cur_phy_mode;
@@ -1517,6 +1521,20 @@ ble_phy_isr(void)
os_trace_isr_exit();
}
#if PHY_USE_HEADERMASK_WORKAROUND
static void
ble_phy_ccm_isr(void)
{
volatile uint8_t *tx_buf = (uint8_t *)g_ble_phy_tx_buf;
if (NRF_CCM->EVENTS_ENDKSGEN) {
while (tx_buf[0] == 0xff);
tx_buf[0] = g_ble_phy_data.phy_headerbyte;
NRF_CCM->INTENCLR = CCM_INTENCLR_ENDKSGEN_Msk;
}
}
#endif
/**
* ble phy init
*
@@ -1599,6 +1617,12 @@ ble_phy_init(void)
NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk;
NRF_CCM->EVENTS_ERROR = 0;
memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad));
#if PHY_USE_HEADERMASK_WORKAROUND
NVIC_SetVector(CCM_AAR_IRQn, (uint32_t)ble_phy_ccm_isr);
NVIC_EnableIRQ(CCM_AAR_IRQn);
NRF_CCM->INTENCLR = CCM_INTENCLR_ENDKSGEN_Msk;;
#endif
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
@@ -1703,6 +1727,9 @@ ble_phy_encrypt_enable(const uint8_t *key)
#ifdef NRF5340_XXAA
NRF_CCM->HEADERMASK = BLE_LL_PDU_HEADERMASK_DATA;
#endif
#if PHY_USE_HEADERMASK_WORKAROUND
g_ble_phy_data.phy_headermask = BLE_LL_PDU_HEADERMASK_DATA;
#endif
}
void
@@ -1711,6 +1738,9 @@ ble_phy_encrypt_header_mask_set(uint8_t mask)
#ifdef NRF5340_XXAA
NRF_CCM->HEADERMASK = mask;
#endif
#if PHY_USE_HEADERMASK_WORKAROUND
g_ble_phy_data.phy_headermask = mask;
#endif
}
void
@@ -1914,6 +1944,15 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans)
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
/* Start key-stream generation and encryption (via short) */
if (g_ble_phy_data.phy_encrypted) {
#if PHY_USE_HEADERMASK_WORKAROUND
if (g_ble_phy_data.phy_headermask != BLE_LL_PDU_HEADERMASK_DATA) {
g_ble_phy_data.phy_headerbyte = dptr[0];
dptr[0] &= g_ble_phy_data.phy_headermask;
g_ble_phy_tx_buf[0] = 0xffffffff;
NRF_CCM->EVENTS_ENDKSGEN = 0;
NRF_CCM->INTENSET = CCM_INTENSET_ENDKSGEN_Msk;
}
#endif
nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN);
}
#endif
@@ -2134,6 +2173,10 @@ ble_phy_disable(void)
{
ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE);
#if PHY_USE_HEADERMASK_WORKAROUND
NRF_CCM->INTENCLR = CCM_INTENCLR_ENDKSGEN_Msk;
#endif
ble_phy_stop_usec_timer();
ble_phy_disable_irq_and_ppi();
+5
View File
@@ -24,6 +24,11 @@
#include <nrf_gpio.h>
#include <nrf_gpiote.h>
#if defined(NRF52840_XXAA) && MYNEWT_VAL(BLE_PHY_NRF52_HEADERMASK_WORKAROUND)
#define PHY_USE_HEADERMASK_WORKAROUND 1
#endif
#define PHY_USE_DEBUG_1 (MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0)
#define PHY_USE_DEBUG_2 (MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0)
#define PHY_USE_DEBUG_3 (MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0)
+9
View File
@@ -55,6 +55,15 @@ syscfg.defs:
This can be used to check if wfr is calculated properly.
value: -1
BLE_PHY_NRF52_HEADERMASK_WORKAROUND:
description: >
This enables workaround for lack of HEADERMASK register on some
nRF52 family MCUs (notably nRF52840) which is required for enabling
encryption for ISO PDUs.
Note: this requires exclusive access to CCM_AAR interrupt and only
works for TX (i.e. ISO Broadcaster).
value: 0
BLE_PHY_UBLOX_BMD345_PUBLIC_ADDR:
description: >
Ublox BMD-345 modules come with public address preprogrammed