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/secure_simple_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
24 namespace bt::gap {
25
26 using pw::bluetooth::emboss::AuthenticationRequirements;
27 using pw::bluetooth::emboss::IoCapability;
28
29 namespace {
30
31 const char* const kInspectEncryptionStatusPropertyName = "encryption_status";
32 const char* const kInspectSecurityPropertiesPropertyName =
33 "security_properties";
34
35 } // namespace
36
SecureSimplePairingState(Peer::WeakPtr peer,PairingDelegate::WeakPtr pairing_delegate,WeakPtr<hci::BrEdrConnection> link,bool outgoing_connection,fit::closure auth_cb,StatusCallback status_cb)37 SecureSimplePairingState::SecureSimplePairingState(
38 Peer::WeakPtr peer,
39 PairingDelegate::WeakPtr pairing_delegate,
40 WeakPtr<hci::BrEdrConnection> link,
41 bool outgoing_connection,
42 fit::closure auth_cb,
43 StatusCallback status_cb)
44 : peer_id_(peer->identifier()),
45 peer_(std::move(peer)),
46 link_(std::move(link)),
47 outgoing_connection_(outgoing_connection),
48 peer_missing_key_(false),
49 pairing_delegate_(std::move(pairing_delegate)),
50 state_(State::kIdle),
51 send_auth_request_callback_(std::move(auth_cb)),
52 status_callback_(std::move(status_cb)) {
53 PW_CHECK(link_.is_alive());
54 PW_CHECK(send_auth_request_callback_);
55 PW_CHECK(status_callback_);
56 link_->set_encryption_change_callback(
57 fit::bind_member<&SecureSimplePairingState::OnEncryptionChange>(this));
58 cleanup_cb_ = [](SecureSimplePairingState* self) {
59 self->link_->set_encryption_change_callback(nullptr);
60 auto callbacks_to_signal =
61 self->CompletePairingRequests(ToResult(HostError::kLinkDisconnected));
62
63 bt_log(TRACE,
64 "gap-bredr",
65 "Signaling %zu unresolved pairing listeners for %#.4x",
66 callbacks_to_signal.size(),
67 self->handle());
68
69 for (auto& cb : callbacks_to_signal) {
70 cb();
71 }
72 };
73 }
74
~SecureSimplePairingState()75 SecureSimplePairingState::~SecureSimplePairingState() {
76 if (cleanup_cb_) {
77 cleanup_cb_(this);
78 }
79 }
80
InitiatePairing(BrEdrSecurityRequirements security_requirements,StatusCallback status_cb)81 void SecureSimplePairingState::InitiatePairing(
82 BrEdrSecurityRequirements security_requirements, StatusCallback status_cb) {
83 // TODO(fxbug.dev/42082728): Reject pairing if peer/local device don't support
84 // Secure Connections and SC is required
85 if (state() == State::kIdle) {
86 PW_CHECK(!is_pairing());
87
88 // If the current link key already meets the security requirements, skip
89 // pairing and report success.
90 if (link_->ltk_type() && SecurityPropertiesMeetRequirements(
91 sm::SecurityProperties(*link_->ltk_type()),
92 security_requirements)) {
93 status_cb(handle(), fit::ok());
94 return;
95 }
96 // TODO(fxbug.dev/42118593): If there is no pairing delegate set AND the
97 // current peer does not have a bonded link key, there is no way to upgrade
98 // the link security, so we don't need to bother calling
99 // `send_auth_request`.
100 //
101 // TODO(fxbug.dev/42133435): If current IO capabilities would make meeting
102 // security requirements impossible, skip pairing and report failure
103 // immediately.
104
105 current_pairing_ =
106 Pairing::MakeInitiator(security_requirements, outgoing_connection_);
107 PairingRequest request{.security_requirements = security_requirements,
108 .status_callback = std::move(status_cb)};
109 request_queue_.push_back(std::move(request));
110 bt_log(DEBUG,
111 "gap-bredr",
112 "Initiating pairing on %#.4x (id %s)",
113 handle(),
114 bt_str(peer_id()));
115 state_ = State::kInitiatorWaitLinkKeyRequest;
116 send_auth_request_callback_();
117 return;
118 }
119
120 // More than one consumer may wish to initiate pairing (e.g. concurrent
121 // outbound L2CAP channels), but each should wait for the results of any
122 // ongoing pairing procedure instead of sending their own Authentication
123 // Request.
124 if (is_pairing()) {
125 PW_CHECK(state() != State::kIdle);
126 bt_log(INFO,
127 "gap-bredr",
128 "Already pairing %#.4x (id: %s); blocking callback on completion",
129 handle(),
130 bt_str(peer_id()));
131 PairingRequest request{.security_requirements = security_requirements,
132 .status_callback = std::move(status_cb)};
133 request_queue_.push_back(std::move(request));
134 } else {
135 // In the error state, we should expect no pairing to be created and cancel
136 // this particular request immediately.
137 PW_CHECK(state() == State::kFailed);
138 status_cb(handle(), ToResult(HostError::kCanceled));
139 }
140 }
141
InitiateNextPairingRequest()142 void SecureSimplePairingState::InitiateNextPairingRequest() {
143 PW_CHECK(state() == State::kIdle);
144 PW_CHECK(!is_pairing());
145
146 if (request_queue_.empty()) {
147 return;
148 }
149
150 PairingRequest& request = request_queue_.front();
151
152 current_pairing_ = Pairing::MakeInitiator(request.security_requirements,
153 outgoing_connection_);
154 bt_log(DEBUG,
155 "gap-bredr",
156 "Initiating queued pairing on %#.4x (id %s)",
157 handle(),
158 bt_str(peer_id()));
159 state_ = State::kInitiatorWaitLinkKeyRequest;
160 send_auth_request_callback_();
161 }
162
OnIoCapabilityRequest()163 std::optional<IoCapability> SecureSimplePairingState::OnIoCapabilityRequest() {
164 if (state() != State::kInitiatorWaitIoCapRequest &&
165 state() != State::kResponderWaitIoCapRequest) {
166 FailWithUnexpectedEvent(__func__);
167 return std::nullopt;
168 }
169
170 // Log an error and return std::nullopt if we can't respond to a pairing
171 // request because there's no pairing delegate. This corresponds to the
172 // non-bondable state as outlined in spec v5.2 Vol. 3 Part C 4.3.1.
173 if (!pairing_delegate().is_alive()) {
174 bt_log(WARN,
175 "gap-bredr",
176 "No pairing delegate set; not pairing link %#.4x (peer: %s)",
177 handle(),
178 bt_str(peer_id()));
179 // We set the state_ to Idle instead of Failed because it is possible that a
180 // PairingDelegate will be set before the next pairing attempt, allowing it
181 // to succeed.
182 state_ = State::kIdle;
183 SignalStatus(ToResult(HostError::kNotReady), __func__);
184 return std::nullopt;
185 }
186
187 current_pairing_->local_iocap =
188 sm::util::IOCapabilityForHci(pairing_delegate()->io_capability());
189 if (state() == State::kInitiatorWaitIoCapRequest) {
190 PW_CHECK(initiator());
191 state_ = State::kInitiatorWaitIoCapResponse;
192 } else {
193 PW_CHECK(is_pairing());
194 PW_CHECK(!initiator());
195 current_pairing_->ComputePairingData();
196
197 state_ = GetStateForPairingEvent(current_pairing_->expected_event);
198 }
199
200 return current_pairing_->local_iocap;
201 }
202
OnIoCapabilityResponse(IoCapability peer_iocap)203 void SecureSimplePairingState::OnIoCapabilityResponse(IoCapability peer_iocap) {
204 // If we preivously provided a key for peer to pair, but that didn't work,
205 // they may try to re-pair. Cancel the previous pairing if they try to
206 // restart.
207 if (state() == State::kWaitEncryption) {
208 PW_CHECK(is_pairing());
209 current_pairing_ = nullptr;
210 state_ = State::kIdle;
211 }
212 if (state() == State::kIdle) {
213 PW_CHECK(!is_pairing());
214 current_pairing_ = Pairing::MakeResponder(peer_iocap, outgoing_connection_);
215
216 // Defer gathering local IO Capability until OnIoCapabilityRequest, where
217 // the pairing can be rejected if there's no pairing delegate.
218 state_ = State::kResponderWaitIoCapRequest;
219 } else if (state() == State::kInitiatorWaitIoCapResponse) {
220 PW_CHECK(initiator());
221
222 current_pairing_->peer_iocap = peer_iocap;
223 current_pairing_->ComputePairingData();
224
225 state_ = GetStateForPairingEvent(current_pairing_->expected_event);
226 } else {
227 FailWithUnexpectedEvent(__func__);
228 }
229 }
230
OnUserConfirmationRequest(uint32_t numeric_value,UserConfirmationCallback cb)231 void SecureSimplePairingState::OnUserConfirmationRequest(
232 uint32_t numeric_value, UserConfirmationCallback cb) {
233 if (state() != State::kWaitUserConfirmationRequest) {
234 FailWithUnexpectedEvent(__func__);
235 cb(false);
236 return;
237 }
238 PW_CHECK(is_pairing());
239
240 // TODO(fxbug.dev/42113087): Reject pairing if pairing delegate went away.
241 PW_CHECK(pairing_delegate().is_alive());
242 state_ = State::kWaitPairingComplete;
243
244 if (current_pairing_->action == PairingAction::kAutomatic) {
245 if (!outgoing_connection_) {
246 bt_log(ERROR,
247 "gap-bredr",
248 "automatically rejecting incoming link pairing (peer: %s, handle: "
249 "%#.4x)",
250 bt_str(peer_id()),
251 handle());
252 } else {
253 bt_log(DEBUG,
254 "gap-bredr",
255 "automatically confirming outgoing link pairing (peer: %s, "
256 "handle: %#.4x)",
257 bt_str(peer_id()),
258 handle());
259 }
260 cb(outgoing_connection_);
261 return;
262 }
263 auto confirm_cb = [callback = std::move(cb),
264 pairing = current_pairing_->GetWeakPtr(),
265 peer_id = peer_id(),
266 handle = handle()](bool confirm) mutable {
267 if (!pairing.is_alive()) {
268 return;
269 }
270 bt_log(DEBUG,
271 "gap-bredr",
272 "%sing User Confirmation Request (peer: %s, handle: %#.4x)",
273 confirm ? "Confirm" : "Cancel",
274 bt_str(peer_id),
275 handle);
276 callback(confirm);
277 };
278 // PairingAction::kDisplayPasskey indicates that this device has a display and
279 // performs "Numeric Comparison with automatic confirmation" but
280 // auto-confirmation is delegated to PairingDelegate.
281 if (current_pairing_->action == PairingAction::kDisplayPasskey ||
282 current_pairing_->action == PairingAction::kComparePasskey) {
283 pairing_delegate()->DisplayPasskey(
284 peer_id(),
285 numeric_value,
286 PairingDelegate::DisplayMethod::kComparison,
287 std::move(confirm_cb));
288 } else if (current_pairing_->action == PairingAction::kGetConsent) {
289 pairing_delegate()->ConfirmPairing(peer_id(), std::move(confirm_cb));
290 } else {
291 BT_PANIC("%#.4x (id: %s): unexpected action %d",
292 handle(),
293 bt_str(peer_id()),
294 static_cast<int>(current_pairing_->action));
295 }
296 }
297
OnUserPasskeyRequest(UserPasskeyCallback cb)298 void SecureSimplePairingState::OnUserPasskeyRequest(UserPasskeyCallback cb) {
299 if (state() != State::kWaitUserPasskeyRequest) {
300 FailWithUnexpectedEvent(__func__);
301 cb(std::nullopt);
302 return;
303 }
304 PW_CHECK(is_pairing());
305
306 // TODO(fxbug.dev/42113087): Reject pairing if pairing delegate went away.
307 PW_CHECK(pairing_delegate().is_alive());
308 state_ = State::kWaitPairingComplete;
309
310 PW_CHECK(current_pairing_->action == PairingAction::kRequestPasskey,
311 "%#.4x (id: %s): unexpected action %d",
312 handle(),
313 bt_str(peer_id()),
314 static_cast<int>(current_pairing_->action));
315 auto pairing = current_pairing_->GetWeakPtr();
316 auto passkey_cb =
317 [this, callback = std::move(cb), pairing](int64_t passkey) mutable {
318 if (!pairing.is_alive()) {
319 return;
320 }
321 bt_log(DEBUG,
322 "gap-bredr",
323 "%#.4x (id: %s): Replying %" PRId64 " to User Passkey Request",
324 handle(),
325 bt_str(peer_id()),
326 passkey);
327 if (passkey >= 0) {
328 callback(static_cast<uint32_t>(passkey));
329 } else {
330 callback(std::nullopt);
331 }
332 };
333 pairing_delegate()->RequestPasskey(peer_id(), std::move(passkey_cb));
334 }
335
OnUserPasskeyNotification(uint32_t numeric_value)336 void SecureSimplePairingState::OnUserPasskeyNotification(
337 uint32_t numeric_value) {
338 if (state() != State::kWaitUserPasskeyNotification) {
339 FailWithUnexpectedEvent(__func__);
340 return;
341 }
342 PW_CHECK(is_pairing());
343
344 // TODO(fxbug.dev/42113087): Reject pairing if pairing delegate went away.
345 PW_CHECK(pairing_delegate().is_alive());
346 state_ = State::kWaitPairingComplete;
347
348 auto pairing = current_pairing_->GetWeakPtr();
349 auto confirm_cb = [this, pairing](bool confirm) {
350 if (!pairing.is_alive()) {
351 return;
352 }
353 bt_log(DEBUG,
354 "gap-bredr",
355 "%#.4x (id: %s): Can't %s pairing from Passkey Notification side",
356 handle(),
357 bt_str(peer_id()),
358 confirm ? "confirm" : "cancel");
359 };
360 pairing_delegate()->DisplayPasskey(peer_id(),
361 numeric_value,
362 PairingDelegate::DisplayMethod::kPeerEntry,
363 std::move(confirm_cb));
364 }
365
OnSimplePairingComplete(pw::bluetooth::emboss::StatusCode status_code)366 void SecureSimplePairingState::OnSimplePairingComplete(
367 pw::bluetooth::emboss::StatusCode status_code) {
368 // The pairing process may fail early, which the controller will deliver as an
369 // Simple Pairing Complete with a non-success status. Log and proxy the error
370 // code.
371 if (const fit::result result = ToResult(status_code);
372 is_pairing() && bt_is_error(result,
373 INFO,
374 "gap-bredr",
375 "Pairing failed on link %#.4x (id: %s)",
376 handle(),
377 bt_str(peer_id()))) {
378 // TODO(fxbug.dev/42113087): Checking pairing_delegate() for reset like this
379 // isn't thread safe.
380 if (pairing_delegate().is_alive()) {
381 pairing_delegate()->CompletePairing(peer_id(),
382 ToResult(HostError::kFailed));
383 }
384 state_ = State::kFailed;
385 SignalStatus(result, __func__);
386 return;
387 }
388 // Handle successful Authentication Complete events that are not expected.
389 if (state() != State::kWaitPairingComplete) {
390 FailWithUnexpectedEvent(__func__);
391 return;
392 }
393 PW_CHECK(is_pairing());
394
395 pairing_delegate()->CompletePairing(peer_id(), fit::ok());
396 state_ = State::kWaitLinkKey;
397 }
398
OnLinkKeyRequest()399 std::optional<hci_spec::LinkKey> SecureSimplePairingState::OnLinkKeyRequest() {
400 if (state() != State::kIdle &&
401 state() != State::kInitiatorWaitLinkKeyRequest) {
402 FailWithUnexpectedEvent(__func__);
403 return std::nullopt;
404 }
405
406 PW_CHECK(peer_.is_alive());
407
408 std::optional<sm::LTK> link_key;
409
410 if (peer_missing_key_) {
411 bt_log(INFO,
412 "gap-bredr",
413 "peer %s missing key, ignoring our key",
414 bt_str(peer_->identifier()));
415 } else if (peer_->bredr() && peer_->bredr()->bonded()) {
416 bt_log(INFO,
417 "gap-bredr",
418 "recalling link key for bonded peer %s",
419 bt_str(peer_->identifier()));
420
421 PW_CHECK(peer_->bredr()->link_key().has_value());
422 link_key = peer_->bredr()->link_key();
423 PW_CHECK(link_key->security().enc_key_size() ==
424 hci_spec::kBrEdrLinkKeySize);
425
426 const auto link_key_type = link_key->security().GetLinkKeyType();
427 link_->set_link_key(link_key->key(), link_key_type);
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 PW_CHECK(!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 PW_CHECK(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 SecureSimplePairingState::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 PW_CHECK(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 PW_CHECK(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 bredr_security_ = 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 SecureSimplePairingState::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 PW_CHECK(initiator());
636 EnableEncryption();
637 }
638
OnEncryptionChange(hci::Result<bool> result)639 void SecureSimplePairingState::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
684 std::unique_ptr<SecureSimplePairingState::Pairing>
MakeInitiator(BrEdrSecurityRequirements security_requirements,bool outgoing_connection)685 SecureSimplePairingState::Pairing::MakeInitiator(
686 BrEdrSecurityRequirements security_requirements, bool outgoing_connection) {
687 // Private ctor is inaccessible to std::make_unique.
688 std::unique_ptr<Pairing> pairing(new Pairing(outgoing_connection));
689 pairing->initiator = true;
690 pairing->preferred_security = security_requirements;
691 return pairing;
692 }
693
694 std::unique_ptr<SecureSimplePairingState::Pairing>
MakeResponder(pw::bluetooth::emboss::IoCapability peer_iocap,bool outgoing_connection)695 SecureSimplePairingState::Pairing::MakeResponder(
696 pw::bluetooth::emboss::IoCapability peer_iocap, bool outgoing_connection) {
697 // Private ctor is inaccessible to std::make_unique.
698 std::unique_ptr<Pairing> pairing(new Pairing(outgoing_connection));
699 pairing->initiator = false;
700 pairing->peer_iocap = peer_iocap;
701 // Don't try to upgrade security as responder.
702 pairing->preferred_security = {.authentication = false,
703 .secure_connections = false};
704 return pairing;
705 }
706
707 std::unique_ptr<SecureSimplePairingState::Pairing>
MakeResponderForBonded()708 SecureSimplePairingState::Pairing::MakeResponderForBonded() {
709 std::unique_ptr<Pairing> pairing(new Pairing(/* link initiated */ false));
710 pairing->initiator = false;
711 // Don't try to upgrade security as responder.
712 pairing->preferred_security = {.authentication = false,
713 .secure_connections = false};
714 return pairing;
715 }
716
ComputePairingData()717 void SecureSimplePairingState::Pairing::ComputePairingData() {
718 if (initiator) {
719 action = GetInitiatorPairingAction(local_iocap, peer_iocap);
720 } else {
721 action = GetResponderPairingAction(peer_iocap, local_iocap);
722 }
723 if (!allow_automatic && action == PairingAction::kAutomatic) {
724 action = PairingAction::kGetConsent;
725 }
726 expected_event = GetExpectedEvent(local_iocap, peer_iocap);
727 PW_DCHECK(GetStateForPairingEvent(expected_event) != State::kFailed);
728 authenticated = IsPairingAuthenticated(local_iocap, peer_iocap);
729 bt_log(DEBUG,
730 "gap-bredr",
731 "As %s with local %hhu/peer %hhu capabilities, expecting an "
732 "%sauthenticated %u pairing "
733 "using %#x%s",
734 initiator ? "initiator" : "responder",
735 static_cast<unsigned char>(local_iocap),
736 static_cast<unsigned char>(peer_iocap),
737 authenticated ? "" : "un",
738 static_cast<unsigned int>(action),
739 expected_event,
740 allow_automatic ? "" : " (auto not allowed)");
741 }
742
ToString(SecureSimplePairingState::State state)743 const char* SecureSimplePairingState::ToString(
744 SecureSimplePairingState::State state) {
745 switch (state) {
746 case State::kIdle:
747 return "Idle";
748 case State::kInitiatorWaitLinkKeyRequest:
749 return "InitiatorWaitLinkKeyRequest";
750 case State::kInitiatorWaitIoCapRequest:
751 return "InitiatorWaitIoCapRequest";
752 case State::kInitiatorWaitIoCapResponse:
753 return "InitiatorWaitIoCapResponse";
754 case State::kResponderWaitIoCapRequest:
755 return "ResponderWaitIoCapRequest";
756 case State::kWaitUserConfirmationRequest:
757 return "WaitUserConfirmationRequest";
758 case State::kWaitUserPasskeyRequest:
759 return "WaitUserPasskeyRequest";
760 case State::kWaitUserPasskeyNotification:
761 return "WaitUserPasskeyNotification";
762 case State::kWaitPairingComplete:
763 return "WaitPairingComplete";
764 case State::kWaitLinkKey:
765 return "WaitLinkKey";
766 case State::kInitiatorWaitAuthComplete:
767 return "InitiatorWaitAuthComplete";
768 case State::kWaitEncryption:
769 return "WaitEncryption";
770 case State::kFailed:
771 return "Failed";
772 default:
773 break;
774 }
775 return "";
776 }
777
778 SecureSimplePairingState::State
GetStateForPairingEvent(hci_spec::EventCode event_code)779 SecureSimplePairingState::GetStateForPairingEvent(
780 hci_spec::EventCode event_code) {
781 switch (event_code) {
782 case hci_spec::kUserConfirmationRequestEventCode:
783 return State::kWaitUserConfirmationRequest;
784 case hci_spec::kUserPasskeyRequestEventCode:
785 return State::kWaitUserPasskeyRequest;
786 case hci_spec::kUserPasskeyNotificationEventCode:
787 return State::kWaitUserPasskeyNotification;
788 default:
789 break;
790 }
791 return State::kFailed;
792 }
793
SignalStatus(hci::Result<> status,const char * caller)794 void SecureSimplePairingState::SignalStatus(hci::Result<> status,
795 const char* caller) {
796 bt_log(INFO,
797 "gap-bredr",
798 "Signaling pairing listeners for %#.4x (id: %s) from %s with %s",
799 handle(),
800 bt_str(peer_id()),
801 caller,
802 bt_str(status));
803
804 // Collect the callbacks before invoking them so that
805 // CompletePairingRequests() can safely access members.
806 auto callbacks_to_signal = CompletePairingRequests(status);
807
808 // This SecureSimplePairingState may be destroyed by these callbacks (e.g. if
809 // signaling an error causes a disconnection), so care must be taken not to
810 // access any members.
811 status_callback_(handle(), status);
812 for (auto& cb : callbacks_to_signal) {
813 cb();
814 }
815 }
816
CompletePairingRequests(hci::Result<> status)817 std::vector<fit::closure> SecureSimplePairingState::CompletePairingRequests(
818 hci::Result<> status) {
819 std::vector<fit::closure> callbacks_to_signal;
820
821 if (!is_pairing()) {
822 PW_CHECK(request_queue_.empty());
823 return callbacks_to_signal;
824 }
825
826 if (status.is_error()) {
827 // On pairing failure, signal all requests.
828 for (auto& request : request_queue_) {
829 callbacks_to_signal.push_back(
830 [handle = handle(),
831 status,
832 cb = std::move(request.status_callback)]() { cb(handle, status); });
833 }
834 request_queue_.clear();
835 current_pairing_ = nullptr;
836 return callbacks_to_signal;
837 }
838
839 PW_CHECK(state_ == State::kIdle);
840 PW_CHECK(link_->ltk_type().has_value());
841
842 auto security_properties = sm::SecurityProperties(link_->ltk_type().value());
843
844 // If a new link key was received, notify all callbacks because we always
845 // negotiate the best security possible. Even though pairing succeeded, send
846 // an error status if the individual request security requirements are not
847 // satisfied.
848 // TODO(fxbug.dev/42075714): Only notify failure to callbacks of requests that
849 // inclusive-language: ignore
850 // have the same (or none) MITM requirements as the current pairing.
851 bool link_key_received = current_pairing_->security_properties.has_value();
852 if (link_key_received) {
853 for (auto& request : request_queue_) {
854 auto sec_props_satisfied = SecurityPropertiesMeetRequirements(
855 security_properties, request.security_requirements);
856 auto request_status = sec_props_satisfied
857 ? status
858 : ToResult(HostError::kInsufficientSecurity);
859
860 callbacks_to_signal.push_back(
861 [handle = handle(),
862 request_status,
863 cb = std::move(request.status_callback)]() {
864 cb(handle, request_status);
865 });
866 }
867 request_queue_.clear();
868 } else {
869 // If no new link key was received, then only authentication with an old key
870 // was performed (Simple Pairing was not required), and unsatisfied requests
871 // should initiate a new pairing rather than failing. If any pairing
872 // requests are satisfied by the existing key, notify them.
873 auto it = request_queue_.begin();
874 while (it != request_queue_.end()) {
875 if (!SecurityPropertiesMeetRequirements(security_properties,
876 it->security_requirements)) {
877 it++;
878 continue;
879 }
880
881 callbacks_to_signal.push_back(
882 [handle = handle(), status, cb = std::move(it->status_callback)]() {
883 cb(handle, status);
884 });
885 it = request_queue_.erase(it);
886 }
887 }
888 current_pairing_ = nullptr;
889 InitiateNextPairingRequest();
890
891 return callbacks_to_signal;
892 }
893
EnableEncryption()894 void SecureSimplePairingState::EnableEncryption() {
895 if (!link_->StartEncryption()) {
896 bt_log(ERROR,
897 "gap-bredr",
898 "%#.4x (id: %s): Failed to enable encryption (state \"%s\")",
899 handle(),
900 bt_str(peer_id()),
901 ToString(state()));
902 status_callback_(link_->handle(), ToResult(HostError::kFailed));
903 state_ = State::kFailed;
904 return;
905 }
906 state_ = State::kWaitEncryption;
907 }
908
FailWithUnexpectedEvent(const char * handler_name)909 void SecureSimplePairingState::FailWithUnexpectedEvent(
910 const char* handler_name) {
911 bt_log(ERROR,
912 "gap-bredr",
913 "%#.4x (id: %s): Unexpected event %s while in state \"%s\"",
914 handle(),
915 bt_str(peer_id()),
916 handler_name,
917 ToString(state()));
918 state_ = State::kFailed;
919 SignalStatus(ToResult(HostError::kNotSupported), __func__);
920 }
921
IsPeerSecureConnectionsSupported() const922 bool SecureSimplePairingState::IsPeerSecureConnectionsSupported() const {
923 return peer_->features().HasBit(
924 /*page=*/1, hci_spec::LMPFeature::kSecureConnectionsHostSupport) &&
925 peer_->features().HasBit(
926 /*page=*/2,
927 hci_spec::LMPFeature::kSecureConnectionsControllerSupport);
928 }
929
AttachInspect(inspect::Node & parent,std::string name)930 void SecureSimplePairingState::AttachInspect(inspect::Node& parent,
931 std::string name) {
932 inspect_node_ = parent.CreateChild(name);
933
934 inspect_properties_.encryption_status = inspect_node_.CreateString(
935 kInspectEncryptionStatusPropertyName,
936 EncryptionStatusToString(link_->encryption_status()));
937
938 security_properties().AttachInspect(inspect_node_,
939 kInspectSecurityPropertiesPropertyName);
940 }
941
GetInitiatorPairingAction(IoCapability initiator_cap,IoCapability responder_cap)942 PairingAction GetInitiatorPairingAction(IoCapability initiator_cap,
943 IoCapability responder_cap) {
944 if (initiator_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
945 return PairingAction::kAutomatic;
946 }
947 if (responder_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
948 if (initiator_cap == IoCapability::DISPLAY_YES_NO) {
949 return PairingAction::kGetConsent;
950 }
951 return PairingAction::kAutomatic;
952 }
953 if (initiator_cap == IoCapability::KEYBOARD_ONLY) {
954 return PairingAction::kRequestPasskey;
955 }
956 if (responder_cap == IoCapability::DISPLAY_ONLY) {
957 if (initiator_cap == IoCapability::DISPLAY_YES_NO) {
958 return PairingAction::kComparePasskey;
959 }
960 return PairingAction::kAutomatic;
961 }
962 return PairingAction::kDisplayPasskey;
963 }
964
GetResponderPairingAction(IoCapability initiator_cap,IoCapability responder_cap)965 PairingAction GetResponderPairingAction(IoCapability initiator_cap,
966 IoCapability responder_cap) {
967 if (initiator_cap == IoCapability::NO_INPUT_NO_OUTPUT &&
968 responder_cap == IoCapability::KEYBOARD_ONLY) {
969 return PairingAction::kGetConsent;
970 }
971 if (initiator_cap == IoCapability::DISPLAY_YES_NO &&
972 responder_cap == IoCapability::DISPLAY_YES_NO) {
973 return PairingAction::kComparePasskey;
974 }
975 return GetInitiatorPairingAction(responder_cap, initiator_cap);
976 }
977
GetExpectedEvent(IoCapability local_cap,IoCapability peer_cap)978 hci_spec::EventCode GetExpectedEvent(IoCapability local_cap,
979 IoCapability peer_cap) {
980 if (local_cap == IoCapability::NO_INPUT_NO_OUTPUT ||
981 peer_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
982 return hci_spec::kUserConfirmationRequestEventCode;
983 }
984 if (local_cap == IoCapability::KEYBOARD_ONLY) {
985 return hci_spec::kUserPasskeyRequestEventCode;
986 }
987 if (peer_cap == IoCapability::KEYBOARD_ONLY) {
988 return hci_spec::kUserPasskeyNotificationEventCode;
989 }
990 return hci_spec::kUserConfirmationRequestEventCode;
991 }
992
IsPairingAuthenticated(IoCapability local_cap,IoCapability peer_cap)993 bool IsPairingAuthenticated(IoCapability local_cap, IoCapability peer_cap) {
994 if (local_cap == IoCapability::NO_INPUT_NO_OUTPUT ||
995 peer_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
996 return false;
997 }
998 if (local_cap == IoCapability::DISPLAY_YES_NO &&
999 peer_cap == IoCapability::DISPLAY_YES_NO) {
1000 return true;
1001 }
1002 if (local_cap == IoCapability::KEYBOARD_ONLY ||
1003 peer_cap == IoCapability::KEYBOARD_ONLY) {
1004 return true;
1005 }
1006 return false;
1007 }
1008
GetInitiatorAuthenticationRequirements(IoCapability local_cap)1009 AuthenticationRequirements GetInitiatorAuthenticationRequirements(
1010 IoCapability local_cap) {
1011 if (local_cap == IoCapability::NO_INPUT_NO_OUTPUT) {
1012 return AuthenticationRequirements::GENERAL_BONDING;
1013 }
1014 // inclusive-language: ignore
1015 return AuthenticationRequirements::MITM_GENERAL_BONDING;
1016 }
1017
GetResponderAuthenticationRequirements(IoCapability local_cap,IoCapability peer_cap)1018 AuthenticationRequirements GetResponderAuthenticationRequirements(
1019 IoCapability local_cap, IoCapability peer_cap) {
1020 if (IsPairingAuthenticated(local_cap, peer_cap)) {
1021 // inclusive-language: ignore
1022 return AuthenticationRequirements::MITM_GENERAL_BONDING;
1023 }
1024 return AuthenticationRequirements::GENERAL_BONDING;
1025 }
1026
1027 } // namespace bt::gap
1028