• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "pw_bluetooth_sapphire/internal/host/sm/pairing_channel.h"
16 
17 #include <memory>
18 
19 #include "lib/fit/function.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
21 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
22 #include "pw_bluetooth_sapphire/internal/host/hci/connection.h"
23 #include "pw_bluetooth_sapphire/internal/host/l2cap/mock_channel_test.h"
24 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
25 #include "pw_bluetooth_sapphire/internal/host/sm/util.h"
26 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
27 
28 namespace bt::sm {
29 namespace {
30 
31 class FakeChannelHandler : public PairingChannel::Handler {
32  public:
FakeChannelHandler()33   FakeChannelHandler() : weak_self_(this) {}
34 
OnRxBFrame(ByteBufferPtr data)35   void OnRxBFrame(ByteBufferPtr data) override {
36     last_rx_data_ = std::move(data);
37     frames_received_++;
38   }
39 
OnChannelClosed()40   void OnChannelClosed() override { channel_closed_count_++; }
41 
last_rx_data()42   ByteBuffer* last_rx_data() { return last_rx_data_.get(); }
43 
frames_received() const44   int frames_received() const { return frames_received_; }
channel_closed_count() const45   int channel_closed_count() const { return channel_closed_count_; }
as_weak_handler()46   PairingChannel::Handler::WeakPtr as_weak_handler() {
47     return weak_self_.GetWeakPtr();
48   }
49 
50  private:
51   ByteBufferPtr last_rx_data_ = nullptr;
52   int frames_received_ = 0;
53   int channel_closed_count_ = 0;
54   WeakSelf<PairingChannel::Handler> weak_self_;
55 };
56 
57 class PairingChannelTest : public l2cap::testing::MockChannelTest {
58  protected:
SetUp()59   void SetUp() override { NewPairingChannel(); }
60 
TearDown()61   void TearDown() override { sm_chan_ = nullptr; }
62 
NewPairingChannel(bt::LinkType ll_type=bt::LinkType::kLE,uint16_t mtu=kNoSecureConnectionsMtu)63   void NewPairingChannel(bt::LinkType ll_type = bt::LinkType::kLE,
64                          uint16_t mtu = kNoSecureConnectionsMtu) {
65     l2cap::ChannelId cid = ll_type == bt::LinkType::kLE ? l2cap::kLESMPChannelId
66                                                         : l2cap::kSMPChannelId;
67     ChannelOptions options(cid, mtu);
68     options.link_type = ll_type;
69     fake_sm_chan_ = CreateFakeChannel(options);
70     sm_chan_ = std::make_unique<PairingChannel>(
71         fake_sm_chan_->GetWeakPtr(),
72         fit::bind_member<&PairingChannelTest::ResetTimer>(this));
73   }
74 
sm_chan()75   PairingChannel* sm_chan() { return sm_chan_.get(); }
set_timer_resetter(fit::closure timer_resetter)76   void set_timer_resetter(fit::closure timer_resetter) {
77     timer_resetter_ = std::move(timer_resetter);
78   }
79 
80  private:
ResetTimer()81   void ResetTimer() { timer_resetter_(); }
82 
83   l2cap::testing::FakeChannel::WeakPtr fake_sm_chan_;
84   std::unique_ptr<PairingChannel> sm_chan_;
__anonc6c092f20202() 85   fit::closure timer_resetter_ = []() {};
86 };
87 
88 using PairingChannelDeathTest = PairingChannelTest;
TEST_F(PairingChannelDeathTest,L2capChannelMtuTooSmallDies)89 TEST_F(PairingChannelDeathTest, L2capChannelMtuTooSmallDies) {
90   ASSERT_DEATH_IF_SUPPORTED(
91       NewPairingChannel(bt::LinkType::kLE, kNoSecureConnectionsMtu - 1),
92       ".*max.*_sdu_size.*");
93 }
94 
TEST_F(PairingChannelDeathTest,SendInvalidMessageDies)95 TEST_F(PairingChannelDeathTest, SendInvalidMessageDies) {
96   // Tests that an invalid SMP code aborts the process
97   EXPECT_DEATH_IF_SUPPORTED(
98       sm_chan()->SendMessage(0xFF, ErrorCode::kUnspecifiedReason), ".*end.*");
99 
100   // Tests that a valid SMP code with a mismatched payload aborts the process
101   EXPECT_DEATH_IF_SUPPORTED(
102       sm_chan()->SendMessage(kPairingFailed, PairingRequestParams{}),
103       ".*sizeof.*");
104 }
105 
TEST_F(PairingChannelTest,SendMessageWorks)106 TEST_F(PairingChannelTest, SendMessageWorks) {
107   PairingRandomValue kExpectedPayload = {1, 2, 3, 4, 5};
108   StaticByteBuffer<util::PacketSize<PairingRandomValue>()> kExpectedPacket;
109   PacketWriter w(kPairingRandom, &kExpectedPacket);
110   *w.mutable_payload<PairingRandomValue>() = kExpectedPayload;
111   bool timer_reset = false;
112   set_timer_resetter([&]() { timer_reset = true; });
113   EXPECT_PACKET_OUT(kExpectedPacket);
114   sm_chan()->SendMessage(kPairingRandom, kExpectedPayload);
115   RunUntilIdle();
116   ASSERT_TRUE(timer_reset);
117 }
118 
119 // This checks that PairingChannel doesn't crash when receiving events without a
120 // handler set.
TEST_F(PairingChannelTest,NoHandlerSetDataDropped)121 TEST_F(PairingChannelTest, NoHandlerSetDataDropped) {
122   ASSERT_TRUE(sm_chan());
123   const StaticByteBuffer kSmPacket(kPairingFailed,
124                                    ErrorCode::kPairingNotSupported);
125 
126   fake_chan()->Receive(kSmPacket);
127   RunUntilIdle();
128 
129   fake_chan()->Close();
130   RunUntilIdle();
131 }
132 
TEST_F(PairingChannelTest,SetHandlerReceivesData)133 TEST_F(PairingChannelTest, SetHandlerReceivesData) {
134   ASSERT_TRUE(sm_chan());
135   const StaticByteBuffer kSmPacket1(kPairingFailed,
136                                     ErrorCode::kPairingNotSupported);
137   const StaticByteBuffer kSmPacket2(kPairingFailed,
138                                     ErrorCode::kConfirmValueFailed);
139   FakeChannelHandler handler;
140   sm_chan()->SetChannelHandler(handler.as_weak_handler());
141   ASSERT_EQ(handler.last_rx_data(), nullptr);
142   ASSERT_EQ(handler.frames_received(), 0);
143 
144   fake_chan()->Receive(kSmPacket1);
145   RunUntilIdle();
146   ASSERT_NE(handler.last_rx_data(), nullptr);
147   EXPECT_TRUE(ContainersEqual(*handler.last_rx_data(), kSmPacket1));
148   ASSERT_EQ(handler.frames_received(), 1);
149 
150   fake_chan()->Receive(kSmPacket2);
151   RunUntilIdle();
152   ASSERT_NE(handler.last_rx_data(), nullptr);
153   EXPECT_TRUE(ContainersEqual(*handler.last_rx_data(), kSmPacket2));
154   ASSERT_EQ(handler.frames_received(), 2);
155 
156   fake_chan()->Close();
157   RunUntilIdle();
158   ASSERT_EQ(handler.channel_closed_count(), 1);
159 }
160 
TEST_F(PairingChannelTest,ChangeHandlerNewHandlerReceivesData)161 TEST_F(PairingChannelTest, ChangeHandlerNewHandlerReceivesData) {
162   ASSERT_TRUE(sm_chan());
163   const StaticByteBuffer kSmPacket1(kPairingFailed,
164                                     ErrorCode::kPairingNotSupported);
165   const StaticByteBuffer kSmPacket2(kPairingFailed,
166                                     ErrorCode::kConfirmValueFailed);
167   FakeChannelHandler handler;
168   sm_chan()->SetChannelHandler(handler.as_weak_handler());
169   ASSERT_EQ(handler.last_rx_data(), nullptr);
170   ASSERT_EQ(handler.frames_received(), 0);
171 
172   fake_chan()->Receive(kSmPacket1);
173   RunUntilIdle();
174   ASSERT_NE(handler.last_rx_data(), nullptr);
175   EXPECT_TRUE(ContainersEqual(*handler.last_rx_data(), kSmPacket1));
176   ASSERT_EQ(handler.frames_received(), 1);
177 
178   FakeChannelHandler new_handler;
179   ASSERT_EQ(new_handler.last_rx_data(), nullptr);
180   sm_chan()->SetChannelHandler(new_handler.as_weak_handler());
181   fake_chan()->Receive(kSmPacket2);
182   RunUntilIdle();
183   ASSERT_NE(new_handler.last_rx_data(), nullptr);
184   EXPECT_TRUE(ContainersEqual(*new_handler.last_rx_data(), kSmPacket2));
185   ASSERT_EQ(new_handler.frames_received(), 1);
186   // Check handler's data hasn't changed.
187   EXPECT_TRUE(ContainersEqual(*handler.last_rx_data(), kSmPacket1));
188   ASSERT_EQ(handler.frames_received(), 1);
189 
190   fake_chan()->Close();
191   RunUntilIdle();
192   ASSERT_EQ(new_handler.channel_closed_count(), 1);
193   ASSERT_EQ(handler.channel_closed_count(), 0);
194 }
195 }  // namespace
196 }  // namespace bt::sm
197