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