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, static_cast<uint16_t>(event_code),
50                             status, reason, value);
51 }
log_address(const Address & bda,EventCode event_code)52 static void log_address(const Address& bda, EventCode event_code) {
53   uint32_t cmd = android::bluetooth::hci::CMD_UNKNOWN;
54   uint16_t status = android::bluetooth::hci::STATUS_UNKNOWN;
55   uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
56   uint16_t handle = bluetooth::common::kUnknownConnectionHandle;
57   int64_t value = 0;
58   log_classic_pairing_event(ToRawAddress(bda), handle, cmd, static_cast<uint16_t>(event_code),
59                             status, reason, value);
60 }
parse_encryption_change(const EventView event)61 static void parse_encryption_change(const EventView event) {
62   auto change_opt = EncryptionChangeView::CreateOptional(event);
63   log::assert_that(change_opt.has_value(), "assert failed: change_opt.has_value()");
64   auto change = change_opt.value();
65 
66   ErrorCode status = change.GetStatus();
67   uint16_t handle = change.GetConnectionHandle();
68   EncryptionEnabled encr_enable = change.GetEncryptionEnabled();
69 
70   btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status),
71                                 static_cast<uint8_t>(encr_enable), 0);
72   log_classic_pairing_event(
73           ToRawAddress(Address::kEmpty), handle, android::bluetooth::hci::CMD_UNKNOWN,
74           static_cast<uint32_t>(change.GetEventCode()), static_cast<uint16_t>(status),
75           android::bluetooth::hci::STATUS_UNKNOWN, 0);
76 }
parse_encryption_change_v2(const EventView event)77 static void parse_encryption_change_v2(const EventView event) {
78   auto change_opt = EncryptionChangeV2View::CreateOptional(event);
79   log::assert_that(change_opt.has_value(), "assert failed: change_opt.has_value()");
80   auto change = change_opt.value();
81 
82   ErrorCode status = change.GetStatus();
83   uint16_t handle = change.GetConnectionHandle();
84   EncryptionEnabled encr_enable = change.GetEncryptionEnabled();
85   uint8_t key_size = change.GetKeySize();
86 
87   btm_sec_encryption_change_evt(handle, static_cast<tHCI_STATUS>(status),
88                                 static_cast<uint8_t>(encr_enable), key_size);
89   log_classic_pairing_event(
90           ToRawAddress(Address::kEmpty), handle, android::bluetooth::hci::CMD_UNKNOWN,
91           static_cast<uint32_t>(change.GetEventCode()), static_cast<uint16_t>(status),
92           android::bluetooth::hci::STATUS_UNKNOWN, 0);
93 }
parse_change_connection_link_key_complete(const EventView event)94 static void parse_change_connection_link_key_complete(const EventView event) {
95   auto complete_opt = ChangeConnectionLinkKeyCompleteView::CreateOptional(event);
96   log::assert_that(complete_opt.has_value(), "assert failed: complete_opt.has_value()");
97   auto complete = complete_opt.value();
98 
99   log_classic_pairing_event(
100           ToRawAddress(Address::kEmpty), complete.GetConnectionHandle(),
101           android::bluetooth::hci::CMD_UNKNOWN, static_cast<uint32_t>(complete.GetEventCode()),
102           static_cast<uint16_t>(complete.GetStatus()), android::bluetooth::hci::STATUS_UNKNOWN, 0);
103 }
parse_central_link_key_complete(const EventView event)104 static void parse_central_link_key_complete(const EventView event) {
105   auto event_opt = CentralLinkKeyCompleteView::CreateOptional(event);
106   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
107   auto complete = event_opt.value();
108 
109   log::info("Unhandled event: {}", EventCodeText(event.GetEventCode()));
110 }
parse_return_link_keys(const EventView event)111 static void parse_return_link_keys(const EventView event) {
112   auto event_opt = ReturnLinkKeysView::CreateOptional(event);
113   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
114   auto view = event_opt.value();
115 
116   log::info("Unhandled event: {}", EventCodeText(event.GetEventCode()));
117 }
parse_pin_code_request(const EventView event)118 static void parse_pin_code_request(const EventView event) {
119   auto event_opt = PinCodeRequestView::CreateOptional(event);
120   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
121   auto request = event_opt.value();
122   btm_sec_pin_code_request(ToRawAddress(request.GetBdAddr()));
123 }
parse_link_key_request(const EventView event)124 static void parse_link_key_request(const EventView event) {
125   auto event_opt = LinkKeyRequestView::CreateOptional(event);
126   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
127   auto request = event_opt.value();
128 
129   btm_sec_link_key_request(ToRawAddress(request.GetBdAddr()));
130   log_address(request.GetBdAddr(), event.GetEventCode());
131 }
parse_link_key_notification(const EventView event)132 static void parse_link_key_notification(const EventView event) {
133   auto event_opt = LinkKeyNotificationView::CreateOptional(event);
134   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
135   auto notification = event_opt.value();
136 
137   btm_sec_link_key_notification(ToRawAddress(notification.GetBdAddr()), notification.GetLinkKey(),
138                                 static_cast<uint8_t>(notification.GetKeyType()));
139   log_address(notification.GetBdAddr(), event.GetEventCode());
140 }
parse_encryption_key_refresh_complete(const EventView event)141 static void parse_encryption_key_refresh_complete(const EventView event) {
142   auto event_opt = EncryptionKeyRefreshCompleteView::CreateOptional(event);
143   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
144   auto refresh = event_opt.value();
145 
146   btm_sec_encryption_key_refresh_complete(refresh.GetConnectionHandle(),
147                                           static_cast<tHCI_STATUS>(refresh.GetStatus()));
148 }
parse_io_capabilities_req(const EventView event)149 static void parse_io_capabilities_req(const EventView event) {
150   auto event_opt = IoCapabilityRequestView::CreateOptional(event);
151   log::assert_that(event_opt.has_value(), "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(), "assert failed: response_opt.has_value()");
162   auto response = response_opt.value();
163 
164   tBTM_SP_IO_RSP evt_data{
165           .bd_addr = ToRawAddress(response.GetBdAddr()),
166           .io_cap = static_cast<tBTM_IO_CAP>(response.GetIoCapability()),
167           .oob_data = static_cast<tBTM_OOB_DATA>(response.GetOobDataPresent()),
168           .auth_req = static_cast<tBTM_AUTH_REQ>(response.GetAuthenticationRequirements()),
169   };
170 
171   btm_io_capabilities_rsp(evt_data);
172   log_address(response.GetBdAddr(), event.GetEventCode());
173 }
parse_remote_oob_data_request(const EventView event)174 static void parse_remote_oob_data_request(const EventView event) {
175   auto event_opt = RemoteOobDataRequestView::CreateOptional(event);
176   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
177   auto request = event_opt.value();
178 
179   btm_rem_oob_req(ToRawAddress(request.GetBdAddr()));
180   log_address(request.GetBdAddr(), event.GetEventCode());
181 }
parse_simple_pairing_complete(const EventView event)182 static void parse_simple_pairing_complete(const EventView event) {
183   auto event_opt = SimplePairingCompleteView::CreateOptional(event);
184   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
185   auto complete = event_opt.value();
186 
187   btm_simple_pair_complete(ToRawAddress(complete.GetBdAddr()),
188                            static_cast<uint8_t>(complete.GetStatus()));
189   log_address_and_status(complete.GetBdAddr(), event.GetEventCode(), complete.GetStatus());
190 }
parse_user_passkey_notification(const EventView event)191 static void parse_user_passkey_notification(const EventView event) {
192   auto event_opt = UserPasskeyNotificationView::CreateOptional(event);
193   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
194   auto notification = event_opt.value();
195 
196   btm_proc_sp_req_evt(BTM_SP_KEY_NOTIF_EVT, ToRawAddress(notification.GetBdAddr()),
197                       notification.GetPasskey());
198   log_address(notification.GetBdAddr(), event.GetEventCode());
199 }
parse_keypress_notification(const EventView event)200 static void parse_keypress_notification(const EventView event) {
201   auto event_opt = KeypressNotificationView::CreateOptional(event);
202   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
203   auto notification = event_opt.value();
204 
205   log::info("Unhandled event: {}", EventCodeText(event.GetEventCode()));
206   log_address(notification.GetBdAddr(), event.GetEventCode());
207 }
parse_user_confirmation_request(const EventView event)208 static void parse_user_confirmation_request(const EventView event) {
209   auto event_opt = UserConfirmationRequestView::CreateOptional(event);
210   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
211   auto request = event_opt.value();
212 
213   btm_proc_sp_req_evt(BTM_SP_CFM_REQ_EVT, ToRawAddress(request.GetBdAddr()),
214                       request.GetNumericValue());
215   log_address(request.GetBdAddr(), event.GetEventCode());
216 }
parse_user_passkey_request(const EventView event)217 static void parse_user_passkey_request(const EventView event) {
218   auto event_opt = UserPasskeyRequestView::CreateOptional(event);
219   log::assert_that(event_opt.has_value(), "assert failed: event_opt.has_value()");
220   auto request = event_opt.value();
221 
222   btm_proc_sp_req_evt(BTM_SP_KEY_REQ_EVT, ToRawAddress(request.GetBdAddr()),
223                       0 /* No value needed */);
224   log_address(request.GetBdAddr(), event.GetEventCode());
225 }
226 }  // namespace
227 }  // namespace bluetooth::stack::btm
228 
229 namespace bluetooth::stack::btm {
230 
OnSecurityEvent(bluetooth::hci::EventView event)231 void SecurityEventParser::OnSecurityEvent(bluetooth::hci::EventView event) {
232   switch (event.GetEventCode()) {
233     case EventCode::ENCRYPTION_CHANGE:
234       parse_encryption_change(event);
235       break;
236     case EventCode::CHANGE_CONNECTION_LINK_KEY_COMPLETE:
237       parse_change_connection_link_key_complete(event);
238       break;
239     case EventCode::CENTRAL_LINK_KEY_COMPLETE:
240       parse_central_link_key_complete(event);
241       break;
242     case EventCode::RETURN_LINK_KEYS:
243       parse_return_link_keys(event);
244       break;
245     case EventCode::PIN_CODE_REQUEST:
246       parse_pin_code_request(event);
247       break;
248     case EventCode::LINK_KEY_REQUEST:
249       parse_link_key_request(event);
250       break;
251     case EventCode::LINK_KEY_NOTIFICATION:
252       parse_link_key_notification(event);
253       break;
254     case EventCode::ENCRYPTION_KEY_REFRESH_COMPLETE:
255       parse_encryption_key_refresh_complete(event);
256       break;
257     case EventCode::IO_CAPABILITY_REQUEST:
258       parse_io_capabilities_req(event);
259       break;
260     case EventCode::IO_CAPABILITY_RESPONSE:
261       parse_io_capabilities_rsp(event);
262       break;
263     case EventCode::REMOTE_OOB_DATA_REQUEST:
264       parse_remote_oob_data_request(event);
265       break;
266     case EventCode::SIMPLE_PAIRING_COMPLETE:
267       parse_simple_pairing_complete(event);
268       break;
269     case EventCode::USER_PASSKEY_NOTIFICATION:
270       parse_user_passkey_notification(event);
271       break;
272     case EventCode::KEYPRESS_NOTIFICATION:
273       parse_keypress_notification(event);
274       break;
275     case EventCode::USER_CONFIRMATION_REQUEST:
276       parse_user_confirmation_request(event);
277       break;
278     case EventCode::USER_PASSKEY_REQUEST:
279       parse_user_passkey_request(event);
280       break;
281     case EventCode::ENCRYPTION_CHANGE_V2:
282       parse_encryption_change_v2(event);
283       break;
284     default:
285       log::error("Unhandled event {}", EventCodeText(event.GetEventCode()));
286   }
287 }
288 }  // namespace bluetooth::stack::btm
289