/* * * Copyright 2019 The Android Open Source Project * * 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 "security_manager_impl.h" #include #include "common/bind.h" #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" #include "security/security_manager.h" #include "security/ui.h" namespace bluetooth { namespace security { namespace internal { void SecurityManagerImpl::DispatchPairingHandler( std::shared_ptr record, bool locally_initiated, hci::IoCapability io_capability, hci::AuthenticationRequirements auth_requirements, pairing::OobData remote_p192_oob_data, pairing::OobData remote_p256_oob_data) { common::OnceCallback callback = common::BindOnce(&SecurityManagerImpl::OnPairingHandlerComplete, common::Unretained(this)); auto entry = pairing_handler_map_.find(record->GetPseudoAddress()->GetAddress()); if (entry != pairing_handler_map_.end()) { LOG_WARN("Device already has a pairing handler, and is in the middle of pairing!"); return; } std::shared_ptr pairing_handler = nullptr; switch (record->GetPseudoAddress()->GetAddressType()) { case hci::AddressType::PUBLIC_DEVICE_ADDRESS: { pairing_handler = std::make_shared( security_manager_channel_, record, security_handler_, std::move(callback), user_interface_, user_interface_handler_, record->GetPseudoAddress()->ToString(), name_db_module_); break; } default: ASSERT_LOG(false, "Pairing type %hhu not implemented!", record->GetPseudoAddress()->GetAddressType()); } auto new_entry = std::pair>( record->GetPseudoAddress()->GetAddress(), pairing_handler); pairing_handler_map_.insert(std::move(new_entry)); pairing_handler->Initiate( locally_initiated, io_capability, auth_requirements, remote_p192_oob_data, remote_p256_oob_data); } void SecurityManagerImpl::Init() { security_manager_channel_->SetChannelListener(this); security_manager_channel_->SendCommand(hci::WriteSimplePairingModeBuilder::Create(hci::Enable::ENABLED)); security_manager_channel_->SendCommand(hci::WriteSecureConnectionsHostSupportBuilder::Create(hci::Enable::ENABLED)); ASSERT_LOG(storage_module_ != nullptr, "Storage module must not be null!"); security_database_.LoadRecordsFromStorage(); 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); /* 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, minimum_rotation_time, maximum_rotation_time); } void SecurityManagerImpl::CreateBond(hci::AddressWithType device) { this->CreateBondOutOfBand(device, pairing::OobData(), pairing::OobData()); } void SecurityManagerImpl::CreateBondOutOfBand( hci::AddressWithType device, pairing::OobData remote_p192_oob_data, pairing::OobData remote_p256_oob_data) { auto record = security_database_.FindOrCreate(device); if (record->IsPaired()) { // Bonded means we saved it, but the caller doesn't care // Bonded will always mean paired NotifyDeviceBonded(device); } else { if (!record->IsPairing()) { // Dispatch pairing handler, if we are calling create we are the initiator LOG_WARN("Dispatch #1"); DispatchPairingHandler( record, true, this->local_io_capability_, this->local_authentication_requirements_, remote_p192_oob_data, remote_p256_oob_data); } } } void SecurityManagerImpl::CreateBondLe(hci::AddressWithType address) { auto record = security_database_.FindOrCreate(address); if (record->IsPaired()) { NotifyDeviceBondFailed(address, PairingFailure("Already bonded")); return; } pending_le_pairing_.address_ = address; LeFixedChannelEntry* stored_chan = FindStoredLeChannel(address); if (stored_chan) { // We are already connected ConnectionIsReadyStartPairing(stored_chan); return; } l2cap_manager_le_->ConnectServices( address, common::BindOnce(&SecurityManagerImpl::OnConnectionFailureLe, common::Unretained(this)), security_handler_); } void SecurityManagerImpl::CancelBond(hci::AddressWithType device) { auto entry = pairing_handler_map_.find(device.GetAddress()); if (entry != pairing_handler_map_.end()) { auto cancel_me = entry->second; pairing_handler_map_.erase(entry); cancel_me->Cancel(); } auto record = security_database_.FindOrCreate(device); record->CancelPairing(); WipeLePairingHandler(); } void SecurityManagerImpl::RemoveBond(hci::AddressWithType device) { CancelBond(device); security_manager_channel_->Disconnect(device.GetAddress()); security_database_.Remove(device); security_manager_channel_->SendCommand(hci::DeleteStoredLinkKeyBuilder::Create( device.GetAddress(), hci::DeleteStoredLinkKeyDeleteAllFlag::SPECIFIED_BD_ADDR)); NotifyDeviceUnbonded(device); } void SecurityManagerImpl::SetUserInterfaceHandler(UI* user_interface, os::Handler* handler) { if (user_interface_ != nullptr || user_interface_handler_ != nullptr) { LOG_ALWAYS_FATAL("Listener has already been registered!"); } user_interface_ = user_interface; user_interface_handler_ = handler; } // TODO(jpawlowski): remove once we have config file abstraction in cert tests void SecurityManagerImpl::SetLeInitiatorAddressPolicyForTest( hci::LeAddressManager::AddressPolicy address_policy, hci::AddressWithType fixed_address, crypto_toolbox::Octet16 rotation_irk, std::chrono::milliseconds minimum_rotation_time, std::chrono::milliseconds maximum_rotation_time) { acl_manager_->SetPrivacyPolicyForInitiatorAddressForTest( address_policy, fixed_address, rotation_irk, minimum_rotation_time, maximum_rotation_time); } void SecurityManagerImpl::RegisterCallbackListener(ISecurityManagerListener* listener, os::Handler* handler) { for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { if (it->first == listener) { LOG_ALWAYS_FATAL("Listener has already been registered!"); } } listeners_.push_back({listener, handler}); } void SecurityManagerImpl::UnregisterCallbackListener(ISecurityManagerListener* listener) { for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { if (it->first == listener) { listeners_.erase(it); return; } } LOG_ALWAYS_FATAL("Listener has not been registered!"); } void SecurityManagerImpl::NotifyDeviceBonded(hci::AddressWithType device) { for (auto& iter : listeners_) { iter.second->Post(common::Bind(&ISecurityManagerListener::OnDeviceBonded, common::Unretained(iter.first), device)); } } void SecurityManagerImpl::NotifyDeviceBondFailed(hci::AddressWithType device, PairingFailure status) { for (auto& iter : listeners_) { iter.second->Post( common::Bind(&ISecurityManagerListener::OnDeviceBondFailed, common::Unretained(iter.first), device, status)); } } void SecurityManagerImpl::NotifyDeviceUnbonded(hci::AddressWithType device) { for (auto& iter : listeners_) { iter.second->Post( common::Bind(&ISecurityManagerListener::OnDeviceUnbonded, common::Unretained(iter.first), device)); } acl_manager_->RemoveDeviceFromConnectList(device); } void SecurityManagerImpl::NotifyEncryptionStateChanged(hci::EncryptionChangeView encryption_change_view) { for (auto& iter : listeners_) { iter.second->Post(common::Bind(&ISecurityManagerListener::OnEncryptionStateChanged, common::Unretained(iter.first), encryption_change_view)); } } template void SecurityManagerImpl::HandleEvent(T packet) { ASSERT(packet.IsValid()); auto entry = pairing_handler_map_.find(packet.GetBdAddr()); if (entry == pairing_handler_map_.end()) { auto bd_addr = packet.GetBdAddr(); auto event_code = packet.GetEventCode(); if (event_code != hci::EventCode::LINK_KEY_REQUEST && event_code != hci::EventCode::PIN_CODE_REQUEST && event_code != hci::EventCode::IO_CAPABILITY_RESPONSE) { LOG_ERROR("No classic pairing handler for device '%s' ready for command %s ", bd_addr.ToString().c_str(), hci::EventCodeText(event_code).c_str()); return; } auto device = storage_module_->GetDeviceByClassicMacAddress(bd_addr); auto record = security_database_.FindOrCreate(hci::AddressWithType{bd_addr, hci::AddressType::PUBLIC_DEVICE_ADDRESS}); LOG_WARN("Dispatch #2"); DispatchPairingHandler( record, false, this->local_io_capability_, this->local_authentication_requirements_, pairing::OobData(), pairing::OobData()); entry = pairing_handler_map_.find(bd_addr); } entry->second->OnReceive(packet); } void SecurityManagerImpl::OnHciEventReceived(hci::EventView packet) { auto event = hci::EventView::Create(packet); ASSERT_LOG(event.IsValid(), "Received invalid packet"); const hci::EventCode code = event.GetEventCode(); switch (code) { case hci::EventCode::PIN_CODE_REQUEST: HandleEvent(hci::PinCodeRequestView::Create(event)); break; case hci::EventCode::LINK_KEY_REQUEST: HandleEvent(hci::LinkKeyRequestView::Create(event)); break; case hci::EventCode::LINK_KEY_NOTIFICATION: HandleEvent(hci::LinkKeyNotificationView::Create(event)); break; case hci::EventCode::IO_CAPABILITY_REQUEST: HandleEvent(hci::IoCapabilityRequestView::Create(event)); break; case hci::EventCode::IO_CAPABILITY_RESPONSE: HandleEvent(hci::IoCapabilityResponseView::Create(event)); break; case hci::EventCode::SIMPLE_PAIRING_COMPLETE: HandleEvent(hci::SimplePairingCompleteView::Create(event)); break; case hci::EventCode::REMOTE_OOB_DATA_REQUEST: HandleEvent(hci::RemoteOobDataRequestView::Create(event)); break; case hci::EventCode::USER_PASSKEY_NOTIFICATION: HandleEvent(hci::UserPasskeyNotificationView::Create(event)); break; case hci::EventCode::KEYPRESS_NOTIFICATION: HandleEvent(hci::KeypressNotificationView::Create(event)); break; case hci::EventCode::USER_CONFIRMATION_REQUEST: HandleEvent(hci::UserConfirmationRequestView::Create(event)); break; case hci::EventCode::USER_PASSKEY_REQUEST: HandleEvent(hci::UserPasskeyRequestView::Create(event)); break; case hci::EventCode::REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION: LOG_INFO("Unhandled event: %s", hci::EventCodeText(code).c_str()); break; case hci::EventCode::ENCRYPTION_CHANGE: { EncryptionChangeView encryption_change_view = EncryptionChangeView::Create(event); if (!encryption_change_view.IsValid()) { LOG_ERROR("Invalid EncryptionChange packet received"); return; } if (encryption_change_view.GetConnectionHandle() == pending_le_pairing_.connection_handle_) { pending_le_pairing_.handler_->OnHciEvent(event); return; } NotifyEncryptionStateChanged(encryption_change_view); break; } default: ASSERT_LOG(false, "Cannot handle received packet: %s", hci::EventCodeText(code).c_str()); break; } } void SecurityManagerImpl::OnConnectionClosed(hci::Address address) { auto entry = pairing_handler_map_.find(address); if (entry != pairing_handler_map_.end()) { LOG_INFO("Cancelling pairing handler for '%s'", address.ToString().c_str()); entry->second->Cancel(); } auto record = security_database_.FindOrCreate(hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS)); if (record->IsTemporary()) { security_database_.Remove(hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS)); } if (this->facade_disconnect_callback_) { this->security_handler_->Call( *this->facade_disconnect_callback_, hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS)); } } void SecurityManagerImpl::OnHciLeEvent(hci::LeMetaEventView event) { hci::SubeventCode code = event.GetSubeventCode(); if (code == hci::SubeventCode::LONG_TERM_KEY_REQUEST) { hci::LeLongTermKeyRequestView le_long_term_key_request_view = hci::LeLongTermKeyRequestView::Create(event); if (!le_long_term_key_request_view.IsValid()) { LOG_ERROR("Invalid LeLongTermKeyRequestView packet received"); return; } if (le_long_term_key_request_view.GetConnectionHandle() == pending_le_pairing_.connection_handle_) { pending_le_pairing_.handler_->OnHciLeEvent(event); return; } LOG_INFO("Unhandled HCI LE security event, code %s", hci::SubeventCodeText(code).c_str()); return; } // hci::SubeventCode::READ_LOCAL_P256_PUBLIC_KEY_COMPLETE, // hci::SubeventCode::GENERATE_DHKEY_COMPLETE, LOG_ERROR("Unhandled HCI LE security event, code %s", hci::SubeventCodeText(code).c_str()); } void SecurityManagerImpl::OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, bool confirmed) { auto entry = pairing_handler_map_.find(address.GetAddress()); if (entry != pairing_handler_map_.end()) { entry->second->OnPairingPromptAccepted(address, confirmed); } else { if (pending_le_pairing_.address_ == address) { pending_le_pairing_.handler_->OnUiAction(PairingEvent::UI_ACTION_TYPE::PAIRING_ACCEPTED, confirmed); } } } void SecurityManagerImpl::OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, bool confirmed) { auto entry = pairing_handler_map_.find(address.GetAddress()); if (entry != pairing_handler_map_.end()) { entry->second->OnConfirmYesNo(address, confirmed); } else { if (pending_le_pairing_.address_ == address) { pending_le_pairing_.handler_->OnUiAction(PairingEvent::UI_ACTION_TYPE::CONFIRM_YESNO, confirmed); } } } void SecurityManagerImpl::OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, uint32_t passkey) { auto entry = pairing_handler_map_.find(address.GetAddress()); if (entry != pairing_handler_map_.end()) { entry->second->OnPasskeyEntry(address, passkey); } else { if (pending_le_pairing_.address_ == address) { pending_le_pairing_.handler_->OnUiAction(PairingEvent::UI_ACTION_TYPE::PASSKEY, passkey); } } } void SecurityManagerImpl::OnPinEntry(const bluetooth::hci::AddressWithType& address, std::vector pin) { auto entry = pairing_handler_map_.find(address.GetAddress()); if (entry != pairing_handler_map_.end()) { LOG_INFO("PIN for %s", address.ToString().c_str()); entry->second->OnPinEntry(address, pin); } else { LOG_WARN("No handler found for PIN for %s", address.ToString().c_str()); // TODO(jpawlowski): Implement LE version } } void SecurityManagerImpl::OnPairingHandlerComplete(hci::Address address, PairingResultOrFailure status) { auto entry = pairing_handler_map_.find(address); if (entry != pairing_handler_map_.end()) { pairing_handler_map_.erase(entry); security_manager_channel_->Release(address); } auto remote = hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); if (!std::holds_alternative(status)) { NotifyDeviceBonded(remote); } else { NotifyDeviceBondFailed(remote, std::get(status)); } auto record = this->security_database_.FindOrCreate(remote); record->CancelPairing(); security_database_.SaveRecordsToStorage(); // Only call update link if we need to auto policy_callback_entry = enforce_security_policy_callback_map_.find(remote); if (policy_callback_entry != enforce_security_policy_callback_map_.end()) { UpdateLinkSecurityCondition(remote); } } void SecurityManagerImpl::OnL2capRegistrationCompleteLe( l2cap::le::FixedChannelManager::RegistrationResult result, std::unique_ptr le_smp_service) { ASSERT_LOG(result == bluetooth::l2cap::le::FixedChannelManager::RegistrationResult::SUCCESS, "Failed to register to LE SMP Fixed Channel Service"); } LeFixedChannelEntry* SecurityManagerImpl::FindStoredLeChannel(const hci::AddressWithType& device) { for (LeFixedChannelEntry& storage : all_channels_) { if (storage.channel_->GetDevice() == device) { return &storage; } } return nullptr; } bool SecurityManagerImpl::EraseStoredLeChannel(const hci::AddressWithType& device) { for (auto it = all_channels_.begin(); it != all_channels_.end(); it++) { if (it->channel_->GetDevice() == device) { all_channels_.erase(it); return true; } } return false; } void SecurityManagerImpl::OnSmpCommandLe(hci::AddressWithType device) { LeFixedChannelEntry* stored_chan = FindStoredLeChannel(device); if (!stored_chan) { LOG_ALWAYS_FATAL("Received SMP command for unknown channel"); return; } std::unique_ptr& channel = stored_chan->channel_; auto packet = channel->GetQueueUpEnd()->TryDequeue(); if (!packet) { LOG_ERROR("Received dequeue, but no data ready..."); return; } // Pending pairing - pass the data to the handler auto temp_cmd_view = CommandView::Create(*packet); if (pending_le_pairing_.address_ == device) { pending_le_pairing_.handler_->OnCommandView(temp_cmd_view); return; } // no pending pairing attempt if (!temp_cmd_view.IsValid()) { LOG_ERROR("Invalid Command packet"); return; } if (temp_cmd_view.GetCode() == Code::SECURITY_REQUEST) { // TODO: either start encryption or pairing LOG_WARN("Unhandled security request!!!"); return; } auto my_role = channel->GetLinkOptions()->GetRole(); if (temp_cmd_view.GetCode() == Code::PAIRING_REQUEST && my_role == hci::Role::PERIPHERAL) { // TODO: if (pending_le_pairing_) { do not start another } LOG_INFO("start of security request handling!"); stored_chan->channel_->Acquire(); PairingRequestView pairing_request = PairingRequestView::Create(temp_cmd_view); auto& enqueue_buffer = stored_chan->enqueue_buffer_; std::optional remote_oob_data = std::nullopt; if (remote_oob_data_address_.has_value() && remote_oob_data_address_.value() == channel->GetDevice()) remote_oob_data = InitialInformations::out_of_band_data{.le_sc_c = remote_oob_data_le_sc_c_.value(), .le_sc_r = remote_oob_data_le_sc_r_.value()}; // TODO: this doesn't have to be a unique ptr, if there is a way to properly std::move it into place where it's // stored pending_le_pairing_.connection_handle_ = channel->GetLinkOptions()->GetHandle(); 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_, .auth_req = local_le_auth_req_, .maximum_encryption_key_size = local_maximum_encryption_key_size_, .initiator_key_distribution = 0x07, .responder_key_distribution = 0x07}, .remotely_initiated = true, .connection_handle = channel->GetLinkOptions()->GetHandle(), .remote_connection_address = channel->GetDevice(), .remote_name = "TODO: grab proper device name in sec mgr", /* contains pairing request, if the pairing was remotely initiated */ .pairing_request = pairing_request, .remote_oob_data = remote_oob_data, .my_oob_data = local_le_oob_data_, /* Used by Pairing Handler to present user with requests*/ .user_interface = user_interface_, .user_interface_handler = user_interface_handler_, /* HCI interface to use */ .le_security_interface = hci_security_interface_le_, .proper_l2cap_interface = enqueue_buffer.get(), .l2cap_handler = security_handler_, /* Callback to execute once the Pairing process is finished */ // TODO: make it an common::OnceCallback ? .OnPairingFinished = std::bind(&SecurityManagerImpl::OnPairingFinished, this, std::placeholders::_1), }; pending_le_pairing_.address_ = device; pending_le_pairing_.handler_ = std::make_unique(PairingHandlerLe::PHASE1, initial_informations); } } void SecurityManagerImpl::OnConnectionOpenLe(std::unique_ptr channel_param) { auto enqueue_buffer_temp = std::make_unique>(channel_param->GetQueueUpEnd()); all_channels_.push_back({std::move(channel_param), std::move(enqueue_buffer_temp)}); auto& stored_channel = all_channels_.back(); auto& channel = stored_channel.channel_; channel->RegisterOnCloseCallback( security_handler_, common::BindOnce(&SecurityManagerImpl::OnConnectionClosedLe, common::Unretained(this), channel->GetDevice())); channel->GetQueueUpEnd()->RegisterDequeue( security_handler_, common::Bind(&SecurityManagerImpl::OnSmpCommandLe, common::Unretained(this), channel->GetDevice())); if (pending_le_pairing_.address_ != channel->GetDevice()) { return; } ConnectionIsReadyStartPairing(&stored_channel); } void SecurityManagerImpl::ConnectionIsReadyStartPairing(LeFixedChannelEntry* stored_channel) { auto& channel = stored_channel->channel_; auto& enqueue_buffer = stored_channel->enqueue_buffer_; stored_channel->channel_->Acquire(); std::optional remote_oob_data = std::nullopt; if (remote_oob_data_address_.has_value() && remote_oob_data_address_.value() == channel->GetDevice()) remote_oob_data = InitialInformations::out_of_band_data{.le_sc_c = remote_oob_data_le_sc_c_.value(), .le_sc_r = remote_oob_data_le_sc_r_.value()}; // TODO: this doesn't have to be a unique ptr, if there is a way to properly std::move it into place where it's stored pending_le_pairing_.connection_handle_ = channel->GetLinkOptions()->GetHandle(); 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_, .auth_req = local_le_auth_req_, .maximum_encryption_key_size = local_maximum_encryption_key_size_, .initiator_key_distribution = 0x07, .responder_key_distribution = 0x07}, .remotely_initiated = false, .connection_handle = channel->GetLinkOptions()->GetHandle(), .remote_connection_address = channel->GetDevice(), .remote_name = "TODO: grab proper device name in sec mgr", /* contains pairing request, if the pairing was remotely initiated */ .pairing_request = std::nullopt, // TODO: handle remotely initiated pairing in SecurityManager properly .remote_oob_data = remote_oob_data, .my_oob_data = local_le_oob_data_, /* Used by Pairing Handler to present user with requests*/ .user_interface = user_interface_, .user_interface_handler = user_interface_handler_, /* HCI interface to use */ .le_security_interface = hci_security_interface_le_, .proper_l2cap_interface = enqueue_buffer.get(), .l2cap_handler = security_handler_, /* Callback to execute once the Pairing process is finished */ // TODO: make it an common::OnceCallback ? .OnPairingFinished = std::bind(&SecurityManagerImpl::OnPairingFinished, this, std::placeholders::_1), }; pending_le_pairing_.handler_ = std::make_unique(PairingHandlerLe::PHASE1, initial_informations); } void SecurityManagerImpl::OnConnectionClosedLe(hci::AddressWithType address, hci::ErrorCode error_code) { if (pending_le_pairing_.address_ != address) { LeFixedChannelEntry* stored_chan = FindStoredLeChannel(address); if (!stored_chan) { LOG_ALWAYS_FATAL("Received connection closed for unknown channel"); return; } stored_chan->channel_->GetQueueUpEnd()->UnregisterDequeue(); stored_chan->enqueue_buffer_.reset(); EraseStoredLeChannel(address); return; } pending_le_pairing_.handler_->SendExitSignal(); NotifyDeviceBondFailed(address, PairingFailure("Connection closed")); } void SecurityManagerImpl::OnConnectionFailureLe(bluetooth::l2cap::le::FixedChannelManager::ConnectionResult result) { if (result.connection_result_code == bluetooth::l2cap::le::FixedChannelManager::ConnectionResultCode::FAIL_ALL_SERVICES_HAVE_CHANNEL) { // TODO: already connected } // This callback is invoked only for devices we attempted to connect to. NotifyDeviceBondFailed(pending_le_pairing_.address_, PairingFailure("Connection establishment failed")); } SecurityManagerImpl::SecurityManagerImpl( os::Handler* security_handler, l2cap::le::L2capLeModule* l2cap_le_module, 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), l2cap_le_module_(l2cap_le_module), l2cap_manager_le_(l2cap_le_module_->GetFixedChannelManager()), hci_security_interface_le_( 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_), name_db_module_(name_db_module) { Init(); l2cap_manager_le_->RegisterService( bluetooth::l2cap::kSmpCid, common::BindOnce(&SecurityManagerImpl::OnL2capRegistrationCompleteLe, common::Unretained(this)), common::Bind(&SecurityManagerImpl::OnConnectionOpenLe, common::Unretained(this)), security_handler_); } void SecurityManagerImpl::OnPairingFinished(security::PairingResultOrFailure pairing_result) { LOG_INFO(" ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Received pairing result"); LeFixedChannelEntry* stored_chan = FindStoredLeChannel(pending_le_pairing_.address_); if (stored_chan) { stored_chan->channel_->Release(); } if (std::holds_alternative(pairing_result)) { PairingFailure failure = std::get(pairing_result); LOG_INFO(" ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ failure message: %s", failure.message.c_str()); NotifyDeviceBondFailed(stored_chan->channel_->GetDevice(), failure); return; } auto result = std::get(pairing_result); LOG_INFO("Pairing with %s was successful", result.connection_address.ToString().c_str()); // TODO: ensure that the security level is not weaker than what we already have. auto record = this->security_database_.FindOrCreate(result.connection_address); record->identity_address_ = result.distributed_keys.remote_identity_address; record->remote_ltk = result.distributed_keys.remote_ltk; record->key_size = result.key_size; record->security_level = result.security_level; record->remote_ediv = result.distributed_keys.remote_ediv; record->remote_rand = result.distributed_keys.remote_rand; record->remote_irk = result.distributed_keys.remote_irk; record->remote_signature_key = result.distributed_keys.remote_signature_key; if (result.distributed_keys.remote_link_key) record->SetLinkKey(*result.distributed_keys.remote_link_key, hci::KeyType::AUTHENTICATED_P256); security_database_.SaveRecordsToStorage(); NotifyDeviceBonded(result.connection_address); // We also notify bond complete using identity address. That's what old stack used to do. if (result.distributed_keys.remote_identity_address) NotifyDeviceBonded(*result.distributed_keys.remote_identity_address); security_handler_->CallOn(this, &SecurityManagerImpl::WipeLePairingHandler); } void SecurityManagerImpl::WipeLePairingHandler() { pending_le_pairing_.handler_.reset(); pending_le_pairing_.connection_handle_ = 0; pending_le_pairing_.address_ = hci::AddressWithType(); } // Facade Configuration API functions void SecurityManagerImpl::SetDisconnectCallback(FacadeDisconnectCallback callback) { this->facade_disconnect_callback_ = std::make_optional(callback); } void SecurityManagerImpl::SetIoCapability(hci::IoCapability io_capability) { this->local_io_capability_ = io_capability; } void SecurityManagerImpl::SetLeIoCapability(security::IoCapability io_capability) { this->local_le_io_capability_ = io_capability; } void SecurityManagerImpl::SetLeAuthRequirements(uint8_t auth_req) { this->local_le_auth_req_ = auth_req; } void SecurityManagerImpl::SetLeMaximumEncryptionKeySize(uint8_t maximum_encryption_key_size) { this->local_maximum_encryption_key_size_ = maximum_encryption_key_size; } void SecurityManagerImpl::SetLeOobDataPresent(OobDataFlag data_present) { this->local_le_oob_data_present_ = data_present; } void SecurityManagerImpl::GetOutOfBandData(channel::SecurityCommandStatusCallback callback) { this->security_manager_channel_->SendCommand( hci::ReadLocalOobDataBuilder::Create(), std::forward(callback)); } void SecurityManagerImpl::GetLeOutOfBandData( std::array* confirmation_value, std::array* random_value) { local_le_oob_data_ = std::make_optional(PairingHandlerLe::GenerateOobData()); *confirmation_value = local_le_oob_data_.value().c; *random_value = local_le_oob_data_.value().r; } void SecurityManagerImpl::SetOutOfBandData( hci::AddressWithType remote_address, std::array confirmation_value, std::array random_value) { remote_oob_data_address_ = remote_address; remote_oob_data_le_sc_c_ = confirmation_value; remote_oob_data_le_sc_r_ = random_value; } void SecurityManagerImpl::SetAuthenticationRequirements(hci::AuthenticationRequirements authentication_requirements) { this->local_authentication_requirements_ = authentication_requirements; } void SecurityManagerImpl::InternalEnforceSecurityPolicy( hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback) { if (IsSecurityRequirementSatisfied(remote, policy)) { // Notify client immediately if already satisfied std::move(result_callback).Invoke(true); return; } // At this point we don't meet the security requirements; must pair auto record = this->security_database_.FindOrCreate(remote); hci::AuthenticationRequirements authentication_requirements = kDefaultAuthenticationRequirements; enforce_security_policy_callback_map_[remote] = {policy, std::move(result_callback)}; switch (policy) { case l2cap::classic::SecurityPolicy::BEST: case l2cap::classic::SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT: // Force MITM requirement locally authentication_requirements = hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION; break; case l2cap::classic::SecurityPolicy::ENCRYPTED_TRANSPORT: authentication_requirements = hci::AuthenticationRequirements::GENERAL_BONDING; break; default: // I could hear the voice of Myles, "This should be an ASSERT!" ASSERT_LOG(false, "Unreachable code path"); return; } LOG_WARN("Dispatch #3"); DispatchPairingHandler( record, true, this->local_io_capability_, std::as_const(authentication_requirements), pairing::OobData(), pairing::OobData()); } void SecurityManagerImpl::UpdateLinkSecurityCondition(hci::AddressWithType remote) { auto entry = enforce_security_policy_callback_map_.find(remote); if (entry == enforce_security_policy_callback_map_.end()) { LOG_ERROR("No L2CAP security policy callback pending for %s", remote.ToString().c_str()); return; } std::move(entry->second.callback_).Invoke(IsSecurityRequirementSatisfied(remote, entry->second.policy_)); enforce_security_policy_callback_map_.erase(entry); } bool SecurityManagerImpl::IsSecurityRequirementSatisfied( hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy) { auto record = security_database_.FindOrCreate(remote); switch (policy) { case l2cap::classic::SecurityPolicy::BEST: case l2cap::classic::SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT: return (record->IsPaired() && record->IsAuthenticated()); case l2cap::classic::SecurityPolicy::ENCRYPTED_TRANSPORT: return record->IsPaired(); default: return true; } } void SecurityManagerImpl::EnforceSecurityPolicy( hci::AddressWithType remote, l2cap::classic::SecurityPolicy policy, l2cap::classic::SecurityEnforcementInterface::ResultCallback result_callback) { LOG_INFO("Attempting to enforce security policy"); auto record = security_database_.FindOrCreate(remote); if (!record->IsPairing()) { this->InternalEnforceSecurityPolicy(remote, policy, std::move(result_callback)); } } void SecurityManagerImpl::EnforceLeSecurityPolicy( hci::AddressWithType remote, l2cap::le::SecurityPolicy policy, l2cap::le::SecurityEnforcementInterface::ResultCallback result_callback) { bool result = false; // TODO(jpawlowski): Implement for LE switch (policy) { case l2cap::le::SecurityPolicy::BEST: break; case l2cap::le::SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT: break; case l2cap::le::SecurityPolicy::ENCRYPTED_TRANSPORT: break; case l2cap::le::SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK: result = true; break; case l2cap::le::SecurityPolicy::_NOT_FOR_YOU__AUTHENTICATED_PAIRING_WITH_128_BIT_KEY: break; case l2cap::le::SecurityPolicy::_NOT_FOR_YOU__AUTHORIZATION: break; } result_callback.Invoke(result); } } // namespace internal } // namespace security } // namespace bluetooth