| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PHASE_1_H_ |
| #define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PHASE_1_H_ |
| |
| #include <lib/async/cpp/task.h> |
| #include <lib/fit/function.h> |
| |
| #include "src/connectivity/bluetooth/core/bt-host/hci/connection.h" |
| #include "src/connectivity/bluetooth/core/bt-host/l2cap/channel.h" |
| #include "src/connectivity/bluetooth/core/bt-host/sm/active_phase.h" |
| #include "src/connectivity/bluetooth/core/bt-host/sm/smp.h" |
| #include "src/connectivity/bluetooth/core/bt-host/sm/types.h" |
| #include "src/connectivity/bluetooth/core/bt-host/sm/util.h" |
| #include "src/lib/fxl/memory/weak_ptr.h" |
| |
| namespace bt { |
| namespace sm { |
| // Responsible for Phase 1 of SMP pairing, the feature exchange. Takes in the current pairing state |
| // and notifies a constructor-provided callback with the negotiated features upon completion. |
| // |
| // This class is not thread safe and is meant to be accessed on the thread it was created on. All |
| // callbacks will be run by the default dispatcher of a Phase1's creation thread. |
| class Phase1 final : public ActivePhase, public PairingChannelHandler { |
| public: |
| // Called when Phase 1 completes successfully. |features| are the negotiated features. |preq| and |
| // |pres| are the SMP "Pairing Request" and "Pairing Response" payloads exchanged by the devices, |
| // which are returned for use in Phase 2 crypto calculations. |
| using CompleteCallback = fit::function<void(const PairingFeatures& features, |
| const ByteBuffer& preq, const ByteBuffer& pres)>; |
| |
| // Returns a Phase 1 in the initiator/master role. Note the lack of a `preq` parameter: Phase 1 |
| // builds & sends the Pairing Request as initiator. See private ctor for parameter descriptions. |
| static std::unique_ptr<Phase1> CreatePhase1Initiator(fxl::WeakPtr<PairingChannel> chan, |
| fxl::WeakPtr<Listener> listener, |
| IOCapability io_capability, |
| BondableMode bondable_mode, |
| bool mitm_required, |
| CompleteCallback on_complete); |
| |
| // Returns a Phase 1 in the responder/slave role. Note the `preq` parameter: Phase 1 is supplied |
| // the Pairing Request from the remote as responder. See private ctor for parameter descriptions. |
| static std::unique_ptr<Phase1> CreatePhase1Responder( |
| fxl::WeakPtr<PairingChannel> chan, fxl::WeakPtr<Listener> listener, PairingRequestParams preq, |
| IOCapability io_capability, BondableMode bondable_mode, bool mitm_required, |
| CompleteCallback on_complete); |
| |
| ~Phase1() override = default; |
| |
| // Runs the Phase 1 state machine, performing the feature exchange. |
| void Start() final; |
| |
| private: |
| // |chan|, |listener|, and |role|: used to construct the base ActivePhase |
| // |preq|: If empty, the device is in the master role and initiates the pairing. |
| // If present, the device is in the slave role, and will respond to |preq|, the peer |
| // master's pairing request. |
| // |bondable_mode|: the bondable mode of the local device (see V5.1 Vol. 3 Part C Section 9.4). |
| // |on_complete|: called at the end of Phase 1 with the resulting features. |
| Phase1(fxl::WeakPtr<PairingChannel> chan, fxl::WeakPtr<Listener> listener, |
| hci::Connection::Role role, std::optional<PairingRequestParams> preq, |
| IOCapability io_capability, BondableMode bondable_mode, bool mitm_required, |
| CompleteCallback on_complete); |
| |
| // Start the feature exchange with the local device acting as initiator (V5.1 Vol 3, Part H, |
| // 2.3). If the procedure cannot be performed the pairing is aborted. Must be in master HCI role. |
| void InitiateFeatureExchange(); |
| |
| // Handle the feature exchange with the local device as responder. Must be in slave HCI role. |
| void RespondToPairingRequest(const PairingRequestParams& req_params); |
| |
| // The returned `LocalPairingParams` structure contains the locally-preferred pairing parameters. |
| // The caller is responsible for making any adjustments necessary (e.g. due to peer preferences) |
| // before converting the `LocalPairingParams` to SMP PairingResponse/PairingRequest PDUs. |
| LocalPairingParams BuildPairingParameters(); |
| |
| // Called to complete a feature exchange. Returns the resulting PairingFeatures if the parameters |
| // should be accepted, or an error code if the parameters are rejected and pairing should abort. |
| fit::result<PairingFeatures, ErrorCode> ResolveFeatures(bool local_initiator, |
| const PairingRequestParams& preq, |
| const PairingResponseParams& pres); |
| |
| // Called for SMP commands sent by the peer. |
| void OnPairingResponse(const PairingResponseParams& response_params); |
| |
| // PairingChannelHandler callbacks: |
| void OnRxBFrame(ByteBufferPtr sdu) final; |
| void OnChannelClosed() final { ActivePhase::HandleChannelClosed(); } |
| |
| // PairingPhase override |
| fxl::WeakPtr<PairingChannelHandler> AsChannelHandler() final { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| // Only passed in when acting in the responder role. |
| std::optional<PairingRequestParams> peer_request_params_; |
| // Local feature flags that determine the feature exchange negotiation with the peer. |
| bool oob_available_; |
| bool mitm_required_; |
| bool feature_exchange_pending_; |
| IOCapability io_capability_; |
| BondableMode bondable_mode_; |
| |
| // This buffer stores pairing request & response PDUs for later crypto operations, i.e. the |
| // "preq" and "pres" payloads needed for Phase 2 (see V5.1 Vol 3, Part H, 2.2.3 for specifics). |
| StaticByteBuffer<util::PacketSize<PairingRequestParams>()> pairing_payload_buffer_; |
| |
| CompleteCallback on_complete_; |
| |
| fxl::WeakPtrFactory<Phase1> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Phase1); |
| }; |
| |
| } // namespace sm |
| } // namespace bt |
| |
| #endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PHASE_1_H_ |