diff options
-rw-r--r-- | bta/include/bta_api.h | 1 | ||||
-rw-r--r-- | device/src/controller.c | 6 | ||||
-rw-r--r-- | stack/btm/btm_acl.c | 126 | ||||
-rw-r--r-- | stack/btm/btm_int.h | 9 | ||||
-rw-r--r-- | stack/btm/btm_sco.c | 23 | ||||
-rw-r--r-- | stack/btm/btm_sec.c | 581 | ||||
-rw-r--r-- | stack/hcic/hcicmds.c | 2 | ||||
-rw-r--r-- | stack/include/btm_api.h | 57 | ||||
-rw-r--r-- | stack/include/hcidefs.h | 14 |
9 files changed, 605 insertions, 214 deletions
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h index a3410c1fc..772f081d7 100644 --- a/bta/include/bta_api.h +++ b/bta/include/bta_api.h @@ -169,6 +169,7 @@ typedef struct #define BTA_SEC_AUTHORIZE (BTM_SEC_IN_AUTHORIZE ) /* Authorization required (only needed for out going connection )*/ #define BTA_SEC_AUTHENTICATE (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */ #define BTA_SEC_ENCRYPT (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT) /* Encryption required. */ +#define BTA_SEC_MODE4_LEVEL4 (BTM_SEC_MODE4_LEVEL4) /* Mode 4 level 4 service, i.e. incoming/outgoing MITM and P-256 encryption */ typedef UINT8 tBTA_SEC; diff --git a/device/src/controller.c b/device/src/controller.c index 6537cf1f9..f0d3e584d 100644 --- a/device/src/controller.c +++ b/device/src/controller.c @@ -178,6 +178,12 @@ static future_t *start_up(void) { page_number++; } + secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array); + if (secure_connections_supported) { + response = AWAIT_COMMAND(packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED)); + packet_parser->parse_generic_command_complete(response); + } + #if (BLE_INCLUDED == TRUE) ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array); if (ble_supported) { diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c index b47564fc7..a6c765908 100644 --- a/stack/btm/btm_acl.c +++ b/stack/btm/btm_acl.c @@ -16,12 +16,20 @@ * ******************************************************************************/ -/****************************************************************************** - * - * This file contains functions that handle ACL connections. This includes - * operations such as hold and sniff modes, supported packet types. - * - ******************************************************************************/ +/***************************************************************************** +** +** Name: btm_acl.c +** +** Description: This file contains functions that handle ACL connections. +** This includes operations such as hold and sniff modes, +** supported packet types. +** +** This module contains both internal and external (API) +** functions. External (API) functions are distinguishable +** by their names beginning with uppercase BTM. +** +** +******************************************************************************/ #include <stdlib.h> #include <string.h> @@ -42,8 +50,6 @@ static void btm_read_remote_features (UINT16 handle); static void btm_read_remote_ext_features (UINT16 handle, UINT8 page_number); -static void btm_process_remote_ext_features_page (tACL_CONN *p_acl_cb, tBTM_SEC_DEV_REC *p_dev_rec, - UINT8 page_idx); static void btm_process_remote_ext_features (tACL_CONN *p_acl_cb, UINT8 num_read_pages); #define BTM_DEV_REPLY_TIMEOUT 3 /* 3 second timeout waiting for responses */ @@ -274,23 +280,23 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn, { /* If remote features already known, copy them and continue connection setup */ if ((p_dev_rec->num_read_pages) && - (p_dev_rec->num_read_pages <= (HCI_EXT_FEATURES_PAGE_MAX + 1)) /* sanity check */) + (p_dev_rec->num_read_pages <= (HCI_EXT_FEATURES_PAGE_MAX + 1))) { memcpy (p->peer_lmp_features, p_dev_rec->features, (HCI_FEATURE_BYTES_PER_PAGE * p_dev_rec->num_read_pages)); p->num_read_pages = p_dev_rec->num_read_pages; - if (BTM_SEC_MODE_SP == btm_cb.security_mode - && HCI_SSP_HOST_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_1]) - && HCI_SIMPLE_PAIRING_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0])) - { - p_dev_rec->sm4 = BTM_SM4_TRUE; - } - else + const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); + + /* Store the Peer Security Capabilites (in SM4 and rmt_sec_caps) */ + btm_sec_set_peer_sec_caps(p, p_dev_rec); + + BTM_TRACE_API("%s: pend:%d", __FUNCTION__, req_pend); + if (req_pend) { - p_dev_rec->sm4 |= BTM_SM4_KNOWN; + /* Request for remaining Security Features (if any) */ + l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr); } - btm_establish_continue (p); return; } @@ -949,82 +955,28 @@ void btm_process_remote_ext_features (tACL_CONN *p_acl_cb, UINT8 num_read_pages) p_acl_cb->num_read_pages = num_read_pages; p_dev_rec->num_read_pages = num_read_pages; - /* Process the pages one by one */ + /* Move the pages to placeholder */ for (page_idx = 0; page_idx < num_read_pages; page_idx++) { - btm_process_remote_ext_features_page (p_acl_cb, p_dev_rec, page_idx); - } -} - - -/******************************************************************************* -** -** Function btm_process_remote_ext_features_page -** -** Description Local function called to process the information located -** in the specific extended features page read from a remote device. -** -** Returns void -** -*******************************************************************************/ -void btm_process_remote_ext_features_page (tACL_CONN *p_acl_cb, tBTM_SEC_DEV_REC *p_dev_rec, - UINT8 page_idx) -{ - UINT8 req_pend; - - memcpy (p_dev_rec->features[page_idx], p_acl_cb->peer_lmp_features[page_idx], - HCI_FEATURE_BYTES_PER_PAGE); - - switch (page_idx) - { - /* Extended (Legacy) Page 0 */ - case HCI_EXT_FEATURES_PAGE_0: - /* Page 0 indicates Controller support for SSP */ - if (btm_cb.security_mode < BTM_SEC_MODE_SP || - !HCI_SIMPLE_PAIRING_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0])) - { - req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); - p_dev_rec->sm4 = BTM_SM4_KNOWN; - if (req_pend) - { - l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr); - } - } - break; - - /* Extended Page 1 */ - case HCI_EXT_FEATURES_PAGE_1: - /* Page 1 indicates Host support for SSP and SC */ - req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); - - if (btm_cb.security_mode == BTM_SEC_MODE_SP - && HCI_SSP_HOST_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_1]) - && HCI_SIMPLE_PAIRING_SUPPORTED(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_0])) + if (page_idx > HCI_EXT_FEATURES_PAGE_MAX) { - p_dev_rec->sm4 = BTM_SM4_TRUE; - } - else - { - p_dev_rec->sm4 = BTM_SM4_KNOWN; + BTM_TRACE_ERROR("%s: page=%d unexpected", __FUNCTION__, page_idx); + break; } + memcpy (p_dev_rec->features[page_idx], p_acl_cb->peer_lmp_features[page_idx], + HCI_FEATURE_BYTES_PER_PAGE); + } - BTM_TRACE_API ("ext_features_complt page_num:%d f[0]:x%02x, sm4:%x, pend:%d", - HCI_EXT_FEATURES_PAGE_1, *(p_dev_rec->features[HCI_EXT_FEATURES_PAGE_1]), - p_dev_rec->sm4, req_pend); - - if (req_pend) - l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr); - - break; + const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); - /* Extended Page 2 */ - case HCI_EXT_FEATURES_PAGE_2: - /* Page 2 indicates Ping support*/ - break; + /* Store the Peer Security Capabilites (in SM4 and rmt_sec_caps) */ + btm_sec_set_peer_sec_caps(p_acl_cb, p_dev_rec); - default: - BTM_TRACE_ERROR("btm_process_remote_ext_features_page page=%d unexpected", page_idx); - break; + BTM_TRACE_API("%s: pend:%d", __FUNCTION__, req_pend); + if (req_pend) + { + /* Request for remaining Security Features (if any) */ + l2cu_resubmit_pending_sec_req (p_dev_rec->bd_addr); } } diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h index 7d5cac305..ec0a03f82 100644 --- a/stack/btm/btm_int.h +++ b/stack/btm/btm_int.h @@ -189,6 +189,9 @@ BT_OCTET16 ble_encryption_key_value; /* BLE encryption key */ tBTM_IO_CAP loc_io_caps; /* IO capability of the local device */ tBTM_AUTH_REQ loc_auth_req; /* the auth_req flag */ + BOOLEAN secure_connections_only; /* Rejects service level 0 connections if */ + /* itself or peer device doesn't support */ + /* secure connections */ } tBTM_DEVCB; @@ -565,6 +568,11 @@ typedef struct UINT8 sm4; /* BTM_SM4_TRUE, if the peer supports SM4 */ tBTM_IO_CAP rmt_io_caps; /* IO capability of the peer device */ tBTM_AUTH_REQ rmt_auth_req; /* the auth_req flag as in the IO caps rsp evt */ + BOOLEAN remote_supports_secure_connections; + BOOLEAN remote_features_needed; /* set to true if the local device is in */ + /* "Secure Connections Only" mode and it receives */ + /* HCI_IO_CAPABILITY_REQUEST_EVT from the peer before */ + /* it knows peer's support for Secure Connections */ #if (BLE_INCLUDED == TRUE) UINT16 ble_hci_handle; /* use in DUMO connection */ @@ -1056,6 +1064,7 @@ extern void btm_sec_link_key_request (UINT8 *p_bda); extern void btm_sec_pin_code_request (UINT8 *p_bda); extern void btm_sec_update_clock_offset (UINT16 handle, UINT16 clock_offset); extern void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEAN is_le_trasnport); +extern void btm_sec_set_peer_sec_caps (tACL_CONN *p_acl_cb, tBTM_SEC_DEV_REC *p_dev_rec); #if BLE_INCLUDED == TRUE extern void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec); diff --git a/stack/btm/btm_sco.c b/stack/btm/btm_sco.c index 801896d14..585ad71f7 100644 --- a/stack/btm/btm_sco.c +++ b/stack/btm/btm_sco.c @@ -434,6 +434,29 @@ static tBTM_STATUS btm_send_connect_request(UINT16 acl_handle, temp_pkt_types |= (HCI_ESCO_PKT_TYPES_MASK_NO_3_EV3 | HCI_ESCO_PKT_TYPES_MASK_NO_3_EV5); } + + /* Check to see if BR/EDR Secure Connections is being used + ** If so, we cannot use SCO-only packet types (HFP 1.7) + */ + if (BTM_BothEndsSupportSecureConnections(p_acl->remote_addr)) + { + temp_pkt_types &= ~(BTM_SCO_PKT_TYPE_MASK); + BTM_TRACE_DEBUG("%s: SCO Conn: pkt_types after removing SCO (0x%04x)", __FUNCTION__, + temp_pkt_types); + + /* Return error if no packet types left */ + if (temp_pkt_types == 0) + { + BTM_TRACE_ERROR("%s: SCO Conn (BR/EDR SC): No packet types available", + __FUNCTION__); + return (BTM_WRONG_MODE); + } + } + else + { + BTM_TRACE_DEBUG("%s: SCO Conn(BR/EDR SC):local or peer does not support BR/EDR SC", + __FUNCTION__); + } } diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c index db8622e39..b62cef80e 100644 --- a/stack/btm/btm_sec.c +++ b/stack/btm/btm_sec.c @@ -24,6 +24,7 @@ #define LOG_TAG "bt_btm_sec" +#include <stdarg.h> #include <string.h> #include "bt_types.h" @@ -97,6 +98,8 @@ static BOOLEAN btm_dev_authenticated(tBTM_SEC_DEV_REC *p_dev_rec); static BOOLEAN btm_dev_encrypted(tBTM_SEC_DEV_REC *p_dev_rec); static BOOLEAN btm_dev_authorized(tBTM_SEC_DEV_REC *p_dev_rec); static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC *p_serv_rec); +static BOOLEAN btm_sec_is_serv_level0 (UINT16 psm); +static UINT16 btm_sec_set_serv_level4_flags (UINT16 cur_security, BOOLEAN is_originator); static BOOLEAN btm_sec_queue_encrypt_request (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CALLBACK *p_callback, void *p_ref_data); @@ -391,7 +394,28 @@ void BTM_SetPairableMode (BOOLEAN allow_pairing, BOOLEAN connect_only_paired) btm_cb.connect_only_paired = connect_only_paired; } +/******************************************************************************* +** +** Function BTM_SetSecureConnectionsOnly +** +** Description Enable or disable default treatment for Mode 4 Level 0 services +** +** Parameter secure_connections_only_mode - (TRUE or FALSE) whether or not the device +** TRUE means that the device should treat Mode 4 Level 0 services as +** services of other levels. (Secure_connections_only_mode) +** FALSE means that the device should provide default treatment for +** Mode 4 Level 0 services. +** +** Returns void +** +*******************************************************************************/ +void BTM_SetSecureConnectionsOnly (BOOLEAN secure_connections_only_mode) +{ + BTM_TRACE_API("%s: Mode : %u", __FUNCTION__, + secure_connections_only_mode); + btm_cb.devcb.secure_connections_only = secure_connections_only_mode; +} #define BTM_NO_AVAIL_SEC_SERVICES ((UINT16) 0xffff) /******************************************************************************* @@ -562,7 +586,9 @@ static BOOLEAN btm_sec_set_security_level (CONNECTION_TYPE conn_type, char *p_na /* Parameter validation. Originator should not set requirements for incoming connections */ sec_level &= ~(BTM_SEC_IN_AUTHORIZE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_MITM); - if (btm_cb.security_mode == BTM_SEC_MODE_SP) + if (btm_cb.security_mode == BTM_SEC_MODE_SP || + btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG || + btm_cb.security_mode == BTM_SEC_MODE_SC) { if (sec_level & BTM_SEC_OUT_AUTHENTICATE) sec_level |= BTM_SEC_OUT_MITM; @@ -607,7 +633,9 @@ static BOOLEAN btm_sec_set_security_level (CONNECTION_TYPE conn_type, char *p_na /* Parameter validation. Acceptor should not set requirements for outgoing connections */ sec_level &= ~(BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_MITM); - if (btm_cb.security_mode == BTM_SEC_MODE_SP) + if (btm_cb.security_mode == BTM_SEC_MODE_SP || + btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG || + btm_cb.security_mode == BTM_SEC_MODE_SC) { if (sec_level & BTM_SEC_IN_AUTHENTICATE) sec_level |= BTM_SEC_IN_MITM; @@ -1034,9 +1062,12 @@ tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport, || (p_dev_rec->sm4 == BTM_SM4_KNOWN)) { if ( btm_sec_check_prefetch_pin (p_dev_rec) ) - return(BTM_CMD_STARTED); + return (BTM_CMD_STARTED); } - if (BTM_SEC_MODE_SP == btm_cb.security_mode && BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) + if ((btm_cb.security_mode == BTM_SEC_MODE_SP || + btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG || + btm_cb.security_mode == BTM_SEC_MODE_SC) && + BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) { /* local is 2.1 and peer is unknown */ if ((p_dev_rec->sm4 & BTM_SM4_CONN_PEND) == 0) @@ -1763,21 +1794,50 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, /******************************************************************************* ** -** Function BTM_IsLeScSuppLocally +** Function BTM_BothEndsSupportSecureConnections ** -** Description This function is called to check if LE SC is supported. +** Description This function is called to check if both the local device and the peer device +** specified by bd_addr support BR/EDR Secure Connections. ** -** Parameters: None. +** Parameters: bd_addr - address of the peer +** +** Returns TRUE if BR/EDR Secure Connections are supported by both local +** and the remote device. +** else FALSE. ** -** Returns Boolean - TRUE if LE SC is supported. *******************************************************************************/ -BOOLEAN BTM_IsLeScSuppLocally (void) +BOOLEAN BTM_BothEndsSupportSecureConnections(BD_ADDR bd_addr) { -#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE - return TRUE; -#else - return FALSE; -#endif + return ((controller_get_interface()->supports_secure_connections()) && + (BTM_PeerSupportsSecureConnections(bd_addr))); +} + +/******************************************************************************* +** +** Function BTM_PeerSupportsSecureConnections +** +** Description This function is called to check if the peer supports +** BR/EDR Secure Connections. +** +** Parameters: bd_addr - address of the peer +** +** Returns TRUE if BR/EDR Secure Connections are supported by the peer, +** else FALSE. +** +*******************************************************************************/ +BOOLEAN BTM_PeerSupportsSecureConnections(BD_ADDR bd_addr) +{ + tBTM_SEC_DEV_REC *p_dev_rec; + + if ((p_dev_rec = btm_find_dev(bd_addr)) == NULL) + { + BTM_TRACE_WARNING("%s: unknown BDA: %08x%04x", __FUNCTION__, + (bd_addr[0]<<24) + (bd_addr[1]<<16) + (bd_addr[2]<<8) + bd_addr[3], + (bd_addr[4]<< 8) + bd_addr[5]); + return FALSE; + } + + return (p_dev_rec->remote_supports_secure_connections); } /******************************************************************************* @@ -1923,10 +1983,15 @@ static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN /* Already have a link key to the connected peer. Is the link key secure enough? ** Is a link key upgrade even possible? */ - if ((p_dev_rec->security_required & mtm_check) /* needs MITM */ - && (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB) /* has unauthenticated link key */ - && (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 */ + if ((p_dev_rec->security_required & mtm_check) /* needs MITM */ + && ((p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB) || + (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256)) + /* has unauthenticated + link key */ + && (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 */ { /* upgrade is possible: check if the application wants the upgrade. * If the application is configured to use a global MITM flag, @@ -2004,6 +2069,12 @@ static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_origi #define BTM_SEC_OUT_FLAGS (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_AUTHORIZE) #define BTM_SEC_IN_FLAGS (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT | BTM_SEC_IN_AUTHORIZE) +#define BTM_SEC_OUT_LEVEL4_FLAGS (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT | \ + BTM_SEC_OUT_MITM | BTM_SEC_MODE4_LEVEL4) + +#define BTM_SEC_IN_LEVEL4_FLAGS (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT | \ + BTM_SEC_IN_MITM | BTM_SEC_MODE4_LEVEL4) + tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle, CONNECTION_TYPE conn_type, tBTM_SEC_CALLBACK *p_callback, @@ -2048,8 +2119,8 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle return(BTM_MODE_UNSUPPORTED); } - /* SDP connection we will always let through */ - if (BT_PSM_SDP == psm) + /* Services level0 by default have no security */ + if ((btm_sec_is_serv_level0(psm)) && (!btm_cb.devcb.secure_connections_only)) { (*p_callback) (bd_addr,transport, p_ref_data, BTM_SUCCESS_NO_SECURITY); return(BTM_SUCCESS); @@ -2057,7 +2128,15 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle #if (L2CAP_UCD_INCLUDED == TRUE) if ( conn_type & CONNECTION_TYPE_CONNLESS_MASK ) { - security_required = p_serv_rec->ucd_security_flags; + if (btm_cb.security_mode == BTM_SEC_MODE_SC) + { + security_required = btm_sec_set_serv_level4_flags (p_serv_rec->ucd_security_flags, + is_originator); + } + else + { + security_required = p_serv_rec->ucd_security_flags; + } rc = BTM_CMD_STARTED; if (is_originator) @@ -2081,6 +2160,12 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle } } + if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) && + (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) + { + rc = BTM_CMD_STARTED; + } + if (rc == BTM_SUCCESS) { if (p_callback) @@ -2092,7 +2177,36 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle else #endif { - security_required = p_serv_rec->security_flags; + if (btm_cb.security_mode == BTM_SEC_MODE_SC) + { + security_required = btm_sec_set_serv_level4_flags (p_serv_rec->security_flags, + is_originator); + } + else + { + security_required = p_serv_rec->security_flags; + } + } + + BTM_TRACE_DEBUG("%s: security_required 0x%04x, is_originator 0x%02x, psm 0x%04x", + __FUNCTION__, security_required, is_originator, psm); + + if ((!is_originator) && (security_required & BTM_SEC_MODE4_LEVEL4)) + { + BOOLEAN local_supports_sc = controller_get_interface()->supports_secure_connections(); + /* acceptor receives L2CAP Channel Connect Request for Secure Connections Only service */ + if (!(local_supports_sc) || !(p_dev_rec->remote_supports_secure_connections)) + { + BTM_TRACE_DEBUG("%s: SC only service, local_support_for_sc %d", + "rmt_support_for_sc : %d -> fail pairing", __FUNCTION__, + local_supports_sc, + p_dev_rec->remote_supports_secure_connections); + if (p_callback) + (*p_callback) (bd_addr, transport, (void *)p_ref_data, + BTM_MODE4_LEVEL4_NOT_SUPPORTED); + + return (BTM_MODE4_LEVEL4_NOT_SUPPORTED); + } } /* there are some devices (moto KRZR) which connects to several services at the same time */ @@ -2103,10 +2217,12 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle psm, btm_pair_state_descr(btm_cb.pairing_state), btm_cb.security_mode, p_dev_rec->sm4); BTM_TRACE_EVENT ("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)) - ) + if ((btm_cb.security_mode == BTM_SEC_MODE_UNDEFINED || + btm_cb.security_mode == BTM_SEC_MODE_NONE || + btm_cb.security_mode == BTM_SEC_MODE_SERVICE || + btm_cb.security_mode == BTM_SEC_MODE_LINK) || + (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 */ @@ -2134,6 +2250,12 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle } } + if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) && + (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) + { + rc = BTM_CMD_STARTED; + } + if (rc == BTM_SUCCESS) { if (p_callback) @@ -2149,49 +2271,34 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle /* Save pointer to service record */ p_dev_rec->p_cur_service = p_serv_rec; - /* mess /w security_required in btm_sec_l2cap_access_req for Lisbon */ - if (btm_cb.security_mode == BTM_SEC_MODE_SP) + /* Modify security_required in btm_sec_l2cap_access_req for Lisbon */ + if (btm_cb.security_mode == BTM_SEC_MODE_SP || + btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG || + btm_cb.security_mode == BTM_SEC_MODE_SC) { - if (is_originator) + if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) { - if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) + if (is_originator) { /* SM4 to SM4 -> always authenticate & encrypt */ security_required |= (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT); } - else - { - if ( !(BTM_SM4_KNOWN & p_dev_rec->sm4)) - { - BTM_TRACE_DEBUG ("remote features unknown!!sec_flags:0x%x", p_dev_rec->sec_flags); - /* the remote features are not known yet */ - p_dev_rec->sm4 |= BTM_SM4_REQ_PEND; - - return(BTM_CMD_STARTED); - } - } - } - else - { - /* responder */ - if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) + else /* acceptor */ { /* SM4 to SM4: the acceptor needs to make sure the authentication is already done */ chk_acp_auth_done = TRUE; /* SM4 to SM4 -> always authenticate & encrypt */ security_required |= (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT); - } - else - { - if ( !(BTM_SM4_KNOWN & p_dev_rec->sm4)) - { - BTM_TRACE_DEBUG ("(rsp) remote features unknown!!sec_flags:0x%x", p_dev_rec->sec_flags); - /* the remote features are not known yet */ - p_dev_rec->sm4 |= BTM_SM4_REQ_PEND; + } + } + else if (!(BTM_SM4_KNOWN & p_dev_rec->sm4)) + { + /* the remote features are not known yet */ + BTM_TRACE_DEBUG("%s: (%s) remote features unknown!!sec_flags:0x%02x", __FUNCTION__, + (is_originator) ? "initiator" : "acceptor", p_dev_rec->sec_flags); - return(BTM_CMD_STARTED); - } - } + p_dev_rec->sm4 |= BTM_SM4_REQ_PEND; + return (BTM_CMD_STARTED); } } @@ -2234,9 +2341,15 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle } } - /* if the originator is using dynamic PSM in legacy mode, do not start any security process now. - * The layer above L2CAP needs to carry out the security requirement after L2CAP connect response is received*/ - if (is_originator && (btm_cb.security_mode != BTM_SEC_MODE_SP || !BTM_SEC_IS_SM4(p_dev_rec->sm4)) && (psm >= 0x1001)) + /* if the originator is using dynamic PSM in legacy mode, do not start any security process now + * The layer above L2CAP needs to carry out the security requirement after L2CAP connect + * response is received */ + if (is_originator && + ((btm_cb.security_mode == BTM_SEC_MODE_UNDEFINED || + btm_cb.security_mode == BTM_SEC_MODE_NONE || + btm_cb.security_mode == BTM_SEC_MODE_SERVICE || + btm_cb.security_mode == BTM_SEC_MODE_LINK) || + !BTM_SEC_IS_SM4(p_dev_rec->sm4)) && (psm >= 0x1001)) { BTM_TRACE_EVENT ("dynamic PSM:0x%x in legacy mode - postponed for upper layer", psm); /* restore the old settings */ @@ -2286,8 +2399,23 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) { - /* If we already have a link key to the connected peer, is the link key secure enough ? */ - btm_sec_check_upgrade(p_dev_rec, is_originator); + if ((p_dev_rec->security_required & BTM_SEC_MODE4_LEVEL4) && + (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) + { + /* BTM_LKEY_TYPE_AUTH_COMB_P_256 is the only acceptable key in this case */ + if ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) != 0) + { + p_dev_rec->sm4 |= BTM_SM4_UPGRADE; + } + p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED | + BTM_SEC_AUTHENTICATED); + BTM_TRACE_DEBUG ("%s: sec_flags:0x%x", __FUNCTION__, p_dev_rec->sec_flags); + } + else + { + /* If we already have a link key to the connected peer, is it secure enough? */ + btm_sec_check_upgrade(p_dev_rec, is_originator); + } } BTM_TRACE_EVENT ("%s() PSM:%d Handle:%d State:%d Flags: 0x%x Required: 0x%x Service ID:%d", @@ -2354,6 +2482,16 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o return BTM_NO_RESOURCES; } + if ((btm_cb.security_mode == BTM_SEC_MODE_SC) && (!btm_sec_is_serv_level0(psm))) + { + security_required = btm_sec_set_serv_level4_flags (p_serv_rec->security_flags, + is_originator); + } + else + { + security_required = p_serv_rec->security_flags; + } + /* there are some devices (moto phone) which connects to several services at the same time */ /* we will process one after another */ if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) ) @@ -2362,11 +2500,13 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o psm, mx_proto_id, mx_chan_id, btm_pair_state_descr(btm_cb.pairing_state)); 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)) - ) + + if ((btm_cb.security_mode == BTM_SEC_MODE_UNDEFINED || + btm_cb.security_mode == BTM_SEC_MODE_NONE || + btm_cb.security_mode == BTM_SEC_MODE_SERVICE || + btm_cb.security_mode == BTM_SEC_MODE_LINK) || + (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 */ @@ -2393,23 +2533,100 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o rc = BTM_SUCCESS; } } + if ((rc == BTM_SUCCESS) && (security_required & BTM_SEC_MODE4_LEVEL4) && + (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) + { + rc = BTM_CMD_STARTED; + } + } + + if (rc == BTM_SUCCESS) + { + BTM_TRACE_EVENT("%s: allow to bypass, checking authorization", __FUNCTION__); + /* the security in BTM_SEC_IN_FLAGS is fullfilled so far, check the requirements in */ + /* btm_sec_execute_procedure */ + if ((is_originator && (p_serv_rec->security_flags & BTM_SEC_OUT_AUTHORIZE)) || + (!is_originator && (p_serv_rec->security_flags & BTM_SEC_IN_AUTHORIZE))) + { + BTM_TRACE_EVENT("%s: still need authorization", __FUNCTION__); + rc = BTM_CMD_STARTED; + } + } + + /* Check whether there is a pending security procedure, if so we should always queue */ + /* the new security request */ + if (p_dev_rec->sec_state != BTM_SEC_STATE_IDLE) + { + BTM_TRACE_EVENT("%s: There is a pending security procedure", __FUNCTION__); + rc = BTM_CMD_STARTED; } 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; + BTM_TRACE_EVENT("%s: call btm_sec_queue_mx_request", __FUNCTION__); + btm_sec_queue_mx_request (bd_addr, psm, is_originator, mx_proto_id, + mx_chan_id, p_callback, p_ref_data); + } + else /* rc == BTM_SUCCESS */ + { + /* access granted */ + if (p_callback) + { + (*p_callback) (bd_addr, transport, p_ref_data, (UINT8)rc); + } + } + + BTM_TRACE_EVENT("%s: return with rc = 0x%02x in delayed state %s", __FUNCTION__, rc, + btm_pair_state_descr(btm_cb.pairing_state)); + return rc; + } + + if ((!is_originator) && ((security_required & BTM_SEC_MODE4_LEVEL4) || + (btm_cb.security_mode == BTM_SEC_MODE_SC))) + { + BOOLEAN local_supports_sc = controller_get_interface()->supports_secure_connections(); + /* acceptor receives service connection establishment Request for */ + /* Secure Connections Only service */ + if (!(local_supports_sc) || !(p_dev_rec->remote_supports_secure_connections)) + { + BTM_TRACE_DEBUG("%s: SC only service,local_support_for_sc %d,", + "remote_support_for_sc %d: fail pairing",__FUNCTION__, + local_supports_sc, p_dev_rec->remote_supports_secure_connections); + + if (p_callback) + (*p_callback) (bd_addr, transport, (void *)p_ref_data, + BTM_MODE4_LEVEL4_NOT_SUPPORTED); + + return (BTM_MODE4_LEVEL4_NOT_SUPPORTED); } } p_dev_rec->p_cur_service = p_serv_rec; - p_dev_rec->security_required = p_serv_rec->security_flags; + p_dev_rec->security_required = security_required; - if (BTM_SEC_MODE_SP == btm_cb.security_mode) + if (btm_cb.security_mode == BTM_SEC_MODE_SP || + btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG || + btm_cb.security_mode == BTM_SEC_MODE_SC) { if (BTM_SEC_IS_SM4(p_dev_rec->sm4)) { - /* If we already have a link key, check if that link key is good enough */ - btm_sec_check_upgrade(p_dev_rec, is_originator); + if ((p_dev_rec->security_required & BTM_SEC_MODE4_LEVEL4) && + (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) + { + /* BTM_LKEY_TYPE_AUTH_COMB_P_256 is the only acceptable key in this case */ + if ((p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN) != 0) + { + p_dev_rec->sm4 |= BTM_SM4_UPGRADE; + } + + p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED | + BTM_SEC_AUTHENTICATED); + BTM_TRACE_DEBUG("%s: sec_flags:0x%x", __FUNCTION__, p_dev_rec->sec_flags); + } + else + { + /* If we already have a link key, check if that link key is good enough */ + btm_sec_check_upgrade(p_dev_rec, is_originator); + } } } @@ -3104,51 +3321,94 @@ void btm_io_capabilities_req (UINT8 *p) evt_data.oob_data = BTM_OOB_NONE; evt_data.auth_req = BTM_DEFAULT_AUTH_REQ; - BTM_TRACE_EVENT ("btm_io_capabilities_req() State: %s", btm_pair_state_descr(btm_cb.pairing_state)); + BTM_TRACE_EVENT("%s: State: %s", __FUNCTION__, btm_pair_state_descr(btm_cb.pairing_state)); p_dev_rec = btm_find_or_alloc_dev (evt_data.bd_addr); + + BTM_TRACE_DEBUG("%s:Security mode: %d, Num Read Remote Feat pages: %d", __FUNCTION__, + btm_cb.security_mode, p_dev_rec->num_read_pages); + + if ((btm_cb.security_mode == BTM_SEC_MODE_SC) && (p_dev_rec->num_read_pages == 0)) + { + BTM_TRACE_EVENT("%s: Device security mode is SC only.", + "To continue need to know remote features.", __FUNCTION__); + + p_dev_rec->remote_features_needed = TRUE; + return; + } + p_dev_rec->sm4 |= BTM_SM4_TRUE; - BTM_TRACE_EVENT ("btm_io_capabilities_req() State: %s Flags: 0x%04x p_cur_service: 0x%08x", - btm_pair_state_descr(btm_cb.pairing_state), btm_cb.pairing_flags, p_dev_rec->p_cur_service); + BTM_TRACE_EVENT("%s: State: %s Flags: 0x%04x p_cur_service: 0x%08x", + __FUNCTION__, btm_pair_state_descr(btm_cb.pairing_state), + btm_cb.pairing_flags, p_dev_rec->p_cur_service); - if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) + if (p_dev_rec->p_cur_service) { - if (btm_cb.pairing_state == BTM_PAIR_STATE_INCOMING_SSP) - { - /* received IO capability response already-> not the originator of SSP */ + BTM_TRACE_EVENT("%s: cur_service psm: 0x%04x, security_flags: 0x%04x", + __FUNCTION__, p_dev_rec->p_cur_service->psm, + p_dev_rec->p_cur_service->security_flags); + } + + switch (btm_cb.pairing_state) + { + /* initiator connecting */ + case BTM_PAIR_STATE_IDLE: + //TODO: Handle Idle pairing state + //security_required = p_dev_rec->security_required; + break; + + /* received IO capability response already->acceptor */ + case BTM_PAIR_STATE_INCOMING_SSP: is_orig = FALSE; if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_PEER_STARTED_DD) + { + /* acceptor in dedicated bonding */ evt_data.auth_req = BTM_DEFAULT_DD_AUTH_REQ; - } - /* security is already in progress */ - else if (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_PIN_REQ) - { -/* coverity[uninit_use_in_call] -Event uninit_use_in_call: Using uninitialized element of array "evt_data.bd_addr" in call to function "memcmp" -False-positive: evt_data.bd_addr is set at the beginning with: STREAM_TO_BDADDR (evt_data.bd_addr, p); -*/ - if (memcmp (evt_data.bd_addr, btm_cb.pairing_bda, BD_ADDR_LEN)) + } + break; + + /* initiator, at this point it is expected to be dedicated bonding + initiated by local device */ + case BTM_PAIR_STATE_WAIT_PIN_REQ: + if (!memcmp (evt_data.bd_addr, btm_cb.pairing_bda, BD_ADDR_LEN)) { - /* and it's not the device in bonding -> reject it */ - err_code = HCI_ERR_HOST_BUSY_PAIRING; + evt_data.auth_req = BTM_DEFAULT_DD_AUTH_REQ; } else { - /* local device initiated dedicated bonding */ - evt_data.auth_req = BTM_DEFAULT_DD_AUTH_REQ; + err_code = HCI_ERR_HOST_BUSY_PAIRING; } - } - else - { + break; + + /* any other state is unexpected */ + default: err_code = HCI_ERR_HOST_BUSY_PAIRING; - } + BTM_TRACE_ERROR("%s: Unexpected Pairing state received %d", __FUNCTION__, + btm_cb.pairing_state); + break; } - /* paring is not allowed */ if (btm_cb.pairing_disabled) + { + /* pairing is not allowed */ + BTM_TRACE_DEBUG("%s: Pairing is not allowed -> fail pairing.", __FUNCTION__); err_code = HCI_ERR_PAIRING_NOT_ALLOWED; + } + else if (btm_cb.security_mode == BTM_SEC_MODE_SC) + { + BOOLEAN local_supports_sc = controller_get_interface()->supports_secure_connections(); + /* device in Secure Connections Only mode */ + if (!(local_supports_sc) || !(p_dev_rec->remote_supports_secure_connections)) + { + BTM_TRACE_DEBUG("%s: SC only service, local_support_for_sc %d,", + " remote_support_for_sc 0x%02x -> fail pairing", __FUNCTION__, + local_supports_sc, p_dev_rec->remote_supports_secure_connections); + + err_code = HCI_ERR_PAIRING_NOT_ALLOWED; + } + } if (err_code != 0) { @@ -3169,7 +3429,16 @@ False-positive: evt_data.bd_addr is set at the beginning with: STREAM_TO_BDA p_dev_rec->p_cur_service && (p_dev_rec->p_cur_service->security_flags & BTM_SEC_OUT_AUTHENTICATE)) { - evt_data.auth_req = (p_dev_rec->p_cur_service->security_flags & BTM_SEC_OUT_MITM) ? BTM_AUTH_SP_YES : BTM_AUTH_SP_NO; + if (btm_cb.security_mode == BTM_SEC_MODE_SC) + { + /* SC only mode device requires MITM protection */ + evt_data.auth_req = BTM_AUTH_SP_YES; + } + else + { + evt_data.auth_req = (p_dev_rec->p_cur_service->security_flags & + BTM_SEC_OUT_MITM)? BTM_AUTH_SP_YES : BTM_AUTH_SP_NO; + } } } @@ -3212,14 +3481,23 @@ False-positive: False-positive: evt_data.bd_addr is set at the beginning with: evt_data.auth_req = (BTM_AUTH_DD_BOND | (evt_data.auth_req & BTM_AUTH_YN_BIT)); } - /* if the user does not indicate "reply later" by setting the oob_data to unknown - * send the response right now. Save the current IO capability in the control block */ + if (btm_cb.security_mode == BTM_SEC_MODE_SC) + { + /* At this moment we know that both sides are SC capable, device in */ + /* SC only mode requires MITM for any service so let's set MITM bit */ + evt_data.auth_req |= BTM_AUTH_YN_BIT; + BTM_TRACE_DEBUG("%s: for device in \"SC only\" mode set auth_req to 0x%02x", + __FUNCTION__, evt_data.auth_req); + } + + /* if the user does not indicate "reply later" by setting the oob_data to unknown */ + /* send the response right now. Save the current IO capability in the control block */ btm_cb.devcb.loc_auth_req = evt_data.auth_req; btm_cb.devcb.loc_io_caps = evt_data.io_cap; - BTM_TRACE_EVENT ("btm_io_capabilities_req: State: %s IO_CAP:%d oob_data:%d auth_req:%d", - btm_pair_state_descr(btm_cb.pairing_state), evt_data.io_cap, - evt_data.oob_data, evt_data.auth_req); + BTM_TRACE_EVENT("%s: State: %s IO_CAP:%d oob_data:%d auth_req:%d", + __FUNCTION__, btm_pair_state_descr(btm_cb.pairing_state), evt_data.io_cap, + evt_data.oob_data, evt_data.auth_req); btsnd_hcic_io_cap_req_reply(evt_data.bd_addr, evt_data.io_cap, evt_data.oob_data, evt_data.auth_req); @@ -5042,6 +5320,14 @@ static tBTM_STATUS btm_sec_execute_procedure (tBTM_SEC_DEV_REC *p_dev_rec) return(BTM_CMD_STARTED); } + if ((p_dev_rec->security_required & BTM_SEC_MODE4_LEVEL4) && + (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256)) + { + BTM_TRACE_EVENT("%s: Security Manager: SC only service, but link key type is 0x%02x -", + "security failure", __FUNCTION__, p_dev_rec->link_key_type); + return (BTM_FAILED_ON_SECURITY); + } + /* If connection is not authorized and authorization is required */ /* start authorization and return PENDING to the caller */ if (!(p_dev_rec->sec_flags & BTM_SEC_AUTHORIZED) @@ -5701,6 +5987,52 @@ static BOOLEAN btm_sec_queue_encrypt_request (BD_ADDR bd_addr, tBT_TRANSPORT tra /******************************************************************************* ** +** Function btm_sec_set_peer_sec_caps +** +** Description This function is called to set sm4 and rmt_sec_caps fields +** based on the available peer device features. +** +** Returns void +** +*******************************************************************************/ +void btm_sec_set_peer_sec_caps(tACL_CONN *p_acl_cb, tBTM_SEC_DEV_REC *p_dev_rec) +{ + BD_ADDR rem_bd_addr; + UINT8 *p_rem_bd_addr; + + if ((btm_cb.security_mode == BTM_SEC_MODE_SP || + btm_cb.security_mode == BTM_SEC_MODE_SP_DEBUG || + btm_cb.security_mode == BTM_SEC_MODE_SC) && + HCI_SSP_HOST_SUPPORTED(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_1])) + { + p_dev_rec->sm4 = BTM_SM4_TRUE; + p_dev_rec->remote_supports_secure_connections = + (HCI_SC_HOST_SUPPORTED(p_acl_cb->peer_lmp_features[HCI_EXT_FEATURES_PAGE_1])); + } + else + { + p_dev_rec->sm4 = BTM_SM4_KNOWN; + p_dev_rec->remote_supports_secure_connections = FALSE; + } + + BTM_TRACE_API("%s: sm4: 0x%02x, rmt_support_for_secure_connections %d", __FUNCTION__, + p_dev_rec->sm4, p_dev_rec->remote_supports_secure_connections); + + + if (p_dev_rec->remote_features_needed) + { + BTM_TRACE_EVENT("%s: Now device in SC Only mode, waiting for peer remote features!", + __FUNCTION__); + p_rem_bd_addr = (UINT8*) rem_bd_addr; + BDADDR_TO_STREAM(p_rem_bd_addr, p_dev_rec->bd_addr); + p_rem_bd_addr = (UINT8*) rem_bd_addr; + btm_io_capabilities_req(p_rem_bd_addr); + p_dev_rec->remote_features_needed = FALSE; + } +} + +/******************************************************************************* +** ** Function btm_sec_clean_pending_req_queue ** ** Description This function cleans up the pending security request when the @@ -5729,7 +6061,26 @@ static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT t } p_e = (tBTM_SEC_QUEUE_ENTRY *) GKI_getnext ((void *)p_e); } - return; +} + +/******************************************************************************* +** +** Function btm_sec_is_serv_level0 +** +** Description This function is called to check if the service corresponding +** to PSM is security mode 4 level 0 service. +** +** Returns TRUE if the service is security mode 4 level 0 service +** +*******************************************************************************/ +static BOOLEAN btm_sec_is_serv_level0(UINT16 psm) +{ + if (psm == BT_PSM_SDP) + { + BTM_TRACE_DEBUG("%s: PSM: 0x%04x -> mode 4 level 0 service", __FUNCTION__, psm); + return TRUE; + } + return FALSE; } /******************************************************************************* @@ -5776,7 +6127,23 @@ static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC *p_dev_rec, tBT_TRA } p_e = (tBTM_SEC_QUEUE_ENTRY *) GKI_getnext ((void *)p_e); } - return; +} + +/******************************************************************************* +** +** Function btm_sec_set_serv_level4_flags +** +** Description This function is called to set security mode 4 level 4 flags. +** +** Returns service security requirements updated to include secure +** connections only mode. +** +*******************************************************************************/ +static UINT16 btm_sec_set_serv_level4_flags(UINT16 cur_security, BOOLEAN is_originator) +{ + UINT16 sec_level4_flags = is_originator ? BTM_SEC_OUT_LEVEL4_FLAGS : BTM_SEC_IN_LEVEL4_FLAGS; + + return cur_security | sec_level4_flags; } #if (BLE_INCLUDED == TRUE) @@ -5805,7 +6172,6 @@ void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec) #endif } - /******************************************************************************* ** ** Function btm_sec_is_a_bonded_dev @@ -5894,7 +6260,6 @@ BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_D return(found); } - /******************************************************************************* ** ** Function btm_sec_use_smp_br_chnl diff --git a/stack/hcic/hcicmds.c b/stack/hcic/hcicmds.c index 13d755895..8d340cb72 100644 --- a/stack/hcic/hcicmds.c +++ b/stack/hcic/hcicmds.c @@ -1401,7 +1401,7 @@ BOOLEAN btsnd_hcic_io_cap_req_reply (BD_ADDR bd_addr, UINT8 capability, p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_IO_CAP_RESP; p->offset = 0; - UINT16_TO_STREAM (pp, HCI_IO_CAPABILITY_RESPONSE); + UINT16_TO_STREAM (pp, HCI_IO_CAPABILITY_REQUEST_REPLY); UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_IO_CAP_RESP); BDADDR_TO_STREAM (pp, bd_addr); diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h index c108439d7..de0b1959e 100644 --- a/stack/include/btm_api.h +++ b/stack/include/btm_api.h @@ -60,8 +60,9 @@ enum BTM_DELAY_CHECK, /* 15 delay the check on encryption */ BTM_SCO_BAD_LENGTH, /* 16 Bad SCO over HCI data length */ BTM_SUCCESS_NO_SECURITY, /* 17 security passed, no security set */ - BTM_FAILED_ON_SECURITY , /* 18 security failed */ - BTM_REPEATED_ATTEMPTS /* 19 repeated attempts for LE security requests */ + BTM_FAILED_ON_SECURITY, /* 18 security failed */ + BTM_REPEATED_ATTEMPTS, /* 19 repeated attempts for LE security requests */ + BTM_MODE4_LEVEL4_NOT_SUPPORTED /* 20 Secure Connections Only Mode can't be supported */ }; typedef UINT8 tBTM_STATUS; @@ -1085,6 +1086,9 @@ typedef void (tBTM_ESCO_CBACK) (tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) #define BTM_SEC_MODE_SP_DEBUG 5 #define BTM_SEC_MODE_SC 6 +/* Maximum Number of BTM Security Modes */ +#define BTM_SEC_MODES_MAX 7 + /* Security Service Levels [bit mask] (BTM_SetSecurityLevel) ** Encryption should not be used without authentication */ @@ -1095,8 +1099,7 @@ typedef void (tBTM_ESCO_CBACK) (tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) #define BTM_SEC_OUT_AUTHORIZE 0x0008 /* Outbound call requires authorization */ #define BTM_SEC_OUT_AUTHENTICATE 0x0010 /* Outbound call requires authentication */ #define BTM_SEC_OUT_ENCRYPT 0x0020 /* Outbound call requires encryption */ -#define BTM_SEC_BOND 0x0040 /* Bonding */ -#define BTM_SEC_BOND_CONN 0x0080 /* bond_created_connection */ +#define BTM_SEC_MODE4_LEVEL4 0x0040 /* Secure Connections Only Mode */ #define BTM_SEC_FORCE_MASTER 0x0100 /* Need to switch connection to be master */ #define BTM_SEC_ATTEMPT_MASTER 0x0200 /* Try to switch connection to be master */ #define BTM_SEC_FORCE_SLAVE 0x0400 /* Need to switch connection to be master */ @@ -3212,6 +3215,23 @@ extern void BTM_SetPairableMode (BOOLEAN allow_pairing, BOOLEAN connect_only_pai /******************************************************************************* ** +** Function BTM_SetSecureConnectionsOnly +** +** Description Enable or disable default treatment for Mode 4 Level 0 services +** +** Parameter secure_connections_only_mode - (TRUE or FALSE) +** TRUE means that the device should treat Mode 4 Level 0 services as +** services of other levels. +** FALSE means that the device should provide default treatment for +** Mode 4 Level 0 services. +** +** Returns void +** +*******************************************************************************/ +extern void BTM_SetSecureConnectionsOnly (BOOLEAN secure_connections_only_mode); + +/******************************************************************************* +** ** Function BTM_SetSecurityLevel ** ** Description Register service security level with Security Manager. Each @@ -3524,15 +3544,34 @@ extern UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, /******************************************************************************* ** -** Function BTM_IsLeScSuppLocally +** Function BTM_BothEndsSupportSecureConnections +** +** Description This function is called to check if both the local device and the peer device +** specified by bd_addr support BR/EDR Secure Connections. +** +** Parameters: bd_addr - address of the peer +** +** Returns TRUE if BR/EDR Secure Connections are supported by both local +** and the remote device. +** else FALSE. +** +*******************************************************************************/ +extern BOOLEAN BTM_BothEndsSupportSecureConnections(BD_ADDR bd_addr); + +/******************************************************************************* +** +** Function BTM_PeerSupportsSecureConnections +** +** Description This function is called to check if the peer supports +** BR/EDR Secure Connections. ** -** Description This function is called to check if LE SC is supported. +** Parameters: bd_addr - address of the peer ** -** Parameters: None. +** Returns TRUE if BR/EDR Secure Connections are supported by the peer, +** else FALSE. ** -** Returns Boolean - TRUE if LE SC is supported. *******************************************************************************/ -extern BOOLEAN BTM_IsLeScSuppLocally (void); +extern BOOLEAN BTM_PeerSupportsSecureConnections(BD_ADDR bd_addr); /******************************************************************************* ** diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h index 31fd90b69..92d9d844e 100644 --- a/stack/include/hcidefs.h +++ b/stack/include/hcidefs.h @@ -77,7 +77,7 @@ #define HCI_SETUP_ESCO_CONNECTION (0x0028 | HCI_GRP_LINK_CONTROL_CMDS) #define HCI_ACCEPT_ESCO_CONNECTION (0x0029 | HCI_GRP_LINK_CONTROL_CMDS) #define HCI_REJECT_ESCO_CONNECTION (0x002A | HCI_GRP_LINK_CONTROL_CMDS) -#define HCI_IO_CAPABILITY_RESPONSE (0x002B | HCI_GRP_LINK_CONTROL_CMDS) +#define HCI_IO_CAPABILITY_REQUEST_REPLY (0x002B | HCI_GRP_LINK_CONTROL_CMDS) #define HCI_USER_CONF_REQUEST_REPLY (0x002C | HCI_GRP_LINK_CONTROL_CMDS) #define HCI_USER_CONF_VALUE_NEG_REPLY (0x002D | HCI_GRP_LINK_CONTROL_CMDS) #define HCI_USER_PASSKEY_REQ_REPLY (0x002E | HCI_GRP_LINK_CONTROL_CMDS) @@ -230,7 +230,7 @@ #define HCI_SET_MWS_SCAN_FREQUENCY_TABLE (0x0072 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) #define HCI_SET_MWS_PATTERN_CONFIGURATION (0x0073 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) -/* ConnectionLess Broadcast */ +/* Connectionless Broadcast */ #define HCI_SET_RESERVED_LT_ADDR (0x0074 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) #define HCI_DELETE_RESERVED_LT_ADDR (0x0075 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) #define HCI_WRITE_CLB_DATA (0x0076 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) @@ -697,10 +697,6 @@ /* Definitions for LE Channel Map */ #define HCI_BLE_CHNL_MAP_SIZE 5 - -#define HCI_EVENT_RSP_FIRST HCI_INQUIRY_COMP_EVT -#define HCI_EVENT_RSP_LAST HCI_CLB_CHANNEL_CHANGE_EVT - #define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */ #define HCI_NAP_TRACE_EVT 0xFF /* was define 0xFE, 0xFD, change to 0xFF because conflict w/ TCI_EVT and per @@ -2291,9 +2287,9 @@ typedef struct #define HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF 18 #define HCI_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF] & HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK) -#define HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_MASK 0x80 -#define HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_OFF 18 -#define HCI_IO_CAPABILITY_RESPONSE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_OFF] & HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_MASK) +#define HCI_SUPP_COMMANDS_IO_CAPABILITY_REQUEST_REPLY_MASK 0x80 +#define HCI_SUPP_COMMANDS_IO_CAPABILITY_REQUEST_REPLY_OFF 18 +#define HCI_IO_CAPABILITY_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_IO_CAPABILITY_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_IO_CAPABILITY_REQUEST_REPLY_MASK) #define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_MASK 0x01 #define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_OFF 19 |