1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_bluetooth_sapphire/internal/host/gap/pairing_state.h"
16
17 #include <inttypes.h>
18
19 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
20 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_connection_manager.h"
21 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
22 #include "pw_bluetooth_sapphire/internal/host/sm/util.h"
23 #include "pw_bluetooth_sapphire/internal/host/transport/transport.h"
24
25 namespace bt::gap {
26
27 using pw::bluetooth::emboss::AuthenticationRequirements;
28 using pw::bluetooth::emboss::IoCapability;
29 using sm::util::IOCapabilityForHci;
30
31 namespace {
32
33 const char* const kInspectEncryptionStatusPropertyName = "encryption_status";
34 const char* const kInspectSecurityPropertiesPropertyName =
35 "security_properties";
36
37 } // namespace
38
PairingState(Peer::WeakPtr peer,hci::BrEdrConnection * link,bool link_initiated,fit::closure auth_cb,StatusCallback status_cb)39 PairingState::PairingState(Peer::WeakPtr peer,
40 hci::BrEdrConnection* link,
41 bool link_initiated,
42 fit::closure auth_cb,
43 StatusCallback status_cb)
44 : peer_id_(peer->identifier()),
45 peer_(std::move(peer)),
46 link_(link),
47 outgoing_connection_(link_initiated),
48 peer_missing_key_(false),
49 state_(State::kIdle),
50 send_auth_request_callback_(std::move(auth_cb)),
51 status_callback_(std::move(status_cb)) {
52 BT_ASSERT(link_);
53 BT_ASSERT(send_auth_request_callback_);
54 BT_ASSERT(status_callback_);
55 link_->set_encryption_change_callback(
56 fit::bind_member<&PairingState::OnEncryptionChange>(this));
57 cleanup_cb_ = [](PairingState* self) {
58 self->link_->set_encryption_change_callback(nullptr);
59 auto callbacks_to_signal =
60 self->CompletePairingRequests(ToResult(HostError::kLinkDisconnected));
61
62 bt_log(TRACE,
63 "gap-bredr",
64 "Signaling %zu unresolved pairing listeners for %#.4x",
65 callbacks_to_signal.size(),
66 self->handle());
67
68 for (auto& cb : callbacks_to_signal) {
69 cb();
70 }
71 };
72 }
73
~PairingState()74 PairingState::~PairingState() {
75 if (cleanup_cb_) {
76 cleanup_cb_(this);
77 }
78 }
79
InitiatePairing(BrEdrSecurityRequirements security_requirements,StatusCallback status_cb)80 void PairingState::InitiatePairing(
81 BrEdrSecurityRequirements security_requirements, StatusCallback status_cb) {
82 // TODO(fxbug.dev/42082728): Reject pairing if peer/local device don't support
83 // Secure Connections and SC is required
84 if (state() == State::kIdle) {
85 BT_ASSERT(!is_pairing());
86
87 // If the current link key already meets the security requirements, skip
88 // pairing and report success.
89 if (link_->ltk_type() && SecurityPropertiesMeetRequirements(
90 sm::SecurityProperties(*link_->ltk_type()),
91 security_requirements)) {
92 status_cb(handle(), fit::ok());
93 return;
94 }
95 // TODO(fxbug.dev/42118593): If there is no pairing delegate set AND the
96 // current peer does not have a bonded link key, there is no way to upgrade
97 // the link security, so we don't need to bother calling
98 // `send_auth_request`.
99 //
100 // TODO(fxbug.dev/42133435): If current IO capabilities would make meeting
101 // security requirements impossible, skip pairing and report failure
102 // immediately.
103
104 current_pairing_ =
105 Pairing::MakeInitiator(security_requirements, outgoing_connection_);
106 PairingRequest request{.security_requirements = security_requirements,
107 .status_callback = std::move(status_cb)};
108 request_queue_.push_back(std::move(request));
109 bt_log(DEBUG,
110 "gap-bredr",
111 "Initiating pairing on %#.4x (id %s)",
112 handle(),
113 bt_str(peer_id()));
114 state_ = State::kInitiatorWaitLinkKeyRequest;
115 send_auth_request_callback_();
116 return;
117 }
118
119 // More than one consumer may wish to initiate pairing (e.g. concurrent
120 // outbound L2CAP channels), but each should wait for the results of any
121 // ongoing pairing procedure instead of sending their own Authentication
122 // Request.
123 if (is_pairing()) {
124 BT_ASSERT(state() != State::kIdle);
125 bt_log(INFO,
126 "gap-bredr",
127 "Already pairing %#.4x (id: %s); blocking callback on completion",
128 handle(),
129 bt_str(peer_id()));
130 PairingRequest request{.security_requirements = security_requirements,
131 .status_callback = std::move(status_cb)};
132 request_queue_.push_back(std::move(request));
133 } else {
134 // In the error state, we should expect no pairing to be created and cancel
135 // this particular request immediately.
136 BT_ASSERT(state() == State::kFailed);
137 status_cb(handle(), ToResult(HostError::kCanceled));
138 }
139 }
140
InitiateNextPairingRequest()141 void PairingState::InitiateNextPairingRequest() {
142 BT_ASSERT(state() == State::kIdle);
143 BT_ASSERT(!is_pairing());
144
145 if (request_queue_.empty()) {
146 return;
147 }
148
149 PairingRequest& request = request_queue_.front();
150
151 current_pairing_ = Pairing::MakeInitiator(request.security_requirements,
152 outgoing_connection_);
153 bt_log(DEBUG,
154 "gap-bredr",
155 "Initiating queued pairing on %#.4x (id %s)",
156 handle(),
157 bt_str(peer_id()));
158 state_ = State::kInitiatorWaitLinkKeyRequest;
159 send_auth_request_callback_();
160 }
161
OnIoCapabilityRequest()162 std::optional<IoCapability> PairingState::OnIoCapabilityRequest() {
163 if (state() != State::kInitiatorWaitIoCapRequest &&
164 state() != State::kResponderWaitIoCapRequest) {
165 FailWithUnexpectedEvent(__func__);
166 return std::nullopt;
167 }
168
169 // Log an error and return std::nullopt if we can't respond to a pairing
170 // request because there's no pairing delegate. This corresponds to the
171 // non-bondable state as outlined in spec v5.2 Vol. 3 Part C 4.3.1.
172 if (!pairing_delegate().is_alive()) {
173 bt_log(WARN,
174 "gap-bredr",
175 "No pairing delegate set; not pairing link %#.4x (peer: %s)",
176 handle(),
177 bt_str(peer_id()));
178 // We set the state_ to Idle instead of Failed because it is possible that a
179 // PairingDelegate will be set before the next pairing attempt, allowing it
180 // to succeed.
181 state_ = State::kIdle;
182 SignalStatus(ToResult(HostError::kNotReady), __func__);
183 return std::nullopt;
184 }
185
186 current_pairing_->local_iocap =
187 sm::util::IOCapabilityForHci(pairing_delegate()->io_capability());
188 if (state() == State::kInitiatorWaitIoCapRequest) {
189 BT_ASSERT(initiator());
190 state_ = State::kInitiatorWaitIoCapResponse;
191 } else {
192 BT_ASSERT(is_pairing());
193 BT_ASSERT(!initiator());
194 current_pairing_->ComputePairingData();
195
196 state_ = GetStateForPairingEvent(current_pairing_->expected_event);
197 }
198
199 return current_pairing_->local_iocap;
200 }
201
OnIoCapabilityResponse(IoCapability peer_iocap)202 void PairingState::OnIoCapabilityResponse(IoCapability peer_iocap) {
203 // If we preivously provided a key for peer to pair, but that didn't work,
204 // they may try to re-pair. Cancel the previous pairing if they try to
205 // restart.
206 if (state() == State::kWaitEncryption) {
207 BT_ASSERT(is_pairing());
208 current_pairing_ = nullptr;
209 state_ = State::kIdle;
210 }
211 if (state() == State::kIdle) {
212 BT_ASSERT(!is_pairing());
213 current_pairing_ = Pairing::MakeResponder(peer_iocap, outgoing_connection_);
214
215 // Defer gathering local IO Capability until OnIoCapabilityRequest, where
216 // the pairing can be rejected if there's no pairing delegate.
217 state_ = State::kResponderWaitIoCapRequest;
218 } else if (state() == State::kInitiatorWaitIoCapResponse) {
219 BT_ASSERT(initiator());
220
221 current_pairing_->peer_iocap = peer_iocap;
222 current_pairing_->ComputePairingData();
223
224 state_ = GetStateForPairingEvent(current_pairing_->expected_event);
225 } else {
226 FailWithUnexpectedEvent(__func__);
227 }
228 }
229
OnUserConfirmationRequest(uint32_t numeric_value,UserConfirmationCallback cb)230 void PairingState::OnUserConfirmationRequest(uint32_t numeric_value,
231 UserConfirmationCallback cb) {
232 if (state() != State::kWaitUserConfirmationRequest) {
233 FailWithUnexpectedEvent(__func__);
234 cb(false);
235 return;
236 }
237 BT_ASSERT(is_pairing());
238
239 // TODO(fxbug.dev/42113087): Reject pairing if pairing delegate went away.
240 BT_ASSERT(pairing_delegate().is_alive());
241 state_ = State::kWaitPairingComplete;
242
243 if (current_pairing_->action == PairingAction::kAutomatic) {
244 if (!outgoing_connection_) {
245 bt_log(ERROR,
246 "gap-bredr",
247 "automatically rejecting incoming link pairing (peer: %s, handle: "
248 "%#.4x)",
249 bt_str(peer_id()),
250 handle());
251 } else {
252 bt_log(DEBUG,
253 "gap-bredr",
254 "automatically confirming outgoing link pairing (peer: %s, "
255 "handle: %#.4x)",
256 bt_str(peer_id()),
257 handle());
258 }
259 cb(outgoing_connection_);
260 return;
261 }
262 auto confirm_cb = [cb = std::move(cb),
263 pairing = current_pairing_->GetWeakPtr(),
264 peer_id = peer_id(),
265 handle = handle()](bool confirm) mutable {
266 if (!pairing.is_alive()) {
267 return;
268 }
269 bt_log(DEBUG,
270 "gap-bredr",
271 "%sing User Confirmation Request (peer: %s, handle: %#.4x)",
272 confirm ? "Confirm" : "Cancel",
273 bt_str(peer_id),
274 handle);
275 cb(confirm);
276 };
277 // PairingAction::kDisplayPasskey indicates that this device has a display and
278 // performs "Numeric Comparison with automatic confirmation" but
279 // auto-confirmation is delegated to PairingDelegate.
280 if (current_pairing_->action == PairingAction::kDisplayPasskey ||
281 current_pairing_->action == PairingAction::kComparePasskey) {
282 pairing_delegate()->DisplayPasskey(
283 peer_id(),
284 numeric_value,
285 PairingDelegate::DisplayMethod::kComparison,
286 std::move(confirm_cb));
287 } else if (current_pairing_->action == PairingAction::kGetConsent) {
288 pairing_delegate()->ConfirmPairing(peer_id(), std::move(confirm_cb));
289 } else {
290 BT_PANIC("%#.4x (id: %s): unexpected action %d",
291 handle(),
292 bt_str(peer_id()),
293 static_cast<int>(current_pairing_->action));
294 }
295 }
296
OnUserPasskeyRequest(UserPasskeyCallback cb)297 void PairingState::OnUserPasskeyRequest(UserPasskeyCallback cb) {
298 if (state() != State::kWaitUserPasskeyRequest) {
299 FailWithUnexpectedEvent(__func__);
300 cb(std::nullopt);
301 return;
302 }
303 BT_ASSERT(is_pairing());
304
305 // TODO(fxbug.dev/42113087): Reject pairing if pairing delegate went away.
306 BT_ASSERT(pairing_delegate().is_alive());
307 state_ = State::kWaitPairingComplete;
308
309 BT_ASSERT_MSG(current_pairing_->action == PairingAction::kRequestPasskey,
310 "%#.4x (id: %s): unexpected action %d",
311 handle(),
312 bt_str(peer_id()),
313 static_cast<int>(current_pairing_->action));
314 auto pairing = current_pairing_->GetWeakPtr();
315 auto passkey_cb =
316 [this, cb = std::move(cb), pairing](int64_t passkey) mutable {
317 if (!pairing.is_alive()) {
318 return;
319 }
320 bt_log(DEBUG,
321 "gap-bredr",
322 "%#.4x (id: %s): Replying %" PRId64 " to User Passkey Request",
323 handle(),
324 bt_str(peer_id()),
325 passkey);
326 if (passkey >= 0) {
327 cb(static_cast<uint32_t>(passkey));
328 } else {
329 cb(std::nullopt);
330 }
331 };
332 pairing_delegate()->RequestPasskey(peer_id(), std::move(passkey_cb));
333 }
334
OnUserPasskeyNotification(uint32_t numeric_value)335 void PairingState::OnUserPasskeyNotification(uint32_t numeric_value) {
336 if (state() != State::kWaitUserPasskeyNotification) {
337 FailWithUnexpectedEvent(__func__);
338 return;
339 }
340 BT_ASSERT(is_pairing());
341
342 // TODO(fxbug.dev/42113087): Reject pairing if pairing delegate went away.
343 BT_ASSERT(pairing_delegate().is_alive());
344 state_ = State::kWaitPairingComplete;
345
346 auto pairing = current_pairing_->GetWeakPtr();
347 auto confirm_cb = [this, pairing](bool confirm) {
348 if (!pairing.is_alive()) {
349 return;
350 }
351 bt_log(DEBUG,
352 "gap-bredr",
353 "%#.4x (id: %s): Can't %s pairing from Passkey Notification side",
354 handle(),
355 bt_str(peer_id()),
356 confirm ? "confirm" : "cancel");
357 };
358 pairing_delegate()->DisplayPasskey(peer_id(),
359 numeric_value,
360 PairingDelegate::DisplayMethod::kPeerEntry,
361 std::move(confirm_cb));
362 }
363
OnSimplePairingComplete(pw::bluetooth::emboss::StatusCode status_code)364 void PairingState::OnSimplePairingComplete(
365 pw::bluetooth::emboss::StatusCode status_code) {
366 // The pairing process may fail early, which the controller will deliver as an
367 // Simple Pairing Complete with a non-success status. Log and proxy the error
368 // code.
369 if (const fit::result result = ToResult(status_code);
370 is_pairing() && bt_is_error(result,
371 INFO,
372 "gap-bredr",
373 "Pairing failed on link %#.4x (id: %s)",
374 handle(),
375 bt_str(peer_id()))) {
376 // TODO(fxbug.dev/42113087): Checking pairing_delegate() for reset like this
377 // isn't thread safe.
378 if (pairing_delegate().is_alive()) {
379 pairing_delegate()->CompletePairing(peer_id(),
380 ToResult(HostError::kFailed));
381 }
382 state_ = State::kFailed;
383 SignalStatus(result, __func__);
384 return;
385 }
386 // Handle successful Authentication Complete events that are not expected.
387 if (state() != State::kWaitPairingComplete) {
388 FailWithUnexpectedEvent(__func__);
389 return;
390 }
391 BT_ASSERT(is_pairing());
392
393 pairing_delegate()->CompletePairing(peer_id(), fit::ok());
394 state_ = State::kWaitLinkKey;
395 }
396
OnLinkKeyRequest()397 std::optional<hci_spec::LinkKey> PairingState::OnLinkKeyRequest() {
398 if (state() != State::kIdle &&
399 state() != State::kInitiatorWaitLinkKeyRequest) {
400 FailWithUnexpectedEvent(__func__);
401 return std::nullopt;
402 }
403
404 BT_ASSERT(peer_.is_alive());
405
406 std::optional<sm::LTK> link_key;
407
408 if (peer_missing_key_) {
409 bt_log(INFO,
410 "gap-bredr",
411 "peer %s missing key, ignoring our key",
412 bt_str(peer_->identifier()));
413 } else if (peer_->bredr() && peer_->bredr()->bonded()) {
414 bt_log(INFO,
415 "gap-bredr",
416 "recalling link key for bonded peer %s",
417 bt_str(peer_->identifier()));
418
419 BT_ASSERT(peer_->bredr()->link_key().has_value());
420 link_key = peer_->bredr()->link_key();
421 BT_ASSERT(link_key->security().enc_key_size() ==
422 hci_spec::kBrEdrLinkKeySize);
423
424 const auto link_key_type = link_key->security().GetLinkKeyType();
425 BT_ASSERT(link_key_type.has_value());
426
427 link_->set_link_key(link_key->key(), link_key_type.value());
428 } else {
429 bt_log(
430 INFO, "gap-bredr", "peer %s not bonded", bt_str(peer_->identifier()));
431 }
432
433 // The link key request may be received outside of Simple Pairing (e.g. when
434 // the peer initiates the authentication procedure).
435 if (state() == State::kIdle) {
436 if (link_key.has_value()) {
437 BT_ASSERT(!is_pairing());
438 current_pairing_ = Pairing::MakeResponderForBonded();
439 state_ = State::kWaitEncryption;
440 return link_key->key();
441 }
442 return std::optional<hci_spec::LinkKey>();
443 }
444
445 BT_ASSERT(is_pairing());
446
447 if (link_key.has_value() &&
448 SecurityPropertiesMeetRequirements(
449 link_key->security(), current_pairing_->preferred_security)) {
450 // Skip Simple Pairing and just perform authentication with existing key.
451 state_ = State::kInitiatorWaitAuthComplete;
452 return link_key->key();
453 }
454
455 // Request that the controller perform Simple Pairing to generate a new key.
456 state_ = State::kInitiatorWaitIoCapRequest;
457 return std::nullopt;
458 }
459
OnLinkKeyNotification(const UInt128 & link_key,hci_spec::LinkKeyType key_type,bool local_secure_connections_supported)460 void PairingState::OnLinkKeyNotification(
461 const UInt128& link_key,
462 hci_spec::LinkKeyType key_type,
463 bool local_secure_connections_supported) {
464 // TODO(fxbug.dev/42111880): We assume the controller is never in pairing
465 // debug mode because it's a security hazard to pair and bond using Debug
466 // Combination link keys.
467 BT_ASSERT_MSG(key_type != hci_spec::LinkKeyType::kDebugCombination,
468 "Pairing on link %#.4x (id: %s) resulted in insecure Debug "
469 "Combination link key",
470 handle(),
471 bt_str(peer_id()));
472
473 // When not pairing, only connection link key changes are allowed.
474 if (state() == State::kIdle &&
475 key_type == hci_spec::LinkKeyType::kChangedCombination) {
476 if (!link_->ltk()) {
477 bt_log(WARN,
478 "gap-bredr",
479 "Got Changed Combination key but link %#.4x (id: %s) has no "
480 "current key",
481 handle(),
482 bt_str(peer_id()));
483 state_ = State::kFailed;
484 SignalStatus(ToResult(HostError::kInsufficientSecurity),
485 "OnLinkKeyNotification with no current key");
486 return;
487 }
488
489 bt_log(DEBUG,
490 "gap-bredr",
491 "Changing link key on %#.4x (id: %s)",
492 handle(),
493 bt_str(peer_id()));
494 link_->set_link_key(hci_spec::LinkKey(link_key, 0, 0), key_type);
495 return;
496 }
497
498 if (state() != State::kWaitLinkKey) {
499 FailWithUnexpectedEvent(__func__);
500 return;
501 }
502
503 // The association model and resulting link security properties are computed
504 // by both the Link Manager (controller) and the host subsystem, so check that
505 // they agree.
506 BT_ASSERT(is_pairing());
507 sm::SecurityProperties sec_props = sm::SecurityProperties(key_type);
508 current_pairing_->security_properties = sec_props;
509
510 // Link keys resulting from legacy pairing are assigned lowest security level
511 // and we reject them.
512 if (sec_props.level() == sm::SecurityLevel::kNoSecurity) {
513 bt_log(WARN,
514 "gap-bredr",
515 "Link key (type %hhu) for %#.4x (id: %s) has insufficient security",
516 static_cast<unsigned char>(key_type),
517 handle(),
518 bt_str(peer_id()));
519 state_ = State::kFailed;
520 SignalStatus(ToResult(HostError::kInsufficientSecurity),
521 "OnLinkKeyNotification with insufficient security");
522 return;
523 }
524
525 // inclusive-language: ignore
526 // If we performed an association procedure for MITM protection then expect
527 // the controller to produce a corresponding "authenticated" link key.
528 // Inversely, do not accept a link key reported as authenticated if we haven't
529 // performed the corresponding association procedure because it may provide a
530 // false high expectation of security to the user or application.
531 if (sec_props.authenticated() != current_pairing_->authenticated) {
532 bt_log(WARN,
533 "gap-bredr",
534 "Expected %sauthenticated link key for %#.4x (id: %s), got %hhu",
535 current_pairing_->authenticated ? "" : "un",
536 handle(),
537 bt_str(peer_id()),
538 static_cast<unsigned char>(key_type));
539 state_ = State::kFailed;
540 SignalStatus(ToResult(HostError::kInsufficientSecurity),
541 "OnLinkKeyNotification with incorrect link authorization");
542 return;
543 }
544
545 // Set Security Properties for this BR/EDR connection
546 set_security_properties(sec_props);
547
548 // TODO(fxbug.dev/42082735): When in SC Only mode, all services require
549 // security mode 4, level 4
550 if (security_mode() == BrEdrSecurityMode::SecureConnectionsOnly &&
551 security_properties().level() !=
552 sm::SecurityLevel::kSecureAuthenticated) {
553 bt_log(WARN,
554 "gap-bredr",
555 "BR/EDR link key has insufficient security for Secure Connections "
556 "Only mode");
557 state_ = State::kFailed;
558 SignalStatus(ToResult(HostError::kInsufficientSecurity),
559 "OnLinkKeyNotification requires Secure Connections");
560 return;
561 }
562
563 // If peer and local Secure Connections support are present, the pairing logic
564 // needs to verify that the Link Key Type received in the Link Key
565 // Notification event is one of the Secure Connections types (0x07 and 0x08).
566 //
567 // Core Spec v5.2 Vol 4, Part E, 7.7.24: The values 0x07 and 0x08 shall only
568 // be used when the Host has indicated support for Secure Connections in the
569 // Secure_Connections_Host_Support parameter.
570 if (IsPeerSecureConnectionsSupported() &&
571 local_secure_connections_supported) {
572 if (!security_properties().secure_connections()) {
573 bt_log(WARN,
574 "gap-bredr",
575 "Link Key Type must be a Secure Connections key type;"
576 " Received type: %hhu (handle: %#.4x, id: %s)",
577 static_cast<unsigned char>(key_type),
578 handle(),
579 bt_str(peer_id()));
580 state_ = State::kFailed;
581 SignalStatus(ToResult(HostError::kInsufficientSecurity),
582 "OnLinkKeyNotification requires Secure Connections");
583 return;
584 }
585 link_->set_use_secure_connections(true);
586 }
587
588 link_->set_link_key(hci_spec::LinkKey(link_key, 0, 0), key_type);
589 if (initiator()) {
590 state_ = State::kInitiatorWaitAuthComplete;
591 } else {
592 EnableEncryption();
593 }
594 }
595
OnAuthenticationComplete(pw::bluetooth::emboss::StatusCode status_code)596 void PairingState::OnAuthenticationComplete(
597 pw::bluetooth::emboss::StatusCode status_code) {
598 if (is_pairing() && peer_->bredr() && peer_->bredr()->bonded() &&
599 status_code == pw::bluetooth::emboss::StatusCode::PIN_OR_KEY_MISSING) {
600 // We have provided our link key, but the remote side says they don't have a
601 // key. Pretend we don't have a link key, then start the pairing over. We
602 // will get consent even if we are otherwise kAutomatic
603 bt_log(
604 INFO,
605 "gap-bredr",
606 "Re-initiating pairing on %#.4x (id %s) as remote side reports no key.",
607 handle(),
608 bt_str(peer_id()));
609 peer_missing_key_ = true;
610 current_pairing_->allow_automatic = false;
611 state_ = State::kInitiatorWaitLinkKeyRequest;
612 send_auth_request_callback_();
613 return;
614 }
615 // The pairing process may fail early, which the controller will deliver as an
616 // Authentication Complete with a non-success status. Log and proxy the error
617 // code.
618 if (const fit::result result = ToResult(status_code);
619 bt_is_error(result,
620 INFO,
621 "gap-bredr",
622 "Authentication failed on link %#.4x (id: %s)",
623 handle(),
624 bt_str(peer_id()))) {
625 state_ = State::kFailed;
626 SignalStatus(result, __func__);
627 return;
628 }
629
630 // Handle successful Authentication Complete events that are not expected.
631 if (state() != State::kInitiatorWaitAuthComplete) {
632 FailWithUnexpectedEvent(__func__);
633 return;
634 }
635 BT_ASSERT(initiator());
636 EnableEncryption();
637 }
638
OnEncryptionChange(hci::Result<bool> result)639 void PairingState::OnEncryptionChange(hci::Result<bool> result) {
640 // Update inspect properties
641 pw::bluetooth::emboss::EncryptionStatus encryption_status =
642 link_->encryption_status();
643 inspect_properties_.encryption_status.Set(
644 EncryptionStatusToString(encryption_status));
645
646 if (state() != State::kWaitEncryption) {
647 // Ignore encryption changes when not expecting them because they may be
648 // triggered by the peer at any time (v5.0 Vol 2, Part F, Sec 4.4).
649 bt_log(TRACE,
650 "gap-bredr",
651 "%#.4x (id: %s): %s(%s, %s) in state \"%s\"; taking no action",
652 handle(),
653 bt_str(peer_id()),
654 __func__,
655 bt_str(result),
656 result.is_ok() ? (result.value() ? "true" : "false") : "?",
657 ToString(state()));
658 return;
659 }
660
661 if (result.is_ok() && !result.value()) {
662 // With Secure Connections, encryption should never be disabled (v5.0 Vol 2,
663 // Part E, Sec 7.1.16) at all.
664 bt_log(WARN,
665 "gap-bredr",
666 "Pairing failed due to encryption disable on link %#.4x (id: %s)",
667 handle(),
668 bt_str(peer_id()));
669 result = fit::error(Error(HostError::kFailed));
670 }
671
672 // Perform state transition.
673 if (result.is_ok()) {
674 // Reset state for another pairing.
675 state_ = State::kIdle;
676 } else {
677 state_ = State::kFailed;
678 }
679
680 SignalStatus(result.is_ok() ? hci::Result<>(fit::ok()) : result.take_error(),
681 __func__);
682 }
683
MakeInitiator(BrEdrSecurityRequirements security_requirements,bool link_initiated)684 std::unique_ptr<PairingState::Pairing> PairingState::Pairing::MakeInitiator(
685 BrEdrSecurityRequirements security_requirements, bool link_initiated) {
686 // Private ctor is inaccessible to std::make_unique.
687 std::unique_ptr<Pairing> pairing(new Pairing(link_initiated));
688 pairing->initiator = true;
689 pairing->preferred_security = security_requirements;
690 return pairing;
691 }
692
MakeResponder(pw::bluetooth::emboss::IoCapability peer_iocap,bool link_initiated)693 std::unique_ptr<PairingState::Pairing> PairingState::Pairing::MakeResponder(
694 pw::bluetooth::emboss::IoCapability peer_iocap, bool link_initiated) {
695 // Private ctor is inaccessible to std::make_unique.
696 std::unique_ptr<Pairing> pairing(new Pairing(link_initiated));
697 pairing->initiator = false;
698 pairing->peer_iocap = peer_iocap;
699 // Don't try to upgrade security as responder.
700 pairing->preferred_security = {.authentication = false,
701 .secure_connections = false};
702 return pairing;
703 }
704
705 std::unique_ptr<PairingState::Pairing>
MakeResponderForBonded()706 PairingState::Pairing::MakeResponderForBonded() {
707 std::unique_ptr<Pairing> pairing(new Pairing(/* link initiated */ false));
708 pairing->initiator = false;
709 // Don't try to upgrade security as responder.
710 pairing->preferred_security = {.authentication = false,
711 .secure_connections = false};
712 return pairing;
713 }
714
ComputePairingData()715 void PairingState::Pairing::ComputePairingData() {
716 if (initiator) {
717 action = GetInitiatorPairingAction(local_iocap, peer_iocap);
718 } else {
719 action = GetResponderPairingAction(peer_iocap, local_iocap);
720 }
721 if (!allow_automatic && action == PairingAction::kAutomatic) {
722 action = PairingAction::kGetConsent;
723 }
724 expected_event = GetExpectedEvent(local_iocap, peer_iocap);
725 BT_DEBUG_ASSERT(GetStateForPairingEvent(expected_event) != State::kFailed);
726 authenticated = IsPairingAuthenticated(local_iocap, peer_iocap);
727 bt_log(DEBUG,
728 "gap-bredr",
729 "As %s with local %hhu/peer %hhu capabilities, expecting an "
730 "%sauthenticated %u pairing "
731 "using %#x%s",
732 initiator ? "initiator" : "responder",
733 static_cast<unsigned char>(local_iocap),
734 static_cast<unsigned char>(peer_iocap),
735 authenticated ? "" : "un",
736 static_cast<unsigned int>(action),
737 expected_event,
738 allow_automatic ? "" : " (auto not allowed)");
739 }
740
ToString(PairingState::State state)741 const char* PairingState::ToString(PairingState::State state) {
742 switch (state) {
743 case State::kIdle:
744 return "Idle";
745 case State::kInitiatorWaitLinkKeyRequest:
746 return "InitiatorWaitLinkKeyRequest";
747 case State::kInitiatorWaitIoCapRequest:
748 return "InitiatorWaitIoCapRequest";
749 case State::kInitiatorWaitIoCapResponse:
750 return "InitiatorWaitIoCapResponse";
751 case State::kResponderWaitIoCapRequest:
752 return "ResponderWaitIoCapRequest";
753 case State::kWaitUserConfirmationRequest:
754 return "WaitUserConfirmationRequest";
755 case State::kWaitUserPasskeyRequest:
756 return "WaitUserPasskeyRequest";
757 case State::kWaitUserPasskeyNotification:
758 return "WaitUserPasskeyNotification";
759 case State::kWaitPairingComplete:
760 return "WaitPairingComplete";
761 case State::kWaitLinkKey:
762 return "WaitLinkKey";
763 case State::kInitiatorWaitAuthComplete:
764 return "InitiatorWaitAuthComplete";
765 case State::kWaitEncryption:
766 return "WaitEncryption";
767 case State::kFailed:
768 return "Failed";
769 default:
770 break;
771 }
772 return "";
773 }
774
GetStateForPairingEvent(hci_spec::EventCode event_code)775 PairingState::State PairingState::GetStateForPairingEvent(
776 hci_spec::EventCode event_code) {
777 switch (event_code) {
778 case hci_spec::kUserConfirmationRequestEventCode:
779 return State::kWaitUserConfirmationRequest;
780 case hci_spec::kUserPasskeyRequestEventCode:
781 return State::kWaitUserPasskeyRequest;
782 case hci_spec::kUserPasskeyNotificationEventCode:
783 return State::kWaitUserPasskeyNotification;
784 default:
785 break;
786 }
787 return State::kFailed;
788 }
789
SignalStatus(hci::Result<> status,const char * caller)790 void PairingState::SignalStatus(hci::Result<> status, const char* caller) {
791 bt_log(INFO,
792 "gap-bredr",
793 "Signaling pairing listeners for %#.4x (id: %s) from %s with %s",
794 handle(),
795 bt_str(peer_id()),
796 caller,
797 bt_str(status));
798
799 // Collect the callbacks before invoking them so that
800 // CompletePairingRequests() can safely access members.
801 auto callbacks_to_signal = CompletePairingRequests(status);
802
803 // This PairingState may be destroyed by these callbacks (e.g. if signaling an
804 // error causes a disconnection), so care must be taken not to access any
805 // members.
806 status_callback_(handle(), status);
807 for (auto& cb : callbacks_to_signal) {
808 cb();
809 }
810 }
811
CompletePairingRequests(hci::Result<> status)812 std::vector<fit::closure> PairingState::CompletePairingRequests(
813 hci::Result<> status) {
814 std::vector<fit::closure> callbacks_to_signal;
815
816 if (!is_pairing()) {
817 BT_ASSERT(request_queue_.empty());
818 return callbacks_to_signal;
819 }
820
821 if (status.is_error()) {
822 // On pairing failure, signal all requests.
823 for (auto& request : request_queue_) {
824 callbacks_to_signal.push_back(
825 [handle = handle(),
826 status,
827 cb = std::move(request.status_callback)]() { cb(handle, status); });
828 }
829 request_queue_.clear();
830 current_pairing_ = nullptr;
831 return callbacks_to_signal;
832 }
833
834 BT_ASSERT(state_ == State::kIdle);
835 BT_ASSERT(link_->ltk_type().has_value());
836
837 auto security_properties = sm::SecurityProperties(link_->ltk_type().value());
838
839 // If a new link key was received, notify all callbacks because we always
840 // negotiate the best security possible. Even though pairing succeeded, send
841 // an error status if the individual request security requirements are not
842 // satisfied.
843 // TODO(fxbug.dev/42075714): Only notify failure to callbacks of requests that
844 // inclusive-language: ignore
845 // have the same (or none) MITM requirements as the current pairing.
846 bool link_key_received = current_pairing_->security_properties.has_value();
847 if (link_key_received) {
848 for (auto& request : request_queue_) {
849 auto sec_props_satisfied = SecurityPropertiesMeetRequirements(
850 security_properties, request.security_requirements);
851 auto request_status = sec_props_satisfied
852 ? status
853 : ToResult(HostError::kInsufficientSecurity);
854
855 callbacks_to_signal.push_back(
856 [handle = handle(),
857 request_status,
858 cb = std::move(request.status_callback)]() {
859 cb(handle, request_status);
860 });
861 }
862 request_queue_.clear();
863 } else {
864 // If no new link key was received, then only authentication with an old key
865 // was performed (Simple Pairing was not required), and unsatisfied requests
866 // should initiate a new pairing rather than failing. If any pairing
867 // requests are satisfied by the existing key, notify them.
868 auto it = request_queue_.begin();
869 while (it != request_queue_.end()) {
870 if (!SecurityPropertiesMeetRequirements(security_properties,
871 it->security_requirements)) {
872 it++;
873 continue;
874 }
875
876 callbacks_to_signal.push_back(
877 [handle = handle(), status, cb = std::move(it->status_callback)]() {
878 cb(handle, status);
879 });
880 it = request_queue_.erase(it);
881 }
882 }
883 current_pairing_ = nullptr;
884 InitiateNextPairingRequest();
885
886 return callbacks_to_signal;
887 }
888
EnableEncryption()889 void PairingState::EnableEncryption() {
890 if (!link_->StartEncryption()) {
891 bt_log(ERROR,
892 "gap-bredr",
893 "%#.4x (id: %s): Failed to enable encryption (state \"%s\")",
894 handle(),
895 bt_str(peer_id()),
896 ToString(state()));
897 status_callback_(link_->handle(), ToResult(HostError::kFailed));
898 state_ = State::kFailed;
899 return;
900 }
901 state_ = State::kWaitEncryption;
902 }
903
FailWithUnexpectedEvent(const char * handler_name)904 void PairingState::FailWithUnexpectedEvent(const char* handler_name) {
905 bt_log(ERROR,
906 "gap-bredr",
907 "%#.4x (id: %s): Unexpected event %s while in state \"%s\"",
908 handle(),
909 bt_str(peer_id()),
910 handler_name,
911 ToString(state()));
912 state_ = State::kFailed;
913 SignalStatus(ToResult(HostError::kNotSupported), __func__);
914 }
915
IsPeerSecureConnectionsSupported() const916 bool PairingState::IsPeerSecureConnectionsSupported() const {
917 return peer_->features().HasBit(
918 /*page=*/1, hci_spec::LMPFeature::kSecureConnectionsHostSupport) &&
919 peer_->features().HasBit(
920 /*page=*/2,
921 hci_spec::LMPFeature::kSecureConnectionsControllerSupport);
922 }
923
AttachInspect(inspect::Node & parent,std::string name)924 void PairingState::AttachInspect(inspect::Node& parent, std::string name) {
925 inspect_node_ = parent.CreateChild(name);
926
927 inspect_properties_.encryption_status = inspect_node_.CreateString(
928 kInspectEncryptionStatusPropertyName,
929 EncryptionStatusToString(link_->encryption_status()));
930
931 security_properties().AttachInspect(inspect_node_,
932 kInspectSecurityPropertiesPropertyName);
933 }
934
GetInitiatorPairingAction(IoCapability initiator_cap,IoCapability responder_cap)935 PairingAction GetInitiatorPairingAction(IoCapability initiator_cap,
936 IoCapability responder_cap) {
937 if (initiator_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
938 return PairingAction::kAutomatic;
939 }
940 if (responder_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
941 if (initiator_cap == IoCapability::DISPLAY_YES_NO) {
942 return PairingAction::kGetConsent;
943 }
944 return PairingAction::kAutomatic;
945 }
946 if (initiator_cap == IoCapability::KEYBOARD_ONLY) {
947 return PairingAction::kRequestPasskey;
948 }
949 if (responder_cap == IoCapability::DISPLAY_ONLY) {
950 if (initiator_cap == IoCapability::DISPLAY_YES_NO) {
951 return PairingAction::kComparePasskey;
952 }
953 return PairingAction::kAutomatic;
954 }
955 return PairingAction::kDisplayPasskey;
956 }
957
GetResponderPairingAction(IoCapability initiator_cap,IoCapability responder_cap)958 PairingAction GetResponderPairingAction(IoCapability initiator_cap,
959 IoCapability responder_cap) {
960 if (initiator_cap == IoCapability::NO_INPUT_NO_OUTPUT &&
961 responder_cap == IoCapability::KEYBOARD_ONLY) {
962 return PairingAction::kGetConsent;
963 }
964 if (initiator_cap == IoCapability::DISPLAY_YES_NO &&
965 responder_cap == IoCapability::DISPLAY_YES_NO) {
966 return PairingAction::kComparePasskey;
967 }
968 return GetInitiatorPairingAction(responder_cap, initiator_cap);
969 }
970
GetExpectedEvent(IoCapability local_cap,IoCapability peer_cap)971 hci_spec::EventCode GetExpectedEvent(IoCapability local_cap,
972 IoCapability peer_cap) {
973 if (local_cap == IoCapability::NO_INPUT_NO_OUTPUT ||
974 peer_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
975 return hci_spec::kUserConfirmationRequestEventCode;
976 }
977 if (local_cap == IoCapability::KEYBOARD_ONLY) {
978 return hci_spec::kUserPasskeyRequestEventCode;
979 }
980 if (peer_cap == IoCapability::KEYBOARD_ONLY) {
981 return hci_spec::kUserPasskeyNotificationEventCode;
982 }
983 return hci_spec::kUserConfirmationRequestEventCode;
984 }
985
IsPairingAuthenticated(IoCapability local_cap,IoCapability peer_cap)986 bool IsPairingAuthenticated(IoCapability local_cap, IoCapability peer_cap) {
987 if (local_cap == IoCapability::NO_INPUT_NO_OUTPUT ||
988 peer_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
989 return false;
990 }
991 if (local_cap == IoCapability::DISPLAY_YES_NO &&
992 peer_cap == IoCapability::DISPLAY_YES_NO) {
993 return true;
994 }
995 if (local_cap == IoCapability::KEYBOARD_ONLY ||
996 peer_cap == IoCapability::KEYBOARD_ONLY) {
997 return true;
998 }
999 return false;
1000 }
1001
GetInitiatorAuthenticationRequirements(IoCapability local_cap)1002 AuthenticationRequirements GetInitiatorAuthenticationRequirements(
1003 IoCapability local_cap) {
1004 if (local_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
1005 return AuthenticationRequirements::GENERAL_BONDING;
1006 }
1007 // inclusive-language: ignore
1008 return AuthenticationRequirements::MITM_GENERAL_BONDING;
1009 }
1010
GetResponderAuthenticationRequirements(IoCapability local_cap,IoCapability peer_cap)1011 AuthenticationRequirements GetResponderAuthenticationRequirements(
1012 IoCapability local_cap, IoCapability peer_cap) {
1013 if (IsPairingAuthenticated(local_cap, peer_cap)) {
1014 // inclusive-language: ignore
1015 return AuthenticationRequirements::MITM_GENERAL_BONDING;
1016 }
1017 return AuthenticationRequirements::GENERAL_BONDING;
1018 }
1019
1020 } // namespace bt::gap
1021