summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bta/include/bta_api.h1
-rw-r--r--device/src/controller.c6
-rw-r--r--stack/btm/btm_acl.c126
-rw-r--r--stack/btm/btm_int.h9
-rw-r--r--stack/btm/btm_sco.c23
-rw-r--r--stack/btm/btm_sec.c581
-rw-r--r--stack/hcic/hcicmds.c2
-rw-r--r--stack/include/btm_api.h57
-rw-r--r--stack/include/hcidefs.h14
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