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