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