1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_bluetooth_sapphire/internal/host/sm/util.h"
16
17 #include <array>
18 #include <cstdint>
19
20 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/device_address.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/uint128.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/uint256.h"
24 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
25 #include "pw_bluetooth_sapphire/internal/host/sm/error.h"
26 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
27 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
28 #include "pw_unit_test/framework.h"
29
30 // inclusive-language: disable
31
32 namespace bt::sm::util {
33 namespace {
34
TEST(UtilTest,ConvertSmIoCapabilityToHci)35 TEST(UtilTest, ConvertSmIoCapabilityToHci) {
36 EXPECT_EQ(pw::bluetooth::emboss::IoCapability::DISPLAY_ONLY,
37 IOCapabilityForHci(IOCapability::kDisplayOnly));
38 EXPECT_EQ(pw::bluetooth::emboss::IoCapability::DISPLAY_YES_NO,
39 IOCapabilityForHci(IOCapability::kDisplayYesNo));
40 EXPECT_EQ(pw::bluetooth::emboss::IoCapability::KEYBOARD_ONLY,
41 IOCapabilityForHci(IOCapability::kKeyboardOnly));
42 EXPECT_EQ(pw::bluetooth::emboss::IoCapability::NO_INPUT_NO_OUTPUT,
43 IOCapabilityForHci(IOCapability::kNoInputNoOutput));
44 EXPECT_EQ(pw::bluetooth::emboss::IoCapability::DISPLAY_YES_NO,
45 IOCapabilityForHci(IOCapability::kKeyboardDisplay));
46
47 // Test remaining invalid values for sm::IOCapability.
48 for (int i = 0x05; i < 0xff; i++) {
49 EXPECT_EQ(pw::bluetooth::emboss::IoCapability::NO_INPUT_NO_OUTPUT,
50 IOCapabilityForHci(static_cast<IOCapability>(i)));
51 }
52 }
53
TEST(UtilTest,MapToRolesCorrectly)54 TEST(UtilTest, MapToRolesCorrectly) {
55 UInt128 local_val = {1}, peer_val = {2};
56 auto [initiator_val, responder_val] =
57 MapToRoles(local_val, peer_val, Role::kInitiator);
58 EXPECT_EQ(local_val, initiator_val);
59 EXPECT_EQ(peer_val, responder_val);
60
61 std::tie(initiator_val, responder_val) =
62 MapToRoles(local_val, peer_val, Role::kResponder);
63 EXPECT_EQ(local_val, responder_val);
64 EXPECT_EQ(peer_val, initiator_val);
65 }
66
TEST(UtilTest,SelectPairingMethodOOB)67 TEST(UtilTest, SelectPairingMethodOOB) {
68 // In SC OOB is selected if either device has OOB data.
69 EXPECT_EQ(PairingMethod::kOutOfBand,
70 SelectPairingMethod(/*secure_connections=*/true,
71 /*local_oob=*/true,
72 /*peer_oob=*/false,
73 /*mitm_required=*/true,
74 /*local_ioc=*/IOCapability::kKeyboardDisplay,
75 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
76 /*local_initiator=*/true));
77 EXPECT_EQ(PairingMethod::kOutOfBand,
78 SelectPairingMethod(/*secure_connections=*/true,
79 /*local_oob=*/false,
80 /*peer_oob=*/true,
81 /*mitm_required=*/true,
82 /*local_ioc=*/IOCapability::kKeyboardDisplay,
83 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
84 /*local_initiator=*/true));
85 EXPECT_NE(PairingMethod::kOutOfBand,
86 SelectPairingMethod(/*secure_connections=*/true,
87 /*local_oob=*/false,
88 /*peer_oob=*/false,
89 /*mitm_required=*/true,
90 /*local_ioc=*/IOCapability::kKeyboardDisplay,
91 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
92 /*local_initiator=*/true));
93
94 // In legacy OOB is selected if both devices have OOB data.
95 EXPECT_EQ(PairingMethod::kOutOfBand,
96 SelectPairingMethod(/*secure_connections=*/false,
97 /*local_oob=*/true,
98 /*peer_oob=*/true,
99 /*mitm_required=*/true,
100 /*local_ioc=*/IOCapability::kKeyboardDisplay,
101 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
102 /*local_initiator=*/true));
103 EXPECT_NE(PairingMethod::kOutOfBand,
104 SelectPairingMethod(/*secure_connections=*/false,
105 /*local_oob=*/false,
106 /*peer_oob=*/true,
107 /*mitm_required=*/true,
108 /*local_ioc=*/IOCapability::kKeyboardDisplay,
109 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
110 /*local_initiator=*/true));
111 EXPECT_NE(PairingMethod::kOutOfBand,
112 SelectPairingMethod(/*secure_connections=*/false,
113 /*local_oob=*/true,
114 /*peer_oob=*/false,
115 /*mitm_required=*/true,
116 /*local_ioc=*/IOCapability::kKeyboardDisplay,
117 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
118 /*local_initiator=*/true));
119 EXPECT_NE(PairingMethod::kOutOfBand,
120 SelectPairingMethod(/*secure_connections=*/false,
121 /*local_oob=*/false,
122 /*peer_oob=*/false,
123 /*mitm_required=*/true,
124 /*local_ioc=*/IOCapability::kKeyboardDisplay,
125 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
126 /*local_initiator=*/true));
127 }
128
TEST(UtilTest,SelectPairingMethodNoMITM)129 TEST(UtilTest, SelectPairingMethodNoMITM) {
130 // The pairing method should be "Just Works" if neither device requires MITM
131 // protection, regardless of other parameters.
132 EXPECT_EQ(PairingMethod::kJustWorks,
133 SelectPairingMethod(/*secure_connections=*/true,
134 /*local_oob=*/false,
135 /*peer_oob=*/false,
136 /*mitm_required=*/false,
137 /*local_ioc=*/IOCapability::kKeyboardDisplay,
138 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
139 /*local_initiator=*/true));
140
141 // Shouldn't default to "Just Works" if at least one device requires MITM
142 // protection.
143 EXPECT_NE(PairingMethod::kJustWorks,
144 SelectPairingMethod(/*secure_connections=*/false,
145 /*local_oob=*/false,
146 /*peer_oob=*/false,
147 /*mitm_required=*/true,
148 /*local_ioc=*/IOCapability::kKeyboardDisplay,
149 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
150 /*local_initiator=*/true));
151 }
152
153 // Tests all combinations that result in the "Just Works" pairing method.
TEST(UtilTest,SelectPairingMethodJustWorks)154 TEST(UtilTest, SelectPairingMethodJustWorks) {
155 // Local: DisplayOnly
156 EXPECT_EQ(PairingMethod::kJustWorks,
157 SelectPairingMethod(/*secure_connections=*/true,
158 /*local_oob=*/false,
159 /*peer_oob=*/false,
160 /*mitm_required=*/true,
161 /*local_ioc=*/IOCapability::kDisplayOnly,
162 /*peer_ioc=*/IOCapability::kDisplayOnly,
163 /*local_initiator=*/true));
164 EXPECT_EQ(PairingMethod::kJustWorks,
165 SelectPairingMethod(/*secure_connections=*/true,
166 /*local_oob=*/false,
167 /*peer_oob=*/false,
168 /*mitm_required=*/true,
169 /*local_ioc=*/IOCapability::kDisplayOnly,
170 /*peer_ioc=*/IOCapability::kDisplayYesNo,
171 /*local_initiator=*/true));
172 EXPECT_EQ(PairingMethod::kJustWorks,
173 SelectPairingMethod(/*secure_connections=*/true,
174 /*local_oob=*/false,
175 /*peer_oob=*/false,
176 /*mitm_required=*/true,
177 /*local_ioc=*/IOCapability::kDisplayOnly,
178 /*peer_ioc=*/IOCapability::kNoInputNoOutput,
179 /*local_initiator=*/true));
180
181 // Local: DisplayYesNo
182 EXPECT_EQ(PairingMethod::kJustWorks,
183 SelectPairingMethod(/*secure_connections=*/true,
184 /*local_oob=*/false,
185 /*peer_oob=*/false,
186 /*mitm_required=*/true,
187 /*local_ioc=*/IOCapability::kDisplayYesNo,
188 /*peer_ioc=*/IOCapability::kDisplayOnly,
189 /*local_initiator=*/true));
190 // If both devices are DisplayYesNo, then "Just Works" is selected for LE
191 // legacy pairing (i.e. at least one device doesn't support Secure
192 // Connections).
193 EXPECT_EQ(PairingMethod::kJustWorks,
194 SelectPairingMethod(/*secure_connections=*/false,
195 /*local_oob=*/false,
196 /*peer_oob=*/false,
197 /*mitm_required=*/true,
198 /*local_ioc=*/IOCapability::kDisplayYesNo,
199 /*peer_ioc=*/IOCapability::kDisplayYesNo,
200 /*local_initiator=*/true));
201 EXPECT_EQ(PairingMethod::kJustWorks,
202 SelectPairingMethod(/*secure_connections=*/true,
203 /*local_oob=*/false,
204 /*peer_oob=*/false,
205 /*mitm_required=*/true,
206 /*local_ioc=*/IOCapability::kDisplayYesNo,
207 /*peer_ioc=*/IOCapability::kNoInputNoOutput,
208 /*local_initiator=*/true));
209
210 // Local: KeyboardOnly
211 EXPECT_EQ(PairingMethod::kJustWorks,
212 SelectPairingMethod(/*secure_connections=*/true,
213 /*local_oob=*/false,
214 /*peer_oob=*/false,
215 /*mitm_required=*/true,
216 /*local_ioc=*/IOCapability::kKeyboardOnly,
217 /*peer_ioc=*/IOCapability::kNoInputNoOutput,
218 /*local_initiator=*/true));
219
220 // Local: NoInputNoOutput. Always "Just Works".
221 EXPECT_EQ(PairingMethod::kJustWorks,
222 SelectPairingMethod(/*secure_connections=*/true,
223 /*local_oob=*/false,
224 /*peer_oob=*/false,
225 /*mitm_required=*/true,
226 /*local_ioc=*/IOCapability::kNoInputNoOutput,
227 /*peer_ioc=*/IOCapability::kDisplayOnly,
228 /*local_initiator=*/true));
229 EXPECT_EQ(PairingMethod::kJustWorks,
230 SelectPairingMethod(/*secure_connections=*/true,
231 /*local_oob=*/false,
232 /*peer_oob=*/false,
233 /*mitm_required=*/true,
234 /*local_ioc=*/IOCapability::kNoInputNoOutput,
235 /*peer_ioc=*/IOCapability::kDisplayYesNo,
236 /*local_initiator=*/true));
237 EXPECT_EQ(PairingMethod::kJustWorks,
238 SelectPairingMethod(/*secure_connections=*/true,
239 /*local_oob=*/false,
240 /*peer_oob=*/false,
241 /*mitm_required=*/true,
242 /*local_ioc=*/IOCapability::kNoInputNoOutput,
243 /*peer_ioc=*/IOCapability::kKeyboardOnly,
244 /*local_initiator=*/true));
245 EXPECT_EQ(PairingMethod::kJustWorks,
246 SelectPairingMethod(/*secure_connections=*/true,
247 /*local_oob=*/false,
248 /*peer_oob=*/false,
249 /*mitm_required=*/true,
250 /*local_ioc=*/IOCapability::kNoInputNoOutput,
251 /*peer_ioc=*/IOCapability::kNoInputNoOutput,
252 /*local_initiator=*/true));
253 EXPECT_EQ(PairingMethod::kJustWorks,
254 SelectPairingMethod(/*secure_connections=*/true,
255 /*local_oob=*/false,
256 /*peer_oob=*/false,
257 /*mitm_required=*/true,
258 /*local_ioc=*/IOCapability::kNoInputNoOutput,
259 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
260 /*local_initiator=*/true));
261
262 // Local: KeyboardDisplay
263 EXPECT_EQ(PairingMethod::kJustWorks,
264 SelectPairingMethod(/*secure_connections=*/true,
265 /*local_oob=*/false,
266 /*peer_oob=*/false,
267 /*mitm_required=*/true,
268 /*local_ioc=*/IOCapability::kKeyboardDisplay,
269 /*peer_ioc=*/IOCapability::kNoInputNoOutput,
270 /*local_initiator=*/true));
271 }
272
273 // Tests all combinations that result in the "Passkey Entry (input)" pairing
274 // method.
TEST(UtilTest,SelectPairingMethodPasskeyEntryInput)275 TEST(UtilTest, SelectPairingMethodPasskeyEntryInput) {
276 // Local: KeyboardOnly
277 EXPECT_EQ(PairingMethod::kPasskeyEntryInput,
278 SelectPairingMethod(/*secure_connections=*/true,
279 /*local_oob=*/false,
280 /*peer_oob=*/false,
281 /*mitm_required=*/true,
282 /*local_ioc=*/IOCapability::kKeyboardOnly,
283 /*peer_ioc=*/IOCapability::kDisplayOnly,
284 /*local_initiator=*/true));
285 EXPECT_EQ(PairingMethod::kPasskeyEntryInput,
286 SelectPairingMethod(/*secure_connections=*/true,
287 /*local_oob=*/false,
288 /*peer_oob=*/false,
289 /*mitm_required=*/true,
290 /*local_ioc=*/IOCapability::kKeyboardOnly,
291 /*peer_ioc=*/IOCapability::kDisplayYesNo,
292 /*local_initiator=*/true));
293 EXPECT_EQ(PairingMethod::kPasskeyEntryInput,
294 SelectPairingMethod(/*secure_connections=*/true,
295 /*local_oob=*/false,
296 /*peer_oob=*/false,
297 /*mitm_required=*/true,
298 /*local_ioc=*/IOCapability::kKeyboardOnly,
299 /*peer_ioc=*/IOCapability::kKeyboardOnly,
300 /*local_initiator=*/true));
301 EXPECT_EQ(PairingMethod::kPasskeyEntryInput,
302 SelectPairingMethod(/*secure_connections=*/true,
303 /*local_oob=*/false,
304 /*peer_oob=*/false,
305 /*mitm_required=*/true,
306 /*local_ioc=*/IOCapability::kKeyboardOnly,
307 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
308 /*local_initiator=*/true));
309
310 // Local: KeyboardDisplay
311 EXPECT_EQ(PairingMethod::kPasskeyEntryInput,
312 SelectPairingMethod(/*secure_connections=*/true,
313 /*local_oob=*/false,
314 /*peer_oob=*/false,
315 /*mitm_required=*/true,
316 /*local_ioc=*/IOCapability::kKeyboardDisplay,
317 /*peer_ioc=*/IOCapability::kDisplayOnly,
318 /*local_initiator=*/true));
319 EXPECT_EQ(PairingMethod::kPasskeyEntryInput,
320 SelectPairingMethod(/*secure_connections=*/false,
321 /*local_oob=*/false,
322 /*peer_oob=*/false,
323 /*mitm_required=*/true,
324 /*local_ioc=*/IOCapability::kKeyboardDisplay,
325 /*peer_ioc=*/IOCapability::kDisplayYesNo,
326 /*local_initiator=*/true));
327
328 // If both devices have the KeyboardDisplay capability then the responder
329 // inputs.
330 EXPECT_EQ(PairingMethod::kPasskeyEntryInput,
331 SelectPairingMethod(/*secure_connections=*/false,
332 /*local_oob=*/false,
333 /*peer_oob=*/false,
334 /*mitm_required=*/true,
335 /*local_ioc=*/IOCapability::kKeyboardDisplay,
336 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
337 /*local_initiator=*/false));
338 }
339
340 // Tests all combinations that result in the "Passkey Entry (display)" pairing
341 // method.
TEST(UtilTest,SelectPairingMethodPasskeyEntryDisplay)342 TEST(UtilTest, SelectPairingMethodPasskeyEntryDisplay) {
343 // Local: DisplayOnly
344 EXPECT_EQ(PairingMethod::kPasskeyEntryDisplay,
345 SelectPairingMethod(/*secure_connections=*/true,
346 /*local_oob=*/false,
347 /*peer_oob=*/false,
348 /*mitm_required=*/true,
349 /*local_ioc=*/IOCapability::kDisplayOnly,
350 /*peer_ioc=*/IOCapability::kKeyboardOnly,
351 /*local_initiator=*/true));
352 EXPECT_EQ(PairingMethod::kPasskeyEntryDisplay,
353 SelectPairingMethod(/*secure_connections=*/true,
354 /*local_oob=*/false,
355 /*peer_oob=*/false,
356 /*mitm_required=*/true,
357 /*local_ioc=*/IOCapability::kDisplayOnly,
358 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
359 /*local_initiator=*/true));
360
361 // Local: DisplayYesNo
362 EXPECT_EQ(PairingMethod::kPasskeyEntryDisplay,
363 SelectPairingMethod(/*secure_connections=*/true,
364 /*local_oob=*/false,
365 /*peer_oob=*/false,
366 /*mitm_required=*/true,
367 /*local_ioc=*/IOCapability::kDisplayYesNo,
368 /*peer_ioc=*/IOCapability::kKeyboardOnly,
369 /*local_initiator=*/true));
370 // If the peer has a display then use "Passkey Entry" only for LE Legacy
371 // pairing.
372 EXPECT_EQ(PairingMethod::kPasskeyEntryDisplay,
373 SelectPairingMethod(/*secure_connections=*/false,
374 /*local_oob=*/false,
375 /*peer_oob=*/false,
376 /*mitm_required=*/true,
377 /*local_ioc=*/IOCapability::kDisplayYesNo,
378 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
379 /*local_initiator=*/true));
380
381 // Local: KeyboardDisplay
382 EXPECT_EQ(PairingMethod::kPasskeyEntryDisplay,
383 SelectPairingMethod(/*secure_connections=*/true,
384 /*local_oob=*/false,
385 /*peer_oob=*/false,
386 /*mitm_required=*/true,
387 /*local_ioc=*/IOCapability::kKeyboardDisplay,
388 /*peer_ioc=*/IOCapability::kKeyboardOnly,
389 /*local_initiator=*/true));
390
391 // If both devices have the KeyboardDisplay capability then the initiator
392 // displays.
393 EXPECT_EQ(PairingMethod::kPasskeyEntryDisplay,
394 SelectPairingMethod(/*secure_connections=*/false,
395 /*local_oob=*/false,
396 /*peer_oob=*/false,
397 /*mitm_required=*/true,
398 /*local_ioc=*/IOCapability::kKeyboardDisplay,
399 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
400 /*local_initiator=*/true));
401 }
402
403 // Tests all combinations that result in the "Numeric Comparison" pairing
404 // method. This will be selected in certain I/O capability combinations only if
405 // both devices support Secure Connections.
TEST(UtilTest,SelectPairingMethodNumericComparison)406 TEST(UtilTest, SelectPairingMethodNumericComparison) {
407 // Local: DisplayYesNo
408 EXPECT_EQ(PairingMethod::kNumericComparison,
409 SelectPairingMethod(/*secure_connections=*/true,
410 /*local_oob=*/false,
411 /*peer_oob=*/false,
412 /*mitm_required=*/true,
413 /*local_ioc=*/IOCapability::kDisplayYesNo,
414 /*peer_ioc=*/IOCapability::kDisplayYesNo,
415 /*local_initiator=*/true));
416 EXPECT_EQ(PairingMethod::kNumericComparison,
417 SelectPairingMethod(/*secure_connections=*/true,
418 /*local_oob=*/false,
419 /*peer_oob=*/false,
420 /*mitm_required=*/true,
421 /*local_ioc=*/IOCapability::kDisplayYesNo,
422 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
423 /*local_initiator=*/true));
424
425 // Local: KeyboardDisplay
426 EXPECT_EQ(PairingMethod::kNumericComparison,
427 SelectPairingMethod(/*secure_connections=*/true,
428 /*local_oob=*/false,
429 /*peer_oob=*/false,
430 /*mitm_required=*/true,
431 /*local_ioc=*/IOCapability::kKeyboardDisplay,
432 /*peer_ioc=*/IOCapability::kDisplayYesNo,
433 /*local_initiator=*/true));
434 EXPECT_EQ(PairingMethod::kNumericComparison,
435 SelectPairingMethod(/*secure_connections=*/true,
436 /*local_oob=*/false,
437 /*peer_oob=*/false,
438 /*mitm_required=*/true,
439 /*local_ioc=*/IOCapability::kKeyboardDisplay,
440 /*peer_ioc=*/IOCapability::kKeyboardDisplay,
441 /*local_initiator=*/true));
442 }
443
444 // Tests "c1" using the sample data from Vol 3, Part H, 2.2.3.
TEST(UtilTest,C1)445 TEST(UtilTest, C1) {
446 const UInt128 tk{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
447 const UInt128 r{{0xE0,
448 0x2E,
449 0x70,
450 0xC6,
451 0x4E,
452 0x27,
453 0x88,
454 0x63,
455 0x0E,
456 0x6F,
457 0xAD,
458 0x56,
459 0x21,
460 0xD5,
461 0x83,
462 0x57}};
463 const StaticByteBuffer preq(0x01, 0x01, 0x00, 0x00, 0x10, 0x07, 0x07);
464 const StaticByteBuffer pres(0x02, 0x03, 0x00, 0x00, 0x08, 0x00, 0x05);
465 const DeviceAddress initiator_addr(DeviceAddress::Type::kLERandom,
466 {0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1});
467 const DeviceAddress responder_addr(DeviceAddress::Type::kLEPublic,
468 {0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1});
469
470 const UInt128 kExpected{{0x86,
471 0x3B,
472 0xF1,
473 0xBE,
474 0xC5,
475 0x4D,
476 0xA7,
477 0xD2,
478 0xEA,
479 0x88,
480 0x89,
481 0x87,
482 0xEF,
483 0x3F,
484 0x1E,
485 0x1E}};
486
487 UInt128 result;
488 C1(tk, r, preq, pres, initiator_addr, responder_addr, &result);
489 EXPECT_TRUE(ContainersEqual(kExpected, result));
490 }
491
492 // Tests "s1" using the sample data from Vol 3, Part H, 2.2.4.
TEST(UtilTest,S1)493 TEST(UtilTest, S1) {
494 const UInt128 tk{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
495 const UInt128 r1{{0x88,
496 0x77,
497 0x66,
498 0x55,
499 0x44,
500 0x33,
501 0x22,
502 0x11,
503 0x09,
504 0xA0,
505 0xB0,
506 0xC0,
507 0xD0,
508 0xE0,
509 0xF0,
510 0x00}};
511 const UInt128 r2{{0x00,
512 0xFF,
513 0xEE,
514 0xDD,
515 0xCC,
516 0xBB,
517 0xAA,
518 0x99,
519 0x08,
520 0x07,
521 0x06,
522 0x05,
523 0x04,
524 0x03,
525 0x02,
526 0x01}};
527
528 const UInt128 kExpected{{0x62,
529 0xA0,
530 0x6D,
531 0x79,
532 0xAE,
533 0x16,
534 0x42,
535 0x5B,
536 0x9B,
537 0xF4,
538 0xB0,
539 0xE8,
540 0xF0,
541 0xE1,
542 0x1F,
543 0x9A}};
544
545 UInt128 result;
546 S1(tk, r1, r2, &result);
547 EXPECT_TRUE(ContainersEqual(kExpected, result));
548 }
549
550 // Test "ah" using the sample data from Vol 3, Part H, Appendix D.7.
TEST(UtilTest,Ah)551 TEST(UtilTest, Ah) {
552 const UInt128 irk{{0x9B,
553 0x7D,
554 0x39,
555 0x0A,
556 0xA6,
557 0x10,
558 0x10,
559 0x34,
560 0x05,
561 0xAD,
562 0xC8,
563 0x57,
564 0xA3,
565 0x34,
566 0x02,
567 0xEC}};
568 const uint32_t prand = 0x708194;
569 const uint32_t kExpected = 0x0DFBAA;
570
571 EXPECT_EQ(kExpected, Ah(irk, prand));
572 }
573
TEST(UtilTest,IrkCanResolveRpa)574 TEST(UtilTest, IrkCanResolveRpa) {
575 // Using the sample data from Vol 3, Part H, Appendix D.7.
576 const UInt128 kIRK{{0x9B,
577 0x7D,
578 0x39,
579 0x0A,
580 0xA6,
581 0x10,
582 0x10,
583 0x34,
584 0x05,
585 0xAD,
586 0xC8,
587 0x57,
588 0xA3,
589 0x34,
590 0x02,
591 0xEC}};
592 const DeviceAddress kStaticRandom(DeviceAddress::Type::kLERandom,
593 {0xA9, 0xFB, 0x0D, 0x94, 0x81, 0xF0});
594 const DeviceAddress kNonResolvable(DeviceAddress::Type::kLERandom,
595 {0xA9, 0xFB, 0x0D, 0x94, 0x81, 0x00});
596 const DeviceAddress kNonMatchingResolvable(
597 DeviceAddress::Type::kLERandom, {0xA9, 0xFB, 0x0D, 0x94, 0x81, 0x70});
598 const DeviceAddress kMatchingResolvable(DeviceAddress::Type::kLERandom,
599 {0xAA, 0xFB, 0x0D, 0x94, 0x81, 0x70});
600
601 ASSERT_FALSE(kStaticRandom.IsResolvablePrivate());
602 ASSERT_FALSE(kNonResolvable.IsResolvablePrivate());
603 ASSERT_TRUE(kNonMatchingResolvable.IsResolvablePrivate());
604 ASSERT_TRUE(kMatchingResolvable.IsResolvablePrivate());
605
606 EXPECT_FALSE(IrkCanResolveRpa(kIRK, kStaticRandom));
607 EXPECT_FALSE(IrkCanResolveRpa(kIRK, kNonResolvable));
608 EXPECT_FALSE(IrkCanResolveRpa(kIRK, kNonMatchingResolvable));
609 EXPECT_TRUE(IrkCanResolveRpa(kIRK, kMatchingResolvable));
610 }
611
TEST(UtilTest,GenerateRpa)612 TEST(UtilTest, GenerateRpa) {
613 const UInt128 irk{{'s',
614 'o',
615 'm',
616 'e',
617 ' ',
618 'r',
619 'a',
620 'n',
621 'd',
622 'o',
623 'm',
624 ' ',
625 'd',
626 'a',
627 't',
628 'a'}};
629
630 DeviceAddress rpa = GenerateRpa(irk);
631
632 EXPECT_EQ(DeviceAddress::Type::kLERandom, rpa.type());
633 EXPECT_TRUE(rpa.IsResolvablePrivate());
634
635 // It should be possible to resolve the RPA with the IRK used to generate it.
636 EXPECT_TRUE(IrkCanResolveRpa(irk, rpa));
637 }
638
TEST(UtilTest,GenerateRandomAddress)639 TEST(UtilTest, GenerateRandomAddress) {
640 DeviceAddress addr = GenerateRandomAddress(false);
641 EXPECT_EQ(DeviceAddress::Type::kLERandom, addr.type());
642 EXPECT_TRUE(addr.IsNonResolvablePrivate());
643
644 addr = GenerateRandomAddress(true);
645 EXPECT_EQ(DeviceAddress::Type::kLERandom, addr.type());
646 EXPECT_TRUE(addr.IsStaticRandom());
647 }
648
649 // Using the sample data from Vol 3, Part H, Appendix D.1.
TEST(UtilTest,AesCmac)650 TEST(UtilTest, AesCmac) {
651 const UInt128 key{0x3C,
652 0x4F,
653 0xCF,
654 0x09,
655 0x88,
656 0x15,
657 0xF7,
658 0xAB,
659 0xA6,
660 0xD2,
661 0xAE,
662 0x28,
663 0x16,
664 0x15,
665 0x7E,
666 0x2B};
667
668 // D.1.1 Example 1: Len = 0
669 const BufferView kMsg0;
670 const UInt128 kMsg0ExpectedCmac = {0x46,
671 0x67,
672 0x75,
673 0x9B,
674 0x12,
675 0x7D,
676 0xA3,
677 0x7F,
678 0x28,
679 0x37,
680 0x59,
681 0xE9,
682 0x29,
683 0x69,
684 0x1D,
685 0xBB};
686
687 // D.1.2 Example 2: Len = 16
688 const StaticByteBuffer<16> kMsg16{0x2A,
689 0x17,
690 0x93,
691 0x73,
692 0x11,
693 0x7E,
694 0x3D,
695 0xE9,
696 0x96,
697 0x9F,
698 0x40,
699 0x2E,
700 0xE2,
701 0xBE,
702 0xC1,
703 0x6B};
704 const UInt128 kMsg16ExpectedCmac{0x7C,
705 0x28,
706 0x4A,
707 0xD0,
708 0x9D,
709 0xDD,
710 0x9B,
711 0xF7,
712 0x44,
713 0x41,
714 0x4D,
715 0x6B,
716 0xB4,
717 0x16,
718 0x0A,
719 0x07};
720
721 // D.1.3 Example 3: Len = 40
722 const StaticByteBuffer<40> kMsg40{
723 0x11, 0xE4, 0x5C, 0xA3, 0x46, 0x1C, 0xC8, 0x30, 0x51, 0x8E,
724 0xAF, 0x45, 0xAC, 0x6F, 0xB7, 0x9E, 0x9C, 0xAC, 0x03, 0x1E,
725 0x57, 0x8A, 0x2D, 0xAE, 0x2A, 0x17, 0x93, 0x73, 0x11, 0x7E,
726 0x3D, 0xE9, 0x96, 0x9F, 0x40, 0x2E, 0xE2, 0xBE, 0xC1, 0x6B};
727 const UInt128 kMsg40ExpectedCmac{0x27,
728 0xC8,
729 0x97,
730 0x14,
731 0x61,
732 0x32,
733 0xCA,
734 0x30,
735 0x30,
736 0xE6,
737 0x9A,
738 0xDE,
739 0x47,
740 0x67,
741 0xA6,
742 0xDF};
743
744 // D.1.4 Example 4: Len = 64
745 const StaticByteBuffer<64> kMsg64{
746 0x10, 0x37, 0x6C, 0xE6, 0x7B, 0x41, 0x2B, 0xAD, 0x17, 0x9B, 0x4F,
747 0xDF, 0x45, 0x24, 0x9F, 0xF6, 0xEF, 0x52, 0x0A, 0x1A, 0x19, 0xC1,
748 0xFB, 0xE5, 0x11, 0xE4, 0x5C, 0xA3, 0x46, 0x1C, 0xC8, 0x30, 0x51,
749 0x8E, 0xAF, 0x45, 0xAC, 0x6F, 0xB7, 0x9E, 0x9C, 0xAC, 0x03, 0x1E,
750 0x57, 0x8A, 0x2D, 0xAE, 0x2A, 0x17, 0x93, 0x73, 0x11, 0x7E, 0x3D,
751 0xE9, 0x96, 0x9F, 0x40, 0x2E, 0xE2, 0xBE, 0xC1, 0x6B};
752 const UInt128 kMsg64ExpectedCmac{0xFE,
753 0x3C,
754 0x36,
755 0x79,
756 0x17,
757 0x74,
758 0x49,
759 0xFC,
760 0x92,
761 0x9D,
762 0x3B,
763 0x7E,
764 0xBF,
765 0xBE,
766 0xF0,
767 0x51};
768
769 std::optional<UInt128> cmac_output{};
770
771 cmac_output = AesCmac(key, kMsg0);
772 ASSERT_TRUE(cmac_output.has_value());
773 EXPECT_EQ(kMsg0ExpectedCmac, *cmac_output);
774
775 cmac_output = AesCmac(key, kMsg16);
776 ASSERT_TRUE(cmac_output.has_value());
777 EXPECT_EQ(kMsg16ExpectedCmac, *cmac_output);
778
779 cmac_output = AesCmac(key, kMsg40);
780 ASSERT_TRUE(cmac_output.has_value());
781 EXPECT_EQ(kMsg40ExpectedCmac, *cmac_output);
782
783 cmac_output = AesCmac(key, kMsg64);
784 ASSERT_TRUE(cmac_output.has_value());
785 EXPECT_EQ(kMsg64ExpectedCmac, *cmac_output);
786 }
787
788 // Using the sample data from Vol 3, Part H, Appendix D.2.
TEST(UtilTest,F4)789 TEST(UtilTest, F4) {
790 const UInt256 kU{0xE6, 0x9D, 0x35, 0x0E, 0x48, 0x01, 0x03, 0xCC,
791 0xDB, 0xFD, 0xF4, 0xAC, 0x11, 0x91, 0xF4, 0xEF,
792 0xB9, 0xA5, 0xF9, 0xE9, 0xA7, 0x83, 0x2C, 0x5E,
793 0x2C, 0xBE, 0x97, 0xF2, 0xD2, 0x03, 0xB0, 0x20};
794 const UInt256 kV{0xFD, 0xC5, 0x7F, 0xF4, 0x49, 0xDD, 0x4F, 0x6B,
795 0xFB, 0x7C, 0x9D, 0xF1, 0xC2, 0x9A, 0xCB, 0x59,
796 0x2A, 0xE7, 0xD4, 0xEE, 0xFB, 0xFC, 0x0A, 0x90,
797 0x9A, 0xBB, 0xF6, 0x32, 0x3D, 0x8B, 0x18, 0x55};
798 const UInt128 kX{0xAB,
799 0xAE,
800 0x2B,
801 0x71,
802 0xEC,
803 0xB2,
804 0xFF,
805 0xFF,
806 0x3E,
807 0x73,
808 0x77,
809 0xD1,
810 0x54,
811 0x84,
812 0xCB,
813 0xD5};
814 const uint8_t kZ = 0x00;
815 const UInt128 kExpectedF4{0x2D,
816 0x87,
817 0x74,
818 0xA9,
819 0xBE,
820 0xA1,
821 0xED,
822 0xF1,
823 0x1C,
824 0xBD,
825 0xA9,
826 0x07,
827 0xF1,
828 0x16,
829 0xC9,
830 0xF2};
831
832 std::optional<UInt128> f4_out = F4(kU, kV, kX, kZ);
833 ASSERT_TRUE(f4_out.has_value());
834 EXPECT_EQ(kExpectedF4, *f4_out);
835 }
836
837 // Using the sample data from Vol 3, Part H, Appendix D.3.
TEST(UtilTest,F5)838 TEST(UtilTest, F5) {
839 const UInt256 kDhKey{0x98, 0xA6, 0xBF, 0x73, 0xF3, 0x34, 0x8D, 0x86,
840 0xF1, 0x66, 0xF8, 0xB4, 0x13, 0x6B, 0x79, 0x99,
841 0x9B, 0x7D, 0x39, 0x0A, 0xA6, 0x10, 0x10, 0x34,
842 0x05, 0xAD, 0xC8, 0x57, 0xA3, 0x34, 0x02, 0xEC};
843 const UInt128 kInitiatorNonce{0xAB,
844 0xAE,
845 0x2B,
846 0x71,
847 0xEC,
848 0xB2,
849 0xFF,
850 0xFF,
851 0x3E,
852 0x73,
853 0x77,
854 0xD1,
855 0x54,
856 0x84,
857 0xCB,
858 0xD5};
859 const UInt128 kResponderNonce{0xCF,
860 0xC4,
861 0x3D,
862 0xFF,
863 0xF7,
864 0x83,
865 0x65,
866 0x21,
867 0x6E,
868 0x5F,
869 0xA7,
870 0x25,
871 0xCC,
872 0xE7,
873 0xE8,
874 0xA6};
875 const DeviceAddress kInitiatorAddr(DeviceAddress::Type::kLEPublic,
876 {0xCE, 0xBF, 0x37, 0x37, 0x12, 0x56});
877 const DeviceAddress kResponderAddr(DeviceAddress::Type::kLEPublic,
878 {0xC1, 0xCF, 0x2D, 0x70, 0x13, 0xA7});
879 const UInt128 kExpectedMacKey{0x20,
880 0x6E,
881 0x63,
882 0xCE,
883 0x20,
884 0x6A,
885 0x3F,
886 0xFD,
887 0x02,
888 0x4A,
889 0x08,
890 0xA1,
891 0x76,
892 0xF1,
893 0x65,
894 0x29};
895 const UInt128 kExpectedLtk{0x38,
896 0x0A,
897 0x75,
898 0x94,
899 0xB5,
900 0x22,
901 0x05,
902 0x98,
903 0x23,
904 0xCD,
905 0xD7,
906 0x69,
907 0x11,
908 0x79,
909 0x86,
910 0x69};
911
912 std::optional<F5Results> results = F5(
913 kDhKey, kInitiatorNonce, kResponderNonce, kInitiatorAddr, kResponderAddr);
914
915 ASSERT_TRUE(results.has_value());
916 EXPECT_EQ(kExpectedMacKey, results->mac_key);
917 EXPECT_EQ(kExpectedLtk, results->ltk);
918 }
919
920 // Using the sample data from Vol 3, Part H, Appendix D.4
TEST(UtilTest,F6)921 TEST(UtilTest, F6) {
922 const UInt128 kMacKey{0x20,
923 0x6E,
924 0x63,
925 0xCE,
926 0x20,
927 0x6A,
928 0x3F,
929 0xFD,
930 0x02,
931 0x4A,
932 0x08,
933 0xA1,
934 0x76,
935 0xF1,
936 0x65,
937 0x29};
938 const UInt128 kN1{0xAB,
939 0xAE,
940 0x2B,
941 0x71,
942 0xEC,
943 0xB2,
944 0xFF,
945 0xFF,
946 0x3E,
947 0x73,
948 0x77,
949 0xD1,
950 0x54,
951 0x84,
952 0xCB,
953 0xD5};
954 const UInt128 kN2{0xCF,
955 0xC4,
956 0x3D,
957 0xFF,
958 0xF7,
959 0x83,
960 0x65,
961 0x21,
962 0x6E,
963 0x5F,
964 0xA7,
965 0x25,
966 0xCC,
967 0xE7,
968 0xE8,
969 0xA6};
970 const UInt128 kR{0xC8,
971 0x0F,
972 0x2D,
973 0x0C,
974 0xD2,
975 0x42,
976 0xDA,
977 0x08,
978 0x54,
979 0xBB,
980 0x53,
981 0xB4,
982 0x3B,
983 0x34,
984 0xA3,
985 0x12};
986 const AuthReqField auth_req = 0x01;
987 const auto oob = static_cast<OOBDataFlag>(0x01);
988 const auto io_cap = static_cast<IOCapability>(0x02);
989 const DeviceAddress a1(DeviceAddress::Type::kLEPublic,
990 {0xCE, 0xBF, 0x37, 0x37, 0x12, 0x56});
991 const DeviceAddress a2(DeviceAddress::Type::kLEPublic,
992 {0xC1, 0xCF, 0x2D, 0x70, 0x13, 0xA7});
993 const UInt128 kExpectedF6Out{0x61,
994 0x8F,
995 0x95,
996 0xDA,
997 0x09,
998 0x0B,
999 0x6C,
1000 0xD2,
1001 0xC5,
1002 0xE8,
1003 0xD0,
1004 0x9C,
1005 0x98,
1006 0x73,
1007 0xC4,
1008 0xE3};
1009
1010 std::optional<UInt128> f6_out =
1011 F6(kMacKey, kN1, kN2, kR, auth_req, oob, io_cap, a1, a2);
1012
1013 ASSERT_TRUE(f6_out.has_value());
1014 EXPECT_EQ(kExpectedF6Out, *f6_out);
1015 }
1016
1017 // Using the sample data from Vol 3, Part H, Appendix D.5
TEST(UtilTest,G2)1018 TEST(UtilTest, G2) {
1019 const UInt256 kInitiatorPubKeyX{
1020 0xE6, 0x9D, 0x35, 0x0E, 0x48, 0x01, 0x03, 0xCC, 0xDB, 0xFD, 0xF4,
1021 0xAC, 0x11, 0x91, 0xF4, 0xEF, 0xB9, 0xA5, 0xF9, 0xE9, 0xA7, 0x83,
1022 0x2C, 0x5E, 0x2C, 0xBE, 0x97, 0xF2, 0xD2, 0x03, 0xB0, 0x20};
1023 const UInt256 kResponderPubKeyX{
1024 0xFD, 0xC5, 0x7F, 0xF4, 0x49, 0xDD, 0x4F, 0x6B, 0xFB, 0x7C, 0x9D,
1025 0xF1, 0xC2, 0x9A, 0xCB, 0x59, 0x2A, 0xE7, 0xD4, 0xEE, 0xFB, 0xFC,
1026 0x0A, 0x90, 0x9A, 0xBB, 0xF6, 0x32, 0x3D, 0x8B, 0x18, 0x55};
1027 const UInt128 kInitiatorNonce{0xAB,
1028 0xAE,
1029 0x2B,
1030 0x71,
1031 0xEC,
1032 0xB2,
1033 0xFF,
1034 0xFF,
1035 0x3E,
1036 0x73,
1037 0x77,
1038 0xD1,
1039 0x54,
1040 0x84,
1041 0xCB,
1042 0xD5};
1043 const UInt128 kResponderNonce{0xCF,
1044 0xC4,
1045 0x3D,
1046 0xFF,
1047 0xF7,
1048 0x83,
1049 0x65,
1050 0x21,
1051 0x6E,
1052 0x5F,
1053 0xA7,
1054 0x25,
1055 0xCC,
1056 0xE7,
1057 0xE8,
1058 0xA6};
1059 const uint32_t kExpectedG2Out = 0x2f9ed5ba;
1060
1061 std::optional<uint32_t> g2_out = G2(
1062 kInitiatorPubKeyX, kResponderPubKeyX, kInitiatorNonce, kResponderNonce);
1063
1064 ASSERT_TRUE(g2_out.has_value());
1065 EXPECT_EQ(kExpectedG2Out, *g2_out);
1066 }
1067
1068 // Using the sample data from v5.2 Vol. 3, Part H, Appendix D.6
TEST(UtilTest,H6)1069 TEST(UtilTest, H6) {
1070 const UInt128 kKeyBytes = {0x9B,
1071 0x7D,
1072 0x39,
1073 0x0A,
1074 0xA6,
1075 0x10,
1076 0x10,
1077 0x34,
1078 0x05,
1079 0xAD,
1080 0xC8,
1081 0x57,
1082 0xA3,
1083 0x34,
1084 0x02,
1085 0xEC};
1086 const uint32_t kKeyId = 0x6c656272;
1087 const UInt128 kExpectedH6Out = {0x99,
1088 0x63,
1089 0xB1,
1090 0x80,
1091 0xE2,
1092 0xA9,
1093 0xD3,
1094 0xE8,
1095 0x1C,
1096 0xC9,
1097 0x6D,
1098 0xE7,
1099 0x02,
1100 0xE1,
1101 0x9A,
1102 0x2D};
1103
1104 std::optional<UInt128> h6_out = H6(kKeyBytes, kKeyId);
1105 ASSERT_TRUE(h6_out.has_value());
1106 ASSERT_EQ(kExpectedH6Out, *h6_out);
1107 }
1108
1109 // Using the sample data from v5.2 Vol. 3, Part H, Appendix D.8
TEST(UtilTest,H7)1110 TEST(UtilTest, H7) {
1111 const UInt128 kKeyBytes = {0x9B,
1112 0x7D,
1113 0x39,
1114 0x0A,
1115 0xA6,
1116 0x10,
1117 0x10,
1118 0x34,
1119 0x05,
1120 0xAD,
1121 0xC8,
1122 0x57,
1123 0xA3,
1124 0x34,
1125 0x02,
1126 0xEC};
1127 const UInt128 kSalt = {0x31,
1128 0x70,
1129 0x6D,
1130 0x74,
1131 0x00,
1132 0x00,
1133 0x00,
1134 0x00,
1135 0x00,
1136 0x00,
1137 0x00,
1138 0x00,
1139 0x00,
1140 0x00,
1141 0x00,
1142 0x00};
1143 const UInt128 kExpectedH7Out = {0x11,
1144 0x70,
1145 0xA5,
1146 0x75,
1147 0x2A,
1148 0x8C,
1149 0x99,
1150 0xD2,
1151 0xEC,
1152 0xC0,
1153 0xA3,
1154 0xC6,
1155 0x97,
1156 0x35,
1157 0x17,
1158 0xFB};
1159
1160 std::optional<UInt128> h7_out = H7(kSalt, kKeyBytes);
1161 ASSERT_TRUE(h7_out.has_value());
1162 ASSERT_EQ(kExpectedH7Out, *h7_out);
1163 }
1164
1165 // Using the sample data from v5.2 Vol. 3, Part H, Appendix D.9
TEST(UtilTest,LtkToLinkKeyUsingH7)1166 TEST(UtilTest, LtkToLinkKeyUsingH7) {
1167 const UInt128 kLtkBytes = {0x64,
1168 0xBF,
1169 0x4F,
1170 0x33,
1171 0x33,
1172 0x6C,
1173 0x06,
1174 0xBD,
1175 0x58,
1176 0x4B,
1177 0x26,
1178 0xE3,
1179 0xBC,
1180 0xF9,
1181 0x8D,
1182 0x36};
1183 const UInt128 kExpectedLinkKeyBytes = {0x35,
1184 0xB8,
1185 0x47,
1186 0x30,
1187 0xF4,
1188 0xF1,
1189 0x39,
1190 0x0A,
1191 0x53,
1192 0x02,
1193 0xA4,
1194 0xDC,
1195 0x79,
1196 0xD3,
1197 0x7A,
1198 0x28};
1199 std::optional<UInt128> out_link_key =
1200 LeLtkToBrEdrLinkKey(kLtkBytes, CrossTransportKeyAlgo::kUseH7);
1201
1202 ASSERT_TRUE(out_link_key.has_value());
1203 EXPECT_EQ(kExpectedLinkKeyBytes, *out_link_key);
1204 }
1205
1206 // Using the sample data from v5.2 Vol. 3, Part H, Appendix D.10
TEST(UtilTest,LtkToLinkKeyUsingH6)1207 TEST(UtilTest, LtkToLinkKeyUsingH6) {
1208 const UInt128 kLtkBytes = {0x64,
1209 0xBF,
1210 0x4F,
1211 0x33,
1212 0x33,
1213 0x6C,
1214 0x06,
1215 0xBD,
1216 0x58,
1217 0x4B,
1218 0x26,
1219 0xE3,
1220 0xBC,
1221 0xF9,
1222 0x8D,
1223 0x36};
1224 const UInt128 kExpectedLinkKeyBytes = {0xB0,
1225 0x8F,
1226 0x38,
1227 0xEE,
1228 0xAF,
1229 0x30,
1230 0x82,
1231 0x0D,
1232 0xBD,
1233 0xC1,
1234 0x3F,
1235 0x63,
1236 0xEF,
1237 0xA4,
1238 0x1C,
1239 0xBC};
1240 std::optional<UInt128> out_link_key =
1241 LeLtkToBrEdrLinkKey(kLtkBytes, CrossTransportKeyAlgo::kUseH6);
1242
1243 ASSERT_TRUE(out_link_key.has_value());
1244 EXPECT_EQ(kExpectedLinkKeyBytes, *out_link_key);
1245 }
1246 } // namespace
1247 } // namespace bt::sm::util
1248