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