1 /******************************************************************************
2 *
3 * Copyright 2019 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 #include <memory>
22
23 #include "os/log.h"
24 #include "os/rand.h"
25 #include "security/pairing_handler_le.h"
26 #include "security/test/mocks.h"
27
28 using ::testing::_;
29 using ::testing::Eq;
30 using ::testing::Field;
31 using ::testing::VariantWith;
32
33 using bluetooth::os::GenerateRandom;
34 using bluetooth::security::CommandView;
35
36 namespace bluetooth {
37 namespace security {
38
39 namespace {
40
BuilderToView(std::unique_ptr<BasePacketBuilder> builder)41 CommandView BuilderToView(std::unique_ptr<BasePacketBuilder> builder) {
42 std::shared_ptr<std::vector<uint8_t>> packet_bytes = std::make_shared<std::vector<uint8_t>>();
43 BitInserter it(*packet_bytes);
44 builder->Serialize(it);
45 PacketView<kLittleEndian> packet_bytes_view(packet_bytes);
46 auto temp_cmd_view = CommandView::Create(packet_bytes_view);
47 return CommandView::Create(temp_cmd_view);
48 }
49
50 class PairingResultHandlerMock {
51 public:
52 MOCK_CONST_METHOD1(OnPairingFinished, void(PairingResultOrFailure));
53 };
54
55 std::unique_ptr<PairingResultHandlerMock> pairingResult;
56 LeSecurityInterfaceMock leSecurityMock;
57 UIMock uiMock;
58
OnPairingFinished(PairingResultOrFailure r)59 void OnPairingFinished(PairingResultOrFailure r) {
60 if (std::holds_alternative<PairingResult>(r)) {
61 LOG(INFO) << "pairing with " << std::get<PairingResult>(r).connection_address << " finished successfully!";
62 } else {
63 LOG(INFO) << "pairing with ... failed!";
64 }
65 pairingResult->OnPairingFinished(r);
66 }
67 } // namespace
68
69 class PairingHandlerUnitTest : public testing::Test {
70 protected:
SetUp()71 void SetUp() {
72 thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL);
73 handler_ = new os::Handler(thread_);
74
75 bidi_queue_ =
76 std::make_unique<common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>>(10);
77 up_buffer_ = std::make_unique<os::EnqueueBuffer<packet::BasePacketBuilder>>(bidi_queue_->GetUpEnd());
78
79 bidi_queue_->GetDownEnd()->RegisterDequeue(
80 handler_, common::Bind(&PairingHandlerUnitTest::L2CAP_SendSmp, common::Unretained(this)));
81
82 pairingResult.reset(new PairingResultHandlerMock);
83 }
TearDown()84 void TearDown() {
85 pairingResult.reset();
86 bidi_queue_->GetDownEnd()->UnregisterDequeue();
87 handler_->Clear();
88 delete handler_;
89 delete thread_;
90
91 ::testing::Mock::VerifyAndClearExpectations(&leSecurityMock);
92 ::testing::Mock::VerifyAndClearExpectations(&uiMock);
93 }
94
L2CAP_SendSmp()95 void L2CAP_SendSmp() {
96 std::unique_ptr<packet::BasePacketBuilder> builder = bidi_queue_->GetDownEnd()->TryDequeue();
97
98 outgoing_l2cap_packet_ = BuilderToView(std::move(builder));
99 outgoing_l2cap_packet_->IsValid();
100
101 outgoing_l2cap_blocker_.notify_one();
102 }
103
WaitForOutgoingL2capPacket()104 std::optional<bluetooth::security::CommandView> WaitForOutgoingL2capPacket() {
105 std::mutex mutex;
106 std::unique_lock<std::mutex> lock(mutex);
107
108 // It is possible that we lost wakeup from condition_variable, check if data is already waiting to be processed
109 if (outgoing_l2cap_packet_ != std::nullopt) {
110 std::optional<bluetooth::security::CommandView> tmp = std::nullopt;
111 outgoing_l2cap_packet_.swap(tmp);
112 return tmp;
113 }
114
115 // Data not ready yet, wait for it.
116 if (outgoing_l2cap_blocker_.wait_for(lock, std::chrono::seconds(5)) == std::cv_status::timeout) {
117 return std::nullopt;
118 }
119
120 std::optional<bluetooth::security::CommandView> tmp = std::nullopt;
121 outgoing_l2cap_packet_.swap(tmp);
122 return tmp;
123 }
124
125 public:
126 os::Thread* thread_;
127 os::Handler* handler_;
128 std::unique_ptr<common::BidiQueue<packet::PacketView<packet::kLittleEndian>, packet::BasePacketBuilder>> bidi_queue_;
129 std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> up_buffer_;
130 std::condition_variable outgoing_l2cap_blocker_;
131 std::optional<bluetooth::security::CommandView> outgoing_l2cap_packet_ = std::nullopt;
132 };
133
134 InitialInformations initial_informations{
135 .my_role = hci::Role::CENTRAL,
136 .my_connection_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
137 .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
138 .my_identity_resolving_key =
139 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
140
141 .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
142 .oob_data_flag = OobDataFlag::NOT_PRESENT,
143 .auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc,
144 .maximum_encryption_key_size = 16,
145 .initiator_key_distribution = 0x03,
146 .responder_key_distribution = 0x03},
147
148 .remotely_initiated = false,
149 .remote_connection_address = {{}, hci::AddressType::RANDOM_DEVICE_ADDRESS},
150 .user_interface = &uiMock,
151 .le_security_interface = &leSecurityMock,
152 .OnPairingFinished = OnPairingFinished,
153 };
154
TEST_F(PairingHandlerUnitTest,test_phase_1_failure)155 TEST_F(PairingHandlerUnitTest, test_phase_1_failure) {
156 initial_informations.proper_l2cap_interface = up_buffer_.get();
157 initial_informations.l2cap_handler = handler_;
158 initial_informations.user_interface_handler = handler_;
159
160 std::unique_ptr<PairingHandlerLe> pairing_handler =
161 std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations);
162
163 std::optional<bluetooth::security::CommandView> pairing_request = WaitForOutgoingL2capPacket();
164 EXPECT_TRUE(pairing_request.has_value());
165 EXPECT_EQ(pairing_request->GetCode(), Code::PAIRING_REQUEST);
166
167 EXPECT_CALL(*pairingResult, OnPairingFinished(VariantWith<PairingFailure>(_))).Times(1);
168
169 // SMP will waith for Pairing Response, once bad packet is received, it should stop the Pairing
170 CommandView bad_pairing_response = BuilderToView(PairingRandomBuilder::Create({}));
171 bad_pairing_response.IsValid();
172 pairing_handler->OnCommandView(bad_pairing_response);
173
174 std::optional<bluetooth::security::CommandView> pairing_failure = WaitForOutgoingL2capPacket();
175 EXPECT_TRUE(pairing_failure.has_value());
176 EXPECT_EQ(pairing_failure->GetCode(), Code::PAIRING_FAILED);
177 }
178
TEST_F(PairingHandlerUnitTest,test_secure_connections_just_works)179 TEST_F(PairingHandlerUnitTest, test_secure_connections_just_works) {
180 initial_informations.proper_l2cap_interface = up_buffer_.get();
181 initial_informations.l2cap_handler = handler_;
182 initial_informations.user_interface_handler = handler_;
183
184 // we keep the pairing_handler as unique_ptr to better mimick how it's used
185 // in the real world
186 std::unique_ptr<PairingHandlerLe> pairing_handler =
187 std::make_unique<PairingHandlerLe>(PairingHandlerLe::PHASE1, initial_informations);
188
189 std::optional<bluetooth::security::CommandView> pairing_request_pkt = WaitForOutgoingL2capPacket();
190 EXPECT_TRUE(pairing_request_pkt.has_value());
191 EXPECT_EQ(pairing_request_pkt->GetCode(), Code::PAIRING_REQUEST);
192 CommandView pairing_request = pairing_request_pkt.value();
193
194 auto pairing_response = BuilderToView(
195 PairingResponseBuilder::Create(IoCapability::KEYBOARD_DISPLAY, OobDataFlag::NOT_PRESENT,
196 AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc, 16, 0x03, 0x03));
197 pairing_handler->OnCommandView(pairing_response);
198 // Phase 1 finished.
199
200 // pairing public key
201 std::optional<bluetooth::security::CommandView> public_key_pkt = WaitForOutgoingL2capPacket();
202 EXPECT_TRUE(public_key_pkt.has_value());
203 EXPECT_EQ(Code::PAIRING_PUBLIC_KEY, public_key_pkt->GetCode());
204 EcdhPublicKey my_public_key;
205 auto ppkv = PairingPublicKeyView::Create(public_key_pkt.value());
206 ppkv.IsValid();
207 my_public_key.x = ppkv.GetPublicKeyX();
208 my_public_key.y = ppkv.GetPublicKeyY();
209
210 const auto [private_key, public_key] = GenerateECDHKeyPair();
211
212 pairing_handler->OnCommandView(BuilderToView(PairingPublicKeyBuilder::Create(public_key.x, public_key.y)));
213 // DHKey exchange finished
214 std::array<uint8_t, 32> dhkey = ComputeDHKey(private_key, my_public_key);
215
216 // Phasae 2 Stage 1 start
217 Octet16 ra, rb;
218 ra = rb = {0};
219
220 Octet16 Nb = GenerateRandom<16>();
221
222 // Compute confirm
223 Octet16 Cb = crypto_toolbox::f4((uint8_t*)public_key.x.data(), (uint8_t*)my_public_key.x.data(), Nb, 0);
224
225 pairing_handler->OnCommandView(BuilderToView(PairingConfirmBuilder::Create(Cb)));
226
227 // random
228 std::optional<bluetooth::security::CommandView> random_pkt = WaitForOutgoingL2capPacket();
229 EXPECT_TRUE(random_pkt.has_value());
230 EXPECT_EQ(Code::PAIRING_RANDOM, random_pkt->GetCode());
231 auto prv = PairingRandomView::Create(random_pkt.value());
232 prv.IsValid();
233 Octet16 Na = prv.GetRandomValue();
234
235 pairing_handler->OnCommandView(BuilderToView(PairingRandomBuilder::Create(Nb)));
236
237 // Start of authentication stage 2
238 uint8_t a[7];
239 uint8_t b[7];
240 memcpy(b, initial_informations.remote_connection_address.GetAddress().data(), hci::Address::kLength);
241 b[6] = (uint8_t)initial_informations.remote_connection_address.GetAddressType();
242 memcpy(a, initial_informations.my_connection_address.GetAddress().data(), hci::Address::kLength);
243 a[6] = (uint8_t)initial_informations.my_connection_address.GetAddressType();
244
245 Octet16 ltk, mac_key;
246 crypto_toolbox::f5(dhkey.data(), Na, Nb, a, b, &mac_key, <k);
247
248 PairingRequestView preqv = PairingRequestView::Create(pairing_request);
249 PairingResponseView prspv = PairingResponseView::Create(pairing_response);
250
251 preqv.IsValid();
252 prspv.IsValid();
253 std::array<uint8_t, 3> iocapA{static_cast<uint8_t>(preqv.GetIoCapability()),
254 static_cast<uint8_t>(preqv.GetOobDataFlag()), preqv.GetAuthReq()};
255 std::array<uint8_t, 3> iocapB{static_cast<uint8_t>(prspv.GetIoCapability()),
256 static_cast<uint8_t>(prspv.GetOobDataFlag()), prspv.GetAuthReq()};
257
258 Octet16 Ea = crypto_toolbox::f6(mac_key, Na, Nb, rb, iocapA.data(), a, b);
259 Octet16 Eb = crypto_toolbox::f6(mac_key, Nb, Na, ra, iocapB.data(), b, a);
260
261 std::optional<bluetooth::security::CommandView> dh_key_pkt = WaitForOutgoingL2capPacket();
262 EXPECT_TRUE(dh_key_pkt.has_value());
263 EXPECT_EQ(Code::PAIRING_DH_KEY_CHECK, dh_key_pkt->GetCode());
264 auto pdhkcv = PairingDhKeyCheckView::Create(dh_key_pkt.value());
265 pdhkcv.IsValid();
266 EXPECT_EQ(pdhkcv.GetDhKeyCheck(), Ea);
267
268 pairing_handler->OnCommandView(BuilderToView(PairingDhKeyCheckBuilder::Create(Eb)));
269
270 // Phase 2 finished
271 // We don't care for the rest of the flow, let it die.
272 }
273
274 InitialInformations initial_informations_trsi{
275 .my_role = hci::Role::CENTRAL,
276 .my_connection_address = hci::AddressWithType(),
277 .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
278 .my_identity_resolving_key =
279 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
280
281 .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
282 .oob_data_flag = OobDataFlag::NOT_PRESENT,
283 .auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc,
284 .maximum_encryption_key_size = 16,
285 .initiator_key_distribution = 0x03,
286 .responder_key_distribution = 0x03},
287
288 .remotely_initiated = true,
289 .remote_connection_address = hci::AddressWithType(),
290 .user_interface = &uiMock,
291 .le_security_interface = &leSecurityMock,
292 .OnPairingFinished = OnPairingFinished,
293 };
294
295 /* This test verifies that when remote peripheral device sends security request , and user
296 * does accept the prompt, we do send pairing request */
TEST_F(PairingHandlerUnitTest,test_remote_peripheral_initiating)297 TEST_F(PairingHandlerUnitTest, test_remote_peripheral_initiating) {
298 initial_informations_trsi.proper_l2cap_interface = up_buffer_.get();
299 initial_informations_trsi.l2cap_handler = handler_;
300 initial_informations_trsi.user_interface_handler = handler_;
301
302 std::unique_ptr<PairingHandlerLe> pairing_handler =
303 std::make_unique<PairingHandlerLe>(PairingHandlerLe::ACCEPT_PROMPT, initial_informations_trsi);
304
305 // Simulate user accepting the pairing in UI
306 pairing_handler->OnUiAction(PairingEvent::PAIRING_ACCEPTED, 0x01 /* Non-zero value means success */);
307
308 std::optional<bluetooth::security::CommandView> pairing_request_pkt = WaitForOutgoingL2capPacket();
309 EXPECT_TRUE(pairing_request_pkt.has_value());
310 EXPECT_EQ(Code::PAIRING_REQUEST, pairing_request_pkt->GetCode());
311
312 // We don't care for the rest of the flow, let it die.
313 pairing_handler.reset();
314 }
315
316 InitialInformations initial_informations_trmi{
317 .my_role = hci::Role::PERIPHERAL,
318 .my_connection_address = hci::AddressWithType(),
319 .my_identity_address = {{}, hci::AddressType::PUBLIC_DEVICE_ADDRESS},
320 .my_identity_resolving_key =
321 {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
322
323 .myPairingCapabilities = {.io_capability = IoCapability::NO_INPUT_NO_OUTPUT,
324 .oob_data_flag = OobDataFlag::NOT_PRESENT,
325 .auth_req = AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc,
326 .maximum_encryption_key_size = 16,
327 .initiator_key_distribution = 0x03,
328 .responder_key_distribution = 0x03},
329
330 .remotely_initiated = true,
331 .remote_connection_address = hci::AddressWithType(),
332 .pairing_request = PairingRequestView::Create(BuilderToView(PairingRequestBuilder::Create(
333 IoCapability::NO_INPUT_NO_OUTPUT,
334 OobDataFlag::NOT_PRESENT,
335 AuthReqMaskBondingFlag | AuthReqMaskMitm | AuthReqMaskSc,
336 16,
337 0x03,
338 0x03))),
339 .user_interface = &uiMock,
340 .le_security_interface = &leSecurityMock,
341
342 .OnPairingFinished = OnPairingFinished,
343 };
344
345 /* This test verifies that when remote device sends pairing request, and user does accept the prompt, we do send proper
346 * reply back */
TEST_F(PairingHandlerUnitTest,test_remote_central_initiating)347 TEST_F(PairingHandlerUnitTest, test_remote_central_initiating) {
348 initial_informations_trmi.proper_l2cap_interface = up_buffer_.get();
349 initial_informations_trmi.l2cap_handler = handler_;
350 initial_informations_trmi.user_interface_handler = handler_;
351
352 std::unique_ptr<PairingHandlerLe> pairing_handler =
353 std::make_unique<PairingHandlerLe>(PairingHandlerLe::ACCEPT_PROMPT, initial_informations_trmi);
354
355 // Simulate user accepting the pairing in UI
356 pairing_handler->OnUiAction(PairingEvent::PAIRING_ACCEPTED, 0x01 /* Non-zero value means success */);
357
358 std::optional<bluetooth::security::CommandView> pairing_response_pkt = WaitForOutgoingL2capPacket();
359 EXPECT_TRUE(pairing_response_pkt.has_value());
360 EXPECT_EQ(Code::PAIRING_RESPONSE, pairing_response_pkt->GetCode());
361 // Phase 1 finished.
362
363 // We don't care for the rest of the flow, it's handled in in other tests. let it die.
364 pairing_handler.reset();
365 }
366
367 } // namespace security
368 } // namespace bluetooth
369