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