1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "security_event_parser.h"
18 
19 #include <bluetooth/log.h>
20 
21 #include <optional>
22 #include <string>
23 
24 #include "btm_sec.h"
25 #include "common/metrics.h"
26 #include "hci/hci_packets.h"
27 #include "main/shim/helpers.h"
28 #include "stack/include/btm_sec_api_types.h"
29 #include "stack/include/hci_error_code.h"
30 #include "stack/include/sec_hci_link_interface.h"
31 #include "stack/include/stack_metrics_logging.h"
32 #include "types/raw_address.h"
33 
34 using namespace bluetooth;
35 using namespace bluetooth::hci;
36 using android::bluetooth::hci::CMD_UNKNOWN;
37 using android::bluetooth::hci::STATUS_UNKNOWN;
38 using bluetooth::common::kUnknownConnectionHandle;
39 
40 namespace bluetooth::stack::btm {
41 namespace {
log_address_and_status(const Address & bda,EventCode event_code,ErrorCode event_status)42 static void log_address_and_status(const Address& bda, EventCode event_code,
43                                    ErrorCode event_status) {
44   uint32_t cmd = android::bluetooth::hci::CMD_UNKNOWN;
45   uint16_t status = static_cast<uint16_t>(event_status);
46   uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
47   uint16_t handle = bluetooth::common::kUnknownConnectionHandle;
48   int64_t value = 0;
49   log_classic_pairing_event(ToRawAddress(bda), handle, cmd,
50                             static_cast<uint16_t>(event_code), status, reason,
51                             value);
52 }
log_address(const Address & bda,EventCode event_code)53 static void log_address(const Address& bda, EventCode event_code) {
54   uint32_t cmd = android::bluetooth::hci::CMD_UNKNOWN;
55   uint16_t status = android::bluetooth::hci::STATUS_UNKNOWN;
56   uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
57   uint16_t handle = bluetooth::common::kUnknownConnectionHandle;
58   int64_t value = 0;
59   log_classic_pairing_event(ToRawAddress(bda), handle, cmd,
60                             static_cast<uint16_t>(event_code), status, reason,
61                             value);
62 }
parse_encryption_change(const EventView event)63 static void parse_encryption_change(const EventView event) {
64   auto change_opt = EncryptionChangeView::CreateOptional(event);
65   log::assert_that(change_opt.has_value(),
66                    "assert failed: change_opt.has_value()");
67   auto change = change_opt.value();
68 
69   ErrorCode status = change.GetStatus();
70   uint16_t handle = change.GetConnectionHandle();
71   EncryptionEnabled encr_enable = change.GetEncryptionEnabled();
72 
73   btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status),
74                                 static_cast<uint8_t>(encr_enable));
75   log_classic_pairing_event(ToRawAddress(Address::kEmpty), handle,
76                             android::bluetooth::hci::CMD_UNKNOWN,
77                             static_cast<uint32_t>(change.GetEventCode()),
78                             static_cast<uint16_t>(status),
79                             android::bluetooth::hci::STATUS_UNKNOWN, 0);
80 }
parse_change_connection_link_key_complete(const EventView event)81 static void parse_change_connection_link_key_complete(const EventView event) {
82   auto complete_opt =
83       ChangeConnectionLinkKeyCompleteView::CreateOptional(event);
84   log::assert_that(complete_opt.has_value(),
85                    "assert failed: complete_opt.has_value()");
86   auto complete = complete_opt.value();
87 
88   log_classic_pairing_event(ToRawAddress(Address::kEmpty),
89                             complete.GetConnectionHandle(),
90                             android::bluetooth::hci::CMD_UNKNOWN,
91                             static_cast<uint32_t>(complete.GetEventCode()),
92                             static_cast<uint16_t>(complete.GetStatus()),
93                             android::bluetooth::hci::STATUS_UNKNOWN, 0);
94 }
parse_central_link_key_complete(const EventView event)95 static void parse_central_link_key_complete(const EventView event) {
96   auto event_opt = CentralLinkKeyCompleteView::CreateOptional(event);
97   log::assert_that(event_opt.has_value(),
98                    "assert failed: event_opt.has_value()");
99   auto complete = event_opt.value();
100 
101   log::info("Unhandled event: {}", EventCodeText(event.GetEventCode()));
102 }
parse_return_link_keys(const EventView event)103 static void parse_return_link_keys(const EventView event) {
104   auto event_opt = ReturnLinkKeysView::CreateOptional(event);
105   log::assert_that(event_opt.has_value(),
106                    "assert failed: event_opt.has_value()");
107   auto view = event_opt.value();
108 
109   log::info("Unhandled event: {}", EventCodeText(event.GetEventCode()));
110 }
parse_pin_code_request(const EventView event)111 static void parse_pin_code_request(const EventView event) {
112   auto event_opt = PinCodeRequestView::CreateOptional(event);
113   log::assert_that(event_opt.has_value(),
114                    "assert failed: event_opt.has_value()");
115   auto request = event_opt.value();
116   btm_sec_pin_code_request(ToRawAddress(request.GetBdAddr()));
117 }
parse_link_key_request(const EventView event)118 static void parse_link_key_request(const EventView event) {
119   auto event_opt = LinkKeyRequestView::CreateOptional(event);
120   log::assert_that(event_opt.has_value(),
121                    "assert failed: event_opt.has_value()");
122   auto request = event_opt.value();
123 
124   btm_sec_link_key_request(ToRawAddress(request.GetBdAddr()));
125   log_address(request.GetBdAddr(), event.GetEventCode());
126 }
parse_link_key_notification(const EventView event)127 static void parse_link_key_notification(const EventView event) {
128   auto event_opt = LinkKeyNotificationView::CreateOptional(event);
129   log::assert_that(event_opt.has_value(),
130                    "assert failed: event_opt.has_value()");
131   auto notification = event_opt.value();
132 
133   btm_sec_link_key_notification(
134       ToRawAddress(notification.GetBdAddr()), notification.GetLinkKey(),
135       static_cast<uint8_t>(notification.GetKeyType()));
136   log_address(notification.GetBdAddr(), event.GetEventCode());
137 }
parse_encryption_key_refresh_complete(const EventView event)138 static void parse_encryption_key_refresh_complete(const EventView event) {
139   auto event_opt = EncryptionKeyRefreshCompleteView::CreateOptional(event);
140   log::assert_that(event_opt.has_value(),
141                    "assert failed: event_opt.has_value()");
142   auto refresh = event_opt.value();
143 
144   btm_sec_encryption_key_refresh_complete(
145       refresh.GetConnectionHandle(),
146       static_cast<tHCI_STATUS>(refresh.GetStatus()));
147 }
parse_io_capabilities_req(const EventView event)148 static void parse_io_capabilities_req(const EventView event) {
149   auto event_opt = IoCapabilityRequestView::CreateOptional(event);
150   log::assert_that(event_opt.has_value(),
151                    "assert failed: event_opt.has_value()");
152   auto request = event_opt.value();
153 
154   RawAddress peer = ToRawAddress(request.GetBdAddr());
155 
156   btm_io_capabilities_req(peer);
157   log_address(request.GetBdAddr(), event.GetEventCode());
158 }
parse_io_capabilities_rsp(const EventView event)159 static void parse_io_capabilities_rsp(const EventView event) {
160   auto response_opt = IoCapabilityResponseView::CreateOptional(event);
161   log::assert_that(response_opt.has_value(),
162                    "assert failed: response_opt.has_value()");
163   auto response = response_opt.value();
164 
165   tBTM_SP_IO_RSP evt_data{
166       .bd_addr = ToRawAddress(response.GetBdAddr()),
167       .io_cap = static_cast<tBTM_IO_CAP>(response.GetIoCapability()),
168       .oob_data = static_cast<tBTM_OOB_DATA>(response.GetOobDataPresent()),
169       .auth_req =
170           static_cast<tBTM_AUTH_REQ>(response.GetAuthenticationRequirements()),
171   };
172 
173   btm_io_capabilities_rsp(evt_data);
174   log_address(response.GetBdAddr(), event.GetEventCode());
175 }
parse_remote_oob_data_request(const EventView event)176 static void parse_remote_oob_data_request(const EventView event) {
177   auto event_opt = RemoteOobDataRequestView::CreateOptional(event);
178   log::assert_that(event_opt.has_value(),
179                    "assert failed: event_opt.has_value()");
180   auto request = event_opt.value();
181 
182   btm_rem_oob_req(ToRawAddress(request.GetBdAddr()));
183   log_address(request.GetBdAddr(), event.GetEventCode());
184 }
parse_simple_pairing_complete(const EventView event)185 static void parse_simple_pairing_complete(const EventView event) {
186   auto event_opt = SimplePairingCompleteView::CreateOptional(event);
187   log::assert_that(event_opt.has_value(),
188                    "assert failed: event_opt.has_value()");
189   auto complete = event_opt.value();
190 
191   btm_simple_pair_complete(ToRawAddress(complete.GetBdAddr()),
192                            static_cast<uint8_t>(complete.GetStatus()));
193   log_address_and_status(complete.GetBdAddr(), event.GetEventCode(),
194                          complete.GetStatus());
195 }
parse_user_passkey_notification(const EventView event)196 static void parse_user_passkey_notification(const EventView event) {
197   auto event_opt = UserPasskeyNotificationView::CreateOptional(event);
198   log::assert_that(event_opt.has_value(),
199                    "assert failed: event_opt.has_value()");
200   auto notification = event_opt.value();
201 
202   btm_proc_sp_req_evt(BTM_SP_KEY_NOTIF_EVT,
203                       ToRawAddress(notification.GetBdAddr()),
204                       notification.GetPasskey());
205   log_address(notification.GetBdAddr(), event.GetEventCode());
206 }
parse_keypress_notification(const EventView event)207 static void parse_keypress_notification(const EventView event) {
208   auto event_opt = KeypressNotificationView::CreateOptional(event);
209   log::assert_that(event_opt.has_value(),
210                    "assert failed: event_opt.has_value()");
211   auto notification = event_opt.value();
212 
213   log::info("Unhandled event: {}", EventCodeText(event.GetEventCode()));
214   log_address(notification.GetBdAddr(), event.GetEventCode());
215 }
parse_user_confirmation_request(const EventView event)216 static void parse_user_confirmation_request(const EventView event) {
217   auto event_opt = UserConfirmationRequestView::CreateOptional(event);
218   log::assert_that(event_opt.has_value(),
219                    "assert failed: event_opt.has_value()");
220   auto request = event_opt.value();
221 
222   btm_proc_sp_req_evt(BTM_SP_CFM_REQ_EVT, ToRawAddress(request.GetBdAddr()),
223                       request.GetNumericValue());
224   log_address(request.GetBdAddr(), event.GetEventCode());
225 }
parse_user_passkey_request(const EventView event)226 static void parse_user_passkey_request(const EventView event) {
227   auto event_opt = UserPasskeyRequestView::CreateOptional(event);
228   log::assert_that(event_opt.has_value(),
229                    "assert failed: event_opt.has_value()");
230   auto request = event_opt.value();
231 
232   btm_proc_sp_req_evt(BTM_SP_KEY_REQ_EVT, ToRawAddress(request.GetBdAddr()),
233                       0 /* No value needed */);
234   log_address(request.GetBdAddr(), event.GetEventCode());
235 }
236 }  // namespace
237 }  // namespace bluetooth::stack::btm
238 
239 namespace bluetooth::stack::btm {
240 
OnSecurityEvent(bluetooth::hci::EventView event)241 void SecurityEventParser::OnSecurityEvent(bluetooth::hci::EventView event) {
242   switch (event.GetEventCode()) {
243     case EventCode::ENCRYPTION_CHANGE:
244       parse_encryption_change(event);
245       break;
246     case EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE:
247       parse_change_connection_link_key_complete(event);
248       break;
249     case EventCode::CENTRAL_LINK_KEY_COMPLETE:
250       parse_central_link_key_complete(event);
251       break;
252     case EventCode::RETURN_LINK_KEYS:
253       parse_return_link_keys(event);
254       break;
255     case EventCode::PIN_CODE_REQUEST:
256       parse_pin_code_request(event);
257       break;
258     case EventCode::LINK_KEY_REQUEST:
259       parse_link_key_request(event);
260       break;
261     case EventCode::LINK_KEY_NOTIFICATION:
262       parse_link_key_notification(event);
263       break;
264     case EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE:
265       parse_encryption_key_refresh_complete(event);
266       break;
267     case EventCode::IO_CAPABILITY_REQUEST:
268       parse_io_capabilities_req(event);
269       break;
270     case EventCode::IO_CAPABILITY_RESPONSE:
271       parse_io_capabilities_rsp(event);
272       break;
273     case EventCode::REMOTE_OOB_DATA_REQUEST:
274       parse_remote_oob_data_request(event);
275       break;
276     case EventCode::SIMPLE_PAIRING_COMPLETE:
277       parse_simple_pairing_complete(event);
278       break;
279     case EventCode::USER_PASSKEY_NOTIFICATION:
280       parse_user_passkey_notification(event);
281       break;
282     case EventCode::KEYPRESS_NOTIFICATION:
283       parse_keypress_notification(event);
284       break;
285     case EventCode::USER_CONFIRMATION_REQUEST:
286       parse_user_confirmation_request(event);
287       break;
288     case EventCode::USER_PASSKEY_REQUEST:
289       parse_user_passkey_request(event);
290       break;
291     default:
292       log::error("Unhandled event {}", EventCodeText(event.GetEventCode()));
293   }
294 }
295 }  // namespace bluetooth::stack::btm
296