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 #pragma once
16 #include <memory>
17 
18 #include "pw_bluetooth_sapphire/internal/host/gap/gap.h"
19 #include "pw_bluetooth_sapphire/internal/host/hci/low_energy_connection.h"
20 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel.h"
21 #include "pw_bluetooth_sapphire/internal/host/sm/delegate.h"
22 #include "pw_bluetooth_sapphire/internal/host/sm/error.h"
23 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
24 #include "pw_bluetooth_sapphire/internal/host/sm/types.h"
25 #include "pw_bluetooth_sapphire/internal/host/sm/util.h"
26 
27 namespace bt::sm {
28 
29 // SecurityManager provides a per-peer interface to Security Manager Protocol
30 // functionality in v5.2 Vol. 3 Part H. The peer device must be a LE or
31 // BR/EDR/LE device. SecurityManager is an abstract class so that SM-dependent
32 // code can dependency-inject test doubles in unit tests.
33 //
34 // The production implementation of SecurityManager is the SecurityManagerImpl
35 // class, which implements the functionality detailed in README.md. Clients
36 // should obtain a production object through the SecurityManager::Create factory
37 // function.
38 //
39 // A SecurityManager test double can be obtained through
40 // `TestSecurityManager::Create`.
41 //
42 /// See README.md for more overview of this library.
43 class SecurityManager {
44  public:
45   // Factory function which returns a production SecurityManager instance:
46   // |link|: The LE logical link over which pairing procedures occur.
47   // |smp|: The L2CAP LE SMP fixed channel that operates over |link|.
48   // |io_capability|: The initial I/O capability.
49   // |delegate|: Delegate which handles SMP interactions with the rest of the
50   // Bluetooth stack. |bondable_mode|: the operating bondable mode of the device
51   // (see v5.2, Vol. 3, Part C 9.4). |security_mode|: the security mode of this
52   // SecurityManager (see v5.2, Vol. 3, Part C 10.2).
53   static std::unique_ptr<SecurityManager> Create(
54       hci::LowEnergyConnection::WeakPtr link,
55       l2cap::Channel::WeakPtr smp,
56       IOCapability io_capability,
57       Delegate::WeakPtr delegate,
58       BondableMode bondable_mode,
59       gap::LESecurityMode security_mode,
60       pw::async::Dispatcher& dispatcher);
61   virtual ~SecurityManager() = default;
62   // Assigns the requested |ltk| to this connection, adopting the security
63   // properties of |ltk|. If the local device is the central of the underlying
64   // link, then the link layer authentication procedure will be initiated.
65   //
66   // Returns false if a pairing procedure is in progress when this method is
67   // called. If the link layer authentication procedure fails, then the link
68   // will be disconnected by the controller (Vol 2, Part E, 7.8.24;
69   // hci::Connection guarantees this by severing the link directly).
70   //
71   // This function is mainly intended to assign an existing LTK to a connection
72   // (e.g. from bonding data). This function overwrites any previously assigned
73   // LTK.
74   virtual bool AssignLongTermKey(const LTK& ltk) = 0;
75 
76   // TODO(fxbug.dev/42130294): Add function to register a BR/EDR link and SMP
77   // channel.
78 
79   // Attempt to raise the security level of the connection to the desired
80   // |level| and notify the result in |callback|.
81   //
82   // If the desired security properties are already satisfied, this procedure
83   // will succeed immediately (|callback| will be run with the current security
84   // properties).
85   //
86   // If a pairing procedure has already been initiated (either by us or the
87   // peer), the request will be queued and |callback| will be notified when the
88   // procedure completes. If the resulting security level does not satisfy
89   // |level|, pairing will be re-initiated. Note that this means security
90   // requests of different |level|s may not complete in the order they are made.
91   //
92   // If no pairing is in progress then the local device will initiate pairing.
93   //
94   // If pairing fails |callback| will be called with a |status| that represents
95   // the error.
96   using PairingCallback =
97       fit::function<void(Result<> status, const SecurityProperties& sec_props)>;
98   virtual void UpgradeSecurity(SecurityLevel level,
99                                PairingCallback callback) = 0;
100 
101   // Assign I/O capabilities. This aborts any ongoing pairing procedure and sets
102   // up the I/O capabilities to use for future requests.
103   virtual void Reset(IOCapability io_capability) = 0;
104 
105   // Abort all ongoing pairing procedures and notify pairing callbacks with the
106   // provided error.
Abort()107   void Abort() { Abort(ErrorCode::kUnspecifiedReason); }
108   virtual void Abort(ErrorCode ecode) = 0;
109 
110   // Returns the current security properties of the LE link.
security()111   const SecurityProperties& security() const { return le_sec_; }
112 
113   // Returns whether or not the SecurityManager is in bondable mode. Note that
114   // being in bondable mode does not guarantee that pairing will necessarily
115   // bond.
bondable_mode()116   BondableMode bondable_mode() const { return bondable_mode_; }
117 
118   // Sets the bondable mode of the SecurityManager. Any in-progress pairings
119   // will not be affected - if bondable mode needs to be reset during a pairing
120   // Reset() or Abort() must be called first.
set_bondable_mode(sm::BondableMode mode)121   void set_bondable_mode(sm::BondableMode mode) { bondable_mode_ = mode; }
122 
123   // Sets the LE Security mode of the SecurityManager - see enum definition for
124   // details of each mode. If a security upgrade is in-progress, only takes
125   // effect on the next security upgrade.
set_security_mode(gap::LESecurityMode mode)126   void set_security_mode(gap::LESecurityMode mode) { security_mode_ = mode; }
security_mode()127   gap::LESecurityMode security_mode() { return security_mode_; }
128 
129  protected:
130   SecurityManager(BondableMode bondable_mode,
131                   gap::LESecurityMode security_mode);
set_security(SecurityProperties security)132   void set_security(SecurityProperties security) { le_sec_ = security; }
133 
134  private:
135   // The operating bondable mode of the device.
136   BondableMode bondable_mode_ = BondableMode::Bondable;
137 
138   // The current GAP security mode of the device (v5.2 Vol. 3 Part C
139   // Section 10.2)
140   gap::LESecurityMode security_mode_ = gap::LESecurityMode::Mode1;
141 
142   // Current security properties of the LE-U link.
143   SecurityProperties le_sec_ = SecurityProperties();
144 };
145 
146 using SecurityManagerFactory =
147     std::function<decltype(sm::SecurityManager::Create)>;
148 
149 }  // namespace bt::sm
150