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