From 83aa2811dfed8e935c51279ad60981a03b6bb5e9 Mon Sep 17 00:00:00 2001 From: Martin Brabham Date: Thu, 20 May 2021 14:30:09 -0700 Subject: [PATCH] OOB: Start advertising when OOB data is generated. This affords the stack the capability to provide the proper random address and address type to the user via the OobDataCallback. Previous to this commit, the data defaults to the public address. This advertisement will time out, and will clear OOB data upon timeout. Bug: 192084169 Test: Manual, test app. Test: m bt_host_test_bta Test: m net_test_btif_stack Tag: #feature Change-Id: Ia24c10e7209027b8b070b9196caba7e394ee6dcb Merged-In: Ia24c10e7209027b8b070b9196caba7e394ee6dcb --- btif/include/btif_common.h | 3 +- btif/include/btif_gatt.h | 2 + btif/src/bluetooth.cc | 6 +-- btif/src/btif_dm.cc | 95 +++++++++++++++++++++++++++++++++++++---- stack/include/smp_api.h | 15 ++++--- stack/smp/smp_api.cc | 19 +++++---- stack/smp/smp_int.h | 1 + stack/smp/smp_keys.cc | 2 + test/mock/mock_stack_smp_api.cc | 10 ++--- 9 files changed, 120 insertions(+), 33 deletions(-) diff --git a/btif/include/btif_common.h b/btif/include/btif_common.h index 51effded6..3ce8db6da 100644 --- a/btif/include/btif_common.h +++ b/btif/include/btif_common.h @@ -208,7 +208,8 @@ void invoke_ssp_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, uint32_t cod, bt_ssp_variant_t pairing_variant, uint32_t pass_key); void invoke_oob_data_request_cb(tBT_TRANSPORT t, bool valid, Octet16 c, - Octet16 r, RawAddress raw_address); + Octet16 r, RawAddress raw_address, + uint8_t address_type); void invoke_bond_state_changed_cb(bt_status_t status, RawAddress bd_addr, bt_bond_state_t state); void invoke_acl_state_changed_cb(bt_status_t status, RawAddress bd_addr, diff --git a/btif/include/btif_gatt.h b/btif/include/btif_gatt.h index 88f18a7b9..7391e6dbe 100644 --- a/btif/include/btif_gatt.h +++ b/btif/include/btif_gatt.h @@ -27,6 +27,8 @@ #ifndef BTIF_GATT_H #define BTIF_GATT_H +#include "include/hardware/bt_gatt.h" + extern const btgatt_client_interface_t btgattClientInterface; extern const btgatt_server_interface_t btgattServerInterface; diff --git a/btif/src/bluetooth.cc b/btif/src/bluetooth.cc index 7a267a399..e071a70bc 100644 --- a/btif/src/bluetooth.cc +++ b/btif/src/bluetooth.cc @@ -739,7 +739,8 @@ void invoke_ssp_request_cb(RawAddress bd_addr, bt_bdname_t bd_name, } void invoke_oob_data_request_cb(tBT_TRANSPORT t, bool valid, Octet16 c, - Octet16 r, RawAddress raw_address) { + Octet16 r, RawAddress raw_address, + uint8_t address_type) { LOG_INFO("%s", __func__); bt_oob_data_t oob_data = {}; @@ -749,8 +750,7 @@ void invoke_oob_data_request_cb(tBT_TRANSPORT t, bool valid, Octet16 c, oob_data.address[i] = raw_address.address[j]; j--; } - // Set type always public - oob_data.address[6] = 0; + oob_data.address[6] = address_type; // Each value (for C and R) is 16 octets in length bool c_empty = true; diff --git a/btif/src/btif_dm.cc b/btif/src/btif_dm.cc index a888a2065..5cda4d3e3 100644 --- a/btif/src/btif_dm.cc +++ b/btif/src/btif_dm.cc @@ -54,6 +54,7 @@ #include "btif_bqr.h" #include "btif_config.h" #include "btif_dm.h" +#include "btif_gatt.h" #include "btif_hd.h" #include "btif_hf.h" #include "btif_hh.h" @@ -1334,16 +1335,16 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, p_data->disc_res.num_uuids == 0) { LOG_INFO("SDP failed, send empty UUID to unblock bonding %s", bd_addr.ToString().c_str()); - bt_property_t prop; + bt_property_t prop_uuids; Uuid uuid = {}; - prop.type = BT_PROPERTY_UUIDS; - prop.val = &uuid; - prop.len = Uuid::kNumBytes128; + prop_uuids.type = BT_PROPERTY_UUIDS; + prop_uuids.val = &uuid; + prop_uuids.len = Uuid::kNumBytes128; /* Send the event to the BTIF */ invoke_remote_device_properties_cb(BT_STATUS_SUCCESS, bd_addr, 1, - &prop); + &prop_uuids); break; } } @@ -2374,14 +2375,92 @@ void btif_dm_generate_local_oob_data(tBT_TRANSPORT transport) { if (transport == BT_TRANSPORT_BR_EDR) { BTM_ReadLocalOobData(); } else if (transport == BT_TRANSPORT_LE) { - SMP_CrLocScOobData(base::BindOnce(&btif_dm_proc_loc_oob)); + // Call create data first, so we don't have to hold on to the address for + // the state machine lifecycle. Rather, lets create the data, then start + // advertising then request the address. + SMP_CrLocScOobData(); } } +// Step Four: CallBack from Step Three +static void get_address_callback(tBT_TRANSPORT transport, bool is_valid, + const Octet16& c, const Octet16& r, + uint8_t address_type, RawAddress address) { + invoke_oob_data_request_cb(transport, is_valid, c, r, address, address_type); +} + +// Step Three: CallBack from Step Two, advertise and get address +static void start_advertising_callback(uint8_t id, tBT_TRANSPORT transport, + bool is_valid, const Octet16& c, + const Octet16& r, uint8_t status) { + if (status != 0) { + LOG_INFO("OOB get advertiser ID failed with status %hhd", status); + invoke_oob_data_request_cb(transport, false, c, r, RawAddress{}, 0x00); + SMP_ClearLocScOobData(); + return; + } + LOG_DEBUG("OOB advertiser with id %hhd", id); + auto advertiser = get_ble_advertiser_instance(); + advertiser->GetOwnAddress( + id, base::Bind(&get_address_callback, transport, is_valid, c, r)); +} + +static void timeout_cb(uint8_t id, uint8_t status) { + LOG_INFO("OOB advertiser with id %hhd timed out with status %hhd", id, + status); + auto advertiser = get_ble_advertiser_instance(); + advertiser->Unregister(id); + SMP_ClearLocScOobData(); +} + +// Step Two: CallBack from Step One, advertise and get address +static void id_status_callback(tBT_TRANSPORT transport, bool is_valid, + const Octet16& c, const Octet16& r, uint8_t id, + uint8_t status) { + if (status != 0) { + LOG_INFO("OOB get advertiser ID failed with status %hhd", status); + invoke_oob_data_request_cb(transport, false, c, r, RawAddress{}, 0x00); + SMP_ClearLocScOobData(); + return; + } + + auto advertiser = get_ble_advertiser_instance(); + AdvertiseParameters parameters; + parameters.advertising_event_properties = 0x0041 /* connectable, tx power */; + parameters.min_interval = 0xa0; // 100 ms + parameters.max_interval = 0x500; // 800 ms + parameters.channel_map = 0x7; // Use all the channels + parameters.tx_power = 0; // 0 dBm + parameters.primary_advertising_phy = 1; + parameters.secondary_advertising_phy = 2; + parameters.scan_request_notification_enable = 0; + + std::vector advertisement{0x02, 0x01 /* Flags */, + 0x02 /* Connectable */}; + std::vector scan_data{}; + + advertiser->StartAdvertising( + id, + base::Bind(&start_advertising_callback, id, transport, is_valid, c, r), + parameters, advertisement, scan_data, 3600 /* timeout_s */, + base::Bind(&timeout_cb, id)); +} + +// Step One: Start the advertiser +static void start_oob_advertiser(tBT_TRANSPORT transport, bool is_valid, + const Octet16& c, const Octet16& r) { + auto advertiser = get_ble_advertiser_instance(); + advertiser->RegisterAdvertiser( + base::Bind(&id_status_callback, transport, is_valid, c, r)); +} + void btif_dm_proc_loc_oob(tBT_TRANSPORT transport, bool is_valid, const Octet16& c, const Octet16& r) { - invoke_oob_data_request_cb(transport, is_valid, c, r, - *controller_get_interface()->get_address()); + // is_valid is important for deciding which OobDataCallback function to use + if (!is_valid) + invoke_oob_data_request_cb(transport, false, c, r, RawAddress{}, 0x00); + // Now that we have the data, lets start advertising and get the address. + start_oob_advertiser(transport, is_valid, c, r); } /******************************************************************************* diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h index bc4060cdc..9787bd856 100644 --- a/stack/include/smp_api.h +++ b/stack/include/smp_api.h @@ -182,14 +182,17 @@ extern void SMP_SecureConnectionOobDataReply(uint8_t* p_data); * Description This function is called to generate a public key to be * passed to a remote device via an Out of Band transport * - * Parameters: callback - receive the data + ******************************************************************************/ +extern void SMP_CrLocScOobData(); + +/******************************************************************************* + * + * Function SMP_ClearLocScOobData + * + * Description This function is called to clear out the OOB stored locally. * ******************************************************************************/ -extern void SMP_CrLocScOobData( - base::OnceCallback&, - const std::array&)> - callback); +extern void SMP_ClearLocScOobData(); // Called when LTK request is received from controller. extern bool smp_proc_ltk_request(const RawAddress& bda); diff --git a/stack/smp/smp_api.cc b/stack/smp/smp_api.cc index 452e68f73..164971dfc 100644 --- a/stack/smp/smp_api.cc +++ b/stack/smp/smp_api.cc @@ -557,16 +557,19 @@ void SMP_SecureConnectionOobDataReply(uint8_t* p_data) { * Function SMP_CrLocScOobData * * Description This function is called to generate a public key to be - * passed to a remote device via Out of Band transport - * - * Parameters: callback - receive the data + * passed to a remote device via Out of Band transport. * ******************************************************************************/ -void SMP_CrLocScOobData( - base::OnceCallback&, - const std::array&)> - callback) { +void SMP_CrLocScOobData() { tSMP_INT_DATA smp_int_data; smp_sm_event(&smp_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, &smp_int_data); } + +/******************************************************************************* + * + * Function SMP_ClearLocScOobData + * + * Description This function is called to clear out the OOB stored locally. + * + ******************************************************************************/ +void SMP_ClearLocScOobData() { smp_clear_local_oob_data(); } diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h index 88f125cd6..54fdfdffa 100644 --- a/stack/smp/smp_int.h +++ b/stack/smp/smp_int.h @@ -464,5 +464,6 @@ extern void smp_xor_128(Octet16* a, const Octet16& b); /* Save the p_cb->sc_oob_data.loc_oob_data for later, since the p_cb gets * cleaned up */ extern void smp_save_local_oob_data(tSMP_CB* p_cb); +extern void smp_clear_local_oob_data(); #endif /* SMP_INT_H */ diff --git a/stack/smp/smp_keys.cc b/stack/smp/smp_keys.cc index 2bddd0ded..50b9245d4 100644 --- a/stack/smp/smp_keys.cc +++ b/stack/smp/smp_keys.cc @@ -63,6 +63,8 @@ void smp_save_local_oob_data(tSMP_CB* p_cb) { saved_local_oob_data = p_cb->sc_oob_data.loc_oob_data; } +void smp_clear_local_oob_data() { saved_local_oob_data = {}; } + static bool is_empty(tSMP_LOC_OOB_DATA* data) { tSMP_LOC_OOB_DATA empty_data = {}; return memcmp(data, &empty_data, sizeof(tSMP_LOC_OOB_DATA)) == 0; diff --git a/test/mock/mock_stack_smp_api.cc b/test/mock/mock_stack_smp_api.cc index ae48e423d..6d6335a47 100644 --- a/test/mock/mock_stack_smp_api.cc +++ b/test/mock/mock_stack_smp_api.cc @@ -79,10 +79,6 @@ void SMP_SecurityGrant(const RawAddress& bd_addr, tSMP_STATUS res) { mock_function_count_map[__func__]++; } -void SMP_CrLocScOobData( - base::OnceCallback&, - const std::array&)> - callback) { - mock_function_count_map[__func__]++; -} +void SMP_CrLocScOobData() { mock_function_count_map[__func__]++; } + +void SMP_ClearLocScOobData() { mock_function_count_map[__func__]++; } -- 2.11.0