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