1 /******************************************************************************
2 *
3 * Copyright 1999-2012 Broadcom Corporation
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
19 /******************************************************************************
20 *
21 * This file contains functions for the SMP L2Cap interface
22 *
23 ******************************************************************************/
24
25 #define LOG_TAG "bluetooth"
26
27 #include <base/logging.h>
28 #include <string.h>
29
30 #include "bt_target.h"
31 #include "btm_ble_api.h"
32 #include "common/metrics.h"
33 #include "l2c_api.h"
34 #include "main/shim/dumpsys.h"
35 #include "osi/include/allocator.h"
36 #include "osi/include/log.h"
37 #include "osi/include/osi.h" // UNUSED_ATTR
38 #include "smp_int.h"
39 #include "stack/btm/btm_dev.h"
40 #include "stack/include/bt_hdr.h"
41 #include "types/raw_address.h"
42
43 static void smp_connect_callback(uint16_t channel, const RawAddress& bd_addr,
44 bool connected, uint16_t reason,
45 tBT_TRANSPORT transport);
46 static void smp_data_received(uint16_t channel, const RawAddress& bd_addr,
47 BT_HDR* p_buf);
48
49 static void smp_br_connect_callback(uint16_t channel, const RawAddress& bd_addr,
50 bool connected, uint16_t reason,
51 tBT_TRANSPORT transport);
52 static void smp_br_data_received(uint16_t channel, const RawAddress& bd_addr,
53 BT_HDR* p_buf);
54
55 /*******************************************************************************
56 *
57 * Function smp_l2cap_if_init
58 *
59 * Description This function is called during the SMP task startup
60 * to register interface functions with L2CAP.
61 *
62 ******************************************************************************/
smp_l2cap_if_init(void)63 void smp_l2cap_if_init(void) {
64 tL2CAP_FIXED_CHNL_REG fixed_reg;
65 SMP_TRACE_EVENT("SMDBG l2c %s", __func__);
66
67 fixed_reg.pL2CA_FixedConn_Cb = smp_connect_callback;
68 fixed_reg.pL2CA_FixedData_Cb = smp_data_received;
69
70 fixed_reg.pL2CA_FixedCong_Cb =
71 NULL; /* do not handle congestion on this channel */
72 fixed_reg.default_idle_tout =
73 60; /* set 60 seconds timeout, 0xffff default idle timeout */
74
75 L2CA_RegisterFixedChannel(L2CAP_SMP_CID, &fixed_reg);
76
77 fixed_reg.pL2CA_FixedConn_Cb = smp_br_connect_callback;
78 fixed_reg.pL2CA_FixedData_Cb = smp_br_data_received;
79
80 L2CA_RegisterFixedChannel(L2CAP_SMP_BR_CID, &fixed_reg);
81 }
82
83 /*******************************************************************************
84 *
85 * Function smp_connect_callback
86 *
87 * Description This callback function is called by L2CAP to indicate that
88 * SMP channel is
89 * connected (conn = true)/disconnected (conn = false).
90 *
91 ******************************************************************************/
smp_connect_callback(UNUSED_ATTR uint16_t channel,const RawAddress & bd_addr,bool connected,UNUSED_ATTR uint16_t reason,tBT_TRANSPORT transport)92 static void smp_connect_callback(UNUSED_ATTR uint16_t channel,
93 const RawAddress& bd_addr, bool connected,
94 UNUSED_ATTR uint16_t reason,
95 tBT_TRANSPORT transport) {
96 tSMP_CB* p_cb = &smp_cb;
97 tSMP_INT_DATA int_data;
98
99 if (bd_addr.IsEmpty()) {
100 LOG_WARN("Received unexpected callback for empty address");
101 return;
102 }
103
104 if (transport == BT_TRANSPORT_BR_EDR) {
105 LOG_WARN("Received unexpected callback on classic channel peer:%s",
106 PRIVATE_ADDRESS(bd_addr));
107 return;
108 }
109
110 if (connected) {
111 LOG_DEBUG("SMP Received connect callback bd_addr:%s transport:%s",
112 PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str());
113 } else {
114 LOG_DEBUG("SMP Received disconnect callback bd_addr:%s transport:%s",
115 PRIVATE_ADDRESS(bd_addr), bt_transport_text(transport).c_str());
116 }
117
118 if (bd_addr == p_cb->pairing_bda) {
119 LOG_DEBUG("Received callback for device in pairing process:%s state:%s",
120 PRIVATE_ADDRESS(bd_addr),
121 (connected) ? "connected" : "disconnected");
122
123 if (connected) {
124 if (!p_cb->connect_initialized) {
125 p_cb->connect_initialized = true;
126 /* initiating connection established */
127 p_cb->role = L2CA_GetBleConnRole(bd_addr);
128
129 /* initialize local i/r key to be default keys */
130 p_cb->local_r_key = p_cb->local_i_key = SMP_SEC_DEFAULT_KEY;
131 p_cb->loc_auth_req = p_cb->peer_auth_req = SMP_DEFAULT_AUTH_REQ;
132 p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
133 smp_sm_event(p_cb, SMP_L2CAP_CONN_EVT, NULL);
134 }
135 } else {
136 /* Disconnected while doing security */
137 smp_sm_event(p_cb, SMP_L2CAP_DISCONN_EVT, &int_data);
138 }
139 }
140 }
141
142 /*******************************************************************************
143 *
144 * Function smp_data_received
145 *
146 * Description This function is called when data is received from L2CAP on
147 * SMP channel.
148 *
149 *
150 * Returns void
151 *
152 ******************************************************************************/
smp_data_received(uint16_t channel,const RawAddress & bd_addr,BT_HDR * p_buf)153 static void smp_data_received(uint16_t channel, const RawAddress& bd_addr,
154 BT_HDR* p_buf) {
155 tSMP_CB* p_cb = &smp_cb;
156 uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
157 uint8_t cmd;
158
159 if (p_buf->len < 1) {
160 SMP_TRACE_WARNING("%s: smp packet length %d too short: must be at least 1",
161 __func__, p_buf->len);
162 osi_free(p_buf);
163 return;
164 }
165
166 STREAM_TO_UINT8(cmd, p);
167
168 SMP_TRACE_EVENT("%s: SMDBG l2c, cmd=0x%x", __func__, cmd);
169
170 /* sanity check */
171 if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd)) {
172 SMP_TRACE_WARNING("Ignore received command with RESERVED code 0x%02x", cmd);
173 osi_free(p_buf);
174 return;
175 }
176
177 /* reject the pairing request if there is an on-going SMP pairing */
178 if (SMP_OPCODE_PAIRING_REQ == cmd || SMP_OPCODE_SEC_REQ == cmd) {
179 if ((p_cb->state == SMP_STATE_IDLE) &&
180 (p_cb->br_state == SMP_BR_STATE_IDLE) &&
181 !(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)) {
182 p_cb->role = L2CA_GetBleConnRole(bd_addr);
183 p_cb->pairing_bda = bd_addr;
184 } else if (bd_addr != p_cb->pairing_bda) {
185 osi_free(p_buf);
186 smp_reject_unexpected_pairing_command(bd_addr);
187 return;
188 }
189 /* else, out of state pairing request/security request received, passed into
190 * SM */
191 }
192
193 if (bd_addr == p_cb->pairing_bda) {
194 alarm_set_on_mloop(p_cb->smp_rsp_timer_ent, SMP_WAIT_FOR_RSP_TIMEOUT_MS,
195 smp_rsp_timeout, NULL);
196
197 smp_log_metrics(p_cb->pairing_bda, false /* incoming */,
198 p_buf->data + p_buf->offset, p_buf->len,
199 false /* is_over_br */);
200
201 if (cmd == SMP_OPCODE_CONFIRM) {
202 SMP_TRACE_DEBUG(
203 "in %s cmd = 0x%02x, peer_auth_req = 0x%02x,"
204 "loc_auth_req = 0x%02x",
205 __func__, cmd, p_cb->peer_auth_req, p_cb->loc_auth_req);
206
207 if ((p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT) &&
208 (p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT)) {
209 cmd = SMP_OPCODE_PAIR_COMMITM;
210 }
211 }
212
213 p_cb->rcvd_cmd_code = cmd;
214 p_cb->rcvd_cmd_len = (uint8_t)p_buf->len;
215 tSMP_INT_DATA smp_int_data;
216 smp_int_data.p_data = p;
217 smp_sm_event(p_cb, static_cast<tSMP_EVENT>(cmd), &smp_int_data);
218 }
219
220 osi_free(p_buf);
221 }
222
223 /*******************************************************************************
224 *
225 * Function smp_br_connect_callback
226 *
227 * Description This callback function is called by L2CAP to indicate that
228 * SMP BR channel is
229 * connected (conn = true)/disconnected (conn = false).
230 *
231 ******************************************************************************/
smp_br_connect_callback(uint16_t channel,const RawAddress & bd_addr,bool connected,uint16_t reason,tBT_TRANSPORT transport)232 static void smp_br_connect_callback(uint16_t channel, const RawAddress& bd_addr,
233 bool connected, uint16_t reason,
234 tBT_TRANSPORT transport) {
235 tSMP_CB* p_cb = &smp_cb;
236 tSMP_INT_DATA int_data;
237
238 SMP_TRACE_EVENT("%s", __func__);
239
240 if (transport != BT_TRANSPORT_BR_EDR) {
241 SMP_TRACE_WARNING("%s is called on unexpected transport %d", __func__,
242 transport);
243 return;
244 }
245
246 VLOG(1) << __func__ << " for pairing BDA: " << bd_addr
247 << ", pairing_bda:" << p_cb->pairing_bda
248 << " Event: " << ((connected) ? "connected" : "disconnected");
249
250 if (bd_addr != p_cb->pairing_bda) return;
251
252 /* Check if we already finished SMP pairing over LE, and are waiting to
253 * check if other side returns some errors. Connection/disconnection on
254 * Classic transport shouldn't impact that.
255 */
256 tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_cb->pairing_bda);
257 if (smp_get_state() == SMP_STATE_BOND_PENDING &&
258 (p_dev_rec && p_dev_rec->is_link_key_known()) &&
259 alarm_is_scheduled(p_cb->delayed_auth_timer_ent)) {
260 /* If we were to not return here, we would reset SMP control block, and
261 * delayed_auth_timer_ent would never be executed. Even though we stored all
262 * keys, stack would consider device as not bonded. It would reappear after
263 * stack restart, when we re-read record from storage. Service discovery
264 * would stay broken.
265 */
266 LOG_INFO("Classic event after CTKD on LE transport");
267 return;
268 }
269
270 if (connected) {
271 if (!p_cb->connect_initialized) {
272 p_cb->connect_initialized = true;
273 /* initialize local i/r key to be default keys */
274 p_cb->local_r_key = p_cb->local_i_key = SMP_BR_SEC_DEFAULT_KEY;
275 p_cb->loc_auth_req = p_cb->peer_auth_req = 0;
276 p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT;
277 smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_CONN_EVT, NULL);
278 }
279 } else {
280 /* Disconnected while doing security */
281 smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_DISCONN_EVT, &int_data);
282 }
283 }
284
285 /*******************************************************************************
286 *
287 * Function smp_br_data_received
288 *
289 * Description This function is called when data is received from L2CAP on
290 * SMP BR channel.
291 *
292 * Returns void
293 *
294 ******************************************************************************/
smp_br_data_received(uint16_t channel,const RawAddress & bd_addr,BT_HDR * p_buf)295 static void smp_br_data_received(uint16_t channel, const RawAddress& bd_addr,
296 BT_HDR* p_buf) {
297 tSMP_CB* p_cb = &smp_cb;
298 uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
299 uint8_t cmd;
300 SMP_TRACE_EVENT("SMDBG l2c %s", __func__);
301
302 if (p_buf->len < 1) {
303 SMP_TRACE_WARNING("%s: smp packet length %d too short: must be at least 1",
304 __func__, p_buf->len);
305 osi_free(p_buf);
306 return;
307 }
308
309 STREAM_TO_UINT8(cmd, p);
310
311 /* sanity check */
312 if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd)) {
313 SMP_TRACE_WARNING("Ignore received command with RESERVED code 0x%02x", cmd);
314 osi_free(p_buf);
315 return;
316 }
317
318 /* reject the pairing request if there is an on-going SMP pairing */
319 if (SMP_OPCODE_PAIRING_REQ == cmd) {
320 if ((p_cb->state == SMP_STATE_IDLE) &&
321 (p_cb->br_state == SMP_BR_STATE_IDLE)) {
322 p_cb->role = HCI_ROLE_PERIPHERAL;
323 p_cb->smp_over_br = true;
324 p_cb->pairing_bda = bd_addr;
325 } else if (bd_addr != p_cb->pairing_bda) {
326 osi_free(p_buf);
327 smp_reject_unexpected_pairing_command(bd_addr);
328 return;
329 }
330 /* else, out of state pairing request received, passed into State Machine */
331 }
332
333 if (bd_addr == p_cb->pairing_bda) {
334 alarm_set_on_mloop(p_cb->smp_rsp_timer_ent, SMP_WAIT_FOR_RSP_TIMEOUT_MS,
335 smp_rsp_timeout, NULL);
336
337 smp_log_metrics(p_cb->pairing_bda, false /* incoming */,
338 p_buf->data + p_buf->offset, p_buf->len,
339 true /* is_over_br */);
340
341 p_cb->rcvd_cmd_code = cmd;
342 p_cb->rcvd_cmd_len = (uint8_t)p_buf->len;
343 tSMP_INT_DATA smp_int_data;
344 smp_int_data.p_data = p;
345 smp_br_state_machine_event(p_cb, static_cast<tSMP_EVENT>(cmd),
346 &smp_int_data);
347 }
348
349 osi_free(p_buf);
350 }
351