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