1#![warn(missing_docs)]
2use core::num::NonZeroU128;
5
6use aes::cipher::{BlockEncrypt, KeyInit};
7use aes::Aes128;
8use bt_hci::param::BdAddr;
9use cmac::digest;
10use p256::ecdh;
11use rand_core::{CryptoRng, RngCore};
12
13use crate::Address;
14
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18#[must_use]
19#[repr(transparent)]
20pub struct LongTermKey(pub u128);
21
22impl LongTermKey {
23 #[inline(always)]
25 pub const fn new(k: u128) -> Self {
26 Self(k)
27 }
28 #[inline(always)]
30 pub const fn from_le_bytes(k: [u8; 16]) -> Self {
31 Self(u128::from_le_bytes(k))
32 }
33 #[inline(always)]
35 pub const fn to_le_bytes(self) -> [u8; 16] {
36 self.0.to_le_bytes()
37 }
38
39 #[inline]
44 pub fn from_encryption_root(er: u128, div: u16) -> Self {
45 Self(d1(er, div, 0))
46 }
47}
48
49impl From<&LongTermKey> for u128 {
50 #[inline(always)]
51 fn from(k: &LongTermKey) -> Self {
52 k.0
53 }
54}
55
56impl core::fmt::Display for LongTermKey {
57 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
58 write!(f, "{:016x}", self.0)
59 }
60}
61
62#[cfg(feature = "defmt")]
63impl defmt::Format for LongTermKey {
64 fn format(&self, fmt: defmt::Formatter) {
65 defmt::write!(fmt, "{:016x}", self.0)
66 }
67}
68
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71#[derive(Clone, Copy, Debug, Eq, PartialEq)]
72#[must_use]
73#[repr(transparent)]
74pub struct IdentityResolvingKey(pub NonZeroU128);
75
76impl IdentityResolvingKey {
77 #[inline(always)]
79 pub const fn new(k: u128) -> Option<Self> {
80 match NonZeroU128::new(k) {
81 Some(k) => Some(Self(k)),
82 None => None,
83 }
84 }
85
86 #[inline(always)]
88 pub const fn from_le_bytes(k: [u8; 16]) -> Option<Self> {
89 Self::new(u128::from_le_bytes(k))
90 }
91
92 #[inline]
97 pub fn from_identity_root(ir: u128) -> Option<Self> {
98 Self::new(d1(ir, 1, 0))
99 }
100
101 #[inline(always)]
103 pub const fn to_le_bytes(self) -> [u8; 16] {
104 self.0.get().to_le_bytes()
105 }
106
107 pub fn generate_resolvable_address<T: RngCore + CryptoRng>(&self, rng: &mut T) -> [u8; 6] {
112 let mut prand = [0u8; 3];
114 rng.fill_bytes(&mut prand);
115
116 prand[2] &= 0b00111111; prand[2] |= 0b01000000; let hash = self.ah(prand);
122
123 let mut address = [0u8; 6];
125 address[3..6].copy_from_slice(&prand);
126 address[0..3].copy_from_slice(&hash);
127
128 address
129 }
130
131 pub fn resolve_address(&self, address: &BdAddr) -> bool {
135 let mut prand = [0u8; 3];
137 prand.copy_from_slice(&address.raw()[3..6]);
138
139 if (prand[2] & 0b11000000) != 0b01000000 {
141 return false; }
143
144 prand.reverse();
145
146 let mut local_hash = self.ah(prand);
148 local_hash.reverse();
149
150 let mut address_hash = [0u8; 3];
152 address_hash.copy_from_slice(&address.raw()[0..3]);
153 local_hash == address_hash
154 }
155
156 fn ah(&self, r: [u8; 3]) -> [u8; 3] {
160 let mut r_prime = [0u8; 16];
161 r_prime[13..].copy_from_slice(&r);
162
163 let cipher = Aes128::new_from_slice(&self.0.get().to_be_bytes()).unwrap();
164 cipher.encrypt_block((&mut r_prime).into());
165 r_prime[13..16].try_into().unwrap()
167 }
168}
169
170impl From<&IdentityResolvingKey> for u128 {
171 #[inline(always)]
172 fn from(k: &IdentityResolvingKey) -> Self {
173 k.0.get()
174 }
175}
176
177impl core::fmt::Display for IdentityResolvingKey {
178 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
179 write!(f, "{:016x}", self.0)
180 }
181}
182
183#[cfg(feature = "defmt")]
184impl defmt::Format for IdentityResolvingKey {
185 fn format(&self, fmt: defmt::Formatter) {
186 defmt::write!(fmt, "{:016x}", self.0)
187 }
188}
189
190#[derive(Debug)]
192#[repr(transparent)]
193pub struct AesCmac(cmac::Cmac<aes::Aes128>);
194
195impl AesCmac {
196 #[inline(always)]
198 #[must_use]
199 pub(super) fn new(k: &Key) -> Self {
200 Self(digest::KeyInit::new(&k.0))
201 }
202
203 #[inline(always)]
206 #[must_use]
207 pub fn db_hash() -> Self {
208 Self::new(&Key::new(0))
209 }
210
211 #[inline(always)]
213 pub fn update(&mut self, b: impl AsRef<[u8]>) -> &mut Self {
214 digest::Update::update(&mut self.0, b.as_ref());
215 self
216 }
217
218 #[inline(always)]
220 #[must_use]
221 pub fn finalize(self) -> u128 {
222 u128::from_be_bytes(*digest::FixedOutput::finalize_fixed(self.0).as_ref())
223 }
224
225 #[inline(always)]
228 pub(super) fn finalize_key(&mut self) -> Key {
229 let mut k = Key::new(0);
231 digest::FixedOutputReset::finalize_into_reset(&mut self.0, &mut k.0);
232 k
233 }
234}
235
236#[derive(Clone, Copy, Debug, PartialEq, Eq)]
238#[must_use]
239#[repr(transparent)]
240pub struct Check(pub u128);
241
242#[derive(Clone, Copy)]
243#[repr(transparent)]
244pub(super) struct Key(aes::cipher::Key<aes::Aes128>);
245
246impl Key {
247 #[inline(always)]
249 pub fn new(k: u128) -> Self {
250 Self(k.to_be_bytes().into())
251 }
252}
253
254impl From<&Key> for u128 {
255 #[inline(always)]
256 fn from(k: &Key) -> Self {
257 Self::from_be_bytes(k.0.into())
258 }
259}
260
261#[repr(transparent)]
264#[derive(Clone, Copy, Debug)]
265pub struct IoCap(pub(crate) [u8; 3]);
266
267impl IoCap {
268 #[inline(always)]
270 pub fn new(auth_req: u8, oob_data: bool, io_cap: u8) -> Self {
271 Self([auth_req, u8::from(oob_data), io_cap])
272 }
273}
274
275#[derive(Clone, Copy)]
278#[must_use]
279#[repr(transparent)]
280pub struct MacKey(Key);
281
282impl core::fmt::Debug for MacKey {
283 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
284 f.debug_tuple("MacKey").field(&"***").finish()
285 }
286}
287
288#[cfg(feature = "defmt")]
289impl defmt::Format for MacKey {
290 fn format(&self, fmt: defmt::Formatter) {
291 defmt::write!(fmt, "MacKey(***)");
292 }
293}
294
295impl MacKey {
296 #[inline]
299 pub fn f6(&self, n1: Nonce, n2: Nonce, r: u128, io_cap: IoCap, a1: Address, a2: Address) -> Check {
300 let mut m = AesCmac::new(&self.0);
301 m.update(n1.0.to_be_bytes())
302 .update(n2.0.to_be_bytes())
303 .update(r.to_be_bytes())
304 .update(io_cap.0)
305 .update(a1.to_bytes())
306 .update(a2.to_bytes());
307 Check(m.finalize())
308 }
309}
310
311#[derive(Clone, Copy, Debug, Eq, PartialEq)]
313#[cfg_attr(feature = "defmt", derive(defmt::Format))]
314#[repr(transparent)]
315pub struct Nonce(pub u128);
316
317impl Nonce {
318 #[allow(clippy::new_without_default)]
324 #[inline]
325 pub fn new<T: RngCore>(rng: &mut T) -> Self {
326 let mut b = [0; core::mem::size_of::<u128>()];
327 rng.fill_bytes(b.as_mut_slice());
328 let n = u128::from_ne_bytes(b);
329 assert_ne!(n, 0);
330 Self(n)
331 }
332
333 #[inline]
336 pub fn f4(&self, u: &PublicKeyX, v: &PublicKeyX, z: u8) -> Confirm {
337 let mut m = AesCmac::new(&Key::new(self.0));
338 m.update(u.as_be_bytes()).update(v.as_be_bytes()).update([z]);
339 Confirm(m.finalize())
340 }
341
342 #[inline]
345 pub fn g2(&self, pkax: &PublicKeyX, pkbx: &PublicKeyX, nb: &Self) -> NumCompare {
346 let mut m = AesCmac::new(&Key::new(self.0));
347 m.update(pkax.as_be_bytes())
348 .update(pkbx.as_be_bytes())
349 .update(nb.0.to_be_bytes());
350 #[allow(clippy::cast_possible_truncation)]
351 NumCompare(m.finalize() as u32 % 1_000_000)
352 }
353}
354
355#[derive(Clone, Copy, Debug, PartialEq, Eq)]
357#[cfg_attr(feature = "defmt", derive(defmt::Format))]
358#[must_use]
359#[repr(transparent)]
360pub struct Confirm(pub u128);
361
362#[derive(Clone, Copy, Eq, PartialEq, Debug)]
365#[cfg_attr(feature = "defmt", derive(defmt::Format))]
366#[must_use]
367#[repr(transparent)]
368pub struct NumCompare(pub u32);
369
370#[derive(Clone)]
372#[must_use]
373#[repr(transparent)]
374pub struct SecretKey(p256::NonZeroScalar);
375
376impl core::fmt::Debug for SecretKey {
377 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
378 f.debug_tuple("SecretKey").field(&"***").finish()
379 }
380}
381
382#[cfg(feature = "defmt")]
383impl defmt::Format for SecretKey {
384 fn format(&self, fmt: defmt::Formatter) {
385 defmt::write!(fmt, "SecretKey(***)");
386 }
387}
388
389impl SecretKey {
390 #[allow(clippy::new_without_default)]
392 #[inline(always)]
393 pub fn new<T: RngCore + CryptoRng>(rng: &mut T) -> Self {
394 Self(p256::NonZeroScalar::random(rng))
395 }
396
397 pub fn public_key(&self) -> PublicKey {
399 use p256::elliptic_curve::sec1::Coordinates::Uncompressed;
400 use p256::elliptic_curve::sec1::ToEncodedPoint;
401 let p = p256::PublicKey::from_secret_scalar(&self.0).to_encoded_point(false);
402 match p.coordinates() {
403 Uncompressed { x, y } => PublicKey {
404 x: PublicKeyX(Coord(*x.as_ref())),
405 y: Coord(*y.as_ref()),
406 },
407 _ => unreachable!("invalid secret key"),
408 }
409 }
410
411 #[must_use]
415 pub fn dh_key(&self, pk: PublicKey) -> Option<DHKey> {
416 use p256::elliptic_curve::sec1::FromEncodedPoint;
417 if pk.is_debug() {
418 return None; }
420
421 let (x, y) = (&pk.x.0 .0.into(), &pk.y.0.into());
422 let rep = p256::EncodedPoint::from_affine_coordinates(x, y, false);
423 let lpk = p256::PublicKey::from_secret_scalar(&self.0);
424 let rpk = Option::from(p256::PublicKey::from_encoded_point(&rep)).unwrap_or(lpk);
427 (rpk != lpk).then(|| DHKey(ecdh::diffie_hellman(&self.0, rpk.as_affine())))
428 }
429}
430
431#[derive(Clone, Copy, Debug, Eq, PartialEq)]
433#[cfg_attr(feature = "defmt", derive(defmt::Format))]
434#[must_use]
435pub struct PublicKey {
436 pub x: PublicKeyX,
437 pub y: Coord,
438}
439
440impl PublicKey {
441 pub fn from_bytes(bytes: &[u8]) -> Self {
442 let mut x = [0u8; 32];
443 let mut y = [0u8; 32];
444
445 x.copy_from_slice(&bytes[..32]);
446 y.copy_from_slice(&bytes[32..]);
447
448 x.reverse();
449 y.reverse();
450
451 Self {
452 x: PublicKeyX(Coord(x)),
453 y: Coord(y),
454 }
455 }
456
457 #[inline(always)]
459 pub const fn x(&self) -> &PublicKeyX {
460 &self.x
461 }
462
463 #[allow(clippy::unreadable_literal)]
466 #[allow(clippy::unusual_byte_groupings)]
467 fn is_debug(&self) -> bool {
468 let (x, y) = (&self.x.0 .0, &self.y.0);
469 x[..16] == u128::to_be_bytes(0x20b003d2_f297be2c_5e2c83a7_e9f9a5b9)
470 && x[16..] == u128::to_be_bytes(0xeff49111_acf4fddb_cc030148_0e359de6)
471 && y[..16] == u128::to_be_bytes(0xdc809c49_652aeb6d_63329abf_5a52155c)
472 && y[16..] == u128::to_be_bytes(0x766345c2_8fed3024_741c8ed0_1589d28b)
473 }
474}
475
476#[derive(Clone, Copy, Debug, Eq, PartialEq)]
478#[cfg_attr(feature = "defmt", derive(defmt::Format))]
479#[repr(transparent)]
480pub struct Coord([u8; 256 / u8::BITS as usize]);
481
482impl Coord {
483 #[inline(always)]
485 pub(super) const fn as_be_bytes(&self) -> &[u8; core::mem::size_of::<Self>()] {
486 &self.0
487 }
488}
489
490#[derive(Clone, Copy, Debug, Eq, PartialEq)]
492#[cfg_attr(feature = "defmt", derive(defmt::Format))]
493#[must_use]
494#[repr(transparent)]
495pub struct PublicKeyX(Coord);
496
497impl PublicKeyX {
498 #[cfg(test)]
500 #[inline]
501 pub(super) const fn from_be_bytes(x: [u8; core::mem::size_of::<Self>()]) -> Self {
502 Self(Coord(x))
503 }
504
505 #[inline(always)]
507 pub(super) const fn as_be_bytes(&self) -> &[u8; core::mem::size_of::<Self>()] {
508 &self.0 .0
509 }
510}
511
512#[must_use]
514#[repr(transparent)]
515pub struct DHKey(ecdh::SharedSecret);
516
517impl Clone for DHKey {
518 fn clone(&self) -> Self {
519 Self(ecdh::SharedSecret::from(*self.0.raw_secret_bytes()))
520 }
521}
522
523impl core::fmt::Debug for DHKey {
524 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
525 f.debug_tuple("DHKey").field(&"***").finish()
526 }
527}
528
529#[cfg(feature = "defmt")]
530impl defmt::Format for DHKey {
531 fn format(&self, fmt: defmt::Formatter) {
532 defmt::write!(fmt, "DHKey(***)");
533 }
534}
535
536impl DHKey {
537 #[inline]
540 pub fn f5(&self, n1: Nonce, n2: Nonce, a1: Address, a2: Address) -> (MacKey, LongTermKey) {
541 let n1 = n1.0.to_be_bytes();
542 let n2 = n2.0.to_be_bytes();
543 let half = |m: &mut AesCmac, counter: u8| {
544 m.update([counter])
545 .update(b"btle")
546 .update(n1)
547 .update(n2)
548 .update(a1.to_bytes())
549 .update(a2.to_bytes())
550 .update(256_u16.to_be_bytes())
551 .finalize_key()
552 };
553 let mut m = AesCmac::new(&Key::new(0x6C88_8391_AAF5_A538_6037_0BDB_5A60_83BE));
554 m.update(self.0.raw_secret_bytes());
555 let mut m = AesCmac::new(&m.finalize_key());
556 (MacKey(half(&mut m, 0)), LongTermKey(u128::from(&half(&mut m, 1))))
557 }
558}
559
560#[cfg(feature = "legacy-pairing")]
561#[allow(clippy::too_many_arguments)]
562pub(super) fn c1(
575 k: u128,
576 r: u128,
577 preq: &[u8; 7],
578 pres: &[u8; 7],
579 iat: u8,
580 ia: &[u8; 6],
581 rat: u8,
582 ra: &[u8; 6],
583) -> u128 {
584 let mut pres_rev = *pres;
588 pres_rev.reverse();
589 let mut preq_rev = *preq;
590 preq_rev.reverse();
591
592 let mut p1 = [0u8; 16];
593 p1[0..7].copy_from_slice(&pres_rev);
594 p1[7..14].copy_from_slice(&preq_rev);
595 p1[14] = rat;
596 p1[15] = iat;
597
598 let mut p2 = [0u8; 16];
600 p2[4..10].copy_from_slice(ia);
601 p2[10..16].copy_from_slice(ra);
602
603 let cipher = Aes128::new_from_slice(&k.to_be_bytes()).unwrap();
604
605 let r_bytes = r.to_be_bytes();
607 let mut block = [0u8; 16];
608 for i in 0..16 {
609 block[i] = r_bytes[i] ^ p1[i];
610 }
611 cipher.encrypt_block((&mut block).into());
612
613 for i in 0..16 {
615 block[i] ^= p2[i];
616 }
617 cipher.encrypt_block((&mut block).into());
618
619 u128::from_be_bytes(block)
620}
621
622#[cfg(feature = "legacy-pairing")]
623pub(super) fn s1(k: u128, r1: u128, r2: u128) -> u128 {
629 let r1_bytes = r1.to_be_bytes();
630 let r2_bytes = r2.to_be_bytes();
631
632 let mut r_prime = [0u8; 16];
635 r_prime[0..8].copy_from_slice(&r1_bytes[8..16]);
636 r_prime[8..16].copy_from_slice(&r2_bytes[8..16]);
637
638 let cipher = Aes128::new_from_slice(&k.to_be_bytes()).unwrap();
639 cipher.encrypt_block((&mut r_prime).into());
640
641 u128::from_be_bytes(r_prime)
642}
643
644pub(super) fn d1(k: u128, d: u16, r: u16) -> u128 {
650 let mut d_prime = [0u8; 16];
651 d_prime[12..14].copy_from_slice(&r.to_be_bytes());
652 d_prime[14..16].copy_from_slice(&d.to_be_bytes());
653
654 let cipher = Aes128::new_from_slice(&k.to_be_bytes()).unwrap();
655 cipher.encrypt_block((&mut d_prime).into());
656
657 u128::from_be_bytes(d_prime)
658}
659
660#[allow(clippy::redundant_pub_crate)]
662#[cfg(test)]
663pub(super) fn u256<T: From<[u8; 32]>>(hi: u128, lo: u128) -> T {
664 let mut b = [0; 32];
665 b[..16].copy_from_slice(&hi.to_be_bytes());
666 b[16..].copy_from_slice(&lo.to_be_bytes());
667 T::from(b)
668}
669
670#[allow(clippy::unreadable_literal)]
671#[allow(clippy::unusual_byte_groupings)]
672#[cfg(test)]
673mod tests {
674 use p256::elliptic_curve::rand_core::OsRng;
675
676 use super::*;
677 extern crate std;
678 use bt_hci::param::{AddrKind, BdAddr};
679
680 #[test]
681 fn sizes() {
682 assert_eq!(core::mem::size_of::<Coord>(), 32);
683 assert_eq!(core::mem::size_of::<PublicKey>(), 64);
684 assert_eq!(core::mem::size_of::<SecretKey>(), 32);
685 assert_eq!(core::mem::size_of::<DHKey>(), 32);
686 }
687
688 #[test]
690 fn debug_key() {
691 let sk = secret_key(
692 0x3f49f6d4_a3c55f38_74c9b3e3_d2103f50,
693 0x4aff607b_eb40b799_5899b8a6_cd3c1abd,
694 );
695 let pk = PublicKey {
696 x: PublicKeyX(Coord(u256(
697 0x20b003d2_f297be2c_5e2c83a7_e9f9a5b9,
698 0xeff49111_acf4fddb_cc030148_0e359de6,
699 ))),
700 y: Coord(u256(
701 0xdc809c49_652aeb6d_63329abf_5a52155c,
702 0x766345c2_8fed3024_741c8ed0_1589d28b,
703 )),
704 };
705 assert_eq!(sk.public_key(), pk);
706 assert!(pk.is_debug());
707 }
708
709 #[test]
711 fn p256_1() {
712 let (ska, skb) = (
713 secret_key(
714 0x3f49f6d4_a3c55f38_74c9b3e3_d2103f50,
715 0x4aff607b_eb40b799_5899b8a6_cd3c1abd,
716 ),
717 secret_key(
718 0x55188b3d_32f6bb9a_900afcfb_eed4e72a,
719 0x59cb9ac2_f19d7cfb_6b4fdd49_f47fc5fd,
720 ),
721 );
722 let (pka, pkb) = (
723 PublicKey {
724 x: PublicKeyX(Coord(u256(
725 0x20b003d2_f297be2c_5e2c83a7_e9f9a5b9,
726 0xeff49111_acf4fddb_cc030148_0e359de6,
727 ))),
728 y: Coord(u256(
729 0xdc809c49_652aeb6d_63329abf_5a52155c,
730 0x766345c2_8fed3024_741c8ed0_1589d28b,
731 )),
732 },
733 PublicKey {
734 x: PublicKeyX(Coord(u256(
735 0x1ea1f0f0_1faf1d96_09592284_f19e4c00,
736 0x47b58afd_8615a69f_559077b2_2faaa190,
737 ))),
738 y: Coord(u256(
739 0x4c55f33e_429dad37_7356703a_9ab85160,
740 0x472d1130_e28e3676_5f89aff9_15b1214a,
741 )),
742 },
743 );
744 let dh_key = shared_secret(
745 0xec0234a3_57c8ad05_341010a6_0a397d9b,
746 0x99796b13_b4f866f1_868d34f3_73bfa698,
747 );
748 assert_eq!(ska.public_key(), pka);
749 assert_eq!(skb.public_key(), pkb);
750 assert_eq!(
751 ska.dh_key(pkb).unwrap().0.raw_secret_bytes(),
752 dh_key.0.raw_secret_bytes()
753 );
754
755 assert!(!pkb.is_debug());
756 assert!(skb.dh_key(pkb).is_none());
757 }
758
759 #[test]
761 fn p256_2() {
762 let (ska, skb) = (
763 secret_key(
764 0x06a51669_3c9aa31a_6084545d_0c5db641,
765 0xb48572b9_7203ddff_b7ac73f7_d0457663,
766 ),
767 secret_key(
768 0x529aa067_0d72cd64_97502ed4_73502b03,
769 0x7e8803b5_c60829a5_a3caa219_505530ba,
770 ),
771 );
772 let (pka, pkb) = (
773 PublicKey {
774 x: PublicKeyX(Coord(u256(
775 0x2c31a47b_5779809e_f44cb5ea_af5c3e43,
776 0xd5f8faad_4a8794cb_987e9b03_745c78dd,
777 ))),
778 y: Coord(u256(
779 0x91951218_3898dfbe_cd52e240_8e43871f,
780 0xd0211091_17bd3ed4_eaf84377_43715d4f,
781 )),
782 },
783 PublicKey {
784 x: PublicKeyX(Coord(u256(
785 0xf465e43f_f23d3f1b_9dc7dfc0_4da87581,
786 0x84dbc966_204796ec_cf0d6cf5_e16500cc,
787 ))),
788 y: Coord(u256(
789 0x0201d048_bcbbd899_eeefc424_164e33c2,
790 0x01c2b010_ca6b4d43_a8a155ca_d8ecb279,
791 )),
792 },
793 );
794 let dh_key = shared_secret(
795 0xab85843a_2f6d883f_62e5684b_38e30733,
796 0x5fe6e194_5ecd1960_4105c6f2_3221eb69,
797 );
798 assert_eq!(ska.public_key(), pka);
799 assert_eq!(skb.public_key(), pkb);
800 assert_eq!(
801 ska.dh_key(pkb).unwrap().0.raw_secret_bytes(),
802 dh_key.0.raw_secret_bytes()
803 );
804 }
805
806 #[test]
808 fn dh_key_f5() {
809 let w = shared_secret(
810 0xec0234a3_57c8ad05_341010a6_0a397d9b,
811 0x99796b13_b4f866f1_868d34f3_73bfa698,
812 );
813 let n1 = Nonce(0xd5cb8454_d177733e_ffffb2ec_712baeab);
814 let n2 = Nonce(0xa6e8e7cc_25a75f6e_216583f7_ff3dc4cf);
815 let a1 = Address::new(AddrKind::PUBLIC, BdAddr::new([0xce, 0xbf, 0x37, 0x37, 0x12, 0x56]));
816 let a2 = Address::new(AddrKind::PUBLIC, BdAddr::new([0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7]));
817 let (mk, ltk) = w.f5(n1, n2, a1, a2);
818 assert_eq!(ltk.0, 0x69867911_69d7cd23_980522b5_94750a38);
819 assert_eq!(u128::from(&mk.0), 0x2965f176_a1084a02_fd3f6a20_ce636e20);
820 }
821
822 #[inline]
823 fn secret_key(hi: u128, lo: u128) -> SecretKey {
824 SecretKey(p256::NonZeroScalar::from_repr(u256(hi, lo)).unwrap())
825 }
826
827 #[inline]
828 fn shared_secret(hi: u128, lo: u128) -> DHKey {
829 DHKey(ecdh::SharedSecret::from(u256::<p256::FieldBytes>(hi, lo)))
830 }
831
832 #[test]
833 fn testtest() {
834 let skb = SecretKey::new(&mut OsRng::default());
835 let _pkb = skb.public_key();
836
837 let ska = SecretKey::new(&mut OsRng::default());
838 let pka = ska.public_key();
839
840 let _dh_key = skb.dh_key(pka).unwrap();
841 }
842
843 #[test]
844 fn testtest2() {
845 let bytes = [
846 0x1eu8, 0x3b, 0x26, 0x40, 0x0e, 0xba, 0x72, 0x51, 0x81, 0xf9, 0x3d, 0x16, 0xb3, 0xc4, 0x11, 0x55, 0x3f,
847 0xa8, 0x88, 0x47, 0x08, 0x1c, 0x4a, 0x42, 0x88, 0xbb, 0x68, 0x1d, 0x93, 0xe5, 0xab, 0xb3, 0x72, 0xfa, 0x93,
848 0xb4, 0xa0, 0xfe, 0x3f, 0x83, 0x9c, 0x85, 0x5b, 0x5f, 0xb6, 0x30, 0x09, 0x85, 0x47, 0xfd, 0xa8, 0xfa, 0x11,
849 0x71, 0xe4, 0x95, 0x17, 0x71, 0x98, 0x82, 0x8f, 0xf8, 0x79, 0x94,
850 ];
851
852 let skb = SecretKey::new(&mut OsRng::default());
853 let _pkb = skb.public_key();
854
855 let pka = PublicKey::from_bytes(&bytes);
856
857 let _dh_key = skb.dh_key(pka).unwrap();
858 }
859
860 #[test]
861 fn nonce() {
862 assert_ne!(Nonce::new(&mut OsRng::default()), Nonce::new(&mut OsRng::default()));
864 }
865
866 #[test]
868 fn nonce_f4() {
869 let u = PublicKeyX::from_be_bytes(u256(
870 0x20b003d2_f297be2c_5e2c83a7_e9f9a5b9,
871 0xeff49111_acf4fddb_cc030148_0e359de6,
872 ));
873 let v = PublicKeyX::from_be_bytes(u256(
874 0x55188b3d_32f6bb9a_900afcfb_eed4e72a,
875 0x59cb9ac2_f19d7cfb_6b4fdd49_f47fc5fd,
876 ));
877 let x = Nonce(0xd5cb8454_d177733e_ffffb2ec_712baeab);
878 assert_eq!(x.f4(&u, &v, 0).0, 0xf2c916f1_07a9bd1c_f1eda1be_a974872d);
879 }
880
881 #[allow(clippy::unreadable_literal)]
883 #[test]
884 fn nonce_g2() {
885 let u = PublicKeyX::from_be_bytes(u256(
886 0x20b003d2_f297be2c_5e2c83a7_e9f9a5b9,
887 0xeff49111_acf4fddb_cc030148_0e359de6,
888 ));
889 let v = PublicKeyX::from_be_bytes(u256(
890 0x55188b3d_32f6bb9a_900afcfb_eed4e72a,
891 0x59cb9ac2_f19d7cfb_6b4fdd49_f47fc5fd,
892 ));
893 let x = Nonce(0xd5cb8454_d177733e_ffffb2ec_712baeab);
894 let y = Nonce(0xa6e8e7cc_25a75f6e_216583f7_ff3dc4cf);
895 assert_eq!(x.g2(&u, &v, &y), NumCompare(0x2f9ed5ba % 1_000_000));
896 }
897
898 #[test]
900 fn mac_key_f6() {
901 let k = MacKey(Key::new(0x2965f176_a1084a02_fd3f6a20_ce636e20));
902 let n1 = Nonce(0xd5cb8454_d177733e_ffffb2ec_712baeab);
903 let n2 = Nonce(0xa6e8e7cc_25a75f6e_216583f7_ff3dc4cf);
904 let r = 0x12a3343b_b453bb54_08da42d2_0c2d0fc8;
905 let io_cap = IoCap([0x01, 0x01, 0x02]);
906 let a1 = Address::new(AddrKind::PUBLIC, BdAddr::new([0xce, 0xbf, 0x37, 0x37, 0x12, 0x56]));
907 let a2 = Address::new(AddrKind::PUBLIC, BdAddr::new([0xc1, 0xcf, 0x2d, 0x70, 0x13, 0xa7]));
908 let c = k.f6(n1, n2, r, io_cap, a1, a2);
909 assert_eq!(c.0, 0xe3c47398_9cd0e8c5_d26c0b09_da958f61);
910 }
911
912 #[test]
913 fn nonce_f4_test() {
914 let ra = [
915 0x11u8, 0x3a, 0x7a, 0x69, 0x11, 0xcd, 0x44, 0x15, 0x52, 0xf7, 0x47, 0xe8, 0x26, 0x67, 0x72, 0xca,
916 ];
917
918 let rb = [
919 0xa5u8, 0x9e, 0x9a, 0x32, 0xc0, 0x97, 0x1c, 0xf7, 0x72, 0x1c, 0x29, 0xa7, 0x8c, 0x1e, 0xfd, 0x18,
920 ];
921
922 let pkb = [
923 0xd, 0x80, 0x33, 0x93, 0xad, 0x1f, 0x7e, 0x9a, 0x30, 0xc9, 0x6e, 0x1, 0x78, 0xf3, 0x43, 0x14, 0xa0, 0x57,
924 0xae, 0xa5, 0xa8, 0xee, 0x75, 0x51, 0x3f, 0xaa, 0xb1, 0x80, 0x75, 0xc7, 0x14, 0x50, 0x73, 0x9a, 0x98, 0x95,
925 0x36, 0x2e, 0xe6, 0x81, 0x5f, 0xbf, 0x16, 0xa2, 0x8c, 0xf6, 0x9d, 0xdc, 0x1f, 0xb8, 0x84, 0x8c, 0x7d, 0x37,
926 0x36, 0xe4, 0x36, 0x3c, 0xb3, 0xe8, 0xfe, 0x4a, 0x73, 0xc6,
927 ];
928
929 let pka = [
930 0x97, 0x20, 0x0f, 0xfe, 0xf0, 0xec, 0xdd, 0x11, 0xda, 0xa8, 0xa8, 0x07, 0x3e, 0xd7, 0xc6, 0xf2, 0x68, 0x5d,
931 0xc2, 0x58, 0x71, 0x1e, 0x34, 0x4f, 0xa1, 0xc4, 0x44, 0xa9, 0x7c, 0x71, 0xee, 0x54, 0x0d, 0xad, 0xb7, 0x69,
932 0x89, 0x9d, 0x4f, 0x83, 0x37, 0xcd, 0x43, 0xd3, 0x9f, 0x05, 0x13, 0x99, 0x6f, 0xbc, 0x1a, 0x89, 0xed, 0xb4,
933 0x7f, 0x80, 0x98, 0xcf, 0xad, 0x7c, 0x4c, 0x57, 0xbf, 0xe1,
934 ];
935
936 let mut pkb_x = [0u8; 32];
937 pkb_x.copy_from_slice(&pkb[..32]);
938 pkb_x.reverse();
939 let mut pka_x = [0u8; 32];
940 pka_x.copy_from_slice(&pka[..32]);
941 pka_x.reverse();
942
943 let pkbx = PublicKeyX::from_be_bytes(pkb_x);
944 let pkax = PublicKeyX::from_be_bytes(pka_x);
945 extern crate std;
946
947 let x = Nonce(u128::from_le_bytes(ra));
948 let y = Nonce(u128::from_le_bytes(rb));
949
950 assert_eq!(x.g2(&pkax, &pkbx, &y).0, 991180);
951 }
952
953 #[test]
954 pub fn irk_test() {
955 let irk = IdentityResolvingKey::new(0xec0234a3_57c8ad05_341010a6_0a397d9b).unwrap();
956 let prand = [0x70, 0x81, 0x94];
957
958 let hash = irk.ah(prand);
959 assert_eq!(hash, [0x0d, 0xfb, 0xaa]);
960 }
961
962 #[test]
963 pub fn rpa_test() {
964 let irk = IdentityResolvingKey::new(0x8b3958c158ed64467bd27bc90d3cf54d).unwrap();
965 let address = BdAddr::new([0x92, 0xF2, 0x8F, 0x84, 0x72, 0x4F]);
966 let re = irk.resolve_address(&address);
967 assert_eq!(re, true);
968 }
969
970 #[cfg(feature = "legacy-pairing")]
973 #[allow(clippy::unreadable_literal)]
974 #[test]
975 fn legacy_c1() {
976 let k: u128 = 0;
977 let r: u128 = 0x5783D52156AD6F0E6388274EC6702EE0;
978 let preq: [u8; 7] = [0x01, 0x01, 0x00, 0x00, 0x10, 0x07, 0x07];
980 let pres: [u8; 7] = [0x02, 0x03, 0x00, 0x00, 0x08, 0x00, 0x05];
981 let iat: u8 = 0x01;
982 let rat: u8 = 0x00;
983 let ia: [u8; 6] = [0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6];
984 let ra: [u8; 6] = [0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6];
985
986 let result = c1(k, r, &preq, &pres, iat, &ia, rat, &ra);
987 assert_eq!(result, 0x1E1E3FEF878988EAD2A74DC5BEF13B86);
988 }
989
990 #[cfg(feature = "legacy-pairing")]
992 #[allow(clippy::unreadable_literal)]
993 #[test]
994 fn legacy_s1() {
995 let k: u128 = 0;
996 let r1: u128 = 0x000F0E0D0C0B0A091122334455667788;
997 let r2: u128 = 0x010203040506070899AABBCCDDEEFF00;
998
999 let result = s1(k, r1, r2);
1000 assert_eq!(result, 0x9a1fe1f0e8b0f49b5b4216ae796da062);
1001 }
1002
1003 #[allow(clippy::unreadable_literal)]
1006 #[test]
1007 fn diversify_d1() {
1008 let k: u128 = 0x000102030405060708090a0b0c0d0e0f;
1009 let d: u16 = 0x1234;
1010 let r: u16 = 0xABCD;
1011 assert_eq!(d1(k, d, r), 0xb66854fa3dd35aadf83a6c59e22b52fd);
1012 }
1013}