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/gap/peer.h" 20 #include "pw_bluetooth_sapphire/internal/host/hci/bredr_connection.h" 21 #include "pw_bluetooth_sapphire/internal/host/hci/low_energy_connection.h" 22 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel.h" 23 #include "pw_bluetooth_sapphire/internal/host/sm/delegate.h" 24 #include "pw_bluetooth_sapphire/internal/host/sm/error.h" 25 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h" 26 #include "pw_bluetooth_sapphire/internal/host/sm/util.h" 27 28 namespace bt::sm { 29 30 // SecurityManager provides a per-peer interface to Security Manager Protocol 31 // functionality in v5.2 Vol. 3 Part H. The peer device must be a LE or 32 // BR/EDR/LE device. SecurityManager is an abstract class so that SM-dependent 33 // code can dependency-inject test doubles in unit tests. 34 // 35 // The production implementation of SecurityManager is the SecurityManagerImpl 36 // class, which implements the functionality detailed in README.md. Clients 37 // should obtain a production object through the SecurityManager::Create factory 38 // function. 39 // 40 // A SecurityManager test double can be obtained through 41 // `TestSecurityManager::Create`. 42 // 43 /// See README.md for more overview of this library. 44 class SecurityManager { 45 public: 46 // Factory function which returns a production LE SecurityManager instance: 47 // |link|: The LE logical link over which pairing procedures occur. 48 // |smp|: The L2CAP LE SMP fixed channel that operates over |link|. 49 // |io_capability|: The initial I/O capability. 50 // |delegate|: Delegate which handles SMP interactions with the rest of the 51 // Bluetooth stack. 52 // |bondable_mode|: the operating bondable mode of the device 53 // (see v5.2, Vol. 3, Part C 9.4). 54 // |security_mode|: the security mode of this SecurityManager (see v5.2, Vol. 55 // 3, Part C 10.2). 56 // |peer|: The peer that the SMP fixed channel corresponds to. 57 static std::unique_ptr<SecurityManager> CreateLE( 58 hci::LowEnergyConnection::WeakPtr link, 59 l2cap::Channel::WeakPtr smp, 60 IOCapability io_capability, 61 Delegate::WeakPtr delegate, 62 BondableMode bondable_mode, 63 gap::LESecurityMode security_mode, 64 pw::async::Dispatcher& dispatcher, 65 bt::gap::Peer::WeakPtr peer); 66 67 // Factory function that returns a production BR/EDR SecurityManager object. 68 // |link|: The BR/EDR link over which the SMP channel operates. 69 // |smp|: The L2CAP BR/EDR SMP fixed channel. 70 // |delegate|: Delegate which handles SMP interactions with the rest of the 71 // Bluetooth stack. 72 // |is_controller_remote_public_key_validation_supported|: Indicates 73 // controller support for remote public key validation. |peer|: The peer that 74 // the link and SMP channel correspond to. 75 static std::unique_ptr<SecurityManager> CreateBrEdr( 76 hci::BrEdrConnection::WeakPtr link, 77 l2cap::Channel::WeakPtr smp, 78 Delegate::WeakPtr delegate, 79 bool is_controller_remote_public_key_validation_supported, 80 pw::async::Dispatcher& dispatcher, 81 bt::gap::Peer::WeakPtr peer); 82 83 virtual ~SecurityManager() = default; 84 85 // Attempt to raise the security level of the connection to the desired 86 // |level| and notify the result in |callback|. 87 // 88 // If the desired security properties are already satisfied, this procedure 89 // will succeed immediately (|callback| will be run with the current security 90 // properties). 91 // 92 // If a pairing procedure has already been initiated (either by us or the 93 // peer), the request will be queued and |callback| will be notified when the 94 // procedure completes. If the resulting security level does not satisfy 95 // |level|, pairing will be re-initiated. Note that this means security 96 // requests of different |level|s may not complete in the order they are made. 97 // 98 // If no pairing is in progress then the local device will initiate pairing. 99 // 100 // If pairing fails |callback| will be called with a |status| that represents 101 // the error. 102 using PairingCallback = 103 fit::function<void(Result<> status, const SecurityProperties& sec_props)>; 104 virtual void UpgradeSecurity(SecurityLevel level, 105 PairingCallback callback) = 0; 106 107 // Attempt to perform the BR/EDR cross-transport key derivation procedure. 108 // |callback| will be called on completion or failure. On success, the LE LTK 109 // will be delivered to Delegate::OnNewPairingData() in 110 // PairingData::cross_transport_key. Only 1 CTKD procedure is allowed at a 111 // time. Additional calls will return an error. Only the Central can initiate 112 // CTKD. 113 using CrossTransportKeyDerivationResultCallback = 114 fit::callback<void(Result<> result)>; 115 virtual void InitiateBrEdrCrossTransportKeyDerivation( 116 CrossTransportKeyDerivationResultCallback callback) = 0; 117 118 // Assign I/O capabilities. This aborts any ongoing pairing procedure and sets 119 // up the I/O capabilities to use for future requests. 120 virtual void Reset(IOCapability io_capability) = 0; 121 122 // Abort all ongoing pairing procedures and notify pairing callbacks with the 123 // provided error. Abort()124 void Abort() { Abort(ErrorCode::kUnspecifiedReason); } 125 virtual void Abort(ErrorCode ecode) = 0; 126 127 // Returns the current security properties of the LE link. security()128 const SecurityProperties& security() const { 129 return low_energy_security_properties_; 130 } 131 132 // Returns whether or not the SecurityManager is in bondable mode. Note that 133 // being in bondable mode does not guarantee that pairing will necessarily 134 // bond. bondable_mode()135 BondableMode bondable_mode() const { return low_energy_bondable_mode_; } 136 137 // Sets the bondable mode of the SecurityManager. Any in-progress pairings 138 // will not be affected - if bondable mode needs to be reset during a pairing 139 // Reset() or Abort() must be called first. set_bondable_mode(sm::BondableMode mode)140 void set_bondable_mode(sm::BondableMode mode) { 141 low_energy_bondable_mode_ = mode; 142 } 143 144 // Sets the LE Security mode of the SecurityManager - see enum definition for 145 // details of each mode. If a security upgrade is in-progress, only takes 146 // effect on the next security upgrade. set_security_mode(gap::LESecurityMode mode)147 void set_security_mode(gap::LESecurityMode mode) { 148 low_energy_security_mode_ = mode; 149 } security_mode()150 gap::LESecurityMode security_mode() { return low_energy_security_mode_; } 151 152 protected: 153 SecurityManager(BondableMode bondable_mode, 154 gap::LESecurityMode security_mode); set_security(SecurityProperties security)155 void set_security(SecurityProperties security) { 156 low_energy_security_properties_ = security; 157 } 158 159 private: 160 // The operating bondable mode of the device. 161 BondableMode low_energy_bondable_mode_ = BondableMode::Bondable; 162 163 // The current GAP security mode of the device (v5.2 Vol. 3 Part C 164 // Section 10.2) 165 gap::LESecurityMode low_energy_security_mode_ = gap::LESecurityMode::Mode1; 166 167 // Current security properties of the LE-U link. 168 SecurityProperties low_energy_security_properties_ = SecurityProperties(); 169 }; 170 171 using SecurityManagerFactory = 172 std::function<decltype(sm::SecurityManager::CreateLE)>; 173 174 using BrEdrSecurityManagerFactory = 175 std::function<decltype(sm::SecurityManager::CreateBrEdr)>; 176 177 } // namespace bt::sm 178