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 #include "pw_bluetooth_sapphire/internal/host/sm/test_security_manager.h"
15
16 #include <pw_assert/check.h>
17
18 #include <memory>
19
20 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
21 #include "pw_bluetooth_sapphire/internal/host/hci/connection.h"
22 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
23
24 namespace bt::sm::testing {
25
26 namespace {
RoleFromLinks(hci::LowEnergyConnection::WeakPtr link,hci::BrEdrConnection::WeakPtr bredr_link)27 Role RoleFromLinks(hci::LowEnergyConnection::WeakPtr link,
28 hci::BrEdrConnection::WeakPtr bredr_link) {
29 pw::bluetooth::emboss::ConnectionRole conn_role =
30 pw::bluetooth::emboss::ConnectionRole::CENTRAL;
31 if (link.is_alive()) {
32 conn_role = link->role();
33 }
34 if (bredr_link.is_alive()) {
35 conn_role = bredr_link->role();
36 }
37 return conn_role == pw::bluetooth::emboss::ConnectionRole::CENTRAL
38 ? Role::kInitiator
39 : Role::kResponder;
40 }
41 } // namespace
42
TestSecurityManager(hci::LowEnergyConnection::WeakPtr link,hci::BrEdrConnection::WeakPtr bredr_link,l2cap::Channel::WeakPtr,IOCapability,Delegate::WeakPtr delegate,BondableMode bondable_mode,gap::LESecurityMode security_mode,gap::Peer::WeakPtr peer)43 TestSecurityManager::TestSecurityManager(
44 hci::LowEnergyConnection::WeakPtr link,
45 hci::BrEdrConnection::WeakPtr bredr_link,
46 l2cap::Channel::WeakPtr,
47 IOCapability,
48 Delegate::WeakPtr delegate,
49 BondableMode bondable_mode,
50 gap::LESecurityMode security_mode,
51 gap::Peer::WeakPtr peer)
52 : SecurityManager(bondable_mode, security_mode),
53 role_(RoleFromLinks(link, bredr_link)),
54 delegate_(std::move(delegate)),
55 peer_(std::move(peer)),
56 weak_self_(this) {
57 if (link.is_alive()) {
58 if (peer_->le() && peer_->le()->bond_data()) {
59 current_ltk_ =
60 (link->role() == pw::bluetooth::emboss::ConnectionRole::CENTRAL)
61 ? peer_->le()->bond_data()->peer_ltk
62 : peer_->le()->bond_data()->local_ltk;
63 }
64 if (current_ltk_) {
65 if (role_ == Role::kInitiator) {
66 set_security(current_ltk_->security());
67 }
68 }
69 }
70 }
71
UpgradeSecurity(SecurityLevel level,PairingCallback callback)72 void TestSecurityManager::UpgradeSecurity(SecurityLevel level,
73 PairingCallback callback) {
74 last_requested_upgrade_ = level;
75 set_security(SecurityProperties(
76 level, kMaxEncryptionKeySize, /*secure_connections=*/true));
77 callback(fit::ok(), security());
78 }
79
InitiateBrEdrCrossTransportKeyDerivation(CrossTransportKeyDerivationResultCallback callback)80 void TestSecurityManager::InitiateBrEdrCrossTransportKeyDerivation(
81 CrossTransportKeyDerivationResultCallback callback) {
82 if (!pairing_data_) {
83 callback(ToResult(HostError::kFailed));
84 return;
85 }
86 last_identity_info_ = delegate_->OnIdentityInformationRequest();
87 delegate_->OnPairingComplete(fit::ok());
88 peer_->MutLe().StoreBond(pairing_data_.value());
89 callback(fit::ok());
90 }
91
TriggerPairingComplete(sm::PairingData data)92 void TestSecurityManager::TriggerPairingComplete(sm::PairingData data) {
93 last_identity_info_ = delegate_->OnIdentityInformationRequest();
94 delegate_->OnPairingComplete(fit::ok());
95 peer_->MutLe().StoreBond(data);
96 }
97
Reset(IOCapability)98 void TestSecurityManager::Reset(IOCapability) {}
Abort(ErrorCode)99 void TestSecurityManager::Abort(ErrorCode) {}
100
CreateSm(hci::LowEnergyConnection::WeakPtr link,l2cap::Channel::WeakPtr smp,IOCapability io_capability,Delegate::WeakPtr delegate,BondableMode bondable_mode,gap::LESecurityMode security_mode,pw::async::Dispatcher &,gap::Peer::WeakPtr peer)101 std::unique_ptr<SecurityManager> TestSecurityManagerFactory::CreateSm(
102 hci::LowEnergyConnection::WeakPtr link,
103 l2cap::Channel::WeakPtr smp,
104 IOCapability io_capability,
105 Delegate::WeakPtr delegate,
106 BondableMode bondable_mode,
107 gap::LESecurityMode security_mode,
108 pw::async::Dispatcher&,
109 gap::Peer::WeakPtr peer) {
110 hci_spec::ConnectionHandle conn = link->handle();
111 auto test_sm = std::unique_ptr<TestSecurityManager>(
112 new TestSecurityManager(std::move(link),
113 hci::BrEdrConnection::WeakPtr(),
114 std::move(smp),
115 io_capability,
116 std::move(delegate),
117 bondable_mode,
118 security_mode,
119 std::move(peer)));
120 test_sms_[conn] = test_sm->GetWeakPtr();
121 return test_sm;
122 }
123
CreateBrEdr(hci::BrEdrConnection::WeakPtr link,l2cap::Channel::WeakPtr smp,Delegate::WeakPtr delegate,bool,pw::async::Dispatcher &,bt::gap::Peer::WeakPtr peer)124 std::unique_ptr<SecurityManager> TestSecurityManagerFactory::CreateBrEdr(
125 hci::BrEdrConnection::WeakPtr link,
126 l2cap::Channel::WeakPtr smp,
127 Delegate::WeakPtr delegate,
128 bool /*is_controller_remote_public_key_validation_supported*/,
129 pw::async::Dispatcher&,
130 bt::gap::Peer::WeakPtr peer) {
131 PW_CHECK(smp.is_alive());
132 hci_spec::ConnectionHandle conn = link->handle();
133 auto test_sm = std::unique_ptr<TestSecurityManager>(
134 new TestSecurityManager(hci::LowEnergyConnection::WeakPtr(),
135 std::move(link),
136 std::move(smp),
137 IOCapability::kNoInputNoOutput,
138 std::move(delegate),
139 BondableMode::Bondable,
140 gap::LESecurityMode::SecureConnectionsOnly,
141 std::move(peer)));
142 test_sms_[conn] = test_sm->GetWeakPtr();
143 return test_sm;
144 }
145
GetTestSm(hci_spec::ConnectionHandle conn_handle)146 WeakSelf<TestSecurityManager>::WeakPtr TestSecurityManagerFactory::GetTestSm(
147 hci_spec::ConnectionHandle conn_handle) {
148 auto iter = test_sms_.find(conn_handle);
149 PW_CHECK(iter != test_sms_.end());
150 return iter->second;
151 }
152
153 } // namespace bt::sm::testing
154