• 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 #include "security/pairing_handler_le.h"
20 
21 #include "os/rand.h"
22 
23 #include <base/logging.h>
24 
25 using bluetooth::os::GenerateRandom;
26 
27 namespace bluetooth {
28 namespace security {
29 
ExchangePublicKeys(const InitialInformations & i,OobDataFlag remote_have_oob_data)30 std::variant<PairingFailure, KeyExchangeResult> PairingHandlerLe::ExchangePublicKeys(const InitialInformations& i,
31                                                                                      OobDataFlag remote_have_oob_data) {
32   // Generate ECDH, or use one that was used for OOB data
33   const auto [private_key, public_key] = (remote_have_oob_data == OobDataFlag::NOT_PRESENT || !i.my_oob_data)
34                                              ? GenerateECDHKeyPair()
35                                              : std::make_pair(i.my_oob_data->private_key, i.my_oob_data->public_key);
36 
37   LOG_INFO("Public key exchange start");
38   std::unique_ptr<PairingPublicKeyBuilder> myPublicKey = PairingPublicKeyBuilder::Create(public_key.x, public_key.y);
39 
40   if (!ValidateECDHPoint(public_key)) {
41     LOG_ERROR("Can't validate my own public key!!!");
42     return PairingFailure("Can't validate my own public key");
43   }
44 
45   if (IAmCentral(i)) {
46     // Send pairing public key
47     LOG_INFO("Central sends out public key");
48     SendL2capPacket(i, std::move(myPublicKey));
49   }
50 
51   LOG_INFO(" Waiting for Public key...");
52   auto response = WaitPairingPublicKey();
53   LOG_INFO(" Received public key");
54   if (std::holds_alternative<PairingFailure>(response)) {
55     return std::get<PairingFailure>(response);
56   }
57 
58   EcdhPublicKey remote_public_key;
59   auto ppkv = std::get<PairingPublicKeyView>(response);
60   remote_public_key.x = ppkv.GetPublicKeyX();
61   remote_public_key.y = ppkv.GetPublicKeyY();
62   LOG_INFO("Received Public key from remote");
63 
64   if (public_key.x == remote_public_key.x) {
65     LOG_INFO("Remote and local public keys can't match");
66     return PairingFailure("Remote and local public keys match");
67   }
68 
69   // validate received public key
70   if (!ValidateECDHPoint(remote_public_key)) {
71     // TODO: Spec is unclear what should happend when the point is not on
72     // the correct curve: A device that detects an invalid public key from
73     // the peer at any point during the LE Secure Connections pairing
74     // process shall not use the resulting LTK, if any.
75     LOG_INFO("Can't validate remote public key");
76     return PairingFailure("Can't validate remote public key");
77   }
78 
79   if (!IAmCentral(i)) {
80     LOG_INFO("Peripheral sends out public key");
81     // Send pairing public key
82     SendL2capPacket(i, std::move(myPublicKey));
83   }
84 
85   LOG_INFO("Public key exchange finish");
86 
87   std::array<uint8_t, 32> dhkey = ComputeDHKey(private_key, remote_public_key);
88 
89   const EcdhPublicKey& PKa = IAmCentral(i) ? public_key : remote_public_key;
90   const EcdhPublicKey& PKb = IAmCentral(i) ? remote_public_key : public_key;
91 
92   return KeyExchangeResult{PKa, PKb, dhkey};
93 }
94 
DoSecureConnectionsStage1(const InitialInformations & i,const EcdhPublicKey & PKa,const EcdhPublicKey & PKb,const PairingRequestView & pairing_request,const PairingResponseView & pairing_response)95 Stage1ResultOrFailure PairingHandlerLe::DoSecureConnectionsStage1(const InitialInformations& i,
96                                                                   const EcdhPublicKey& PKa, const EcdhPublicKey& PKb,
97                                                                   const PairingRequestView& pairing_request,
98                                                                   const PairingResponseView& pairing_response) {
99   if (((pairing_request.GetAuthReq() & AuthReqMaskMitm) == 0) &&
100       ((pairing_response.GetAuthReq() & AuthReqMaskMitm) == 0)) {
101     // If both devices have not set MITM option, Just Works shall be used
102     return SecureConnectionsJustWorks(i, PKa, PKb);
103   }
104 
105   if (pairing_request.GetOobDataFlag() == OobDataFlag::PRESENT ||
106       pairing_response.GetOobDataFlag() == OobDataFlag::PRESENT) {
107     OobDataFlag remote_oob_flag = IAmCentral(i) ? pairing_response.GetOobDataFlag() : pairing_request.GetOobDataFlag();
108     OobDataFlag my_oob_flag = IAmCentral(i) ? pairing_request.GetOobDataFlag() : pairing_response.GetOobDataFlag();
109     return SecureConnectionsOutOfBand(i, PKa, PKb, my_oob_flag, remote_oob_flag);
110   }
111 
112   const auto& iom = pairing_request.GetIoCapability();
113   const auto& ios = pairing_response.GetIoCapability();
114 
115   if ((iom == IoCapability::KEYBOARD_DISPLAY || iom == IoCapability::DISPLAY_YES_NO) &&
116       (ios == IoCapability::KEYBOARD_DISPLAY || ios == IoCapability::DISPLAY_YES_NO)) {
117     return SecureConnectionsNumericComparison(i, PKa, PKb);
118   }
119 
120   if (iom == IoCapability::NO_INPUT_NO_OUTPUT || ios == IoCapability::NO_INPUT_NO_OUTPUT) {
121     return SecureConnectionsJustWorks(i, PKa, PKb);
122   }
123 
124   if ((iom == IoCapability::DISPLAY_ONLY || iom == IoCapability::DISPLAY_YES_NO) &&
125       (ios == IoCapability::DISPLAY_ONLY || ios == IoCapability::DISPLAY_YES_NO)) {
126     return SecureConnectionsJustWorks(i, PKa, PKb);
127   }
128 
129   IoCapability my_iocaps = IAmCentral(i) ? iom : ios;
130   IoCapability remote_iocaps = IAmCentral(i) ? ios : iom;
131   return SecureConnectionsPasskeyEntry(i, PKa, PKb, my_iocaps, remote_iocaps);
132 }
133 
DoSecureConnectionsStage2(const InitialInformations & i,const EcdhPublicKey & PKa,const EcdhPublicKey & PKb,const PairingRequestView & pairing_request,const PairingResponseView & pairing_response,const Stage1Result stage1result,const std::array<uint8_t,32> & dhkey)134 Stage2ResultOrFailure PairingHandlerLe::DoSecureConnectionsStage2(const InitialInformations& i,
135                                                                   const EcdhPublicKey& PKa, const EcdhPublicKey& PKb,
136                                                                   const PairingRequestView& pairing_request,
137                                                                   const PairingResponseView& pairing_response,
138                                                                   const Stage1Result stage1result,
139                                                                   const std::array<uint8_t, 32>& dhkey) {
140   LOG_INFO("Authentication stage 2 started");
141 
142   auto [Na, Nb, ra, rb] = stage1result;
143 
144   // 2.3.5.6.5 Authentication stage 2 long term key calculation
145   uint8_t a[7];
146   uint8_t b[7];
147 
148   if (IAmCentral(i)) {
149     memcpy(a, i.my_connection_address.GetAddress().data(), hci::Address::kLength);
150     a[6] = (uint8_t)i.my_connection_address.GetAddressType();
151     memcpy(b, i.remote_connection_address.GetAddress().data(), hci::Address::kLength);
152     b[6] = (uint8_t)i.remote_connection_address.GetAddressType();
153   } else {
154     memcpy(a, i.remote_connection_address.GetAddress().data(), hci::Address::kLength);
155     a[6] = (uint8_t)i.remote_connection_address.GetAddressType();
156     memcpy(b, i.my_connection_address.GetAddress().data(), hci::Address::kLength);
157     b[6] = (uint8_t)i.my_connection_address.GetAddressType();
158   }
159 
160   Octet16 ltk, mac_key;
161   crypto_toolbox::f5((uint8_t*)dhkey.data(), Na, Nb, a, b, &mac_key, &ltk);
162 
163   // DHKey exchange and check
164 
165   std::array<uint8_t, 3> iocapA{static_cast<uint8_t>(pairing_request.GetIoCapability()),
166                                 static_cast<uint8_t>(pairing_request.GetOobDataFlag()), pairing_request.GetAuthReq()};
167   std::array<uint8_t, 3> iocapB{static_cast<uint8_t>(pairing_response.GetIoCapability()),
168                                 static_cast<uint8_t>(pairing_response.GetOobDataFlag()), pairing_response.GetAuthReq()};
169 
170   // LOG(INFO) << +(IAmCentral(i)) << " LTK = " << base::HexEncode(ltk.data(), ltk.size());
171   // LOG(INFO) << +(IAmCentral(i)) << " MAC_KEY = " << base::HexEncode(mac_key.data(), mac_key.size());
172   // LOG(INFO) << +(IAmCentral(i)) << " Na = " << base::HexEncode(Na.data(), Na.size());
173   // LOG(INFO) << +(IAmCentral(i)) << " Nb = " << base::HexEncode(Nb.data(), Nb.size());
174   // LOG(INFO) << +(IAmCentral(i)) << " ra = " << base::HexEncode(ra.data(), ra.size());
175   // LOG(INFO) << +(IAmCentral(i)) << " rb = " << base::HexEncode(rb.data(), rb.size());
176   // LOG(INFO) << +(IAmCentral(i)) << " iocapA = " << base::HexEncode(iocapA.data(), iocapA.size());
177   // LOG(INFO) << +(IAmCentral(i)) << " iocapB = " << base::HexEncode(iocapB.data(), iocapB.size());
178   // LOG(INFO) << +(IAmCentral(i)) << " a = " << base::HexEncode(a, 7);
179   // LOG(INFO) << +(IAmCentral(i)) << " b = " << base::HexEncode(b, 7);
180 
181   Octet16 Ea = crypto_toolbox::f6(mac_key, Na, Nb, rb, iocapA.data(), a, b);
182 
183   Octet16 Eb = crypto_toolbox::f6(mac_key, Nb, Na, ra, iocapB.data(), b, a);
184 
185   if (IAmCentral(i)) {
186     // send Pairing DHKey Check
187     SendL2capPacket(i, PairingDhKeyCheckBuilder::Create(Ea));
188 
189     auto response = WaitPairingDHKeyCheck();
190     if (std::holds_alternative<PairingFailure>(response)) {
191       return std::get<PairingFailure>(response);
192     }
193 
194     if (std::get<PairingDhKeyCheckView>(response).GetDhKeyCheck() != Eb) {
195       LOG_INFO("Ea != Eb, aborting!");
196       SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::DHKEY_CHECK_FAILED));
197       return PairingFailure("Ea != Eb");
198     }
199   } else {
200     auto response = WaitPairingDHKeyCheck();
201     if (std::holds_alternative<PairingFailure>(response)) {
202       return std::get<PairingFailure>(response);
203     }
204 
205     if (std::get<PairingDhKeyCheckView>(response).GetDhKeyCheck() != Ea) {
206       LOG_INFO("Ea != Eb, aborting!");
207       SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::DHKEY_CHECK_FAILED));
208       return PairingFailure("Ea != Eb");
209     }
210 
211     // send Pairing DHKey Check
212     SendL2capPacket(i, PairingDhKeyCheckBuilder::Create(Eb));
213   }
214 
215   LOG_INFO("Authentication stage 2 (DHKey checks) finished");
216   return ltk;
217 }
218 
SecureConnectionsOutOfBand(const InitialInformations & i,const EcdhPublicKey & Pka,const EcdhPublicKey & Pkb,OobDataFlag my_oob_flag,OobDataFlag remote_oob_flag)219 Stage1ResultOrFailure PairingHandlerLe::SecureConnectionsOutOfBand(const InitialInformations& i,
220                                                                    const EcdhPublicKey& Pka, const EcdhPublicKey& Pkb,
221                                                                    OobDataFlag my_oob_flag,
222                                                                    OobDataFlag remote_oob_flag) {
223   LOG_INFO("Out Of Band start");
224 
225   Octet16 zeros{0};
226   Octet16 localR = (remote_oob_flag == OobDataFlag::PRESENT && i.my_oob_data) ? i.my_oob_data->r : zeros;
227   Octet16 remoteR;
228 
229   if (my_oob_flag == OobDataFlag::NOT_PRESENT || (my_oob_flag == OobDataFlag::PRESENT && !i.remote_oob_data)) {
230     /* we have send the OOB data, but not received them. remote will check if
231      * C value is correct */
232     remoteR = zeros;
233   } else {
234     remoteR = i.remote_oob_data->le_sc_r;
235     Octet16 remoteC = i.remote_oob_data->le_sc_c;
236 
237     Octet16 remoteC2;
238     if (IAmCentral(i)) {
239       remoteC2 = crypto_toolbox::f4((uint8_t*)Pkb.x.data(), (uint8_t*)Pkb.x.data(), remoteR, 0);
240     } else {
241       remoteC2 = crypto_toolbox::f4((uint8_t*)Pka.x.data(), (uint8_t*)Pka.x.data(), remoteR, 0);
242     }
243 
244     if (remoteC2 != remoteC) {
245       LOG_ERROR("C_computed != C_from_remote, aborting!");
246       return PairingFailure("C_computed != C_from_remote, aborting");
247     }
248   }
249 
250   Octet16 Na, Nb, ra, rb;
251   if (IAmCentral(i)) {
252     ra = localR;
253     rb = remoteR;
254     Na = GenerateRandom<16>();
255     // Send Pairing Random
256     SendL2capPacket(i, PairingRandomBuilder::Create(Na));
257 
258     LOG_INFO("Central waits for Nb");
259     auto random = WaitPairingRandom();
260     if (std::holds_alternative<PairingFailure>(random)) {
261       return std::get<PairingFailure>(random);
262     }
263     Nb = std::get<PairingRandomView>(random).GetRandomValue();
264   } else {
265     ra = remoteR;
266     rb = localR;
267     Nb = GenerateRandom<16>();
268 
269     LOG_INFO("Peripheral waits for random");
270     auto random = WaitPairingRandom();
271     if (std::holds_alternative<PairingFailure>(random)) {
272       return std::get<PairingFailure>(random);
273     }
274     Na = std::get<PairingRandomView>(random).GetRandomValue();
275 
276     SendL2capPacket(i, PairingRandomBuilder::Create(Nb));
277   }
278 
279   return Stage1Result{Na, Nb, ra, rb};
280 }
281 
SecureConnectionsPasskeyEntry(const InitialInformations & i,const EcdhPublicKey & PKa,const EcdhPublicKey & PKb,IoCapability my_iocaps,IoCapability remote_iocaps)282 Stage1ResultOrFailure PairingHandlerLe::SecureConnectionsPasskeyEntry(const InitialInformations& i,
283                                                                       const EcdhPublicKey& PKa,
284                                                                       const EcdhPublicKey& PKb, IoCapability my_iocaps,
285                                                                       IoCapability remote_iocaps) {
286   LOG_INFO("Passkey Entry start");
287   Octet16 Na, Nb, ra{0}, rb{0};
288 
289   uint32_t passkey;
290 
291   if (my_iocaps == IoCapability::DISPLAY_ONLY || remote_iocaps == IoCapability::KEYBOARD_ONLY) {
292     // I display
293     passkey = GenerateRandom();
294     passkey &= 0x0fffff; /* maximum 20 significant bytes */
295     constexpr uint32_t PASSKEY_MAX = 999999;
296     while (passkey > PASSKEY_MAX) passkey >>= 1;
297 
298     ConfirmationData data(i.remote_connection_address, i.remote_name, passkey);
299     i.user_interface_handler->Post(common::BindOnce(&UI::DisplayPasskey, common::Unretained(i.user_interface), data));
300 
301   } else if (my_iocaps == IoCapability::KEYBOARD_ONLY || remote_iocaps == IoCapability::DISPLAY_ONLY) {
302     ConfirmationData data(i.remote_connection_address, i.remote_name);
303     i.user_interface_handler->Post(
304         common::BindOnce(&UI::DisplayEnterPasskeyDialog, common::Unretained(i.user_interface), data));
305     std::optional<PairingEvent> response = WaitUiPasskey();
306     if (!response) return PairingFailure("Passkey did not arrive!");
307 
308     passkey = response->ui_value;
309 
310     /*TODO: shall we send "Keypress Notification" after each key ? This would
311      * have impact on the SMP timeout*/
312 
313   } else {
314     LOG(FATAL) << "THIS SHOULD NEVER HAPPEN";
315     return PairingFailure("FATAL!");
316   }
317 
318   uint32_t bitmask = 0x01;
319   for (int loop = 0; loop < 20; loop++, bitmask <<= 1) {
320     LOG_INFO("Iteration no %d", loop);
321     bool bit_set = ((bitmask & passkey) != 0);
322     uint8_t ri = bit_set ? 0x81 : 0x80;
323 
324     Octet16 Cai, Cbi, Nai, Nbi;
325     if (IAmCentral(i)) {
326       Nai = GenerateRandom<16>();
327 
328       Cai = crypto_toolbox::f4((uint8_t*)PKa.x.data(), (uint8_t*)PKb.x.data(), Nai, ri);
329 
330       // Send Pairing Confirm
331       LOG_INFO("Central sends Cai");
332       SendL2capPacket(i, PairingConfirmBuilder::Create(Cai));
333 
334       LOG_INFO("Central waits for the Cbi");
335       auto confirm = WaitPairingConfirm();
336       if (std::holds_alternative<PairingFailure>(confirm)) {
337         return std::get<PairingFailure>(confirm);
338       }
339       Cbi = std::get<PairingConfirmView>(confirm).GetConfirmValue();
340 
341       // Send Pairing Random
342       SendL2capPacket(i, PairingRandomBuilder::Create(Nai));
343 
344       LOG_INFO("Central waits for Nbi");
345       auto random = WaitPairingRandom();
346       if (std::holds_alternative<PairingFailure>(random)) {
347         return std::get<PairingFailure>(random);
348       }
349       Nbi = std::get<PairingRandomView>(random).GetRandomValue();
350 
351       Octet16 Cbi2 = crypto_toolbox::f4((uint8_t*)PKb.x.data(), (uint8_t*)PKa.x.data(), Nbi, ri);
352       if (Cbi != Cbi2) {
353         LOG_INFO("Cai != Cbi, aborting!");
354         SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED));
355         return PairingFailure("Cai != Cbi");
356       }
357     } else {
358       Nbi = GenerateRandom<16>();
359       // Compute confirm
360       Cbi = crypto_toolbox::f4((uint8_t*)PKb.x.data(), (uint8_t*)PKa.x.data(), Nbi, ri);
361 
362       LOG_INFO("Peripheral waits for the Cai");
363       auto confirm = WaitPairingConfirm();
364       if (std::holds_alternative<PairingFailure>(confirm)) {
365         return std::get<PairingFailure>(confirm);
366       }
367       Cai = std::get<PairingConfirmView>(confirm).GetConfirmValue();
368 
369       // Send Pairing Confirm
370       LOG_INFO("Peripheral sends confirmation");
371       SendL2capPacket(i, PairingConfirmBuilder::Create(Cbi));
372 
373       LOG_INFO("Peripheral waits for random");
374       auto random = WaitPairingRandom();
375       if (std::holds_alternative<PairingFailure>(random)) {
376         return std::get<PairingFailure>(random);
377       }
378       Nai = std::get<PairingRandomView>(random).GetRandomValue();
379 
380       Octet16 Cai2 = crypto_toolbox::f4((uint8_t*)PKa.x.data(), (uint8_t*)PKb.x.data(), Nai, ri);
381       if (Cai != Cai2) {
382         LOG_INFO("Cai != Cai2, aborting!");
383         SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED));
384         return PairingFailure("Cai != Cai2");
385       }
386 
387       // Send Pairing Random
388       SendL2capPacket(i, PairingRandomBuilder::Create(Nbi));
389     }
390 
391     if (loop == 19) {
392       Na = Nai;
393       Nb = Nbi;
394     }
395   }
396 
397   ra[0] = (uint8_t)(passkey);
398   ra[1] = (uint8_t)(passkey >> 8);
399   ra[2] = (uint8_t)(passkey >> 16);
400   ra[3] = (uint8_t)(passkey >> 24);
401   rb = ra;
402 
403   return Stage1Result{Na, Nb, ra, rb};
404 }
405 
SecureConnectionsNumericComparison(const InitialInformations & i,const EcdhPublicKey & PKa,const EcdhPublicKey & PKb)406 Stage1ResultOrFailure PairingHandlerLe::SecureConnectionsNumericComparison(const InitialInformations& i,
407                                                                            const EcdhPublicKey& PKa,
408                                                                            const EcdhPublicKey& PKb) {
409   LOG_INFO("Numeric Comparison start");
410   Stage1ResultOrFailure result = SecureConnectionsJustWorks(i, PKa, PKb);
411   if (std::holds_alternative<PairingFailure>(result)) {
412     return std::get<PairingFailure>(result);
413   }
414 
415   const auto [Na, Nb, ra, rb] = std::get<Stage1Result>(result);
416 
417   uint32_t number_to_display = crypto_toolbox::g2((uint8_t*)PKa.x.data(), (uint8_t*)PKb.x.data(), Na, Nb);
418 
419   ConfirmationData data(i.remote_connection_address, i.remote_name, number_to_display);
420   i.user_interface_handler->Post(
421       common::BindOnce(&UI::DisplayConfirmValue, common::Unretained(i.user_interface), data));
422 
423   std::optional<PairingEvent> confirmyesno = WaitUiConfirmYesNo();
424   if (!confirmyesno || confirmyesno->ui_value == 0) {
425     LOG_INFO("Was expecting the user value confirm");
426     return PairingFailure("Was expecting the user value confirm");
427   }
428 
429   return result;
430 }
431 
SecureConnectionsJustWorks(const InitialInformations & i,const EcdhPublicKey & PKa,const EcdhPublicKey & PKb)432 Stage1ResultOrFailure PairingHandlerLe::SecureConnectionsJustWorks(const InitialInformations& i,
433                                                                    const EcdhPublicKey& PKa, const EcdhPublicKey& PKb) {
434   Octet16 Cb, Na, Nb, ra, rb;
435 
436   ra = rb = {0};
437 
438   if (IAmCentral(i)) {
439     Na = GenerateRandom<16>();
440     LOG_INFO("Central waits for confirmation");
441     auto confirm = WaitPairingConfirm();
442     if (std::holds_alternative<PairingFailure>(confirm)) {
443       return std::get<PairingFailure>(confirm);
444     }
445     Cb = std::get<PairingConfirmView>(confirm).GetConfirmValue();
446 
447     // Send Pairing Random
448     SendL2capPacket(i, PairingRandomBuilder::Create(Na));
449 
450     LOG_INFO("Central waits for Random");
451     auto random = WaitPairingRandom();
452     if (std::holds_alternative<PairingFailure>(random)) {
453       return std::get<PairingFailure>(random);
454     }
455     Nb = std::get<PairingRandomView>(random).GetRandomValue();
456 
457     // Compute Cb locally
458     Octet16 Cb_local = crypto_toolbox::f4((uint8_t*)PKb.x.data(), (uint8_t*)PKa.x.data(), Nb, 0);
459 
460     if (Cb_local != Cb) {
461       LOG_INFO("Cb_local != Cb, aborting!");
462       SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED));
463       return PairingFailure("Cb_local != Cb");
464     }
465   } else {
466     Nb = GenerateRandom<16>();
467     // Compute confirm
468     Cb = crypto_toolbox::f4((uint8_t*)PKb.x.data(), (uint8_t*)PKa.x.data(), Nb, 0);
469 
470     // Send Pairing Confirm
471     LOG_INFO("Peripheral sends confirmation");
472     SendL2capPacket(i, PairingConfirmBuilder::Create(Cb));
473 
474     LOG_INFO("Peripheral waits for random");
475     auto random = WaitPairingRandom();
476     if (std::holds_alternative<PairingFailure>(random)) {
477       return std::get<PairingFailure>(random);
478     }
479     Na = std::get<PairingRandomView>(random).GetRandomValue();
480 
481     // Send Pairing Random
482     SendL2capPacket(i, PairingRandomBuilder::Create(Nb));
483   }
484 
485   return Stage1Result{Na, Nb, ra, rb};
486 }
487 
488 }  // namespace security
489 }  // namespace bluetooth
490