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