diff --git a/common/protob/messages-ble.proto b/common/protob/messages-ble.proto index 724482efe0..756d1589f3 100644 --- a/common/protob/messages-ble.proto +++ b/common/protob/messages-ble.proto @@ -39,3 +39,21 @@ message UploadBLEFirmwareNextChunk { message UploadBLEFirmwareChunk { required bytes data = 1; } + + +/** + * Request: initiates new pairing request + * @start + * @next AuthKey + * @next Failure + */ +message PairingRequest { +} + +/** + * Request: confirms pairing request with auth key entered on the device + * @end + */ +message AuthKey { + required bytes key = 1; +} diff --git a/common/protob/messages.proto b/common/protob/messages.proto index 344d64bf48..3db210d11d 100644 --- a/common/protob/messages.proto +++ b/common/protob/messages.proto @@ -140,6 +140,8 @@ enum MessageType { MessageType_UploadBLEFirmwareInit = 8000 [(bitcoin_only) = true, (wire_in) = true]; MessageType_UploadBLEFirmwareNextChunk = 8001 [(bitcoin_only) = true, (wire_out) = true]; MessageType_UploadBLEFirmwareChunk = 8002 [(bitcoin_only) = true, (wire_in) = true]; + MessageType_PairingRequest = 8003 [(bitcoin_only) = true, (wire_in) = true]; + MessageType_AuthKey = 8004 [(bitcoin_only) = true, (wire_out) = true]; // Bitcoin MessageType_GetPublicKey = 11 [(bitcoin_only) = true, (wire_in) = true]; diff --git a/core/SConscript.ble_firmware b/core/SConscript.ble_firmware index b314b5a948..0daec60bd2 100644 --- a/core/SConscript.ble_firmware +++ b/core/SConscript.ble_firmware @@ -251,14 +251,29 @@ SOURCE_NRFHAL = [ 'embed/sdk/nrf52/components/ble/nrf_ble_gatt/nrf_ble_gatt.c', 'embed/sdk/nrf52/components/ble/nrf_ble_qwr/nrf_ble_qwr.c', 'embed/sdk/nrf52/external/utf_converter/utf.c', - 'embed/sdk/nrf52/components/ble/ble_services/ble_nus/ble_nus.c', 'embed/sdk/nrf52/components/softdevice/common/nrf_sdh.c', 'embed/sdk/nrf52/components/softdevice/common/nrf_sdh_ble.c', 'embed/sdk/nrf52/components/softdevice/common/nrf_sdh_soc.c', + 'embed/sdk/nrf52/components/ble/peer_manager/gatt_cache_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/gatts_cache_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/id_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_data_storage.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_database.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_id.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_manager_handler.c', + 'embed/sdk/nrf52/components/ble/peer_manager/pm_buffer.c', + 'embed/sdk/nrf52/components/libraries/fds/fds.c', + 'embed/sdk/nrf52/components/ble/peer_manager/security_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/security_dispatcher.c', + 'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage.c', + 'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage_sd.c', + ] SOURCE_BLE_FIRMWARE = [ 'embed/ble_firmware/main.c', + 'embed/ble_firmware/ble_nus.c', ] if MMD: diff --git a/core/embed/ble_firmware/ble_nus.c b/core/embed/ble_firmware/ble_nus.c new file mode 100644 index 0000000000..d2dad7b095 --- /dev/null +++ b/core/embed/ble_firmware/ble_nus.c @@ -0,0 +1,356 @@ +// clang-format off + +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(BLE_NUS) +#include "ble.h" +#include "ble_nus.h" +#include "ble_srv_common.h" + +#define NRF_LOG_MODULE_NAME ble_nus +#if BLE_NUS_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL BLE_NUS_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR BLE_NUS_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR +#else // BLE_NUS_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif // BLE_NUS_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */ +#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */ + +#define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ +#define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ + +#define NUS_BASE_UUID {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor specific UUID. */ + + +/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_connect(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_gatts_value_t gatts_val; + uint8_t cccd_value[2]; + ble_nus_client_context_t * p_client = NULL; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gap_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gap_evt.conn_handle); + } + + /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */ + memset(&gatts_val, 0, sizeof(ble_gatts_value_t)); + gatts_val.p_value = cccd_value; + gatts_val.len = sizeof(cccd_value); + gatts_val.offset = 0; + + err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle, + p_nus->tx_handles.cccd_handle, + &gatts_val); + + if ((err_code == NRF_SUCCESS) && + (p_nus->data_handler != NULL) && + ble_srv_is_notification_enabled(gatts_val.p_value)) + { + if (p_client != NULL) + { + p_client->is_notification_enabled = true; + } + + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.type = BLE_NUS_EVT_COMM_STARTED; + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + evt.p_link_ctx = p_client; + + p_nus->data_handler(&evt); + } +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_nus_client_context_t * p_client; + ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gatts_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gatts_evt.conn_handle); + } + + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + evt.p_link_ctx = p_client; + + if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) && + (p_evt_write->len == 2)) + { + if (p_client != NULL) + { + if (ble_srv_is_notification_enabled(p_evt_write->data)) + { + p_client->is_notification_enabled = true; + evt.type = BLE_NUS_EVT_COMM_STARTED; + } + else + { + p_client->is_notification_enabled = false; + evt.type = BLE_NUS_EVT_COMM_STOPPED; + } + + if (p_nus->data_handler != NULL) + { + p_nus->data_handler(&evt); + } + + } + } + else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) && + (p_nus->data_handler != NULL)) + { + evt.type = BLE_NUS_EVT_RX_DATA; + evt.params.rx_data.p_data = p_evt_write->data; + evt.params.rx_data.length = p_evt_write->len; + + p_nus->data_handler(&evt); + } + else + { + // Do Nothing. This event is not relevant for this service. + } +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_nus_client_context_t * p_client; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gatts_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gatts_evt.conn_handle); + return; + } + + if ((p_client->is_notification_enabled) && (p_nus->data_handler != NULL)) + { + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.type = BLE_NUS_EVT_TX_RDY; + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + evt.p_link_ctx = p_client; + + p_nus->data_handler(&evt); + } +} + + +void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + if ((p_context == NULL) || (p_ble_evt == NULL)) + { + return; + } + + ble_nus_t * p_nus = (ble_nus_t *)p_context; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connect(p_nus, p_ble_evt); + break; + + case BLE_GATTS_EVT_WRITE: + on_write(p_nus, p_ble_evt); + break; + + case BLE_GATTS_EVT_HVN_TX_COMPLETE: + on_hvx_tx_complete(p_nus, p_ble_evt); + break; + + default: + // No implementation needed. + break; + } +} + + +uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) +{ + ret_code_t err_code; + ble_uuid_t ble_uuid; + ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; + ble_add_char_params_t add_char_params; + + VERIFY_PARAM_NOT_NULL(p_nus); + VERIFY_PARAM_NOT_NULL(p_nus_init); + + // Initialize the service structure. + p_nus->data_handler = p_nus_init->data_handler; + + /**@snippet [Adding proprietary Service to the SoftDevice] */ + // Add a custom base UUID. + err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); + VERIFY_SUCCESS(err_code); + + ble_uuid.type = p_nus->uuid_type; + ble_uuid.uuid = BLE_UUID_NUS_SERVICE; + + // Add the service. + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, + &ble_uuid, + &p_nus->service_handle); + /**@snippet [Adding proprietary Service to the SoftDevice] */ + VERIFY_SUCCESS(err_code); + + // Add the RX Characteristic. + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.write = 1; + add_char_params.char_props.write_wo_resp = 1; + + add_char_params.read_access = SEC_MITM; + add_char_params.write_access = SEC_MITM; + + err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // Add the TX Characteristic. + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = BLE_NUS_MAX_TX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + + add_char_params.read_access = SEC_MITM; + add_char_params.write_access = SEC_MITM; + add_char_params.cccd_write_access = SEC_MITM; + + return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles); + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ +} + + +uint32_t ble_nus_data_send(ble_nus_t * p_nus, + uint8_t * p_data, + uint16_t * p_length, + uint16_t conn_handle) +{ + ret_code_t err_code; + ble_gatts_hvx_params_t hvx_params; + ble_nus_client_context_t * p_client; + + VERIFY_PARAM_NOT_NULL(p_nus); + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client); + VERIFY_SUCCESS(err_code); + + if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL)) + { + return NRF_ERROR_NOT_FOUND; + } + + if (!p_client->is_notification_enabled) + { + return NRF_ERROR_INVALID_STATE; + } + + if (*p_length > BLE_NUS_MAX_DATA_LEN) + { + return NRF_ERROR_INVALID_PARAM; + } + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_nus->tx_handles.value_handle; + hvx_params.p_data = p_data; + hvx_params.p_len = p_length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + + return sd_ble_gatts_hvx(conn_handle, &hvx_params); +} + + +#endif // NRF_MODULE_ENABLED(BLE_NUS) diff --git a/core/embed/ble_firmware/main.c b/core/embed/ble_firmware/main.c index 50541c46b3..dfb5052fec 100644 --- a/core/embed/ble_firmware/main.c +++ b/core/embed/ble_firmware/main.c @@ -52,6 +52,7 @@ #include #include +#include "app_scheduler.h" #include "app_timer.h" #include "app_uart.h" #include "app_util_platform.h" @@ -69,6 +70,8 @@ #include "nrf_sdh.h" #include "nrf_sdh_ble.h" #include "nrf_sdh_soc.h" +#include "peer_manager.h" +#include "peer_manager_handler.h" #if defined(UART_PRESENT) #include "nrf_uart.h" @@ -142,6 +145,8 @@ NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ +static pm_peer_id_t + m_peer_id; /**< Device reference handle to the current bonded central. */ static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ static uint16_t m_ble_nus_max_data_len = @@ -151,6 +156,9 @@ static uint16_t m_ble_nus_max_data_len = static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; +static uint8_t m_uart_rx_data[BLE_NUS_MAX_DATA_LEN]; +static bool m_uart_rx_data_ready_internal = false; + /**@brief Function for assert macro callback. * * @details This function will be called in case of an assert in the SoftDevice. @@ -190,6 +198,9 @@ static void gap_params_init(void) { strlen(DEVICE_NAME)); APP_ERROR_CHECK(err_code); + err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN); + APP_ERROR_CHECK(err_code); + memset(&gap_conn_params, 0, sizeof(gap_conn_params)); gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; @@ -229,6 +240,14 @@ static void nus_data_handler(ble_nus_evt_t *p_evt) { NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); + if (p_evt->params.rx_data.length != 64) { + return; + } + + app_uart_put(0xA1); // external message + app_uart_put(0x00); // len - HI + app_uart_put(0x44); // len - LO + for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++) { do { err_code = app_uart_put(p_evt->params.rx_data.p_data[i]); @@ -238,11 +257,8 @@ static void nus_data_handler(ble_nus_evt_t *p_evt) { } } while (err_code == NRF_ERROR_BUSY); } - // if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == - // '\r') { - // while (app_uart_put('\n') == NRF_ERROR_BUSY) - // ; - // } + + app_uart_put(0x55); // EOM } } /**@snippet [Handling the data received over BLE] */ @@ -270,27 +286,6 @@ static void services_init(void) { APP_ERROR_CHECK(err_code); } -/**@brief Function for handling an event from the Connection Parameters Module. - * - * @details This function will be called for all events in the Connection - * Parameters Module which are passed to the application. - * - * @note All this function does is to disconnect. This could have been done by - * simply setting the disconnect_on_fail config parameter, but instead we use - * the event handler mechanism to demonstrate its use. - * - * @param[in] p_evt Event received from the Connection Parameters Module. - */ -static void on_conn_params_evt(ble_conn_params_evt_t *p_evt) { - uint32_t err_code; - - if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { - err_code = sd_ble_gap_disconnect(m_conn_handle, - BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); - APP_ERROR_CHECK(err_code); - } -} - /**@brief Function for handling errors from the Connection Parameters module. * * @param[in] nrf_error Error code containing information about what went @@ -314,7 +309,7 @@ static void conn_params_init(void) { cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; cp_init.disconnect_on_fail = false; - cp_init.evt_handler = on_conn_params_evt; + cp_init.evt_handler = NULL; cp_init.error_handler = conn_params_error_handler; err_code = ble_conn_params_init(&cp_init); @@ -339,6 +334,22 @@ static void sleep_mode_enter(void) { APP_ERROR_CHECK(err_code); } +/**@brief Function for setting filtered device identities. + * + * @param[in] skip Filter passed to @ref pm_peer_id_list. + */ +static void identities_set(pm_peer_id_list_skip_t skip) { + pm_peer_id_t peer_ids[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; + uint32_t peer_id_count = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; + + ret_code_t err_code = + pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip); + APP_ERROR_CHECK(err_code); + + err_code = pm_device_identities_list_set(peer_ids, peer_id_count); + APP_ERROR_CHECK(err_code); +} + /**@brief Function for handling advertising events. * * @details This function will be called for advertising events which are passed @@ -350,13 +361,91 @@ static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { uint32_t err_code; switch (ble_adv_evt) { + case BLE_ADV_EVT_DIRECTED_HIGH_DUTY: + NRF_LOG_INFO("High Duty Directed advertising."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_DIRECTED: + NRF_LOG_INFO("Directed advertising."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_DIRECTED); + APP_ERROR_CHECK(err_code); + break; + case BLE_ADV_EVT_FAST: + NRF_LOG_INFO("Fast advertising."); err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); APP_ERROR_CHECK(err_code); break; + + case BLE_ADV_EVT_SLOW: + NRF_LOG_INFO("Slow advertising."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_SLOW); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_FAST_WHITELIST: + NRF_LOG_INFO("Fast advertising with whitelist."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST); + APP_ERROR_CHECK(err_code); + break; + + case BLE_ADV_EVT_SLOW_WHITELIST: + NRF_LOG_INFO("Slow advertising with whitelist."); + err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING_WHITELIST); + APP_ERROR_CHECK(err_code); + break; + case BLE_ADV_EVT_IDLE: sleep_mode_enter(); break; + + case BLE_ADV_EVT_WHITELIST_REQUEST: { + ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + uint32_t addr_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + uint32_t irk_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + + err_code = pm_whitelist_get(whitelist_addrs, &addr_cnt, whitelist_irks, + &irk_cnt); + APP_ERROR_CHECK(err_code); + NRF_LOG_DEBUG( + "pm_whitelist_get returns %d addr in whitelist and %d irk whitelist", + addr_cnt, irk_cnt); + + // Set the correct identities list (no excluding peers with no Central + // Address Resolution). + identities_set(PM_PEER_ID_LIST_SKIP_NO_IRK); + + // Apply the whitelist. + err_code = ble_advertising_whitelist_reply( + &m_advertising, whitelist_addrs, addr_cnt, whitelist_irks, irk_cnt); + APP_ERROR_CHECK(err_code); + } break; // BLE_ADV_EVT_WHITELIST_REQUEST + + case BLE_ADV_EVT_PEER_ADDR_REQUEST: { + pm_peer_data_bonding_t peer_bonding_data; + + // Only Give peer address if we have a handle to the bonded peer. + if (m_peer_id != PM_PEER_ID_INVALID) { + err_code = pm_peer_data_bonding_load(m_peer_id, &peer_bonding_data); + if (err_code != NRF_ERROR_NOT_FOUND) { + APP_ERROR_CHECK(err_code); + + // Manipulate identities to exclude peers with no Central Address + // Resolution. + identities_set(PM_PEER_ID_LIST_SKIP_ALL); + + ble_gap_addr_t *p_peer_addr = + &(peer_bonding_data.peer_ble_id.id_addr_info); + err_code = + ble_advertising_peer_addr_reply(&m_advertising, p_peer_addr); + APP_ERROR_CHECK(err_code); + } + } + } break; // BLE_ADV_EVT_PEER_ADDR_REQUEST + default: break; } @@ -397,19 +486,45 @@ static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { APP_ERROR_CHECK(err_code); } break; - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - // Pairing not supported - err_code = sd_ble_gap_sec_params_reply( - m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); - APP_ERROR_CHECK(err_code); - break; + case BLE_GAP_EVT_AUTH_KEY_REQUEST: { + NRF_LOG_INFO("Key requested."); - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - // No system attributes have been stored. - err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); - APP_ERROR_CHECK(err_code); - break; + uint8_t tx_data[] = { + 0xA0, // internal message + 0x00, // length - HI + 0x0D, // length - LO + 0x3F, 0x23, 0x23, 0x1F, 0x43, 0x00, 0x00, 0x00, 0x00, + 0x55, // EOM + }; + for (uint32_t i = 0; i < sizeof(tx_data); i++) { + do { + err_code = app_uart_put(tx_data[i]); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { + NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", + err_code); + APP_ERROR_CHECK(err_code); + } + } while (err_code == NRF_ERROR_BUSY); + } + + uint8_t p_key[6] = {0}; + + while (!m_uart_rx_data_ready_internal) + ; + for (int i = 0; i < 6; i++) { + p_key[i] = m_uart_rx_data[i + 11]; + } + m_uart_rx_data_ready_internal = false; + + NRF_LOG_INFO("Received data: %c", p_key); + + err_code = + sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, + BLE_GAP_AUTH_KEY_TYPE_PASSKEY, p_key); + // APP_ERROR_CHECK(err_code); + break; + } case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event. err_code = @@ -526,43 +641,89 @@ void bsp_event_handler(bsp_event_t event) { */ /**@snippet [Handling the data received over UART] */ void uart_event_handle(app_uart_evt_t *p_event) { - static uint8_t data_array[BLE_NUS_MAX_DATA_LEN]; static uint8_t index = 0; + static uint8_t external = 0; + static uint16_t len = 0; uint32_t err_code; + uint8_t rx_byte = 0; switch (p_event->evt_type) { case APP_UART_DATA_READY: - UNUSED_VARIABLE(app_uart_get(&data_array[index])); - index++; + while (app_uart_get(&rx_byte) == NRF_SUCCESS) { + if (index == 0) { + // decide destination + if (rx_byte == 0xA0) { + // internal message + external = 0; + index += 1; + continue; + } else if (rx_byte == 0xA1) { + // external message + external = 1; + index += 1; + continue; - if ((index >= 64)) { - if (index > 1) { - NRF_LOG_DEBUG("Ready to send data over BLE NUS"); - NRF_LOG_HEXDUMP_DEBUG(data_array, index); - - do { - uint16_t length = (uint16_t)index; - err_code = - ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle); - if ((err_code != NRF_ERROR_INVALID_STATE) && - (err_code != NRF_ERROR_RESOURCES) && - (err_code != NRF_ERROR_NOT_FOUND)) { - APP_ERROR_CHECK(err_code); - } - } while (err_code == NRF_ERROR_RESOURCES); + } else { + // unknown message + continue; + } } - index = 0; + if (index == 1) { + // len HI + len = rx_byte << 8; + index += 1; + continue; + } + + if (index == 2) { + // len LO + len |= rx_byte; + index += 1; + continue; + } + + if (index < (len - 1)) { + // command + m_uart_rx_data[index - 3] = rx_byte; + index += 1; + continue; + } + + if (index >= (len - 1)) { + { + if (rx_byte == 0x55) { + if (external) { + NRF_LOG_DEBUG("Ready to send data over BLE NUS"); + NRF_LOG_HEXDUMP_DEBUG(m_uart_rx_data, index); + + do { + uint16_t length = (uint16_t)len - 4; + err_code = ble_nus_data_send(&m_nus, m_uart_rx_data, &length, + m_conn_handle); + if ((err_code != NRF_ERROR_INVALID_STATE) && + (err_code != NRF_ERROR_RESOURCES) && + (err_code != NRF_ERROR_NOT_FOUND)) { + APP_ERROR_CHECK(err_code); + } + } while (err_code == NRF_ERROR_RESOURCES); + } else { + m_uart_rx_data_ready_internal = true; + } + } + index = 0; + } + } } break; -// case APP_UART_COMMUNICATION_ERROR: -// APP_ERROR_HANDLER(p_event->data.error_communication); -// break; -// -// case APP_UART_FIFO_ERROR: -// APP_ERROR_HANDLER(p_event->data.error_code); -// break; + // case APP_UART_COMMUNICATION_ERROR: + // APP_ERROR_HANDLER(p_event->data.error_communication); + // break; + // + // case APP_UART_FIFO_ERROR: + // APP_ERROR_HANDLER(p_event->data.error_code); + // break; default: break; @@ -597,23 +758,55 @@ static void uart_init(void) { /**@brief Function for initializing the Advertising functionality. */ +// static void advertising_init(void) { +// uint32_t err_code; +// ble_advertising_init_t init; +// +// memset(&init, 0, sizeof(init)); +// +// init.advdata.name_type = BLE_ADVDATA_FULL_NAME; +// init.advdata.include_appearance = false; +// init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; +// +// init.srdata.uuids_complete.uuid_cnt = +// sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); +// init.srdata.uuids_complete.p_uuids = m_adv_uuids; +// +// init.config.ble_adv_fast_enabled = true; +// init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; +// init.config.ble_adv_fast_timeout = APP_ADV_DURATION; +// init.evt_handler = on_adv_evt; +// +// err_code = ble_advertising_init(&m_advertising, &init); +// APP_ERROR_CHECK(err_code); +// +// ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); +//} + static void advertising_init(void) { uint32_t err_code; + uint8_t adv_flags; ble_advertising_init_t init; memset(&init, 0, sizeof(init)); + adv_flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; init.advdata.name_type = BLE_ADVDATA_FULL_NAME; - init.advdata.include_appearance = false; - init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; - - init.srdata.uuids_complete.uuid_cnt = + init.advdata.include_appearance = true; + init.advdata.flags = adv_flags; + init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); - init.srdata.uuids_complete.p_uuids = m_adv_uuids; + init.advdata.uuids_complete.p_uuids = m_adv_uuids; + init.config.ble_adv_whitelist_enabled = true; + init.config.ble_adv_directed_high_duty_enabled = true; + init.config.ble_adv_directed_enabled = false; + init.config.ble_adv_directed_interval = 0; + init.config.ble_adv_directed_timeout = 0; init.config.ble_adv_fast_enabled = true; init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; init.config.ble_adv_fast_timeout = APP_ADV_DURATION; + init.evt_handler = on_adv_evt; err_code = ble_advertising_init(&m_advertising, &init); @@ -663,16 +856,145 @@ static void power_management_init(void) { * event occurs. */ static void idle_state_handle(void) { + app_sched_execute(); if (NRF_LOG_PROCESS() == false) { nrf_pwr_mgmt_run(); } } -/**@brief Function for starting advertising. +/**@brief Function for setting filtered whitelist. + * + * @param[in] skip Filter passed to @ref pm_peer_id_list. */ -static void advertising_start(void) { - uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); +static void whitelist_set(pm_peer_id_list_skip_t skip) { + pm_peer_id_t peer_ids[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + uint32_t peer_id_count = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + + ret_code_t err_code = + pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip); APP_ERROR_CHECK(err_code); + + NRF_LOG_INFO("\tm_whitelist_peer_cnt %d, MAX_PEERS_WLIST %d", + peer_id_count + 1, BLE_GAP_WHITELIST_ADDR_MAX_COUNT); + + err_code = pm_whitelist_set(peer_ids, peer_id_count); + APP_ERROR_CHECK(err_code); +} + +///**@brief Clear bond information from persistent storage. */ +static void delete_bonds(void) { + ret_code_t err_code; + + NRF_LOG_INFO("Erase bonds!"); + + err_code = pm_peers_delete(); + APP_ERROR_CHECK(err_code); +} + +static void advertising_start(bool erase_bonds) { + if (erase_bonds == true) { + delete_bonds(); + // Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event. + } else { + whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); + + ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); + APP_ERROR_CHECK(ret); + } +} + +#define SEC_PARAM_BOND 1 /**< Perform bonding. */ +#define SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */ +#define SEC_PARAM_LESC 0 /**< LE Secure Connections not enabled. */ +#define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ +#define SEC_PARAM_IO_CAPABILITIES \ + BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY /**< No I/O capabilities. */ +#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ +#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ +#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ + +#define SCHED_MAX_EVENT_DATA_SIZE \ + APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */ +#ifdef SVCALL_AS_NORMAL_FUNCTION +#define SCHED_QUEUE_SIZE \ + 20 /**< Maximum number of events in the scheduler queue. More is needed in \ + case of Serialization. */ +#else +#define SCHED_QUEUE_SIZE \ + 10 /**< Maximum number of events in the scheduler queue. */ +#endif + +/**@brief Function for handling Peer Manager events. + * + * @param[in] p_evt Peer Manager event. + */ +static void pm_evt_handler(pm_evt_t const *p_evt) { + pm_handler_on_pm_evt(p_evt); + pm_handler_disconnect_on_sec_failure(p_evt); + pm_handler_flash_clean(p_evt); + + switch (p_evt->evt_id) { + case PM_EVT_CONN_SEC_SUCCEEDED: + m_peer_id = p_evt->peer_id; + break; + + case PM_EVT_PEERS_DELETE_SUCCEEDED: + advertising_start(false); + break; + + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + if (p_evt->params.peer_data_update_succeeded.flash_changed && + (p_evt->params.peer_data_update_succeeded.data_id == + PM_PEER_DATA_ID_BONDING)) { + NRF_LOG_INFO("New Bond, add the peer to the whitelist if possible"); + // Note: You should check on what kind of white list policy your + // application should use. + + whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); + } + break; + + default: + break; + } +} + +/**@brief Function for the Peer Manager initialization. + */ +static void peer_manager_init(void) { + ble_gap_sec_params_t sec_param; + ret_code_t err_code; + + err_code = pm_init(); + APP_ERROR_CHECK(err_code); + + memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); + + // Security parameters to be used for all security procedures. + sec_param.bond = SEC_PARAM_BOND; + sec_param.mitm = SEC_PARAM_MITM; + sec_param.lesc = SEC_PARAM_LESC; + sec_param.keypress = SEC_PARAM_KEYPRESS; + sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; + sec_param.oob = SEC_PARAM_OOB; + sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; + sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; + sec_param.kdist_own.enc = 1; + sec_param.kdist_own.id = 1; + sec_param.kdist_peer.enc = 1; + sec_param.kdist_peer.id = 1; + + err_code = pm_sec_params_set(&sec_param); + APP_ERROR_CHECK(err_code); + + err_code = pm_register(pm_evt_handler); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for the Event Scheduler initialization. + */ +static void scheduler_init(void) { + APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); } /**@brief Application main function. @@ -687,16 +1009,16 @@ int main(void) { buttons_leds_init(&erase_bonds); power_management_init(); ble_stack_init(); + scheduler_init(); gap_params_init(); gatt_init(); services_init(); advertising_init(); conn_params_init(); + peer_manager_init(); // Start execution. - printf("\r\nUART started.\r\n"); - NRF_LOG_INFO("Debug logging for UART over RTT started."); - advertising_start(); + advertising_start(true); // Enter main loop. for (;;) { diff --git a/core/embed/ble_firmware/sdk_config.h b/core/embed/ble_firmware/sdk_config.h index b4cdcf183b..98904944dd 100644 --- a/core/embed/ble_firmware/sdk_config.h +++ b/core/embed/ble_firmware/sdk_config.h @@ -206,7 +206,7 @@ // PEER_MANAGER_ENABLED - peer_manager - Peer Manager //========================================================== #ifndef PEER_MANAGER_ENABLED -#define PEER_MANAGER_ENABLED 0 +#define PEER_MANAGER_ENABLED 1 #endif // PM_MAX_REGISTRANTS - Number of event handlers that can be registered. #ifndef PM_MAX_REGISTRANTS @@ -226,7 +226,7 @@ // Enable/disable central-specific Peer Manager functionality. #ifndef PM_CENTRAL_ENABLED -#define PM_CENTRAL_ENABLED 1 +#define PM_CENTRAL_ENABLED 0 #endif // PM_SERVICE_CHANGED_ENABLED - Enable/disable the service changed management for GATT server in Peer Manager. @@ -6728,7 +6728,7 @@ // FDS_ENABLED - fds - Flash data storage module //========================================================== #ifndef FDS_ENABLED -#define FDS_ENABLED 0 +#define FDS_ENABLED 1 #endif // Pages - Virtual page settings @@ -7252,7 +7252,7 @@ // NRF_FSTORAGE_ENABLED - nrf_fstorage - Flash abstraction library //========================================================== #ifndef NRF_FSTORAGE_ENABLED -#define NRF_FSTORAGE_ENABLED 0 +#define NRF_FSTORAGE_ENABLED 1 #endif // nrf_fstorage - Common settings @@ -7496,7 +7496,7 @@ #ifndef RETARGET_ENABLED -#define RETARGET_ENABLED 1 +#define RETARGET_ENABLED 0 #endif // SLIP_ENABLED - slip - SLIP encoding and decoding @@ -11914,7 +11914,7 @@ // <2=> NRF_SDH_DISPATCH_MODEL_POLLING #ifndef NRF_SDH_DISPATCH_MODEL -#define NRF_SDH_DISPATCH_MODEL 0 +#define NRF_SDH_DISPATCH_MODEL 1 #endif // diff --git a/core/embed/extmod/modtrezorio/modtrezorio-ble.h b/core/embed/extmod/modtrezorio/modtrezorio-ble.h index 6ee204d43d..a7d3e0da56 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio-ble.h +++ b/core/embed/extmod/modtrezorio/modtrezorio-ble.h @@ -72,7 +72,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorio_BLE_update_chunk_obj, STATIC mp_obj_t mod_trezorio_BLE_write(mp_obj_t self, mp_obj_t msg) { mp_buffer_info_t buf = {0}; mp_get_buffer_raise(msg, &buf, MP_BUFFER_READ); - ble_comm_send(buf.buf, buf.len); + ble_int_comm_send(buf.buf, buf.len, ble_last_internal); return MP_OBJ_NEW_SMALL_INT(buf.len); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_BLE_write_obj, diff --git a/core/embed/extmod/modtrezorio/modtrezorio.c b/core/embed/extmod/modtrezorio/modtrezorio.c index 3962642d71..ade09942d3 100644 --- a/core/embed/extmod/modtrezorio/modtrezorio.c +++ b/core/embed/extmod/modtrezorio/modtrezorio.c @@ -34,6 +34,7 @@ // Whether USB data pins were connected on last check (USB configured) bool usb_connected_previously = true; +bool ble_last_internal = false; #define CHECK_PARAM_RANGE(value, minimum, maximum) \ if (value < minimum || value > maximum) { \ diff --git a/core/embed/trezorhal/ble/comm.c b/core/embed/trezorhal/ble/comm.c index 6f9a339b87..156bf391ac 100644 --- a/core/embed/trezorhal/ble/comm.c +++ b/core/embed/trezorhal/ble/comm.c @@ -20,6 +20,8 @@ #include STM32_HAL_H #include TREZOR_BOARD +#include "comm.h" + static UART_HandleTypeDef urt; void ble_comm_init(void) { @@ -47,7 +49,7 @@ void ble_comm_init(void) { } void ble_comm_send(uint8_t *data, uint32_t len) { - HAL_UART_Transmit(&urt, data, len, 10); + HAL_UART_Transmit(&urt, data, len, 30); } uint32_t ble_comm_receive(uint8_t *data, uint32_t len) { @@ -65,3 +67,67 @@ uint32_t ble_comm_receive(uint8_t *data, uint32_t len) { } return 0; } + +void ble_int_comm_send(uint8_t *data, uint32_t len, bool internal) { + uint16_t msg_len = len + 4; + uint8_t len_hi = msg_len >> 8; + uint8_t len_lo = msg_len & 0xFF; + uint8_t eom = 0x55; + + uint8_t init_byte = 0; + if (internal) { + init_byte = 0xA0; + } else { + init_byte = 0xA1; + } + + HAL_UART_Transmit(&urt, &init_byte, 1, 1); + HAL_UART_Transmit(&urt, &len_hi, 1, 1); + HAL_UART_Transmit(&urt, &len_lo, 1, 1); + + HAL_UART_Transmit(&urt, data, len, 10); + HAL_UART_Transmit(&urt, &eom, 1, 1); +} + +uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len, bool *internal) { + data[0] = 0; + if (urt.Instance->SR & USART_SR_RXNE) { + uint8_t init_byte = 0; + HAL_UART_Receive(&urt, &init_byte, 1, 1); + + if (init_byte == 0xA0 || init_byte == 0xA1) { + uint8_t len_hi = 0; + uint8_t len_lo = 0; + HAL_UART_Receive(&urt, &len_hi, 1, 1); + HAL_UART_Receive(&urt, &len_lo, 1, 1); + + uint16_t act_len = (len_hi << 8) | len_lo; + + HAL_StatusTypeDef result = HAL_UART_Receive(&urt, data, act_len - 4, 5); + + if (result != HAL_OK) { + return 0; + } + + uint8_t eom = 0; + HAL_UART_Receive(&urt, &eom, 1, 1); + + if (eom == 0x55) { + if (init_byte == 0xA0) { + *internal = true; + } else { + *internal = false; + } + return act_len - 4; + } + return 0; + + } else { + // disregard byte. + // todo: flush everything on the line, also for other errors + return 0; + } + } + + return 0; +} diff --git a/core/embed/trezorhal/ble/comm.h b/core/embed/trezorhal/ble/comm.h index 118b34e8d7..b5019f95e1 100644 --- a/core/embed/trezorhal/ble/comm.h +++ b/core/embed/trezorhal/ble/comm.h @@ -1,7 +1,9 @@ - +#include void ble_comm_init(void); void ble_comm_send(uint8_t *data, uint32_t len); - uint32_t ble_comm_receive(uint8_t *data, uint32_t len); + +void ble_int_comm_send(uint8_t *data, uint32_t len, bool internal); +uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len, bool *internal); diff --git a/core/embed/trezorhal/ble/dfu.c b/core/embed/trezorhal/ble/dfu.c index 67e04664d7..6476e5306b 100644 --- a/core/embed/trezorhal/ble/dfu.c +++ b/core/embed/trezorhal/ble/dfu.c @@ -121,7 +121,6 @@ dfu_result_t dfu_update_do(uint8_t *datfile, uint32_t datfile_len, void txFunction(struct SFwu *fwu, uint8_t *buf, uint8_t len) { ble_comm_send(buf, len); - ; } static uint8_t readData(uint8_t *data, int maxLen) { diff --git a/core/src/all_modules.py b/core/src/all_modules.py index 010d1081df..6433b03afb 100644 --- a/core/src/all_modules.py +++ b/core/src/all_modules.py @@ -303,6 +303,8 @@ apps.management.backup_device import apps.management.backup_device apps.management.backup_types import apps.management.backup_types +apps.management.ble.pairing_request +import apps.management.ble.pairing_request apps.management.ble.upload_ble_firmware_init import apps.management.ble.upload_ble_firmware_init apps.management.change_pin diff --git a/core/src/apps/management/ble/pairing_request.py b/core/src/apps/management/ble/pairing_request.py new file mode 100644 index 0000000000..dce32262da --- /dev/null +++ b/core/src/apps/management/ble/pairing_request.py @@ -0,0 +1,19 @@ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from trezor.wire import GenericContext + from trezor.messages import ( + AuthKey, + PairingRequest, + ) + + +async def pairing_request(ctx: GenericContext, _msg: PairingRequest) -> AuthKey: + from trezor.messages import ( + AuthKey, + ) + from trezor.ui.layouts import request_pin_on_device + + pin = await request_pin_on_device(ctx, "PAIRING", None, True, False, True) + + return AuthKey(key=pin.encode()) diff --git a/core/src/apps/workflow_handlers.py b/core/src/apps/workflow_handlers.py index 2841c1a6fd..5193154c17 100644 --- a/core/src/apps/workflow_handlers.py +++ b/core/src/apps/workflow_handlers.py @@ -58,6 +58,8 @@ def _find_message_handler_module(msg_type: int) -> str: # BLE if msg_type == MessageType.UploadBLEFirmwareInit: return "apps.management.ble.upload_ble_firmware_init" + if msg_type == MessageType.PairingRequest: + return "apps.management.ble.pairing_request" # bitcoin if msg_type == MessageType.AuthorizeCoinJoin: diff --git a/core/src/trezor/enums/MessageType.py b/core/src/trezor/enums/MessageType.py index a068363574..f83aaf7cc6 100644 --- a/core/src/trezor/enums/MessageType.py +++ b/core/src/trezor/enums/MessageType.py @@ -53,6 +53,8 @@ SelfTest = 32 UploadBLEFirmwareInit = 8000 UploadBLEFirmwareNextChunk = 8001 UploadBLEFirmwareChunk = 8002 +PairingRequest = 8003 +AuthKey = 8004 GetPublicKey = 11 PublicKey = 12 SignTx = 15 diff --git a/core/src/trezor/enums/__init__.py b/core/src/trezor/enums/__init__.py index 9dacb3ff0c..398b0e17e5 100644 --- a/core/src/trezor/enums/__init__.py +++ b/core/src/trezor/enums/__init__.py @@ -75,6 +75,8 @@ if TYPE_CHECKING: UploadBLEFirmwareInit = 8000 UploadBLEFirmwareNextChunk = 8001 UploadBLEFirmwareChunk = 8002 + PairingRequest = 8003 + AuthKey = 8004 GetPublicKey = 11 PublicKey = 12 SignTx = 15 diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py index c05c06808c..26114980c4 100644 --- a/core/src/trezor/messages.py +++ b/core/src/trezor/messages.py @@ -1221,6 +1221,26 @@ if TYPE_CHECKING: def is_type_of(cls, msg: Any) -> TypeGuard["UploadBLEFirmwareChunk"]: return isinstance(msg, cls) + class PairingRequest(protobuf.MessageType): + + @classmethod + def is_type_of(cls, msg: Any) -> TypeGuard["PairingRequest"]: + return isinstance(msg, cls) + + class AuthKey(protobuf.MessageType): + key: "bytes" + + def __init__( + self, + *, + key: "bytes", + ) -> None: + pass + + @classmethod + def is_type_of(cls, msg: Any) -> TypeGuard["AuthKey"]: + return isinstance(msg, cls) + class CardanoBlockchainPointerType(protobuf.MessageType): block_index: "int" tx_index: "int" diff --git a/core/src/trezor/ui/layouts/tt_v2/__init__.py b/core/src/trezor/ui/layouts/tt_v2/__init__.py index 7ea96e3cd3..2b30d73656 100644 --- a/core/src/trezor/ui/layouts/tt_v2/__init__.py +++ b/core/src/trezor/ui/layouts/tt_v2/__init__.py @@ -1101,10 +1101,12 @@ async def request_pin_on_device( attempts_remaining: int | None, allow_cancel: bool, wrong_pin: bool = False, + skip_button_request: bool = False, ) -> str: from trezor.wire import PinCancelled - await button_request(ctx, "pin_device", code=ButtonRequestType.PinEntry) + if not skip_button_request: + await button_request(ctx, "pin_device", code=ButtonRequestType.PinEntry) if attempts_remaining is None: subprompt = "" diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index 991083e159..c0b1b4055f 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -83,6 +83,8 @@ class MessageType(IntEnum): UploadBLEFirmwareInit = 8000 UploadBLEFirmwareNextChunk = 8001 UploadBLEFirmwareChunk = 8002 + PairingRequest = 8003 + AuthKey = 8004 GetPublicKey = 11 PublicKey = 12 SignTx = 15 @@ -2089,6 +2091,24 @@ class UploadBLEFirmwareChunk(protobuf.MessageType): self.data = data +class PairingRequest(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 8003 + + +class AuthKey(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 8004 + FIELDS = { + 1: protobuf.Field("key", "bytes", repeated=False, required=True), + } + + def __init__( + self, + *, + key: "bytes", + ) -> None: + self.key = key + + class FirmwareErase(protobuf.MessageType): MESSAGE_WIRE_TYPE = 6 FIELDS = {