diff options
Diffstat (limited to 'stack/btm/btm_sec.c')
-rw-r--r-- | stack/btm/btm_sec.c | 294 |
1 files changed, 241 insertions, 53 deletions
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c index 956364e5d..212b11871 100644 --- a/stack/btm/btm_sec.c +++ b/stack/btm/btm_sec.c @@ -288,7 +288,7 @@ void BTM_SetSecurityMode (UINT8 security_mode) { UINT8 old_mode = btm_cb.security_mode; - UINT8 sp_mode = HCI_SPD_MODE_ENABLED; + UINT8 sp_mode = HCI_SP_MODE_ENABLED; UINT8 sp_debug_mode = HCI_SPD_MODE_DISABLED; switch (security_mode) @@ -777,6 +777,39 @@ UINT8 btm_sec_clr_service_by_psm (UINT16 psm) /******************************************************************************* ** +** Function btm_sec_clr_temp_auth_service +** +** Description Removes specified device record's temporary authorization +** flag from the security database. +** +** Parameters Device address to be cleared +** +** Returns void. +** +*******************************************************************************/ +void btm_sec_clr_temp_auth_service (BD_ADDR bda) +{ + tBTM_SEC_DEV_REC *p_dev_rec; + + if ((p_dev_rec = btm_find_dev (bda)) == NULL) + { + BTM_TRACE_WARNING0 ("btm_sec_clr_temp_auth_service() - no dev CB"); + return; + } + + /* Reset the temporary authorized flag so that next time (untrusted) service is accessed autorization will take place */ + if (p_dev_rec->last_author_service_id != BTM_SEC_NO_LAST_SERVICE_ID && p_dev_rec->p_cur_service) + { + BTM_TRACE_DEBUG6 ("btm_sec_clr_auth_service_by_psm [clearing device: %02x:%02x:%02x:%02x:%02x:%02x]", + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + + p_dev_rec->last_author_service_id = BTM_SEC_NO_LAST_SERVICE_ID; + } +} + +/******************************************************************************* +** +** ** Function BTM_SecClrUCDService ** ** Description @@ -964,7 +997,18 @@ void BTM_DeviceAuthorized (BD_ADDR bd_addr, UINT8 res, UINT32 trusted_mask[]) { p_dev_rec->sec_flags |= BTM_SEC_AUTHORIZED; if (trusted_mask) + { BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask); + } + + /* Save the currently authorized service in case we are asked again + by another multiplexer layer */ + if (!p_dev_rec->is_originator) + { + BTM_TRACE_DEBUG1("BTM_DeviceAuthorized: Setting last_author_service_id to %d", + p_dev_rec->p_cur_service->service_id); + p_dev_rec->last_author_service_id = p_dev_rec->p_cur_service->service_id; + } } if (p_dev_rec->sec_state != BTM_SEC_STATE_AUTHORIZING) @@ -1008,6 +1052,8 @@ tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 tr #if SMP_INCLUDED == TRUE tACL_CONN *p=NULL; BOOLEAN is_le_slave_role=FALSE; + tBT_DEVICE_TYPE dev_type; + tBLE_ADDR_TYPE addr_type; #endif BTM_TRACE_API6 ("BTM_SecBond BDA: %02x:%02x:%02x:%02x:%02x:%02x", bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]); @@ -1100,10 +1146,11 @@ tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 tr } + BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type); /* LE device, do SMP pairing */ - if (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) + if (dev_type == BT_DEVICE_TYPE_BLE) { - if (SMP_Pair(p_dev_rec->bd_addr) == SMP_STARTED) + if (SMP_Pair(bd_addr) == SMP_STARTED) { p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING; return BTM_CMD_STARTED; @@ -1275,7 +1322,12 @@ tBTM_STATUS BTM_SecBondCancel (BD_ADDR bd_addr) return BTM_NO_RESOURCES; } - + if (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME) + { + BTM_CancelRemoteDeviceName(); + btm_cb.pairing_flags |= BTM_PAIR_FLAGS_WE_CANCEL_DD; + return BTM_CMD_STARTED; + } return BTM_NOT_AUTHORIZED; } } @@ -1450,7 +1502,8 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBTM_SEC_CBACK *p_callback, *******************************************************************************/ static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason) { - UINT8 old_state = p_dev_rec->sec_state; + UINT8 old_state = p_dev_rec->sec_state; + tBTM_STATUS status = BTM_CMD_STARTED; BTM_TRACE_EVENT2 ("btm_sec_send_hci_disconnect: handle:0x%x, reason=0x%x", p_dev_rec->hci_handle, reason); @@ -1466,18 +1519,19 @@ static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UIN { BTM_TRACE_ERROR0("RS in progress - Set DISC Pending flag in btm_sec_send_hci_disconnect to delay disconnect"); p_dev_rec->rs_disc_pending = BTM_SEC_DISC_PENDING; - return BTM_SUCCESS; + status = BTM_SUCCESS; } + else #endif /* Tear down the HCI link */ if (!btsnd_hcic_disconnect (p_dev_rec->hci_handle, reason)) { /* could not send disconnect. restore old state */ p_dev_rec->sec_state = old_state; - return(BTM_NO_RESOURCES); + status = BTM_NO_RESOURCES; } } - return(BTM_CMD_STARTED); + return (status); } /******************************************************************************* @@ -1916,23 +1970,23 @@ void BTM_SetOutService(BD_ADDR bd_addr, UINT8 service_id, UINT32 mx_chan_id) *************************************************************************/ /******************************************************************************* ** -** Function btm_sec_check_upgrade +** Function btm_sec_is_upgrade_possible ** -** Description This function is called to check if the existing link key -** needs to be upgraded. +** Description This function returns TRUE if the existing link key +** can be upgraded or if the link key does not exist. ** -** Returns void +** Returns BOOLEAN ** *******************************************************************************/ -static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator) +static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator) { - tBTM_SP_UPGRADE evt_data; UINT16 mtm_check = is_originator ? BTM_SEC_OUT_MITM : BTM_SEC_IN_MITM; + BOOLEAN is_possible = TRUE; if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) { - - BTM_TRACE_DEBUG5 ("btm_sec_check_upgrade id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x", + is_possible = FALSE; + BTM_TRACE_DEBUG5 ("btm_sec_is_upgrade_possible id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x", p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps, mtm_check, p_dev_rec->p_cur_service->security_flags); /* Already have a link key to the connected peer. Is the link key secure enough? @@ -1943,26 +1997,56 @@ static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_origi && (p_dev_rec->rmt_io_caps < BTM_IO_CAP_MAX) /* a valid peer IO cap */ && (btm_sec_io_map[p_dev_rec->rmt_io_caps][btm_cb.devcb.loc_io_caps])) /* authenticated link key is possible */ { - BTM_TRACE_DEBUG1 ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags); /* upgrade is possible: check if the application wants the upgrade. * If the application is configured to use a global MITM flag, * it probably would not want to upgrade the link key based on the security level database */ - memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN); - evt_data.upgrade = TRUE; - if (btm_cb.api.p_sp_callback) - (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data); + is_possible = TRUE; + } + } + BTM_TRACE_DEBUG2 ("btm_sec_is_upgrade_possible is_possible:%d sec_flags:0x%x", is_possible, p_dev_rec->sec_flags); + return is_possible; +} - BTM_TRACE_DEBUG1 ("evt_data.upgrade:0x%x", evt_data.upgrade); - if (evt_data.upgrade) - { - /* if the application confirms the upgrade, set the upgrade bit */ - p_dev_rec->sm4 |= BTM_SM4_UPGRADE; +/******************************************************************************* +** +** Function btm_sec_check_upgrade +** +** Description This function is called to check if the existing link key +** needs to be upgraded. +** +** Returns void +** +*******************************************************************************/ +static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator) +{ + tBTM_SP_UPGRADE evt_data; - /* Clear the link key known to go through authentication/pairing again */ - p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED); - p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED; - BTM_TRACE_DEBUG1 ("sec_flags:0x%x", p_dev_rec->sec_flags); - } + BTM_TRACE_DEBUG0 ("btm_sec_check_upgrade..."); + + /* Only check if link key already exists */ + if (!(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) + return; + if (btm_sec_is_upgrade_possible (p_dev_rec, is_originator) == TRUE) + { + BTM_TRACE_DEBUG1 ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags); + /* upgrade is possible: check if the application wants the upgrade. + * If the application is configured to use a global MITM flag, + * it probably would not want to upgrade the link key based on the security level database */ + memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN); + evt_data.upgrade = TRUE; + if (btm_cb.api.p_sp_callback) + (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data); + + BTM_TRACE_DEBUG1 ("evt_data.upgrade:0x%x", evt_data.upgrade); + if (evt_data.upgrade) + { + /* if the application confirms the upgrade, set the upgrade bit */ + p_dev_rec->sm4 |= BTM_SM4_UPGRADE; + + /* Clear the link key known to go through authentication/pairing again */ + p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED); + p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED; + BTM_TRACE_DEBUG1 ("sec_flags:0x%x", p_dev_rec->sec_flags); } } } @@ -2085,15 +2169,17 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle /* we will process one after another */ if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) ) { - BTM_TRACE_EVENT2 ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed state: %s", - psm, btm_pair_state_descr(btm_cb.pairing_state)); + BTM_TRACE_EVENT4 ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed state: %s mode:%d, sm4:0x%x", + psm, btm_pair_state_descr(btm_cb.pairing_state), btm_cb.security_mode, p_dev_rec->sm4); + BTM_TRACE_EVENT2 ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags); rc = BTM_CMD_STARTED; if ((BTM_SEC_MODE_SP != btm_cb.security_mode) || ((BTM_SEC_MODE_SP == btm_cb.security_mode) && (BTM_SM4_KNOWN == p_dev_rec->sm4)) + || (BTM_SEC_IS_SM4(p_dev_rec->sm4) && (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE)) ) { - BTM_TRACE_EVENT2 ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags); - /* legacy mode - local is legacy or local is lisbon/peer is legacy */ + /* legacy mode - local is legacy or local is lisbon/peer is legacy + * or SM4 with no possibility of link key upgrade */ if (is_originator) { if (((security_required & BTM_SEC_OUT_FLAGS) == 0) || @@ -2256,11 +2342,16 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle p_dev_rec->p_callback = p_callback; - /* Although authentication and encryption are per connection */ - /* authorization is per access request. For example when serial connection */ - /* is up and authorized and client requests to read file (access to other */ - /* scn, we need to request user's permission again. */ - p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED; + if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID + || p_dev_rec->last_author_service_id != p_dev_rec->p_cur_service->service_id) + { + /* Although authentication and encryption are per connection + ** authorization is per access request. For example when serial connection + ** is up and authorized and client requests to read file (access to other + ** scn), we need to request user's permission again. + */ + p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED; + } if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) { @@ -2311,6 +2402,7 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o tBTM_SEC_DEV_REC *p_dev_rec; tBTM_SEC_SERV_REC *p_serv_rec; tBTM_STATUS rc; + UINT16 security_required; BTM_TRACE_DEBUG1 ("btm_sec_mx_access_request is_originator:%d", is_originator); /* Find or get oldest record */ @@ -2337,8 +2429,41 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o BTM_TRACE_EVENT4 ("btm_sec_mx_access_request service PSM:%d Proto:%d SCN:%d delayed state: %s", psm, mx_proto_id, mx_chan_id, btm_pair_state_descr(btm_cb.pairing_state)); - btm_sec_queue_mx_request (bd_addr, psm, is_originator, mx_proto_id, mx_chan_id, p_callback, p_ref_data); - return BTM_CMD_STARTED; + rc = BTM_CMD_STARTED; + security_required = p_serv_rec->security_flags; + if ((BTM_SEC_MODE_SP != btm_cb.security_mode) + || ((BTM_SEC_MODE_SP == btm_cb.security_mode) && (BTM_SM4_KNOWN == p_dev_rec->sm4)) + || (BTM_SEC_IS_SM4(p_dev_rec->sm4) && (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE)) + ) + { + /* legacy mode - local is legacy or local is lisbon/peer is legacy + * or SM4 with no possibility of link key upgrade */ + if (is_originator) + { + if (((security_required & BTM_SEC_OUT_FLAGS) == 0) || + ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) || + ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) + ) + { + rc = BTM_SUCCESS; + } + } + else + { + if (((security_required & BTM_SEC_IN_FLAGS) == 0) || + ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) || + ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED))) + ) + { + rc = BTM_SUCCESS; + } + } + } + if (rc == BTM_CMD_STARTED) + { + btm_sec_queue_mx_request (bd_addr, psm, is_originator, mx_proto_id, mx_chan_id, p_callback, p_ref_data); + return rc; + } } p_dev_rec->p_cur_service = p_serv_rec; @@ -2487,7 +2612,9 @@ static void btm_sec_bond_cancel_complete (void) if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE) || (BTM_PAIR_STATE_WAIT_LOCAL_PIN == btm_cb.pairing_state && - BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags)) + BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags) || + (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME && + BTM_PAIR_FLAGS_WE_CANCEL_DD & btm_cb.pairing_flags)) { /* for dedicated bonding in legacy mode, authentication happens at "link level" * btm_sec_connected is called with failed status. @@ -2894,6 +3021,12 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT if (p_bd_addr && memcmp (btm_cb.pairing_bda, p_bd_addr, BD_ADDR_LEN) == 0) { BTM_TRACE_EVENT2 ("btm_sec_rmt_name_request_complete() continue bonding sm4: 0x%04x, status:0x%x", p_dev_rec->sm4, status); + if(btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_CANCEL_DD) + { + btm_sec_bond_cancel_complete(); + return; + } + if (status != HCI_SUCCESS) { btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE); @@ -3531,6 +3664,7 @@ void btm_rem_oob_req (UINT8 *p) memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN); memcpy (evt_data.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN); BCM_STRNCPY_S((char *)evt_data.bd_name, sizeof(evt_data.bd_name), (char *)p_dev_rec->sec_bd_name, BTM_MAX_REM_BD_NAME_LEN+1); + evt_data.bd_name[BTM_MAX_REM_BD_NAME_LEN] = 0; btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP); if ((*btm_cb.api.p_sp_callback) (BTM_SP_RMT_OOB_EVT, (tBTM_SP_EVT_DATA *)&evt_data) == BTM_NOT_AUTHORIZED) @@ -3834,10 +3968,12 @@ void btm_sec_mkey_comp_event (UINT16 handle, UINT8 status, UINT8 key_flg) void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) { tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle); - +#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE + tACL_CONN *p_acl; +#endif BTM_TRACE_EVENT3 ("Security Manager: encrypt_change status:%d State:%d, encr_enable = %d", status, (p_dev_rec) ? p_dev_rec->sec_state : 0, encr_enable); - BTM_TRACE_DEBUG1 ("before update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags ); + BTM_TRACE_DEBUG1 ("before update p_dev_rec->sec_flags=0x%x", (p_dev_rec) ? p_dev_rec->sec_flags : 0 ); /* For transaction collision we need to wait and repeat. There is no need */ /* for random timeout because only slave should receive the result */ @@ -3860,8 +3996,11 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED; BTM_TRACE_DEBUG1 ("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags ); + #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE - if (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) + p_acl = btm_bda_to_acl(p_dev_rec->bd_addr); + + if (p_acl && p_acl->is_le_link) { btm_ble_link_encrypted(p_dev_rec->bd_addr, encr_enable); return; @@ -4004,6 +4143,9 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) if (status == HCI_SUCCESS) { p_dev_rec = btm_sec_alloc_dev (bda); +#if BLE_INCLUDED == TRUE + p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR; +#endif } else { @@ -4061,6 +4203,8 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */ #endif + p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */ + if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) && (memcmp (btm_cb.pairing_bda, bda, BD_ADDR_LEN) == 0) ) { @@ -4208,8 +4352,6 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode) if (btm_cb.btm_def_link_policy) BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy); #endif - - BTM_SetLinkSuperTout (p_acl_cb->remote_addr, btm_cb.btm_def_link_super_tout); } btm_acl_created (bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, handle, HCI_ROLE_SLAVE, FALSE); @@ -4338,6 +4480,8 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) if (!p_dev_rec) return; + p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */ + #if BTM_DISC_DURING_RS == TRUE BTM_TRACE_ERROR0("btm_sec_disconnected - Clearing Pending flag"); p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */ @@ -4382,7 +4526,7 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE p_dev_rec->enc_key_size = 0; - btm_ble_resume_bg_conn(NULL, TRUE); + btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, p_dev_rec->bd_addr, FALSE); /* see sec_flags processing in btm_acl_removed */ #endif p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED); @@ -4421,7 +4565,10 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t p_dev_rec->link_key_type = key_type; p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN; - +#if (BLE_INCLUDED == TRUE) + /* BR/EDR connection, update the encryption key size to be 16 as always */ + p_dev_rec->enc_key_size = 16; +#endif memcpy (p_dev_rec->link_key, p_link_key, LINK_KEY_LEN); if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) @@ -5059,16 +5206,33 @@ static UINT8 btm_sec_start_authorization (tBTM_SEC_DEV_REC *p_dev_rec) else service_id = 0; - p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING; - result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr, + /* Send authorization request if not already sent during this service connection */ + if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID + || p_dev_rec->last_author_service_id != service_id) + { + p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING; + result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, p_service_name, service_id, p_dev_rec->is_originator); + } + + else /* Already authorized once for this L2CAP bringup */ + { + BTM_TRACE_DEBUG1 ("btm_sec_start_authorization: (Ignoring extra Authorization prompt for service %d)", service_id); + return (BTM_SUCCESS); + } + if (result == BTM_SUCCESS) { p_dev_rec->sec_flags |= BTM_SEC_AUTHORIZED; + + /* Save the currently authorized service in case we are asked again by another multiplexer layer */ + if (!p_dev_rec->is_originator) + p_dev_rec->last_author_service_id = service_id; + p_dev_rec->sec_state = BTM_SEC_STATE_IDLE; } return(result); @@ -5088,7 +5252,7 @@ static UINT8 btm_sec_start_authorization (tBTM_SEC_DEV_REC *p_dev_rec) *******************************************************************************/ BOOLEAN btm_sec_are_all_trusted(UINT32 p_mask[]) { - int trusted_inx; + UINT32 trusted_inx; for (trusted_inx = 0; trusted_inx < BTM_SEC_SERVICE_ARRAY_SIZE; trusted_inx++) { if (p_mask[trusted_inx] != BTM_SEC_TRUST_ALL) @@ -5611,6 +5775,30 @@ BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda) /******************************************************************************* ** +** Function btm_sec_is_le_capable_dev +** +** Description Is the specified device is dual mode or LE only device +** +** Returns TRUE - dev is a dual mode +** +*******************************************************************************/ +BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda) +{ + tBTM_SEC_DEV_REC *p_dev_rec= btm_find_dev (bda); + BOOLEAN le_capable = FALSE; + +#if (BLE_INCLUDED== TRUE) + if (p_dev_rec && ((p_dev_rec->device_type == BT_DEVICE_TYPE_DUMO) || + (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) ) ) + { + le_capable = TRUE; + } +#endif + return le_capable; +} + +/******************************************************************************* +** ** Function btm_sec_find_bonded_dev ** ** Description Find a bonded device starting from the specified index |