• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Bluetooth Core, Vol 2, Part C, 4.2.1
2 
3 use crate::either::Either;
4 use crate::num_hci_command_packets;
5 use crate::packets::{hci, lmp};
6 use crate::procedure::features;
7 use crate::procedure::legacy_pairing;
8 use crate::procedure::secure_simple_pairing;
9 use crate::procedure::Context;
10 
send_challenge( ctx: &impl Context, transaction_id: u8, _link_key: [u8; 16], ) -> Result<(), ()>11 pub async fn send_challenge(
12     ctx: &impl Context,
13     transaction_id: u8,
14     _link_key: [u8; 16],
15 ) -> Result<(), ()> {
16     let random_number = [0; 16];
17     ctx.send_lmp_packet(lmp::AuRandBuilder { transaction_id, random_number }.build());
18 
19     match ctx.receive_lmp_packet::<Either<lmp::SresPacket, lmp::NotAcceptedPacket>>().await {
20         Either::Left(_response) => Ok(()),
21         Either::Right(_) => Err(()),
22     }
23 }
24 
receive_challenge(ctx: &impl Context, _link_key: [u8; 16])25 pub async fn receive_challenge(ctx: &impl Context, _link_key: [u8; 16]) {
26     let _random_number = *ctx.receive_lmp_packet::<lmp::AuRandPacket>().await.get_random_number();
27     ctx.send_lmp_packet(lmp::SresBuilder { transaction_id: 0, authentication_rsp: [0; 4] }.build());
28 }
29 
initiate(ctx: &impl Context)30 pub async fn initiate(ctx: &impl Context) {
31     let _ = ctx.receive_hci_command::<hci::AuthenticationRequestedPacket>().await;
32     ctx.send_hci_event(
33         hci::AuthenticationRequestedStatusBuilder {
34             num_hci_command_packets,
35             status: hci::ErrorCode::Success,
36         }
37         .build(),
38     );
39 
40     ctx.send_hci_event(hci::LinkKeyRequestBuilder { bd_addr: ctx.peer_address() }.build());
41 
42     let status = match ctx.receive_hci_command::<Either<
43         hci::LinkKeyRequestReplyPacket,
44         hci::LinkKeyRequestNegativeReplyPacket,
45     >>().await {
46         Either::Left(_reply) => {
47             ctx.send_hci_event(
48                 hci::LinkKeyRequestReplyCompleteBuilder {
49                     num_hci_command_packets,
50                     status: hci::ErrorCode::Success,
51                     bd_addr: ctx.peer_address(),
52                 }
53                 .build(),
54             );
55             hci::ErrorCode::Success
56         },
57         Either::Right(_) => {
58             ctx.send_hci_event(
59                 hci::LinkKeyRequestNegativeReplyCompleteBuilder {
60                     num_hci_command_packets,
61                     status: hci::ErrorCode::Success,
62                     bd_addr: ctx.peer_address(),
63                 }
64                 .build(),
65             );
66 
67             let result = if features::supported_on_both_page1(ctx, hci::LMPFeaturesPage1Bits::SecureSimplePairingHostSupport).await {
68                 secure_simple_pairing::initiate(ctx).await
69             } else {
70                 legacy_pairing::initiate(ctx).await
71             };
72 
73             match result {
74                 Ok(_) => hci::ErrorCode::Success,
75                 Err(_) => hci::ErrorCode::AuthenticationFailure
76             }
77         }
78     };
79 
80     ctx.send_hci_event(
81         hci::AuthenticationCompleteBuilder { status, connection_handle: ctx.peer_handle() }.build(),
82     );
83 }
84 
respond(ctx: &impl Context)85 pub async fn respond(ctx: &impl Context) {
86     match ctx.receive_lmp_packet::<Either<
87         lmp::AuRandPacket,
88         Either<lmp::IoCapabilityReqPacket, lmp::InRandPacket>
89     >>()
90     .await
91     {
92         Either::Left(_random_number) => {
93             // TODO: Resolve authentication challenge
94             // TODO: Ask for link key
95             ctx.send_lmp_packet(lmp::SresBuilder { transaction_id: 0, authentication_rsp: [0; 4] }.build());
96         },
97         Either::Right(pairing) => {
98             let _result = match pairing {
99                 Either::Left(io_capability_request) =>
100                     secure_simple_pairing::respond(ctx, io_capability_request).await,
101                 Either::Right(in_rand) =>
102                     legacy_pairing::respond(ctx, in_rand).await,
103             };
104         }
105     }
106 }
107