hci::Role my_role;
hci::AddressWithType my_connection_address;
+ hci::AddressWithType my_identity_address;
+ crypto_toolbox::Octet16 my_identity_resolving_key;
+
/* My capabilities, as in pairing request/response */
struct {
IoCapability io_capability;
#include "crypto_toolbox/crypto_toolbox.h"
#include "hci/address_with_type.h"
#include "os/log.h"
+#include "os/rand.h"
#include "security/initial_informations.h"
#include "security/internal/security_manager_impl.h"
#include "security/pairing_handler_le.h"
ASSERT_LOG(storage_module_ != nullptr, "Storage module must not be null!");
security_database_.LoadRecordsFromStorage();
- // TODO(b/161543441): read the privacy policy from device-specific configuration, and IRK from config file.
+ storage::AdapterConfig adapter_config = storage_module_->GetAdapterConfig();
+ if (!adapter_config.GetLeIdentityResolvingKey()) {
+ auto mutation = storage_module_->Modify();
+ mutation.Add(adapter_config.SetLeIdentityResolvingKey(bluetooth::os::GenerateRandom<16>()));
+ mutation.Commit();
+ }
+
+ Address controllerAddress = controller_->GetMacAddress();
+ if (!adapter_config.GetAddress() || adapter_config.GetAddress().value() != controllerAddress) {
+ auto mutation = storage_module_->Modify();
+ mutation.Add(adapter_config.SetAddress(controllerAddress));
+ mutation.Commit();
+ }
+
+ local_identity_address_ =
+ hci::AddressWithType(adapter_config.GetAddress().value(), hci::AddressType::PUBLIC_DEVICE_ADDRESS);
+ local_identity_resolving_key_ = adapter_config.GetLeIdentityResolvingKey().value().bytes;
+
hci::LeAddressManager::AddressPolicy address_policy = hci::LeAddressManager::AddressPolicy::USE_RESOLVABLE_ADDRESS;
hci::AddressWithType address_with_type(hci::Address{}, hci::AddressType::RANDOM_DEVICE_ADDRESS);
- crypto_toolbox::Octet16 irk = {
- 0x44, 0xfb, 0x4b, 0x8d, 0x6c, 0x58, 0x21, 0x0c, 0xf9, 0x3d, 0xda, 0xf1, 0x64, 0xa3, 0xbb, 0x7f};
+
/* 7 minutes minimum, 15 minutes maximum for random address refreshing */
auto minimum_rotation_time = std::chrono::minutes(7);
auto maximum_rotation_time = std::chrono::minutes(15);
acl_manager_->SetPrivacyPolicyForInitiatorAddress(
- address_policy, address_with_type, irk, minimum_rotation_time, maximum_rotation_time);
+ address_policy, address_with_type, local_identity_resolving_key_, minimum_rotation_time, maximum_rotation_time);
}
void SecurityManagerImpl::CreateBond(hci::AddressWithType device) {
InitialInformations initial_informations{
.my_role = my_role,
.my_connection_address = channel->GetLinkOptions()->GetLocalAddress(),
+ .my_identity_address = local_identity_address_,
+ .my_identity_resolving_key = local_identity_resolving_key_,
/*TODO: properly obtain capabilities from device-specific storage*/
.myPairingCapabilities = {.io_capability = local_le_io_capability_,
.oob_data_flag = local_le_oob_data_present_,
InitialInformations initial_informations{
.my_role = channel->GetLinkOptions()->GetRole(),
.my_connection_address = channel->GetLinkOptions()->GetLocalAddress(),
+ .my_identity_address = local_identity_address_,
+ .my_identity_resolving_key = local_identity_resolving_key_,
/*TODO: properly obtain capabilities from device-specific storage*/
.myPairingCapabilities = {.io_capability = local_le_io_capability_,
.oob_data_flag = local_le_oob_data_present_,
channel::SecurityManagerChannel* security_manager_channel,
hci::HciLayer* hci_layer,
hci::AclManager* acl_manager,
+ hci::Controller* controller,
storage::StorageModule* storage_module,
neighbor::NameDbModule* name_db_module)
: security_handler_(security_handler),
hci_layer->GetLeSecurityInterface(security_handler_->BindOn(this, &SecurityManagerImpl::OnHciLeEvent))),
security_manager_channel_(security_manager_channel),
acl_manager_(acl_manager),
+ controller_(controller),
storage_module_(storage_module),
security_record_storage_(storage_module, security_handler),
security_database_(security_record_storage_),
#include <utility>
#include "hci/acl_manager.h"
+#include "hci/controller.h"
#include "l2cap/classic/security_enforcement_interface.h"
#include "l2cap/le/l2cap_le_module.h"
#include "l2cap/le/security_enforcement_interface.h"
channel::SecurityManagerChannel* security_manager_channel,
hci::HciLayer* hci_layer,
hci::AclManager* acl_manager,
+ hci::Controller* controller,
storage::StorageModule* storage_module,
neighbor::NameDbModule* name_db_module);
void OnPairingFinished(bluetooth::security::PairingResultOrFailure pairing_result);
void OnHciLeEvent(hci::LeMetaEventView event);
LeFixedChannelEntry* FindStoredLeChannel(const hci::AddressWithType& device);
+ LeFixedChannelEntry* FindStoredLeChannel(uint8_t connection_handle);
bool EraseStoredLeChannel(const hci::AddressWithType& device);
void InternalEnforceSecurityPolicy(
hci::AddressWithType remote,
hci::LeSecurityInterface* hci_security_interface_le_ __attribute__((unused));
channel::SecurityManagerChannel* security_manager_channel_;
hci::AclManager* acl_manager_;
+ hci::Controller* controller_;
storage::StorageModule* storage_module_ __attribute__((unused));
record::SecurityRecordStorage security_record_storage_;
record::SecurityRecordDatabase security_database_;
std::optional<crypto_toolbox::Octet16> remote_oob_data_le_sc_c_;
std::optional<crypto_toolbox::Octet16> remote_oob_data_le_sc_r_;
std::optional<FacadeDisconnectCallback> facade_disconnect_callback_;
+ hci::AddressWithType local_identity_address_;
+ crypto_toolbox::Octet16 local_identity_resolving_key_;
struct PendingSecurityEnforcementEntry {
l2cap::classic::SecurityPolicy policy_;
i.OnPairingFinished(PairingResult{
.connection_address = i.remote_connection_address,
- .distributed_keys = std::get<DistributedKeys>(keyExchangeStatus),
+ .distributed_keys = distributed_keys,
+ .key_size = key_size,
});
LOG_INFO("Pairing finished successfully.");
uint16_t my_ediv = bluetooth::os::GenerateRandom();
std::array<uint8_t, 8> my_rand = bluetooth::os::GenerateRandom<8>();
- Octet16 my_irk = {0x01};
- Address my_identity_address;
- AddrType my_identity_address_type = AddrType::PUBLIC;
+ Octet16 my_irk = i.my_identity_resolving_key;
+ Address my_identity_address = i.my_identity_address.GetAddress();
+ AddrType my_identity_address_type =
+ static_cast<bluetooth::security::AddrType>(i.my_identity_address.GetAddressType());
Octet16 my_signature_key{0};
if (IAmCentral(i)) {
InitialInformations initial_informations{
.my_role = hci::Role::CENTRAL,
.my_connection_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
+ .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
+ .my_identity_resolving_key =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
InitialInformations initial_informations_trsi{
.my_role = hci::Role::CENTRAL,
.my_connection_address = hci::AddressWithType(),
+ .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
+ .my_identity_resolving_key =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
InitialInformations initial_informations_trmi{
.my_role = hci::Role::PERIPHERAL,
.my_connection_address = hci::AddressWithType(),
+ .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
+ .my_identity_resolving_key =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
l2cap::classic::L2capClassicModule* l2cap_classic_module,
hci::HciLayer* hci_layer,
hci::AclManager* acl_manager,
+ hci::Controller* controller,
storage::StorageModule* storage_module,
neighbor::NameDbModule* name_db_module)
: security_handler_(security_handler),
security_manager_channel_(new channel::SecurityManagerChannel(security_handler_, hci_layer)),
hci_layer_(hci_layer),
acl_manager_(acl_manager),
+ controller_(controller),
storage_module_(storage_module),
l2cap_security_interface_(&security_manager_impl, security_handler),
name_db_module_(name_db_module) {
channel::SecurityManagerChannel* security_manager_channel_;
hci::HciLayer* hci_layer_;
hci::AclManager* acl_manager_;
+ hci::Controller* controller_;
storage::StorageModule* storage_module_;
L2capSecurityModuleInterface l2cap_security_interface_;
neighbor::NameDbModule* name_db_module_;
security_manager_channel_,
hci_layer_,
acl_manager_,
+ controller_,
storage_module_,
name_db_module_};
list->add<l2cap::classic::L2capClassicModule>();
list->add<hci::HciLayer>();
list->add<hci::AclManager>();
+ list->add<hci::Controller>();
list->add<storage::StorageModule>();
list->add<neighbor::NameDbModule>();
}
GetDependency<l2cap::classic::L2capClassicModule>(),
GetDependency<hci::HciLayer>(),
GetDependency<hci::AclManager>(),
+ GetDependency<hci::Controller>(),
GetDependency<storage::StorageModule>(),
GetDependency<neighbor::NameDbModule>());
namespace {
Address ADDRESS_CENTRAL{{0x26, 0x64, 0x76, 0x86, 0xab, 0xba}};
AddressType ADDRESS_TYPE_CENTRAL = AddressType::RANDOM_DEVICE_ADDRESS;
+Address IDENTITY_ADDRESS_CENTRAL{{0x12, 0x34, 0x56, 0x78, 0x90, 0xaa}};
+AddressType IDENTITY_ADDRESS_TYPE_CENTRAL = AddressType::PUBLIC_DEVICE_ADDRESS;
+crypto_toolbox::Octet16 IRK_CENTRAL = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
Address ADDRESS_PERIPHERAL{{0x33, 0x58, 0x24, 0x76, 0x11, 0x89}};
AddressType ADDRESS_TYPE_PERIPHERAL = AddressType::RANDOM_DEVICE_ADDRESS;
+Address IDENTITY_ADDRESS_PERIPHERAL{{0x21, 0x43, 0x65, 0x87, 0x09, 0x44}};
+AddressType IDENTITY_ADDRESS_TYPE_PERIPHERAL = AddressType::PUBLIC_DEVICE_ADDRESS;
+crypto_toolbox::Octet16 IRK_PERIPHERAL = {
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
std::optional<PairingResultOrFailure> pairing_result_central;
std::optional<PairingResultOrFailure> pairing_result_peripheral;
central_setup = {
.my_role = hci::Role::CENTRAL,
.my_connection_address = {ADDRESS_CENTRAL, ADDRESS_TYPE_CENTRAL},
+ .my_identity_address = {IDENTITY_ADDRESS_CENTRAL, IDENTITY_ADDRESS_TYPE_CENTRAL},
+ .my_identity_resolving_key = IRK_CENTRAL,
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
.my_role = hci::Role::PERIPHERAL,
.my_connection_address = {ADDRESS_PERIPHERAL, ADDRESS_TYPE_PERIPHERAL},
+ .my_identity_address = {IDENTITY_ADDRESS_PERIPHERAL, IDENTITY_ADDRESS_TYPE_PERIPHERAL},
+ .my_identity_resolving_key = IRK_PERIPHERAL,
+
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
.auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc,
EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_central.value()));
EXPECT_TRUE(std::holds_alternative<PairingResult>(pairing_result_peripheral.value()));
+
+ auto central_result = std::get<PairingResult>(pairing_result_central.value());
+ ASSERT_EQ(central_result.distributed_keys.remote_identity_address->GetAddress(), IDENTITY_ADDRESS_PERIPHERAL);
+ ASSERT_EQ(
+ central_result.distributed_keys.remote_identity_address->GetAddressType(), IDENTITY_ADDRESS_TYPE_PERIPHERAL);
+ ASSERT_EQ(*central_result.distributed_keys.remote_irk, IRK_PERIPHERAL);
+
+ auto peripheral_result = std::get<PairingResult>(pairing_result_peripheral.value());
+ ASSERT_EQ(peripheral_result.distributed_keys.remote_identity_address->GetAddress(), IDENTITY_ADDRESS_CENTRAL);
+ ASSERT_EQ(
+ peripheral_result.distributed_keys.remote_identity_address->GetAddressType(), IDENTITY_ADDRESS_TYPE_CENTRAL);
+ ASSERT_EQ(*peripheral_result.distributed_keys.remote_irk, IRK_CENTRAL);
}
TEST_F(PairingHandlerPairTest, test_secure_connections_just_works_peripheral_initiated) {
central_setup = {
.my_role = hci::Role::CENTRAL,
.my_connection_address = {ADDRESS_CENTRAL, ADDRESS_TYPE_CENTRAL},
+ .my_identity_address = {IDENTITY_ADDRESS_CENTRAL, IDENTITY_ADDRESS_TYPE_CENTRAL},
+ .my_identity_resolving_key = IRK_CENTRAL,
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
.auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc,
peripheral_setup = {
.my_role = hci::Role::PERIPHERAL,
.my_connection_address = {ADDRESS_PERIPHERAL, ADDRESS_TYPE_PERIPHERAL},
+ .my_identity_address = {IDENTITY_ADDRESS_PERIPHERAL, IDENTITY_ADDRESS_TYPE_PERIPHERAL},
+ .my_identity_resolving_key = IRK_PERIPHERAL,
.myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
.oob_data_flag = OobDataFlag::NOT_PRESENT,
.auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc,