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