/* * 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 "fake_GAPAPI.h" #include "bluetopia_interface.h" #include #include "clar_asserts.h" static bool s_is_le_advertising_enabled; static GAP_LE_Event_Callback_t s_le_adv_connection_event_callback; static unsigned long s_le_adv_connection_callback_param; static uint16_t s_min_advertising_interval_slots; static uint16_t s_max_advertising_interval_slots; void gap_le_set_advertising_disabled(void) { s_is_le_advertising_enabled = false; s_min_advertising_interval_slots = 0; s_max_advertising_interval_slots = 0; } int GAP_LE_Advertising_Disable(unsigned int BluetoothStackID) { s_is_le_advertising_enabled = false; s_le_adv_connection_event_callback = NULL; s_le_adv_connection_callback_param = 0; s_min_advertising_interval_slots = 0; s_max_advertising_interval_slots = 0; return 0; } int GAP_LE_Advertising_Enable(unsigned int BluetoothStackID, Boolean_t EnableScanResponse, GAP_LE_Advertising_Parameters_t *GAP_LE_Advertising_Parameters, GAP_LE_Connectability_Parameters_t *GAP_LE_Connectability_Parameters, GAP_LE_Event_Callback_t GAP_LE_Event_Callback, unsigned long CallbackParameter) { s_is_le_advertising_enabled = true; s_le_adv_connection_event_callback = GAP_LE_Event_Callback; s_le_adv_connection_callback_param = CallbackParameter; if (GAP_LE_Advertising_Parameters) { // Convert from ms to slots: s_min_advertising_interval_slots = (GAP_LE_Advertising_Parameters->Advertising_Interval_Min * 16) / 10; s_max_advertising_interval_slots = (GAP_LE_Advertising_Parameters->Advertising_Interval_Max * 16) / 10; } else { s_min_advertising_interval_slots = 0; s_max_advertising_interval_slots = 0; } return 0; } void gap_le_assert_advertising_interval(uint16_t expected_min_slots, uint16_t expected_max_slots) { cl_assert_equal_i(s_min_advertising_interval_slots, expected_min_slots); cl_assert_equal_i(s_max_advertising_interval_slots, expected_max_slots); } bool gap_le_is_advertising_enabled(void) { return s_is_le_advertising_enabled; } static Advertising_Data_t s_ad_data; static unsigned int s_ad_data_length; int GAP_LE_Set_Advertising_Data(unsigned int BluetoothStackID, unsigned int Length, Advertising_Data_t *Advertising_Data) { memcpy(&s_ad_data, Advertising_Data, Length); s_ad_data_length = Length; return 0; } unsigned int gap_le_get_advertising_data(Advertising_Data_t *ad_data_out) { *ad_data_out = s_ad_data; return s_ad_data_length; } static Scan_Response_Data_t s_scan_resp_data; static unsigned int s_scan_resp_data_length; int GAP_LE_Set_Scan_Response_Data(unsigned int BluetoothStackID, unsigned int Length, Scan_Response_Data_t *Scan_Response_Data) { memcpy(&s_scan_resp_data, Scan_Response_Data, Length); s_scan_resp_data_length = Length; return 0; } unsigned int gap_le_get_scan_response_data(Scan_Response_Data_t *scan_resp_data_out) { *scan_resp_data_out = s_scan_resp_data; return s_scan_resp_data_length; } static GAP_LE_Event_Callback_t s_le_create_connection_event_callback; static unsigned long s_le_create_connection_callback_param; int GAP_LE_Create_Connection(unsigned int BluetoothStackID, unsigned int ScanInterval, unsigned int ScanWindow, GAP_LE_Filter_Policy_t InitatorFilterPolicy, GAP_LE_Address_Type_t RemoteAddressType, BD_ADDR_t *RemoteDevice, GAP_LE_Address_Type_t LocalAddressType, GAP_LE_Connection_Parameters_t *ConnectionParameters, GAP_LE_Event_Callback_t GAP_LE_Event_Callback, unsigned long CallbackParameter) { s_le_create_connection_event_callback = GAP_LE_Event_Callback; s_le_create_connection_callback_param = CallbackParameter; return 0; } void prv_fake_gap_le_create_connection_event_put(GAP_LE_Event_Data_t *event) { cl_assert(s_le_create_connection_event_callback != NULL); s_le_create_connection_event_callback(1, event, s_le_create_connection_callback_param); } void prv_fake_gap_le_adv_connection_event_put(GAP_LE_Event_Data_t *event) { cl_assert(s_le_adv_connection_event_callback != NULL); s_le_adv_connection_event_callback(1, event, s_le_adv_connection_callback_param); } void fake_gap_put_connection_event(uint8_t status, bool is_master, const BTDeviceInternal *device) { GAP_LE_Connection_Complete_Event_Data_t event_data = (GAP_LE_Connection_Complete_Event_Data_t) { .Status = status, .Master = is_master, .Peer_Address_Type = device->is_random_address ? latRandom : latPublic, .Peer_Address = BTDeviceAddressToBDADDR(device->address), }; GAP_LE_Event_Data_t event = (GAP_LE_Event_Data_t) { .Event_Data_Type = etLE_Connection_Complete, .Event_Data_Size = sizeof(GAP_LE_Connection_Complete_Event_Data_t), .Event_Data.GAP_LE_Connection_Complete_Event_Data = &event_data, }; if (is_master) { prv_fake_gap_le_create_connection_event_put(&event); } else { prv_fake_gap_le_adv_connection_event_put(&event); } } void fake_gap_put_disconnection_event(uint8_t status, uint8_t reason, bool is_master, const BTDeviceInternal *device) { GAP_LE_Disconnection_Complete_Event_Data_t event_data = (GAP_LE_Disconnection_Complete_Event_Data_t) { .Status = status, .Reason = reason, .Peer_Address_Type = device->is_random_address ? latRandom : latPublic, .Peer_Address = BTDeviceAddressToBDADDR(device->address), }; GAP_LE_Event_Data_t event = (GAP_LE_Event_Data_t) { .Event_Data_Type = etLE_Disconnection_Complete, .Event_Data_Size = sizeof(GAP_LE_Disconnection_Complete_Event_Data_t), .Event_Data.GAP_LE_Disconnection_Complete_Event_Data = &event_data, }; if (is_master) { prv_fake_gap_le_create_connection_event_put(&event); } else { prv_fake_gap_le_adv_connection_event_put(&event); } } void fake_GAPAPI_put_encryption_change_event(bool encrypted, uint8_t status, bool is_master, const BTDeviceInternal *device) { GAP_LE_Encryption_Change_Event_Data_t event_data = (GAP_LE_Encryption_Change_Event_Data_t) { .BD_ADDR = BTDeviceAddressToBDADDR(device->address), .Encryption_Change_Status = status, .Encryption_Mode = encrypted ? emEnabled : emDisabled, }; GAP_LE_Event_Data_t event = (GAP_LE_Event_Data_t) { .Event_Data_Type = etLE_Encryption_Change, .Event_Data_Size = sizeof(GAP_LE_Encryption_Change_Event_Data_t), .Event_Data.GAP_LE_Encryption_Change_Event_Data = &event_data, }; if (is_master) { prv_fake_gap_le_create_connection_event_put(&event); } else { prv_fake_gap_le_adv_connection_event_put(&event); } } int GAP_LE_Cancel_Create_Connection(unsigned int BluetoothStackID) { return 0; } // Puts the event that the BT Controller will emit after a succesfull // GAP_LE_Cancel_Create_Connection call. void fake_gap_le_put_cancel_create_event(const BTDeviceInternal *device, bool is_master) { fake_gap_put_connection_event(HCI_ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, is_master, device); } int GAP_LE_Disconnect(unsigned int BluetoothStackID, BD_ADDR_t BD_ADDR) { return 0; } int GAP_LE_Pair_Remote_Device(unsigned int BluetoothStackID, BD_ADDR_t BD_ADDR, GAP_LE_Pairing_Capabilities_t *Capabilities, GAP_LE_Event_Callback_t GAP_LE_Event_Callback, unsigned long CallbackParameter) { return 0; } // ------------------------------------------------------------------------------------------------- // Bluetopia's Security Manager API int GAP_LE_Authentication_Response(unsigned int BluetoothStackID, BD_ADDR_t BD_ADDR, GAP_LE_Authentication_Response_Information_t *GAP_LE_Authentication_Information) { return 0; } int GAP_LE_Diversify_Function(unsigned int BluetoothStackID, Encryption_Key_t *Key, Word_t DIn, Word_t RIn, Encryption_Key_t *Result) { return 0; } int GAP_LE_Generate_Long_Term_Key(unsigned int BluetoothStackID, Encryption_Key_t *DHK, Encryption_Key_t *ER, Long_Term_Key_t *LTK_Result, Word_t *DIV_Result, Word_t *EDIV_Result, Random_Number_t *Rand_Result) { return 0; } static BD_ADDR_t s_encrypted_device; int GAP_LE_Query_Encryption_Mode(unsigned int BluetoothStackID, BD_ADDR_t BD_ADDR, GAP_Encryption_Mode_t *GAP_Encryption_Mode) { *GAP_Encryption_Mode = (COMPARE_BD_ADDR(s_encrypted_device, BD_ADDR)) ? emEnabled : emDisabled; return 0; } void fake_GAPAPI_set_encrypted_for_device(const BTDeviceInternal *device) { s_encrypted_device = BTDeviceAddressToBDADDR(device->address); } int GAP_LE_Regenerate_Long_Term_Key(unsigned int BluetoothStackID, Encryption_Key_t *DHK, Encryption_Key_t *ER, Word_t EDIV, Random_Number_t *Rand, Long_Term_Key_t *LTK_Result) { return 0; } int GAP_LE_Register_Remote_Authentication(unsigned int BluetoothStackID, GAP_LE_Event_Callback_t GAP_LE_Event_Callback, unsigned long CallbackParameter) { return 0; } int GAP_LE_Un_Register_Remote_Authentication(unsigned int BluetoothStackID) { return 0; } int GAP_LE_Request_Security(unsigned int BluetoothStackID, BD_ADDR_t BD_ADDR, GAP_LE_Bonding_Type_t Bonding_Type, Boolean_t MITM, GAP_LE_Event_Callback_t GAP_LE_Event_Callback, unsigned long CallbackParameter) { return 0; } int GAP_LE_Set_Pairability_Mode(unsigned int BluetoothStackID, GAP_LE_Pairability_Mode_t PairableMode) { return 0; } int GAP_LE_Generate_Resolvable_Address(unsigned int BluetoothStackID, Encryption_Key_t *IRK, BD_ADDR_t *ResolvableAddress_Result) { return 0; } int GAP_LE_Set_Random_Address(unsigned int BluetoothStackID, BD_ADDR_t RandomAddress) { return 0; } int GAP_Query_Local_BD_ADDR(unsigned int BluetoothStackID, BD_ADDR_t *BD_ADDR) { return 0; } static const Encryption_Key_t s_fake_irk = { 0xaa, 0xaa, }; static const BD_ADDR_t s_resolving_bd_addr = { 0xaa, 0xff, 0xff, 0xff, 0xff, 0x7f /* 6th byte: bit 6 set, bit 7 unset indicates "resolvable private address" */ }; static const BD_ADDR_t s_not_resolving_bd_addr = { 0xff, }; const Encryption_Key_t *fake_GAPAPI_get_fake_irk(void) { return &s_fake_irk; } const BD_ADDR_t *fake_GAPAPI_get_bd_addr_not_resolving_to_fake_irk(void) { return &s_not_resolving_bd_addr; } const BTDeviceInternal *fake_GAPAPI_get_device_not_resolving_to_fake_irk(void) { static BTDeviceInternal s_not_resolving_device; s_not_resolving_device = (const BTDeviceInternal) { .address = BDADDRToBTDeviceAddress(s_not_resolving_bd_addr), .is_random_address = true, }; return &s_not_resolving_device; } const BD_ADDR_t *fake_GAPAPI_get_bd_addr_resolving_to_fake_irk(void) { return &s_resolving_bd_addr; } const BTDeviceInternal *fake_GAPAPI_get_device_resolving_to_fake_irk(void) { static BTDeviceInternal s_resolving_device; s_resolving_device = (const BTDeviceInternal) { .address = BDADDRToBTDeviceAddress(s_resolving_bd_addr), .is_random_address = true, }; return &s_resolving_device; } Boolean_t GAP_LE_Resolve_Address(unsigned int BluetoothStackID, Encryption_Key_t *IRK, BD_ADDR_t ResolvableAddress) { return COMPARE_BD_ADDR(ResolvableAddress, s_resolving_bd_addr) && COMPARE_ENCRYPTION_KEY(*IRK, s_fake_irk); } void fake_GAPAPI_init(void) { memset(&s_encrypted_device, 0, sizeof(s_encrypted_device)); s_is_le_advertising_enabled = false; s_le_adv_connection_event_callback = NULL; s_le_adv_connection_callback_param = 0; memset(&s_ad_data, 0, sizeof(s_ad_data)); s_ad_data_length = 0; s_le_create_connection_event_callback = NULL; s_le_create_connection_callback_param = 0; memset(&s_scan_resp_data, 0, sizeof(s_scan_resp_data)); s_scan_resp_data_length = 0; }