1 /*
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 *
17 */
18 #include "security/pairing/classic_pairing_handler.h"
19
20 #include "common/bind.h"
21
22 namespace bluetooth {
23 namespace security {
24 namespace pairing {
25
NotifyUiDisplayYesNo(uint32_t numeric_value)26 void ClassicPairingHandler::NotifyUiDisplayYesNo(uint32_t numeric_value) {
27 user_interface_handler_->Post(common::BindOnce(&UI::DisplayConfirmValue, common::Unretained(user_interface_),
28 GetRecord()->GetPseudoAddress(), device_name_, numeric_value));
29 }
30
NotifyUiDisplayYesNo()31 void ClassicPairingHandler::NotifyUiDisplayYesNo() {
32 user_interface_handler_->Post(common::BindOnce(&UI::DisplayYesNoDialog, common::Unretained(user_interface_),
33 GetRecord()->GetPseudoAddress(), device_name_));
34 }
35
NotifyUiDisplayPasskey(uint32_t passkey)36 void ClassicPairingHandler::NotifyUiDisplayPasskey(uint32_t passkey) {
37 user_interface_handler_->Post(common::BindOnce(&UI::DisplayPasskey, common::Unretained(user_interface_),
38 GetRecord()->GetPseudoAddress(), device_name_, passkey));
39 }
40
NotifyUiDisplayPasskeyInput()41 void ClassicPairingHandler::NotifyUiDisplayPasskeyInput() {
42 user_interface_handler_->Post(common::BindOnce(&UI::DisplayEnterPasskeyDialog, common::Unretained(user_interface_),
43 GetRecord()->GetPseudoAddress(), device_name_));
44 }
45
NotifyUiDisplayCancel()46 void ClassicPairingHandler::NotifyUiDisplayCancel() {
47 user_interface_handler_->Post(
48 common::BindOnce(&UI::Cancel, common::Unretained(user_interface_), GetRecord()->GetPseudoAddress()));
49 }
50
OnRegistrationComplete(l2cap::classic::FixedChannelManager::RegistrationResult result,std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service)51 void ClassicPairingHandler::OnRegistrationComplete(
52 l2cap::classic::FixedChannelManager::RegistrationResult result,
53 std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service) {
54 if (result != l2cap::classic::FixedChannelManager::RegistrationResult::SUCCESS) {
55 LOG_ERROR("Failed service registration!");
56 return;
57 }
58 fixed_channel_service_ = std::move(fixed_channel_service);
59 fixed_channel_manager_->ConnectServices(
60 GetRecord()->GetPseudoAddress().GetAddress(),
61 common::Bind(&ClassicPairingHandler::OnConnectionFail, common::Unretained(this)), security_handler_);
62 }
63
OnUnregistered()64 void ClassicPairingHandler::OnUnregistered() {
65 PairingResultOrFailure result = PairingResult();
66 if (last_status_ != hci::ErrorCode::SUCCESS) {
67 result = PairingFailure(hci::ErrorCodeText(last_status_));
68 }
69 std::move(complete_callback_).Run(GetRecord()->GetPseudoAddress().GetAddress(), result);
70 }
71
OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel)72 void ClassicPairingHandler::OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel) {
73 ASSERT(fixed_channel_ == nullptr);
74 fixed_channel_ = std::move(fixed_channel);
75 ASSERT(fixed_channel_->GetDevice() == GetRecord()->GetPseudoAddress().GetAddress());
76 fixed_channel_->RegisterOnCloseCallback(
77 security_handler_, common::BindOnce(&ClassicPairingHandler::OnConnectionClose, common::Unretained(this)));
78 fixed_channel_->Acquire();
79 }
80
OnConnectionFail(l2cap::classic::FixedChannelManager::ConnectionResult result)81 void ClassicPairingHandler::OnConnectionFail(l2cap::classic::FixedChannelManager::ConnectionResult result) {
82 Cancel();
83 }
84
OnConnectionClose(hci::ErrorCode error_code)85 void ClassicPairingHandler::OnConnectionClose(hci::ErrorCode error_code) {
86 // Called when the connection gets closed
87 LOG_ERROR("Connection closed due to: %s", hci::ErrorCodeText(error_code).c_str());
88 ASSERT(fixed_channel_ != nullptr);
89 fixed_channel_.reset();
90 Cancel();
91 }
92
OnPairingPromptAccepted(const bluetooth::hci::AddressWithType & address,bool confirmed)93 void ClassicPairingHandler::OnPairingPromptAccepted(const bluetooth::hci::AddressWithType& address, bool confirmed) {
94 LOG_WARN("TODO Not Implemented!");
95 }
96
OnConfirmYesNo(const bluetooth::hci::AddressWithType & address,bool confirmed)97 void ClassicPairingHandler::OnConfirmYesNo(const bluetooth::hci::AddressWithType& address, bool confirmed) {
98 LOG_WARN("TODO Not Implemented!");
99 GetChannel()->SendCommand(
100 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
101 }
102
OnPasskeyEntry(const bluetooth::hci::AddressWithType & address,uint32_t passkey)103 void ClassicPairingHandler::OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, uint32_t passkey) {
104 LOG_WARN("TODO Not Implemented!");
105 }
106
Initiate(bool locally_initiated,hci::IoCapability io_capability,hci::OobDataPresent oob_present,hci::AuthenticationRequirements auth_requirements)107 void ClassicPairingHandler::Initiate(bool locally_initiated, hci::IoCapability io_capability,
108 hci::OobDataPresent oob_present,
109 hci::AuthenticationRequirements auth_requirements) {
110 locally_initiated_ = locally_initiated;
111 local_io_capability_ = io_capability;
112 local_oob_present_ = oob_present;
113 local_authentication_requirements_ = auth_requirements;
114
115 // TODO(optedoblivion): Read OOB data
116 // if host and controller support secure connections used HCIREADLOCALOOBEXTENDEDDATA vs HCIREADLOCALOOBDATA
117
118 fixed_channel_manager_->RegisterService(
119 l2cap::kClassicPairingTriggerCid, security_policy_,
120 common::Bind(&ClassicPairingHandler::OnRegistrationComplete, common::Unretained(this)),
121 common::Bind(&ClassicPairingHandler::OnConnectionOpen, common::Unretained(this)), security_handler_);
122 }
123
Cancel()124 void ClassicPairingHandler::Cancel() {
125 if (fixed_channel_ != nullptr) {
126 fixed_channel_->Release();
127 }
128 if (fixed_channel_service_ != nullptr) {
129 fixed_channel_service_->Unregister(common::Bind(&ClassicPairingHandler::OnUnregistered, common::Unretained(this)),
130 security_handler_);
131 }
132 }
133
OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet)134 void ClassicPairingHandler::OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) {
135 ASSERT(packet.IsValid());
136 LOG_INFO("Received unsupported event: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
137 }
138
OnReceive(hci::MasterLinkKeyCompleteView packet)139 void ClassicPairingHandler::OnReceive(hci::MasterLinkKeyCompleteView packet) {
140 ASSERT(packet.IsValid());
141 LOG_INFO("Received unsupported event: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
142 }
143
OnReceive(hci::PinCodeRequestView packet)144 void ClassicPairingHandler::OnReceive(hci::PinCodeRequestView packet) {
145 ASSERT(packet.IsValid());
146 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
147 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
148 }
149
OnReceive(hci::LinkKeyRequestView packet)150 void ClassicPairingHandler::OnReceive(hci::LinkKeyRequestView packet) {
151 ASSERT(packet.IsValid());
152 // TODO(optedoblivion): Add collision detection here
153 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
154 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
155 if (GetRecord()->IsBonded() || GetRecord()->IsPaired()) {
156 auto packet = hci::LinkKeyRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress(),
157 GetRecord()->GetLinkKey());
158 this->GetChannel()->SendCommand(std::move(packet));
159 } else {
160 auto packet = hci::LinkKeyRequestNegativeReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress());
161 this->GetChannel()->SendCommand(std::move(packet));
162 }
163 }
164
OnReceive(hci::LinkKeyNotificationView packet)165 void ClassicPairingHandler::OnReceive(hci::LinkKeyNotificationView packet) {
166 ASSERT(packet.IsValid());
167 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
168 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
169 GetRecord()->SetLinkKey(packet.GetLinkKey(), packet.GetKeyType());
170 Cancel();
171 }
172
OnReceive(hci::IoCapabilityRequestView packet)173 void ClassicPairingHandler::OnReceive(hci::IoCapabilityRequestView packet) {
174 ASSERT(packet.IsValid());
175 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
176 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
177 hci::IoCapability io_capability = local_io_capability_;
178 hci::OobDataPresent oob_present = hci::OobDataPresent::NOT_PRESENT;
179 hci::AuthenticationRequirements authentication_requirements = local_authentication_requirements_;
180 auto reply_packet = hci::IoCapabilityRequestReplyBuilder::Create(
181 GetRecord()->GetPseudoAddress().GetAddress(), io_capability, oob_present, authentication_requirements);
182 this->GetChannel()->SendCommand(std::move(reply_packet));
183 }
184
OnReceive(hci::IoCapabilityResponseView packet)185 void ClassicPairingHandler::OnReceive(hci::IoCapabilityResponseView packet) {
186 ASSERT(packet.IsValid());
187 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
188 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
189
190 // Using local variable until device database pointer is ready
191 remote_io_capability_ = packet.GetIoCapability();
192 }
193
OnReceive(hci::SimplePairingCompleteView packet)194 void ClassicPairingHandler::OnReceive(hci::SimplePairingCompleteView packet) {
195 ASSERT(packet.IsValid());
196 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
197 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
198 last_status_ = packet.GetStatus();
199 if (last_status_ != hci::ErrorCode::SUCCESS) {
200 LOG_INFO("Failed SimplePairingComplete: %s", hci::ErrorCodeText(last_status_).c_str());
201 Cancel();
202 }
203 }
204
OnReceive(hci::ReturnLinkKeysView packet)205 void ClassicPairingHandler::OnReceive(hci::ReturnLinkKeysView packet) {
206 ASSERT(packet.IsValid());
207 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
208 }
209
OnReceive(hci::EncryptionChangeView packet)210 void ClassicPairingHandler::OnReceive(hci::EncryptionChangeView packet) {
211 ASSERT(packet.IsValid());
212 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
213 }
214
OnReceive(hci::EncryptionKeyRefreshCompleteView packet)215 void ClassicPairingHandler::OnReceive(hci::EncryptionKeyRefreshCompleteView packet) {
216 ASSERT(packet.IsValid());
217 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
218 }
219
OnReceive(hci::RemoteOobDataRequestView packet)220 void ClassicPairingHandler::OnReceive(hci::RemoteOobDataRequestView packet) {
221 ASSERT(packet.IsValid());
222 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
223 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
224 }
225
OnReceive(hci::UserPasskeyNotificationView packet)226 void ClassicPairingHandler::OnReceive(hci::UserPasskeyNotificationView packet) {
227 ASSERT(packet.IsValid());
228 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
229 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
230 }
231
OnReceive(hci::KeypressNotificationView packet)232 void ClassicPairingHandler::OnReceive(hci::KeypressNotificationView packet) {
233 ASSERT(packet.IsValid());
234 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
235 LOG_INFO("Notification Type: %s", hci::KeypressNotificationTypeText(packet.GetNotificationType()).c_str());
236 switch (packet.GetNotificationType()) {
237 case hci::KeypressNotificationType::ENTRY_STARTED:
238 // Get ready to keep track of key input
239 break;
240 case hci::KeypressNotificationType::DIGIT_ENTERED:
241 // Append digit to key
242 break;
243 case hci::KeypressNotificationType::DIGIT_ERASED:
244 // erase last digit from key
245 break;
246 case hci::KeypressNotificationType::CLEARED:
247 // erase all digits from key
248 break;
249 case hci::KeypressNotificationType::ENTRY_COMPLETED:
250 // set full key to security record
251 break;
252 }
253 }
254
255 /**
256 * Here we decide what type of pairing authentication method we will use
257 *
258 * The table is on pg 2133 of the Core v5.1 spec.
259 */
OnReceive(hci::UserConfirmationRequestView packet)260 void ClassicPairingHandler::OnReceive(hci::UserConfirmationRequestView packet) {
261 ASSERT(packet.IsValid());
262 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
263 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
264 // if locally_initialized, use default, otherwise us remote io caps
265 hci::IoCapability initiator_io_capability = (locally_initiated_) ? local_io_capability_ : remote_io_capability_;
266 hci::IoCapability responder_io_capability = (!locally_initiated_) ? local_io_capability_ : remote_io_capability_;
267 // TODO(optedoblivion): Check for TEMPORARY pairing case
268 switch (initiator_io_capability) {
269 case hci::IoCapability::DISPLAY_ONLY:
270 switch (responder_io_capability) {
271 case hci::IoCapability::DISPLAY_ONLY:
272 // NumericComparison, Both auto confirm
273 LOG_INFO("Numeric Comparison: A and B auto confirm");
274 GetChannel()->SendCommand(
275 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
276 // Unauthenticated
277 break;
278 case hci::IoCapability::DISPLAY_YES_NO:
279 // NumericComparison, Initiator auto confirm, Responder display
280 GetChannel()->SendCommand(
281 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
282 LOG_INFO("Numeric Comparison: A auto confirm");
283 // Unauthenticated
284 break;
285 case hci::IoCapability::KEYBOARD_ONLY:
286 // PassKey Entry, Initiator display, Responder input
287 NotifyUiDisplayPasskey(packet.GetNumericValue());
288 LOG_INFO("Passkey Entry: A display, B input");
289 // Authenticated
290 break;
291 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
292 // NumericComparison, Both auto confirm
293 LOG_INFO("Numeric Comparison: A and B auto confirm");
294 GetChannel()->SendCommand(
295 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
296 // Unauthenticated
297 break;
298 }
299 break;
300 case hci::IoCapability::DISPLAY_YES_NO:
301 switch (responder_io_capability) {
302 case hci::IoCapability::DISPLAY_ONLY:
303 // NumericComparison, Initiator display, Responder auto confirm
304 LOG_INFO("Numeric Comparison: A DisplayYesNo, B auto confirm");
305 NotifyUiDisplayYesNo(packet.GetNumericValue());
306 // Unauthenticated
307 break;
308 case hci::IoCapability::DISPLAY_YES_NO:
309 // NumericComparison Both Display, Both confirm
310 LOG_INFO("Numeric Comparison: A and B DisplayYesNo");
311 NotifyUiDisplayYesNo(packet.GetNumericValue());
312 // Authenticated
313 break;
314 case hci::IoCapability::KEYBOARD_ONLY:
315 // PassKey Entry, Initiator display, Responder input
316 NotifyUiDisplayPasskey(packet.GetNumericValue());
317 LOG_INFO("Passkey Entry: A display, B input");
318 // Authenticated
319 break;
320 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
321 // NumericComparison, auto confirm Responder, Yes/No confirm Initiator. Don't show confirmation value
322 NotifyUiDisplayYesNo();
323 LOG_INFO("Numeric Comparison: A DisplayYesNo, B auto confirm, no show value");
324 // Unauthenticated
325 break;
326 }
327 break;
328 case hci::IoCapability::KEYBOARD_ONLY:
329 switch (responder_io_capability) {
330 case hci::IoCapability::DISPLAY_ONLY:
331 // PassKey Entry, Responder display, Initiator input
332 NotifyUiDisplayPasskeyInput();
333 LOG_INFO("Passkey Entry: A input, B display");
334 // Authenticated
335 break;
336 case hci::IoCapability::DISPLAY_YES_NO:
337 // PassKey Entry, Responder display, Initiator input
338 NotifyUiDisplayPasskeyInput();
339 LOG_INFO("Passkey Entry: A input, B display");
340 // Authenticated
341 break;
342 case hci::IoCapability::KEYBOARD_ONLY:
343 // PassKey Entry, both input
344 NotifyUiDisplayPasskeyInput();
345 LOG_INFO("Passkey Entry: A input, B input");
346 // Authenticated
347 break;
348 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
349 // NumericComparison, both auto confirm
350 LOG_INFO("Numeric Comparison: A and B auto confirm");
351 GetChannel()->SendCommand(
352 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
353 // Unauthenticated
354 break;
355 }
356 break;
357 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
358 switch (responder_io_capability) {
359 case hci::IoCapability::DISPLAY_ONLY:
360 // NumericComparison, both auto confirm
361 LOG_INFO("Numeric Comparison: A and B auto confirm");
362 GetChannel()->SendCommand(
363 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
364 // Unauthenticated
365 break;
366 case hci::IoCapability::DISPLAY_YES_NO:
367 // NumericComparison, Initiator auto confirm, Responder Yes/No confirm, no show conf val
368 LOG_INFO("Numeric Comparison: A auto confirm");
369 GetChannel()->SendCommand(
370 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
371 // Unauthenticated
372 break;
373 case hci::IoCapability::KEYBOARD_ONLY:
374 // NumericComparison, both auto confirm
375 LOG_INFO("Numeric Comparison: A and B auto confirm");
376 GetChannel()->SendCommand(
377 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
378 // Unauthenticated
379 break;
380 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
381 // NumericComparison, both auto confirm
382 LOG_INFO("Numeric Comparison: A and B auto confirm");
383 GetChannel()->SendCommand(
384 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
385 // Unauthenticated
386 break;
387 }
388 break;
389 }
390 }
391
OnReceive(hci::UserPasskeyRequestView packet)392 void ClassicPairingHandler::OnReceive(hci::UserPasskeyRequestView packet) {
393 ASSERT(packet.IsValid());
394 ASSERT_LOG(GetRecord()->GetPseudoAddress().GetAddress() == packet.GetBdAddr(), "Address mismatch");
395 }
396
OnUserInput(bool user_input)397 void ClassicPairingHandler::OnUserInput(bool user_input) {
398 if (user_input) {
399 UserClickedYes();
400 } else {
401 UserClickedNo();
402 }
403 }
404
UserClickedYes()405 void ClassicPairingHandler::UserClickedYes() {
406 GetChannel()->SendCommand(
407 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
408 }
409
UserClickedNo()410 void ClassicPairingHandler::UserClickedNo() {
411 GetChannel()->SendCommand(
412 hci::UserConfirmationRequestNegativeReplyBuilder::Create(GetRecord()->GetPseudoAddress().GetAddress()));
413 }
414
OnPasskeyInput(uint32_t passkey)415 void ClassicPairingHandler::OnPasskeyInput(uint32_t passkey) {
416 passkey_ = passkey;
417 }
418
419 } // namespace pairing
420 } // namespace security
421 } // namespace bluetooth
422