• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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