Skip to content

Commit d2097b3

Browse files
HaoboGululf
authored andcommitted
test: add unittest for peripheral IRK support
Signed-off-by: Haobo Gu <[email protected]>
1 parent 1e77f9a commit d2097b3

File tree

1 file changed

+158
-2
lines changed

1 file changed

+158
-2
lines changed

host/src/security_manager/pairing/peripheral.rs

Lines changed: 158 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ impl Pairing {
431431
if peer_features.initiator_key_distribution.identity_key() {
432432
pairing_data
433433
.local_features
434-
.initiator_key_distribution
434+
.responder_key_distribution
435435
.set_identity_key();
436436
}
437437

@@ -715,15 +715,19 @@ impl Pairing {
715715

716716
#[cfg(test)]
717717
mod tests {
718+
use core::ops::Deref;
718719
use rand_chacha::{ChaCha12Core, ChaCha12Rng};
719720
use rand_core::SeedableRng;
720721

722+
use super::{Pairing, Step};
723+
use crate::prelude::{ConnectionEvent, SecurityLevel};
721724
use crate::security_manager::crypto::{Nonce, PublicKey, SecretKey};
722-
use crate::security_manager::pairing::peripheral::Pairing;
723725
use crate::security_manager::pairing::tests::{HeaplessPool, TestOps};
724726
use crate::security_manager::pairing::util::make_public_key_packet;
727+
use crate::security_manager::pairing::Event;
725728
use crate::security_manager::types::{Command, PairingFeatures};
726729
use crate::{Address, IoCapabilities, LongTermKey};
730+
use bt_hci::param::{AddrKind, BdAddr};
727731

728732
#[test]
729733
fn just_works() {
@@ -862,4 +866,156 @@ mod tests {
862866
assert!(matches!(pairing_ops.encryptions[0], LongTermKey(_)));
863867
}
864868
}
869+
870+
#[test]
871+
fn just_works_with_irk_distribution() {
872+
let mut pairing_ops: TestOps<10> = TestOps {
873+
bondable: true,
874+
..Default::default()
875+
};
876+
let pairing = Pairing::new(
877+
Address::random([1, 2, 3, 4, 5, 6]),
878+
Address::random([7, 8, 9, 10, 11, 12]),
879+
IoCapabilities::NoInputNoOutput,
880+
);
881+
let mut rng: ChaCha12Rng = ChaCha12Core::seed_from_u64(1).into();
882+
883+
// Central sends pairing request with identity_key bit set, expects pairing response from peripheral
884+
let pairing_request = [
885+
0x03, // IO Capabilities
886+
0x00, // OOB data flag
887+
0x09, // Auth Req(Secure Connection + Bonding)
888+
16, // Maximum Encryption Key Size
889+
0x02, // Initiator Key Distribution(identity_key = true)
890+
0x00, // Responder Key Distribution
891+
];
892+
893+
pairing
894+
.handle_l2cap_command::<HeaplessPool, _, _>(
895+
Command::PairingRequest,
896+
&pairing_request,
897+
&mut pairing_ops,
898+
&mut rng,
899+
)
900+
.unwrap();
901+
902+
{
903+
let pairing_data = pairing.pairing_data.borrow();
904+
let sent_packets = &pairing_ops.sent_packets;
905+
906+
assert!(pairing_data.local_features.responder_key_distribution.identity_key());
907+
assert!(pairing_data.peer_features.initiator_key_distribution.identity_key());
908+
909+
assert_eq!(sent_packets.len(), 1);
910+
assert_eq!(sent_packets[0].command, Command::PairingResponse);
911+
let response_payload = sent_packets[0].payload();
912+
// Check AuthReq and identity key bit in response
913+
assert_eq!(response_payload[2] & 0x09, 0x09);
914+
assert_eq!(response_payload[5] & 0x02, 0x02);
915+
}
916+
917+
// Central sends public key, expects peripheral public key followed by peripheral confirm
918+
let secret_key = SecretKey::new(&mut rng);
919+
let packet = make_public_key_packet::<HeaplessPool>(&secret_key.public_key()).unwrap();
920+
pairing
921+
.handle_l2cap_command::<HeaplessPool, _, _>(
922+
Command::PairingPublicKey,
923+
packet.payload(),
924+
&mut pairing_ops,
925+
&mut rng,
926+
)
927+
.unwrap();
928+
929+
// Central sends Nonce, expects Nonce
930+
pairing
931+
.handle_l2cap_command::<HeaplessPool, _, _>(
932+
Command::PairingRandom,
933+
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
934+
&mut pairing_ops,
935+
&mut rng,
936+
)
937+
.unwrap();
938+
939+
// Central sends DHKey Check, expects encrypted link
940+
pairing
941+
.handle_l2cap_command::<HeaplessPool, _, _>(
942+
Command::PairingDhKeyCheck,
943+
&[
944+
0x06, 0x32, 0x9c, 0x2c, 0x99, 0xc2, 0xb1, 0x62, 0x6a, 0x02, 0x0e, 0x56, 0x46, 0xf6, 0x0e, 0x97,
945+
],
946+
&mut pairing_ops,
947+
&mut rng,
948+
)
949+
.unwrap();
950+
951+
pairing
952+
.handle_event(Event::LinkEncryptedResult(true), &mut pairing_ops, &mut rng)
953+
.unwrap();
954+
955+
// Waiting identity information check
956+
assert!(matches!(
957+
pairing.current_step.borrow().deref(),
958+
Step::WaitingIdentitityInformation
959+
));
960+
961+
// Central sends identity information(IRK)
962+
let irk_data: [u8; 16] = [
963+
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00,
964+
];
965+
pairing
966+
.handle_l2cap_command::<HeaplessPool, _, _>(
967+
Command::IdentityInformation,
968+
&irk_data,
969+
&mut pairing_ops,
970+
&mut rng,
971+
)
972+
.unwrap();
973+
974+
// Central sends identity address information
975+
let addr_data: [u8; 7] = [
976+
0x00, // Public address type
977+
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, // Address
978+
];
979+
pairing
980+
.handle_l2cap_command::<HeaplessPool, _, _>(
981+
Command::IdentityAddressInformation,
982+
&addr_data,
983+
&mut pairing_ops,
984+
&mut rng,
985+
)
986+
.unwrap();
987+
988+
// The step should be `Success` after `IdentityAddressInformation` command
989+
assert!(matches!(pairing.current_step.borrow().deref(), Step::Success));
990+
991+
// Verify identity and address
992+
{
993+
let pairing_data = pairing.pairing_data.borrow();
994+
let bond = pairing_data.bond_information.as_ref().unwrap();
995+
996+
assert!(bond.identity.irk.is_some());
997+
let stored_irk = bond.identity.irk.unwrap();
998+
assert_eq!(stored_irk.0, u128::from_le_bytes(irk_data));
999+
1000+
assert_eq!(bond.identity.bd_addr, BdAddr::new([0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]));
1001+
assert_eq!(pairing_data.peer_address.kind, AddrKind::PUBLIC);
1002+
assert_eq!(
1003+
pairing_data.peer_address.addr,
1004+
BdAddr::new([0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC])
1005+
);
1006+
}
1007+
1008+
// Verify completeness
1009+
assert_eq!(pairing_ops.connection_events.len(), 1);
1010+
match &pairing_ops.connection_events[0] {
1011+
ConnectionEvent::PairingComplete { security_level, bond } => {
1012+
assert_eq!(*security_level, SecurityLevel::Encrypted);
1013+
assert!(bond.is_some());
1014+
let bond_info = bond.as_ref().unwrap();
1015+
assert!(bond_info.identity.irk.is_some());
1016+
assert_eq!(bond_info.identity.irk.unwrap().0, u128::from_le_bytes(irk_data));
1017+
}
1018+
_ => panic!("Unexpected connection event"),
1019+
}
1020+
}
8651021
}

0 commit comments

Comments
 (0)