summaryrefslogtreecommitdiffstats
path: root/stack/btm/btm_sec.c
diff options
context:
space:
mode:
Diffstat (limited to 'stack/btm/btm_sec.c')
-rw-r--r--stack/btm/btm_sec.c581
1 files changed, 473 insertions, 108 deletions
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