Skip to content

Commit d6b8b4e

Browse files
committed
rp2: Enable BTstack pairing/bonding support.
BTstack automatically generates and manages ER/IR keys via TLV storage, providing secure pairing and bonding functionality without requiring manual key generation. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
1 parent 10afe83 commit d6b8b4e

File tree

3 files changed

+82
-14
lines changed

3 files changed

+82
-14
lines changed

extmod/btstack/modbluetooth_btstack.c

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ typedef struct _mp_btstack_active_connection_t {
115115
uint32_t last_encryption_update;
116116
} mp_btstack_active_connection_t;
117117

118+
#endif // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
119+
120+
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
121+
// Encryption state tracking to prevent duplicate events
122+
typedef struct _encryption_state_cache_t {
123+
btstack_linked_item_t *next; // Must be first field to match btstack_linked_item.
124+
125+
uint16_t conn_handle;
126+
bool is_encrypted;
127+
uint32_t last_update_ms;
128+
} encryption_state_cache_t;
129+
118130
static mp_btstack_active_connection_t *create_active_connection(uint16_t conn_handle) {
119131
DEBUG_printf("create_active_connection: conn_handle=%d\n", conn_handle);
120132
mp_btstack_active_connection_t *conn = m_new(mp_btstack_active_connection_t, 1);
@@ -160,6 +172,60 @@ static void remove_active_connection(uint16_t conn_handle) {
160172
}
161173
#endif
162174

175+
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
176+
// Encryption state management functions
177+
static encryption_state_cache_t *find_encryption_state(uint16_t conn_handle) {
178+
btstack_linked_list_iterator_t it;
179+
btstack_linked_list_iterator_init(&it, &MP_STATE_PORT(bluetooth_btstack_root_pointers)->encryption_states);
180+
encryption_state_cache_t *state = NULL;
181+
while (btstack_linked_list_iterator_has_next(&it)) {
182+
state = (encryption_state_cache_t *)btstack_linked_list_iterator_next(&it);
183+
if (state->conn_handle == conn_handle) {
184+
return state;
185+
}
186+
}
187+
return NULL;
188+
}
189+
190+
static encryption_state_cache_t *get_or_create_encryption_state(uint16_t conn_handle) {
191+
encryption_state_cache_t *state = find_encryption_state(conn_handle);
192+
if (!state) {
193+
state = m_new(encryption_state_cache_t, 1);
194+
state->conn_handle = conn_handle;
195+
state->is_encrypted = false;
196+
state->last_update_ms = 0;
197+
btstack_linked_list_add(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->encryption_states, (btstack_linked_item_t *)state);
198+
}
199+
return state;
200+
}
201+
202+
static void remove_encryption_state(uint16_t conn_handle) {
203+
encryption_state_cache_t *state = find_encryption_state(conn_handle);
204+
if (state) {
205+
btstack_linked_list_remove(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->encryption_states, (btstack_linked_item_t *)state);
206+
m_del(encryption_state_cache_t, state, 1);
207+
}
208+
}
209+
210+
static bool should_forward_encryption_event(uint16_t conn_handle, bool is_encrypted) {
211+
encryption_state_cache_t *state = get_or_create_encryption_state(conn_handle);
212+
uint32_t current_time = mp_hal_ticks_ms();
213+
214+
// Check if state has actually changed
215+
if (state->is_encrypted == is_encrypted) {
216+
// State hasn't changed - check if enough time has passed to allow duplicate
217+
if (current_time - state->last_update_ms < 1000) { // 1 second minimum
218+
return false; // Suppress duplicate event
219+
}
220+
}
221+
222+
// Update state and timestamp
223+
state->is_encrypted = is_encrypted;
224+
state->last_update_ms = current_time;
225+
return true; // Forward the event
226+
}
227+
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
228+
163229
// This needs to be separate to btstack_packet_handler otherwise we get
164230
// dual-delivery of the HCI_EVENT_LE_META event.
165231
static void btstack_packet_handler_att_server(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
@@ -339,8 +405,14 @@ static void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel
339405
}
340406
#endif
341407

342-
mp_bluetooth_gatts_on_encryption_update(conn_handle,
343-
encrypted, authenticated, bonded, desc->sm_actual_encryption_key_size);
408+
// Use encryption state cache to prevent duplicate events
409+
if (should_forward_encryption_event(conn_handle, encrypted)) {
410+
DEBUG_printf(" --> forwarding encryption event: encrypted=%d, authenticated=%d, bonded=%d\n", encrypted, authenticated, bonded);
411+
mp_bluetooth_gatts_on_encryption_update(conn_handle,
412+
encrypted, authenticated, bonded, desc->sm_actual_encryption_key_size);
413+
} else {
414+
DEBUG_printf(" --> suppressing duplicate encryption event for conn_handle=%d\n", conn_handle);
415+
}
344416
} else if (event_type == SM_EVENT_PASSKEY_DISPLAY_NUMBER) {
345417
mp_bluetooth_gap_on_passkey_action(sm_event_passkey_display_number_get_handle(packet), MP_BLUETOOTH_PASSKEY_ACTION_DISPLAY, sm_event_passkey_display_number_get_passkey(packet));
346418
} else if (event_type == SM_EVENT_PASSKEY_INPUT_NUMBER) {
@@ -365,6 +437,9 @@ static void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel
365437
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
366438
remove_active_connection(conn_handle);
367439
#endif
440+
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
441+
remove_encryption_state(conn_handle);
442+
#endif
368443
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
369444
} else if (event_type == GAP_EVENT_ADVERTISING_REPORT) {
370445
DEBUG_printf(" --> gap advertising report\n");
@@ -712,18 +787,7 @@ int mp_bluetooth_init(void) {
712787
le_device_db_init();
713788
sm_init();
714789

715-
// Set cryptographically secure ER/IR keys for bonding
716-
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
717-
// Use port-specific secure key generation
718-
extern void mp_bluetooth_btstack_port_set_er_ir_keys(void);
719-
mp_bluetooth_btstack_port_set_er_ir_keys();
720-
#else
721-
// Set blank ER/IR keys to suppress BTstack warning when pairing is disabled
722-
sm_key_t dummy_key;
723-
memset(dummy_key, 0, sizeof(dummy_key));
724-
sm_set_er(dummy_key);
725-
sm_set_ir(dummy_key);
726-
#endif
790+
// BTstack will automatically generate and store ER/IR keys via TLV when pairing is enabled
727791

728792
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
729793
gatt_client_init();

extmod/btstack/modbluetooth_btstack.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ typedef struct _mp_bluetooth_btstack_root_pointers_t {
4242
// Characteristic (and descriptor) value storage.
4343
mp_gatts_db_t gatts_db;
4444

45+
// Encryption state cache for all connections (prevents duplicate events).
46+
btstack_linked_list_t encryption_states;
47+
4548
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
4649
// Registration for notify/indicate events.
4750
gatt_client_notification_t notification;

ports/rp2/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ if(MICROPY_PY_BLUETOOTH)
332332
MICROPY_PY_BLUETOOTH=1
333333
MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
334334
MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1
335+
MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
335336
)
336337
endif()
337338

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy