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