From 6634fea2399f22294da3b6320352699a509572a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20D=C3=B6rre?= Date: Sat, 8 Apr 2023 21:42:40 +0000 Subject: [PATCH] extmod/btstack: Implement key storage to enable pairing/bonding. Btstack offers two abstraction layers for secret storage, one called "device db" and another called "tlv". Pairing information is stored in the "device db", additional secrets (like own keys) are stored directly in the tlv. Luckily there is a "device db" implementation using tlv, so we only need to provide one interface. Additionally, I've removed some btstack files from compilation that were not referenced. --- extmod/btstack/btstack.cmake | 42 +++++++-------- extmod/btstack/btstack.mk | 2 +- extmod/btstack/btstack_config_common.h | 2 +- extmod/btstack/modbluetooth_btstack.c | 71 +++++++++++++++++++++++--- ports/rp2/CMakeLists.txt | 1 + 5 files changed, 89 insertions(+), 29 deletions(-) diff --git a/extmod/btstack/btstack.cmake b/extmod/btstack/btstack.cmake index dd416fcbfb..2b3310f4e8 100644 --- a/extmod/btstack/btstack.cmake +++ b/extmod/btstack/btstack.cmake @@ -16,45 +16,45 @@ target_include_directories(micropy_extmod_btstack INTERFACE target_sources(micropy_extmod_btstack INTERFACE ${BTSTACK_LIB_DIR}/platform/embedded/hci_dump_embedded_stdout.c - ${BTSTACK_LIB_DIR}/src/ad_parser.c + #${BTSTACK_LIB_DIR}/src/ad_parser.c ${BTSTACK_LIB_DIR}/src/ble/gatt-service/ancs_client.c ${BTSTACK_LIB_DIR}/src/ble/att_db.c ${BTSTACK_LIB_DIR}/src/ble/att_db_util.c ${BTSTACK_LIB_DIR}/src/ble/att_dispatch.c ${BTSTACK_LIB_DIR}/src/ble/att_server.c - ${BTSTACK_LIB_DIR}/src/ble/gatt-service/battery_service_server.c - ${BTSTACK_LIB_DIR}/src/ble/gatt-service/cycling_power_service_server.c - ${BTSTACK_LIB_DIR}/src/ble/gatt-service/cycling_speed_and_cadence_service_server.c - ${BTSTACK_LIB_DIR}/src/ble/gatt-service/device_information_service_server.c - ${BTSTACK_LIB_DIR}/src/ble/gatt-service/heart_rate_service_server.c - ${BTSTACK_LIB_DIR}/src/ble/gatt-service/hids_device.c - ${BTSTACK_LIB_DIR}/src/mesh/gatt-service/mesh_provisioning_service_server.c - ${BTSTACK_LIB_DIR}/src/mesh/gatt-service/mesh_proxy_service_server.c - ${BTSTACK_LIB_DIR}/src/ble/gatt-service/nordic_spp_service_server.c - ${BTSTACK_LIB_DIR}/src/ble/gatt-service/ublox_spp_service_server.c + #${BTSTACK_LIB_DIR}/src/ble/gatt-service/battery_service_server.c + #${BTSTACK_LIB_DIR}/src/ble/gatt-service/cycling_power_service_server.c + #${BTSTACK_LIB_DIR}/src/ble/gatt-service/cycling_speed_and_cadence_service_server.c + #${BTSTACK_LIB_DIR}/src/ble/gatt-service/device_information_service_server.c + #${BTSTACK_LIB_DIR}/src/ble/gatt-service/heart_rate_service_server.c + #${BTSTACK_LIB_DIR}/src/ble/gatt-service/hids_device.c + #${BTSTACK_LIB_DIR}/src/mesh/gatt-service/mesh_provisioning_service_server.c + #${BTSTACK_LIB_DIR}/src/mesh/gatt-service/mesh_proxy_service_server.c + #${BTSTACK_LIB_DIR}/src/ble/gatt-service/nordic_spp_service_server.c + #${BTSTACK_LIB_DIR}/src/ble/gatt-service/ublox_spp_service_server.c ${BTSTACK_LIB_DIR}/src/ble/gatt_client.c - ${BTSTACK_LIB_DIR}/src/ble/le_device_db_memory.c + ${BTSTACK_LIB_DIR}/src/ble/le_device_db_tlv.c ${BTSTACK_LIB_DIR}/src/ble/sm.c - ${BTSTACK_LIB_DIR}/src/btstack_audio.c - ${BTSTACK_LIB_DIR}/src/btstack_base64_decoder.c + #${BTSTACK_LIB_DIR}/src/btstack_audio.c + #${BTSTACK_LIB_DIR}/src/btstack_base64_decoder.c ${BTSTACK_LIB_DIR}/src/btstack_crypto.c - ${BTSTACK_LIB_DIR}/src/btstack_hid_parser.c + #${BTSTACK_LIB_DIR}/src/btstack_hid_parser.c ${BTSTACK_LIB_DIR}/src/btstack_linked_list.c ${BTSTACK_LIB_DIR}/src/btstack_memory.c ${BTSTACK_LIB_DIR}/src/btstack_memory_pool.c - ${BTSTACK_LIB_DIR}/src/btstack_resample.c - ${BTSTACK_LIB_DIR}/src/btstack_ring_buffer.c + #${BTSTACK_LIB_DIR}/src/btstack_resample.c + #${BTSTACK_LIB_DIR}/src/btstack_ring_buffer.c ${BTSTACK_LIB_DIR}/src/btstack_run_loop.c ${BTSTACK_LIB_DIR}/src/btstack_run_loop_base.c - ${BTSTACK_LIB_DIR}/src/btstack_slip.c + #${BTSTACK_LIB_DIR}/src/btstack_slip.c ${BTSTACK_LIB_DIR}/src/btstack_tlv.c - ${BTSTACK_LIB_DIR}/src/btstack_tlv_none.c + #${BTSTACK_LIB_DIR}/src/btstack_tlv_none.c ${BTSTACK_LIB_DIR}/src/btstack_util.c ${BTSTACK_LIB_DIR}/src/hci.c ${BTSTACK_LIB_DIR}/src/hci_cmd.c ${BTSTACK_LIB_DIR}/src/hci_dump.c - ${BTSTACK_LIB_DIR}/src/hci_transport_em9304_spi.c - ${BTSTACK_LIB_DIR}/src/hci_transport_h4.c + #${BTSTACK_LIB_DIR}/src/hci_transport_em9304_spi.c + #${BTSTACK_LIB_DIR}/src/hci_transport_h4.c ${BTSTACK_LIB_DIR}/src/l2cap.c ${BTSTACK_LIB_DIR}/src/l2cap_signaling.c ) diff --git a/extmod/btstack/btstack.mk b/extmod/btstack/btstack.mk index 281d032ae1..fe5f1a6c5a 100644 --- a/extmod/btstack/btstack.mk +++ b/extmod/btstack/btstack.mk @@ -34,7 +34,7 @@ INC += -I$(BTSTACK_DIR)/3rd-party/yxml SRC_BTSTACK_C = \ $(addprefix lib/btstack/src/, $(SRC_FILES)) \ - $(addprefix lib/btstack/src/ble/, $(filter-out %_tlv.c, $(SRC_BLE_FILES))) \ + $(addprefix lib/btstack/src/ble/, $(filter-out le_device_db_memory.c, $(SRC_BLE_FILES))) \ lib/btstack/platform/embedded/hci_dump_embedded_stdout.c \ ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1) diff --git a/extmod/btstack/btstack_config_common.h b/extmod/btstack/btstack_config_common.h index 0f616f7505..d08b36eca1 100644 --- a/extmod/btstack/btstack_config_common.h +++ b/extmod/btstack/btstack_config_common.h @@ -35,7 +35,7 @@ #define MAX_NR_LE_DEVICE_DB_ENTRIES 4 // Link Key DB and LE Device DB using TLV on top of Flash Sector interface -// #define NVM_NUM_DEVICE_DB_ENTRIES 16 +#define NVM_NUM_DEVICE_DB_ENTRIES 16 // We don't give btstack a malloc, so use a fixed-size ATT DB. #define MAX_ATT_DB_SIZE 512 diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index 8f65e26dcc..b30ad555cf 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -34,6 +34,8 @@ #include "extmod/modbluetooth.h" #include "lib/btstack/src/btstack.h" +#include "lib/btstack/src/ble/le_device_db_tlv.h" +#include "lib/btstack/src/btstack_tlv.h" #define DEBUG_printf(...) // printf("btstack: " __VA_ARGS__) @@ -300,6 +302,12 @@ static void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel desc->sm_connection_authenticated, desc->sm_le_db_index != -1, desc->sm_actual_encryption_key_size); + } else if (event_type == SM_EVENT_PASSKEY_DISPLAY_NUMBER) { + 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)); + } else if (event_type == SM_EVENT_PASSKEY_INPUT_NUMBER) { + mp_bluetooth_gap_on_passkey_action(sm_event_passkey_input_number_get_handle(packet), MP_BLUETOOTH_PASSKEY_ACTION_INPUT, 0); + } else if (event_type == SM_EVENT_NUMERIC_COMPARISON_REQUEST) { + mp_bluetooth_gap_on_passkey_action(sm_event_numeric_comparison_request_get_handle(packet), MP_BLUETOOTH_PASSKEY_ACTION_NUMERIC_COMPARISON, sm_event_numeric_comparison_request_get_passkey(packet)); #endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING } else if (event_type == HCI_EVENT_DISCONNECTION_COMPLETE) { DEBUG_printf(" --> hci disconnect complete\n"); @@ -372,7 +380,10 @@ static void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel } } -static btstack_packet_callback_registration_t hci_event_callback_registration = { +static btstack_packet_callback_registration_t mp_hci_event_callback_registration = { + .callback = &btstack_packet_handler_generic +}; +static btstack_packet_callback_registration_t mp_sm_event_callback_registration = { .callback = &btstack_packet_handler_generic }; @@ -590,10 +601,13 @@ static void deinit_stack(void) { hci_deinit(); btstack_memory_deinit(); btstack_run_loop_deinit(); + btstack_crypto_deinit(); MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL; } +static const btstack_tlv_t btstack_tlv_mp; + int mp_bluetooth_init(void) { DEBUG_printf("mp_bluetooth_init\n"); @@ -623,6 +637,8 @@ int mp_bluetooth_init(void) { mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_STARTING; l2cap_init(); + btstack_tlv_set_instance(&btstack_tlv_mp, NULL); + le_device_db_tlv_configure(&btstack_tlv_mp, NULL); le_device_db_init(); sm_init(); @@ -641,7 +657,9 @@ int mp_bluetooth_init(void) { #endif // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT // Register for HCI events. - hci_add_event_handler(&hci_event_callback_registration); + hci_add_event_handler(&mp_hci_event_callback_registration); + + sm_add_event_handler(&mp_sm_event_callback_registration); // Register for ATT server events. att_server_register_packet_handler(&btstack_packet_handler_att_server); @@ -771,10 +789,14 @@ void mp_bluetooth_set_address_mode(uint8_t addr_mode) { set_random_address(); break; } - case MP_BLUETOOTH_ADDRESS_MODE_RPA: - case MP_BLUETOOTH_ADDRESS_MODE_NRPA: - // Not yet supported. - mp_raise_OSError(MP_EINVAL); + case MP_BLUETOOTH_ADDRESS_MODE_RPA: { + gap_random_address_set_mode(GAP_RANDOM_ADDRESS_RESOLVABLE); + break; + } + case MP_BLUETOOTH_ADDRESS_MODE_NRPA: { + gap_random_address_set_mode(GAP_RANDOM_ADDRESS_NON_RESOLVABLE); + break; + } } } @@ -1564,4 +1586,41 @@ int mp_bluetooth_l2cap_recvinto(uint16_t conn_handle, uint16_t cid, uint8_t *buf MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_btstack_root_pointers_t *bluetooth_btstack_root_pointers); +#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + +static int btstack_tlv_mp_get_tag(void *context, uint32_t tag, uint8_t *buffer, uint32_t buffer_size) { + UNUSED(context); + const uint8_t *data; + size_t data_len; + if (!mp_bluetooth_gap_on_get_secret(0, 0, (uint8_t *)&tag, sizeof(tag), &data, &data_len)) { + return -1; + } + if (data_len > buffer_size) { + return -1; + } + memcpy(buffer, data, data_len); + return data_len; +} + +static int btstack_tlv_mp_store_tag(void *context, uint32_t tag, const uint8_t *data, uint32_t data_size) { + UNUSED(context); + if (mp_bluetooth_gap_on_set_secret(0, (uint8_t *)&tag, sizeof(tag), (uint8_t *)data, data_size)) { + return 0; + } else { + return 1; + } +} + +static void btstack_tlv_mp_delete_tag(void *context, uint32_t tag) { + mp_bluetooth_gap_on_set_secret(0, (uint8_t *)&tag, sizeof(tag), NULL, 0); +} + +static const btstack_tlv_t btstack_tlv_mp = { + &btstack_tlv_mp_get_tag, + &btstack_tlv_mp_store_tag, + &btstack_tlv_mp_delete_tag, +}; + +#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING + #endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index fcc435b7b9..371f77a87c 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -260,6 +260,7 @@ if(MICROPY_PY_BLUETOOTH) MICROPY_PY_BLUETOOTH=1 MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1 MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1 + MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1 ) endif()