Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 1 | /* |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 2 | * |
| 3 | * Copyright 2019 The Android Open Source Project |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at: |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | * |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 17 | */ |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 18 | #include "security_manager_impl.h" |
| 19 | |
| 20 | #include <iostream> |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 21 | |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 22 | #include "hci/address_with_type.h" |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 23 | #include "os/log.h" |
Jakub Pawlowski | 5a67e40 | 2019-11-18 16:14:22 +0100 | [diff] [blame] | 24 | #include "security/security_manager.h" |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 25 | |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 26 | namespace bluetooth { |
| 27 | namespace security { |
| 28 | namespace internal { |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 29 | |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 30 | std::shared_ptr<bluetooth::security::record::SecurityRecord> SecurityManagerImpl::CreateSecurityRecord( |
| 31 | hci::Address address) { |
| 32 | hci::AddressWithType device(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); |
| 33 | // Security record check |
| 34 | auto entry = security_record_map_.find(device.GetAddress()); |
| 35 | if (entry == security_record_map_.end()) { |
| 36 | LOG_INFO("No security record for device: %s ", device.ToString().c_str()); |
| 37 | // Create one |
| 38 | std::shared_ptr<security::record::SecurityRecord> record = |
| 39 | std::make_shared<security::record::SecurityRecord>(device); |
| 40 | auto new_entry = std::pair<hci::Address, std::shared_ptr<security::record::SecurityRecord>>( |
| 41 | record->GetDevice().GetAddress(), record); |
| 42 | // Keep track of it |
| 43 | security_record_map_.insert(new_entry); |
| 44 | return record; |
| 45 | } |
| 46 | return entry->second; |
| 47 | } |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 48 | |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 49 | void SecurityManagerImpl::DispatchPairingHandler(std::shared_ptr<security::record::SecurityRecord> record, |
| 50 | bool locally_initiated) { |
| 51 | common::OnceCallback<void(hci::Address)> callback = |
| 52 | common::BindOnce(&SecurityManagerImpl::OnPairingHandlerComplete, common::Unretained(this)); |
| 53 | auto entry = pairing_handler_map_.find(record->GetDevice().GetAddress()); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 54 | if (entry != pairing_handler_map_.end()) { |
| 55 | LOG_WARN("Device already has a pairing handler, and is in the middle of pairing!"); |
| 56 | return; |
| 57 | } |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 58 | std::shared_ptr<pairing::PairingHandler> pairing_handler = nullptr; |
| 59 | switch (record->GetDevice().GetAddressType()) { |
| 60 | case hci::AddressType::PUBLIC_DEVICE_ADDRESS: |
| 61 | pairing_handler = std::make_shared<security::pairing::ClassicPairingHandler>( |
| 62 | l2cap_classic_module_->GetFixedChannelManager(), security_manager_channel_, record, security_handler_, |
| 63 | std::move(callback)); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 64 | break; |
| 65 | default: |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 66 | ASSERT_LOG(false, "Pairing type %hhu not implemented!", record->GetDevice().GetAddressType()); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 67 | } |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 68 | auto new_entry = std::pair<hci::Address, std::shared_ptr<pairing::PairingHandler>>(record->GetDevice().GetAddress(), |
| 69 | pairing_handler); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 70 | pairing_handler_map_.insert(std::move(new_entry)); |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 71 | pairing_handler->Initiate(locally_initiated, pairing::kDefaultIoCapability, pairing::kDefaultOobDataPresent, |
| 72 | pairing::kDefaultAuthenticationRequirements); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 73 | } |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 74 | |
| 75 | void SecurityManagerImpl::Init() { |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 76 | security_manager_channel_->SetChannelListener(this); |
| 77 | security_manager_channel_->SendCommand(hci::WriteSimplePairingModeBuilder::Create(hci::Enable::ENABLED)); |
| 78 | security_manager_channel_->SendCommand(hci::WriteSecureConnectionsHostSupportBuilder::Create(hci::Enable::ENABLED)); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 79 | // TODO(optedoblivion): Populate security record memory map from disk |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 80 | } |
| 81 | |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 82 | void SecurityManagerImpl::CreateBond(hci::AddressWithType device) { |
| 83 | auto record = CreateSecurityRecord(device.GetAddress()); |
| 84 | if (record->IsBonded()) { |
| 85 | NotifyDeviceBonded(device); |
| 86 | } else { |
| 87 | // Dispatch pairing handler, if we are calling create we are the initiator |
| 88 | DispatchPairingHandler(record, true); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 89 | } |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 90 | } |
| 91 | |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 92 | void SecurityManagerImpl::CancelBond(hci::AddressWithType device) { |
| 93 | auto entry = pairing_handler_map_.find(device.GetAddress()); |
| 94 | if (entry != pairing_handler_map_.end()) { |
Greg Kaiser | f98cc3d | 2019-11-27 07:08:14 -0800 | [diff] [blame^] | 95 | auto cancel_me = entry->second; |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 96 | pairing_handler_map_.erase(entry); |
Greg Kaiser | f98cc3d | 2019-11-27 07:08:14 -0800 | [diff] [blame^] | 97 | cancel_me->Cancel(); |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 98 | } |
| 99 | } |
| 100 | |
| 101 | void SecurityManagerImpl::RemoveBond(hci::AddressWithType device) { |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 102 | CancelBond(device); |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 103 | auto entry = security_record_map_.find(device.GetAddress()); |
| 104 | if (entry != security_record_map_.end()) { |
| 105 | security_record_map_.erase(entry); |
| 106 | } |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 107 | // Signal disconnect |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 108 | // Remove security record |
| 109 | // Signal Remove from database |
| 110 | } |
| 111 | |
Jakub Pawlowski | 24d5f35 | 2019-11-18 18:54:09 +0100 | [diff] [blame] | 112 | void SecurityManagerImpl::RegisterCallbackListener(ISecurityManagerListener* listener, os::Handler* handler) { |
Jakub Pawlowski | f7cd656 | 2019-11-18 19:27:06 +0100 | [diff] [blame] | 113 | for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { |
| 114 | if (it->first == listener) { |
| 115 | LOG_ALWAYS_FATAL("Listener has already been registered!"); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 116 | } |
| 117 | } |
Jakub Pawlowski | f7cd656 | 2019-11-18 19:27:06 +0100 | [diff] [blame] | 118 | |
| 119 | listeners_.push_back({listener, handler}); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | void SecurityManagerImpl::UnregisterCallbackListener(ISecurityManagerListener* listener) { |
Jakub Pawlowski | f7cd656 | 2019-11-18 19:27:06 +0100 | [diff] [blame] | 123 | for (auto it = listeners_.begin(); it != listeners_.end(); ++it) { |
| 124 | if (it->first == listener) { |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 125 | listeners_.erase(it); |
Jakub Pawlowski | f7cd656 | 2019-11-18 19:27:06 +0100 | [diff] [blame] | 126 | return; |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 127 | } |
| 128 | } |
Jakub Pawlowski | f7cd656 | 2019-11-18 19:27:06 +0100 | [diff] [blame] | 129 | |
| 130 | LOG_ALWAYS_FATAL("Listener has not been registered!"); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 131 | } |
| 132 | |
Jakub Pawlowski | d2c82f5 | 2019-11-22 15:33:12 +0100 | [diff] [blame] | 133 | void SecurityManagerImpl::NotifyDeviceBonded(hci::AddressWithType device) { |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 134 | for (auto& iter : listeners_) { |
Jakub Pawlowski | 24d5f35 | 2019-11-18 18:54:09 +0100 | [diff] [blame] | 135 | iter.second->Post(common::Bind(&ISecurityManagerListener::OnDeviceBonded, common::Unretained(iter.first), device)); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 136 | } |
| 137 | } |
| 138 | |
Jakub Pawlowski | d2c82f5 | 2019-11-22 15:33:12 +0100 | [diff] [blame] | 139 | void SecurityManagerImpl::NotifyDeviceBondFailed(hci::AddressWithType device) { |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 140 | for (auto& iter : listeners_) { |
Jakub Pawlowski | 24d5f35 | 2019-11-18 18:54:09 +0100 | [diff] [blame] | 141 | iter.second->Post( |
| 142 | common::Bind(&ISecurityManagerListener::OnDeviceBondFailed, common::Unretained(iter.first), device)); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 143 | } |
| 144 | } |
| 145 | |
Jakub Pawlowski | d2c82f5 | 2019-11-22 15:33:12 +0100 | [diff] [blame] | 146 | void SecurityManagerImpl::NotifyDeviceUnbonded(hci::AddressWithType device) { |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 147 | for (auto& iter : listeners_) { |
Jakub Pawlowski | 24d5f35 | 2019-11-18 18:54:09 +0100 | [diff] [blame] | 148 | iter.second->Post( |
| 149 | common::Bind(&ISecurityManagerListener::OnDeviceUnbonded, common::Unretained(iter.first), device)); |
Martin Brabham | 605d6f1 | 2019-03-29 12:02:30 -0700 | [diff] [blame] | 150 | } |
| 151 | } |
Martin Brabham | 80854c2 | 2019-11-12 14:52:42 -0800 | [diff] [blame] | 152 | |
| 153 | template <class T> |
| 154 | void SecurityManagerImpl::HandleEvent(T packet) { |
| 155 | ASSERT(packet.IsValid()); |
| 156 | auto entry = pairing_handler_map_.find(packet.GetBdAddr()); |
| 157 | if (entry != pairing_handler_map_.end()) { |
| 158 | entry->second->OnReceive(packet); |
| 159 | } else { |
| 160 | auto event = hci::EventPacketView::Create(std::move(packet)); |
| 161 | ASSERT_LOG(event.IsValid(), "Received invalid packet"); |
| 162 | const hci::EventCode code = event.GetEventCode(); |
| 163 | auto record = CreateSecurityRecord(packet.GetBdAddr()); |
| 164 | switch (code) { |
| 165 | case hci::EventCode::LINK_KEY_REQUEST: |
| 166 | DispatchPairingHandler(record, true); |
| 167 | break; |
| 168 | default: |
| 169 | LOG_ERROR("No classic pairing handler for device '%s' ready for command '%hhx' ", |
| 170 | packet.GetBdAddr().ToString().c_str(), packet.GetEventCode()); |
| 171 | break; |
| 172 | } |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | void SecurityManagerImpl::OnHciEventReceived(hci::EventPacketView packet) { |
| 177 | auto event = hci::EventPacketView::Create(packet); |
| 178 | ASSERT_LOG(event.IsValid(), "Received invalid packet"); |
| 179 | const hci::EventCode code = event.GetEventCode(); |
| 180 | switch (code) { |
| 181 | case hci::EventCode::PIN_CODE_REQUEST: |
| 182 | HandleEvent<hci::PinCodeRequestView>(hci::PinCodeRequestView::Create(event)); |
| 183 | break; |
| 184 | case hci::EventCode::LINK_KEY_REQUEST: |
| 185 | HandleEvent(hci::LinkKeyRequestView::Create(event)); |
| 186 | break; |
| 187 | case hci::EventCode::LINK_KEY_NOTIFICATION: |
| 188 | HandleEvent(hci::LinkKeyNotificationView::Create(event)); |
| 189 | break; |
| 190 | case hci::EventCode::IO_CAPABILITY_REQUEST: |
| 191 | HandleEvent(hci::IoCapabilityRequestView::Create(event)); |
| 192 | break; |
| 193 | case hci::EventCode::IO_CAPABILITY_RESPONSE: |
| 194 | HandleEvent(hci::IoCapabilityResponseView::Create(event)); |
| 195 | break; |
| 196 | case hci::EventCode::SIMPLE_PAIRING_COMPLETE: |
| 197 | HandleEvent(hci::SimplePairingCompleteView::Create(event)); |
| 198 | break; |
| 199 | case hci::EventCode::REMOTE_OOB_DATA_REQUEST: |
| 200 | HandleEvent(hci::RemoteOobDataRequestView::Create(event)); |
| 201 | break; |
| 202 | case hci::EventCode::USER_PASSKEY_NOTIFICATION: |
| 203 | HandleEvent<hci::UserPasskeyNotificationView>(hci::UserPasskeyNotificationView::Create(event)); |
| 204 | break; |
| 205 | case hci::EventCode::KEYPRESS_NOTIFICATION: |
| 206 | HandleEvent(hci::KeypressNotificationView::Create(event)); |
| 207 | break; |
| 208 | case hci::EventCode::USER_CONFIRMATION_REQUEST: |
| 209 | HandleEvent(hci::UserConfirmationRequestView::Create(event)); |
| 210 | break; |
| 211 | case hci::EventCode::USER_PASSKEY_REQUEST: |
| 212 | HandleEvent(hci::UserPasskeyRequestView::Create(event)); |
| 213 | break; |
| 214 | default: |
| 215 | ASSERT_LOG(false, "Cannot handle received packet: %s", hci::EventCodeText(code).c_str()); |
| 216 | break; |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | void SecurityManagerImpl::OnPairingHandlerComplete(hci::Address address) { |
| 221 | auto entry = pairing_handler_map_.find(address); |
| 222 | if (entry != pairing_handler_map_.end()) { |
| 223 | pairing_handler_map_.erase(entry); |
| 224 | } |
| 225 | NotifyDeviceBonded(hci::AddressWithType(address, hci::AddressType::PUBLIC_DEVICE_ADDRESS)); |
| 226 | } |
| 227 | |
| 228 | } // namespace internal |
| 229 | } // namespace security |
| 230 | } // namespace bluetooth |