Skip to content

Commit

Permalink
drv/bluetooth: use nonresolvable private address
Browse files Browse the repository at this point in the history
This updates all Bluetooth drivers to use a nonresolvable private
address instead of a public address. This means that each time the
Bluetooth chip is reset, we get a new random address (or more often
on a properly implemented stack like btstack). This should help avoid
issues caused by OS Bluetooth stacks caching the device attribute
database which can change when firmware is updated.

Issue: pybricks/support#600
  • Loading branch information
dlech committed Oct 21, 2022
1 parent fd2a3d3 commit 1815b8e
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 36 deletions.
47 changes: 19 additions & 28 deletions lib/BlueNRG-MS/hci/hci_le.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,29 +250,30 @@ int hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup)
return status;
}

int hci_le_rand(uint8_t random_number[8])
void hci_le_rand_begin(void)
{
struct hci_request_and_response rq;
le_rand_rp resp;

memset(&resp, 0, sizeof(resp));
struct hci_request rq;

memset(&rq, 0, sizeof(rq));
rq.opcode = cmd_opcode_pack(OGF_LE_CTL, OCF_LE_RAND);
rq.cparam = NULL;
rq.clen = 0;
rq.rparam = &resp;
rq.rlen = LE_RAND_RP_SIZE;

hci_send_req_recv_rsp(&rq);
hci_send_req(&rq);
}

if (resp.status) {
return resp.status;
}
tBleStatus hci_le_rand_end(uint8_t *random_number)
{
struct hci_response rq;
le_rand_rp resp;

memcpy(random_number, resp.random, 8);
rq.rparam = &resp;
rq.rlen = sizeof(resp);

return 0;
hci_recv_resp(&rq);

memcpy(random_number, resp.random, sizeof(resp.random));

return resp.status;
}

void hci_le_set_scan_response_data_begin(uint8_t length, const uint8_t *data)
Expand Down Expand Up @@ -317,25 +318,15 @@ int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level)
return 0;
}

int hci_le_set_random_address(tBDAddr bdaddr)
void hci_le_set_random_address_begin(tBDAddr bdaddr)
{
struct hci_request_and_response rq;
le_set_random_address_cp set_rand_addr_cp;
uint8_t status;

memset(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp));
memcpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr));
struct hci_request rq;

memset(&rq, 0, sizeof(rq));
rq.opcode = cmd_opcode_pack(OGF_LE_CTL, OCF_LE_SET_RANDOM_ADDRESS);
rq.cparam = &set_rand_addr_cp;
rq.cparam = bdaddr;
rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE;
rq.rparam = &status;
rq.rlen = 1;

hci_send_req_recv_rsp(&rq);

return status;
hci_send_req(&rq);
}

int hci_read_bd_addr(tBDAddr bdaddr)
Expand Down
6 changes: 4 additions & 2 deletions lib/BlueNRG-MS/includes/hci_le.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,15 @@ void hci_le_set_advertising_data_begin(uint8_t length, const uint8_t *data);
void hci_le_set_scan_response_data_begin(uint8_t length, const uint8_t *data);
#define hci_le_set_scan_response_data_end hci_le_command_end

int hci_le_rand(uint8_t random_number[8]);
void hci_le_rand_begin(void);
tBleStatus hci_le_rand_end(uint8_t *random_number);

int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level);

int hci_acl_data(const uint8_t * data, uint16_t len);

int hci_le_set_random_address(tBDAddr bdaddr);
void hci_le_set_random_address_begin(tBDAddr bdaddr);
#define hci_le_set_random_address_end hci_le_command_end

int hci_read_bd_addr(tBDAddr bdaddr);

Expand Down
15 changes: 15 additions & 0 deletions lib/ble5stack/central/gap.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,21 @@ HCI_StatusCodes_t GapInit_cancelConnect(void)
return status;
}

HCI_StatusCodes_t GAP_ConfigDeviceAddr(Gap_initiatorAddrType_t addrType, const uint8_t *Addr)
{
uint8_t pData[7];

pData[0] = addrType;

if (Addr) {
memcpy(&pData[1], Addr, 6);
} else {
memset(&pData[1], 0, 6);
}

return HCI_sendHCICommand(GAP_CONFIG_DEVICE_ADDR, pData, 7);
}

HCI_StatusCodes_t GAP_DeviceDiscoveryRequest(Gap_deviceDiscoveryMode_t mode, uint8_t activeScan, Gap_filterPolicy_t filterPolicy)
{
uint8_t pData[3];
Expand Down
2 changes: 2 additions & 0 deletions lib/ble5stack/central/gap.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#define GAP_AUTHENTICATE 0xFE0B
#define GAP_TERMINATEAUTH 0xFE10
#define GAP_UPDATELINKPARAMREQ 0xFE11
#define GAP_CONFIG_DEVICE_ADDR 0xFE03
#define GAP_DEVICE_DISCOVERY_REQUEST 0xFE04
#define GAP_DEVICE_DISCOVERY_CANCEL 0xFE05
#define GAP_MAKE_DISCOVERABLE 0xFE06
Expand Down Expand Up @@ -1701,6 +1702,7 @@ extern HCI_StatusCodes_t GAP_SetParamValue(uint8_t paramID, uint16_t paramValue)
*/
extern HCI_StatusCodes_t GAP_GetParamValue(uint8_t paramID);

HCI_StatusCodes_t GAP_ConfigDeviceAddr(Gap_initiatorAddrType_t addrType, const uint8_t *Addr);

/*-------------------------------------------------------------------
* FUNCTIONS - Device Discovery
Expand Down
2 changes: 2 additions & 0 deletions lib/pbio/drv/bluetooth/bluetooth_btstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ void pbdrv_bluetooth_init(void) {
sm_set_er((uint8_t *)pdata->er_key);
sm_set_ir((uint8_t *)pdata->ir_key);

gap_random_address_set_mode(GAP_RANDOM_ADDRESS_NON_RESOLVABLE);

// GATT Client setup
gatt_client_init();

Expand Down
21 changes: 20 additions & 1 deletion lib/pbio/drv/bluetooth/bluetooth_stm32_bluenrg.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ static PT_THREAD(set_discoverable(struct pt *pt, pbio_task_t *task)) {
hci_le_set_scan_response_data_end();

PT_WAIT_WHILE(pt, write_xfer_size);
aci_gap_set_discoverable_begin(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE,
aci_gap_set_discoverable_begin(ADV_IND, 0, 0, RANDOM_ADDR, NO_WHITE_LIST_USE,
0, NULL, sizeof(service_uuids), service_uuids, 0, 0);
PT_WAIT_UNTIL(pt, hci_command_complete);
aci_gap_set_discoverable_end();
Expand Down Expand Up @@ -1128,6 +1128,25 @@ static PT_THREAD(hci_init(struct pt *pt)) {
PT_WAIT_UNTIL(pt, hci_command_complete);
aci_gatt_update_char_value_end();

// The chip always uses the same random address, so we have to generate
// an actually random one to get a new address each time. This must be
// called after aci_gap_init to take effect.

// STM32F0 doesn't have a random number generator, so we use the bluetooth
// chip to get some random bytes.
hci_le_rand_begin();
PT_WAIT_UNTIL(pt, hci_command_complete);
{
uint8_t rand_buf[8];
hci_le_rand_end(rand_buf);

// clear two msb to meet requirements of nonresolvable private address
rand_buf[5] &= 0x3F;
hci_le_set_random_address_begin(rand_buf);
}
PT_WAIT_UNTIL(pt, hci_command_complete);
hci_le_set_random_address_end();

PT_END(pt);
}

Expand Down
18 changes: 16 additions & 2 deletions lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ static uint16_t remote_handle = NO_CONNECTION;
// handle to LWP3 characteristic on remote
static uint16_t remote_lwp3_char_handle = NO_CONNECTION;

// The Identity Resolving Key read from the Bluetooth chip.
static uint8_t device_irk[16];
// GATT service handles
static uint16_t gatt_service_handle, gatt_service_end_handle;
// GAP service handles
Expand Down Expand Up @@ -317,7 +319,7 @@ static PT_THREAD(set_discoverable(struct pt *pt, pbio_task_t *task)) {
// make discoverable

PT_WAIT_WHILE(pt, write_xfer_size);
GAP_makeDiscoverable(ADV_IND, GAP_INITIATOR_ADDR_TYPE_PUBLIC, NULL,
GAP_makeDiscoverable(ADV_IND, GAP_INITIATOR_ADDR_TYPE_PRIVATE_NON_RESOLVE, NULL,
GAP_CHANNEL_MAP_ALL, GAP_FILTER_POLICY_SCAN_ANY_CONNECT_ANY);
PT_WAIT_UNTIL(pt, hci_command_complete);
// ignoring response data
Expand Down Expand Up @@ -1240,10 +1242,12 @@ static void handle_event(uint8_t *packet) {
advertising_data_received = true;
break;

case GAP_DEVICE_INIT_DONE:
memcpy(device_irk, &data[12], sizeof(device_irk));
__attribute__((fallthrough));
case HCI_EXT_SET_TX_POWER_EVENT:
case HCI_EXT_SET_LOCAL_SUPPORTED_FEATURES_EVENT:
case HCI_EXT_SET_BDADDR_EVENT:
case GAP_DEVICE_INIT_DONE:
case GAP_ADVERT_DATA_UPDATE_DONE:
case GAP_MAKE_DISCOVERABLE_DONE:
case GAP_END_DISCOVERABLE_DONE:
Expand Down Expand Up @@ -1472,6 +1476,16 @@ static PT_THREAD(gap_init(struct pt *pt)) {
PT_WAIT_UNTIL(pt, hci_command_complete);
// ignoring response data

// This sets the device address to a new random value each time we reset
// the Bluetooth chip. Since we don't support bonding, we use the IRK as
// our random value. The Bluetooth stack on the chip handles setting the
// correct bits for the address type.

PT_WAIT_WHILE(pt, write_xfer_size);
GAP_ConfigDeviceAddr(GAP_INITIATOR_ADDR_TYPE_PRIVATE_NON_RESOLVE, device_irk);
PT_WAIT_UNTIL(pt, hci_command_status);
// ignoring response data

PT_END(pt);
}

Expand Down
13 changes: 10 additions & 3 deletions lib/pbio/test/drv/bluetooth.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,8 @@ static void handle_send(const uint8_t *buffer, uint16_t length) {
case 0x2001: // LE Set Event Mask
queue_command_complete(opcode, 0x00);
break;
case 0x2017: // LE Encrypt - key 16, data 16
queue_command_complete(opcode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
case 0x2005: // LE Set Random Address
queue_command_complete(opcode, 0x00);
break;
case 0x2006: // LE Set Advertising Parameters
log_debug("advertising parameters, min %d, max %d, type 0x%02x, own addr type 0x%02x, peer addr type 0x%02x, peer addr %02x:%02x:%02x:%02x:%02x:%02x, chan map 0x%02x",
Expand All @@ -315,6 +314,14 @@ static void handle_send(const uint8_t *buffer, uint16_t length) {
case 0x200f: // LE Read White List Size
queue_command_complete(opcode, 0x00, 0x01);
break;
case 0x2017: // LE Encrypt - key 16, data 16
queue_command_complete(opcode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
break;
case 0x2018: // LE Rand
// not actual random for deterministic tests
queue_command_complete(opcode, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);
break;
case 0xff36: // HCI_VS_Update_UART_HCI_Baudrate
queue_command_complete(opcode, 0x00);
break;
Expand Down

0 comments on commit 1815b8e

Please sign in to comment.