• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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