@@ -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) ]
717717mod 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