• 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/phase_2_secure_connections.h"
16 
17 #include <cstdint>
18 #include <memory>
19 
20 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/device_address.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/random.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/uint128.h"
24 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
25 #include "pw_bluetooth_sapphire/internal/host/hci/connection.h"
26 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_channel_test.h"
27 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
28 #include "pw_bluetooth_sapphire/internal/host/sm/ecdh_key.h"
29 #include "pw_bluetooth_sapphire/internal/host/sm/fake_phase_listener.h"
30 #include "pw_bluetooth_sapphire/internal/host/sm/packet.h"
31 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
32 #include "pw_bluetooth_sapphire/internal/host/sm/types.h"
33 #include "pw_bluetooth_sapphire/internal/host/sm/util.h"
34 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
35 #include "pw_unit_test/framework.h"
36 
37 namespace bt::sm {
38 namespace {
39 using ConfirmCallback = FakeListener::ConfirmCallback;
40 using PasskeyResponseCallback = FakeListener::PasskeyResponseCallback;
41 
42 const PairingFeatures kDefaultFeatures = {
43     .initiator = true,
44     .secure_connections = true,
45     .will_bond = true,
46     .generate_ct_key = std::optional<CrossTransportKeyAlgo>{std::nullopt},
47     .method = PairingMethod::kJustWorks,
48     .encryption_key_size = kMaxEncryptionKeySize,
49     .local_key_distribution = KeyDistGen::kIdKey,
50     .remote_key_distribution = KeyDistGen::kIdKey | KeyDistGen::kEncKey};
51 
52 const PairingRequestParams kDefaultPreq{
53     .io_capability = IOCapability::kNoInputNoOutput,
54     .oob_data_flag = OOBDataFlag::kNotPresent,
55     .auth_req = AuthReq::kSC | AuthReq::kBondingFlag,
56     .max_encryption_key_size = kMaxEncryptionKeySize,
57     .initiator_key_dist_gen = KeyDistGen::kIdKey,
58     .responder_key_dist_gen = KeyDistGen::kIdKey | KeyDistGen::kEncKey};
59 
60 const PairingResponseParams kDefaultPres{
61     .io_capability = IOCapability::kNoInputNoOutput,
62     .oob_data_flag = OOBDataFlag::kNotPresent,
63     .auth_req = AuthReq::kSC | AuthReq::kBondingFlag,
64     .max_encryption_key_size = kMaxEncryptionKeySize,
65     .initiator_key_dist_gen = KeyDistGen::kIdKey,
66     .responder_key_dist_gen = KeyDistGen::kIdKey | KeyDistGen::kEncKey};
67 
68 const DeviceAddress kAddr1(DeviceAddress::Type::kLEPublic,
69                            {0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
70 const DeviceAddress kAddr2(DeviceAddress::Type::kLEPublic,
71                            {0x00, 0x00, 0x00, 0x00, 0x00, 0x02});
72 const LocalEcdhKey kDefaultEcdhKey = LocalEcdhKey::Create().value();
73 
74 using util::PacketSize;
75 
76 class Phase2SecureConnectionsTest : public l2cap::testing::FakeChannelTest {
77  public:
78   Phase2SecureConnectionsTest() = default;
79   ~Phase2SecureConnectionsTest() override = default;
80 
81  protected:
SetUp()82   void SetUp() override { NewPhase2SecureConnections(); }
83 
TearDown()84   void TearDown() override { phase_2_sc_ = nullptr; }
85 
NewPhase2SecureConnections(Role local_role=Role::kInitiator,PairingMethod method=PairingMethod::kJustWorks,uint16_t mtu=kLeSecureConnectionsMtu)86   void NewPhase2SecureConnections(
87       Role local_role = Role::kInitiator,
88       PairingMethod method = PairingMethod::kJustWorks,
89       uint16_t mtu = kLeSecureConnectionsMtu) {
90     features_.initiator = (local_role == Role::kInitiator);
91     features_.method = method;
92     ChannelOptions options(l2cap::kLESMPChannelId, mtu);
93     options.link_type = bt::LinkType::kLE;
94     fake_sm_chan_ = CreateFakeChannel(options);
95     sm_chan_ = std::make_unique<PairingChannel>(fake_sm_chan_->GetWeakPtr());
96 
97     listener_ = std::make_unique<FakeListener>();
98     phase_2_sc_ =
99         std::make_unique<Phase2SecureConnections>(sm_chan_->GetWeakPtr(),
100                                                   listener_->as_weak_ptr(),
101                                                   local_role,
102                                                   features_,
103                                                   preq_,
104                                                   pres_,
105                                                   initiator_addr_,
106                                                   responder_addr_,
107                                                   [this](const UInt128& ltk) {
108                                                     phase_2_complete_count_++;
109                                                     ltk_ = ltk;
110                                                   });
111   }
112 
113   template <typename T>
ReceiveCmd(Code cmd_code,const T & value)114   void ReceiveCmd(Code cmd_code, const T& value) {
115     fake_chan()->Receive(MakeCmd(cmd_code, value));
116   }
117 
118   template <typename T>
MakeCmd(Code cmd_code,const T & value)119   StaticByteBuffer<PacketSize<T>()> MakeCmd(Code cmd_code, const T& value) {
120     StaticByteBuffer<PacketSize<T>()> buffer;
121     PacketWriter writer(cmd_code, &buffer);
122     *writer.mutable_payload<T>() = value;
123     return buffer;
124   }
125 
ExtractCodeAnd128BitCmd(ByteBufferPtr sdu)126   static std::pair<Code, UInt128> ExtractCodeAnd128BitCmd(ByteBufferPtr sdu) {
127     BT_ASSERT_MSG(sdu, "Tried to ExtractCodeAnd128BitCmd from nullptr in test");
128     auto maybe_reader = ValidPacketReader::ParseSdu(sdu);
129     BT_ASSERT_MSG(maybe_reader.is_ok(),
130                   "Tried to ExtractCodeAnd128BitCmd from invalid SMP packet");
131     return {maybe_reader.value().code(),
132             maybe_reader.value().payload<UInt128>()};
133   }
134 
FastForwardPublicKeyExchange()135   std::optional<PairingConfirmValue> FastForwardPublicKeyExchange() {
136     std::optional<PairingConfirmValue> responder_jw_nc_confirm = std::nullopt;
137     fake_chan()->SetSendCallback(
138         [&responder_jw_nc_confirm, this](ByteBufferPtr sdu) {
139           auto reader = ValidPacketReader::ParseSdu(sdu).value();
140           if (reader.code() == kPairingPublicKey) {
141             local_key_ = EcdhKey::ParseFromPublicKey(
142                 reader.payload<PairingPublicKeyParams>());
143           } else if (reader.code() == kPairingConfirm) {
144             // Confirm must come after ECDH Pub Key if it comes now
145             ASSERT_TRUE(local_key_.has_value());
146             responder_jw_nc_confirm = reader.payload<PairingConfirmValue>();
147           } else {
148             ADD_FAILURE() << "unexpected packet code " << reader.code();
149           }
150         },
151         dispatcher());
152 
153     if (phase_2_sc_->role() == Role::kInitiator) {
154       phase_2_sc_->Start();
155       RunUntilIdle();
156       BT_ASSERT_MSG(local_key_.has_value(),
157                     "initiator did not send ecdh key upon starting");
158       ReceiveCmd(kPairingPublicKey, peer_key_.GetSerializedPublicKey());
159       RunUntilIdle();
160     } else {
161       phase_2_sc_->Start();
162       ReceiveCmd(kPairingPublicKey, peer_key_.GetSerializedPublicKey());
163       RunUntilIdle();
164       BT_ASSERT_MSG(local_key_.has_value(),
165                     "responder did not send ecdh key upon peer key");
166       if (features_.method == PairingMethod::kJustWorks ||
167           features_.method == PairingMethod::kNumericComparison) {
168         BT_ASSERT(responder_jw_nc_confirm.has_value());
169         return responder_jw_nc_confirm;
170       }
171     }
172     // We should only send confirm value immediately after ECDH key as responder
173     // in Numeric Comparison/Just Works pairing, in which case we would've
174     // already returned.
175     BT_ASSERT(!responder_jw_nc_confirm.has_value());
176     return responder_jw_nc_confirm;
177   }
178 
GenerateConfirmValue(const UInt128 & random,bool gen_initiator_confirm,uint8_t r=0) const179   UInt128 GenerateConfirmValue(const UInt128& random,
180                                bool gen_initiator_confirm,
181                                uint8_t r = 0) const {
182     BT_ASSERT_MSG(local_key_.has_value(),
183                   "cannot compute confirm, missing key!");
184     UInt256 pka = local_key_->GetPublicKeyX(), pkb = peer_key_.GetPublicKeyX();
185     if (phase_2_sc_->role() == Role::kResponder) {
186       std::swap(pka, pkb);
187     }
188     return gen_initiator_confirm ? util::F4(pka, pkb, random, r).value()
189                                  : util::F4(pkb, pka, random, r).value();
190   }
191 
192   struct MatchingPair {
193     UInt128 confirm;
194     UInt128 random;
195   };
GenerateMatchingConfirmAndRandom(uint8_t r=0) const196   MatchingPair GenerateMatchingConfirmAndRandom(uint8_t r = 0) const {
197     MatchingPair pair{.confirm = {}, .random = {1, 2, 3, 4}};
198     pair.confirm = GenerateConfirmValue(
199         pair.random, phase_2_sc_->role() == Role::kResponder, r);
200     return pair;
201   }
202 
203   struct LtkAndChecks {
204     UInt128 ltk;
205     UInt128 dhkey_check_a;
206     UInt128 dhkey_check_b;
207   };
GenerateLtkAndChecks(const UInt128 & initiator_rand,const UInt128 & responder_rand,uint64_t r=0)208   LtkAndChecks GenerateLtkAndChecks(const UInt128& initiator_rand,
209                                     const UInt128& responder_rand,
210                                     uint64_t r = 0) {
211     LtkAndChecks vals;
212     util::F5Results f5 = *util::F5(peer_key_.CalculateDhKey(*local_key_),
213                                    initiator_rand,
214                                    responder_rand,
215                                    initiator_addr_,
216                                    responder_addr_);
217     vals.ltk = f5.ltk;
218 
219     UInt128 r_array{0};
220     // Copy little-endian uint64 r to the UInt128 array needed for Stage 2
221     std::memcpy(r_array.data(), &r, sizeof(uint64_t));
222     vals.dhkey_check_a = *util::F6(f5.mac_key,
223                                    initiator_rand,
224                                    responder_rand,
225                                    r_array,
226                                    preq_.auth_req,
227                                    preq_.oob_data_flag,
228                                    preq_.io_capability,
229                                    initiator_addr_,
230                                    responder_addr_);
231     vals.dhkey_check_b = *util::F6(f5.mac_key,
232                                    responder_rand,
233                                    initiator_rand,
234                                    r_array,
235                                    pres_.auth_req,
236                                    pres_.oob_data_flag,
237                                    pres_.io_capability,
238                                    responder_addr_,
239                                    initiator_addr_);
240     return vals;
241   }
242 
FastForwardToDhKeyCheck()243   LtkAndChecks FastForwardToDhKeyCheck() {
244     BT_ASSERT_MSG(
245         features_.method == PairingMethod::kJustWorks,
246         "Fast forward to DHKey check only implemented for JustWorks method");
247     return phase_2_sc_->role() == Role::kInitiator
248                ? FastForwardToDhKeyCheckInitiatorJustWorks()
249                : FastForwardToDhKeyCheckResponderJustWorks();
250   }
251 
DestroyPhase2()252   void DestroyPhase2() { phase_2_sc_.reset(nullptr); }
phase_2_sc()253   Phase2SecureConnections* phase_2_sc() { return phase_2_sc_.get(); }
listener()254   FakeListener* listener() { return listener_.get(); }
peer_key()255   const LocalEcdhKey& peer_key() { return peer_key_; }
local_key()256   const std::optional<EcdhKey>& local_key() { return local_key_; }
mut_local_key()257   std::optional<EcdhKey>& mut_local_key() { return local_key_; }
phase_2_complete_count() const258   int phase_2_complete_count() const { return phase_2_complete_count_; }
ltk() const259   UInt128 ltk() const { return ltk_; }
260 
261  private:
FastForwardToDhKeyCheckInitiatorJustWorks()262   LtkAndChecks FastForwardToDhKeyCheckInitiatorJustWorks() {
263     FastForwardPublicKeyExchange();
264     Code sent_code = kPairingFailed;
265     PairingRandomValue initiator_rand;
266     fake_chan()->SetSendCallback(
267         [&](ByteBufferPtr sdu) {
268           std::tie(sent_code, initiator_rand) =
269               ExtractCodeAnd128BitCmd(std::move(sdu));
270         },
271         dispatcher());
272     MatchingPair stage1_vals = GenerateMatchingConfirmAndRandom();
273     ReceiveCmd<PairingConfirmValue>(kPairingConfirm, stage1_vals.confirm);
274     RunUntilIdle();
275     BT_ASSERT_MSG(kPairingRandom == sent_code,
276                   "did not send pairing random when expected!");
277 
278     ReceiveCmd(kPairingRandom, stage1_vals.random);
279     RunUntilIdle();
280     return GenerateLtkAndChecks(initiator_rand, stage1_vals.random);
281   }
282 
FastForwardToDhKeyCheckResponderJustWorks()283   LtkAndChecks FastForwardToDhKeyCheckResponderJustWorks() {
284     UInt128 rsp_confirm = *FastForwardPublicKeyExchange();
285     Code sent_code = kPairingFailed;
286     UInt128 rsp_rand;
287     fake_chan()->SetSendCallback(
288         [&](ByteBufferPtr sdu) {
289           std::tie(sent_code, rsp_rand) =
290               ExtractCodeAnd128BitCmd(std::move(sdu));
291         },
292         dispatcher());
293     PairingRandomValue initiator_rand{1};
294     ReceiveCmd(kPairingRandom, initiator_rand);
295     RunUntilIdle();
296 
297     BT_ASSERT_MSG(kPairingRandom == sent_code,
298                   "did not send pairing random when expected!");
299     BT_ASSERT_MSG(GenerateConfirmValue(
300                       rsp_rand, /*gen_initiator_confirm=*/false) == rsp_confirm,
301                   "send invalid confirm value as JustWorks responder");
302     return GenerateLtkAndChecks(initiator_rand, rsp_rand);
303   }
304 
305   std::unique_ptr<FakeListener> listener_;
306   std::unique_ptr<l2cap::testing::FakeChannel> fake_sm_chan_;
307   std::unique_ptr<PairingChannel> sm_chan_;
308   std::unique_ptr<Phase2SecureConnections> phase_2_sc_;
309   // Key of the internal bt-host SMP stack
310   std::optional<EcdhKey> local_key_;
311   // Key of the unit test peer we're mocking
312   const LocalEcdhKey& peer_key_ = kDefaultEcdhKey;
313 
314   PairingFeatures features_ = kDefaultFeatures;
315   PairingRequestParams preq_ = kDefaultPreq;
316   PairingResponseParams pres_ = kDefaultPres;
317   DeviceAddress initiator_addr_ = kAddr1;
318   DeviceAddress responder_addr_ = kAddr2;
319   int phase_2_complete_count_ = 0;
320   UInt128 ltk_;
321 
322   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Phase2SecureConnectionsTest);
323 };
324 
325 using Phase2SecureConnectionsDeathTest = Phase2SecureConnectionsTest;
326 
TEST_F(Phase2SecureConnectionsDeathTest,MtuTooSmallDies)327 TEST_F(Phase2SecureConnectionsDeathTest, MtuTooSmallDies) {
328   ASSERT_DEATH_IF_SUPPORTED(
329       NewPhase2SecureConnections(
330           Role::kInitiator, PairingMethod::kJustWorks, kNoSecureConnectionsMtu),
331       ".*SecureConnections.*");
332 }
333 
TEST_F(Phase2SecureConnectionsTest,ReceivePairingFailed)334 TEST_F(Phase2SecureConnectionsTest, ReceivePairingFailed) {
335   phase_2_sc()->Start();
336   fake_chan()->Receive(StaticByteBuffer<PacketSize<ErrorCode>()>{
337       kPairingFailed, ErrorCode::kPairingNotSupported});
338   RunUntilIdle();
339 
340   EXPECT_EQ(Error(ErrorCode::kPairingNotSupported), listener()->last_error());
341 }
342 
TEST_F(Phase2SecureConnectionsTest,ReceiveMalformedPacket)343 TEST_F(Phase2SecureConnectionsTest, ReceiveMalformedPacket) {
344   phase_2_sc()->Start();
345   // PairingPublicKeyParams is expected to have both an X and Y value, not just
346   // an X.
347   const UInt256 kX = peer_key().GetPublicKeyX();
348   const auto kPairingPublicKeyCmd = MakeCmd(kPairingPublicKey, kX);
349   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
350       kPairingFailed, ErrorCode::kInvalidParameters};
351 
352   EXPECT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
353 }
354 
TEST_F(Phase2SecureConnectionsTest,ReceiveUnexpectedPacket)355 TEST_F(Phase2SecureConnectionsTest, ReceiveUnexpectedPacket) {
356   phase_2_sc()->Start();
357   // Pairing Responses should only be sent during Phase 1 of pairing.
358   const auto kPairingResponseCmd =
359       MakeCmd(kPairingResponse, PairingResponseParams());
360   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
361       kPairingFailed, ErrorCode::kUnspecifiedReason};
362 
363   EXPECT_TRUE(ReceiveAndExpect(kPairingResponseCmd, kExpectedFailure));
364 }
365 
TEST_F(Phase2SecureConnectionsTest,InitiatorPubKeyOutOfOrder)366 TEST_F(Phase2SecureConnectionsTest, InitiatorPubKeyOutOfOrder) {
367   NewPhase2SecureConnections(Role::kInitiator);
368 
369   const auto kPairingPublicKeyCmd =
370       MakeCmd(kPairingPublicKey, peer_key().GetSerializedPublicKey());
371   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
372       kPairingFailed, ErrorCode::kUnspecifiedReason};
373   ASSERT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
374   ASSERT_EQ(1, listener()->pairing_error_count());
375 }
376 
TEST_F(Phase2SecureConnectionsTest,RejectsPublicKeyOffCurve)377 TEST_F(Phase2SecureConnectionsTest, RejectsPublicKeyOffCurve) {
378   phase_2_sc()->Start();
379   const auto kPairingPublicKeyCmd = MakeCmd(
380       kPairingPublicKey, PairingPublicKeyParams{.x = {0x01}, .y = {0x02}});
381   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
382       kPairingFailed, ErrorCode::kInvalidParameters};
383   ASSERT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
384   ASSERT_EQ(1, listener()->pairing_error_count());
385 }
386 
TEST_F(Phase2SecureConnectionsTest,RejectsPublicKeyIdenticalToLocalKey)387 TEST_F(Phase2SecureConnectionsTest, RejectsPublicKeyIdenticalToLocalKey) {
388   // Read local key sent to peer
389   fake_chan()->SetSendCallback(
390       [this](ByteBufferPtr sdu) {
391         auto reader = ValidPacketReader::ParseSdu(sdu).value();
392         if (reader.code() == kPairingPublicKey) {
393           mut_local_key() = EcdhKey::ParseFromPublicKey(
394               reader.payload<PairingPublicKeyParams>());
395         }
396       },
397       dispatcher());
398 
399   phase_2_sc()->Start();
400   RunUntilIdle();
401   ASSERT_TRUE(local_key().has_value());
402 
403   // Mirror back local key as the peer's public key
404   const auto kPairingPublicKeyCmd =
405       MakeCmd(kPairingPublicKey, local_key()->GetSerializedPublicKey());
406   const StaticByteBuffer kExpectedFailure{kPairingFailed,
407                                           ErrorCode::kInvalidParameters};
408   EXPECT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
409   EXPECT_EQ(1, listener()->pairing_error_count());
410 }
411 
TEST_F(Phase2SecureConnectionsTest,ReceivePeerPublicKeyTwice)412 TEST_F(Phase2SecureConnectionsTest, ReceivePeerPublicKeyTwice) {
413   phase_2_sc()->Start();
414   const auto kPairingPublicKeyCmd =
415       MakeCmd(kPairingPublicKey, peer_key().GetSerializedPublicKey());
416   fake_chan()->Receive(kPairingPublicKeyCmd);
417   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
418       kPairingFailed, ErrorCode::kUnspecifiedReason};
419   ASSERT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
420   ASSERT_EQ(1, listener()->pairing_error_count());
421 }
422 
TEST_F(Phase2SecureConnectionsTest,ReceiveConfirmValueBeforeStage1Fails)423 TEST_F(Phase2SecureConnectionsTest, ReceiveConfirmValueBeforeStage1Fails) {
424   phase_2_sc()->Start();
425   const auto kPairingConfirmCmd =
426       MakeCmd(kPairingConfirm, PairingConfirmValue{1});
427   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
428       kPairingFailed, ErrorCode::kUnspecifiedReason};
429   ASSERT_TRUE(ReceiveAndExpect(kPairingConfirmCmd, kExpectedFailure));
430   ASSERT_EQ(1, listener()->pairing_error_count());
431 }
432 
TEST_F(Phase2SecureConnectionsTest,ReceiveRandomValueBeforeStage1Fails)433 TEST_F(Phase2SecureConnectionsTest, ReceiveRandomValueBeforeStage1Fails) {
434   phase_2_sc()->Start();
435   const auto kPairingRandomCmd = MakeCmd(kPairingRandom, PairingRandomValue{1});
436   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
437       kPairingFailed, ErrorCode::kUnspecifiedReason};
438   ASSERT_TRUE(ReceiveAndExpect(kPairingRandomCmd, kExpectedFailure));
439   ASSERT_EQ(1, listener()->pairing_error_count());
440 }
441 
TEST_F(Phase2SecureConnectionsTest,ReceiveDhKeyCheckValueBeforeStage1Fails)442 TEST_F(Phase2SecureConnectionsTest, ReceiveDhKeyCheckValueBeforeStage1Fails) {
443   phase_2_sc()->Start();
444   const auto kPairingDHKeyCheckCmd =
445       MakeCmd(kPairingDHKeyCheck, PairingDHKeyCheckValueE{1});
446   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
447       kPairingFailed, ErrorCode::kUnspecifiedReason};
448   ASSERT_TRUE(ReceiveAndExpect(kPairingDHKeyCheckCmd, kExpectedFailure));
449   ASSERT_EQ(1, listener()->pairing_error_count());
450 }
451 
TEST_F(Phase2SecureConnectionsTest,ReceiveConfirmValueAfterStage1Fails)452 TEST_F(Phase2SecureConnectionsTest, ReceiveConfirmValueAfterStage1Fails) {
453   FastForwardToDhKeyCheck();
454   const auto kPairingConfirmCmd =
455       MakeCmd(kPairingConfirm, PairingConfirmValue{1});
456   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
457       kPairingFailed, ErrorCode::kUnspecifiedReason};
458   ASSERT_TRUE(ReceiveAndExpect(kPairingConfirmCmd, kExpectedFailure));
459   ASSERT_EQ(1, listener()->pairing_error_count());
460 }
461 
TEST_F(Phase2SecureConnectionsTest,ReceiveRandomValueAfterStage1Fails)462 TEST_F(Phase2SecureConnectionsTest, ReceiveRandomValueAfterStage1Fails) {
463   FastForwardToDhKeyCheck();
464   const auto kPairingRandomCmd = MakeCmd(kPairingRandom, PairingRandomValue{1});
465   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
466       kPairingFailed, ErrorCode::kUnspecifiedReason};
467   ASSERT_TRUE(ReceiveAndExpect(kPairingRandomCmd, kExpectedFailure));
468   ASSERT_EQ(1, listener()->pairing_error_count());
469 }
470 
TEST_F(Phase2SecureConnectionsTest,InitiatorReceiveDhKeyCheckWhileWaitingForConfirmFails)471 TEST_F(Phase2SecureConnectionsTest,
472        InitiatorReceiveDhKeyCheckWhileWaitingForConfirmFails) {
473   NewPhase2SecureConnections(Role::kInitiator);
474   ConfirmCallback confirm_cb = nullptr;
475   listener()->set_confirm_delegate(
476       [&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
477   LtkAndChecks expected_stage2_vals = FastForwardToDhKeyCheck();
478   ASSERT_TRUE(confirm_cb);
479   // Receiving the peer DHKey check before user confirmation should fail as
480   // initiator.
481   const auto kPairingDHKeyCheckCmd =
482       MakeCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_b);
483   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
484       kPairingFailed, ErrorCode::kUnspecifiedReason};
485   ASSERT_TRUE(ReceiveAndExpect(kPairingDHKeyCheckCmd, kExpectedFailure));
486   ASSERT_EQ(1, listener()->pairing_error_count());
487 }
488 
TEST_F(Phase2SecureConnectionsTest,Stage1JustWorksErrorPropagates)489 TEST_F(Phase2SecureConnectionsTest, Stage1JustWorksErrorPropagates) {
490   NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kJustWorks);
491   ConfirmCallback confirm_cb = nullptr;
492   listener()->set_confirm_delegate(
493       [&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
494   FastForwardPublicKeyExchange();
495 
496   Code sent_code = kPairingFailed;
497   fake_chan()->SetSendCallback(
498       [&](ByteBufferPtr sdu) {
499         std::tie(sent_code, std::ignore) =
500             ExtractCodeAnd128BitCmd(std::move(sdu));
501       },
502       dispatcher());
503   MatchingPair stage1_vals = GenerateMatchingConfirmAndRandom();
504   ReceiveCmd<PairingConfirmValue>(kPairingConfirm, stage1_vals.confirm);
505   RunUntilIdle();
506   ASSERT_EQ(kPairingRandom, sent_code);
507   UInt128 mismatched_random = stage1_vals.random;
508   mismatched_random[0] += 1;
509   const auto kMismatchedPairingRandomCmd =
510       MakeCmd(kPairingRandom, mismatched_random);
511   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
512       kPairingFailed, ErrorCode::kConfirmValueFailed};
513   ASSERT_TRUE(ReceiveAndExpect(kMismatchedPairingRandomCmd, kExpectedFailure));
514   ASSERT_EQ(1, listener()->pairing_error_count());
515 }
516 
TEST_F(Phase2SecureConnectionsTest,Stage1PasskeyErrorPropagates)517 TEST_F(Phase2SecureConnectionsTest, Stage1PasskeyErrorPropagates) {
518   NewPhase2SecureConnections(Role::kInitiator,
519                              PairingMethod::kPasskeyEntryDisplay);
520   uint32_t passkey;
521   ConfirmCallback confirm_cb = nullptr;
522   listener()->set_display_delegate([&](uint32_t disp_passkey,
523                                        Delegate::DisplayMethod method,
524                                        ConfirmCallback cb) {
525     ASSERT_EQ(Delegate::DisplayMethod::kPeerEntry, method);
526     confirm_cb = std::move(cb);
527     passkey = disp_passkey;
528   });
529   FastForwardPublicKeyExchange();
530 
531   ASSERT_TRUE(confirm_cb);
532   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
533       kPairingFailed, ErrorCode::kPasskeyEntryFailed};
534   bool failure_sent = false;
535   fake_chan()->SetSendCallback(
536       [&](ByteBufferPtr sdu) {
537         ASSERT_TRUE(ContainersEqual(kExpectedFailure, *sdu));
538         failure_sent = true;
539       },
540       dispatcher());
541   confirm_cb(false);
542   RunUntilIdle();
543   ASSERT_EQ(1, listener()->pairing_error_count());
544   ASSERT_TRUE(failure_sent);
545 }
546 
TEST_F(Phase2SecureConnectionsTest,InitiatorReceiveWrongDhKeyCheckFails)547 TEST_F(Phase2SecureConnectionsTest, InitiatorReceiveWrongDhKeyCheckFails) {
548   NewPhase2SecureConnections(Role::kInitiator);
549   ConfirmCallback confirm_cb = nullptr;
550   listener()->set_confirm_delegate(
551       [&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
552   LtkAndChecks expected_stage2_vals = FastForwardToDhKeyCheck();
553   ASSERT_TRUE(confirm_cb);
554   Code sent_code = kPairingFailed;
555   UInt128 sent_payload;
556   fake_chan()->SetSendCallback(
557       [&](ByteBufferPtr sdu) {
558         std::tie(sent_code, sent_payload) =
559             ExtractCodeAnd128BitCmd(std::move(sdu));
560       },
561       dispatcher());
562   confirm_cb(true);
563   RunUntilIdle();
564   ASSERT_EQ(kPairingDHKeyCheck, sent_code);
565   // As initiator, we expect the dhkey_check_b value, not the a.
566   const auto kPairingDHKeyCheckCmd =
567       MakeCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_a);
568   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
569       kPairingFailed, ErrorCode::kDHKeyCheckFailed};
570   ASSERT_TRUE(ReceiveAndExpect(kPairingDHKeyCheckCmd, kExpectedFailure));
571   ASSERT_EQ(1, listener()->pairing_error_count());
572   ASSERT_EQ(0, phase_2_complete_count());
573 }
574 
TEST_F(Phase2SecureConnectionsTest,InitiatorFlowSuccessJustWorks)575 TEST_F(Phase2SecureConnectionsTest, InitiatorFlowSuccessJustWorks) {
576   NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kJustWorks);
577   ConfirmCallback confirm_cb = nullptr;
578   listener()->set_confirm_delegate(
579       [&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
580   FastForwardPublicKeyExchange();
581 
582   Code sent_code = kPairingFailed;
583   UInt128 sent_payload;
584   fake_chan()->SetSendCallback(
585       [&](ByteBufferPtr sdu) {
586         std::tie(sent_code, sent_payload) =
587             ExtractCodeAnd128BitCmd(std::move(sdu));
588       },
589       dispatcher());
590   MatchingPair stage1_vals = GenerateMatchingConfirmAndRandom();
591   ReceiveCmd<PairingConfirmValue>(kPairingConfirm, stage1_vals.confirm);
592   RunUntilIdle();
593   ASSERT_EQ(kPairingRandom, sent_code);
594   UInt128 local_rand = sent_payload;
595   ASSERT_FALSE(confirm_cb);
596   ReceiveCmd(kPairingRandom, stage1_vals.random);
597   RunUntilIdle();
598   ASSERT_TRUE(confirm_cb);
599 
600   LtkAndChecks expected_stage2_vals =
601       GenerateLtkAndChecks(local_rand, stage1_vals.random);
602   confirm_cb(true);
603   RunUntilIdle();
604   // After receiving user confirmation, we should send (the correct) DHKey Check
605   // Ea
606   ASSERT_EQ(kPairingDHKeyCheck, sent_code);
607   ASSERT_EQ(expected_stage2_vals.dhkey_check_a, sent_payload);
608   ReceiveCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_b);
609   RunUntilIdle();
610   ASSERT_EQ(1, phase_2_complete_count());
611   // We should generate the same LTK on "both sides"
612   ASSERT_EQ(expected_stage2_vals.ltk, ltk());
613 }
614 
TEST_F(Phase2SecureConnectionsTest,InitiatorFlowSuccessNumericComparison)615 TEST_F(Phase2SecureConnectionsTest, InitiatorFlowSuccessNumericComparison) {
616   NewPhase2SecureConnections(Role::kInitiator,
617                              PairingMethod::kNumericComparison);
618   ConfirmCallback confirm_cb = nullptr;
619   listener()->set_display_delegate(
620       [&](uint32_t, Delegate::DisplayMethod method, ConfirmCallback cb) {
621         ASSERT_EQ(Delegate::DisplayMethod::kComparison, method);
622         confirm_cb = std::move(cb);
623       });
624   FastForwardPublicKeyExchange();
625 
626   Code sent_code = kPairingFailed;
627   UInt128 sent_payload;
628   fake_chan()->SetSendCallback(
629       [&](ByteBufferPtr sdu) {
630         std::tie(sent_code, sent_payload) =
631             ExtractCodeAnd128BitCmd(std::move(sdu));
632       },
633       dispatcher());
634   MatchingPair stage1_vals = GenerateMatchingConfirmAndRandom();
635   ReceiveCmd(kPairingConfirm, stage1_vals.confirm);
636   RunUntilIdle();
637   EXPECT_EQ(kPairingRandom, sent_code);
638   UInt128 initiator_random = sent_payload;
639   ASSERT_FALSE(confirm_cb);
640 
641   ReceiveCmd(kPairingRandom, stage1_vals.random);
642   RunUntilIdle();
643   ASSERT_TRUE(confirm_cb);
644   confirm_cb(true);
645   RunUntilIdle();
646   LtkAndChecks vals =
647       GenerateLtkAndChecks(initiator_random, stage1_vals.random);
648   EXPECT_EQ(kPairingDHKeyCheck, sent_code);
649   EXPECT_EQ(vals.dhkey_check_a, sent_payload);
650   ReceiveCmd(kPairingDHKeyCheck, vals.dhkey_check_b);
651   RunUntilIdle();
652   ASSERT_EQ(vals.ltk, ltk());
653 }
654 
TEST_F(Phase2SecureConnectionsTest,InitiatorFlowSuccessPasskeyEntryDisplay)655 TEST_F(Phase2SecureConnectionsTest, InitiatorFlowSuccessPasskeyEntryDisplay) {
656   NewPhase2SecureConnections(Role::kInitiator,
657                              PairingMethod::kPasskeyEntryDisplay);
658   uint32_t passkey;
659   ConfirmCallback confirm_cb = nullptr;
660   listener()->set_display_delegate([&](uint32_t disp_passkey,
661                                        Delegate::DisplayMethod method,
662                                        ConfirmCallback cb) {
663     ASSERT_EQ(Delegate::DisplayMethod::kPeerEntry, method);
664     confirm_cb = std::move(cb);
665     passkey = disp_passkey;
666   });
667   FastForwardPublicKeyExchange();
668   ASSERT_TRUE(confirm_cb);
669   Code sent_code = kPairingFailed;
670   UInt128 sent_payload;
671   fake_chan()->SetSendCallback(
672       [&](ByteBufferPtr sdu) {
673         std::tie(sent_code, sent_payload) =
674             ExtractCodeAnd128BitCmd(std::move(sdu));
675       },
676       dispatcher());
677   confirm_cb(true);
678   MatchingPair stage1_vals;
679   UInt128 last_sent_rand;
680   for (size_t i = 0; i < 20; ++i) {
681     const uint8_t r = (passkey & (1 << i)) ? 0x81 : 0x80;
682     stage1_vals = GenerateMatchingConfirmAndRandom(r);
683     RunUntilIdle();
684 
685     ASSERT_EQ(kPairingConfirm, sent_code);
686     PairingConfirmValue init_confirm = sent_payload;
687     ReceiveCmd(kPairingConfirm, stage1_vals.confirm);
688     RunUntilIdle();
689 
690     ASSERT_EQ(kPairingRandom, sent_code);
691     last_sent_rand = sent_payload;
692     EXPECT_EQ(
693         GenerateConfirmValue(sent_payload, /*gen_initiator_confirm=*/true, r),
694         init_confirm);
695     ReceiveCmd(kPairingRandom, stage1_vals.random);
696   }
697   LtkAndChecks vals = GenerateLtkAndChecks(
698       last_sent_rand, stage1_vals.random, uint64_t{passkey});
699   RunUntilIdle();
700   EXPECT_EQ(kPairingDHKeyCheck, sent_code);
701   EXPECT_EQ(vals.dhkey_check_a, sent_payload);
702   ReceiveCmd(kPairingDHKeyCheck, vals.dhkey_check_b);
703   RunUntilIdle();
704   ASSERT_EQ(vals.ltk, ltk());
705 }
706 
TEST_F(Phase2SecureConnectionsTest,InitiatorFlowSuccessPasskeyEntryInput)707 TEST_F(Phase2SecureConnectionsTest, InitiatorFlowSuccessPasskeyEntryInput) {
708   NewPhase2SecureConnections(Role::kInitiator,
709                              PairingMethod::kPasskeyEntryInput);
710   PasskeyResponseCallback passkey_cb = nullptr;
711   listener()->set_request_passkey_delegate(
712       [&](PasskeyResponseCallback cb) { passkey_cb = std::move(cb); });
713   FastForwardPublicKeyExchange();
714   ASSERT_TRUE(passkey_cb);
715   Code sent_code = kPairingFailed;
716   UInt128 sent_payload;
717   fake_chan()->SetSendCallback(
718       [&](ByteBufferPtr sdu) {
719         std::tie(sent_code, sent_payload) =
720             ExtractCodeAnd128BitCmd(std::move(sdu));
721       },
722       dispatcher());
723   const int64_t passkey = 123456;
724   passkey_cb(passkey);
725   MatchingPair stage1_vals;
726   UInt128 last_sent_rand;
727   for (size_t i = 0; i < 20; ++i) {
728     const uint8_t r = (passkey & (1 << i)) ? 0x81 : 0x80;
729     stage1_vals = GenerateMatchingConfirmAndRandom(r);
730     RunUntilIdle();
731 
732     ASSERT_EQ(kPairingConfirm, sent_code);
733     PairingConfirmValue init_confirm = sent_payload;
734     ReceiveCmd(kPairingConfirm, stage1_vals.confirm);
735     RunUntilIdle();
736 
737     ASSERT_EQ(kPairingRandom, sent_code);
738     last_sent_rand = sent_payload;
739     EXPECT_EQ(
740         GenerateConfirmValue(sent_payload, /*gen_initiator_confirm=*/true, r),
741         init_confirm);
742     ReceiveCmd(kPairingRandom, stage1_vals.random);
743   }
744   LtkAndChecks vals = GenerateLtkAndChecks(
745       last_sent_rand, stage1_vals.random, uint64_t{passkey});
746   RunUntilIdle();
747   EXPECT_EQ(kPairingDHKeyCheck, sent_code);
748   EXPECT_EQ(vals.dhkey_check_a, sent_payload);
749   ReceiveCmd(kPairingDHKeyCheck, vals.dhkey_check_b);
750   RunUntilIdle();
751   ASSERT_EQ(vals.ltk, ltk());
752 }
753 
TEST_F(Phase2SecureConnectionsTest,ResponderReceiveWrongDhKeyCheckFails)754 TEST_F(Phase2SecureConnectionsTest, ResponderReceiveWrongDhKeyCheckFails) {
755   NewPhase2SecureConnections(Role::kResponder);
756   ConfirmCallback confirm_cb = nullptr;
757   listener()->set_confirm_delegate(
758       [&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
759   LtkAndChecks expected_stage2_vals = FastForwardToDhKeyCheck();
760   ASSERT_TRUE(confirm_cb);
761   Code sent_code = kPairingFailed;
762   UInt128 sent_payload;
763   fake_chan()->SetSendCallback(
764       [&](ByteBufferPtr sdu) {
765         std::tie(sent_code, sent_payload) =
766             ExtractCodeAnd128BitCmd(std::move(sdu));
767       },
768       dispatcher());
769   confirm_cb(true);
770   RunUntilIdle();
771   // As responder, we expect the dhkey_check_a value, not the b.
772   const auto kPairingDHKeyCheckCmdWithBValue =
773       MakeCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_b);
774   const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{
775       kPairingFailed, ErrorCode::kDHKeyCheckFailed};
776   ASSERT_TRUE(
777       ReceiveAndExpect(kPairingDHKeyCheckCmdWithBValue, kExpectedFailure));
778   ASSERT_EQ(1, listener()->pairing_error_count());
779   ASSERT_EQ(0, phase_2_complete_count());
780 }
781 
TEST_F(Phase2SecureConnectionsTest,ResponderFlowSuccessJustWorks)782 TEST_F(Phase2SecureConnectionsTest, ResponderFlowSuccessJustWorks) {
783   NewPhase2SecureConnections(Role::kResponder, PairingMethod::kJustWorks);
784   ConfirmCallback confirm_cb = nullptr;
785   listener()->set_confirm_delegate(
786       [&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
787   PairingConfirmValue responder_confirm = *FastForwardPublicKeyExchange();
788 
789   Code sent_code = kPairingFailed;
790   UInt128 sent_payload;
791   fake_chan()->SetSendCallback(
792       [&](ByteBufferPtr sdu) {
793         std::tie(sent_code, sent_payload) =
794             ExtractCodeAnd128BitCmd(std::move(sdu));
795       },
796       dispatcher());
797   ASSERT_FALSE(confirm_cb);
798   const PairingRandomValue kInitiatorRand{1};
799   ReceiveCmd(kPairingRandom, kInitiatorRand);
800   RunUntilIdle();
801 
802   ASSERT_EQ(kPairingRandom, sent_code);
803   UInt128 responder_rand = sent_payload;
804   ASSERT_EQ(
805       GenerateConfirmValue(responder_rand, /*gen_initiator_confirm=*/false),
806       responder_confirm);
807   ASSERT_TRUE(confirm_cb);
808   LtkAndChecks expected_stage2_vals =
809       GenerateLtkAndChecks(kInitiatorRand, responder_rand);
810   // After receiving user confirmation & the peer dhkey check, we should send
811   // the DHKey Check Eb.
812   confirm_cb(true);
813   ReceiveCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_a);
814   RunUntilIdle();
815   ASSERT_EQ(kPairingDHKeyCheck, sent_code);
816   ASSERT_EQ(expected_stage2_vals.dhkey_check_b, sent_payload);
817   ASSERT_EQ(1, phase_2_complete_count());
818   // We should generate the same LTK on "both sides"
819   ASSERT_EQ(expected_stage2_vals.ltk, ltk());
820 }
821 
TEST_F(Phase2SecureConnectionsTest,ResponderReceiveDhKeyCheckWhileWaitingForConfirmSuccess)822 TEST_F(Phase2SecureConnectionsTest,
823        ResponderReceiveDhKeyCheckWhileWaitingForConfirmSuccess) {
824   NewPhase2SecureConnections(Role::kResponder, PairingMethod::kJustWorks);
825   ConfirmCallback confirm_cb = nullptr;
826   listener()->set_confirm_delegate(
827       [&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
828   LtkAndChecks expected_stage2_vals = FastForwardToDhKeyCheck();
829 
830   Code sent_code;
831   PairingDHKeyCheckValueE sent_dhkey_check;
832   fake_chan()->SetSendCallback(
833       [&](ByteBufferPtr sdu) {
834         std::tie(sent_code, sent_dhkey_check) =
835             ExtractCodeAnd128BitCmd(std::move(sdu));
836       },
837       dispatcher());
838   ASSERT_TRUE(confirm_cb);
839   // Receiving the peer DHKey check before user confirmation should work as
840   // responder.
841   ReceiveCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_a);
842   RunUntilIdle();
843   confirm_cb(true);
844   RunUntilIdle();
845 
846   ASSERT_EQ(kPairingDHKeyCheck, sent_code);
847   ASSERT_EQ(expected_stage2_vals.dhkey_check_b, sent_dhkey_check);
848   ASSERT_EQ(1, phase_2_complete_count());
849 }
850 
851 }  // namespace
852 }  // namespace bt::sm
853