blob: e854efec4b92f99ae49f50f465e11e62abcaa8f3 [file] [log] [blame]
Martin Brabham80854c22019-11-12 14:52:42 -08001/*
2 *
3 * Copyright 2019 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18#include "security/pairing/classic_pairing_handler.h"
19
20namespace bluetooth {
21namespace security {
22namespace pairing {
23
24void ClassicPairingHandler::OnRegistrationComplete(
25 l2cap::classic::FixedChannelManager::RegistrationResult result,
26 std::unique_ptr<l2cap::classic::FixedChannelService> fixed_channel_service) {
27 fixed_channel_service_ = std::move(fixed_channel_service);
28 fixed_channel_manager_->ConnectServices(
29 GetRecord()->GetDevice().GetAddress(),
30 common::Bind(&ClassicPairingHandler::OnConnectionFail, common::Unretained(this)), security_handler_);
31}
32
33void ClassicPairingHandler::OnUnregistered() {
34 std::move(complete_callback_).Run(GetRecord()->GetDevice().GetAddress());
35}
36
37void ClassicPairingHandler::OnConnectionOpen(std::unique_ptr<l2cap::classic::FixedChannel> fixed_channel) {
38 ASSERT(fixed_channel_ == nullptr);
39 fixed_channel_ = std::move(fixed_channel);
40 fixed_channel_->Acquire();
41 fixed_channel_->RegisterOnCloseCallback(
42 security_handler_, common::BindOnce(&ClassicPairingHandler::OnConnectionClose, common::Unretained(this)));
43}
44
45void ClassicPairingHandler::OnConnectionFail(l2cap::classic::FixedChannelManager::ConnectionResult result) {
46 Cancel();
47}
48void ClassicPairingHandler::OnConnectionClose(hci::ErrorCode error_code) {
49 // Called when the connection gets closed
50 LOG_ERROR("Connection closed due to: %s", hci::ErrorCodeText(error_code).c_str());
51 ASSERT(fixed_channel_ != nullptr);
52 Cancel();
53}
54
55void ClassicPairingHandler::Initiate(bool locally_initiated, hci::IoCapability io_capability,
56 hci::OobDataPresent oob_present,
57 hci::AuthenticationRequirements auth_requirements) {
58 locally_initiated_ = locally_initiated;
59 local_io_capability_ = io_capability;
60 local_oob_present_ = oob_present;
61 local_authentication_requirements_ = auth_requirements;
62
63 // TODO(optedoblivion): Read OOB data
64 // if host and controller support secure connections used HCIREADLOCALOOBEXTENDEDDATA vs HCIREADLOCALOOBDATA
65
66 fixed_channel_manager_->RegisterService(
67 l2cap::kClassicPairingTriggerCid, security_policy_,
68 common::Bind(&ClassicPairingHandler::OnRegistrationComplete, common::Unretained(this)),
69 common::Bind(&ClassicPairingHandler::OnConnectionOpen, common::Unretained(this)), security_handler_);
70}
71
72void ClassicPairingHandler::Cancel() {
73 if (fixed_channel_ != nullptr) {
74 fixed_channel_->Release();
75 }
76 if (fixed_channel_service_ != nullptr) {
77 fixed_channel_service_->Unregister(common::Bind(&ClassicPairingHandler::OnUnregistered, common::Unretained(this)),
78 security_handler_);
79 }
80}
81
82void ClassicPairingHandler::OnReceive(hci::ChangeConnectionLinkKeyCompleteView packet) {
83 ASSERT(packet.IsValid());
84 LOG_INFO("Received unsupported event: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
85}
86
87void ClassicPairingHandler::OnReceive(hci::MasterLinkKeyCompleteView packet) {
88 ASSERT(packet.IsValid());
89 LOG_INFO("Received unsupported event: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
90}
91
92void ClassicPairingHandler::OnReceive(hci::PinCodeRequestView packet) {
93 ASSERT(packet.IsValid());
94 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
95 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
96}
97
98void ClassicPairingHandler::OnReceive(hci::LinkKeyRequestView packet) {
99 ASSERT(packet.IsValid());
100 // TODO(optedoblivion): Add collision detection here
101 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
102 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
103 if (GetRecord()->IsBonded() || GetRecord()->IsPaired()) {
104 auto packet =
105 hci::LinkKeyRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress(), GetRecord()->GetLinkKey());
106 this->GetChannel()->SendCommand(std::move(packet));
107 } else {
108 auto packet = hci::LinkKeyRequestNegativeReplyBuilder::Create(GetRecord()->GetDevice().GetAddress());
109 this->GetChannel()->SendCommand(std::move(packet));
110 }
111}
112
113void ClassicPairingHandler::OnReceive(hci::LinkKeyNotificationView packet) {
114 ASSERT(packet.IsValid());
115 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
116 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
117 GetRecord()->SetLinkKey(packet.GetLinkKey(), packet.GetKeyType());
118}
119
120void ClassicPairingHandler::OnReceive(hci::IoCapabilityRequestView packet) {
121 ASSERT(packet.IsValid());
122 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
123 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
124 hci::IoCapability io_capability = local_io_capability_;
125 hci::OobDataPresent oob_present = hci::OobDataPresent::NOT_PRESENT;
126 hci::AuthenticationRequirements authentication_requirements = local_authentication_requirements_;
127 auto reply_packet = hci::IoCapabilityRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress(), io_capability,
128 oob_present, authentication_requirements);
129 this->GetChannel()->SendCommand(std::move(reply_packet));
130}
131
132void ClassicPairingHandler::OnReceive(hci::IoCapabilityResponseView packet) {
133 ASSERT(packet.IsValid());
134 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
135 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
136
137 // Using local variable until device database pointer is ready
138 remote_io_capability_ = packet.GetIoCapability();
139 // TODO(optedoblivion): device->SetIoCapability(packet.GetIoCapability);
140}
141
142void ClassicPairingHandler::OnReceive(hci::SimplePairingCompleteView packet) {
143 ASSERT(packet.IsValid());
144 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
145 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
146 Cancel();
147}
148
149void ClassicPairingHandler::OnReceive(hci::ReturnLinkKeysView packet) {
150 ASSERT(packet.IsValid());
151 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
152}
153
154void ClassicPairingHandler::OnReceive(hci::EncryptionChangeView packet) {
155 ASSERT(packet.IsValid());
156 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
157}
158
159void ClassicPairingHandler::OnReceive(hci::EncryptionKeyRefreshCompleteView packet) {
160 ASSERT(packet.IsValid());
161 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
162}
163
164void ClassicPairingHandler::OnReceive(hci::RemoteOobDataRequestView packet) {
165 ASSERT(packet.IsValid());
166 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
167 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
168}
169
170void ClassicPairingHandler::OnReceive(hci::UserPasskeyNotificationView packet) {
171 ASSERT(packet.IsValid());
172 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
173 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
174}
175
176void ClassicPairingHandler::OnReceive(hci::KeypressNotificationView packet) {
177 ASSERT(packet.IsValid());
178 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
179 LOG_INFO("Notification Type: %s", hci::KeypressNotificationTypeText(packet.GetNotificationType()).c_str());
180 switch (packet.GetNotificationType()) {
181 case hci::KeypressNotificationType::ENTRY_STARTED:
182 // Get ready to keep track of key input
183 break;
184 case hci::KeypressNotificationType::DIGIT_ENTERED:
185 // Append digit to key
186 break;
187 case hci::KeypressNotificationType::DIGIT_ERASED:
188 // erase last digit from key
189 break;
190 case hci::KeypressNotificationType::CLEARED:
191 // erase all digits from key
192 break;
193 case hci::KeypressNotificationType::ENTRY_COMPLETED:
194 // set full key to security record
195 break;
196 }
197}
198
199/**
200 * Here we decide what type of pairing authentication method we will use
201 *
202 * The table is on pg 2133 of the Core v5.1 spec.
203 */
204void ClassicPairingHandler::OnReceive(hci::UserConfirmationRequestView packet) {
205 ASSERT(packet.IsValid());
206 LOG_INFO("Received: %s", hci::EventCodeText(packet.GetEventCode()).c_str());
207 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
208 // if locally_initialized, use default, otherwise us remote io caps
209 hci::IoCapability initiator_io_capability = (locally_initiated_) ? local_io_capability_ : remote_io_capability_;
210 hci::IoCapability responder_io_capability = (!locally_initiated_) ? local_io_capability_ : remote_io_capability_;
211 // TODO(optedoblivion): Check for TEMPORARY pairing case
212 switch (initiator_io_capability) {
213 case hci::IoCapability::DISPLAY_ONLY:
214 switch (responder_io_capability) {
215 case hci::IoCapability::DISPLAY_ONLY:
216 // NumericComparison, Both auto confirm
217 LOG_INFO("Numeric Comparison: A and B auto confirm");
218 GetChannel()->SendCommand(
219 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
220 // Unauthenticated
221 break;
222 case hci::IoCapability::DISPLAY_YES_NO:
223 // NumericComparison, Initiator auto confirm, Responder display
224 GetChannel()->SendCommand(
225 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
226 LOG_INFO("Numeric Comparison: A auto confirm");
227 // Unauthenticated
228 break;
229 case hci::IoCapability::KEYBOARD_ONLY:
230 // PassKey Entry, Initiator display, Responder input
231 // TODO(optedoblivion): Notify UI
232 LOG_INFO("Notify UI");
233 // Authenticated
234 break;
235 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
236 // NumericComparison, Both auto confirm
237 LOG_INFO("Numeric Comparison: A and B auto confirm");
238 GetChannel()->SendCommand(
239 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
240 // Unauthenticated
241 break;
242 }
243 break;
244 case hci::IoCapability::DISPLAY_YES_NO:
245 switch (responder_io_capability) {
246 case hci::IoCapability::DISPLAY_ONLY:
247 // NumericComparison, Initiator display, Responder auto confirm
248 // TODO(optedoblivion): Notify UI
249 LOG_INFO("Notify UI");
250 // Unauthenticated
251 break;
252 case hci::IoCapability::DISPLAY_YES_NO:
253 // NumericComparison Both Display, Both confirm
254 // TODO(optedoblivion): Notify UI
255 LOG_INFO("Notify UI");
256 // Authenticated
257 break;
258 case hci::IoCapability::KEYBOARD_ONLY:
259 // PassKey Entry, Initiator display, Responder input
260 // TODO(optedoblivion): Notify UI
261 LOG_INFO("Notify UI");
262 // Authenticated
263 break;
264 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
265 // NumericComparison, auto confirm Responder, Yes/No confirm Initiator. Don't show confirmation value
266 // TODO(optedoblivion): Notify UI
267 LOG_INFO("Notify UI");
268 // Unauthenticated
269 break;
270 }
271 break;
272 case hci::IoCapability::KEYBOARD_ONLY:
273 switch (responder_io_capability) {
274 case hci::IoCapability::DISPLAY_ONLY:
275 // PassKey Entry, Responder display, Initiator input
276 // TODO(optedoblivion): Notify UI
277 LOG_INFO("Notify UI");
278 // Authenticated
279 break;
280 case hci::IoCapability::DISPLAY_YES_NO:
281 // PassKey Entry, Responder display, Initiator input
282 // TODO(optedoblivion): Notify UI
283 LOG_INFO("Notify UI");
284 // Authenticated
285 break;
286 case hci::IoCapability::KEYBOARD_ONLY:
287 // PassKey Entry, both input
288 // TODO(optedoblivion): Notify UI
289 LOG_INFO("Notify UI");
290 // Authenticated
291 break;
292 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
293 // NumericComparison, both auto confirm
294 LOG_INFO("Numeric Comparison: A and B auto confirm");
295 GetChannel()->SendCommand(
296 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
297 // Unauthenticated
298 break;
299 }
300 break;
301 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
302 switch (responder_io_capability) {
303 case hci::IoCapability::DISPLAY_ONLY:
304 // NumericComparison, both auto confirm
305 LOG_INFO("Numeric Comparison: A and B auto confirm");
306 GetChannel()->SendCommand(
307 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
308 // Unauthenticated
309 break;
310 case hci::IoCapability::DISPLAY_YES_NO:
311 // NumericComparison, Initiator auto confirm, Responder Yes/No confirm, no show conf val
312 LOG_INFO("Numeric Comparison: A auto confirm");
313 GetChannel()->SendCommand(
314 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
315 // Unauthenticated
316 break;
317 case hci::IoCapability::KEYBOARD_ONLY:
318 // NumericComparison, both auto confirm
319 LOG_INFO("Numeric Comparison: A and B auto confirm");
320 GetChannel()->SendCommand(
321 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
322 // Unauthenticated
323 break;
324 case hci::IoCapability::NO_INPUT_NO_OUTPUT:
325 // NumericComparison, both auto confirm
326 LOG_INFO("Numeric Comparison: A and B auto confirm");
327 GetChannel()->SendCommand(
328 hci::UserConfirmationRequestReplyBuilder::Create(GetRecord()->GetDevice().GetAddress()));
329 // Unauthenticated
330 break;
331 }
332 break;
333 }
334}
335
336void ClassicPairingHandler::OnReceive(hci::UserPasskeyRequestView packet) {
337 ASSERT(packet.IsValid());
338 ASSERT_LOG(GetRecord()->GetDevice().GetAddress() == packet.GetBdAddr(), "Address mismatch");
339}
340
341} // namespace pairing
342} // namespace security
343} // namespace bluetooth