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