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 <bluetooth/log.h>
21 
22 #include "common/bind.h"
23 
24 namespace bluetooth {
25 namespace security {
26 namespace pairing {
27 
NotifyUiDisplayYesNo(uint32_t numeric_value)28 void ClassicPairingHandler::NotifyUiDisplayYesNo(uint32_t numeric_value) {
29   log::assert_that(
30       user_interface_handler_ != nullptr, "assert failed: user_interface_handler_ != nullptr");
31   ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_, numeric_value);
32   data.SetRemoteIoCaps(remote_io_capability_);
33   data.SetRemoteAuthReqs(remote_authentication_requirements_);
34   data.SetRemoteOobDataPresent(remote_oob_present_);
35   user_interface_handler_->CallOn(user_interface_, &UI::DisplayConfirmValue, data);
36 }
37 
NotifyUiDisplayYesNo()38 void ClassicPairingHandler::NotifyUiDisplayYesNo() {
39   log::assert_that(
40       user_interface_handler_ != nullptr, "assert failed: user_interface_handler_ != nullptr");
41   ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_);
42   data.SetRemoteIoCaps(remote_io_capability_);
43   data.SetRemoteAuthReqs(remote_authentication_requirements_);
44   data.SetRemoteOobDataPresent(remote_oob_present_);
45   user_interface_handler_->CallOn(user_interface_, &UI::DisplayYesNoDialog, data);
46 }
47 
NotifyUiDisplayPasskey(uint32_t passkey)48 void ClassicPairingHandler::NotifyUiDisplayPasskey(uint32_t passkey) {
49   log::assert_that(
50       user_interface_handler_ != nullptr, "assert failed: user_interface_handler_ != nullptr");
51   ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_, passkey);
52   data.SetRemoteIoCaps(remote_io_capability_);
53   data.SetRemoteAuthReqs(remote_authentication_requirements_);
54   data.SetRemoteOobDataPresent(remote_oob_present_);
55   user_interface_handler_->CallOn(user_interface_, &UI::DisplayPasskey, data);
56 }
57 
NotifyUiDisplayPasskeyInput()58 void ClassicPairingHandler::NotifyUiDisplayPasskeyInput() {
59   log::assert_that(
60       user_interface_handler_ != nullptr, "assert failed: user_interface_handler_ != nullptr");
61   ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_);
62   data.SetRemoteIoCaps(remote_io_capability_);
63   data.SetRemoteAuthReqs(remote_authentication_requirements_);
64   data.SetRemoteOobDataPresent(remote_oob_present_);
65   user_interface_handler_->CallOn(user_interface_, &UI::DisplayEnterPasskeyDialog, data);
66 }
67 
NotifyUiDisplayPinCodeInput()68 void ClassicPairingHandler::NotifyUiDisplayPinCodeInput() {
69   log::assert_that(
70       user_interface_handler_ != nullptr, "assert failed: user_interface_handler_ != nullptr");
71   ConfirmationData data(*GetRecord()->GetPseudoAddress(), device_name_);
72   data.SetRemoteIoCaps(remote_io_capability_);
73   data.SetRemoteAuthReqs(remote_authentication_requirements_);
74   data.SetRemoteOobDataPresent(remote_oob_present_);
75   user_interface_handler_->CallOn(user_interface_, &UI::DisplayEnterPinDialog, data);
76 }
77 
NotifyUiDisplayCancel()78 void ClassicPairingHandler::NotifyUiDisplayCancel() {
79   log::assert_that(
80       user_interface_handler_ != nullptr, "assert failed: user_interface_handler_ != nullptr");
81   user_interface_handler_->CallOn(user_interface_, &UI::Cancel, *GetRecord()->GetPseudoAddress());
82 }
83 
OnPairingPromptAccepted(const bluetooth::hci::AddressWithType &,bool)84 void ClassicPairingHandler::OnPairingPromptAccepted(
85     const bluetooth::hci::AddressWithType& /* address */, bool /* confirmed */) {
86   // NOTE: This is not used by Classic, only by LE
87   log::fatal("This is not supported by Classic Pairing Handler, only LE");
88 }
89 
OnConfirmYesNo(const bluetooth::hci::AddressWithType &,bool confirmed)90 void ClassicPairingHandler::OnConfirmYesNo(
91     const bluetooth::hci::AddressWithType& /* address */, bool confirmed) {
92   if (confirmed) {
93     GetChannel()->SendCommand(
94         hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
95   } else {
96     GetChannel()->SendCommand(
97         hci::UserConfirmationRequestNegativeReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
98   }
99 }
100 
OnPasskeyEntry(const bluetooth::hci::AddressWithType & address,uint32_t passkey)101 void ClassicPairingHandler::OnPasskeyEntry(const bluetooth::hci::AddressWithType& address, uint32_t passkey) {
102   GetChannel()->SendCommand(hci::UserPasskeyRequestReplyBuilder::Create(address.GetAddress(), passkey));
103 }
104 
OnPinEntry(const bluetooth::hci::AddressWithType & address,std::vector<uint8_t> pin)105 void ClassicPairingHandler::OnPinEntry(const bluetooth::hci::AddressWithType& address, std::vector<uint8_t> pin) {
106   std::array<uint8_t, 16> padded_pin;
107   for (size_t i = 0; i < 16 && i < pin.size(); i++) {
108     padded_pin[i] = pin[i];
109   }
110   log::info("{}", address.GetAddress());
111   GetChannel()->SendCommand(hci::PinCodeRequestReplyBuilder::Create(address.GetAddress(), pin.size(), padded_pin));
112 }
113 
Initiate(bool locally_initiated,hci::IoCapability io_capability,hci::AuthenticationRequirements auth_requirements,OobData remote_p192_oob_data,OobData remote_p256_oob_data)114 void ClassicPairingHandler::Initiate(
115     bool locally_initiated,
116     hci::IoCapability io_capability,
117     hci::AuthenticationRequirements auth_requirements,
118     OobData remote_p192_oob_data,
119     OobData remote_p256_oob_data) {
120   log::info("Initiate");
121   locally_initiated_ = locally_initiated;
122   local_io_capability_ = io_capability;
123   local_authentication_requirements_ = auth_requirements;
124   remote_p192_oob_data_ = remote_p192_oob_data;
125   remote_p256_oob_data_ = remote_p256_oob_data;
126   bool has192 = remote_p192_oob_data.IsValid();
127   bool has256 = remote_p256_oob_data.IsValid();
128   bool has_both = has192 && has256;
129 
130   if (has_both) {
131     remote_oob_present_ = hci::OobDataPresent::P_192_AND_256_PRESENT;
132   } else {
133     if (has192) {
134       remote_oob_present_ = hci::OobDataPresent::P_192_PRESENT;
135     } else if (has256) {
136       remote_oob_present_ = hci::OobDataPresent::P_256_PRESENT;
137     }
138   }
139 
140   if (locally_initiated_) {
141     GetChannel()->Connect(GetRecord()->GetPseudoAddress()->GetAddress());
142   }
143 }
144 
OnNameRequestComplete(hci::Address address,bool)145 void ClassicPairingHandler::OnNameRequestComplete(hci::Address address, bool /* success */) {
146   if (GetNameDbModule()->IsNameCached(address)) {
147     auto remote_name = GetNameDbModule()->ReadCachedRemoteName(address);
148     std::string tmp_name;
149     for (uint8_t i : remote_name) {
150       tmp_name += i;
151     }
152     device_name_ = tmp_name;
153   }
154   has_gotten_name_response_ = true;
155   // For PIN Pairing
156   if (is_legacy_pin_code_) {
157     NotifyUiDisplayPinCodeInput();
158   }
159   // For SSP/Numeric comparison flow
160   if (user_confirmation_request_) {
161     this->OnReceive(*user_confirmation_request_);
162   }
163   // For OOB Flow; we go to link key notification and must wait for name
164   if (link_key_notification_) {
165     this->OnReceive(*link_key_notification_);
166   }
167 }
168 
Cancel()169 void ClassicPairingHandler::Cancel() {
170   if (is_cancelled_) return;
171   is_cancelled_ = true;
172   PairingResultOrFailure result = PairingResult();
173   if (last_status_ != hci::ErrorCode::SUCCESS) {
174     result = PairingFailure(hci::ErrorCodeText(last_status_));
175   }
176   std::move(complete_callback_).Run(GetRecord()->GetPseudoAddress()->GetAddress(), result);
177 }
178 
OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet)179 void ClassicPairingHandler::OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) {
180   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
181   log::info("Received unsupported event: {}", hci::EventCodeText(packet.GetEventCode()));
182 }
183 
OnReceive(hci::CentralLinkKeyCompleteView packet)184 void ClassicPairingHandler::OnReceive(hci::CentralLinkKeyCompleteView packet) {
185   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
186   log::info("Received unsupported event: {}", hci::EventCodeText(packet.GetEventCode()));
187 }
188 
OnReceive(hci::PinCodeRequestView packet)189 void ClassicPairingHandler::OnReceive(hci::PinCodeRequestView packet) {
190   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
191   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
192   log::assert_that(
193       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
194   is_legacy_pin_code_ = true;
195   GetNameDbModule()->ReadRemoteNameRequest(
196       GetRecord()->GetPseudoAddress()->GetAddress(),
197       common::BindOnce(&ClassicPairingHandler::OnNameRequestComplete, common::Unretained(this)),
198       security_handler_);
199 }
200 
OnReceive(hci::LinkKeyRequestView packet)201 void ClassicPairingHandler::OnReceive(hci::LinkKeyRequestView packet) {
202   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
203   if (already_link_key_replied_) {
204     log::warn("Pairing is already in progress...");
205     return;
206   }
207   already_link_key_replied_ = true;
208   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
209   log::assert_that(
210       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
211   if (GetRecord()->IsPaired()) {
212     log::info("Sending: LINK_KEY_REQUEST_REPLY");
213     this->GetChannel()->SendCommand(hci::LinkKeyRequestReplyBuilder::Create(
214         GetRecord()->GetPseudoAddress()->GetAddress(), GetRecord()->GetLinkKey()));
215     last_status_ = hci::ErrorCode::SUCCESS;
216     Cancel();
217   } else {
218     log::info("Sending: LINK_KEY_REQUEST_NEGATIVE_REPLY");
219     this->GetChannel()->SendCommand(
220         hci::LinkKeyRequestNegativeReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
221   }
222 }
223 
OnReceive(hci::LinkKeyNotificationView packet)224 void ClassicPairingHandler::OnReceive(hci::LinkKeyNotificationView packet) {
225   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
226   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
227   log::assert_that(
228       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
229   GetRecord()->SetLinkKey(packet.GetLinkKey(), packet.GetKeyType());
230   if (!has_gotten_name_response_) {
231     link_key_notification_ = std::make_optional<hci::LinkKeyNotificationView>(packet);
232     return;
233   }
234   if (is_legacy_pin_code_) {
235     last_status_ = hci::ErrorCode::SUCCESS;
236   }
237   Cancel();
238 }
239 
OnReceive(hci::IoCapabilityRequestView packet)240 void ClassicPairingHandler::OnReceive(hci::IoCapabilityRequestView packet) {
241   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
242   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
243   log::assert_that(
244       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
245   hci::IoCapability io_capability = local_io_capability_;
246   hci::OobDataPresent oob_present = remote_oob_present_;
247   hci::AuthenticationRequirements authentication_requirements = local_authentication_requirements_;
248   auto reply_packet = hci::IoCapabilityRequestReplyBuilder::Create(
249       GetRecord()->GetPseudoAddress()->GetAddress(), io_capability, oob_present, authentication_requirements);
250   this->GetChannel()->SendCommand(std::move(reply_packet));
251   GetNameDbModule()->ReadRemoteNameRequest(
252       GetRecord()->GetPseudoAddress()->GetAddress(),
253       common::BindOnce(&ClassicPairingHandler::OnNameRequestComplete, common::Unretained(this)),
254       security_handler_);
255 }
256 
OnReceive(hci::IoCapabilityResponseView packet)257 void ClassicPairingHandler::OnReceive(hci::IoCapabilityResponseView packet) {
258   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
259   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
260   log::assert_that(
261       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
262 
263   remote_io_capability_ = packet.GetIoCapability();
264   remote_authentication_requirements_ = packet.GetAuthenticationRequirements();
265 
266   switch (remote_authentication_requirements_) {
267     case hci::AuthenticationRequirements::NO_BONDING:
268       GetRecord()->SetIsEncryptionRequired(
269           local_authentication_requirements_ != hci::AuthenticationRequirements::NO_BONDING ||
270           local_authentication_requirements_ != hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION);
271       GetRecord()->SetRequiresMitmProtection(
272           local_authentication_requirements_ == hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION ||
273           local_authentication_requirements_ == hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION ||
274           local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION);
275       // TODO(optedoblivion): check for HID device (CoD) and if HID don't make temporary
276       GetRecord()->SetIsTemporary(
277           local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING ||
278           local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION);
279       break;
280     case hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION:
281       GetRecord()->SetIsEncryptionRequired(
282           local_authentication_requirements_ != hci::AuthenticationRequirements::NO_BONDING ||
283           local_authentication_requirements_ != hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION);
284       GetRecord()->SetRequiresMitmProtection(true);
285       GetRecord()->SetIsTemporary(
286           local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING ||
287           local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION);
288       break;
289     case hci::AuthenticationRequirements::DEDICATED_BONDING:
290       GetRecord()->SetIsEncryptionRequired(true);
291       GetRecord()->SetRequiresMitmProtection(
292           local_authentication_requirements_ == hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION ||
293           local_authentication_requirements_ == hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION ||
294           local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION);
295       break;
296     case hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION:
297       GetRecord()->SetIsEncryptionRequired(true);
298       GetRecord()->SetRequiresMitmProtection(true);
299       break;
300     case hci::AuthenticationRequirements::GENERAL_BONDING:
301       GetRecord()->SetIsEncryptionRequired(true);
302       GetRecord()->SetRequiresMitmProtection(
303           local_authentication_requirements_ == hci::AuthenticationRequirements::DEDICATED_BONDING_MITM_PROTECTION ||
304           local_authentication_requirements_ == hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION ||
305           local_authentication_requirements_ == hci::AuthenticationRequirements::NO_BONDING_MITM_PROTECTION);
306       break;
307     case hci::AuthenticationRequirements::GENERAL_BONDING_MITM_PROTECTION:
308       GetRecord()->SetIsEncryptionRequired(true);
309       GetRecord()->SetRequiresMitmProtection(true);
310       break;
311     default:
312       GetRecord()->SetIsEncryptionRequired(true);
313       GetRecord()->SetRequiresMitmProtection(true);
314       break;
315   }
316 
317   has_gotten_io_cap_response_ = true;
318   if (user_confirmation_request_) {
319     this->OnReceive(*user_confirmation_request_);
320   }
321 }
322 
OnReceive(hci::SimplePairingCompleteView packet)323 void ClassicPairingHandler::OnReceive(hci::SimplePairingCompleteView packet) {
324   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
325   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
326   log::assert_that(
327       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
328   last_status_ = packet.GetStatus();
329   if (last_status_ != hci::ErrorCode::SUCCESS) {
330     log::info("Failed SimplePairingComplete: {}", hci::ErrorCodeText(last_status_));
331     // Cancel here since we won't get LinkKeyNotification
332     Cancel();
333   }
334 }
335 
OnReceive(hci::ReturnLinkKeysView packet)336 void ClassicPairingHandler::OnReceive(hci::ReturnLinkKeysView packet) {
337   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
338   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
339 }
340 
OnReceive(hci::EncryptionChangeView packet)341 void ClassicPairingHandler::OnReceive(hci::EncryptionChangeView packet) {
342   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
343   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
344 }
345 
OnReceive(hci::EncryptionKeyRefreshCompleteView packet)346 void ClassicPairingHandler::OnReceive(hci::EncryptionKeyRefreshCompleteView packet) {
347   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
348   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
349 }
350 
OnReceive(hci::RemoteOobDataRequestView packet)351 void ClassicPairingHandler::OnReceive(hci::RemoteOobDataRequestView packet) {
352   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
353   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
354   log::assert_that(
355       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
356 
357   // Corev5.2 V2PF
358   switch (remote_oob_present_) {
359     case hci::OobDataPresent::NOT_PRESENT:
360       log::warn("Missing remote OOB data");
361       GetChannel()->SendCommand(
362           hci::RemoteOobDataRequestNegativeReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
363       break;
364     case hci::OobDataPresent::P_192_PRESENT:
365       log::info("P192 Present");
366       // TODO(optedoblivion): Figure this out and remove
367       secure_connections_enabled_ = false;
368       if (secure_connections_enabled_) {
369         GetChannel()->SendCommand(hci::RemoteOobExtendedDataRequestReplyBuilder::Create(
370             GetRecord()->GetPseudoAddress()->GetAddress(),
371             this->remote_p192_oob_data_.GetC(),
372             this->remote_p192_oob_data_.GetR(),
373             this->remote_p256_oob_data_.GetC(),
374             this->remote_p256_oob_data_.GetR()));
375       } else {
376         GetChannel()->SendCommand(hci::RemoteOobDataRequestReplyBuilder::Create(
377             GetRecord()->GetPseudoAddress()->GetAddress(),
378             this->remote_p192_oob_data_.GetC(),
379             this->remote_p192_oob_data_.GetR()));
380       }
381       break;
382     case hci::OobDataPresent::P_256_PRESENT:
383       log::info("P256 Present");
384       GetChannel()->SendCommand(hci::RemoteOobExtendedDataRequestReplyBuilder::Create(
385           GetRecord()->GetPseudoAddress()->GetAddress(),
386           this->remote_p192_oob_data_.GetC(),
387           this->remote_p192_oob_data_.GetR(),
388           this->remote_p256_oob_data_.GetC(),
389           this->remote_p256_oob_data_.GetR()));
390       break;
391     case hci::OobDataPresent::P_192_AND_256_PRESENT:
392       log::info("P192 and P256 Present");
393       GetChannel()->SendCommand(hci::RemoteOobExtendedDataRequestReplyBuilder::Create(
394           GetRecord()->GetPseudoAddress()->GetAddress(),
395           this->remote_p192_oob_data_.GetC(),
396           this->remote_p192_oob_data_.GetR(),
397           this->remote_p256_oob_data_.GetC(),
398           this->remote_p256_oob_data_.GetR()));
399       break;
400   }
401 }
402 
OnReceive(hci::UserPasskeyNotificationView packet)403 void ClassicPairingHandler::OnReceive(hci::UserPasskeyNotificationView packet) {
404   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
405   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
406   log::assert_that(
407       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
408   NotifyUiDisplayPasskey(packet.GetPasskey());
409 }
410 
OnReceive(hci::KeypressNotificationView packet)411 void ClassicPairingHandler::OnReceive(hci::KeypressNotificationView packet) {
412   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
413   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
414   log::info(
415       "Notification Type: {}", hci::KeypressNotificationTypeText(packet.GetNotificationType()));
416   switch (packet.GetNotificationType()) {
417     case hci::KeypressNotificationType::ENTRY_STARTED:
418       // Tell the UI to highlight the first digit
419       break;
420     case hci::KeypressNotificationType::DIGIT_ENTERED:
421       // Tell the UI to move one digit to the right
422       break;
423     case hci::KeypressNotificationType::DIGIT_ERASED:
424       // Tell the UI to move back one digit
425       break;
426     case hci::KeypressNotificationType::CLEARED:
427       // Tell the UI to highlight the first digit again
428       break;
429     case hci::KeypressNotificationType::ENTRY_COMPLETED:
430       // Tell the UI to hide the dialog
431       break;
432   }
433 }
434 
435 /**
436  * Here we decide what type of pairing authentication method we will use
437  *
438  * The table is on pg 2133 of the Core v5.1 spec.
439  */
440 
OnReceive(hci::UserConfirmationRequestView packet)441 void ClassicPairingHandler::OnReceive(hci::UserConfirmationRequestView packet) {
442   // Ensure we have io cap response otherwise checks will be wrong if it comes late
443   // Ensure we have the name response otherwise we cannot show a name for the device to the user
444   if (!has_gotten_io_cap_response_ || !has_gotten_name_response_) {
445     user_confirmation_request_ = std::make_optional<hci::UserConfirmationRequestView>(packet);
446     return;
447   }
448   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
449   log::info("Received: {}", hci::EventCodeText(packet.GetEventCode()));
450   log::assert_that(
451       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
452   // if locally_initialized, use default, otherwise us remote io caps
453   hci::IoCapability initiator_io_capability = (locally_initiated_) ? local_io_capability_ : remote_io_capability_;
454   hci::IoCapability responder_io_capability = (!locally_initiated_) ? local_io_capability_ : remote_io_capability_;
455   switch (initiator_io_capability) {
456     case hci::IoCapability::DISPLAY_ONLY:
457       switch (responder_io_capability) {
458         case hci::IoCapability::DISPLAY_ONLY:
459           // NumericComparison, Both auto confirm
460           log::info("Numeric Comparison: A and B auto confirm");
461           if (!GetRecord()->RequiresMitmProtection()) {
462             GetChannel()->SendCommand(
463                 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
464             // NOTE(optedoblivion) BTA needs a callback for when auto accepting JustWorks
465             // If we auto accept from the ClassicPairingHandler in GD then we won't
466             // get a callback to this shim function.
467             // We will have to call it anyway until we eliminate the need
468             // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES
469             NotifyUiDisplayYesNo();
470           } else {
471             GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create(
472                 GetRecord()->GetPseudoAddress()->GetAddress()));
473           }
474           // Unauthenticated
475           GetRecord()->SetAuthenticated(false);
476           break;
477         case hci::IoCapability::DISPLAY_YES_NO:
478           // NumericComparison, Initiator auto confirm, Responder display
479           if (!GetRecord()->RequiresMitmProtection()) {
480             GetChannel()->SendCommand(
481                 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
482             // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES
483             NotifyUiDisplayYesNo();
484           } else {
485             GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create(
486                 GetRecord()->GetPseudoAddress()->GetAddress()));
487           }
488           log::info("Numeric Comparison: A auto confirm");
489           // Unauthenticated
490           GetRecord()->SetAuthenticated(true);
491           break;
492         case hci::IoCapability::KEYBOARD_ONLY:
493           // PassKey Entry, Initiator display, Responder input
494           NotifyUiDisplayPasskey(packet.GetNumericValue());
495           log::info("Passkey Entry: A display, B input");
496           // Authenticated
497           GetRecord()->SetAuthenticated(true);
498           break;
499         case hci::IoCapability::NO_INPUT_NO_OUTPUT:
500           // NumericComparison, Both auto confirm
501           log::info("Numeric Comparison: A and B auto confirm");
502           if (!GetRecord()->RequiresMitmProtection()) {
503             GetChannel()->SendCommand(
504                 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
505             // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES
506             NotifyUiDisplayYesNo();
507           } else {
508             GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create(
509                 GetRecord()->GetPseudoAddress()->GetAddress()));
510           }
511           // Unauthenticated
512           GetRecord()->SetAuthenticated(true);
513           break;
514       }
515       break;
516     case hci::IoCapability::DISPLAY_YES_NO:
517       switch (responder_io_capability) {
518         case hci::IoCapability::DISPLAY_ONLY:
519           // NumericComparison, Initiator display, Responder auto confirm
520           log::info("Numeric Comparison: A DisplayYesNo, B auto confirm");
521           NotifyUiDisplayYesNo(packet.GetNumericValue());
522           // Unauthenticated
523           GetRecord()->SetAuthenticated(true);
524           break;
525         case hci::IoCapability::DISPLAY_YES_NO:
526           // NumericComparison Both Display, Both confirm
527           log::info("Numeric Comparison: A and B DisplayYesNo");
528           NotifyUiDisplayYesNo(packet.GetNumericValue());
529           // Authenticated
530           GetRecord()->SetAuthenticated(true);
531           break;
532         case hci::IoCapability::KEYBOARD_ONLY:
533           // PassKey Entry, Initiator display, Responder input
534           NotifyUiDisplayPasskey(packet.GetNumericValue());
535           log::info("Passkey Entry: A display, B input");
536           // Authenticated
537           GetRecord()->SetAuthenticated(true);
538           break;
539         case hci::IoCapability::NO_INPUT_NO_OUTPUT:
540           // NumericComparison, auto confirm Responder, Yes/No confirm Initiator. Don't show confirmation value
541           log::info("Numeric Comparison: A DisplayYesNo, B auto confirm, no show value");
542           NotifyUiDisplayYesNo();
543           // Unauthenticated
544           GetRecord()->SetAuthenticated(true);
545           break;
546       }
547       break;
548     case hci::IoCapability::KEYBOARD_ONLY:
549       switch (responder_io_capability) {
550         case hci::IoCapability::DISPLAY_ONLY:
551           // PassKey Entry, Responder display, Initiator input
552           NotifyUiDisplayPasskeyInput();
553           log::info("Passkey Entry: A input, B display");
554           // Authenticated
555           GetRecord()->SetAuthenticated(true);
556           break;
557         case hci::IoCapability::DISPLAY_YES_NO:
558           // PassKey Entry, Responder display, Initiator input
559           NotifyUiDisplayPasskeyInput();
560           log::info("Passkey Entry: A input, B display");
561           // Authenticated
562           GetRecord()->SetAuthenticated(true);
563           break;
564         case hci::IoCapability::KEYBOARD_ONLY:
565           // PassKey Entry, both input
566           NotifyUiDisplayPasskeyInput();
567           log::info("Passkey Entry: A input, B input");
568           // Authenticated
569           GetRecord()->SetAuthenticated(true);
570           break;
571         case hci::IoCapability::NO_INPUT_NO_OUTPUT:
572           // NumericComparison, both auto confirm
573           log::info("Numeric Comparison: A and B auto confirm");
574           if (!GetRecord()->RequiresMitmProtection()) {
575             GetChannel()->SendCommand(
576                 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
577             // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES
578             NotifyUiDisplayYesNo();
579           } else {
580             GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create(
581                 GetRecord()->GetPseudoAddress()->GetAddress()));
582           }
583           // Unauthenticated
584           GetRecord()->SetAuthenticated(false);
585           break;
586       }
587       break;
588     case hci::IoCapability::NO_INPUT_NO_OUTPUT:
589       switch (responder_io_capability) {
590         case hci::IoCapability::DISPLAY_ONLY:
591           // NumericComparison, both auto confirm
592           log::info("Numeric Comparison: A and B auto confirm");
593           if (!GetRecord()->RequiresMitmProtection()) {
594             GetChannel()->SendCommand(
595                 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
596             // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES
597             NotifyUiDisplayYesNo();
598           } else {
599             GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create(
600                 GetRecord()->GetPseudoAddress()->GetAddress()));
601           }
602           // Unauthenticated
603           GetRecord()->SetAuthenticated(false);
604           break;
605         case hci::IoCapability::DISPLAY_YES_NO:
606           // NumericComparison, Initiator auto confirm, Responder Yes/No confirm, no show conf val
607           log::info("Numeric Comparison: A auto confirm");
608           if (!GetRecord()->RequiresMitmProtection()) {
609             GetChannel()->SendCommand(
610                 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
611             // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES
612             NotifyUiDisplayYesNo();
613           } else {
614             GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create(
615                 GetRecord()->GetPseudoAddress()->GetAddress()));
616           }
617           // Unauthenticated
618           GetRecord()->SetAuthenticated(false);
619           break;
620         case hci::IoCapability::KEYBOARD_ONLY:
621           // NumericComparison, both auto confirm
622           log::info("Numeric Comparison: A and B auto confirm");
623           if (!GetRecord()->RequiresMitmProtection()) {
624             GetChannel()->SendCommand(
625                 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
626             // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES
627             NotifyUiDisplayYesNo();
628           } else {
629             GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create(
630                 GetRecord()->GetPseudoAddress()->GetAddress()));
631           }
632           // Unauthenticated
633           GetRecord()->SetAuthenticated(false);
634           break;
635         case hci::IoCapability::NO_INPUT_NO_OUTPUT:
636           // NumericComparison, both auto confirm
637           log::info("Numeric Comparison: A and B auto confirm");
638           if (!GetRecord()->RequiresMitmProtection()) {
639             GetChannel()->SendCommand(
640                 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
641             // TODO(optedoblivion): REMOVE WHEN SHIM LEAVES
642             NotifyUiDisplayYesNo();
643           } else {
644             GetChannel()->SendCommand(hci::UserConfirmationRequestNegativeReplyBuilder::Create(
645                 GetRecord()->GetPseudoAddress()->GetAddress()));
646           }
647           // Unauthenticated
648           GetRecord()->SetAuthenticated(false);
649           break;
650       }
651       break;
652   }
653 }
654 
OnReceive(hci::UserPasskeyRequestView packet)655 void ClassicPairingHandler::OnReceive(hci::UserPasskeyRequestView packet) {
656   log::assert_that(packet.IsValid(), "assert failed: packet.IsValid()");
657   log::assert_that(
658       GetRecord()->GetPseudoAddress()->GetAddress() == packet.GetBdAddr(), "Address mismatch");
659 }
660 
OnUserInput(bool user_input)661 void ClassicPairingHandler::OnUserInput(bool user_input) {
662   if (user_input) {
663     UserClickedYes();
664   } else {
665     UserClickedNo();
666   }
667 }
668 
UserClickedYes()669 void ClassicPairingHandler::UserClickedYes() {
670   GetChannel()->SendCommand(
671       hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
672 }
673 
UserClickedNo()674 void ClassicPairingHandler::UserClickedNo() {
675   GetChannel()->SendCommand(
676       hci::UserConfirmationRequestNegativeReplyBuilder::Create(GetRecord()->GetPseudoAddress()->GetAddress()));
677 }
678 
OnPasskeyInput(uint32_t passkey)679 void ClassicPairingHandler::OnPasskeyInput(uint32_t passkey) {
680   passkey_ = passkey;
681 }
682 
683 }  // namespace pairing
684 }  // namespace security
685 }  // namespace bluetooth
686