• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 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 Bluetooth Device Manager
22  *
23  ******************************************************************************/
24 
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <stddef.h>
29 
30 #include "bt_types.h"
31 #include "gki.h"
32 #include "hcimsgs.h"
33 #include "btu.h"
34 #include "btm_api.h"
35 #include "btm_int.h"
36 #include "hcidefs.h"
37 #include "l2c_api.h"
38 static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void);
39 
40 /*******************************************************************************
41 **
42 ** Function         BTM_SecAddDevice
43 **
44 ** Description      Add/modify device.  This function will be normally called
45 **                  during host startup to restore all required information
46 **                  stored in the NVRAM.
47 **
48 ** Parameters:      bd_addr          - BD address of the peer
49 **                  dev_class        - Device Class
50 **                  bd_name          - Name of the peer device.  NULL if unknown.
51 **                  features         - Remote device's features (up to 3 pages). NULL if not known
52 **                  trusted_mask     - Bitwise OR of services that do not
53 **                                     require authorization. (array of UINT32)
54 **                  link_key         - Connection link key. NULL if unknown.
55 **
56 ** Returns          TRUE if added OK, else FALSE
57 **
58 *******************************************************************************/
BTM_SecAddDevice(BD_ADDR bd_addr,DEV_CLASS dev_class,BD_NAME bd_name,UINT8 * features,UINT32 trusted_mask[],LINK_KEY link_key,UINT8 key_type,tBTM_IO_CAP io_cap)59 BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
60                           UINT8 *features, UINT32 trusted_mask[],
61                           LINK_KEY link_key, UINT8 key_type, tBTM_IO_CAP io_cap)
62 {
63     tBTM_SEC_DEV_REC  *p_dev_rec;
64     int               i, j;
65     BOOLEAN           found = FALSE;
66 
67     p_dev_rec = btm_find_dev (bd_addr);
68     if (!p_dev_rec)
69     {
70         /* There is no device record, allocate one.
71          * If we can not find an empty spot for this one, let it fail. */
72         for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++)
73         {
74             if (!(btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE))
75             {
76                 p_dev_rec = &btm_cb.sec_dev_rec[i];
77 
78                 /* Mark this record as in use and initialize */
79                 memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
80                 p_dev_rec->sec_flags = BTM_SEC_IN_USE;
81                 memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
82                 p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr);
83 
84 #if BLE_INCLUDED == TRUE
85                 /* use default value for background connection params */
86                 /* update conn params, use default value for background connection params */
87                 memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
88 #endif
89                 break;
90             }
91         }
92 
93         if (!p_dev_rec)
94             return(FALSE);
95     }
96 
97     p_dev_rec->timestamp = btm_cb.dev_rec_count++;
98 
99     if (dev_class)
100         memcpy (p_dev_rec->dev_class, dev_class, DEV_CLASS_LEN);
101 
102     memset(p_dev_rec->sec_bd_name, 0, sizeof(tBTM_BD_NAME));
103 
104     if (bd_name && bd_name[0])
105     {
106         p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
107         BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
108             (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
109     }
110 
111     p_dev_rec->num_read_pages = 0;
112     if (features)
113     {
114         memcpy (p_dev_rec->features, features, sizeof (p_dev_rec->features));
115         for (i = HCI_EXT_FEATURES_PAGE_MAX; i >= 0; i--)
116         {
117             for (j = 0; j < HCI_FEATURE_BYTES_PER_PAGE; j++)
118             {
119                 if (p_dev_rec->features[i][j] != 0)
120                 {
121                     found = TRUE;
122                     break;
123                 }
124             }
125             if (found)
126             {
127                 p_dev_rec->num_read_pages = i + 1;
128                 break;
129             }
130         }
131     }
132     else
133         memset (p_dev_rec->features, 0, sizeof (p_dev_rec->features));
134 
135     BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
136 
137     if (link_key)
138     {
139         BTM_TRACE_EVENT6 ("BTM_SecAddDevice()  BDA: %02x:%02x:%02x:%02x:%02x:%02x",
140                           bd_addr[0], bd_addr[1], bd_addr[2],
141                           bd_addr[3], bd_addr[4], bd_addr[5]);
142         p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
143         memcpy (p_dev_rec->link_key, link_key, LINK_KEY_LEN);
144         p_dev_rec->link_key_type = key_type;
145     }
146 
147 #if defined(BTIF_MIXED_MODE_INCLUDED) && (BTIF_MIXED_MODE_INCLUDED == TRUE)
148     if (key_type  < BTM_MAX_PRE_SM4_LKEY_TYPE)
149         p_dev_rec->sm4 = BTM_SM4_KNOWN;
150     else
151         p_dev_rec->sm4 = BTM_SM4_TRUE;
152 #endif
153 
154     p_dev_rec->rmt_io_caps = io_cap;
155 
156     return(TRUE);
157 }
158 
159 
160 /*******************************************************************************
161 **
162 ** Function         BTM_SecDeleteDevice
163 **
164 ** Description      Free resources associated with the device.
165 **
166 ** Parameters:      bd_addr          - BD address of the peer
167 **
168 ** Returns          TRUE if removed OK, FALSE if not found or ACL link is active
169 **
170 *******************************************************************************/
BTM_SecDeleteDevice(BD_ADDR bd_addr)171 BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr)
172 {
173     tBTM_SEC_DEV_REC  *p_dev_rec;
174 
175     if (BTM_IsAclConnectionUp(bd_addr))
176     {
177         BTM_TRACE_WARNING0("BTM_SecDeleteDevice FAILED: Cannot Delete when connection is active");
178         return(FALSE);
179     }
180 
181     if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
182         return(FALSE);
183 
184     btm_sec_free_dev (p_dev_rec);
185 
186     /* Tell controller to get rid of the link key if it has one stored */
187     BTM_DeleteStoredLinkKey (bd_addr, NULL);
188 
189     return(TRUE);
190 }
191 
192 /*******************************************************************************
193 **
194 ** Function         BTM_SecReadDevName
195 **
196 ** Description      Looks for the device name in the security database for the
197 **                  specified BD address.
198 **
199 ** Returns          Pointer to the name or NULL
200 **
201 *******************************************************************************/
BTM_SecReadDevName(BD_ADDR bd_addr)202 char *BTM_SecReadDevName (BD_ADDR bd_addr)
203 {
204     char *p_name = NULL;
205     tBTM_SEC_DEV_REC *p_srec;
206 
207     if ((p_srec = btm_find_dev(bd_addr)) != NULL)
208         p_name = (char *)p_srec->sec_bd_name;
209 
210     return(p_name);
211 }
212 
213 /*******************************************************************************
214 **
215 ** Function         btm_sec_alloc_dev
216 **
217 ** Description      Look for the record in the device database for the record
218 **                  with specified handle
219 **
220 ** Returns          Pointer to the record
221 **
222 *******************************************************************************/
btm_sec_alloc_dev(BD_ADDR bd_addr)223 tBTM_SEC_DEV_REC *btm_sec_alloc_dev (BD_ADDR bd_addr)
224 {
225     tBTM_SEC_DEV_REC *p_dev_rec = NULL;
226     tBTM_INQ_INFO    *p_inq_info;
227     int               i;
228     BTM_TRACE_EVENT0 ("btm_sec_alloc_dev");
229     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++)
230     {
231         if (!(btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE))
232         {
233             p_dev_rec = &btm_cb.sec_dev_rec[i];
234             break;
235         }
236     }
237 
238     if (!p_dev_rec)
239         p_dev_rec = btm_find_oldest_dev();
240 
241     memset (p_dev_rec, 0, sizeof (tBTM_SEC_DEV_REC));
242 
243     p_dev_rec->sec_flags = BTM_SEC_IN_USE;
244 
245     /* Check with the BT manager if details about remote device are known */
246     /* outgoing connection */
247     if ((p_inq_info = BTM_InqDbRead(bd_addr)) != NULL)
248     {
249         memcpy (p_dev_rec->dev_class, p_inq_info->results.dev_class, DEV_CLASS_LEN);
250 
251 #if BLE_INCLUDED == TRUE
252         p_dev_rec->device_type = p_inq_info->results.device_type;
253         p_dev_rec->ble.ble_addr_type = p_inq_info->results.ble_addr_type;
254 
255         /* update conn params, use default value for background connection params */
256         memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
257 #endif
258 
259 #if BTM_INQ_GET_REMOTE_NAME == TRUE
260         if (p_inq_info->remote_name_state == BTM_INQ_RMT_NAME_DONE)
261         {
262             BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
263                      (char *)p_inq_info->remote_name, BTM_MAX_REM_BD_NAME_LEN);
264             p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
265         }
266 #endif
267     }
268     else
269     {
270 #if BLE_INCLUDED == TRUE
271         /* update conn params, use default value for background connection params */
272         memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
273 #endif
274 
275         if (!memcmp (bd_addr, btm_cb.connecting_bda, BD_ADDR_LEN))
276             memcpy (p_dev_rec->dev_class, btm_cb.connecting_dc, DEV_CLASS_LEN);
277     }
278 
279     memcpy (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN);
280 
281     p_dev_rec->hci_handle = BTM_GetHCIConnHandle (bd_addr);
282     p_dev_rec->timestamp = btm_cb.dev_rec_count++;
283 
284     return(p_dev_rec);
285 }
286 
287 
288 /*******************************************************************************
289 **
290 ** Function         btm_sec_free_dev
291 **
292 ** Description      Mark device record as not used
293 **
294 *******************************************************************************/
btm_sec_free_dev(tBTM_SEC_DEV_REC * p_dev_rec)295 void btm_sec_free_dev (tBTM_SEC_DEV_REC *p_dev_rec)
296 {
297     p_dev_rec->sec_flags = 0;
298 
299 #if BLE_INCLUDED == TRUE
300     /* Clear out any saved BLE keys */
301     btm_sec_clear_ble_keys (p_dev_rec);
302 #endif
303 
304 
305 }
306 
307 /*******************************************************************************
308 **
309 ** Function         btm_dev_support_switch
310 **
311 ** Description      This function is called by the L2CAP to check if remote
312 **                  device supports role switch
313 **
314 ** Parameters:      bd_addr       - Address of the peer device
315 **
316 ** Returns          TRUE if device is known and role switch is supported
317 **
318 *******************************************************************************/
btm_dev_support_switch(BD_ADDR bd_addr)319 BOOLEAN btm_dev_support_switch (BD_ADDR bd_addr)
320 {
321     tBTM_SEC_DEV_REC  *p_dev_rec;
322     UINT8   xx;
323     BOOLEAN feature_empty = TRUE;
324 
325 #if BTM_SCO_INCLUDED == TRUE
326     /* Role switch is not allowed if a SCO is up */
327     if (btm_is_sco_active_by_bdaddr(bd_addr))
328         return(FALSE);
329 #endif
330     p_dev_rec = btm_find_dev (bd_addr);
331     if (p_dev_rec && HCI_SWITCH_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_0]))
332     {
333         if (HCI_SWITCH_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0]))
334         {
335             BTM_TRACE_DEBUG0("btm_dev_support_switch return TRUE (feature found)");
336             return (TRUE);
337         }
338 
339         /* If the feature field is all zero, we never received them */
340         for (xx = 0 ; xx < BD_FEATURES_LEN ; xx++)
341         {
342             if (p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0][xx] != 0x00)
343             {
344                 feature_empty = FALSE; /* at least one is != 0 */
345                 break;
346             }
347         }
348 
349         /* If we don't know peer's capabilities, assume it supports Role-switch */
350         if (feature_empty)
351         {
352             BTM_TRACE_DEBUG0("btm_dev_support_switch return TRUE (feature empty)");
353             return (TRUE);
354         }
355     }
356 
357     BTM_TRACE_DEBUG0("btm_dev_support_switch return FALSE");
358     return(FALSE);
359 }
360 
361 /*******************************************************************************
362 **
363 ** Function         btm_find_dev_by_handle
364 **
365 ** Description      Look for the record in the device database for the record
366 **                  with specified handle
367 **
368 ** Returns          Pointer to the record or NULL
369 **
370 *******************************************************************************/
btm_find_dev_by_handle(UINT16 handle)371 tBTM_SEC_DEV_REC *btm_find_dev_by_handle (UINT16 handle)
372 {
373     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
374     int i;
375 
376     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
377     {
378         if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
379             && (p_dev_rec->hci_handle == handle))
380             return(p_dev_rec);
381     }
382     return(NULL);
383 }
384 
385 /*******************************************************************************
386 **
387 ** Function         btm_find_dev
388 **
389 ** Description      Look for the record in the device database for the record
390 **                  with specified BD address
391 **
392 ** Returns          Pointer to the record or NULL
393 **
394 *******************************************************************************/
btm_find_dev(BD_ADDR bd_addr)395 tBTM_SEC_DEV_REC *btm_find_dev (BD_ADDR bd_addr)
396 {
397     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
398     int i;
399 
400     if (bd_addr)
401     {
402         for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
403         {
404             if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
405                 && (!memcmp (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN)))
406                 return(p_dev_rec);
407         }
408     }
409     return(NULL);
410 }
411 
412 /*******************************************************************************
413 **
414 ** Function         btm_find_or_alloc_dev
415 **
416 ** Description      Look for the record in the device database for the record
417 **                  with specified BD address
418 **
419 ** Returns          Pointer to the record or NULL
420 **
421 *******************************************************************************/
btm_find_or_alloc_dev(BD_ADDR bd_addr)422 tBTM_SEC_DEV_REC *btm_find_or_alloc_dev (BD_ADDR bd_addr)
423 {
424     tBTM_SEC_DEV_REC *p_dev_rec;
425     BTM_TRACE_EVENT0 ("btm_find_or_alloc_dev");
426     if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
427     {
428 
429         /* Allocate a new device record or reuse the oldest one */
430         p_dev_rec = btm_sec_alloc_dev (bd_addr);
431     }
432     return(p_dev_rec);
433 }
434 
435 /*******************************************************************************
436 **
437 ** Function         btm_find_oldest_dev
438 **
439 ** Description      Locates the oldest device in use. It first looks for
440 **                  the oldest non-paired device.  If all devices are paired it
441 **                  deletes the oldest paired device.
442 **
443 ** Returns          Pointer to the record
444 **
445 *******************************************************************************/
btm_find_oldest_dev(void)446 tBTM_SEC_DEV_REC *btm_find_oldest_dev (void)
447 {
448     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
449     tBTM_SEC_DEV_REC *p_oldest = p_dev_rec;
450     UINT32       ot = 0xFFFFFFFF;
451     int i;
452 
453     /* First look for the non-paired devices for the oldest entry */
454     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
455     {
456         if (((p_dev_rec->sec_flags & BTM_SEC_IN_USE) == 0)
457             || ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) != 0))
458             continue; /* Device is paired so skip it */
459 
460         if (p_dev_rec->timestamp < ot)
461         {
462             p_oldest = p_dev_rec;
463             ot       = p_dev_rec->timestamp;
464         }
465     }
466 
467     if (ot != 0xFFFFFFFF)
468         return(p_oldest);
469 
470     /* All devices are paired; find the oldest */
471     p_dev_rec = &btm_cb.sec_dev_rec[0];
472     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
473     {
474         if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) == 0)
475             continue;
476 
477         if (p_dev_rec->timestamp < ot)
478         {
479             p_oldest = p_dev_rec;
480             ot       = p_dev_rec->timestamp;
481         }
482     }
483     return(p_oldest);
484 }
485 
486 
487