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, <k);
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