Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 38819fb6 authored by Brian Delwiche's avatar Brian Delwiche
Browse files

Add tests for BR/EDR temp bond authentication

As an action item following a regression postmortem, we need to create
tests covering the behavior when accessing a secure service from a temp
bond.  This is an internal function and is not directly accessible to
unit testing, but can be accessed via several indirect entry points.

Three tests have been added to cover different scenarios, all using
btm_sec_mx_access_request as the entry point.

Bug: 333617609
Test: atest StackBtmSecWithInitFreeTest
Tag: #security
Flag: EXEMPT test_only
Merged-In: I5183ea06c1a5b3f878b8a1ad648caba666c46981
Change-Id: I5183ea06c1a5b3f878b8a1ad648caba666c46981
parent 602c2457
Loading
Loading
Loading
Loading
+145 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "stack/btm/btm_sec.h"
#include "stack/btm/btm_sec_cb.h"
#include "stack/btm/security_device_record.h"
#include "stack/include/btm_status.h"
#include "stack/test/btm/btm_test_fixtures.h"
#include "test/mock/mock_main_shim_entry.h"
#include "types/raw_address.h"
@@ -288,3 +289,147 @@ TEST_F(StackBtmSecWithInitFreeTest, btm_sec_rmt_name_request_complete) {
  }
  ASSERT_EQ(8U, history.size());
}

TEST_F(StackBtmSecWithInitFreeTest, btm_sec_temp_bond_auth_authenticated_temporary) {
  RawAddress bd_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
  const uint16_t classic_handle = 0x1234;
  const uint16_t ble_handle = 0x9876;
  bool rval = false;

  tBTM_SEC_DEV_REC* device_record = btm_sec_allocate_dev_rec();
  device_record->bd_addr = bd_addr;
  device_record->hci_handle = classic_handle;
  device_record->ble_hci_handle = ble_handle;

  device_record->sec_rec.sec_flags |= BTM_SEC_AUTHENTICATED;
  device_record->sec_rec.sec_flags |= BTM_SEC_NAME_KNOWN;
  device_record->sec_rec.bond_type = BOND_TYPE_TEMPORARY;

  btm_sec_cb.security_mode = BTM_SEC_MODE_SERVICE;
  btm_sec_cb.pairing_state = BTM_PAIR_STATE_IDLE;

  uint16_t sec_req = BTM_SEC_IN_AUTHENTICATE;
  tBTM_STATUS status = tBTM_STATUS::BTM_UNDEFINED;

  status = btm_sec_mx_access_request(bd_addr, false, sec_req, NULL, NULL);

  ASSERT_EQ(status, tBTM_STATUS::BTM_FAILED_ON_SECURITY);
}

TEST_F(StackBtmSecWithInitFreeTest, btm_sec_temp_bond_auth_non_authenticated_temporary) {
  RawAddress bd_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
  const uint16_t classic_handle = 0x1234;
  const uint16_t ble_handle = 0x9876;
  bool rval = false;

  tBTM_SEC_DEV_REC* device_record = btm_sec_allocate_dev_rec();
  device_record->bd_addr = bd_addr;
  device_record->hci_handle = classic_handle;
  device_record->ble_hci_handle = ble_handle;

  device_record->sec_rec.sec_flags &= ~BTM_SEC_AUTHENTICATED;
  device_record->sec_rec.sec_flags |= BTM_SEC_NAME_KNOWN;
  device_record->sec_rec.bond_type = BOND_TYPE_TEMPORARY;

  btm_sec_cb.security_mode = BTM_SEC_MODE_SERVICE;
  btm_sec_cb.pairing_state = BTM_PAIR_STATE_IDLE;

  uint16_t sec_req = BTM_SEC_IN_AUTHENTICATE;
  tBTM_STATUS status = tBTM_STATUS::BTM_UNDEFINED;

  status = btm_sec_mx_access_request(bd_addr, false, sec_req, NULL, NULL);

  // We're testing the temp bonding security behavior here, so all we care about
  // is that it doesn't fail on security.
  ASSERT_NE(status, tBTM_STATUS::BTM_FAILED_ON_SECURITY);
}

TEST_F(StackBtmSecWithInitFreeTest, btm_sec_temp_bond_auth_authenticated_persistent) {
  RawAddress bd_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
  const uint16_t classic_handle = 0x1234;
  const uint16_t ble_handle = 0x9876;
  bool rval = false;

  tBTM_SEC_DEV_REC* device_record = btm_sec_allocate_dev_rec();
  device_record->bd_addr = bd_addr;
  device_record->hci_handle = classic_handle;
  device_record->ble_hci_handle = ble_handle;

  device_record->sec_rec.sec_flags |= BTM_SEC_AUTHENTICATED;
  device_record->sec_rec.sec_flags |= BTM_SEC_NAME_KNOWN;
  device_record->sec_rec.bond_type = BOND_TYPE_PERSISTENT;

  btm_sec_cb.security_mode = BTM_SEC_MODE_SERVICE;
  btm_sec_cb.pairing_state = BTM_PAIR_STATE_IDLE;

  uint16_t sec_req = BTM_SEC_IN_AUTHENTICATE;
  tBTM_STATUS status = tBTM_STATUS::BTM_UNDEFINED;

  status = btm_sec_mx_access_request(bd_addr, false, sec_req, NULL, NULL);

  // We're testing the temp bonding security behavior here, so all we care about
  // is that it doesn't fail on security.
  ASSERT_NE(status, tBTM_STATUS::BTM_FAILED_ON_SECURITY);
}

TEST_F(StackBtmSecWithInitFreeTest, btm_sec_temp_bond_auth_upgrade_needed) {
  RawAddress bd_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
  const uint16_t classic_handle = 0x1234;
  const uint16_t ble_handle = 0x9876;
  bool rval = false;

  tBTM_SEC_DEV_REC* device_record = btm_sec_allocate_dev_rec();
  device_record->bd_addr = bd_addr;
  device_record->hci_handle = classic_handle;
  device_record->ble_hci_handle = ble_handle;

  device_record->sec_rec.sec_flags |= BTM_SEC_NAME_KNOWN;
  device_record->sec_rec.sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
  device_record->sec_rec.bond_type = BOND_TYPE_PERSISTENT;

  btm_sec_cb.security_mode = BTM_SEC_MODE_SERVICE;
  btm_sec_cb.pairing_state = BTM_PAIR_STATE_IDLE;

  uint16_t sec_req = BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MIN_16_DIGIT_PIN;
  tBTM_STATUS status = tBTM_STATUS::BTM_UNDEFINED;

  // This should be marked in btm_sec_execute_procedure with "start_auth"
  // because BTM_SEC_IN_AUTHENTICATE is required but the security flags
  // do not contain BTM_SEC_AUTHENTICATED

  status = btm_sec_mx_access_request(bd_addr, false, sec_req, NULL, NULL);

  // In this case we expect it to clear several security flags and return
  // BTM_CMD_STARTED.
  ASSERT_EQ(status, tBTM_STATUS::BTM_CMD_STARTED);
  ASSERT_FALSE(device_record->sec_rec.sec_flags & BTM_SEC_LINK_KEY_KNOWN);
}

TEST_F(StackBtmSecWithInitFreeTest, btm_sec_temp_bond_auth_encryption_required) {
  RawAddress bd_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
  const uint16_t classic_handle = 0x1234;
  const uint16_t ble_handle = 0x9876;
  bool rval = false;

  tBTM_SEC_DEV_REC* device_record = btm_sec_allocate_dev_rec();
  device_record->bd_addr = bd_addr;
  device_record->hci_handle = classic_handle;
  device_record->ble_hci_handle = ble_handle;

  device_record->sec_rec.sec_flags |= BTM_SEC_AUTHENTICATED;
  device_record->sec_rec.sec_flags |= BTM_SEC_NAME_KNOWN;
  device_record->sec_rec.bond_type = BOND_TYPE_PERSISTENT;

  btm_sec_cb.security_mode = BTM_SEC_MODE_SERVICE;
  btm_sec_cb.pairing_state = BTM_PAIR_STATE_IDLE;

  uint16_t sec_req = BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT;
  tBTM_STATUS status = tBTM_STATUS::BTM_UNDEFINED;

  // In this case we need to encrypt the link, so we will mark the link
  // encrypted and return BTM_CMD_STARTED.
  status = btm_sec_mx_access_request(bd_addr, true, sec_req, NULL, NULL);

  ASSERT_EQ(status, tBTM_STATUS::BTM_CMD_STARTED);
  ASSERT_EQ(device_record->sec_rec.classic_link, tSECURITY_STATE::ENCRYPTING);
}