/* * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "clar.h" #include #include #include "services/common/bluetooth/bluetooth_persistent_storage.h" #include "services/normal/bluetooth/bluetooth_persistent_storage_unittest_impl.h" #include "services/normal/settings/settings_file.h" #include "services/normal/filesystem/pfs.h" #include "services/common/event_service.h" #include "services/common/analytics/analytics.h" #include "services/common/analytics/analytics_external.h" #include "flash_region/flash_region.h" // Stubs //////////////////////////////////// typedef struct GAPLEConnection GAPLEConnection; #include "fake_bonding_sync.h" #include "fake_rtc.h" #include "fake_spi_flash.h" #include "fake_system_task.h" #include "fake_events.h" #include "fake_new_timer.h" #include "fake_pbl_malloc.h" #include "fake_shared_prf_storage.h" #include "stubs_bluetopia_interface.h" #include "stubs_bluetooth_persistent_storage_debug.h" #include "stubs_bt_driver.h" #include "stubs_bt_lock.h" #include "stubs_gap_le_advert.h" #include "stubs_bluetooth_analytics.h" #include "stubs_gatt_client_discovery.h" #include "stubs_gatt_client_subscriptions.h" #include "stubs_logging.h" #include "stubs_mutex.h" #include "stubs_passert.h" #include "stubs_pebble_pairing_service.h" #include "stubs_print.h" #include "stubs_prompt.h" #include "stubs_regular_timer.h" #include "stubs_serial.h" #include "stubs_sleep.h" #include "stubs_system_reset.h" #include "stubs_task_watchdog.h" static int s_ble_bonding_change_add_count; static int s_ble_bonding_change_update_count; static int s_ble_bonding_change_delete_count; static int s_analytics_ble_pairings_count; typedef bool (*BondingSyncFilterCb)(const BleBonding *bonding, void *ctx); const BleBonding *bonding_sync_find(BondingSyncFilterCb cb, void *ctx) { return NULL; } void bt_driver_pebble_pairing_service_handle_status_change(const GAPLEConnection *connection) { } bool bt_ctl_is_bluetooth_running(void) { return true; } void bt_driver_handle_le_conn_params_update_event( const BleConnectionUpdateCompleteEvent *event) { } typedef struct PairingUserConfirmationCtx PairingUserConfirmationCtx; void bt_driver_cb_pairing_confirm_handle_request(const PairingUserConfirmationCtx *ctx, const char *device_name, const char *confirmation_token) { } void bt_driver_cb_pairing_confirm_handle_completed(const PairingUserConfirmationCtx *ctx, bool success) { } void cc2564A_bad_le_connection_complete_handle(unsigned int stack_id, const GAP_LE_Current_Connection_Parameters_t *params) { } void gap_le_connect_handle_bonding_change(BTBondingID bonding_id, BtPersistBondingOp op) { } void gap_le_connection_handle_bonding_change(BTBondingID bonding, BtPersistBondingOp op) { } void gap_le_device_name_request(uintptr_t stack_id, GAPLEConnection *connection) { } void bt_pairability_update_due_to_bonding_change(void) { } void bt_local_addr_handle_bonding_change(BTBondingID bonding, BtPersistBondingOp op) { } void kernel_le_client_handle_bonding_change(BTBondingID bonding, BtPersistBondingOp op) { if (op == BtPersistBondingOpDidAdd) { s_ble_bonding_change_add_count++; } else if (op == BtPersistBondingOpDidChange) { s_ble_bonding_change_update_count++; } else if (op == BtPersistBondingOpWillDelete) { s_ble_bonding_change_delete_count++; } return; } void analytics_set(AnalyticsMetric metric, int64_t val, AnalyticsClient client) { if (metric == ANALYTICS_DEVICE_METRIC_BLE_PAIRING_RECORDS_COUNT) { s_analytics_ble_pairings_count = val; } } void analytics_event_bt_error(AnalyticsEvent type, uint32_t error) { } void analytics_inc(AnalyticsMetric metric, AnalyticsClient client) { } void gap_update_bt_classic_connectability(void) { } uint16_t gaps_get_starting_att_handle(void) { return 4; } void gatt_service_changed_server_cleanup_by_connection(GAPLEConnection *connection) { } void launcher_task_add_callback(void (*callback)(void *data), void *data) { callback(data); } // Tests /////////////////////////////////////////////////////////// void test_bluetooth_persistent_storage__initialize(void) { bonding_sync_init(); fake_spi_flash_init(0, 0x1000000); pfs_init(false); s_ble_bonding_change_add_count = 0; s_ble_bonding_change_update_count = 0; s_ble_bonding_change_delete_count = 0; s_analytics_ble_pairings_count = 0; fake_shared_prf_storage_reset_counts(); bt_persistent_storage_init(); } void test_bluetooth_persistent_storage__cleanup(void) { bonding_sync_deinit(); } /////////////////////////////////////////////////////////////////////////////////////////////////// //! BLE Pairing Info void test_bluetooth_persistent_storage__ble_address_pinning(void) { cl_assert_equal_b(bt_persistent_storage_has_pinned_ble_pairings(), false); BTDeviceAddress address_out = {}; cl_assert_equal_b(bt_persistent_storage_get_ble_pinned_address(&address_out), false); BTDeviceAddress address_out_expected = {}; cl_assert_equal_m(&address_out_expected, &address_out, sizeof(address_out)); BTDeviceAddress address = (BTDeviceAddress) { .octets = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }, }; cl_assert_equal_b(bt_persistent_storage_set_ble_pinned_address(&address), true); SMPairingInfo pairing_1 = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) { .data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00 }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }, }, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, .is_mitm_protection_enabled = true, }; BleBonding ble_bonding = (BleBonding) { .is_gateway = true, .pairing_info = pairing_1, }; bonding_sync_add_bonding(&ble_bonding); BTBondingID id = bt_persistent_storage_store_ble_pairing(&pairing_1, true /* is_gateway */, NULL, true /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id != BT_BONDING_ID_INVALID); cl_assert_equal_b(bt_persistent_storage_has_pinned_ble_pairings(), true); bt_persistent_storage_delete_ble_pairing_by_id(id); cl_assert_equal_b(bt_persistent_storage_has_pinned_ble_pairings(), false); cl_assert_equal_b(bt_persistent_storage_set_ble_pinned_address(NULL), true); cl_assert_equal_b(bt_persistent_storage_get_ble_pinned_address(NULL), false); } void test_bluetooth_persistent_storage__ble_store_and_get(void) { bool ret; // Output variables SMIdentityResolvingKey irk_out; BTDeviceInternal device_out; // Store a new pairing SMPairingInfo pairing_1; memset(&pairing_1, 0x00, sizeof(pairing_1)); pairing_1 = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) { .data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00 }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }, }, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, .is_mitm_protection_enabled = true, }; BTBondingID id_1 = bt_persistent_storage_store_ble_pairing(&pairing_1, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id_1 != BT_BONDING_ID_INVALID); cl_assert_equal_i(s_ble_bonding_change_add_count, 1); cl_assert_equal_i(fake_shared_prf_storage_get_ble_store_count(), 1); cl_assert_equal_b(bt_persistent_storage_has_pinned_ble_pairings(), false); // Read it back ret = bt_persistent_storage_get_ble_pairing_by_id(id_1, &irk_out, &device_out, NULL /* name */); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing_1.irk, sizeof(irk_out)); cl_assert_equal_m(&device_out, &pairing_1.identity, sizeof(device_out)); // Store another pairing SMPairingInfo pairing_2; memset(&pairing_2, 0x00, sizeof(pairing_2)); pairing_2 = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) { .data = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x08, 0x09, 0x02, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x20, }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x21, 0x22, 0x13, 0x14, 0x15, 0x26, }, }, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; BTBondingID id_2 = bt_persistent_storage_store_ble_pairing(&pairing_2, false /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id_2 != BT_BONDING_ID_INVALID); cl_assert_equal_i(s_ble_bonding_change_add_count, 2); cl_assert_equal_i(fake_shared_prf_storage_get_ble_store_count(), 1); // This wasn't a gateway // Read both pairings back ret = bt_persistent_storage_get_ble_pairing_by_id(id_1, &irk_out, &device_out, NULL /* name */); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing_1.irk, sizeof(irk_out)); cl_assert_equal_m(&device_out, &pairing_1.identity, sizeof(device_out)); ret = bt_persistent_storage_get_ble_pairing_by_id(id_2, &irk_out, &device_out, NULL /* name */); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing_2.irk, sizeof(irk_out)); cl_assert_equal_m(&device_out, &pairing_2.identity, sizeof(device_out)); // Update first pairing (with the same data) BTBondingID id_X = bt_persistent_storage_store_ble_pairing(&pairing_1, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert_equal_i(id_1, id_X); cl_assert_equal_i(s_ble_bonding_change_update_count, 1); cl_assert_equal_i(fake_shared_prf_storage_get_ble_store_count(), 1); // Read both pairings back again ret = bt_persistent_storage_get_ble_pairing_by_id(id_1, &irk_out, &device_out, NULL /* name */); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing_1.irk, sizeof(irk_out)); cl_assert_equal_m(&device_out, &pairing_1.identity, sizeof(device_out)); ret = bt_persistent_storage_get_ble_pairing_by_id(id_2, &irk_out, &device_out, NULL /* name */); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing_2.irk, sizeof(irk_out)); cl_assert_equal_m(&device_out, &pairing_2.identity, sizeof(device_out)); // Add a thrid pairing SMPairingInfo pairing_3; memset(&pairing_3, 0x00, sizeof(pairing_3)); pairing_3 = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) { .data = { 0x91, 0x22, 0x73, 0x24, 0x25, 0x26, 0x27, 0x08, 0x69, 0x02, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x99, }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x29, 0x92, 0x13, 0x99, 0x15, 0x96, }, }, .is_classic = true, .is_random_address = true, }, .is_remote_identity_info_valid = true, }; BTBondingID id_3 = bt_persistent_storage_store_ble_pairing(&pairing_3, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id_3 != BT_BONDING_ID_INVALID); cl_assert_equal_i(s_ble_bonding_change_add_count, 3); cl_assert_equal_i(fake_shared_prf_storage_get_ble_store_count(), 2); // Read all three pairings back ret = bt_persistent_storage_get_ble_pairing_by_id(id_1, &irk_out, &device_out, NULL /* name */); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing_1.irk, sizeof(irk_out)); cl_assert_equal_m(&device_out, &pairing_1.identity, sizeof(device_out)); ret = bt_persistent_storage_get_ble_pairing_by_id(id_2, &irk_out, &device_out, NULL /* name */); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing_2.irk, sizeof(irk_out)); cl_assert_equal_m(&device_out, &pairing_2.identity, sizeof(device_out)); ret = bt_persistent_storage_get_ble_pairing_by_id(id_3, &irk_out, &device_out, NULL /* name */); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing_3.irk, sizeof(irk_out)); cl_assert_equal_m(&device_out, &pairing_3.identity, sizeof(device_out)); bt_persistent_storage_register_existing_ble_bondings(); cl_assert_equal_b(bonding_sync_contains_pairing_info(&pairing_1, true), true); cl_assert_equal_b(bonding_sync_contains_pairing_info(&pairing_2, false), true); cl_assert_equal_b(bonding_sync_contains_pairing_info(&pairing_3, true), true); } void test_bluetooth_persistent_storage__get_ble_by_addr(void) { bool ret; // Output variables SMIdentityResolvingKey irk_out; // Store a pairing SMPairingInfo pairing = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) { .data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, }, }, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; BTBondingID id = bt_persistent_storage_store_ble_pairing(&pairing, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id != BT_BONDING_ID_INVALID); // Read it back ret = bt_persistent_storage_get_ble_pairing_by_addr(&pairing.identity, &irk_out, NULL); cl_assert(ret); cl_assert_equal_m(&irk_out, &pairing.irk, sizeof(irk_out)); } void test_bluetooth_persistent_storage__delete_ble_pairing_by_id(void) { bool ret; // Output variables SMIdentityResolvingKey irk_out; BTDeviceInternal device_out; // Store a pairing SMPairingInfo pairing = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) { .data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, }, }, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; BleBonding ble_bonding = (BleBonding) { .is_gateway = true, .pairing_info = pairing, }; bonding_sync_add_bonding(&ble_bonding); BTBondingID id = bt_persistent_storage_store_ble_pairing(&pairing, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id != BT_BONDING_ID_INVALID); cl_assert_equal_i(s_ble_bonding_change_add_count, 1); cl_assert_equal_i(fake_shared_prf_storage_get_ble_store_count(), 1); cl_assert_equal_i(fake_shared_prf_storage_get_ble_delete_count(), 1); // Delete the Pairing bt_persistent_storage_delete_ble_pairing_by_id(id); cl_assert_equal_i(s_ble_bonding_change_delete_count, 1); cl_assert_equal_i(fake_shared_prf_storage_get_ble_delete_count(), 2); // Try to read it back ret = bt_persistent_storage_get_ble_pairing_by_id(id, &irk_out, &device_out, NULL); cl_assert(!ret); // Add the pairing again bonding_sync_add_bonding(&ble_bonding); id = bt_persistent_storage_store_ble_pairing(&pairing, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id != BT_BONDING_ID_INVALID); cl_assert_equal_i(s_ble_bonding_change_add_count, 2); cl_assert_equal_i(fake_shared_prf_storage_get_ble_store_count(), 2); // Delete a pairing that doesn't exist. Delete count should stay at 1 bt_persistent_storage_delete_ble_pairing_by_id(9); cl_assert_equal_i(s_ble_bonding_change_delete_count, 1); cl_assert_equal_i(fake_shared_prf_storage_get_ble_delete_count(), 3); // Make sure the pairing is actually still there ret = bt_persistent_storage_get_ble_pairing_by_id(id, &irk_out, &device_out, NULL); cl_assert(ret); // And delete is again bt_persistent_storage_delete_ble_pairing_by_id(id); cl_assert_equal_i(s_ble_bonding_change_delete_count, 2); cl_assert_equal_i(fake_shared_prf_storage_get_ble_delete_count(), 4); // Try to read it back ret = bt_persistent_storage_get_ble_pairing_by_id(id, &irk_out, &device_out, NULL); cl_assert(!ret); } void test_bluetooth_persistent_storage__analytics_external_collect_ble_pairing_info(void) { // No pairings yet analytics_external_collect_ble_pairing_info(); cl_assert_equal_i(s_analytics_ble_pairings_count, 0); // Store a pairing SMPairingInfo pairing = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) { .data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, }, }, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; BleBonding ble_bonding = (BleBonding) { .is_gateway = true, .pairing_info = pairing, }; bonding_sync_add_bonding(&ble_bonding); BTBondingID id = bt_persistent_storage_store_ble_pairing(&pairing, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id != BT_BONDING_ID_INVALID); // We should now be at 1 analytics_external_collect_ble_pairing_info(); cl_assert_equal_i(s_analytics_ble_pairings_count, 1); // Delete the Pairing bt_persistent_storage_delete_ble_pairing_by_id(id); cl_assert_equal_i(s_ble_bonding_change_delete_count, 1); // We should now be at 0 analytics_external_collect_ble_pairing_info(); cl_assert_equal_i(s_analytics_ble_pairings_count, 0); } void test_bluetooth_persistent_storage__ble_ancs_bonding(void) { bool ret; SMPairingInfo pairing = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) { .data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, }, }, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; // This pairing is a heart rate monitor or something similar BTBondingID id = bt_persistent_storage_store_ble_pairing(&pairing, false /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id != BT_BONDING_ID_INVALID); // No ANCS bonding yet BTBondingID ancs_id = bt_persistent_storage_get_ble_ancs_bonding(); cl_assert_equal_i(ancs_id, BT_BONDING_ID_INVALID); ret = bt_persistent_storage_has_ble_ancs_bonding(); cl_assert(!ret); ret = bt_persistent_storage_is_ble_ancs_bonding(id); cl_assert(!ret); // Store another pairing, this one is a gateway (supports ancs) pairing.identity.address.octets[0] = 0x12; BTBondingID id2 = bt_persistent_storage_store_ble_pairing(&pairing, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id2 != BT_BONDING_ID_INVALID); // Find it ancs_id = bt_persistent_storage_get_ble_ancs_bonding(); cl_assert_equal_i(ancs_id, id2); ret = bt_persistent_storage_has_ble_ancs_bonding(); cl_assert(ret); ret = bt_persistent_storage_is_ble_ancs_bonding(id2); cl_assert(ret); } void test_bluetooth_persistent_storage__ble_device_name(void) { SMPairingInfo pairing = { .irk = (SMIdentityResolvingKey) { .data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, }, }, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) { .octets = { 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, }, }, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; const char *device_name = "iPhone"; BTBondingID id = bt_persistent_storage_store_ble_pairing(&pairing, false /* is_gateway */, device_name, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id != BT_BONDING_ID_INVALID); char device_name_out[BT_DEVICE_NAME_BUFFER_SIZE]; bt_persistent_storage_get_ble_pairing_by_id(id, NULL, NULL, device_name_out); cl_assert_equal_i(strcmp(device_name, device_name_out), 0); // Update: const char *new_device_name = "New iPhone"; bt_persistent_storage_update_ble_device_name(id, new_device_name); bt_persistent_storage_get_ble_pairing_by_id(id, NULL, NULL, device_name_out); cl_assert_equal_i(strcmp(new_device_name, device_name_out), 0); } /////////////////////////////////////////////////////////////////////////////////////////////////// //! BT Classic Pairing Info void test_bluetooth_persistent_storage__bt_classic_store_and_get(void) { bool ret; // Output variables BTDeviceAddress addr_out; SM128BitKey link_key_out; char name_out[BT_DEVICE_NAME_BUFFER_SIZE]; uint8_t platform_bits_out; // Store a new pairing BTDeviceAddress addr_1 = {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_1 = {{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_1[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 1"; uint8_t platform_bits_1 = 0x11; BTBondingID id_1 = bt_persistent_storage_store_bt_classic_pairing(&addr_1, &link_key_1, name_1, &platform_bits_1); cl_assert(id_1 != BT_BONDING_ID_INVALID); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_store_count(), 1); // Read it back ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_1, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); cl_assert_equal_m(&addr_1, &addr_out, sizeof(addr_out)); cl_assert_equal_m(&link_key_1, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_1, name_out); cl_assert_equal_i(platform_bits_1, platform_bits_out); // Store another pairing BTDeviceAddress addr_2 = {{0x21, 0x22, 0x23, 0x24, 0x25, 0x26}}; SM128BitKey link_key_2 = {{0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}}; char name_2[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 2"; uint8_t platform_bits_2 = 0x22; BTBondingID id_2 = bt_persistent_storage_store_bt_classic_pairing(&addr_2, &link_key_2, name_2, &platform_bits_2); cl_assert(id_2 != BT_BONDING_ID_INVALID); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_store_count(), 2); // Read both pairings back ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_1, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); cl_assert_equal_m(&addr_1, &addr_out, sizeof(addr_out)); cl_assert_equal_m(&link_key_1, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_1, name_out); cl_assert_equal_i(platform_bits_1, platform_bits_out); ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_2, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); cl_assert_equal_m(&addr_2, &addr_out, sizeof(addr_out)); cl_assert_equal_m(&link_key_2, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_2, name_out); cl_assert_equal_i(platform_bits_2, platform_bits_out); // Update first pairing (with the same data) BTBondingID id_X = bt_persistent_storage_store_bt_classic_pairing(&addr_1, &link_key_1, name_1, &platform_bits_1); cl_assert_equal_i(id_1, id_X); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_store_count(), 2); // Read both pairings back again ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_1, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); cl_assert_equal_m(&addr_1, &addr_out, sizeof(addr_out)); cl_assert_equal_m(&link_key_1, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_1, name_out); cl_assert_equal_i(platform_bits_1, platform_bits_out); ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_2, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); cl_assert_equal_m(&addr_2, &addr_out, sizeof(addr_out)); cl_assert_equal_m(&link_key_2, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_2, name_out); cl_assert_equal_i(platform_bits_2, platform_bits_out); // Add a thrid pairing BTDeviceAddress addr_3 = {{0x31, 0x32, 0x33, 0x34, 0x35, 0x36}}; SM128BitKey link_key_3 = {{0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}}; char name_3[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 3"; uint8_t platform_bits_3 = 0x33; BTBondingID id_3 = bt_persistent_storage_store_bt_classic_pairing(&addr_3, &link_key_3, name_3, &platform_bits_3); cl_assert(id_3 != BT_BONDING_ID_INVALID); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_store_count(), 3); // Read all three pairings back ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_1, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); cl_assert_equal_m(&addr_1, &addr_out, sizeof(addr_out)); cl_assert_equal_m(&link_key_1, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_1, name_out); cl_assert_equal_i(platform_bits_1, platform_bits_out); ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_2, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); cl_assert_equal_m(&addr_2, &addr_out, sizeof(addr_out)); cl_assert_equal_m(&link_key_2, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_2, name_out); cl_assert_equal_i(platform_bits_2, platform_bits_out); ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_3, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); cl_assert_equal_m(&addr_3, &addr_out, sizeof(addr_out)); cl_assert_equal_m(&link_key_3, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_3, name_out); cl_assert_equal_i(platform_bits_3, platform_bits_out); // Add a fourth pairing BTDeviceAddress addr_4 = {{0x41, 0x42, 0x43, 0x34, 0x35, 0x44}}; SM128BitKey link_key_4 = {{0x40, 0x40, 0x30, 0x30, 0x30, 0x30, 0x30, 0x40, 0x40, 0x40, 0x30, 0x30, 0x30, 0x30, 0x30, 0x40}}; char name_4[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 4"; uint8_t platform_bits_4 = 0x44; // Don't add the platform bits BTBondingID id_4 = bt_persistent_storage_store_bt_classic_pairing(&addr_4, &link_key_4, name_4, NULL); cl_assert(id_4 != BT_BONDING_ID_INVALID); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_store_count(), 4); // Update with platform bits id_4 = bt_persistent_storage_store_bt_classic_pairing(&addr_4, NULL, NULL, &platform_bits_4); cl_assert(id_4 != BT_BONDING_ID_INVALID); } void test_bluetooth_persistent_storage__get_bt_classic_pairing_by_addr(void) { // Output variables SM128BitKey link_key_out; char name_out[BT_DEVICE_NAME_BUFFER_SIZE]; uint8_t platform_bits_out; // Store a new pairing BTDeviceAddress addr_in = {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_in = {{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_in[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 1"; uint8_t platform_bits_in = 0x11; BTBondingID id = bt_persistent_storage_store_bt_classic_pairing(&addr_in, &link_key_in, name_in, &platform_bits_in); cl_assert(id != BT_BONDING_ID_INVALID); // Read it back BTBondingID id_out = bt_persistent_storage_get_bt_classic_pairing_by_addr(&addr_in, &link_key_out, name_out, &platform_bits_out); cl_assert_equal_i(id, id_out); cl_assert_equal_m(&link_key_in, &link_key_out, sizeof(link_key_out)); cl_assert_equal_s(name_in, name_out); cl_assert_equal_i(platform_bits_in, platform_bits_out); // Now try to read out a pairing that doesn't exist addr_in.octets[0] = 0xff; id_out = bt_persistent_storage_get_bt_classic_pairing_by_addr(&addr_in, &link_key_out, name_out, &platform_bits_out); cl_assert(id_out == BT_BONDING_ID_INVALID); } void test_bluetooth_persistent_storage__delete_bt_classic_pairing_by_id(void) { bool ret; // Output variables BTDeviceAddress addr_out; SM128BitKey link_key_out; char name_out[BT_DEVICE_NAME_BUFFER_SIZE]; uint8_t platform_bits_out; // Store a new pairing BTDeviceAddress addr_in = {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_in = {{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_in[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 1"; uint8_t platform_bits_in = 0x11; BTBondingID id = bt_persistent_storage_store_bt_classic_pairing(&addr_in, &link_key_in, name_in, &platform_bits_in); cl_assert(id != BT_BONDING_ID_INVALID); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_store_count(), 1); // Delete the Pairing bt_persistent_storage_delete_bt_classic_pairing_by_id(id); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_delete_count(), 2); // Try to read it back ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(!ret); // Add the pairing again id = bt_persistent_storage_store_bt_classic_pairing(&addr_in, &link_key_in, name_in, &platform_bits_in); cl_assert(id != BT_BONDING_ID_INVALID); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_store_count(), 2); // Delete a pairing that doesn't exist bt_persistent_storage_delete_bt_classic_pairing_by_id(9); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_delete_count(), 3); // Make sure the pairing is actually still there ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); // And delete is again bt_persistent_storage_delete_bt_classic_pairing_by_id(id); cl_assert_equal_i(fake_shared_prf_storage_get_bt_classic_delete_count(), 4); // Try to read it back ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(!ret); } void test_bluetooth_persistent_storage__delete_bt_classic_pairing_by_addr(void) { bool ret; // Output variables BTDeviceAddress addr_out; SM128BitKey link_key_out; char name_out[BT_DEVICE_NAME_BUFFER_SIZE]; uint8_t platform_bits_out; // Store a new pairing BTDeviceAddress addr_in = {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_in = {{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_in[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 1"; uint8_t platform_bits_in = 0x11; BTBondingID id = bt_persistent_storage_store_bt_classic_pairing(&addr_in, &link_key_in, name_in, &platform_bits_in); cl_assert(id != BT_BONDING_ID_INVALID); // Delete the Pairing bt_persistent_storage_delete_bt_classic_pairing_by_addr(&addr_in); // Try to read it back ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(!ret); // Add the pairing again id = bt_persistent_storage_store_bt_classic_pairing(&addr_in, &link_key_in, name_in, &platform_bits_in); cl_assert(id != BT_BONDING_ID_INVALID); // Delete a pairing that doesn't exist BTDeviceAddress dummy_addr = {{0xff, 0x11, 0x22, 0x14, 0x15, 0x16}}; bt_persistent_storage_delete_bt_classic_pairing_by_addr(&dummy_addr); // Make sure the pairing is actually still there ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(ret); // And delete is again bt_persistent_storage_delete_bt_classic_pairing_by_addr(&addr_in); // Try to read it back ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id, &addr_out, &link_key_out, name_out, &platform_bits_out); cl_assert(!ret); } /////////////////////////////////////////////////////////////////////////////////////////////////// //! Local Device Info void test_bluetooth_persistent_storage__test_active_gateway(void) { bool ret; BtPersistBondingType type_out; BTBondingID id_out; // Nothing is stored, so no active gateways yet ret = bt_persistent_storage_get_active_gateway(&id_out, &type_out); cl_assert(!ret); ret = bt_persistent_storage_has_active_bt_classic_gateway_bonding(); cl_assert(!ret); ret = bt_persistent_storage_has_active_ble_gateway_bonding(); cl_assert(!ret); // Store a new BT Classic pairing BTDeviceAddress addr_1 = {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_1 = {{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_1[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 1"; uint8_t platform_bits_1 = 0x11; BTBondingID id_1 = bt_persistent_storage_store_bt_classic_pairing(&addr_1, &link_key_1, name_1, &platform_bits_1); cl_assert(id_1 != BT_BONDING_ID_INVALID); // It should be the active gateway ret = bt_persistent_storage_get_active_gateway(&id_out, &type_out); cl_assert(ret); cl_assert_equal_i(id_out, id_1); cl_assert_equal_i(type_out, BtPersistBondingTypeBTClassic); ret = bt_persistent_storage_has_active_bt_classic_gateway_bonding(); cl_assert(ret); ret = bt_persistent_storage_has_active_ble_gateway_bonding(); cl_assert(!ret); // Store another BT Classic pairing BTDeviceAddress addr_2 = {{0x22, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_2 = {{0x22, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_2[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 2"; uint8_t platform_bits_2 = 0x22; BTBondingID id_2 = bt_persistent_storage_store_bt_classic_pairing(&addr_2, &link_key_2, name_2, &platform_bits_2); cl_assert(id_2 != BT_BONDING_ID_INVALID); // The new pairing should be the active gateway ret = bt_persistent_storage_get_active_gateway(&id_out, &type_out); cl_assert(ret); cl_assert_equal_i(id_out, id_2); cl_assert_equal_i(type_out, BtPersistBondingTypeBTClassic); ret = bt_persistent_storage_has_active_bt_classic_gateway_bonding(); cl_assert(ret); ret = bt_persistent_storage_has_active_ble_gateway_bonding(); cl_assert(!ret); // Delete the pairing. bt_persistent_storage_delete_bt_classic_pairing_by_id(id_2); // There should be no active gateway now ret = bt_persistent_storage_get_active_gateway(&id_out, &type_out); cl_assert(!ret); ret = bt_persistent_storage_has_active_bt_classic_gateway_bonding(); cl_assert(!ret); ret = bt_persistent_storage_has_active_ble_gateway_bonding(); cl_assert(!ret); // Store a new BLE pairing SMPairingInfo pairing_1 = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) {{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}}, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; BTBondingID id_3 = bt_persistent_storage_store_ble_pairing(&pairing_1, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id_3 != BT_BONDING_ID_INVALID); // There should still be no active gateway ret = bt_persistent_storage_get_active_gateway(&id_out, &type_out); cl_assert(!ret); ret = bt_persistent_storage_has_active_bt_classic_gateway_bonding(); cl_assert(!ret); ret = bt_persistent_storage_has_active_ble_gateway_bonding(); cl_assert(!ret); // Manually set the active gateway bt_persistent_storage_set_active_gateway(id_1); ret = bt_persistent_storage_get_active_gateway(&id_out, &type_out); cl_assert(ret); cl_assert_equal_i(id_out, id_1); cl_assert_equal_i(type_out, BtPersistBondingTypeBTClassic); ret = bt_persistent_storage_has_active_bt_classic_gateway_bonding(); cl_assert(ret); ret = bt_persistent_storage_has_active_ble_gateway_bonding(); cl_assert(!ret); // Manually set the active gateway again (to the ble pairing) bt_persistent_storage_set_active_gateway(id_3); ret = bt_persistent_storage_get_active_gateway(&id_out, &type_out); cl_assert(ret); cl_assert_equal_i(id_out, id_3); cl_assert_equal_i(type_out, BtPersistBondingTypeBLE); ret = bt_persistent_storage_has_active_bt_classic_gateway_bonding(); cl_assert(!ret); ret = bt_persistent_storage_has_active_ble_gateway_bonding(); cl_assert(ret); } void test_bluetooth_persistent_storage__test_is_faithful(void) { bool ret; // No pairing yet, we should be unfaithful ret = bt_persistent_storage_is_unfaithful(); cl_assert(ret); // Add a pairing, still unfaithful BTDeviceAddress addr_1 = {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_1 = {{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_1[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 1"; uint8_t platform_bits_1 = 0x11; BTBondingID id_1 = bt_persistent_storage_store_bt_classic_pairing(&addr_1, &link_key_1, name_1, &platform_bits_1); cl_assert(id_1 != BT_BONDING_ID_INVALID); ret = bt_persistent_storage_is_unfaithful(); cl_assert(ret); // A "sync" happened. We are now faithful bt_persistent_storage_set_unfaithful(false); ret = bt_persistent_storage_is_unfaithful(); cl_assert(!ret); // Add a new pairing, the active gateway should have changed making us unfaithful BTDeviceAddress addr_2 = {{0x22, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_2 = {{0x22, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_2[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 2"; uint8_t platform_bits_2 = 0x22; BTBondingID id_2 = bt_persistent_storage_store_bt_classic_pairing(&addr_2, &link_key_2, name_2, &platform_bits_2); cl_assert(id_2 != BT_BONDING_ID_INVALID); ret = bt_persistent_storage_is_unfaithful(); cl_assert(ret); // A "sync" happened. We are now faithful bt_persistent_storage_set_unfaithful(false); ret = bt_persistent_storage_is_unfaithful(); cl_assert(!ret); // Add a BLE pairing. We should still be faithful (no PPoGATT yet) SMPairingInfo pairing_1 = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) {{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00 }}, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; BTBondingID id_3 = bt_persistent_storage_store_ble_pairing(&pairing_1, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(id_3 != BT_BONDING_ID_INVALID); ret = bt_persistent_storage_is_unfaithful(); cl_assert(!ret); // Manually set a new active gateway. bt_persistent_storage_set_active_gateway(id_3); ret = bt_persistent_storage_is_unfaithful(); cl_assert(ret); // We should be unfaithful ret = bt_persistent_storage_is_unfaithful(); cl_assert(ret); // A "sync" happened. We are now faithful bt_persistent_storage_set_unfaithful(false); ret = bt_persistent_storage_is_unfaithful(); cl_assert(!ret); // Another "sync" happened. We should still be faithful bt_persistent_storage_set_unfaithful(false); ret = bt_persistent_storage_is_unfaithful(); cl_assert(!ret); } void test_bluetooth_persistent_storage__test_root_keys(void) { SM128BitKey keys[2] = { {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}, {{0x21, 0x22, 0x23, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x11, 0x12, 0x13, 0x24, 0x25, 0x26}}, }; SM128BitKey keys_out[2]; bt_persistent_storage_set_root_keys(keys); bt_persistent_storage_get_root_key(0, &keys_out[0]); bt_persistent_storage_get_root_key(1, &keys_out[1]); cl_assert_equal_m(&keys[0], &keys_out[0], sizeof(SM128BitKey)); cl_assert_equal_m(&keys[1], &keys_out[1], sizeof(SM128BitKey)); bt_persistent_storage_init(); bt_persistent_storage_get_root_key(0, &keys_out[0]); bt_persistent_storage_get_root_key(1, &keys_out[1]); cl_assert_equal_m(&keys[0], &keys_out[0], sizeof(SM128BitKey)); cl_assert_equal_m(&keys[1], &keys_out[1], sizeof(SM128BitKey)); } void test_bluetooth_persistent_storage__delete_all(void) { bool ret; // Add some pairings // BT Classic pairing 1 BTDeviceAddress addr_1 = {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_1 = {{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_1[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 1"; uint8_t platform_bits_1 = 0x11; BTBondingID id_1 = bt_persistent_storage_store_bt_classic_pairing(&addr_1, &link_key_1, name_1, &platform_bits_1); cl_assert(id_1 != BT_BONDING_ID_INVALID); // BT Classic pairing 2 BTDeviceAddress addr_2 = {{0x22, 0x12, 0x13, 0x14, 0x15, 0x16}}; SM128BitKey link_key_2 = {{0x22, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}}; char name_2[BT_DEVICE_NAME_BUFFER_SIZE] = "Device 2"; uint8_t platform_bits_2 = 0x22; BTBondingID id_2 = bt_persistent_storage_store_bt_classic_pairing(&addr_2, &link_key_2, name_2, &platform_bits_2); cl_assert(id_2 != BT_BONDING_ID_INVALID); // BLE pairing 1 SMPairingInfo pairing_1 = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) {{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00 }}, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) {{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}}, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; BTBondingID id_3 = bt_persistent_storage_store_ble_pairing(&pairing_1, true /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); // BLE pairing 2 SMPairingInfo pairing_2 = (SMPairingInfo) { .irk = (SMIdentityResolvingKey) {{ 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x02, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00 }}, .identity = (BTDeviceInternal) { .address = (BTDeviceAddress) {{0x22, 0x12, 0x13, 0x14, 0x15, 0x16}}, .is_classic = false, .is_random_address = false, }, .is_remote_identity_info_valid = true, }; BTBondingID id_4 = bt_persistent_storage_store_ble_pairing(&pairing_2, false /* is_gateway */, NULL, false /* requires_address_pinning */, false /* auto_accept_re_pairing */); // Delete all bt_persistent_storage_delete_all_pairings(); // Try to get the pairings ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_1, NULL, NULL, NULL, NULL); cl_assert(!ret); ret = bt_persistent_storage_get_bt_classic_pairing_by_id(id_2, NULL, NULL, NULL, NULL); cl_assert(!ret); ret = bt_persistent_storage_get_ble_pairing_by_id(id_3, NULL, NULL, NULL); cl_assert(!ret); ret = bt_persistent_storage_get_ble_pairing_by_id(id_4, NULL, NULL, NULL); cl_assert(!ret); } // Test to make sure we don't accidentally change the serialized data formats. void test_bluetooth_persistent_storage__ble_serialized_data(void) { #if UNITTEST_BT_PERSISTENT_STORAGE_VERSION == 1 //0000 01 00 69 50 68 6f 6e 65 20 4d 61 72 74 79 00 00 ..iPhone Marty.. //0010 00 00 00 00 00 00 3f f9 92 8a 00 00 00 00 75 36 ......?. ......u6 //0020 9c 6e 1a 1b eb 5f fb 89 db 0b ec a5 95 7a 44 f6 .n..._.. .....zD. //0030 1c 47 90 53 43 18 f3 e7 00 00 00 00 00 00 d1 6d .G.SC... .......m //0040 89 95 83 aa 5e 7f ff 39 b3 47 36 e4 37 7e 05 1b ....^..9 .G6.7~.. //0050 85 e3 b8 98 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ //0060 00 00 00 00 00 00 07 00 00 00 00 00 00 00 ........ ...... const uint8_t expected_raw_data[] = { 0x01, 0x00, 0x69, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x20, 0x4d, 0x61, 0x72, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf9, 0x92, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x75, 0x36, 0x9c, 0x6e, 0x1a, 0x1b, 0xeb, 0x5f, 0xfb, 0x89, 0xdb, 0x0b, 0xec, 0xa5, 0x95, 0x7a, 0x44, 0xf6, 0x1c, 0x47, 0x90, 0x53, 0x43, 0x18, 0xf3, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x6d, 0x89, 0x95, 0x83, 0xaa, 0x5e, 0x7f, 0xff, 0x39, 0xb3, 0x47, 0x36, 0xe4, 0x37, 0x7e, 0x05, 0x1b, 0x85, 0xe3, 0xb8, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; size_t data_size = 110; #elif UNITTEST_BT_PERSISTENT_STORAGE_VERSION == 2 //0000 01 00 69 50 68 6f 6e 65 20 4d 61 72 74 79 00 00 ..iPhone Marty.. //0010 00 00 00 00 00 00 90 36 9c 6e 1a 1b eb 5f fb 89 .......6.n..._.. //0020 db 0b ec a5 95 ab 92 8a aa f6 1c 47 90 53 43 ff ...........G.SC. //0030 75 36 9c 6e 1a 1b eb 5f fb 89 db 0b ec a5 95 7a u6.n..._.......z //0040 f3 e7 44 f6 1c 47 90 53 43 18 d1 6d 89 95 83 aa ..D..G.SC..m.... //0050 5e 7f ff 39 b3 47 36 e4 37 7e 05 1b 85 e3 b8 98 ^..9.G6.7~...... //0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ //0070 00 00 17 ... ... const uint8_t expected_raw_data[] = { 0x01, 0x00, 0x69, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x20, 0x4d, 0x61, 0x72, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x36, 0x9c, 0x6e, 0x1a, 0x1b, 0xeb, 0x5f, 0xfb, 0x89, 0xdb, 0x0b, 0xec, 0xa5, 0x95, 0xab, 0x92, 0x8a, 0xaa, 0xf6, 0x1c, 0x47, 0x90, 0x53, 0x43, 0xff, 0x75, 0x36, 0x9c, 0x6e, 0x1a, 0x1b, 0xeb, 0x5f, 0xfb, 0x89, 0xdb, 0x0b, 0xec, 0xa5, 0x95, 0x7a, 0xf3, 0xe7, 0x44, 0xf6, 0x1c, 0x47, 0x90, 0x53, 0x43, 0x18, 0xd1, 0x6d, 0x89, 0x95, 0x83, 0xaa, 0x5e, 0x7f, 0xff, 0x39, 0xb3, 0x47, 0x36, 0xe4, 0x37, 0x7e, 0x05, 0x1b, 0x85, 0xe3, 0xb8, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, }; size_t data_size = 115; #else # error "Unknown version!" #endif const SMPairingInfo pairing_info = { .local_encryption_info = { .ltk = { .data = { 0x90, 0x36, 0x9c, 0x6e, 0x1a, 0x1b, 0xeb, 0x5f, 0xfb, 0x89, 0xdb, 0x0b, 0xec, 0xa5, 0x95, 0xab, }, }, .rand = 0xff435390471cf6aa, .div = 0xf93f, .ediv = 0x8a92, }, .remote_encryption_info = { .ltk = { .data = { 0x75, 0x36, 0x9c, 0x6e, 0x1a, 0x1b, 0xeb, 0x5f, 0xfb, 0x89, 0xdb, 0x0b, 0xec, 0xa5, 0x95, 0x7a, }, }, .rand = 0x18435390471cf644, .ediv = 0xe7f3, }, .irk = { .data = { 0xd1, 0x6d, 0x89, 0x95, 0x83, 0xaa, 0x5e, 0x7f, 0xff, 0x39, 0xb3, 0x47, 0x36, 0xe4, 0x37, 0x7e, } }, .identity = { { { .address = { .octets = {0x5, 0x1b, 0x85, 0xe3, 0xb8, 0x98} }, .is_classic = 0x0, .is_random_address = 0x0, .zero = 0x0, }, } }, .csrk = {}, .is_local_encryption_info_valid = 0x1, .is_remote_encryption_info_valid = 0x1, .is_remote_identity_info_valid = 0x1, .is_remote_signing_info_valid = 0x0, .is_mitm_protection_enabled = 0x1, }; BTBondingID key = bt_persistent_storage_store_ble_pairing(&pairing_info, false /* is_gateway */, "iPhone Marty", false /* requires_address_pinning */, false /* auto_accept_re_pairing */); cl_assert(key != BT_BONDING_ID_INVALID); uint8_t data[data_size]; memset(data, 0, sizeof(data)); int data_len = bt_persistent_storage_get_raw_data(&key, sizeof(key), data, data_size); cl_assert_equal_i(data_len, data_size); cl_assert_equal_m(expected_raw_data, data, sizeof(expected_raw_data)); } void test_bluetooth_persistent_storage__v1_bt_classic(void) { #if UNITTEST_BT_PERSISTENT_STORAGE_VERSION != 1 // We only care about BT Classic in v1. return; #endif BTDeviceAddress address = { .octets = {0x5, 0x1b, 0x85, 0xe3, 0xb8, 0x98}, }; SM128BitKey link_key = { .data = { 0xb5, 0xa8, 0x09, 0xcc, 0x1a, 0xdf, 0xfa, 0x8e, 0x96, 0x87, 0x76, 0xac, 0xcf, 0xb8, 0x15, 0x12, }, }; uint8_t platform_bits = 0x01; BTBondingID key = bt_persistent_storage_store_bt_classic_pairing(&address, &link_key, "iPhone Marty", &platform_bits); cl_assert(key != BT_BONDING_ID_INVALID); size_t v1_size = 110; uint8_t v1_data[v1_size]; memset(v1_data, 0, sizeof(v1_data)); int data_len = bt_persistent_storage_get_raw_data(&key, sizeof(key), v1_data, v1_size); cl_assert_equal_i(data_len, v1_size); // 00000000: 0005 1b85 e3b8 98b5 a809 cc1a dffa 8e96 ................ // 00000010: 8776 accf b815 1269 5068 6f6e 6520 4d61 .v.....iPhone Ma // 00000020: 7274 7900 0000 0000 0000 0001 0000 0000 rty............. // 00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ // 00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ // 00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................ // 00000060: 0000 0000 0000 0000 0000 0000 0000 .............. const uint8_t expected_raw_data[] = { 0x00, 0x05, 0x1b, 0x85, 0xe3, 0xb8, 0x98, 0xb5, 0xa8, 0x09, 0xcc, 0x1a, 0xdf, 0xfa, 0x8e, 0x96, 0x87, 0x76, 0xac, 0xcf, 0xb8, 0x15, 0x12, 0x69, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x20, 0x4d, 0x61, 0x72, 0x74, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; cl_assert_equal_m(expected_raw_data, v1_data, sizeof(expected_raw_data)); }