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