Loading system/stack/btm/btm_sec.cc +44 −27 Original line number Diff line number Diff line Loading @@ -3210,7 +3210,6 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status) { ******************************************************************************/ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable) { tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle); /* For transaction collision we need to wait and repeat. There is no need */ /* for random timeout because only peripheral should receive the result */ if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) || Loading @@ -3220,7 +3219,17 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, } btm_cb.collision_start_time = 0; if (!p_dev_rec) return; tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle); if (p_dev_rec == nullptr) { LOG_WARN( "Received encryption change for unknown device handle:0x%04x status:%s " "enable:0x%x", handle, hci_status_code_text(status).c_str(), encr_enable); return; } const tBT_TRANSPORT transport = BTM_IsBleConnection(handle) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR; LOG_DEBUG( "Security Manager encryption change request hci_status:%s" Loading @@ -3230,37 +3239,46 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, (p_dev_rec->sec_state) ? "encrypted" : "unencrypted", p_dev_rec->sec_flags); if ((status == HCI_SUCCESS) && encr_enable) { if (p_dev_rec->hci_handle == handle) { if (status == HCI_SUCCESS) { if (encr_enable) { if (p_dev_rec->hci_handle == handle) { // classic p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED); if (p_dev_rec->pin_code_length >= 16 || p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB || p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) { p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; } } else if (p_dev_rec->ble_hci_handle == handle) { // BLE p_dev_rec->sec_flags |= (BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED); } else { p_dev_rec->sec_flags |= (BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED); LOG_ERROR( "Received encryption change for unknown device handle:0x%04x " "status:%s enable:0x%x", handle, hci_status_code_text(status).c_str(), encr_enable); } } } else { /* It is possible that we decrypted the link to perform role switch */ /* mark link not to be encrypted, so that when we execute security next time * it will kick in again */ if ((status == HCI_SUCCESS) && !encr_enable) { if (p_dev_rec->hci_handle == handle) /* mark link not to be encrypted, so that when we execute security next * time it will kick in again */ if (p_dev_rec->hci_handle == handle) { // clasic p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED; else } else if (p_dev_rec->ble_hci_handle == handle) { // BLE p_dev_rec->sec_flags &= ~BTM_SEC_LE_ENCRYPTED; } else { LOG_ERROR( "Received encryption change for unknown device handle:0x%04x " "status:%s enable:0x%x", handle, hci_status_code_text(status).c_str(), encr_enable); } } } BTM_TRACE_DEBUG("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags); LOG_DEBUG("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags); auto transport = BTM_IsBleConnection(handle) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR; btm_sec_check_pending_enc_req(p_dev_rec, transport, encr_enable); if (BTM_IsBleConnection(handle)) { if (transport == BT_TRANSPORT_LE) { if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE || status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE) { p_dev_rec->sec_flags &= ~(BTM_SEC_LE_LINK_KEY_KNOWN); Loading @@ -3274,8 +3292,7 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, p_dev_rec->enc_key_size = 16; } BTM_TRACE_DEBUG("in %s new_encr_key_256 is %d", __func__, p_dev_rec->new_encryption_key_is_p256); LOG_DEBUG("in new_encr_key_256 is %d", p_dev_rec->new_encryption_key_is_p256); if ((status == HCI_SUCCESS) && encr_enable && (p_dev_rec->hci_handle == handle)) { Loading system/stack/test/btm/stack_btm_test.cc +71 −0 Original line number Diff line number Diff line Loading @@ -35,11 +35,14 @@ #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sco.h" #include "stack/btm/btm_sec.h" #include "stack/btm/security_device_record.h" #include "stack/include/acl_api.h" #include "stack/include/acl_hci_link_interface.h" #include "stack/include/btm_client_interface.h" #include "stack/include/hcidefs.h" #include "stack/include/sec_hci_link_interface.h" #include "stack/l2cap/l2c_int.h" #include "test/mock/mock_osi_list.h" #include "test/mock/mock_stack_hcic_hcicmds.h" #include "types/raw_address.h" Loading Loading @@ -112,6 +115,13 @@ class StackBtmTest : public Test { void TearDown() override {} }; class StackBtmWithInitFreeTest : public StackBtmTest { public: protected: void SetUp() override { btm_cb.Init(BTM_SEC_MODE_SC); } void TearDown() override { btm_cb.Free(); } }; TEST_F(StackBtmTest, GlobalLifecycle) { get_btm_client_interface().lifecycle.btm_init(); get_btm_client_interface().lifecycle.btm_free(); Loading @@ -122,6 +132,11 @@ TEST_F(StackBtmTest, DynamicLifecycle) { delete btm; } TEST_F(StackBtmTest, InitFree) { btm_cb.Init(0x1); btm_cb.Free(); } TEST_F(StackBtmTest, tSCO_CB) { bluetooth::common::InitFlags::SetAllForTesting(); tSCO_CB* p_sco = &btm_cb.sco_cb; Loading Loading @@ -263,3 +278,59 @@ TEST(SecTest, btm_sec_rmt_name_request_complete) { btm_cb.Free(); } TEST_F(StackBtmWithInitFreeTest, btm_sec_encrypt_change) { bluetooth::common::InitFlags::SetAllForTesting(); RawAddress bd_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6}); const uint16_t classic_handle = 0x1234; const uint16_t ble_handle = 0x9876; // Check the collision conditionals btm_cb.collision_start_time = 0UL; btm_sec_encrypt_change(classic_handle, HCI_ERR_LMP_ERR_TRANS_COLLISION, 0x01); uint64_t collision_start_time = btm_cb.collision_start_time; ASSERT_NE(0UL, collision_start_time); btm_cb.collision_start_time = 0UL; btm_sec_encrypt_change(classic_handle, HCI_ERR_DIFF_TRANSACTION_COLLISION, 0x01); collision_start_time = btm_cb.collision_start_time; ASSERT_NE(0UL, collision_start_time); // No device btm_cb.collision_start_time = 0; btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x01); ASSERT_EQ(0UL, btm_cb.collision_start_time); // Setup device tBTM_SEC_DEV_REC* device_record = btm_sec_allocate_dev_rec(); ASSERT_NE(nullptr, device_record); ASSERT_EQ(BTM_SEC_IN_USE, device_record->sec_flags); device_record->bd_addr = bd_addr; device_record->hci_handle = classic_handle; device_record->ble_hci_handle = ble_handle; // With classic device encryption enable btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x01); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED, device_record->sec_flags); // With classic device encryption disable btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x00); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_AUTHENTICATED, device_record->sec_flags); device_record->sec_flags = BTM_SEC_IN_USE; // With le device encryption enable btm_sec_encrypt_change(ble_handle, HCI_SUCCESS, 0x01); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED, device_record->sec_flags); // With le device encryption disable btm_sec_encrypt_change(ble_handle, HCI_SUCCESS, 0x00); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_LE_AUTHENTICATED, device_record->sec_flags); device_record->sec_flags = BTM_SEC_IN_USE; wipe_secrets_and_remove(device_record); } Loading
system/stack/btm/btm_sec.cc +44 −27 Original line number Diff line number Diff line Loading @@ -3210,7 +3210,6 @@ void btm_sec_auth_complete(uint16_t handle, tHCI_STATUS status) { ******************************************************************************/ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, uint8_t encr_enable) { tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle); /* For transaction collision we need to wait and repeat. There is no need */ /* for random timeout because only peripheral should receive the result */ if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) || Loading @@ -3220,7 +3219,17 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, } btm_cb.collision_start_time = 0; if (!p_dev_rec) return; tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle); if (p_dev_rec == nullptr) { LOG_WARN( "Received encryption change for unknown device handle:0x%04x status:%s " "enable:0x%x", handle, hci_status_code_text(status).c_str(), encr_enable); return; } const tBT_TRANSPORT transport = BTM_IsBleConnection(handle) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR; LOG_DEBUG( "Security Manager encryption change request hci_status:%s" Loading @@ -3230,37 +3239,46 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, (p_dev_rec->sec_state) ? "encrypted" : "unencrypted", p_dev_rec->sec_flags); if ((status == HCI_SUCCESS) && encr_enable) { if (p_dev_rec->hci_handle == handle) { if (status == HCI_SUCCESS) { if (encr_enable) { if (p_dev_rec->hci_handle == handle) { // classic p_dev_rec->sec_flags |= (BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED); if (p_dev_rec->pin_code_length >= 16 || p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB || p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256) { p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; } } else if (p_dev_rec->ble_hci_handle == handle) { // BLE p_dev_rec->sec_flags |= (BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED); } else { p_dev_rec->sec_flags |= (BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED); LOG_ERROR( "Received encryption change for unknown device handle:0x%04x " "status:%s enable:0x%x", handle, hci_status_code_text(status).c_str(), encr_enable); } } } else { /* It is possible that we decrypted the link to perform role switch */ /* mark link not to be encrypted, so that when we execute security next time * it will kick in again */ if ((status == HCI_SUCCESS) && !encr_enable) { if (p_dev_rec->hci_handle == handle) /* mark link not to be encrypted, so that when we execute security next * time it will kick in again */ if (p_dev_rec->hci_handle == handle) { // clasic p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED; else } else if (p_dev_rec->ble_hci_handle == handle) { // BLE p_dev_rec->sec_flags &= ~BTM_SEC_LE_ENCRYPTED; } else { LOG_ERROR( "Received encryption change for unknown device handle:0x%04x " "status:%s enable:0x%x", handle, hci_status_code_text(status).c_str(), encr_enable); } } } BTM_TRACE_DEBUG("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags); LOG_DEBUG("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags); auto transport = BTM_IsBleConnection(handle) ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR; btm_sec_check_pending_enc_req(p_dev_rec, transport, encr_enable); if (BTM_IsBleConnection(handle)) { if (transport == BT_TRANSPORT_LE) { if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE || status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE) { p_dev_rec->sec_flags &= ~(BTM_SEC_LE_LINK_KEY_KNOWN); Loading @@ -3274,8 +3292,7 @@ void btm_sec_encrypt_change(uint16_t handle, tHCI_STATUS status, p_dev_rec->enc_key_size = 16; } BTM_TRACE_DEBUG("in %s new_encr_key_256 is %d", __func__, p_dev_rec->new_encryption_key_is_p256); LOG_DEBUG("in new_encr_key_256 is %d", p_dev_rec->new_encryption_key_is_p256); if ((status == HCI_SUCCESS) && encr_enable && (p_dev_rec->hci_handle == handle)) { Loading
system/stack/test/btm/stack_btm_test.cc +71 −0 Original line number Diff line number Diff line Loading @@ -35,11 +35,14 @@ #include "stack/btm/btm_int_types.h" #include "stack/btm/btm_sco.h" #include "stack/btm/btm_sec.h" #include "stack/btm/security_device_record.h" #include "stack/include/acl_api.h" #include "stack/include/acl_hci_link_interface.h" #include "stack/include/btm_client_interface.h" #include "stack/include/hcidefs.h" #include "stack/include/sec_hci_link_interface.h" #include "stack/l2cap/l2c_int.h" #include "test/mock/mock_osi_list.h" #include "test/mock/mock_stack_hcic_hcicmds.h" #include "types/raw_address.h" Loading Loading @@ -112,6 +115,13 @@ class StackBtmTest : public Test { void TearDown() override {} }; class StackBtmWithInitFreeTest : public StackBtmTest { public: protected: void SetUp() override { btm_cb.Init(BTM_SEC_MODE_SC); } void TearDown() override { btm_cb.Free(); } }; TEST_F(StackBtmTest, GlobalLifecycle) { get_btm_client_interface().lifecycle.btm_init(); get_btm_client_interface().lifecycle.btm_free(); Loading @@ -122,6 +132,11 @@ TEST_F(StackBtmTest, DynamicLifecycle) { delete btm; } TEST_F(StackBtmTest, InitFree) { btm_cb.Init(0x1); btm_cb.Free(); } TEST_F(StackBtmTest, tSCO_CB) { bluetooth::common::InitFlags::SetAllForTesting(); tSCO_CB* p_sco = &btm_cb.sco_cb; Loading Loading @@ -263,3 +278,59 @@ TEST(SecTest, btm_sec_rmt_name_request_complete) { btm_cb.Free(); } TEST_F(StackBtmWithInitFreeTest, btm_sec_encrypt_change) { bluetooth::common::InitFlags::SetAllForTesting(); RawAddress bd_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6}); const uint16_t classic_handle = 0x1234; const uint16_t ble_handle = 0x9876; // Check the collision conditionals btm_cb.collision_start_time = 0UL; btm_sec_encrypt_change(classic_handle, HCI_ERR_LMP_ERR_TRANS_COLLISION, 0x01); uint64_t collision_start_time = btm_cb.collision_start_time; ASSERT_NE(0UL, collision_start_time); btm_cb.collision_start_time = 0UL; btm_sec_encrypt_change(classic_handle, HCI_ERR_DIFF_TRANSACTION_COLLISION, 0x01); collision_start_time = btm_cb.collision_start_time; ASSERT_NE(0UL, collision_start_time); // No device btm_cb.collision_start_time = 0; btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x01); ASSERT_EQ(0UL, btm_cb.collision_start_time); // Setup device tBTM_SEC_DEV_REC* device_record = btm_sec_allocate_dev_rec(); ASSERT_NE(nullptr, device_record); ASSERT_EQ(BTM_SEC_IN_USE, device_record->sec_flags); device_record->bd_addr = bd_addr; device_record->hci_handle = classic_handle; device_record->ble_hci_handle = ble_handle; // With classic device encryption enable btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x01); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED, device_record->sec_flags); // With classic device encryption disable btm_sec_encrypt_change(classic_handle, HCI_SUCCESS, 0x00); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_AUTHENTICATED, device_record->sec_flags); device_record->sec_flags = BTM_SEC_IN_USE; // With le device encryption enable btm_sec_encrypt_change(ble_handle, HCI_SUCCESS, 0x01); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED, device_record->sec_flags); // With le device encryption disable btm_sec_encrypt_change(ble_handle, HCI_SUCCESS, 0x00); ASSERT_EQ(BTM_SEC_IN_USE | BTM_SEC_LE_AUTHENTICATED, device_record->sec_flags); device_record->sec_flags = BTM_SEC_IN_USE; wipe_secrets_and_remove(device_record); }