1 // Copyright 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Bluetooth Core, Vol 2, Part C, 4.2.2
16 
17 use crate::lmp::procedure::{authentication, Context};
18 use crate::packets::{hci, lmp};
19 
20 use crate::num_hci_command_packets;
21 
initiate(ctx: &impl Context) -> Result<(), ()>22 pub async fn initiate(ctx: &impl Context) -> Result<(), ()> {
23     ctx.send_hci_event(hci::PinCodeRequestBuilder { bd_addr: ctx.peer_address() }.build());
24 
25     let _pin_code = ctx.receive_hci_command::<hci::PinCodeRequestReply>().await;
26 
27     ctx.send_hci_event(
28         hci::PinCodeRequestReplyCompleteBuilder {
29             num_hci_command_packets: 1,
30             status: hci::ErrorCode::Success,
31             bd_addr: ctx.peer_address(),
32         }
33         .build(),
34     );
35 
36     // TODO: handle result
37     let _ = ctx
38         .send_accepted_lmp_packet(
39             lmp::InRandBuilder { transaction_id: 0, random_number: [0; 16] }.build(),
40         )
41         .await;
42 
43     ctx.send_lmp_packet(lmp::CombKeyBuilder { transaction_id: 0, random_number: [0; 16] }.build());
44 
45     let _ = ctx.receive_lmp_packet::<lmp::CombKey>().await;
46 
47     // Post pairing authentication
48     let link_key = [0; 16];
49     let auth_result = authentication::send_challenge(ctx, 0, link_key).await;
50     authentication::receive_challenge(ctx, link_key).await;
51 
52     if auth_result.is_err() {
53         return Err(());
54     }
55     ctx.send_hci_event(
56         hci::LinkKeyNotificationBuilder {
57             bd_addr: ctx.peer_address(),
58             key_type: hci::KeyType::Combination,
59             link_key,
60         }
61         .build(),
62     );
63 
64     Ok(())
65 }
66 
respond(ctx: &impl Context, _request: lmp::InRand) -> Result<(), ()>67 pub async fn respond(ctx: &impl Context, _request: lmp::InRand) -> Result<(), ()> {
68     ctx.send_hci_event(hci::PinCodeRequestBuilder { bd_addr: ctx.peer_address() }.build());
69 
70     let _pin_code = ctx.receive_hci_command::<hci::PinCodeRequestReply>().await;
71 
72     ctx.send_hci_event(
73         hci::PinCodeRequestReplyCompleteBuilder {
74             num_hci_command_packets,
75             status: hci::ErrorCode::Success,
76             bd_addr: ctx.peer_address(),
77         }
78         .build(),
79     );
80 
81     ctx.send_lmp_packet(
82         lmp::AcceptedBuilder { transaction_id: 0, accepted_opcode: lmp::Opcode::InRand }.build(),
83     );
84 
85     let _ = ctx.receive_lmp_packet::<lmp::CombKey>().await;
86 
87     ctx.send_lmp_packet(lmp::CombKeyBuilder { transaction_id: 0, random_number: [0; 16] }.build());
88 
89     // Post pairing authentication
90     let link_key = [0; 16];
91     authentication::receive_challenge(ctx, link_key).await;
92     let auth_result = authentication::send_challenge(ctx, 0, link_key).await;
93 
94     if auth_result.is_err() {
95         return Err(());
96     }
97     ctx.send_hci_event(
98         hci::LinkKeyNotificationBuilder {
99             bd_addr: ctx.peer_address(),
100             key_type: hci::KeyType::Combination,
101             link_key,
102         }
103         .build(),
104     );
105 
106     Ok(())
107 }
108