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