summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMudumba Ananth <ananthm@broadcom.com>2015-01-30 02:33:02 -0800
committerAndre Eisenbach <eisenbach@google.com>2015-04-13 14:09:06 -0700
commit899b77140675a157dba034e98527ab546bc9ac35 (patch)
tree998eb1873ed2ac4c14795b095e9b8b7516d2d6ec
parent7fb0da6c0df9491f06c61ab0ba4183129502a065 (diff)
downloadandroid_system_bt-899b77140675a157dba034e98527ab546bc9ac35.tar.gz
android_system_bt-899b77140675a157dba034e98527ab546bc9ac35.tar.bz2
android_system_bt-899b77140675a157dba034e98527ab546bc9ac35.zip
BR/EDR secure connections support
As a part of BT 4.1 stack upgrade, added host support for BR/EDR secure connections to be able to interact with controllers that support secure connections and upgrade the SSP mechanism to use secure connection rules. This change checks for controller support in the extended_features (LMP page 2) and then declares the host support (extended_features LMP page 1) using WRITE SECURE CONNECTIONS HOST SUPPORT. If both the sides support secure connections, the simple pairing process utilizes the link key generated using P-256 elliptic curve (in the controller) and both the sides will be in a secure connection. Bug: 19289699 Change-Id: Idb3c41f439973bea137f5a4a69468c1f55aecbd7
-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