• 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::EventView> 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::EventView hci_event)80   PairingEvent(hci::EventView 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                                             i.l2cap_handler->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   }
147 
SendHciLeLongTermKeyReply(const InitialInformations & i,uint16_t conn_handle,const Octet16 & ltk)148   void SendHciLeLongTermKeyReply(const InitialInformations& i, uint16_t conn_handle, const Octet16& ltk) {
149     i.le_security_interface->EnqueueCommand(
150         hci::LeLongTermKeyRequestReplyBuilder::Create(conn_handle, ltk),
151         i.l2cap_handler->BindOnce([](hci::CommandCompleteView) {}));
152   }
153 
WaitEncryptionChanged()154   std::variant<PairingFailure, EncryptionChangeView, EncryptionKeyRefreshCompleteView> WaitEncryptionChanged() {
155     PairingEvent e = WaitForEvent();
156     if (e.type != PairingEvent::HCI_EVENT) return PairingFailure("Was expecting HCI event but received something else");
157 
158     if (!e.hci_event->IsValid()) return PairingFailure("Received invalid HCI event");
159 
160     if (e.hci_event->GetEventCode() == hci::EventCode::ENCRYPTION_CHANGE) {
161       EncryptionChangeView enc_chg_packet = EncryptionChangeView::Create(*e.hci_event);
162       if (!enc_chg_packet.IsValid()) {
163         return PairingFailure("Invalid Encryption Change packet received");
164       }
165       return enc_chg_packet;
166     }
167 
168     if (e.hci_event->GetEventCode() == hci::EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE) {
169       hci::EncryptionKeyRefreshCompleteView enc_packet = EncryptionKeyRefreshCompleteView::Create(*e.hci_event);
170       if (!enc_packet.IsValid()) {
171         return PairingFailure("Invalid Key Refresh packet received");
172       }
173       return enc_packet;
174     }
175 
176     return PairingFailure("Was expecting Encryption Change or Key Refresh Complete but received something else");
177   }
178 
WaitLeLongTermKeyRequest()179   std::variant<PairingFailure, hci::LeLongTermKeyRequestView> WaitLeLongTermKeyRequest() {
180     PairingEvent e = WaitForEvent();
181     if (e.type != PairingEvent::HCI_EVENT) return PairingFailure("Was expecting HCI event but received something else");
182 
183     if (!e.hci_event->IsValid()) return PairingFailure("Received invalid HCI event");
184 
185     if (e.hci_event->GetEventCode() != hci::EventCode::LE_META_EVENT) return PairingFailure("Was expecting LE event");
186 
187     hci::LeMetaEventView le_event = hci::LeMetaEventView::Create(*e.hci_event);
188     if (!le_event.IsValid()) {
189       return PairingFailure("Invalid LE Event received");
190     }
191 
192     if (le_event.GetSubeventCode() != hci::SubeventCode::LONG_TERM_KEY_REQUEST) {
193       return PairingFailure("Was expecting Long Term Key Request");
194     }
195 
196     hci::LeLongTermKeyRequestView ltk_req_packet = hci::LeLongTermKeyRequestView::Create(le_event);
197     if (!ltk_req_packet.IsValid()) {
198       return PairingFailure("Invalid LE Long Term Key Request received");
199     }
200 
201     return ltk_req_packet;
202   }
203 
IAmCentral(const InitialInformations & i)204   inline bool IAmCentral(const InitialInformations& i) {
205     return i.my_role == hci::Role::CENTRAL;
206   }
207 
208   /* This function generates data that should be passed to remote device, except
209      the private key. */
210   static MyOobData GenerateOobData();
211 
212   std::variant<PairingFailure, KeyExchangeResult> ExchangePublicKeys(const InitialInformations& i,
213                                                                      OobDataFlag remote_have_oob_data);
214 
215   Stage1ResultOrFailure DoSecureConnectionsStage1(const InitialInformations& i, const EcdhPublicKey& PKa,
216                                                   const EcdhPublicKey& PKb, const PairingRequestView& pairing_request,
217                                                   const PairingResponseView& pairing_response);
218 
219   Stage1ResultOrFailure SecureConnectionsNumericComparison(const InitialInformations& i, const EcdhPublicKey& PKa,
220                                                            const EcdhPublicKey& PKb);
221 
222   Stage1ResultOrFailure SecureConnectionsJustWorks(const InitialInformations& i, const EcdhPublicKey& PKa,
223                                                    const EcdhPublicKey& PKb);
224 
225   Stage1ResultOrFailure SecureConnectionsPasskeyEntry(const InitialInformations& i, const EcdhPublicKey& PKa,
226                                                       const EcdhPublicKey& PKb, IoCapability my_iocaps,
227                                                       IoCapability remote_iocaps);
228 
229   Stage1ResultOrFailure SecureConnectionsOutOfBand(const InitialInformations& i, const EcdhPublicKey& Pka,
230                                                    const EcdhPublicKey& Pkb, OobDataFlag my_oob_flag,
231                                                    OobDataFlag remote_oob_flag);
232 
233   Stage2ResultOrFailure DoSecureConnectionsStage2(const InitialInformations& i, const EcdhPublicKey& PKa,
234                                                   const EcdhPublicKey& PKb, const PairingRequestView& pairing_request,
235                                                   const PairingResponseView& pairing_response,
236                                                   const Stage1Result stage1result,
237                                                   const std::array<uint8_t, 32>& dhkey);
238 
239   DistributedKeysOrFailure DistributeKeys(const InitialInformations& i, const PairingResponseView& pairing_response,
240                                           bool isSecureConnections);
241 
242   DistributedKeysOrFailure ReceiveKeys(const uint8_t& keys_i_receive);
243 
244   LegacyStage1ResultOrFailure DoLegacyStage1(const InitialInformations& i, const PairingRequestView& pairing_request,
245                                              const PairingResponseView& pairing_response);
246   LegacyStage1ResultOrFailure LegacyOutOfBand(const InitialInformations& i);
247   LegacyStage1ResultOrFailure LegacyJustWorks();
248   LegacyStage1ResultOrFailure LegacyPasskeyEntry(const InitialInformations& i, const IoCapability& my_iocaps,
249                                                  const IoCapability& remote_iocaps);
250   StkOrFailure DoLegacyStage2(const InitialInformations& i, const PairingRequestView& pairing_request,
251                               const PairingResponseView& pairing_response, const Octet16& tk);
252 
253   void SendKeys(const InitialInformations& i, const uint8_t& keys_i_send, Octet16 ltk, uint16_t ediv,
254                 std::array<uint8_t, 8> rand, Octet16 irk, Address identity_address, AddrType identity_addres_type,
255                 Octet16 signature_key);
256 
257   /* This can be called from any thread to immediately finish the pairing in progress. */
SendExitSignal()258   void SendExitSignal() {
259     {
260       std::unique_lock<std::mutex> lock(queue_guard);
261       queue.push(PairingEvent(PairingEvent::EXIT));
262     }
263     pairing_thread_blocker_.notify_one();
264   }
265 
266   /* SMP Command received from remote device */
OnCommandView(CommandView packet)267   void OnCommandView(CommandView packet) {
268     {
269       std::unique_lock<std::mutex> lock(queue_guard);
270       queue.push(PairingEvent(std::move(packet)));
271     }
272     pairing_thread_blocker_.notify_one();
273   }
274 
275   /* SMP Command received from remote device */
OnHciEvent(hci::EventView hci_event)276   void OnHciEvent(hci::EventView hci_event) {
277     {
278       std::unique_lock<std::mutex> lock(queue_guard);
279       queue.push(PairingEvent(std::move(hci_event)));
280     }
281     pairing_thread_blocker_.notify_one();
282   }
283 
284   /* Interaction from user */
OnUiAction(PairingEvent::UI_ACTION_TYPE ui_action,uint32_t ui_value)285   void OnUiAction(PairingEvent::UI_ACTION_TYPE ui_action, uint32_t ui_value) {
286     {
287       std::unique_lock<std::mutex> lock(queue_guard);
288       queue.push(PairingEvent(ui_action, ui_value));
289     }
290     pairing_thread_blocker_.notify_one();
291   }
292 
293   /* HCI LE event received from remote device */
OnHciLeEvent(hci::LeMetaEventView hci_event)294   void OnHciLeEvent(hci::LeMetaEventView hci_event) {
295     {
296       std::unique_lock<std::mutex> lock(queue_guard);
297       queue.push(PairingEvent(std::move(hci_event)));
298     }
299     pairing_thread_blocker_.notify_one();
300   }
301 
302   /* Blocks the pairing process until some external interaction, or timeout happens */
WaitForEvent()303   PairingEvent WaitForEvent() {
304     std::unique_lock<std::mutex> lock(queue_guard);
305     do {
306       if (!queue.empty()) {
307         PairingEvent e = queue.front();
308         queue.pop();
309         return e;
310       }
311       // This releases the lock while blocking.
312       if (pairing_thread_blocker_.wait_for(lock, std::chrono::seconds(SMP_TIMEOUT)) == std::cv_status::timeout) {
313         return PairingEvent(PairingEvent::EXIT);
314       }
315 
316     } while (true);
317   }
318 
WaitUiPairingAccept()319   std::optional<PairingEvent> WaitUiPairingAccept() {
320     PairingEvent e = WaitForEvent();
321     if (e.type == PairingEvent::UI & e.ui_action == PairingEvent::PAIRING_ACCEPTED) {
322       return e;
323     } else {
324       return std::nullopt;
325     }
326   }
327 
WaitUiConfirmYesNo()328   std::optional<PairingEvent> WaitUiConfirmYesNo() {
329     PairingEvent e = WaitForEvent();
330     if (e.type == PairingEvent::UI & e.ui_action == PairingEvent::CONFIRM_YESNO) {
331       return e;
332     } else {
333       return std::nullopt;
334     }
335   }
336 
WaitUiPasskey()337   std::optional<PairingEvent> WaitUiPasskey() {
338     PairingEvent e = WaitForEvent();
339 
340     // It's possible to receive PAIRING_CONFIRM from remote device while waiting for the passkey.
341     // Store it until it's needed.
342     if (e.type == PairingEvent::L2CAP) {
343       auto l2cap_packet = e.l2cap_packet.value();
344       if (!l2cap_packet.IsValid()) {
345         LOG_WARN("Malformed L2CAP packet received!");
346         return std::nullopt;
347       }
348 
349       const auto& received_code = l2cap_packet.GetCode();
350       if (received_code != Code::PAIRING_CONFIRM) {
351         LOG_WARN("Was waiting for passkey, received bad packet instead!");
352         return std::nullopt;
353       }
354 
355       auto pkt = PairingConfirmView::Create(l2cap_packet);
356       if (!pkt.IsValid()) {
357         LOG_WARN("Malformed PAIRING_CONFIRM packet");
358         return std::nullopt;
359       }
360 
361       cached_pariring_confirm_view = std::make_unique<PairingConfirmView>(pkt);
362       e = WaitForEvent();
363     }
364 
365     if (e.type == PairingEvent::UI & e.ui_action == PairingEvent::PASSKEY) {
366       return e;
367     } else {
368       return std::nullopt;
369     }
370   }
371 
372   template <Code C>
373   struct CodeToPacketView;
374   template <>
375   struct CodeToPacketView<Code::PAIRING_REQUEST> {
376     typedef PairingRequestView type;
377   };
378   template <>
379   struct CodeToPacketView<Code::PAIRING_RESPONSE> {
380     typedef PairingResponseView type;
381   };
382   template <>
383   struct CodeToPacketView<Code::PAIRING_CONFIRM> {
384     typedef PairingConfirmView type;
385   };
386   template <>
387   struct CodeToPacketView<Code::PAIRING_RANDOM> {
388     typedef PairingRandomView type;
389   };
390   template <>
391   struct CodeToPacketView<Code::PAIRING_FAILED> {
392     typedef PairingFailedView type;
393   };
394   template <>
395   struct CodeToPacketView<Code::ENCRYPTION_INFORMATION> {
396     typedef EncryptionInformationView type;
397   };
398   template <>
399   struct CodeToPacketView<Code::CENTRAL_IDENTIFICATION> {
400     typedef CentralIdentificationView type;
401   };
402   template <>
403   struct CodeToPacketView<Code::IDENTITY_INFORMATION> {
404     typedef IdentityInformationView type;
405   };
406   template <>
407   struct CodeToPacketView<Code::IDENTITY_ADDRESS_INFORMATION> {
408     typedef IdentityAddressInformationView type;
409   };
410   template <>
411   struct CodeToPacketView<Code::SIGNING_INFORMATION> {
412     typedef SigningInformationView type;
413   };
414   template <>
415   struct CodeToPacketView<Code::SECURITY_REQUEST> {
416     typedef SecurityRequestView type;
417   };
418   template <>
419   struct CodeToPacketView<Code::PAIRING_PUBLIC_KEY> {
420     typedef PairingPublicKeyView type;
421   };
422   template <>
423   struct CodeToPacketView<Code::PAIRING_DH_KEY_CHECK> {
424     typedef PairingDhKeyCheckView type;
425   };
426   template <>
427   struct CodeToPacketView<Code::PAIRING_KEYPRESS_NOTIFICATION> {
428     typedef PairingKeypressNotificationView type;
429   };
430 
431   template <Code CODE>
432   std::variant<typename CodeToPacketView<CODE>::type, PairingFailure> WaitPacket() {
433     PairingEvent e = WaitForEvent();
434     switch (e.type) {
435       case PairingEvent::EXIT:
436         return PairingFailure(
437             /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + ", but received EXIT instead");
438 
439       case PairingEvent::HCI_EVENT:
440         return PairingFailure(
441             /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + ", but received HCI_EVENT instead");
442 
443       case PairingEvent::UI:
444         return PairingFailure(
445             /*FROM_HERE,*/ "Was expecting L2CAP Packet " + CodeText(CODE) + ", but received UI instead");
446 
447       case PairingEvent::L2CAP: {
448         auto l2cap_packet = e.l2cap_packet.value();
449         if (!l2cap_packet.IsValid()) {
450           return PairingFailure("Malformed L2CAP packet received!");
451         }
452 
453         const auto& received_code = l2cap_packet.GetCode();
454         if (received_code != CODE) {
455           if (received_code == Code::PAIRING_FAILED) {
456             auto pkt = PairingFailedView::Create(l2cap_packet);
457             if (!pkt.IsValid()) return PairingFailure("Malformed " + CodeText(CODE) + " packet");
458             return PairingFailure(/*FROM_HERE,*/
459                                   "Was expecting " + CodeText(CODE) + ", but received PAIRING_FAILED instead",
460                                   pkt.GetReason());
461           }
462 
463           return PairingFailure(/*FROM_HERE,*/
464                                 "Was expecting " + CodeText(CODE) + ", but received " + CodeText(received_code) +
465                                     " instead",
466                                 received_code);
467         }
468 
469         auto pkt = CodeToPacketView<CODE>::type::Create(l2cap_packet);
470         if (!pkt.IsValid()) return PairingFailure("Malformed " + CodeText(CODE) + " packet");
471         return pkt;
472       }
473     }
474   }
475 
476   auto WaitPairingRequest() {
477     return WaitPacket<Code::PAIRING_REQUEST>();
478   }
479 
480   auto WaitPairingResponse() {
481     return WaitPacket<Code::PAIRING_RESPONSE>();
482   }
483 
484   std::variant<bluetooth::security::PairingConfirmView, bluetooth::security::PairingFailure> WaitPairingConfirm() {
485     if (cached_pariring_confirm_view) {
486       PairingConfirmView pkt = *cached_pariring_confirm_view;
487       cached_pariring_confirm_view.release();
488       return pkt;
489     }
490     return WaitPacket<Code::PAIRING_CONFIRM>();
491   }
492 
493   auto WaitPairingRandom() {
494     return WaitPacket<Code::PAIRING_RANDOM>();
495   }
496 
497   auto WaitPairingPublicKey() {
498     return WaitPacket<Code::PAIRING_PUBLIC_KEY>();
499   }
500 
501   auto WaitPairingDHKeyCheck() {
502     return WaitPacket<Code::PAIRING_DH_KEY_CHECK>();
503   }
504 
505   auto WaitEncryptionInformationRequest() {
506     return WaitPacket<Code::ENCRYPTION_INFORMATION>();
507   }
508 
509   auto WaitEncryptionInformation() {
510     return WaitPacket<Code::ENCRYPTION_INFORMATION>();
511   }
512 
513   auto WaitCentralIdentification() {
514     return WaitPacket<Code::CENTRAL_IDENTIFICATION>();
515   }
516 
517   auto WaitIdentityInformation() {
518     return WaitPacket<Code::IDENTITY_INFORMATION>();
519   }
520 
521   auto WaitIdentityAddressInformation() {
522     return WaitPacket<Code::IDENTITY_ADDRESS_INFORMATION>();
523   }
524 
525   auto WaitSigningInformation() {
526     return WaitPacket<Code::SIGNING_INFORMATION>();
527   }
528 
529   /* This is just for test, never use in production code! */
530   void WaitUntilPairingFinished() {
531     thread_.join();
532   }
533 
534  private:
535   std::condition_variable pairing_thread_blocker_;
536 
537   std::mutex queue_guard;
538   std::queue<PairingEvent> queue;
539 
540   std::thread thread_;
541 
542   // holds pairing_confirm, if received out of order
543   std::unique_ptr<PairingConfirmView> cached_pariring_confirm_view;
544 };
545 }  // namespace security
546 }  // namespace bluetooth
547