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 #include <unordered_map> 18 19 #include "pw_bluetooth_sapphire/internal/host/common/uint128.h" 20 #include "pw_bluetooth_sapphire/internal/host/gap/gap.h" 21 #include "pw_bluetooth_sapphire/internal/host/hci-spec/link_key.h" 22 #include "pw_bluetooth_sapphire/internal/host/hci/connection.h" 23 #include "pw_bluetooth_sapphire/internal/host/hci/low_energy_connection.h" 24 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel.h" 25 #include "pw_bluetooth_sapphire/internal/host/sm/delegate.h" 26 #include "pw_bluetooth_sapphire/internal/host/sm/error.h" 27 #include "pw_bluetooth_sapphire/internal/host/sm/security_manager.h" 28 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h" 29 #include "pw_bluetooth_sapphire/internal/host/sm/types.h" 30 31 namespace bt::sm::testing { 32 33 // TestSecurityManager implements the public interface of the SM library. The 34 // intended use is in unit tests of code directly dependent on SM (currently, 35 // GAP). The implementation is currently limited to a basic test spy, with 36 // stubbed out responses and request tracking for a few functions and empty 37 // implementations for others. 38 class TestSecurityManager final : public SecurityManager { 39 public: 40 ~TestSecurityManager() override = default; 41 42 // SecurityManager overrides: 43 void UpgradeSecurity(SecurityLevel level, PairingCallback callback) override; 44 void InitiateBrEdrCrossTransportKeyDerivation( 45 CrossTransportKeyDerivationResultCallback) override; 46 void Reset(IOCapability io_capability) override; 47 void Abort(ErrorCode ecode) override; 48 49 // Returns the most recent security upgrade request received by this SM, if 50 // one has been made. last_requested_upgrade()51 std::optional<SecurityLevel> last_requested_upgrade() const { 52 return last_requested_upgrade_; 53 } 54 last_identity_info()55 std::optional<sm::IdentityInfo> last_identity_info() const { 56 return last_identity_info_; 57 } 58 59 // Set pairing data to return to InitiateBrEdrCrossTransportKeyDerivation(). 60 // If not set, CTKD will fail. set_pairing_data(std::optional<sm::PairingData> data)61 void set_pairing_data(std::optional<sm::PairingData> data) { 62 pairing_data_ = std::move(data); 63 } 64 65 void TriggerPairingComplete(sm::PairingData data); 66 67 using WeakPtr = WeakSelf<TestSecurityManager>::WeakPtr; GetWeakPtr()68 WeakPtr GetWeakPtr() { return weak_self_.GetWeakPtr(); } 69 70 private: 71 friend class TestSecurityManagerFactory; 72 TestSecurityManager(hci::LowEnergyConnection::WeakPtr link, 73 hci::BrEdrConnection::WeakPtr bredr_link, 74 l2cap::Channel::WeakPtr smp, 75 IOCapability io_capability, 76 Delegate::WeakPtr delegate, 77 BondableMode bondable_mode, 78 gap::LESecurityMode security_mode, 79 gap::Peer::WeakPtr peer); 80 Role role_; 81 std::optional<LTK> current_ltk_; 82 std::optional<SecurityLevel> last_requested_upgrade_; 83 Delegate::WeakPtr delegate_; 84 std::optional<sm::IdentityInfo> last_identity_info_; 85 std::optional<sm::PairingData> pairing_data_; 86 gap::Peer::WeakPtr peer_; 87 WeakSelf<TestSecurityManager> weak_self_; 88 }; 89 90 // TestSecurityManagerFactory provides a public factory method to create 91 // TestSecurityManagers for dependency injection. It stores these TestSMs so 92 // test code can access them to set and verify expectations. A separate storage 93 // object is needed because SecurityManagers cannot be directly injected, e.g. 94 // during construction, as they are created on demand upon connection creation. 95 // Storing the TestSMs in a factory object is preferable to a static member of 96 // TestSM itself so that each test is sandboxed from TestSMs in other tests. 97 // This is done by tying the lifetime of the factory to the test. 98 class TestSecurityManagerFactory { 99 public: 100 TestSecurityManagerFactory() = default; 101 // Code which uses TestSecurityManagers should create these objects through 102 // `CreateSm`. |link|: The LE logical link over which pairing procedures 103 // occur. |smp|: The L2CAP LE SMP fixed channel that operates over |link|. 104 // |io_capability|: The initial I/O capability. 105 // |delegate|: Delegate which handles SMP interactions with the rest of the 106 // Bluetooth stack. |bondable_mode|: the operating bondable mode of the device 107 // (see v5.2, Vol. 3, Part C 9.4). |security_mode|: the security mode this 108 // SecurityManager is in (see v5.2, Vol. 3, Part C 10.2). 109 std::unique_ptr<SecurityManager> CreateSm( 110 hci::LowEnergyConnection::WeakPtr link, 111 l2cap::Channel::WeakPtr smp, 112 IOCapability io_capability, 113 Delegate::WeakPtr delegate, 114 BondableMode bondable_mode, 115 gap::LESecurityMode security_mode, 116 pw::async::Dispatcher& dispatcher, 117 gap::Peer::WeakPtr peer); 118 119 std::unique_ptr<SecurityManager> CreateBrEdr( 120 hci::BrEdrConnection::WeakPtr link, 121 l2cap::Channel::WeakPtr smp, 122 Delegate::WeakPtr delegate, 123 bool is_controller_remote_public_key_validation_supported, 124 pw::async::Dispatcher& dispatcher, 125 bt::gap::Peer::WeakPtr peer); 126 127 // Obtain a reference to the TestSecurityManager associated with 128 // |conn_handle|'s connection for use in test code. 129 testing::TestSecurityManager::WeakPtr GetTestSm( 130 hci_spec::ConnectionHandle conn_handle); 131 132 private: 133 std::unordered_map<hci_spec::ConnectionHandle, 134 testing::TestSecurityManager::WeakPtr> 135 test_sms_; 136 }; 137 138 } // namespace bt::sm::testing 139