Skip to content

Commit 1815b8e

Browse files
committed
drv/bluetooth: use nonresolvable private address
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
1 parent fd2a3d3 commit 1815b8e

File tree

8 files changed

+88
-36
lines changed

8 files changed

+88
-36
lines changed

lib/BlueNRG-MS/hci/hci_le.c

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -250,29 +250,30 @@ int hci_le_set_scan_enable(uint8_t enable, uint8_t filter_dup)
250250
return status;
251251
}
252252

253-
int hci_le_rand(uint8_t random_number[8])
253+
void hci_le_rand_begin(void)
254254
{
255-
struct hci_request_and_response rq;
256-
le_rand_rp resp;
257-
258-
memset(&resp, 0, sizeof(resp));
255+
struct hci_request rq;
259256

260-
memset(&rq, 0, sizeof(rq));
261257
rq.opcode = cmd_opcode_pack(OGF_LE_CTL, OCF_LE_RAND);
262258
rq.cparam = NULL;
263259
rq.clen = 0;
264-
rq.rparam = &resp;
265-
rq.rlen = LE_RAND_RP_SIZE;
266260

267-
hci_send_req_recv_rsp(&rq);
261+
hci_send_req(&rq);
262+
}
268263

269-
if (resp.status) {
270-
return resp.status;
271-
}
264+
tBleStatus hci_le_rand_end(uint8_t *random_number)
265+
{
266+
struct hci_response rq;
267+
le_rand_rp resp;
272268

273-
memcpy(random_number, resp.random, 8);
269+
rq.rparam = &resp;
270+
rq.rlen = sizeof(resp);
274271

275-
return 0;
272+
hci_recv_resp(&rq);
273+
274+
memcpy(random_number, resp.random, sizeof(resp.random));
275+
276+
return resp.status;
276277
}
277278

278279
void hci_le_set_scan_response_data_begin(uint8_t length, const uint8_t *data)
@@ -317,25 +318,15 @@ int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level)
317318
return 0;
318319
}
319320

320-
int hci_le_set_random_address(tBDAddr bdaddr)
321+
void hci_le_set_random_address_begin(tBDAddr bdaddr)
321322
{
322-
struct hci_request_and_response rq;
323-
le_set_random_address_cp set_rand_addr_cp;
324-
uint8_t status;
325-
326-
memset(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp));
327-
memcpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr));
323+
struct hci_request rq;
328324

329-
memset(&rq, 0, sizeof(rq));
330325
rq.opcode = cmd_opcode_pack(OGF_LE_CTL, OCF_LE_SET_RANDOM_ADDRESS);
331-
rq.cparam = &set_rand_addr_cp;
326+
rq.cparam = bdaddr;
332327
rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE;
333-
rq.rparam = &status;
334-
rq.rlen = 1;
335328

336-
hci_send_req_recv_rsp(&rq);
337-
338-
return status;
329+
hci_send_req(&rq);
339330
}
340331

341332
int hci_read_bd_addr(tBDAddr bdaddr)

lib/BlueNRG-MS/includes/hci_le.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,15 @@ void hci_le_set_advertising_data_begin(uint8_t length, const uint8_t *data);
134134
void hci_le_set_scan_response_data_begin(uint8_t length, const uint8_t *data);
135135
#define hci_le_set_scan_response_data_end hci_le_command_end
136136

137-
int hci_le_rand(uint8_t random_number[8]);
137+
void hci_le_rand_begin(void);
138+
tBleStatus hci_le_rand_end(uint8_t *random_number);
138139

139140
int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level);
140141

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

143-
int hci_le_set_random_address(tBDAddr bdaddr);
144+
void hci_le_set_random_address_begin(tBDAddr bdaddr);
145+
#define hci_le_set_random_address_end hci_le_command_end
144146

145147
int hci_read_bd_addr(tBDAddr bdaddr);
146148

lib/ble5stack/central/gap.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,21 @@ HCI_StatusCodes_t GapInit_cancelConnect(void)
172172
return status;
173173
}
174174

175+
HCI_StatusCodes_t GAP_ConfigDeviceAddr(Gap_initiatorAddrType_t addrType, const uint8_t *Addr)
176+
{
177+
uint8_t pData[7];
178+
179+
pData[0] = addrType;
180+
181+
if (Addr) {
182+
memcpy(&pData[1], Addr, 6);
183+
} else {
184+
memset(&pData[1], 0, 6);
185+
}
186+
187+
return HCI_sendHCICommand(GAP_CONFIG_DEVICE_ADDR, pData, 7);
188+
}
189+
175190
HCI_StatusCodes_t GAP_DeviceDiscoveryRequest(Gap_deviceDiscoveryMode_t mode, uint8_t activeScan, Gap_filterPolicy_t filterPolicy)
176191
{
177192
uint8_t pData[3];

lib/ble5stack/central/gap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#define GAP_AUTHENTICATE 0xFE0B
5858
#define GAP_TERMINATEAUTH 0xFE10
5959
#define GAP_UPDATELINKPARAMREQ 0xFE11
60+
#define GAP_CONFIG_DEVICE_ADDR 0xFE03
6061
#define GAP_DEVICE_DISCOVERY_REQUEST 0xFE04
6162
#define GAP_DEVICE_DISCOVERY_CANCEL 0xFE05
6263
#define GAP_MAKE_DISCOVERABLE 0xFE06
@@ -1701,6 +1702,7 @@ extern HCI_StatusCodes_t GAP_SetParamValue(uint8_t paramID, uint16_t paramValue)
17011702
*/
17021703
extern HCI_StatusCodes_t GAP_GetParamValue(uint8_t paramID);
17031704

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

17051707
/*-------------------------------------------------------------------
17061708
* FUNCTIONS - Device Discovery

lib/pbio/drv/bluetooth/bluetooth_btstack.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,8 @@ void pbdrv_bluetooth_init(void) {
425425
sm_set_er((uint8_t *)pdata->er_key);
426426
sm_set_ir((uint8_t *)pdata->ir_key);
427427

428+
gap_random_address_set_mode(GAP_RANDOM_ADDRESS_NON_RESOLVABLE);
429+
428430
// GATT Client setup
429431
gatt_client_init();
430432

lib/pbio/drv/bluetooth/bluetooth_stm32_bluenrg.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ static PT_THREAD(set_discoverable(struct pt *pt, pbio_task_t *task)) {
269269
hci_le_set_scan_response_data_end();
270270

271271
PT_WAIT_WHILE(pt, write_xfer_size);
272-
aci_gap_set_discoverable_begin(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE,
272+
aci_gap_set_discoverable_begin(ADV_IND, 0, 0, RANDOM_ADDR, NO_WHITE_LIST_USE,
273273
0, NULL, sizeof(service_uuids), service_uuids, 0, 0);
274274
PT_WAIT_UNTIL(pt, hci_command_complete);
275275
aci_gap_set_discoverable_end();
@@ -1128,6 +1128,25 @@ static PT_THREAD(hci_init(struct pt *pt)) {
11281128
PT_WAIT_UNTIL(pt, hci_command_complete);
11291129
aci_gatt_update_char_value_end();
11301130

1131+
// The chip always uses the same random address, so we have to generate
1132+
// an actually random one to get a new address each time. This must be
1133+
// called after aci_gap_init to take effect.
1134+
1135+
// STM32F0 doesn't have a random number generator, so we use the bluetooth
1136+
// chip to get some random bytes.
1137+
hci_le_rand_begin();
1138+
PT_WAIT_UNTIL(pt, hci_command_complete);
1139+
{
1140+
uint8_t rand_buf[8];
1141+
hci_le_rand_end(rand_buf);
1142+
1143+
// clear two msb to meet requirements of nonresolvable private address
1144+
rand_buf[5] &= 0x3F;
1145+
hci_le_set_random_address_begin(rand_buf);
1146+
}
1147+
PT_WAIT_UNTIL(pt, hci_command_complete);
1148+
hci_le_set_random_address_end();
1149+
11311150
PT_END(pt);
11321151
}
11331152

lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ static uint16_t remote_handle = NO_CONNECTION;
129129
// handle to LWP3 characteristic on remote
130130
static uint16_t remote_lwp3_char_handle = NO_CONNECTION;
131131

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

319321
PT_WAIT_WHILE(pt, write_xfer_size);
320-
GAP_makeDiscoverable(ADV_IND, GAP_INITIATOR_ADDR_TYPE_PUBLIC, NULL,
322+
GAP_makeDiscoverable(ADV_IND, GAP_INITIATOR_ADDR_TYPE_PRIVATE_NON_RESOLVE, NULL,
321323
GAP_CHANNEL_MAP_ALL, GAP_FILTER_POLICY_SCAN_ANY_CONNECT_ANY);
322324
PT_WAIT_UNTIL(pt, hci_command_complete);
323325
// ignoring response data
@@ -1240,10 +1242,12 @@ static void handle_event(uint8_t *packet) {
12401242
advertising_data_received = true;
12411243
break;
12421244

1245+
case GAP_DEVICE_INIT_DONE:
1246+
memcpy(device_irk, &data[12], sizeof(device_irk));
1247+
__attribute__((fallthrough));
12431248
case HCI_EXT_SET_TX_POWER_EVENT:
12441249
case HCI_EXT_SET_LOCAL_SUPPORTED_FEATURES_EVENT:
12451250
case HCI_EXT_SET_BDADDR_EVENT:
1246-
case GAP_DEVICE_INIT_DONE:
12471251
case GAP_ADVERT_DATA_UPDATE_DONE:
12481252
case GAP_MAKE_DISCOVERABLE_DONE:
12491253
case GAP_END_DISCOVERABLE_DONE:
@@ -1472,6 +1476,16 @@ static PT_THREAD(gap_init(struct pt *pt)) {
14721476
PT_WAIT_UNTIL(pt, hci_command_complete);
14731477
// ignoring response data
14741478

1479+
// This sets the device address to a new random value each time we reset
1480+
// the Bluetooth chip. Since we don't support bonding, we use the IRK as
1481+
// our random value. The Bluetooth stack on the chip handles setting the
1482+
// correct bits for the address type.
1483+
1484+
PT_WAIT_WHILE(pt, write_xfer_size);
1485+
GAP_ConfigDeviceAddr(GAP_INITIATOR_ADDR_TYPE_PRIVATE_NON_RESOLVE, device_irk);
1486+
PT_WAIT_UNTIL(pt, hci_command_status);
1487+
// ignoring response data
1488+
14751489
PT_END(pt);
14761490
}
14771491

lib/pbio/test/drv/bluetooth.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,8 @@ static void handle_send(const uint8_t *buffer, uint16_t length) {
287287
case 0x2001: // LE Set Event Mask
288288
queue_command_complete(opcode, 0x00);
289289
break;
290-
case 0x2017: // LE Encrypt - key 16, data 16
291-
queue_command_complete(opcode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
290+
case 0x2005: // LE Set Random Address
291+
queue_command_complete(opcode, 0x00);
293292
break;
294293
case 0x2006: // LE Set Advertising Parameters
295294
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",
@@ -315,6 +314,14 @@ static void handle_send(const uint8_t *buffer, uint16_t length) {
315314
case 0x200f: // LE Read White List Size
316315
queue_command_complete(opcode, 0x00, 0x01);
317316
break;
317+
case 0x2017: // LE Encrypt - key 16, data 16
318+
queue_command_complete(opcode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
320+
break;
321+
case 0x2018: // LE Rand
322+
// not actual random for deterministic tests
323+
queue_command_complete(opcode, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);
324+
break;
318325
case 0xff36: // HCI_VS_Update_UART_HCI_Baudrate
319326
queue_command_complete(opcode, 0x00);
320327
break;

0 commit comments

Comments
 (0)