blob: f4478dda7ef35303596ed604e06ec6ab29bf62cd [file] [log] [blame]
// 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_PAIRING_PHASE_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PAIRING_PHASE_H_
#include <lib/fit/function.h>
#include <lib/fit/result.h>
#include <zircon/assert.h>
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/packet.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/pairing_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/status.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/types.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bt {
namespace sm {
// Abstract class representing one of the SMP pairing phases as outlined in V5.1 Vol. 3 Part H
// section 2.1. A generic pairing phase operates over the fixed SMP L2CAP channel and directly
// implements a small subset of functionality relevant to all phases of pairing.
//
// 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
// PairingPhase's creation thread.
using PairingChannelHandler = PairingChannel::Handler;
class PairingPhase {
public:
// Interface for notifying the owner of the phase object.
class Listener {
public:
virtual ~Listener() = default;
// Polls for the local identity information, which must be handled by another component of the
// Bluetooth stack. Returns std::nullopt if no local identity info is available.
virtual std::optional<IdentityInfo> OnIdentityRequest() = 0;
using ConfirmCallback = fit::function<void(bool confirm)>;
virtual void ConfirmPairing(ConfirmCallback confirm) = 0;
// Show the user the 6-digit |passkey| that should be compared to the peer's passkey or entered
// into the peer. |confirm| may be called to accept a comparison or to reject the pairing.
virtual void DisplayPasskey(uint32_t passkey, bool is_numeric_comparison,
ConfirmCallback confirm) = 0;
// Ask the user to enter a 6-digit passkey or reject pairing. Reports the result by invoking
// |respond| with |passkey| - a negative value of |passkey| indicates entry failed.
// TODO(49966): Use an optional to convey success/failure instead of the signedness of passkey.
using PasskeyResponseCallback = fit::function<void(int64_t passkey)>;
virtual void RequestPasskey(PasskeyResponseCallback respond) = 0;
// Called when a new LTK is available from legacy pairing phase 3.
virtual void OnNewLongTermKey(const LTK& ltk) = 0;
// Called when an on-going pairing procedure terminates with an error. This method should
// destroy the Phase that calls it. |status| will never indicate success.
virtual void OnPairingFailed(Status status) = 0;
};
virtual ~PairingPhase() = default;
// Returns the connection role.
hci::Connection::Role role() const { return role_; }
protected:
// Protected constructor as PairingPhases should not be created directly. Initializes this
// PairingPhase with the following parameters:
// - |chan|: The L2CAP SMP fixed channel.
// - |listener|: The class that will handle higher-level requests from the current phase.
// - |role|: The local connection role.
PairingPhase(fxl::WeakPtr<PairingChannel> chan, fxl::WeakPtr<Listener> listener,
hci::Connection::Role role);
// Concrete classes of PairingPhase must be PairingChannelHandlers and set the channel's handler
// to a weak pointer to themselves. This abstract method forces concrete PairingPhases to vend
// weak pointers to help enforce this.
virtual fxl::WeakPtr<PairingChannelHandler> AsChannelHandler() = 0;
// Sends a Pairing Failed command to the peer with `ecode` as the associated reason.
void SendPairingFailed(ErrorCode ecode);
PairingChannel& sm_chan() const {
ZX_ASSERT(chan_);
return *chan_;
}
bool is_initiator() const { return role_ == hci::Connection::Role::kMaster; }
bool is_responder() const { return role_ == hci::Connection::Role::kSlave; }
fxl::WeakPtr<Listener> listener() { return listener_; }
private:
fxl::WeakPtr<PairingChannel> chan_;
fxl::WeakPtr<Listener> listener_;
hci::Connection::Role role_;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(PairingPhase);
};
} // namespace sm
} // namespace bt
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PAIRING_PHASE_H_