diff --git a/system/btif/src/btif_storage.cc b/system/btif/src/btif_storage.cc index 41fa4df5fbedf70d5b61983dbd0e6f94bbc327f1..ae81bd1a38bffd930081ffb14f4f0381036b80a2 100644 --- a/system/btif/src/btif_storage.cc +++ b/system/btif/src/btif_storage.cc @@ -92,10 +92,13 @@ using bluetooth::groups::DeviceGroups; #define BTIF_STORAGE_KEY_ADAPTER_SCANMODE "ScanMode" #define BTIF_STORAGE_KEY_LOCAL_IO_CAPS "LocalIOCaps" #define BTIF_STORAGE_KEY_LOCAL_IO_CAPS_BLE "LocalIOCapsBLE" +#define BTIF_STORAGE_KEY_MAX_SESSION_KEY_SIZE "MaxSessionKeySize" #define BTIF_STORAGE_KEY_ADAPTER_DISC_TIMEOUT "DiscoveryTimeout" #define BTIF_STORAGE_KEY_GATT_CLIENT_SUPPORTED "GattClientSupportedFeatures" #define BTIF_STORAGE_KEY_GATT_CLIENT_DB_HASH "GattClientDatabaseHash" #define BTIF_STORAGE_KEY_GATT_SERVER_SUPPORTED "GattServerSupportedFeatures" +#define BTIF_STORAGE_KEY_SECURE_CONNECTIONS_SUPPORTED \ + "SecureConnectionsSupported" #define BTIF_STORAGE_DEVICE_GROUP_BIN "DeviceGroupBin" #define BTIF_STORAGE_CSIS_AUTOCONNECT "CsisAutoconnect" #define BTIF_STORAGE_CSIS_SET_INFO_BIN "CsisSetInfoBin" @@ -281,6 +284,14 @@ static int prop2cfg(const RawAddress* remote_bd_addr, bt_property_t* prop) { btif_config_set_int(bdstr, BT_CONFIG_KEY_REMOTE_VER_SUBVER, info->sub_ver); } break; + case BT_PROPERTY_REMOTE_SECURE_CONNECTIONS_SUPPORTED: + btif_config_set_int(bdstr, BTIF_STORAGE_KEY_SECURE_CONNECTIONS_SUPPORTED, + *(uint8_t*)prop->val); + break; + case BT_PROPERTY_REMOTE_MAX_SESSION_KEY_SIZE: + btif_config_set_int(bdstr, BTIF_STORAGE_KEY_MAX_SESSION_KEY_SIZE, + *(uint8_t*)prop->val); + break; default: BTIF_TRACE_ERROR("Unknown prop type:%d", prop->type); @@ -407,6 +418,26 @@ static int cfg2prop(const RawAddress* remote_bd_addr, bt_property_t* prop) { } } break; + case BT_PROPERTY_REMOTE_SECURE_CONNECTIONS_SUPPORTED: { + int val; + + if (prop->len >= (int)sizeof(uint8_t)) { + ret = btif_config_get_int( + bdstr, BTIF_STORAGE_KEY_SECURE_CONNECTIONS_SUPPORTED, &val); + *(uint8_t*)prop->val = (uint8_t)val; + } + } break; + + case BT_PROPERTY_REMOTE_MAX_SESSION_KEY_SIZE: { + int val; + + if (prop->len >= (int)sizeof(uint8_t)) { + ret = btif_config_get_int(bdstr, BTIF_STORAGE_KEY_MAX_SESSION_KEY_SIZE, + &val); + *(uint8_t*)prop->val = (uint8_t)val; + } + } break; + default: BTIF_TRACE_ERROR("Unknow prop type:%d", prop->type); return false; diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index f9ad870dee1ceaa74c670e118427df5521d4af32..1c92e526f15c15faafe70dd21997df36b5508abf 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -339,6 +339,20 @@ typedef enum { */ BT_PROPERTY_REMOTE_IS_COORDINATED_SET_MEMBER, + /** + * Description - Whether remote device supports Secure Connections mode + * Access mode - GET and SET. + * Data Type - uint8_t. + */ + BT_PROPERTY_REMOTE_SECURE_CONNECTIONS_SUPPORTED, + + /** + * Description - Maximum observed session key for remote device + * Access mode - GET and SET. + * Data Type - uint8_t. + */ + BT_PROPERTY_REMOTE_MAX_SESSION_KEY_SIZE, + BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP = 0xFF, } bt_property_type_t; diff --git a/system/service/logging_helpers.cc b/system/service/logging_helpers.cc index 78a24e600f5b4c47cf6cf804d4ae3557c2e9b14e..0c3644d2baaabfe731857f421a8124b70a07499c 100644 --- a/system/service/logging_helpers.cc +++ b/system/service/logging_helpers.cc @@ -118,6 +118,8 @@ const char* BtPropertyText(const bt_property_type_t prop) { CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_VERSION_INFO); CASE_RETURN_TEXT(BT_PROPERTY_LOCAL_LE_FEATURES); CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP); + CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_SECURE_CONNECTIONS_SUPPORTED); + CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_MAX_SESSION_KEY_SIZE); default: return "Invalid property"; } diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index 3af24dd59ccb3e2c62cc4c75613009bf3fa62425..0ad7b7f9923a092ec75fa3ecfa09d136a9dec91b 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -207,6 +207,109 @@ static bool btm_dev_16_digit_authenticated(tBTM_SEC_DEV_REC* p_dev_rec) { return (false); } +/******************************************************************************* + * + * Function btm_sec_is_device_sc_downgrade + * + * Description Check for a stored device record matching the candidate + * device, and return true if the stored device has reported + * that it supports Secure Connections mode and the candidate + * device reports that it does not. Otherwise, return false. + * + * Returns bool + * + ******************************************************************************/ +static bool btm_sec_is_device_sc_downgrade(uint16_t hci_handle, + bool secure_connections_supported) { + if (secure_connections_supported) return false; + + tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(hci_handle); + if (p_dev_rec == nullptr) return false; + + uint8_t property_val = 0; + bt_property_t property = { + .type = BT_PROPERTY_REMOTE_SECURE_CONNECTIONS_SUPPORTED, + .len = sizeof(uint8_t), + .val = &property_val}; + + bt_status_t cached = + btif_storage_get_remote_device_property(&p_dev_rec->bd_addr, &property); + + if (cached == BT_STATUS_FAIL) return false; + + return (bool)property_val; +} + +/******************************************************************************* + * + * Function btm_sec_store_device_sc_support + * + * Description Save Secure Connections support for this device to file + * + ******************************************************************************/ + +static void btm_sec_store_device_sc_support(uint16_t hci_handle, + bool secure_connections_supported) { + tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(hci_handle); + if (p_dev_rec == nullptr) return; + + uint8_t property_val = (uint8_t)secure_connections_supported; + bt_property_t property = { + .type = BT_PROPERTY_REMOTE_SECURE_CONNECTIONS_SUPPORTED, + .len = sizeof(uint8_t), + .val = &property_val}; + + btif_storage_set_remote_device_property(&p_dev_rec->bd_addr, &property); +} + +/******************************************************************************* + * + * Function btm_sec_is_session_key_size_downgrade + * + * Description Check if there is a stored device record matching this + * handle, and return true if the stored record has a lower + * session key size than the candidate device. + * + * Returns bool + * + ******************************************************************************/ +bool btm_sec_is_session_key_size_downgrade(uint16_t hci_handle, + uint8_t key_size) { + tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(hci_handle); + if (p_dev_rec == nullptr) return false; + + uint8_t property_val = 0; + bt_property_t property = {.type = BT_PROPERTY_REMOTE_MAX_SESSION_KEY_SIZE, + .len = sizeof(uint8_t), + .val = &property_val}; + + bt_status_t cached = + btif_storage_get_remote_device_property(&p_dev_rec->bd_addr, &property); + + if (cached == BT_STATUS_FAIL) return false; + + return property_val > key_size; +} + +/******************************************************************************* + * + * Function btm_sec_update_session_key_size + * + * Description Store the max session key size to disk, if possible. + * + ******************************************************************************/ +void btm_sec_update_session_key_size(uint16_t hci_handle, uint8_t key_size) { + tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(hci_handle); + if (p_dev_rec == nullptr) return; + + uint8_t property_val = key_size; + bt_property_t property = {.type = BT_PROPERTY_REMOTE_MAX_SESSION_KEY_SIZE, + .len = sizeof(uint8_t), + .val = &property_val}; + + btif_storage_set_remote_device_property(&p_dev_rec->bd_addr, &property); +} + /******************************************************************************* * * Function access_secure_service_from_temp_bond diff --git a/system/stack/btm/btm_sec.h b/system/stack/btm/btm_sec.h index 0acb6ca19404570a55dc58d6eacc9fa576e79c11..282cb3c95e80dcf4b603a5fed2d09e592d2c576a 100644 --- a/system/stack/btm/btm_sec.h +++ b/system/stack/btm/btm_sec.h @@ -805,5 +805,28 @@ void btm_sec_set_peer_sec_caps(uint16_t hci_handle, bool ssp_supported, void btm_sec_cr_loc_oob_data_cback_event(const RawAddress& address, tSMP_LOC_OOB_DATA loc_oob_data); +/******************************************************************************* + * + * Function btm_sec_is_session_key_size_downgrade + * + * Description Check if there is a stored device record matching this + * handle, and return true if the stored record has a lower + * session key size than the candidate device. + * + * Returns bool + * + ******************************************************************************/ +bool btm_sec_is_session_key_size_downgrade(uint16_t hci_handle, + uint8_t key_size); + +/******************************************************************************* + * + * Function btm_sec_update_session_key_size + * + * Description Store the max session key size to disk, if possible. + * + ******************************************************************************/ +void btm_sec_update_session_key_size(uint16_t hci_handle, uint8_t key_size); + // Return DEV_CLASS (uint8_t[3]) of bda. If record doesn't exist, create one. const uint8_t* btm_get_dev_class(const RawAddress& bda); diff --git a/system/stack/include/sec_hci_link_interface.h b/system/stack/include/sec_hci_link_interface.h index dce3c479fd8afaf02ccaf25e6d1e12bc456a1990..1fecde74ed1d91d59f014b3d46953d35a9fb42ef 100644 --- a/system/stack/include/sec_hci_link_interface.h +++ b/system/stack/include/sec_hci_link_interface.h @@ -37,6 +37,8 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status); void btm_sec_disconnected(uint16_t handle, tHCI_STATUS reason, std::string); void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable); +bool btm_sec_is_session_key_size_downgrade(uint16_t hci_handle, + uint8_t key_size); void btm_sec_link_key_notification(const RawAddress& p_bda, const Octet16& link_key, uint8_t key_type); void btm_sec_link_key_request(const uint8_t* p_event); @@ -46,4 +48,5 @@ void btm_sec_rmt_name_request_complete(const RawAddress* bd_addr, const uint8_t* bd_name, tHCI_STATUS status); void btm_sec_update_clock_offset(uint16_t handle, uint16_t clock_offset); +void btm_sec_update_session_key_size(uint16_t hci_handle, uint8_t key_size); void btm_simple_pair_complete(const uint8_t* p); diff --git a/system/test/mock/mock_stack_btm_sec.cc b/system/test/mock/mock_stack_btm_sec.cc index ea6ce175058b18553724ba17695d4acaa15a52cf..eeea0bd5827f259c9fdaa944ada1e8ac28294961 100644 --- a/system/test/mock/mock_stack_btm_sec.cc +++ b/system/test/mock/mock_stack_btm_sec.cc @@ -113,6 +113,11 @@ bool btm_sec_is_a_bonded_dev(const RawAddress& bda) { mock_function_count_map[__func__]++; return false; } +bool btm_sec_is_session_key_size_downgrade(uint16_t hci_handle, + uint8_t key_size) { + mock_function_count_map[__func__]++; + return false; +} bool is_sec_state_equal(void* data, void* context) { mock_function_count_map[__func__]++; return false; @@ -313,6 +318,9 @@ void btm_sec_set_peer_sec_caps(uint16_t hci_handle, bool ssp_supported, void btm_sec_update_clock_offset(uint16_t handle, uint16_t clock_offset) { mock_function_count_map[__func__]++; } +void btm_sec_update_session_key_size(uint16_t hci_handle, uint8_t key_size) { + mock_function_count_map[__func__]++; +} void btm_simple_pair_complete(const uint8_t* p) { mock_function_count_map[__func__]++; }