• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #pragma once
20 
21 #include <array>
22 #include <chrono>
23 #include <condition_variable>
24 #include <mutex>
25 #include <optional>
26 #include <queue>
27 #include <thread>
28 #include <variant>
29 
30 #include "common/bind.h"
31 #include "crypto_toolbox/crypto_toolbox.h"
32 #include "hci/hci_packets.h"
33 #include "hci/le_security_interface.h"
34 #include "packet/packet_view.h"
35 #include "security/ecdh_keys.h"
36 #include "security/initial_informations.h"
37 #include "security/pairing_failure.h"
38 #include "security/smp_packets.h"
39 #include "security/ui.h"
40 
41 // Code generated by PDL does not allow us ot do || and && operations on bits
42 // efficiently. Use those masks on fields requiring them until this is solved
43 constexpr uint8_t AuthReqMaskBondingFlag = 0x01;
44 constexpr uint8_t AuthReqMaskMitm = 0x04;
45 constexpr uint8_t AuthReqMaskSc = 0x08;
46 constexpr uint8_t AuthReqMaskKeypress = 0x10;
47 constexpr uint8_t AuthReqMaskCt2 = 0x20;
48 
49 constexpr uint8_t KeyMaskEnc = 0x01;
50 constexpr uint8_t KeyMaskId = 0x02;
51 constexpr uint8_t KeyMaskSign = 0x04;
52 constexpr uint8_t KeyMaskLink = 0x08;
53 
54 using bluetooth::hci::EncryptionChangeView;
55 using bluetooth::hci::EncryptionKeyRefreshCompleteView;
56 
57 namespace bluetooth {
58 namespace security {
59 
60 using crypto_toolbox::Octet16;
61 
62 /* This class represents an event send from other subsystems into SMP Pairing Handler,
63  * i.e. user request from the UI, L2CAP or HCI interaction */
64 class PairingEvent {
65  public:
66   enum TYPE { EXIT, L2CAP, HCI_EVENT, UI };
67   TYPE type;
68 
69   std::optional<CommandView> l2cap_packet;
70 
71   std::optional<hci::EventPacketView> hci_event;
72 
73   enum UI_ACTION_TYPE { PAIRING_ACCEPTED, CONFIRM_YESNO, PASSKEY };
74   UI_ACTION_TYPE ui_action;
75   uint32_t ui_value;
76 
PairingEvent(TYPE type)77   PairingEvent(TYPE type) : type(type) {}
PairingEvent(CommandView l2cap_packet)78   PairingEvent(CommandView l2cap_packet) : type(L2CAP), l2cap_packet(l2cap_packet) {}
PairingEvent(UI_ACTION_TYPE ui_action,uint32_t ui_value)79   PairingEvent(UI_ACTION_TYPE ui_action, uint32_t ui_value) : type(UI), ui_action(ui_action), ui_value(ui_value) {}
PairingEvent(hci::EventPacketView hci_event)80   PairingEvent(hci::EventPacketView hci_event) : type(HCI_EVENT), hci_event(hci_event) {}
81 };
82 
83 constexpr int SMP_TIMEOUT = 30;
84 
85 using CommandViewOrFailure = std::variant<CommandView, PairingFailure>;
86 using Phase1Result = std::pair<PairingRequestView /* pairning_request*/, PairingResponseView /* pairing_response */>;
87 using Phase1ResultOrFailure = std::variant<PairingFailure, Phase1Result>;
88 using KeyExchangeResult =
89     std::tuple<EcdhPublicKey /* PKa */, EcdhPublicKey /* PKb */, std::array<uint8_t, 32> /*dhkey*/>;
90 using Stage1Result = std::tuple<Octet16, Octet16, Octet16, Octet16>;
91 using Stage1ResultOrFailure = std::variant<PairingFailure, Stage1Result>;
92 using Stage2ResultOrFailure = std::variant<PairingFailure, Octet16 /* LTK */>;
93 using DistributedKeysOrFailure = std::variant<PairingFailure, DistributedKeys, std::monostate>;
94 
95 using LegacyStage1Result = Octet16 /*TK*/;
96 using LegacyStage1ResultOrFailure = std::variant<PairingFailure, LegacyStage1Result>;
97 using StkOrFailure = std::variant<PairingFailure, Octet16 /* STK */>;
98 
99 /* PairingHandlerLe takes care of the Pairing process. Pairing is strictly defined
100  * exchange of messages and UI interactions, divided into PHASES.
101  *
102  * Each PairingHandlerLe have a thread executing |PairingMain| method. Thread is
103  * blocked when waiting for UI/L2CAP/HCI interactions, and moves through all the
104  * phases.
105  */
106 class PairingHandlerLe {
107  public:
108   // This is the phase of pairing as defined in BT Spec (with exception of
109   // accept prompt)
110   // * ACCEPT_PROMPT - we're waiting for the user to accept remotely initiated pairing
111   // * PHASE1 - feature exchange
112   // * PHASE2 - authentication
113   // * PHASE3 - key exchange
114   enum PAIRING_PHASE { ACCEPT_PROMPT, PHASE1, PHASE2, PHASE3 };
115   PAIRING_PHASE phase;
116 
117   // All the knowledge to initiate the pairing process must be passed into this function
PairingHandlerLe(PAIRING_PHASE phase,InitialInformations informations)118   PairingHandlerLe(PAIRING_PHASE phase, InitialInformations informations)
119       : phase(phase), queue_guard(), thread_(&PairingHandlerLe::PairingMain, this, informations) {}
120 
~PairingHandlerLe()121   ~PairingHandlerLe() {
122     SendExitSignal();
123     // we need ot check if thread is joinable, because tests call join form
124     // within WaitUntilPairingFinished
125     if (thread_.joinable()) thread_.join();
126   }
127 
128   void PairingMain(InitialInformations i);
129 
130   Phase1ResultOrFailure ExchangePairingFeature(const InitialInformations& i);
131 
SendL2capPacket(const InitialInformations & i,std::unique_ptr<bluetooth::security::CommandBuilder> command)132   void SendL2capPacket(const InitialInformations& i, std::unique_ptr<bluetooth::security::CommandBuilder> command) {
133     i.proper_l2cap_interface->Enqueue(std::move(command), i.l2cap_handler);
134   }
135 
SendHciLeStartEncryption(const InitialInformations & i,uint16_t conn_handle,const std::array<uint8_t,8> & rand,const uint16_t & ediv,const Octet16 & ltk)136   void SendHciLeStartEncryption(const InitialInformations& i, uint16_t conn_handle, const std::array<uint8_t, 8>& rand,
137                                 const uint16_t& ediv, const Octet16& ltk) {
138     i.le_security_interface->EnqueueCommand(hci::LeStartEncryptionBuilder::Create(conn_handle, rand, ediv, ltk),
139                                             common::BindOnce([](hci::CommandStatusView) {
140                                               // TODO: handle command status. It's important - can show we are not
141                                               // connected any more.
142 
143                                               // TODO: if anything useful must be done there, use some sort of proper
144                                               // handler, wait/notify, and execute on the handler thread
145                                             }),
146                                             i.l2cap_handler);
147   }
148 
WaitEncryptionChanged()149   std::variant<PairingFailure, EncryptionChangeView, EncryptionKeyRefreshCompleteView> WaitEncryptionChanged() {
150     PairingEvent e = WaitForEvent();
151     if (e.type != PairingEvent::HCI_EVENT) return PairingFailure("Was expecting HCI event but received something else");
152 
153     if (!e.hci_event->IsValid()) return PairingFailure("Received invalid HCI event");
154 
155     if (e.hci_event->GetEventCode() == hci::EventCode::ENCRYPTION_CHANGE) {
156       EncryptionChangeView enc_chg_packet = EncryptionChangeView::Create(*e.hci_event);
157       if (!enc_chg_packet.IsValid()) {
158         return PairingFailure("Invalid Encryption Change packet received");
159       }
160       return enc_chg_packet;
161     }
162 
163     if (e.hci_event->GetEventCode() == hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE) {
164       hci::EncryptionKeyRefreshCompleteView enc_packet = EncryptionKeyRefreshCompleteView::Create(*e.hci_event);
165       if (!enc_packet.IsValid()) {
166         return PairingFailure("Invalid Key Refresh packet received");
167       }
168       return enc_packet;
169     }
170 
171     return PairingFailure("Was expecting Encryption Change or Key Refresh Complete but received something else");
172   }
173 
IAmMaster(const InitialInformations & i)174   inline bool IAmMaster(const InitialInformations& i) {
175     return i.my_role == hci::Role::MASTER;
176   }
177 
178   /* This function generates data that should be passed to remote device, except
179      the private key. */
GenerateOobData()180   static MyOobData GenerateOobData() {
181     MyOobData data;
182     std::tie(data.private_key, data.public_key) = GenerateECDHKeyPair();
183 
184     data.r = GenerateRandom<16>();
185     data.c = crypto_toolbox::f4(data.public_key.x.data(), data.public_key.x.data(), data.r, 0);
186     return data;
187   }
188 
189   std::variant<PairingFailure, KeyExchangeResult> ExchangePublicKeys(const InitialInformations& i,
190                                                                      OobDataFlag remote_have_oob_data);
191 
192   Stage1ResultOrFailure DoSecureConnectionsStage1(const InitialInformations& i, const EcdhPublicKey& PKa,
193                                                   const EcdhPublicKey& PKb, const PairingRequestView& pairing_request,
194                                                   const PairingResponseView& pairing_response);
195 
196   Stage1ResultOrFailure SecureConnectionsNumericComparison(const InitialInformations& i, const EcdhPublicKey& PKa,
197                                                            const EcdhPublicKey& PKb);
198 
199   Stage1ResultOrFailure SecureConnectionsJustWorks(const InitialInformations& i, const EcdhPublicKey& PKa,
200                                                    const EcdhPublicKey& PKb);
201 
202   Stage1ResultOrFailure SecureConnectionsPasskeyEntry(const InitialInformations& i, const EcdhPublicKey& PKa,
203                                                       const EcdhPublicKey& PKb, IoCapability my_iocaps,
204                                                       IoCapability remote_iocaps);
205 
206   Stage1ResultOrFailure SecureConnectionsOutOfBand(const InitialInformations& i, const EcdhPublicKey& Pka,
207                                                    const EcdhPublicKey& Pkb, OobDataFlag my_oob_flag,
208                                                    OobDataFlag remote_oob_flag);
209 
210   Stage2ResultOrFailure DoSecureConnectionsStage2(const InitialInformations& i, const EcdhPublicKey& PKa,
211                                                   const EcdhPublicKey& PKb, const PairingRequestView& pairing_request,
212                                                   const PairingResponseView& pairing_response,
213                                                   const Stage1Result stage1result,
214                                                   const std::array<uint8_t, 32>& dhkey);
215 
216   DistributedKeysOrFailure DistributeKeys(const InitialInformations& i, const PairingResponseView& pairing_response,
217                                           bool isSecureConnections);
218 
219   DistributedKeysOrFailure ReceiveKeys(const uint8_t& keys_i_receive);
220 
221   LegacyStage1ResultOrFailure DoLegacyStage1(const InitialInformations& i, const PairingRequestView& pairing_request,
222                                              const PairingResponseView& pairing_response);
223   LegacyStage1ResultOrFailure LegacyOutOfBand(const InitialInformations& i);
224   LegacyStage1ResultOrFailure LegacyJustWorks();
225   LegacyStage1ResultOrFailure LegacyPasskeyEntry(const InitialInformations& i, const IoCapability& my_iocaps,
226                                                  const IoCapability& remote_iocaps);
227   StkOrFailure DoLegacyStage2(const InitialInformations& i, const PairingRequestView& pairing_request,
228                               const PairingResponseView& pairing_response, const Octet16& tk);
229 
230   void SendKeys(const InitialInformations& i, const uint8_t& keys_i_send, Octet16 ltk, uint16_t ediv,
231                 std::array<uint8_t, 8> rand, Octet16 irk, Address identity_address, AddrType identity_addres_type,
232                 Octet16 signature_key);
233 
234   /* This can be called from any thread to immediately finish the pairing in progress. */
SendExitSignal()235   void SendExitSignal() {
236     {
237       std::unique_lock<std::mutex> lock(queue_guard);
238       queue.push(PairingEvent(PairingEvent::EXIT));
239     }
240     pairing_thread_blocker_.notify_one();
241   }
242 
243   /* SMP Command received from remote device */
OnCommandView(CommandView packet)244   void OnCommandView(CommandView packet) {
245     {
246       std::unique_lock<std::mutex> lock(queue_guard);
247       queue.push(PairingEvent(std::move(packet)));
248     }
249     pairing_thread_blocker_.notify_one();
250   }
251 
252   /* SMP Command received from remote device */
OnHciEvent(hci::EventPacketView hci_event)253   void OnHciEvent(hci::EventPacketView hci_event) {
254     {
255       std::unique_lock<std::mutex> lock(queue_guard);
256       queue.push(PairingEvent(std::move(hci_event)));
257     }
258     pairing_thread_blocker_.notify_one();
259   }
260 
261   /* Interaction from user */
OnUiAction(PairingEvent::UI_ACTION_TYPE ui_action,uint32_t ui_value)262   void OnUiAction(PairingEvent::UI_ACTION_TYPE ui_action, uint32_t ui_value) {
263     {
264       std::unique_lock<std::mutex> lock(queue_guard);
265       queue.push(PairingEvent(ui_action, ui_value));
266     }
267     pairing_thread_blocker_.notify_one();
268   }
269 
270   /* Blocks the pairing process until some external interaction, or timeout happens */
WaitForEvent()271   PairingEvent WaitForEvent() {
272     std::unique_lock<std::mutex> lock(queue_guard);
273     do {
274       if (!queue.empty()) {
275         PairingEvent e = queue.front();
276         queue.pop();
277         return e;
278       }
279       // This releases the lock while blocking.
280       if (pairing_thread_blocker_.wait_for(lock, std::chrono::seconds(SMP_TIMEOUT)) == std::cv_status::timeout) {
281         return PairingEvent(PairingEvent::EXIT);
282       }
283 
284     } while (true);
285   }
286 
WaitUiPairingAccept()287   std::optional<PairingEvent> WaitUiPairingAccept() {
288     PairingEvent e = WaitForEvent();
289     if (e.type == PairingEvent::UI & e.ui_action == PairingEvent::PAIRING_ACCEPTED) {
290       return e;
291     } else {
292       return std::nullopt;
293     }
294   }
295 
WaitUiConfirmYesNo()296   std::optional<PairingEvent> WaitUiConfirmYesNo() {
297     PairingEvent e = WaitForEvent();
298     if (e.type == PairingEvent::UI & e.ui_action == PairingEvent::CONFIRM_YESNO) {
299       return e;
300     } else {
301       return std::nullopt;
302     }
303   }
304 
WaitUiPasskey()305   std::optional<PairingEvent> WaitUiPasskey() {
306     PairingEvent e = WaitForEvent();
307     if (e.type == PairingEvent::UI & e.ui_action == PairingEvent::PASSKEY) {
308       return e;
309     } else {
310       return std::nullopt;
311     }
312   }
313 
314   template <Code C>
315   struct CodeToPacketView;
316   template <>
317   struct CodeToPacketView<Code::PAIRING_REQUEST> {
318     typedef PairingRequestView type;
319   };
320   template <>
321   struct CodeToPacketView<Code::PAIRING_RESPONSE> {
322     typedef PairingResponseView type;
323   };
324   template <>
325   struct CodeToPacketView<Code::PAIRING_CONFIRM> {
326     typedef PairingConfirmView type;
327   };
328   template <>
329   struct CodeToPacketView<Code::PAIRING_RANDOM> {
330     typedef PairingRandomView type;
331   };
332   template <>
333   struct CodeToPacketView<Code::PAIRING_FAILED> {
334     typedef PairingFailedView type;
335   };
336   template <>
337   struct CodeToPacketView<Code::ENCRYPTION_INFORMATION> {
338     typedef EncryptionInformationView type;
339   };
340   template <>
341   struct CodeToPacketView<Code::MASTER_IDENTIFICATION> {
342     typedef MasterIdentificationView type;
343   };
344   template <>
345   struct CodeToPacketView<Code::IDENTITY_INFORMATION> {
346     typedef IdentityInformationView type;
347   };
348   template <>
349   struct CodeToPacketView<Code::IDENTITY_ADDRESS_INFORMATION> {
350     typedef IdentityAddressInformationView type;
351   };
352   template <>
353   struct CodeToPacketView<Code::SIGNING_INFORMATION> {
354     typedef SigningInformationView type;
355   };
356   template <>
357   struct CodeToPacketView<Code::SECURITY_REQUEST> {
358     typedef SecurityRequestView type;
359   };
360   template <>
361   struct CodeToPacketView<Code::PAIRING_PUBLIC_KEY> {
362     typedef PairingPublicKeyView type;
363   };
364   template <>
365   struct CodeToPacketView<Code::PAIRING_DH_KEY_CHECK> {
366     typedef PairingDhKeyCheckView type;
367   };
368   template <>
369   struct CodeToPacketView<Code::PAIRING_KEYPRESS_NOTIFICATION> {
370     typedef PairingKeypressNotificationView type;
371   };
372 
373   template <Code CODE>
374   std::variant<typename CodeToPacketView<CODE>::type, PairingFailure> WaitPacket() {
375     PairingEvent e = WaitForEvent();
376     switch (e.type) {
377       case PairingEvent::EXIT:
378         return PairingFailure(
379             /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + ", but received EXIT instead");
380 
381       case PairingEvent::HCI_EVENT:
382         return PairingFailure(
383             /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + ", but received HCI_EVENT instead");
384 
385       case PairingEvent::UI:
386         return PairingFailure(
387             /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + ", but received UI instead");
388 
389       case PairingEvent::L2CAP: {
390         auto l2cap_packet = e.l2cap_packet.value();
391         if (!l2cap_packet.IsValid()) {
392           return PairingFailure("Malformed L2CAP packet received!");
393         }
394 
395         const auto& received_code = l2cap_packet.GetCode();
396         if (received_code != CODE) {
397           if (received_code == Code::PAIRING_FAILED) {
398             auto pkt = PairingFailedView::Create(l2cap_packet);
399             if (!pkt.IsValid()) return PairingFailure("Malformed " + CodeText(CODE) + " packet");
400             return PairingFailure(/*FROM_HERE,*/
401                                   "Was expecting " + CodeText(CODE) + ", but received PAIRING_FAILED instead",
402                                   pkt.GetReason());
403           }
404 
405           return PairingFailure(/*FROM_HERE,*/
406                                 "Was expecting " + CodeText(CODE) + ", but received " + CodeText(received_code) +
407                                     " instead",
408                                 received_code);
409         }
410 
411         auto pkt = CodeToPacketView<CODE>::type::Create(l2cap_packet);
412         if (!pkt.IsValid()) return PairingFailure("Malformed " + CodeText(CODE) + " packet");
413         return pkt;
414       }
415     }
416   }
417 
418   auto WaitPairingRequest() {
419     return WaitPacket<Code::PAIRING_REQUEST>();
420   }
421 
422   auto WaitPairingResponse() {
423     return WaitPacket<Code::PAIRING_RESPONSE>();
424   }
425 
426   auto WaitPairingConfirm() {
427     return WaitPacket<Code::PAIRING_CONFIRM>();
428   }
429 
430   auto WaitPairingRandom() {
431     return WaitPacket<Code::PAIRING_RANDOM>();
432   }
433 
434   auto WaitPairingPublicKey() {
435     return WaitPacket<Code::PAIRING_PUBLIC_KEY>();
436   }
437 
438   auto WaitPairingDHKeyCheck() {
439     return WaitPacket<Code::PAIRING_DH_KEY_CHECK>();
440   }
441 
442   auto WaitEncryptionInformationRequest() {
443     return WaitPacket<Code::ENCRYPTION_INFORMATION>();
444   }
445 
446   auto WaitEncryptionInformation() {
447     return WaitPacket<Code::ENCRYPTION_INFORMATION>();
448   }
449 
450   auto WaitMasterIdentification() {
451     return WaitPacket<Code::MASTER_IDENTIFICATION>();
452   }
453 
454   auto WaitIdentityInformation() {
455     return WaitPacket<Code::IDENTITY_INFORMATION>();
456   }
457 
458   auto WaitIdentityAddressInformation() {
459     return WaitPacket<Code::IDENTITY_ADDRESS_INFORMATION>();
460   }
461 
462   auto WaitSigningInformation() {
463     return WaitPacket<Code::SIGNING_INFORMATION>();
464   }
465 
466   template <size_t SIZE>
467   static std::array<uint8_t, SIZE> GenerateRandom() {
468     // TODO:  We need a proper  random number generator here.
469     // use current time as seed for random generator
470     std::srand(std::time(nullptr));
471     std::array<uint8_t, SIZE> r;
472     for (size_t i = 0; i < SIZE; i++) r[i] = std::rand();
473     return r;
474   }
475 
476   uint32_t GenerateRandom() {
477     // TODO:  We need a proper  random number generator here.
478     // use current time as seed for random generator
479     std::srand(std::time(nullptr));
480     return std::rand();
481   }
482 
483   /* This is just for test, never use in production code! */
484   void WaitUntilPairingFinished() {
485     thread_.join();
486   }
487 
488  private:
489   std::condition_variable pairing_thread_blocker_;
490 
491   std::mutex queue_guard;
492   std::queue<PairingEvent> queue;
493 
494   std::thread thread_;
495 };
496 }  // namespace security
497 }  // namespace bluetooth