{
/* Take the link out of sniff and set L2C idle time to 0 */
bta_dm_pm_active(p_scb->peer_addr);
- L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0);
+ L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0, BT_TRANSPORT_BR_EDR);
/* if SCO is open close SCO and wait on RFCOMM close */
if (bta_ag_sco_is_open(p_scb))
UNUSED(p_data);
/* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after last channel is closed) */
- L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0);
+ L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_BR_EDR);
+ L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_LE);
/* disable all active subsystems */
bta_sys_disable(BTA_SYS_HW_BLUETOOTH);
{
tBTM_STATUS status = BTM_SUCCESS;
tBTA_DM_SEC sec_event;
- char* p_name = NULL;
+ char *p_name = NULL;
UINT8 i;
-
- APPL_TRACE_DEBUG("bta_dm_ble_smp_cback");
+ tBT_DEVICE_TYPE dev_type;
if (!bta_dm_cb.p_sec_cback)
return BTM_NOT_AUTHORIZED;
bta_dm_cb.p_sec_cback(BTA_DM_BLE_OOB_REQ_EVT, &sec_event);
break;
+ case BTM_LE_NC_REQ_EVT:
+ bdcpy(sec_event.key_notif.bd_addr, bda);
+ BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+ sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
+ sec_event.key_notif.passkey = p_data->key_notif;
+ bta_dm_cb.p_sec_cback(BTA_DM_BLE_NC_REQ_EVT, &sec_event);
+ break;
+
case BTM_LE_KEY_EVT:
bdcpy(sec_event.ble_key.bd_addr, bda);
sec_event.ble_key.key_type = p_data->key.key_type;
-
- if (p_data->key.key_type == BTM_LE_KEY_PID)
- {
- for (i=0; i<BT_OCTET16_LEN; i++ )
- {
- sec_event.ble_key.key_value.pid_key.irk[i] = p_data->key.p_key_value->pid_key.irk[i];
- }
- sec_event.ble_key.key_value.pid_key.addr_type = p_data->key.p_key_value->pid_key.addr_type;
- memcpy( &(sec_event.ble_key.key_value.pid_key.static_addr),
- &(p_data->key.p_key_value->pid_key.static_addr),
- sizeof (BD_ADDR));
- }
- else
- {
- memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE));
- }
- // memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE)); todo will crash
+ sec_event.ble_key.p_key_value = p_data->key.p_key_value;
bta_dm_cb.p_sec_cback(BTA_DM_BLE_KEY_EVT, &sec_event);
break;
case BTM_LE_COMPLT_EVT:
bdcpy(sec_event.auth_cmpl.bd_addr, bda);
+ BTM_ReadDevInfo(bda, &dev_type, &sec_event.auth_cmpl.addr_type);
p_name = BTM_SecReadDevName(bda);
if (p_name != NULL)
{
sec_event.auth_cmpl.success = TRUE;
GATT_ConfigServiceChangeCCC(bda, TRUE, BT_TRANSPORT_LE);
}
+
if (bta_dm_cb.p_sec_cback)
{
//bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
/*******************************************************************************
**
+** Function bta_dm_ble_confirm_reply
+**
+** Description This is response to SM numeric comparison request submitted
+** to application.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_confirm_reply (tBTA_DM_MSG *p_data)
+{
+ if (p_data->confirm.accept)
+ {
+ BTM_BleConfirmReply(p_data->confirm.bd_addr, BTM_SUCCESS);
+ }
+ else
+ {
+ BTM_BleConfirmReply(p_data->ble_passkey_reply.bd_addr, BTM_NOT_AUTHORIZED);
+ }
+}
+
+/*******************************************************************************
+**
** Function bta_dm_security_grant
**
** Description This function grant SMP security request access.
#include "btm_int.h"
#include <string.h>
#include "utl.h"
-#include "vendor_ble.h"
/*****************************************************************************
** Constants
}
/*******************************************************************************
**
+** Function BTA_DmBleConfirmReply
+**
+** Description Send BLE SMP SC user confirmation reply.
+**
+** Parameters: bd_addr - BD address of the peer
+** accept - numbers to compare are the same or different.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBleConfirmReply(BD_ADDR bd_addr, BOOLEAN accept)
+{
+ tBTA_DM_API_CONFIRM *p_msg = (tBTA_DM_API_CONFIRM *)GKI_getbuf(sizeof(tBTA_DM_API_CONFIRM));
+ if (p_msg != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_CONFIRM));
+ p_msg->hdr.event = BTA_DM_API_BLE_CONFIRM_REPLY_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->accept = accept;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
** Function BTA_DmBleSecurityGrant
**
** Description Grant security request access.
if (cmn_ble_vsc_cb.max_filter > 0)
{
btm_ble_adv_filter_cleanup();
- btm_ble_vendor_cleanup();
+#if BLE_PRIVACY_SPT == TRUE
+ btm_ble_resolving_list_cleanup ();
+#endif
}
if (cmn_ble_vsc_cb.tot_scan_results_strg > 0)
BTA_DM_API_ADD_BLEKEY_EVT,
BTA_DM_API_ADD_BLEDEVICE_EVT,
BTA_DM_API_BLE_PASSKEY_REPLY_EVT,
+ BTA_DM_API_BLE_CONFIRM_REPLY_EVT,
BTA_DM_API_BLE_SEC_GRANT_EVT,
BTA_DM_API_BLE_SET_BG_CONN_TYPE,
BTA_DM_API_BLE_CONN_PARAM_EVT,
extern void bta_dm_add_blekey (tBTA_DM_MSG *p_data);
extern void bta_dm_add_ble_device (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_confirm_reply (tBTA_DM_MSG *p_data);
extern void bta_dm_security_grant (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data);
extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data);
extern void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data);
extern tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr);
-extern void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data);
-
extern void bta_dm_pm_active(BD_ADDR peer_addr);
void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding);
bta_dm_add_blekey, /* BTA_DM_API_ADD_BLEKEY_EVT */
bta_dm_add_ble_device, /* BTA_DM_API_ADD_BLEDEVICE_EVT */
bta_dm_ble_passkey_reply, /* BTA_DM_API_BLE_PASSKEY_REPLY_EVT */
+ bta_dm_ble_confirm_reply, /* BTA_DM_API_BLE_CONFIRM_REPLY_EVT */
bta_dm_security_grant,
bta_dm_ble_set_bg_conn_type,
bta_dm_ble_set_conn_params, /* BTA_DM_API_BLE_CONN_PARAM_EVT */
{
/* Take the link out of sniff and set L2C idle time to 0 */
bta_dm_pm_active(bta_hf_client_cb.scb.peer_addr);
- L2CA_SetIdleTimeoutByBdAddr(bta_hf_client_cb.scb.peer_addr, 0);
+ L2CA_SetIdleTimeoutByBdAddr(bta_hf_client_cb.scb.peer_addr, 0, BT_TRANSPORT_BR_EDR);
/* if SCO is open close SCO and wait on RFCOMM close */
if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST)
#define BTA_DM_BLE_OOB_REQ_EVT 19 /* SMP OOB request event */
#define BTA_DM_BLE_LOCAL_IR_EVT 20 /* BLE local IR event */
#define BTA_DM_BLE_LOCAL_ER_EVT 21 /* BLE local ER event */
+#define BTA_DM_BLE_NC_REQ_EVT 22 /* SMP Numeric Comparison request event */
// btla-specific ++
-#define BTA_DM_BLE_AUTH_CMPL_EVT 22 /* BLE Auth complete */
+#define BTA_DM_SP_RMT_OOB_EXT_EVT 23 /* Simple Pairing Remote OOB Extended Data request. */
+#define BTA_DM_BLE_AUTH_CMPL_EVT 24 /* BLE Auth complete */
// btla-specific --
-#define BTA_DM_DEV_UNPAIRED_EVT 23
-#define BTA_DM_HW_ERROR_EVT 24 /* BT Chip H/W error */
-#define BTA_DM_LE_FEATURES_READ 25 /* Cotroller specific LE features are read */
-#define BTA_DM_ENER_INFO_READ 26 /* Energy info read */
+#define BTA_DM_DEV_UNPAIRED_EVT 25
+#define BTA_DM_HW_ERROR_EVT 26 /* BT Chip H/W error */
+#define BTA_DM_LE_FEATURES_READ 27 /* Cotroller specific LE features are read */
+#define BTA_DM_ENER_INFO_READ 28 /* Energy info read */
typedef UINT8 tBTA_DM_SEC_EVT;
/* Structure associated with BTA_DM_ENABLE_EVT */
#define BTA_DM_AUTH_SMP_INVALID_CMD (BTA_DM_AUTH_FAIL_BASE + SMP_INVALID_CMD)
#define BTA_DM_AUTH_SMP_UNKNOWN_ERR (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_FAIL_UNKNOWN)
#define BTA_DM_AUTH_SMP_REPEATED_ATTEMPT (BTA_DM_AUTH_FAIL_BASE + SMP_REPEATED_ATTEMPTS)
+#define BTA_DM_AUTH_SMP_INVALID_PARAMETERS (BTA_DM_AUTH_FAIL_BASE + SMP_INVALID_PARAMETERS)
#define BTA_DM_AUTH_SMP_INTERNAL_ERR (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_INTERNAL_ERR)
#define BTA_DM_AUTH_SMP_UNKNOWN_IO (BTA_DM_AUTH_FAIL_BASE + SMP_UNKNOWN_IO_CAP)
#define BTA_DM_AUTH_SMP_INIT_FAIL (BTA_DM_AUTH_FAIL_BASE + SMP_INIT_FAIL)
tBTA_LE_PID_KEYS pid_key; /* peer device ID key */
tBTA_LE_LENC_KEYS lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
tBTA_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
+ tBTA_LE_PID_KEYS lid_key; /* local device ID key for the particular remote */
}tBTA_LE_KEY_VALUE;
#define BTA_BLE_LOCAL_KEY_TYPE_ID 1
{
BD_ADDR bd_addr; /* peer address */
tBTM_LE_KEY_TYPE key_type;
- tBTM_LE_KEY_VALUE key_value;
+ tBTM_LE_KEY_VALUE *p_key_value;
}tBTA_DM_BLE_KEY;
/* Structure associated with BTA_DM_AUTH_CMPL_EVT */
UINT8 key_type; /* The type of Link Key */
BOOLEAN success; /* TRUE of authentication succeeded, FALSE if failed. */
UINT8 fail_reason; /* The HCI reason/error code for when success=FALSE */
-
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+ tBLE_ADDR_TYPE addr_type; /* peer device address type */
+#endif
} tBTA_DM_AUTH_CMPL;
UINT8 level_flags; /* indicates individual flags */
} tBTA_DM_BUSY_LEVEL;
-#define BTA_IO_CAP_OUT BTM_IO_CAP_OUT /* DisplayOnly */
-#define BTA_IO_CAP_IO BTM_IO_CAP_IO /* DisplayYesNo */
-#define BTA_IO_CAP_IN BTM_IO_CAP_IN /* KeyboardOnly */
-#define BTA_IO_CAP_NONE BTM_IO_CAP_NONE /* NoInputNoOutput */
+#define BTA_IO_CAP_OUT BTM_IO_CAP_OUT /* 0 DisplayOnly */
+#define BTA_IO_CAP_IO BTM_IO_CAP_IO /* 1 DisplayYesNo */
+#define BTA_IO_CAP_IN BTM_IO_CAP_IN /* 2 KeyboardOnly */
+#define BTA_IO_CAP_NONE BTM_IO_CAP_NONE /* 3 NoInputNoOutput */
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+#define BTA_IO_CAP_KBDISP BTM_IO_CAP_KBDISP /* 4 Keyboard display */
+#endif
typedef tBTM_IO_CAP tBTA_IO_CAP;
#define BTA_AUTH_SP_NO BTM_AUTH_SP_NO /* 0 MITM Protection Not Required - Single Profile/non-bonding
#define BTA_LE_AUTH_NO_BOND BTM_LE_AUTH_REQ_NO_BOND /* 0*/
#define BTA_LE_AUTH_BOND BTM_LE_AUTH_REQ_BOND /* 1 << 0 */
#define BTA_LE_AUTH_REQ_MITM BTM_LE_AUTH_REQ_MITM /* 1 << 2 */
+
+#define BTA_LE_AUTH_REQ_SC_ONLY BTM_LE_AUTH_REQ_SC_ONLY /* 1 << 3 */
+#define BTA_LE_AUTH_REQ_SC_BOND BTM_LE_AUTH_REQ_SC_BOND /* 1001 */
+#define BTA_LE_AUTH_REQ_SC_MITM BTM_LE_AUTH_REQ_SC_MITM /* 1100 */
+#define BTA_LE_AUTH_REQ_SC_MITM_BOND BTM_LE_AUTH_REQ_SC_MITM_BOND /* 1101 */
typedef tBTM_LE_AUTH_REQ tBTA_LE_AUTH_REQ; /* combination of the above bit pattern */
#define BTA_OOB_NONE BTM_OOB_NONE
/*******************************************************************************
**
+** Function BTA_DmBleConfirmReply
+**
+** Description Send BLE SMP SC user confirmation reply.
+**
+** Parameters: bd_addr - BD address of the peer
+** accept - numbers to compare are the same or different.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void BTA_DmBleConfirmReply(BD_ADDR bd_addr, BOOLEAN accept);
+
+/*******************************************************************************
+**
** Function BTA_DmAddBleDevice
**
** Description Add a BLE device. This function will be normally called
** Description This function is called to set scan parameters used in
** BLE connection request
**
-** Parameters: bd_addr - BD address of the peripheral
-** scan_interval - scan interval
+** Parameters: scan_interval - scan interval
** scan_window - scan window
**
** Returns void
btif_dm_ble_lenc_keys_t lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
BOOLEAN is_lcsrk_key_rcvd;
btif_dm_ble_lcsrk_keys_t lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
+ BOOLEAN is_lidk_key_rcvd; /* local identity key received */
} btif_dm_ble_cb_t;
#define BTIF_DM_LE_KEY_PENC BTA_LE_KEY_PENC
}
bool btif_config_set_bin(const char *section, const char *key, const uint8_t *value, size_t length) {
- static const char *lookup = "0123456789abcdef";
+ const char *lookup = "0123456789abcdef";
assert(config != NULL);
assert(section != NULL);
assert(key != NULL);
- assert(value != NULL);
+
+ if (length > 0)
+ assert(value != NULL);
char *str = (char *)calloc(length * 2 + 1, 1);
if (!str)
for (size_t i = 0; i < length; ++i) {
str[(i * 2) + 0] = lookup[(value[i] >> 4) & 0x0F];
- str[(i * 2) + 1] = lookup[(value[i] >> 0) & 0x0F];
+ str[(i * 2) + 1] = lookup[value[i] & 0x0F];
}
pthread_mutex_lock(&lock);
static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF *p_ssp_key_notif);
static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl);
static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req);
+static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req) ;
#endif
static void bte_scan_filt_param_cfg_evt(UINT8 action_type,
case BTA_LE_KEY_PENC:
BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PENC");
pairing_cb.ble.is_penc_key_rcvd = TRUE;
- memcpy(pairing_cb.ble.penc_key.ltk,p_data->ble_key.key_value.penc_key.ltk, 16);
- memcpy(pairing_cb.ble.penc_key.rand, p_data->ble_key.key_value.penc_key.rand,8);
- pairing_cb.ble.penc_key.ediv = p_data->ble_key.key_value.penc_key.ediv;
- pairing_cb.ble.penc_key.sec_level = p_data->ble_key.key_value.penc_key.sec_level;
+ memcpy(pairing_cb.ble.penc_key.ltk,
+ p_data->ble_key.p_key_value->penc_key.ltk, 16);
+ memcpy(pairing_cb.ble.penc_key.rand,
+ p_data->ble_key.p_key_value->penc_key.rand,8);
+ pairing_cb.ble.penc_key.ediv = p_data->ble_key.p_key_value->penc_key.ediv;
+ pairing_cb.ble.penc_key.sec_level =
+ p_data->ble_key.p_key_value->penc_key.sec_level;
for (i=0; i<16; i++)
{
- BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.ltk[%d]=0x%02x",i,pairing_cb.ble.penc_key.ltk[i]);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.ltk[%d]=0x%02x",
+ i,pairing_cb.ble.penc_key.ltk[i]);
}
for (i=0; i<8; i++)
{
- BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.rand[%d]=0x%02x",i,pairing_cb.ble.penc_key.rand[i]);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.rand[%d]=0x%02x",
+ i,pairing_cb.ble.penc_key.rand[i]);
}
- BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.ediv=0x%04x",pairing_cb.ble.penc_key.ediv);
- BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.sec_level=0x%02x",pairing_cb.ble.penc_key.sec_level);
- BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.key_size=0x%02x",pairing_cb.ble.penc_key.key_size);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.ediv=0x%04x",
+ pairing_cb.ble.penc_key.ediv);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.sec_level=0x%02x",
+ pairing_cb.ble.penc_key.sec_level);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.key_size=0x%02x",
+ pairing_cb.ble.penc_key.key_size);
break;
case BTA_LE_KEY_PID:
BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PID");
pairing_cb.ble.is_pid_key_rcvd = TRUE;
- pairing_cb.ble.pid_key.addr_type = p_data->ble_key.key_value.pid_key.addr_type;
- memcpy(pairing_cb.ble.pid_key.irk, p_data->ble_key.key_value.pid_key.irk, 16);
+ pairing_cb.ble.pid_key.addr_type =
+ p_data->ble_key.p_key_value->pid_key.addr_type;
+ memcpy(pairing_cb.ble.pid_key.irk,
+ p_data->ble_key.p_key_value->pid_key.irk, 16);
memcpy(pairing_cb.ble.pid_key.static_addr,
- p_data->ble_key.key_value.pid_key.static_addr,BD_ADDR_LEN);
+ p_data->ble_key.p_key_value->pid_key.static_addr,BD_ADDR_LEN);
for (i=0; i<16; i++)
{
BTIF_TRACE_DEBUG("pairing_cb.ble.pid_key.irk[%d]=0x%02x"
case BTA_LE_KEY_PCSRK:
BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PCSRK");
pairing_cb.ble.is_pcsrk_key_rcvd = TRUE;
- pairing_cb.ble.pcsrk_key.counter = p_data->ble_key.key_value.pcsrk_key.counter;
- pairing_cb.ble.pcsrk_key.sec_level = p_data->ble_key.key_value.pcsrk_key.sec_level;
- memcpy(pairing_cb.ble.pcsrk_key.csrk,p_data->ble_key.key_value.pcsrk_key.csrk,16);
+ pairing_cb.ble.pcsrk_key.counter =
+ p_data->ble_key.p_key_value->pcsrk_key.counter;
+ pairing_cb.ble.pcsrk_key.sec_level =
+ p_data->ble_key.p_key_value->pcsrk_key.sec_level;
+ memcpy(pairing_cb.ble.pcsrk_key.csrk,
+ p_data->ble_key.p_key_value->pcsrk_key.csrk,16);
for (i=0; i<16; i++)
{
- BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.csrk[%d]=0x%02x",i,pairing_cb.ble.pcsrk_key.csrk[i]);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.csrk[%d]=0x%02x",
+ i,pairing_cb.ble.pcsrk_key.csrk[i]);
}
- BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.counter=0x%08x",pairing_cb.ble.pcsrk_key.counter);
- BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.sec_level=0x%02x",pairing_cb.ble.pcsrk_key.sec_level);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.counter=0x%08x",
+ pairing_cb.ble.pcsrk_key.counter);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.sec_level=0x%02x",
+ pairing_cb.ble.pcsrk_key.sec_level);
break;
case BTA_LE_KEY_LENC:
BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LENC");
pairing_cb.ble.is_lenc_key_rcvd = TRUE;
- pairing_cb.ble.lenc_key.div = p_data->ble_key.key_value.lenc_key.div;
- pairing_cb.ble.lenc_key.key_size = p_data->ble_key.key_value.lenc_key.key_size;
- pairing_cb.ble.lenc_key.sec_level = p_data->ble_key.key_value.lenc_key.sec_level;
-
- BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.div=0x%04x",pairing_cb.ble.lenc_key.div);
- BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.key_size=0x%02x",pairing_cb.ble.lenc_key.key_size);
- BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.sec_level=0x%02x",pairing_cb.ble.lenc_key.sec_level);
+ pairing_cb.ble.lenc_key.div = p_data->ble_key.p_key_value->lenc_key.div;
+ pairing_cb.ble.lenc_key.key_size =
+ p_data->ble_key.p_key_value->lenc_key.key_size;
+ pairing_cb.ble.lenc_key.sec_level =
+ p_data->ble_key.p_key_value->lenc_key.sec_level;
+
+ BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.div=0x%04x",
+ pairing_cb.ble.lenc_key.div);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.key_size=0x%02x",
+ pairing_cb.ble.lenc_key.key_size);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.sec_level=0x%02x",
+ pairing_cb.ble.lenc_key.sec_level);
break;
case BTA_LE_KEY_LCSRK:
BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LCSRK");
pairing_cb.ble.is_lcsrk_key_rcvd = TRUE;
- pairing_cb.ble.lcsrk_key.counter = p_data->ble_key.key_value.lcsrk_key.counter;
- pairing_cb.ble.lcsrk_key.div = p_data->ble_key.key_value.lcsrk_key.div;
- pairing_cb.ble.lcsrk_key.sec_level = p_data->ble_key.key_value.lcsrk_key.sec_level;
+ pairing_cb.ble.lcsrk_key.counter =
+ p_data->ble_key.p_key_value->lcsrk_key.counter;
+ pairing_cb.ble.lcsrk_key.div =
+ p_data->ble_key.p_key_value->lcsrk_key.div;
+ pairing_cb.ble.lcsrk_key.sec_level =
+ p_data->ble_key.p_key_value->lcsrk_key.sec_level;
+
+ BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.div=0x%04x",
+ pairing_cb.ble.lcsrk_key.div);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.counter=0x%08x",
+ pairing_cb.ble.lcsrk_key.counter);
+ BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.sec_level=0x%02x",
+ pairing_cb.ble.lcsrk_key.sec_level);
- BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.div=0x%04x",pairing_cb.ble.lcsrk_key.div);
- BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.counter=0x%08x",pairing_cb.ble.lcsrk_key.counter);
- BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.sec_level=0x%02x",pairing_cb.ble.lcsrk_key.sec_level);
+ break;
+ case BTA_LE_KEY_LID:
+ BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LID");
+ pairing_cb.ble.is_lidk_key_rcvd = TRUE;
break;
default:
BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
btif_dm_ble_passkey_req_evt(&p_data->pin_req);
break;
+ case BTA_DM_BLE_NC_REQ_EVT:
+ BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
+ btif_dm_ble_key_nc_req_evt(&p_data->key_notif);
+ break;
case BTA_DM_BLE_OOB_REQ_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_OOB_REQ_EVT. ");
break;
case BTA_DM_BLE_LOCAL_IR_EVT:
BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. ");
ble_local_key_cb.is_id_keys_rcvd = TRUE;
- memcpy(&ble_local_key_cb.id_keys.irk[0], &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16));
- memcpy(&ble_local_key_cb.id_keys.ir[0], &p_data->ble_id_keys.ir[0], sizeof(BT_OCTET16));
- memcpy(&ble_local_key_cb.id_keys.dhk[0], &p_data->ble_id_keys.dhk[0], sizeof(BT_OCTET16));
+ memcpy(&ble_local_key_cb.id_keys.irk[0],
+ &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16));
+ memcpy(&ble_local_key_cb.id_keys.ir[0],
+ &p_data->ble_id_keys.ir[0], sizeof(BT_OCTET16));
+ memcpy(&ble_local_key_cb.id_keys.dhk[0],
+ &p_data->ble_id_keys.dhk[0], sizeof(BT_OCTET16));
btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.irk[0],
BTIF_DM_LE_LOCAL_KEY_IR,
BT_OCTET16_LEN);
break;
case BTA_DM_BLE_AUTH_CMPL_EVT:
- BTIF_TRACE_DEBUG("BTA_DM_BLE_KEY_EVT. ");
+ BTIF_TRACE_DEBUG("BTA_DM_BLE_AUTH_CMPL_EVT. ");
btif_dm_ble_auth_cmpl_evt(&p_data->auth_cmpl);
break;
sizeof(btif_dm_ble_lcsrk_keys_t));
}
+ if (pairing_cb.ble.is_lidk_key_rcvd)
+ {
+ btif_storage_add_ble_bonding_key(&bd_addr,
+ NULL,
+ BTIF_DM_LE_KEY_LID,
+ 0);
+ }
+
}
HAL_CBACK(bt_hal_cbacks, pin_request_cb,
&bd_addr, &bd_name, cod);
}
+static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req)
+{
+ /* TODO implement key notification for numeric comparison */
+ BTIF_TRACE_DEBUG("%s", __FUNCTION__);
+ /* Remote name update */
+ btif_update_remote_properties(p_notif_req->bd_addr , p_notif_req->bd_name,
+ NULL, BT_DEVICE_TYPE_BLE);
+
+ bt_bdaddr_t bd_addr;
+ bdcpy(bd_addr.address, p_notif_req->bd_addr);
+
+ bt_bdname_t bd_name;
+ memcpy(bd_name.name, p_notif_req->bd_name, BD_NAME_LEN);
+
+ bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+ pairing_cb.is_ssp = FALSE;
+
+ HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, &bd_name,
+ COD_UNCLASSIFIED, BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
+ p_notif_req->passkey);
+}
void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name,
tBT_DEVICE_TYPE dev_type)
case BTIF_DM_LE_KEY_LCSRK:
name = "LE_KEY_LCSRK";
break;
+ case BTIF_DM_LE_KEY_LID:
+ name = "LE_KEY_LID";
+ break;
default:
return BT_STATUS_FAIL;
}
case BTIF_DM_LE_KEY_LCSRK:
name = "LE_KEY_LCSRK";
break;
+ case BTIF_DM_LE_KEY_LID:
+ name = "LE_KEY_LID";
default:
return BT_STATUS_FAIL;
}
key_found = TRUE;
}
+ if (btif_storage_get_ble_bonding_key(&bd_addr, BTIF_DM_LE_KEY_LID, buf,
+ sizeof(btif_dm_ble_pid_keys_t))== BT_STATUS_SUCCESS)
+ {
+ if(add)
+ {
+ if (!is_device_added)
+ {
+ BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+ is_device_added = TRUE;
+ }
+ p = (tBTA_LE_KEY_VALUE *)buf;
+ for (i=0; i<BD_ADDR_LEN; i++)
+ {
+ BTIF_TRACE_DEBUG("p->pid_key.static_addr[%d]=%02x"
+ ,i,p->pid_key.static_addr[i]);
+ }
+
+ BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LID);
+ }
+ key_found = TRUE;
+ }
+
memset(buf, 0, sizeof(buf));
if (btif_storage_get_ble_bonding_key(&bd_addr,
BTIF_DM_LE_KEY_PCSRK,
const uint8_t *(*get_ble_supported_states)(void);
bool (*supports_simple_pairing)(void);
+ bool (*supports_secure_connections)(void);
bool (*supports_simultaneous_le_bredr)(void);
bool (*supports_reading_remote_extended_features)(void);
bool (*supports_interlaced_inquiry_scan)(void);
bool (*supports_ble)(void);
bool (*supports_ble_connection_parameters_request)(void);
+ bool (*supports_ble_privacy)(void);
// Get the cached acl data sizes for the controller.
uint16_t (*get_acl_data_size_classic)(void);
// Get the number of acl packets the controller can buffer.
uint16_t (*get_acl_buffer_count_classic)(void);
uint8_t (*get_acl_buffer_count_ble)(void);
+
+ uint8_t (*get_ble_resolving_list_max_size)(void);
+ void (*set_ble_resolving_list_max_size)(int resolving_list_max_size);
} controller_t;
const controller_t *controller_get_interface();
static uint8_t acl_buffer_count_ble;
static uint8_t ble_white_list_size;
+static uint8_t ble_resolving_list_max_size;
static uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE];
static bt_device_features_t features_ble;
static bool readable;
static bool ble_supported;
static bool simple_pairing_supported;
+static bool secure_connections_supported;
#define AWAIT_COMMAND(command) future_await(hci->transmit_command_futured(command))
packet_parser->parse_generic_command_complete(response);
}
+ 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)
if (HCI_LE_SPT_SUPPORTED(features_classic[0].as_array)) {
uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0;
&features_ble
);
+ if (HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array)) {
+ response = AWAIT_COMMAND(packet_factory->make_ble_read_resolving_list_size());
+ packet_parser->parse_ble_read_resolving_list_size_response(
+ response,
+ &ble_resolving_list_max_size);
+ }
+
// Set the ble event mask next
response = AWAIT_COMMAND(packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK));
packet_parser->parse_generic_command_complete(response);
return simple_pairing_supported;
}
+static bool supports_secure_connections(void) {
+ assert(readable);
+ return secure_connections_supported;
+}
+
static bool supports_simultaneous_le_bredr(void) {
assert(readable);
return HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array);
return ble_supported;
}
+static bool supports_ble_privacy(void) {
+ assert(readable);
+ assert(ble_supported);
+ return HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array);
+}
+
static bool supports_ble_connection_parameters_request(void) {
assert(readable);
assert(ble_supported);
return acl_buffer_count_ble;
}
+static uint8_t get_ble_resolving_list_max_size(void) {
+ assert(readable);
+ assert(ble_supported);
+ return ble_resolving_list_max_size;
+}
+
+static void set_ble_resolving_list_max_size(int resolving_list_max_size) {
+ assert(readable);
+ assert(ble_supported);
+ ble_resolving_list_max_size = resolving_list_max_size;
+}
+
static const controller_t interface = {
get_is_ready,
get_ble_supported_states,
supports_simple_pairing,
+ supports_secure_connections,
supports_simultaneous_le_bredr,
supports_reading_remote_extended_features,
supports_interlaced_inquiry_scan,
supports_ble,
supports_ble_connection_parameters_request,
+ supports_ble_privacy,
get_acl_data_size_classic,
get_acl_data_size_ble,
get_acl_packet_size_ble,
get_acl_buffer_count_classic,
- get_acl_buffer_count_ble
+ get_acl_buffer_count_ble,
+
+ get_ble_resolving_list_max_size,
+ set_ble_resolving_list_max_size
};
const controller_t *controller_get_interface() {
BT_HDR *(*make_read_local_supported_commands)(void);
BT_HDR *(*make_read_local_extended_features)(uint8_t page_number);
BT_HDR *(*make_write_simple_pairing_mode)(uint8_t mode);
+ BT_HDR *(*make_write_secure_connections_host_support)(uint8_t mode);
BT_HDR *(*make_set_event_mask)(const bt_event_mask_t *event_mask);
BT_HDR *(*make_ble_write_host_support)(uint8_t supported_host, uint8_t simultaneous_host);
BT_HDR *(*make_ble_read_white_list_size)(void);
BT_HDR *(*make_ble_read_buffer_size)(void);
BT_HDR *(*make_ble_read_supported_states)(void);
BT_HDR *(*make_ble_read_local_supported_features)(void);
+ BT_HDR *(*make_ble_read_resolving_list_size)(void);
BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask);
} hci_packet_factory_t;
BT_HDR *response,
bt_device_features_t *supported_features
);
+
+ void (*parse_ble_read_resolving_list_size_response) (
+ BT_HDR *response,
+ uint8_t *resolving_list_size_ptr
+ );
+
} hci_packet_parser_t;
const hci_packet_parser_t *hci_packet_parser_get_interface();
return packet;
}
+static BT_HDR *make_write_secure_connections_host_support(uint8_t mode) {
+ uint8_t *stream;
+ const uint8_t parameter_size = 1;
+ BT_HDR *packet = make_command(HCI_WRITE_SECURE_CONNS_SUPPORT, parameter_size, &stream);
+
+ UINT8_TO_STREAM(stream, mode);
+ return packet;
+}
+
static BT_HDR *make_set_event_mask(const bt_event_mask_t *event_mask) {
uint8_t *stream;
uint8_t parameter_size = sizeof(bt_event_mask_t);
return make_command_no_params(HCI_BLE_READ_LOCAL_SPT_FEAT);
}
+static BT_HDR *make_ble_read_resolving_list_size(void) {
+ return make_command_no_params(HCI_BLE_READ_RESOLVING_LIST_SIZE);
+}
+
static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask) {
uint8_t *stream;
uint8_t parameter_size = sizeof(bt_event_mask_t);
make_read_local_supported_commands,
make_read_local_extended_features,
make_write_simple_pairing_mode,
+ make_write_secure_connections_host_support,
make_set_event_mask,
make_ble_write_host_support,
make_ble_read_white_list_size,
make_ble_read_buffer_size,
make_ble_read_supported_states,
make_ble_read_local_supported_features,
+ make_ble_read_resolving_list_size,
make_ble_set_event_mask
};
buffer_allocator->free(response);
}
+static void parse_ble_read_resolving_list_size_response(
+ BT_HDR *response,
+ uint8_t *resolving_list_size_ptr) {
+
+ uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */);
+ STREAM_TO_UINT8(*resolving_list_size_ptr, stream);
+
+ buffer_allocator->free(response);
+}
+
// Internal functions
static uint8_t *read_command_complete_header(
parse_ble_read_white_list_size_response,
parse_ble_read_buffer_size_response,
parse_ble_read_supported_states_response,
- parse_ble_read_local_supported_features_response
+ parse_ble_read_local_supported_features_response,
+ parse_ble_read_resolving_list_size_response
};
const hci_packet_parser_t *hci_packet_parser_get_interface() {
/* First fixed channel supported */
#ifndef L2CAP_FIRST_FIXED_CHNL
-#define L2CAP_FIRST_FIXED_CHNL 3
+#define L2CAP_FIRST_FIXED_CHNL 4
#endif
#ifndef L2CAP_LAST_FIXED_CHNL
#define SMP_MIN_ENC_KEY_SIZE 7
#endif
-/* Used for conformance testing ONLY */
-#ifndef SMP_CONFORMANCE_TESTING
-#define SMP_CONFORMANCE_TESTING FALSE
+/* minimum link timeout after SMP pairing is done, leave room for key exchange
+ and racing condition for the following service connection.
+ Prefer greater than 0 second, and no less than default inactivity link idle
+ timer(L2CAP_LINK_INACTIVITY_TOUT) in l2cap) */
+#ifndef SMP_LINK_TOUT_MIN
+#if (L2CAP_LINK_INACTIVITY_TOUT > 0)
+#define SMP_LINK_TOUT_MIN L2CAP_LINK_INACTIVITY_TOUT
+#else
+#define SMP_LINK_TOUT_MIN 2
+#endif
#endif
-
/******************************************************************************
**
** SDP
./btm/btm_ble_multi_adv.c \
./btm/btm_ble_batchscan.c \
./btm/btm_ble_cont_energy.c \
+ ./btm/btm_ble_privacy.c \
./btm/btm_acl.c \
./btm/btm_sco.c \
./btm/btm_pm.c \
./smp/smp_keys.c \
./smp/smp_api.c \
./smp/aes.c \
+ ./smp/smp_br_main.c\
+ ./smp/p_256_curvepara.c \
+ ./smp/p_256_ecc_pp.c \
+ ./smp/p_256_multprecision.c \
./avdt/avdt_ccb.c \
./avdt/avdt_scb_act.c \
./avdt/avdt_msg.c \
./gap/gap_api.c \
./gap/gap_ble.c \
./gap/gap_conn.c \
- ./gap/gap_utils.c \
- ../vnd/ble/vendor_ble.c
+ ./gap/gap_utils.c
LOCAL_MODULE := libbt-brcm_stack
LOCAL_MODULE_TAGS := optional
p->hci_handle = hci_handle;
p->link_role = link_role;
p->link_up_issued = FALSE;
+ memcpy (p->remote_addr, bda, BD_ADDR_LEN);
#if BLE_INCLUDED == TRUE
p->transport = transport;
- if (transport == BT_TRANSPORT_LE)
- {
#if BLE_PRIVACY_SPT == TRUE
- if (btm_cb.ble_ctr_cb.privacy)
- {
- p->conn_addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
- memcpy(p->conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
- }
- else
+ if (transport == BT_TRANSPORT_LE)
+ btm_ble_refresh_local_resolvable_private_addr(bda,
+ btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr);
#endif
- {
- p->conn_addr_type = BLE_ADDR_PUBLIC;
- memcpy(p->conn_addr, controller_get_interface()->get_address()->address, BD_ADDR_LEN);
- }
- }
#endif
p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
btm_pm_sm_alloc(xx);
- memcpy (p->remote_addr, bda, BD_ADDR_LEN);
if (dc)
memcpy (p->remote_dc, dc, DEV_CLASS_LEN);
#include "l2c_int.h"
#include "gap_api.h"
#include "bt_utils.h"
-
-#include "vendor_ble.h"
+#include "device/include/controller.h"
#define LOG_TAG "bt_btm_ble"
#include "osi/include/log.h"
#if SMP_INCLUDED == TRUE
-extern BOOLEAN AES_CMAC ( BT_OCTET16 key, UINT8 *input, UINT16 length, UINT16 tlen, UINT8 *p_signature);
+extern BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
+ UINT16 tlen, UINT8 *p_signature);
extern void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable);
extern BOOLEAN smp_proc_ltk_request(BD_ADDR bda);
#endif
if (!p_dev_rec || !p_le_key ||
(key_type != BTM_LE_KEY_PENC && key_type != BTM_LE_KEY_PID &&
key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC &&
- key_type != BTM_LE_KEY_LCSRK))
+ key_type != BTM_LE_KEY_LCSRK && key_type != BTM_LE_KEY_LID))
{
BTM_TRACE_WARNING ("BTM_SecAddBleKey() Wrong Type, or No Device record \
for bdaddr: %08x%04x, Type: %d",
(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
(bd_addr[4]<<8)+bd_addr[5], key_type);
- if (key_type == BTM_LE_KEY_PENC || key_type == BTM_LE_KEY_PID ||
- key_type == BTM_LE_KEY_PCSRK || key_type == BTM_LE_KEY_LENC ||
- key_type == BTM_LE_KEY_LCSRK)
- {
- btm_sec_save_le_key (bd_addr, key_type, p_le_key, FALSE);
- }
+ btm_sec_save_le_key (bd_addr, key_type, p_le_key, FALSE);
+
+#if (BLE_PRIVACY_SPT == TRUE)
+ if (key_type == BTM_LE_KEY_PID || key_type == BTM_LE_KEY_LID)
+ btm_ble_resolving_list_load_dev (p_dev_rec);
+#endif
#endif
void BTM_BleLoadLocalKeys(UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key)
{
tBTM_DEVCB *p_devcb = &btm_cb.devcb;
- BTM_TRACE_DEBUG ("BTM_BleLoadLocalKeys");
+ BTM_TRACE_DEBUG ("%s", __func__);
if (p_key != NULL)
{
switch (key_type)
break;
case BTM_BLE_KEY_TYPE_ER:
- memcpy(p_devcb->er, p_key->er, sizeof(BT_OCTET16));
+ memcpy(p_devcb->ble_encryption_key_value, p_key->er, sizeof(BT_OCTET16));
break;
default:
** root.
**
** Returns void
-** the local device ER is copied into er
+** the local device ER is copied into ble_encr_key_value
**
*******************************************************************************/
-void BTM_GetDeviceEncRoot (BT_OCTET16 er)
+void BTM_GetDeviceEncRoot (BT_OCTET16 ble_encr_key_value)
{
- BTM_TRACE_DEBUG ("BTM_GetDeviceEncRoot");
-
- memcpy (er, btm_cb.devcb.er, BT_OCTET16_LEN);
+ BTM_TRACE_DEBUG ("%s", __func__);
+ memcpy (ble_encr_key_value, btm_cb.devcb.ble_encryption_key_value, BT_OCTET16_LEN);
}
/*******************************************************************************
return;
}
- p_dev_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED;
+ p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
BTM_TRACE_DEBUG ("BTM_BlePasskeyReply");
SMP_PasskeyReply(bd_addr, res_smp, passkey);
#endif
/*******************************************************************************
**
+** Function BTM_BleConfirmReply
+**
+** Description This function is called after Security Manager submitted
+** numeric comparison request to the application.
+**
+** Parameters: bd_addr - Address of the device with which numeric
+** comparison was requested
+** res - comparison result BTM_SUCCESS if success
+**
+*******************************************************************************/
+void BTM_BleConfirmReply (BD_ADDR bd_addr, UINT8 res)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+ tSMP_STATUS res_smp = (res == BTM_SUCCESS) ? SMP_SUCCESS : SMP_PASSKEY_ENTRY_FAIL;
+
+ if (p_dev_rec == NULL)
+ {
+ BTM_TRACE_ERROR("Passkey reply to Unknown device");
+ return;
+ }
+
+ p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
+ BTM_TRACE_DEBUG ("%s", __func__);
+ SMP_ConfirmReply(bd_addr, res_smp);
+}
+
+/*******************************************************************************
+**
** Function BTM_BleOobDataReply
**
** Description This function is called to provide the OOB data for
return;
}
- p_dev_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED;
+ p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
SMP_OobDataReply(bd_addr, res_smp, len, p_data);
#endif
}
if (BTM_BLE_VALID_PRAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) &&
BTM_BLE_VALID_PRAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX))
{
- btu_stop_timer(&p_ble_cb->scan_param_idle_timer);
-
if (p_ble_cb->scan_int != scan_interval)
{
p_ble_cb->scan_int = scan_interval;
bd_addr[2],bd_addr[3],
bd_addr[4],bd_addr[5]);
- if ((p_rec = btm_find_dev (bd_addr)) != NULL && p_keys)
+ if ((p_rec = btm_find_dev (bd_addr)) != NULL && (p_keys || key_type== BTM_LE_KEY_LID))
{
switch (key_type)
{
case BTM_LE_KEY_PENC:
- memcpy(p_rec->ble.keys.ltk, p_keys->penc_key.ltk, BT_OCTET16_LEN);
+ memcpy(p_rec->ble.keys.pltk, p_keys->penc_key.ltk, BT_OCTET16_LEN);
memcpy(p_rec->ble.keys.rand, p_keys->penc_key.rand, BT_OCTET8_LEN);
p_rec->ble.keys.sec_level = p_keys->penc_key.sec_level;
p_rec->ble.keys.ediv = p_keys->penc_key.ediv;
break;
case BTM_LE_KEY_PCSRK:
- memcpy(p_rec->ble.keys.csrk, p_keys->pcsrk_key.csrk, BT_OCTET16_LEN);
+ memcpy(p_rec->ble.keys.pcsrk, p_keys->pcsrk_key.csrk, BT_OCTET16_LEN);
p_rec->ble.keys.srk_sec_level = p_keys->pcsrk_key.sec_level;
p_rec->ble.keys.counter = p_keys->pcsrk_key.counter;
p_rec->ble.key_type |= BTM_LE_KEY_PCSRK;
break;
case BTM_LE_KEY_LENC:
+ memcpy(p_rec->ble.keys.lltk, p_keys->lenc_key.ltk, BT_OCTET16_LEN);
p_rec->ble.keys.div = p_keys->lenc_key.div; /* update DIV */
p_rec->ble.keys.sec_level = p_keys->lenc_key.sec_level;
p_rec->ble.keys.key_size = p_keys->lenc_key.key_size;
break;
case BTM_LE_KEY_LCSRK:/* local CSRK has been delivered */
+ memcpy (p_rec->ble.keys.lcsrk, p_keys->lcsrk_key.csrk, BT_OCTET16_LEN);
p_rec->ble.keys.div = p_keys->lcsrk_key.div; /* update DIV */
p_rec->ble.keys.local_csrk_sec_level = p_keys->lcsrk_key.sec_level;
p_rec->ble.keys.local_counter = p_keys->lcsrk_key.counter;
p_rec->ble.keys.local_counter );
break;
+ case BTM_LE_KEY_LID:
+ p_rec->ble.key_type |= BTM_LE_KEY_LID;
+ break;
default:
BTM_TRACE_WARNING("btm_sec_save_le_key (Bad key_type 0x%02x)", key_type);
return;
{
cb_data.key.p_key_value = p_keys;
cb_data.key.key_type = key_type;
+
(*btm_cb.api.p_le_callback) (BTM_LE_KEY_EVT, bd_addr, &cb_data);
}
return;
else
{
req_sec_level = BTM_LE_SEC_UNAUTHENTICATE;
- if ((auth_req == (BTM_LE_AUTH_REQ_BOND|BTM_LE_AUTH_REQ_MITM)) ||
- (auth_req == (BTM_LE_AUTH_REQ_MITM)) )
+ if (auth_req & BTM_LE_AUTH_REQ_MITM)
{
req_sec_level = BTM_LE_SEC_AUTHENTICATED;
}
/* currently encrpted */
if (p_dev_rec->sec_flags & BTM_SEC_LE_ENCRYPTED)
{
- if (p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED)
+ if (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED)
cur_sec_level = BTM_LE_SEC_AUTHENTICATED;
else
cur_sec_level = BTM_LE_SEC_UNAUTHENTICATE;
tBTM_STATUS cmd = BTM_NO_RESOURCES;
tBTM_BLE_SEC_ACT sec_act = *(tBTM_BLE_SEC_ACT *)p_ref_data ;
tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
+ tBTM_BLE_SEC_REQ_ACT sec_req_act;
+ tBTM_LE_AUTH_REQ auth_req;
if (p_rec == NULL)
{
case BTM_BLE_SEC_ENCRYPT:
if (link_role == BTM_ROLE_MASTER)
{
- if(p_rec->sec_state == BTM_SEC_STATE_ENCRYPTING) {
- BTM_TRACE_DEBUG ("State is already encrypting::");
- cmd = BTM_CMD_STARTED;
- }
- else {
/* start link layer encryption using the security info stored */
- if (btm_ble_start_encrypt(bd_addr, FALSE, NULL))
- {
- p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
- cmd = BTM_CMD_STARTED;
- }
- }
+ cmd = btm_ble_start_encrypt(bd_addr, FALSE, NULL);
break;
}
/* if salve role then fall through to call SMP_Pair below which will send a
sec_request to request the master to encrypt the link */
case BTM_BLE_SEC_ENCRYPT_NO_MITM:
case BTM_BLE_SEC_ENCRYPT_MITM:
+ if (link_role == BTM_ROLE_MASTER)
+ {
+ auth_req = (sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM)
+ ? SMP_AUTH_GEN_BOND : (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT);
+ btm_ble_link_sec_check (bd_addr, auth_req, &sec_req_act);
+
+ if (sec_req_act == BTM_BLE_SEC_REQ_ACT_ENCRYPT)
+ {
+ cmd = btm_ble_start_encrypt(bd_addr, FALSE, NULL);
+ break;
+ }
+ }
if (SMP_Pair(bd_addr) == SMP_STARTED)
{
else if (p_rec->ble.key_type & BTM_LE_KEY_PENC)
{
if (btsnd_hcic_ble_start_enc(p_rec->ble_hci_handle, p_rec->ble.keys.rand,
- p_rec->ble.keys.ediv, p_rec->ble.keys.ltk))
+ p_rec->ble.keys.ediv, p_rec->ble.keys.pltk))
rt = BTM_CMD_STARTED;
}
else
{
BTM_TRACE_DEBUG ("LTK request OK");
/* calculating LTK , LTK = E er(div) */
- SMP_Encrypt(p_cb->devcb.er, BT_OCTET16_LEN, (UINT8 *)&div, 2, &output);
+ SMP_Encrypt(p_cb->devcb.ble_encryption_key_value, BT_OCTET16_LEN, (UINT8 *)&div, 2, &output);
btm_enc_proc_ltk(&output);
}
else
}
else /* calculate LTK using peer device */
{
- /* generate Y= Encrypt(DHK, Rand) received from encrypt request */
- SMP_Encrypt(p_cb->devcb.id_keys.dhk, BT_OCTET16_LEN, p_cb->enc_rand,
- BT_OCTET8_LEN, &output);
- btm_enc_proc_slave_y(&output);
+ if (p_rec->ble.key_type & BTM_LE_KEY_LENC)
+ btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, p_rec->ble.keys.lltk);
+ else
+ btsnd_hcic_ble_ltk_req_neg_reply(btm_cb.enc_handle);
}
}
if ((p_data->io_cap == BTM_IO_CAP_NONE) && p_data->oob_data == SMP_OOB_NONE)
p_data->auth_req &= ~BTM_LE_AUTH_REQ_MITM;
- BTM_TRACE_DEBUG ("btm_ble_io_capabilities_req 6: IO_CAP:%d oob_data:%d auth_req:%d",
+ if (!(p_data->auth_req & SMP_SC_SUPPORT_BIT))
+ {
+ /* if Secure Connections are not supported then remove LK derivation,
+ ** and keypress notifications.
+ */
+ BTM_TRACE_DEBUG("%s-SC not supported -> No LK derivation, no keypress notifications",
+ __func__);
+ p_data->auth_req &= ~SMP_KP_SUPPORT_BIT;
+ p_data->init_keys &= ~SMP_SEC_KEY_TYPE_LK;
+ p_data->resp_keys &= ~SMP_SEC_KEY_TYPE_LK;
+ }
+
+ BTM_TRACE_DEBUG ("btm_ble_io_capabilities_req 6: IO_CAP:%d oob_data:%d auth_req:0x%02x",
p_data->io_cap, p_data->oob_data, p_data->auth_req);
}
return callback_rc;
}
+/*******************************************************************************
+**
+** Function btm_ble_br_keys_req
+**
+** Description This function is called to handle SMP request for keys sent
+** over BR/EDR.
+**
+** Returns void
+**
+*******************************************************************************/
+UINT8 btm_ble_br_keys_req(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_LE_IO_REQ *p_data)
+{
+ UINT8 callback_rc = BTM_SUCCESS;
+ BTM_TRACE_DEBUG ("%s", __func__);
+ if (btm_cb.api.p_le_callback)
+ {
+ /* the callback function implementation may change the IO capability... */
+ callback_rc = (*btm_cb.api.p_le_callback) (BTM_LE_IO_REQ_EVT, p_dev_rec->bd_addr,
+ (tBTM_LE_EVT_DATA *)p_data);
+ }
+
+ return callback_rc;
+}
+
#if (BLE_PRIVACY_SPT == TRUE )
/*******************************************************************************
**
memcpy(p_dev_rec->ble.cur_rand_addr, bda, BD_ADDR_LEN);
#endif
- if (role == HCI_ROLE_SLAVE)
- p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
- p_cb->inq_var.directed_conn = FALSE;
+ p_cb->inq_var.directed_conn = BTM_BLE_CONNECT_EVT;
return;
}
** Description LE connection complete.
**
******************************************************************************/
-void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
+void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced)
{
#if (BLE_PRIVACY_SPT == TRUE )
UINT8 *p_data = p;
#endif
- UINT8 role, status, bda_type;
+ UINT8 role, status, bda_type, peer_addr_type;
UINT16 handle;
- BD_ADDR bda = {0};
+ BD_ADDR bda, local_rpa, peer_rpa;
UINT16 conn_interval, conn_latency, conn_timeout;
BOOLEAN match = FALSE;
UNUSED(evt_len);
STREAM_TO_UINT16 (handle, p);
STREAM_TO_UINT8 (role, p);
STREAM_TO_UINT8 (bda_type, p);
+ peer_addr_type = bda_type ;
STREAM_TO_BDADDR (bda, p);
if (status == 0)
{
#if (BLE_PRIVACY_SPT == TRUE )
+ match = btm_identity_addr_to_random_pseudo (bda, &bda_type, TRUE);
- if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
- match = btm_public_addr_to_random_pseudo (bda, &bda_type);
+ if (enhanced)
+ {
+ STREAM_TO_BDADDR (local_rpa, p);
+ STREAM_TO_BDADDR (peer_rpa, p);
+ }
/* possiblly receive connection complete with resolvable random on
slave role while the device has been paired */
- if (!match && /*role == HCI_ROLE_SLAVE && */BTM_BLE_IS_RESOLVE_BDA(bda))
+ if (!match && role == HCI_ROLE_SLAVE && BTM_BLE_IS_RESOLVE_BDA(bda))
{
btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_conn_cmpl, p_data);
}
handle = HCID_GET_HANDLE (handle);
btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, bda_type, match);
+
l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
conn_latency, conn_timeout);
+
+#if (BLE_PRIVACY_SPT == TRUE)
+ if (enhanced)
+ {
+ btm_ble_refresh_local_resolvable_private_addr(bda, local_rpa);
+
+ if (peer_addr_type & BLE_ADDR_TYPE_ID_BIT)
+ btm_ble_refresh_peer_resolvable_private_addr(bda, peer_rpa, BLE_ADDR_RANDOM);
+ }
+#endif
}
}
else
role = HCI_ROLE_UNKNOWN;
if (status != HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
- {
btm_ble_set_conn_st(BLE_CONN_IDLE);
}
- /* this is to work around broadcom firmware problem to handle
- * unsolicited command complete event for HCI_LE_Create_Connection_Cancel
- * and LE connection complete event with status error code (0x2)
- * unknown connection identifier from bluetooth controller
- * the workaround is to release the HCI connection to avoid out of sync
- * with bluetooth controller, which cause BT can't be turned off.
- */
- else if ((status == HCI_ERR_NO_CONNECTION) &&
- (btm_ble_get_conn_st() != BLE_CONN_CANCEL))
- {
- tL2C_LCB *p_lcb;
- handle = HCID_GET_HANDLE (handle);
- p_lcb = l2cu_find_lcb_by_handle (handle);
- if (p_lcb != NULL)
- {
- l2c_link_hci_disc_comp (handle, HCI_ERR_PEER_USER);
- btm_sec_disconnected (handle, HCI_ERR_PEER_USER);
- }
- }
- }
- btm_ble_set_conn_st(BLE_CONN_IDLE);
+
btm_ble_update_mode_operation(role, bda, status);
}
+
+
/*****************************************************************************
** Function btm_ble_create_ll_conn_complete
**
******************************************************************************/
void btm_ble_create_ll_conn_complete (UINT8 status)
{
- if (status != 0)
+ if (status != HCI_SUCCESS)
{
btm_ble_set_conn_st(BLE_CONN_IDLE);
btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, NULL, status);
btm_ble_io_capabilities_req(p_dev_rec, (tBTM_LE_IO_REQ *)&p_data->io_req);
break;
+ case SMP_BR_KEYS_REQ_EVT:
+ btm_ble_br_keys_req(p_dev_rec, (tBTM_LE_IO_REQ *)&p_data->io_req);
+ break;
+
case SMP_PASSKEY_REQ_EVT:
case SMP_PASSKEY_NOTIF_EVT:
case SMP_OOB_REQ_EVT:
+ case SMP_NC_REQ_EVT:
+ case SMP_SC_OOB_REQ_EVT:
+ /* fall through */
p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
case SMP_SEC_REQUEST_EVT:
p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
/* fall through */
+
case SMP_COMPLT_EVT:
if (btm_cb.api.p_le_callback)
{
BTM_TRACE_DEBUG ("after update result=%d sec_level=0x%x sec_flags=0x%x",
res, p_data->cmplt.sec_level , p_dev_rec->sec_flags );
- btm_sec_dev_rec_cback_event(p_dev_rec, res, TRUE);
-
if (p_data->cmplt.is_pair_cancel && btm_cb.api.p_bond_cancel_cmpl_callback )
{
BTM_TRACE_DEBUG ("Pairing Cancel completed");
{
if (!btm_cb.devcb.no_disc_if_pair_fail && p_data->cmplt.reason != SMP_CONN_TOUT)
{
- BTM_TRACE_DEBUG ("Pairing failed - Remove ACL");
- btm_remove_acl(bd_addr, BT_TRANSPORT_LE);
+ BTM_TRACE_DEBUG ("Pairing failed - prepare to remove ACL");
+ l2cu_start_post_bond_timer(p_dev_rec->ble_hci_handle);
}
else
{
}
#else
if (res != BTM_SUCCESS && p_data->cmplt.reason != SMP_CONN_TOUT)
- btm_remove_acl(bd_addr, BT_TRANSPORT_LE);
+ {
+ BTM_TRACE_DEBUG ("Pairing failed - prepare to remove ACL");
+ l2cu_start_post_bond_timer(p_dev_rec->ble_hci_handle);
+ }
#endif
BTM_TRACE_DEBUG ("btm_cb pairing_state=%x pairing_flags=%x pin_code_len=%x",
BTM_TRACE_DEBUG ("btm_cb.pairing_bda %02x:%02x:%02x:%02x:%02x:%02x",
btm_cb.pairing_bda[0], btm_cb.pairing_bda[1], btm_cb.pairing_bda[2],
btm_cb.pairing_bda[3], btm_cb.pairing_bda[4], btm_cb.pairing_bda[5]);
+
/* Reset btm state only if the callback address matches pairing address*/
if(memcmp(bd_addr, btm_cb.pairing_bda, BD_ADDR_LEN) == 0)
{
btm_cb.pairing_state = BTM_PAIR_STATE_IDLE;
btm_cb.pairing_flags = 0;
}
+
+ if (res == BTM_SUCCESS)
+ {
+ p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ /* add all bonded device into resolving list if IRK is available*/
+ btm_ble_resolving_list_load_dev(p_dev_rec);
+#endif
+ }
+
+ btm_sec_dev_rec_cback_event(p_dev_rec, res, TRUE);
}
break;
BOOLEAN BTM_BleDataSignature (BD_ADDR bd_addr, UINT8 *p_text, UINT16 len,
BLE_SIGNATURE signature)
{
- BOOLEAN ret = FALSE;
-#if SMP_INCLUDED == TRUE
- tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
- UINT8 *p_buf, *pp;
-
- BT_OCTET16 er;
- UINT16 div;
- UINT8 temp[4]; /* for (r || DIV) r=1*/
- UINT16 r=1;
- UINT8 *p=temp, *p_mac = (UINT8 *)signature;
- tSMP_ENC output;
- BT_OCTET16 local_csrk;
+ tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
- BTM_TRACE_DEBUG ("BTM_BleDataSignature");
+ BTM_TRACE_DEBUG ("%s", __func__);
+ BOOLEAN ret = FALSE;
if (p_rec == NULL)
{
- BTM_TRACE_ERROR("data signing can not be done from unknow device");
+ BTM_TRACE_ERROR("%s-data signing can not be done from unknown device", __func__);
}
else
{
+ UINT8 *p_mac = (UINT8 *)signature;
+ UINT8 *p_buf, *pp;
if ((p_buf = (UINT8 *)GKI_getbuf((UINT16)(len + 4))) != NULL)
{
- BTM_TRACE_DEBUG("Start to generate Local CSRK");
+ BTM_TRACE_DEBUG("%s-Start to generate Local CSRK", __func__);
pp = p_buf;
/* prepare plain text */
if (p_text)
pp = (p_buf + len);
}
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
- if ( btm_cb.devcb.enable_test_local_sign_cntr)
- {
- BTM_TRACE_DEBUG ("Use Test local counter value from script counter_val=%d", btm_cb.devcb.test_local_sign_cntr);
- UINT32_TO_STREAM(pp, btm_cb.devcb.test_local_sign_cntr);
- }
- else
- {
- UINT32_TO_STREAM(pp, p_rec->ble.keys.local_counter);
- }
-#else
UINT32_TO_STREAM(pp, p_rec->ble.keys.local_counter);
-#endif
- /* compute local csrk */
- if (btm_get_local_div(bd_addr, &div))
- {
- BTM_TRACE_DEBUG ("compute_csrk div=%x", div);
- BTM_GetDeviceEncRoot(er);
-
- /* CSRK = d1(ER, DIV, 1) */
- UINT16_TO_STREAM(p, div);
- UINT16_TO_STREAM(p, r);
+ UINT32_TO_STREAM(p_mac, p_rec->ble.keys.local_counter);
- if (!SMP_Encrypt(er, BT_OCTET16_LEN, temp, 4, &output))
- {
- BTM_TRACE_ERROR("Local CSRK generation failed ");
- }
- else
- {
- BTM_TRACE_DEBUG("local CSRK generation success");
- memcpy((void *)local_csrk, output.param_buf, BT_OCTET16_LEN);
-
-
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
- if (btm_cb.devcb.enable_test_local_sign_cntr)
- {
- UINT32_TO_STREAM(p_mac, btm_cb.devcb.test_local_sign_cntr);
- }
- else
- {
- UINT32_TO_STREAM(p_mac, p_rec->ble.keys.local_counter);
- }
-#else
- UINT32_TO_STREAM(p_mac, p_rec->ble.keys.local_counter);
-#endif
-
- if ((ret = AES_CMAC(local_csrk, p_buf, (UINT16)(len + 4), BTM_CMAC_TLEN_SIZE, p_mac)) == TRUE)
- {
- btm_ble_increment_sign_ctr(bd_addr, TRUE);
-
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
- if ( btm_cb.devcb.enable_test_mac_val)
- {
- BTM_TRACE_DEBUG ("Use MAC value from script");
- memcpy(p_mac, btm_cb.devcb.test_mac, BTM_CMAC_TLEN_SIZE);
- }
-#endif
- }
- BTM_TRACE_DEBUG("BTM_BleDataSignature p_mac = %d", p_mac);
- BTM_TRACE_DEBUG("p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = 0x%02x",
- *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
- BTM_TRACE_DEBUG("p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = 0x%02x",
- *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
-
- GKI_freebuf(p_buf);
- }
+ if ((ret = aes_cipher_msg_auth_code(p_rec->ble.keys.lcsrk, p_buf, (UINT16)(len + 4),
+ BTM_CMAC_TLEN_SIZE, p_mac)) == TRUE)
+ {
+ btm_ble_increment_sign_ctr(bd_addr, TRUE);
}
+
+ BTM_TRACE_DEBUG("%s p_mac = %d", __func__, p_mac);
+ BTM_TRACE_DEBUG("p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = 0x%02x",
+ *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
+ BTM_TRACE_DEBUG("p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = 0x%02x",
+ *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
+ GKI_freebuf(p_buf);
}
}
-#endif /* SMP_INCLUDED */
return ret;
}
BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT32 counter,
UINT8 *p_comp)
{
- BOOLEAN verified = FALSE;
+ BOOLEAN verified = FALSE;
#if SMP_INCLUDED == TRUE
- tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
- UINT8 p_mac[BTM_CMAC_TLEN_SIZE];
+ tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
+ UINT8 p_mac[BTM_CMAC_TLEN_SIZE];
if (p_rec == NULL || (p_rec && !(p_rec->ble.key_type & BTM_LE_KEY_PCSRK)))
{
}
else
{
- BTM_TRACE_DEBUG ("BTM_BleVerifySignature rcv_cnt=%d >= expected_cnt=%d", counter, p_rec->ble.keys.counter);
+ BTM_TRACE_DEBUG ("%s rcv_cnt=%d >= expected_cnt=%d", __func__, counter,
+ p_rec->ble.keys.counter);
- if (AES_CMAC(p_rec->ble.keys.csrk, p_orig, len, BTM_CMAC_TLEN_SIZE, p_mac))
+ if (aes_cipher_msg_auth_code(p_rec->ble.keys.pcsrk, p_orig, len, BTM_CMAC_TLEN_SIZE, p_mac))
{
if (memcmp(p_mac, p_comp, BTM_CMAC_TLEN_SIZE) == 0)
{
}
/*******************************************************************************
+**
+** Function BTM_GetLeSecurityState
+**
+** Description This function is called to get security mode 1 flags and
+** encryption key size for LE peer.
+**
+** Returns BOOLEAN TRUE if LE device is found, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN BTM_GetLeSecurityState (BD_ADDR bd_addr, UINT8 *p_le_dev_sec_flags, UINT8 *p_le_key_size)
+{
+#if (BLE_INCLUDED == TRUE)
+ tBTM_SEC_DEV_REC *p_dev_rec;
+ UINT16 dev_rec_sec_flags;
+#endif
+
+ *p_le_dev_sec_flags = 0;
+ *p_le_key_size = 0;
+
+#if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
+ if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
+ {
+ BTM_TRACE_ERROR ("%s fails", __func__);
+ return (FALSE);
+ }
+
+ if (p_dev_rec->ble_hci_handle == BTM_SEC_INVALID_HANDLE)
+ {
+ BTM_TRACE_ERROR ("%s-this is not LE device", __func__);
+ return (FALSE);
+ }
+
+ dev_rec_sec_flags = p_dev_rec->sec_flags;
+
+ if (dev_rec_sec_flags & BTM_SEC_LE_ENCRYPTED)
+ {
+ /* link is encrypted with LTK or STK */
+ *p_le_key_size = p_dev_rec->enc_key_size;
+ *p_le_dev_sec_flags |= BTM_SEC_LE_LINK_ENCRYPTED;
+
+ *p_le_dev_sec_flags |= (dev_rec_sec_flags & BTM_SEC_LE_AUTHENTICATED)
+ ? BTM_SEC_LE_LINK_PAIRED_WITH_MITM /* set auth LTK flag */
+ : BTM_SEC_LE_LINK_PAIRED_WITHOUT_MITM; /* set unauth LTK flag */
+ }
+ else if (p_dev_rec->ble.key_type & BTM_LE_KEY_PENC)
+ {
+ /* link is unencrypted, still LTK is available */
+ *p_le_key_size = p_dev_rec->ble.keys.key_size;
+
+ *p_le_dev_sec_flags |= (dev_rec_sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED)
+ ? BTM_SEC_LE_LINK_PAIRED_WITH_MITM /* set auth LTK flag */
+ : BTM_SEC_LE_LINK_PAIRED_WITHOUT_MITM; /* set unauth LTK flag */
+ }
+
+ BTM_TRACE_DEBUG ("%s - le_dev_sec_flags: 0x%02x, le_key_size: %d",
+ __func__, *p_le_dev_sec_flags, *p_le_key_size);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleSecurityProcedureIsRunning
+**
+** Description This function indicates if LE security procedure is
+** currently running with the peer.
+**
+** Returns BOOLEAN TRUE if security procedure is running, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN BTM_BleSecurityProcedureIsRunning(BD_ADDR bd_addr)
+{
+#if (BLE_INCLUDED == TRUE)
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+
+ if (p_dev_rec == NULL)
+ {
+ BTM_TRACE_ERROR ("%s device with BDA: %08x%04x is not found",
+ __func__, (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->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+ p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING);
+#else
+ return FALSE;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTM_BleGetSupportedKeySize
+**
+** Description This function gets the maximum encryption key size in bytes
+** the local device can suport.
+** record.
+**
+** Returns the key size or 0 if the size can't be retrieved.
+**
+*******************************************************************************/
+extern UINT8 BTM_BleGetSupportedKeySize (BD_ADDR bd_addr)
+{
+#if ((BLE_INCLUDED == TRUE) && (L2CAP_LE_COC_INCLUDED == TRUE))
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+ tBTM_LE_IO_REQ dev_io_cfg;
+ UINT8 callback_rc;
+
+ if (!p_dev_rec)
+ {
+ BTM_TRACE_ERROR ("%s device with BDA: %08x%04x is not found",
+ __func__,(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
+ (bd_addr[4]<<8)+bd_addr[5]);
+ return 0;
+ }
+
+ if (btm_cb.api.p_le_callback == NULL)
+ {
+ BTM_TRACE_ERROR ("%s can't access supported key size",__func__);
+ return 0;
+ }
+
+ callback_rc = (*btm_cb.api.p_le_callback) (BTM_LE_IO_REQ_EVT, p_dev_rec->bd_addr,
+ (tBTM_LE_EVT_DATA *) &dev_io_cfg);
+
+ if (callback_rc != BTM_SUCCESS)
+ {
+ BTM_TRACE_ERROR ("%s can't access supported key size",__func__);
+ return 0;
+ }
+
+ BTM_TRACE_DEBUG ("%s device supports key size = %d", __func__, dev_io_cfg.max_key_size);
+ return (dev_io_cfg.max_key_size);
+#else
+ return 0;
+#endif
+}
+
+/*******************************************************************************
** Utility functions for LE device IR/ER generation
*******************************************************************************/
/*******************************************************************************
case BTM_BLE_KEY_TYPE_ER:
BTM_TRACE_DEBUG ("BTM_BLE_KEY_TYPE_ER");
- p_locak_keys = (tBTM_BLE_LOCAL_KEYS *)&btm_cb.devcb.er;
+ p_locak_keys = (tBTM_BLE_LOCAL_KEYS *)&btm_cb.devcb.ble_encryption_key_value;
break;
default:
if (p &&p->opcode == HCI_BLE_RAND)
{
- memcpy(&btm_cb.devcb.er[8], p->param_buf, BT_OCTET8_LEN);
+ memcpy(&btm_cb.devcb.ble_encryption_key_value[8], p->param_buf, BT_OCTET8_LEN);
btm_notify_new_key(BTM_BLE_KEY_TYPE_ER);
}
else
{
BTM_TRACE_ERROR("Generating ER2 exception.");
- memset(&btm_cb.devcb.er, 0, sizeof(BT_OCTET16));
+ memset(&btm_cb.devcb.ble_encryption_key_value, 0, sizeof(BT_OCTET16));
}
}
if (p &&p->opcode == HCI_BLE_RAND)
{
- memcpy(&btm_cb.devcb.er[0], p->param_buf, BT_OCTET8_LEN);
+ memcpy(&btm_cb.devcb.ble_encryption_key_value[0], p->param_buf, BT_OCTET8_LEN);
if (!btsnd_hcic_ble_rand((void *)btm_ble_process_er2))
{
- memset(&btm_cb.devcb.er, 0, sizeof(BT_OCTET16));
+ memset(&btm_cb.devcb.ble_encryption_key_value, 0, sizeof(BT_OCTET16));
BTM_TRACE_ERROR("Generating ER2 failed.");
}
}
#include "btu.h"
#include "btm_int.h"
#include "gap_api.h"
+#include "device/include/controller.h"
#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
#include "btm_ble_int.h"
#include "smp_api.h"
-#include "vendor_ble.h"
/*******************************************************************************
**
}
}
- #if SMP_INCLUDED == TRUE
+
+#if SMP_INCLUDED == TRUE
/*******************************************************************************
** Utility functions for Random address resolving
*******************************************************************************/
else
(*p_cback)(NULL, p);
}
- #endif
+#endif
+
/*******************************************************************************
** address mapping between pseudo address and real connection address
*******************************************************************************/
/*******************************************************************************
**
-** Function btm_find_dev_by_public_static_addr
+** Function btm_find_dev_by_identity_addr
**
** Description find the security record whose LE static address is matching
**
*******************************************************************************/
-tBTM_SEC_DEV_REC* btm_find_dev_by_public_static_addr(BD_ADDR bd_addr)
+tBTM_SEC_DEV_REC* btm_find_dev_by_identity_addr(BD_ADDR bd_addr, UINT8 addr_type)
{
- UINT8 i;
- tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
#if BLE_PRIVACY_SPT == TRUE
+ UINT8 i;
+ tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+
for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec ++)
{
- if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
- BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
+ if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) &&
+ memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) == 0)
{
- if ( memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) == 0)
+ if ((p_dev_rec->ble.static_addr_type & (~BLE_ADDR_TYPE_ID_BIT)) !=
+ (addr_type & (~BLE_ADDR_TYPE_ID_BIT)))
{
- p_dev_rec->ble.active_addr_type = BTM_BLE_ADDR_RRA;
- /* found the match */
- return p_dev_rec;
+ BTM_TRACE_WARNING("%s find pseudo->random match with diff addr type: %d vs %d",
+ __func__, p_dev_rec->ble.static_addr_type, addr_type);
}
+
+ /* found the match */
+ return p_dev_rec;
}
}
#endif
+
return NULL;
}
/*******************************************************************************
**
-** Function btm_public_addr_to_random_pseudo
+** Function btm_identity_addr_to_random_pseudo
**
** Description This function map a static BD address to a pseudo random address
** in security database.
**
*******************************************************************************/
-BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type)
+BOOLEAN btm_identity_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN refresh)
{
#if BLE_PRIVACY_SPT == TRUE
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_public_static_addr(bd_addr);
-
- BTM_TRACE_EVENT ("btm_public_addr_to_random_pseudo");
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_identity_addr(bd_addr, *p_addr_type);
+ BTM_TRACE_EVENT ("%s", __func__);
/* evt reported on static address, map static address to random pseudo */
- if (p_dev_rec != NULL &&
- /* static address is not static address */
- memcmp(p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN) != 0)
- /* update current random */
- btm_ble_read_irk_entry(p_dev_rec->ble.static_addr);
if (p_dev_rec != NULL)
{
- /* assign the orginal random to be the current report address */
- memcpy(bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
- /* always be a resolvable random if a match is found */
- *p_addr_type = BLE_ADDR_RANDOM;
+ /* if RPA offloading is supported, or 4.2 controller, do RPA refresh */
+ if (refresh && controller_get_interface()->get_ble_resolving_list_max_size() != 0)
+ btm_ble_read_resolving_list_entry(p_dev_rec);
- BTM_TRACE_ERROR("matched a public/reconnect address and map to random pseudo");
+ /* assign the original address to be the current report address */
+ memcpy(bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
+ *p_addr_type = p_dev_rec->ble.ble_addr_type;
return TRUE;
}
/*******************************************************************************
**
-** Function btm_random_pseudo_to_public
+** Function btm_random_pseudo_to_identity_addr
**
** Description This function map a random pseudo address to a public address
** random_pseudo is input and output parameter
**
*******************************************************************************/
-BOOLEAN btm_random_pseudo_to_public(BD_ADDR random_pseudo, UINT8 *p_static_addr_type)
+BOOLEAN btm_random_pseudo_to_identity_addr(BD_ADDR random_pseudo, UINT8 *p_static_addr_type)
{
#if BLE_PRIVACY_SPT == TRUE
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (random_pseudo);
if (p_dev_rec != NULL)
{
- if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
- BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr) &&
- (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0)
+ if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
{
- BTM_TRACE_EVENT ("btm_random_pseudo_to_public found the puclic static address!");
* p_static_addr_type = p_dev_rec->ble.static_addr_type;
memcpy(random_pseudo, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
+ if (controller_get_interface()->supports_ble_privacy())
+ *p_static_addr_type |= BLE_ADDR_TYPE_ID_BIT;
return TRUE;
}
}
/*******************************************************************************
**
-** Function btm_ble_refresh_rra
+** Function btm_ble_refresh_peer_resolvable_private_addr
**
-** Description This function refresh the currently used RRA into security
+** Description This function refresh the currently used resolvable remote private address into security
** database and set active connection address.
**
*******************************************************************************/
-void btm_ble_refresh_rra(BD_ADDR static_bda, BD_ADDR rra)
+void btm_ble_refresh_peer_resolvable_private_addr(BD_ADDR pseudo_bda, BD_ADDR rpa,
+ UINT8 rra_type)
{
#if BLE_PRIVACY_SPT == TRUE
- tBTM_SEC_DEV_REC *p_sec_rec = btm_find_dev_by_public_static_addr(static_bda);
- tACL_CONN *p_acl = btm_bda_to_acl (p_sec_rec->bd_addr, BT_TRANSPORT_LE);
UINT8 rra_dummy = FALSE;
BD_ADDR dummy_bda = {0};
- BTM_TRACE_ERROR("btm_ble_refresh_rra");
-
- if (memcmp(dummy_bda, rra, BD_ADDR_LEN) == 0)
+ if (memcmp(dummy_bda, rpa, BD_ADDR_LEN) == 0)
rra_dummy = TRUE;
- /* connection refresh RRA */
- if (p_acl != NULL /* && memcmp(p_acl->active_remote_addr, dummy_bda, BD_ADDR_LEN) == 0 */)
+ /* update security record here, in adv event or connection complete process */
+ tBTM_SEC_DEV_REC *p_sec_rec = btm_find_dev(pseudo_bda);
+ if (p_sec_rec != NULL)
{
- /* use static address, rra is empty */
- if (rra_dummy)
+ memcpy(p_sec_rec->ble.cur_rand_addr, rpa, BD_ADDR_LEN);
+
+ /* unknown, if dummy address, set to static */
+ if (rra_type == BTM_BLE_ADDR_PSEUDO)
+ p_sec_rec->ble.active_addr_type = rra_dummy ? BTM_BLE_ADDR_STATIC: BTM_BLE_ADDR_RRA;
+ else
+ p_sec_rec->ble.active_addr_type = rra_type;
+ }
+ else
+ {
+ BTM_TRACE_ERROR("No matching known device in record");
+ return;
+ }
+
+ BTM_TRACE_DEBUG("%s: active_addr_type: %d ",
+ __func__, p_sec_rec->ble.active_addr_type);
+
+ /* connection refresh remote address */
+ tACL_CONN *p_acl = p_acl = btm_bda_to_acl(p_sec_rec->bd_addr, BT_TRANSPORT_LE);
+ if (p_acl != NULL)
+ {
+ if (rra_type == BTM_BLE_ADDR_PSEUDO)
{
- p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
- memcpy(p_acl->active_remote_addr, p_sec_rec->ble.static_addr, BD_ADDR_LEN);
+ /* use static address, resolvable_private_addr is empty */
+ if (rra_dummy)
+ {
+ p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
+ memcpy(p_acl->active_remote_addr, p_sec_rec->ble.static_addr, BD_ADDR_LEN);
+ }
+ else
+ {
+ p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
+ memcpy(p_acl->active_remote_addr, rpa, BD_ADDR_LEN);
+ }
}
else
{
- p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
- memcpy(p_acl->active_remote_addr, rra, BD_ADDR_LEN);
+ p_acl->active_remote_addr_type = rra_type;
+ memcpy(p_acl->active_remote_addr, rpa, BD_ADDR_LEN);
}
+
+ BTM_TRACE_DEBUG("p_acl->active_remote_addr_type: %d ", p_acl->active_remote_addr_type);
+ BTM_TRACE_DEBUG("%s conn_addr: %02x:%02x:%02x:%02x:%02x:%02x",
+ __func__,p_acl->active_remote_addr[0], p_acl->active_remote_addr[1],
+ p_acl->active_remote_addr[2], p_acl->active_remote_addr[3],
+ p_acl->active_remote_addr[4], p_acl->active_remote_addr[5]);
}
- /* update security record here, in adv event or connection complete process */
- if (p_sec_rec != NULL)
- {
- memcpy(p_sec_rec->ble.cur_rand_addr, rra, BD_ADDR_LEN);
- p_sec_rec->ble.active_addr_type = rra_dummy ? BTM_BLE_ADDR_STATIC: BTM_BLE_ADDR_RRA;
- }
- else
+#endif
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_refresh_local_resolvable_private_addr
+**
+** Description This function refresh the currently used resolvable private address for the
+** active link to the remote device
+**
+*******************************************************************************/
+void btm_ble_refresh_local_resolvable_private_addr(BD_ADDR pseudo_addr,
+ BD_ADDR local_rpa)
+{
+#if BLE_PRIVACY_SPT == TRUE
+ tACL_CONN *p = btm_bda_to_acl(pseudo_addr, BT_TRANSPORT_LE);
+ BD_ADDR dummy_bda = {0};
+
+ if (p != NULL)
{
- BTM_TRACE_ERROR("No matching known device in record");
+ if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
+ {
+ p->conn_addr_type = BLE_ADDR_RANDOM;
+ if (memcmp(local_rpa, dummy_bda, BD_ADDR_LEN))
+ memcpy(p->conn_addr, local_rpa, BD_ADDR_LEN);
+ else
+ memcpy(p->conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
+ }
+ else
+ {
+ p->conn_addr_type = BLE_ADDR_PUBLIC;
+ memcpy(p->conn_addr,&controller_get_interface()->get_address()->address, BD_ADDR_LEN);
+ }
}
#endif
}
#include "bt_utils.h"
#include "hcidefs.h"
#include "btm_ble_api.h"
-#include "vendor_ble.h"
#include "device/include/controller.h"
#define BTM_BLE_ADV_FILT_META_HDR_LENGTH 3
#define BTM_BLE_ADV_FILT_FEAT_SELN_LEN 13
#define BTM_BLE_ADV_FILT_TRACK_NUM 2
+#define BTM_BLE_PF_SELECT_NONE 0
+
+/* BLE meta vsc header: 1 bytes of sub_code, 1 byte of PCF action */
+#define BTM_BLE_META_HDR_LENGTH 3
+#define BTM_BLE_PF_FEAT_SEL_LEN 18
+#define BTM_BLE_PCF_ENABLE_LEN 2
+
+#define BTM_BLE_META_ADDR_LEN 7
+#define BTM_BLE_META_UUID_LEN 40
+
#define BTM_BLE_PF_BIT_TO_MASK(x) (UINT16)(1 << (x))
#include "l2c_int.h"
#include "hcimsgs.h"
#include "bt_utils.h"
-#include "vendor_ble.h"
+#include "device/include/controller.h"
#ifndef BTM_BLE_SCAN_PARAM_TOUT
#define BTM_BLE_SCAN_PARAM_TOUT 50 /* 50 seconds */
{
if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
{
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
- /* add device into IRK list */
- btm_ble_vendor_irk_list_load_dev(p_dev_rec);
-#endif
started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
+ p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
}
- if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 &&
+ else if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 &&
memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
{
started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.static_addr_type,
p_dev_rec->ble.static_addr);
+ p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
}
}
else
{
if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
{
- started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
+ started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
}
if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0 &&
memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0)
{
- started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
+ started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
}
+ p_dev_rec->ble.in_controller_list &= ~BTM_WHITE_LIST_BIT;
}
} /* if not a known device, shall we add it? */
else
{
BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
+ started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
if (to_add)
started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr);
- else
- started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
}
return started;
return ret;
}
+ /* Look for existing device to add/remove attribute */
for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_bg_dev ++)
{
if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0)
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
BD_ADDR dummy_bda = {0};
BOOLEAN exec = TRUE;
- UINT16 scan_int, scan_win;
+ UINT16 scan_int;
+ UINT16 scan_win;
+ UINT8 own_addr_type = p_cb->addr_mgnt_cb.own_addr_type;
+ UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
if (start)
{
- if ( p_cb->conn_state == BLE_CONN_IDLE )
- {
- exec = btm_execute_wl_dev_operation();
- }
- if ((p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
+ if (p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0
&& btm_ble_topology_check(BTM_BLE_STATE_INIT))
{
- scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
- scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win;
+ p_cb->wl_state |= BTM_BLE_WL_INIT;
+
+ btm_execute_wl_dev_operation();
+
+#if BLE_PRIVACY_SPT == TRUE
+ btm_ble_enable_resolving_list_for_platform();
+#endif
+ scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ?
+ BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
+ scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ?
+ BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win;
+ if (btm_cb.ble_ctr_cb.enabled)
+ {
+ own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+ peer_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+ }
if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */
scan_win, /* UINT16 scan_win */
0x01, /* UINT8 white_list */
- BLE_ADDR_PUBLIC, /* UINT8 addr_type_peer */
+ peer_addr_type, /* UINT8 addr_type_peer */
dummy_bda, /* BD_ADDR bda_peer */
- p_cb->addr_mgnt_cb.own_addr_type,
- /* UINT8 addr_type_own,
- not allow random address for central */
+ own_addr_type, /* UINT8 addr_type_own */
BTM_BLE_CONN_INT_MIN_DEF, /* UINT16 conn_int_min */
BTM_BLE_CONN_INT_MAX_DEF, /* UINT16 conn_int_max */
BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* UINT16 conn_latency */
{
/* start auto connection failed */
exec = FALSE;
+ p_cb->wl_state &= ~BTM_BLE_WL_INIT;
}
else
{
btm_ble_set_conn_st (BLE_BG_CONN);
- p_cb->wl_state |= BTM_BLE_WL_INIT;
}
}
else
{
btsnd_hcic_ble_create_conn_cancel();
btm_ble_set_conn_st (BLE_CONN_CANCEL);
- p_cb->wl_state |= BTM_BLE_WL_INIT;
-
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
- if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
- btm_ble_vendor_disable_irk_list();
-#endif
+ p_cb->wl_state &= ~BTM_BLE_WL_INIT;
}
else
{
scan_win, /* scan window */
p_cb->addr_mgnt_cb.own_addr_type,
SP_ADV_WL) /* process advertising packets only from devices in the White List */
- )
- return FALSE;
+ )
+ return FALSE;
if (!btm_ble_topology_check(BTM_BLE_STATE_PASSIVE_SCAN))
{
{
p_cb->scan_activity &= ~BTM_LE_SELECT_CONN_ACTIVE;
p_cb->p_select_cback = NULL;
-
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
- if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
- btm_ble_vendor_disable_irk_list();
-#endif
- p_cb->wl_state |= BTM_BLE_WL_SCAN;
+ p_cb->wl_state &= ~BTM_BLE_WL_SCAN;
/* stop scanning */
if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
btm_ble_stop_scan(); /* duplicate filtering enabled */
- btm_update_scanner_filter_policy(SP_ADV_ALL);
}
return TRUE;
}
void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st)
{
btm_cb.ble_ctr_cb.conn_state = new_st;
- if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN) {
- btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_INIT;
+
+ if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN)
btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT);
- } else {
- btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_INIT;
+ else
btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
- }
}
/*******************************************************************************
#if BLE_INCLUDED == TRUE
#include "l2c_int.h"
-#include "vendor_ble.h"
#include "gattdefs.h"
#include "gatt_int.h"
UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
tBTM_BLE_ADV_DATA *p_data);
static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
- BD_ADDR_PTR p_addr_ptr,
- tBLE_ADDR_TYPE *p_init_addr_type,
+ BD_ADDR_PTR p_peer_addr_ptr,
+ tBLE_ADDR_TYPE *p_peer_addr_type,
tBLE_ADDR_TYPE *p_own_addr_type);
static void btm_ble_stop_observe(void);
BTM_BLE_DEFAULT_SFP); /* assume observe always not using white list */
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
- /* enable IRK list */
- btm_ble_vendor_irk_list_known_dev (TRUE);
+ /* enable resolving list */
+ btm_ble_enable_resolving_list_for_platform();
#endif
status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
}
}
BTM_TRACE_DEBUG("btm_ble_vnd_cap_vsc_cmpl_cback: stat=%d, irk=%d, ADV ins:%d, rpa=%d, ener=%d",
- status, btm_ble_vendor_cb.irk_avail_size, btm_cb.cmn_ble_vsc_cb.adv_inst_max,
+ status,btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, btm_cb.cmn_ble_vsc_cb.adv_inst_max,
btm_cb.cmn_ble_vsc_cb.rpa_offloading, btm_cb.cmn_ble_vsc_cb.energy_support);
if (BTM_BleMaxMultiAdvInstanceCount() > 0)
btm_ble_adv_filter_init();
}
- if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz > 0)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ /* VS capability included and non-4.2 device */
+ if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz > 0 &&
+ controller_get_interface()->get_ble_resolving_list_max_size() == 0)
{
- btm_ble_vendor_init(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz);
+ btm_ble_resolving_list_init(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz);
}
+#endif
if (btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg > 0)
btm_ble_batchscan_init();
/*******************************************************************************
**
-** Function BTM_RegisterScanReqEvt
+** Function BTM_BleEnableMixedPrivacyMode
**
-** Description This function is called to register a scan request callback
-** on the advertiser.
+** Description This function is called to enabled Mixed mode if privacy 1.2
+** is applicable in controller.
**
-** Parameters p_scan_req_cback: scan request callback. If NULL, remove the
-** registration.
+** Parameters mixed_on: mixed mode to be used or not.
**
** Returns void
**
*******************************************************************************/
-void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback)
+void BTM_BleEnableMixedPrivacyMode(BOOLEAN mixed_on)
{
-#ifdef BTM_BLE_PC_ADV_TEST_MODE /* For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include */
- if (BTM_BLE_PC_ADV_TEST_MODE) /* For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode */
- {
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- p_cb->p_scan_req_cback = p_scan_req_cback;
- }
-#else
- UNUSED(p_scan_req_cback);
+
+#if BLE_PRIVACY_SPT == TRUE
+ btm_cb.ble_ctr_cb.mixed_mode = mixed_on;
+
+ /* TODO: send VSC to enabled mixed mode */
#endif
}
** Description This function is called to enable or disable the privacy in
** LE channel of the local device.
**
-** Parameters enable: TRUE to enable it; FALSE to disable it.
+** Parameters privacy_mode: privacy mode on or off.
**
-** Returns void
+** Returns BOOLEAN privacy mode set success; otherwise failed.
**
*******************************************************************************/
-void BTM_BleConfigPrivacy(BOOLEAN enable)
+BOOLEAN BTM_BleConfigPrivacy(BOOLEAN privacy_mode)
{
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+#if BLE_PRIVACY_SPT == TRUE
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- BTM_TRACE_EVENT (" BTM_BleConfigPrivacy");
+ BTM_TRACE_EVENT ("%s", __func__);
- if (p_cb->privacy != enable)
+ /* if LE is not supported, return error */
+ if (!controller_get_interface()->supports_ble())
+ return FALSE;
+
+ uint8_t addr_resolution = 0;
+ if(!privacy_mode)/* if privacy disabled, always use public address */
{
- p_cb->privacy = enable;
+ p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
+ p_cb->privacy_mode = BTM_PRIVACY_NONE;
+ }
+ else /* privacy is turned on*/
+ {
+ /* always set host random address, used when privacy 1.1 or priavcy 1.2 is disabled */
+ p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
+ btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low);
- if (p_cb->privacy)
- {
- /* generate resolvable private address */
- btm_gen_resolvable_private_addr((void*)btm_gen_resolve_paddr_low);
- }
- else /* if privacy disabled, always use public address */
+ if (BTM_BleMaxMultiAdvInstanceCount() > 0)
+ btm_ble_multi_adv_enb_privacy(privacy_mode);
+
+ /* 4.2 controller only allow privacy 1.2 or mixed mode, resolvable private address in controller */
+ if (controller_get_interface()->supports_ble_privacy())
{
- p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
+ addr_resolution = 1;
+ /* check vendor specific capability */
+ p_cb->privacy_mode = btm_cb.ble_ctr_cb.mixed_mode ? BTM_PRIVACY_MIXED : BTM_PRIVACY_1_2;
}
-
- if (BTM_BleMaxMultiAdvInstanceCount() > 0)
- btm_ble_multi_adv_enb_privacy(p_cb->privacy);
+ else /* 4.1/4.0 controller */
+ p_cb->privacy_mode = BTM_PRIVACY_1_1;
}
+
+ GAP_BleAttrDBUpdate (GATT_UUID_GAP_CENTRAL_ADDR_RESOL, (tGAP_BLE_ATTR_VALUE *)&addr_resolution);
+
+ return TRUE;
+#else
+ return FALSE;
+#endif
}
/*******************************************************************************
** Returns Max multi adv instance count
**
*******************************************************************************/
-extern UINT8 BTM_BleMaxMultiAdvInstanceCount()
+extern UINT8 BTM_BleMaxMultiAdvInstanceCount(void)
{
return btm_cb.cmn_ble_vsc_cb.adv_inst_max < BTM_BLE_MULTI_ADV_MAX ?
btm_cb.cmn_ble_vsc_cb.adv_inst_max : BTM_BLE_MULTI_ADV_MAX;
** Returns Return TRUE if local privacy is enabled else FALSE
**
*******************************************************************************/
-BOOLEAN BTM_BleLocalPrivacyEnabled()
+BOOLEAN BTM_BleLocalPrivacyEnabled(void)
{
#if BLE_PRIVACY_SPT == TRUE
- return btm_cb.ble_ctr_cb.privacy;
+ return (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE);
#else
return false;
#endif
{
btm_ble_start_auto_conn(FALSE);
}
- started = btm_ble_start_select_conn(TRUE, p_select_cback);
+ btm_ble_start_select_conn(TRUE, p_select_cback);
break;
case BTM_BLE_CONN_NONE:
*******************************************************************************/
BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR remote_bda)
{
- BOOLEAN ret = TRUE;
+ BOOLEAN ret = FALSE;
BTM_TRACE_EVENT (" BTM_BleUpdateBgConnDev");
/* update white list */
- ret = btm_update_bg_conn_list(add_remove, remote_bda);
-
- btm_update_dev_to_white_list(add_remove, remote_bda);
+ if (btm_update_bg_conn_list(add_remove, remote_bda))
+ ret = btm_update_dev_to_white_list(add_remove, remote_bda);
return ret;
}
/*******************************************************************************
**
-** Function BTM_BleSetConnMode
+** Function BTM_BleSetConnectableMode
**
** Description This function is called to set BLE connectable mode for a
** peripheral device.
**
-** Parameters directed: is directed connectable mode, or non-directed.
-** p_dir_bda: connectable direct initiator's LE device address
+** Parameters conn_mode: directed connectable mode, or non-directed.It can
+** be BTM_BLE_CONNECT_EVT, BTM_BLE_CONNECT_DIR_EVT or
+** BTM_BLE_CONNECT_LO_DUTY_DIR_EVT
**
-** Returns void
+** Returns BTM_ILLEGAL_VALUE if controller does not support BLE.
+** BTM_SUCCESS is status set successfully; otherwise failure.
**
*******************************************************************************/
-tBTM_STATUS BTM_BleSetConnMode(BOOLEAN is_directed)
+tBTM_STATUS BTM_BleSetConnectableMode(tBTM_BLE_CONN_MODE connectable_mode)
{
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
- BTM_TRACE_EVENT ("BTM_BleSetConnMode is_directed = %d ", is_directed);
+ BTM_TRACE_EVENT ("%s connectable_mode = %d ", __func__, connectable_mode);
if (!controller_get_interface()->supports_ble())
return BTM_ILLEGAL_VALUE;
- p_cb->directed_conn = is_directed;
+ p_cb->directed_conn = connectable_mode;
return btm_ble_set_connectability( p_cb->connectable_mode);
-
}
/*******************************************************************************
**
*******************************************************************************/
static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
- BD_ADDR_PTR p_addr_ptr,
- tBLE_ADDR_TYPE *p_init_addr_type,
+ BD_ADDR_PTR p_peer_addr_ptr,
+ tBLE_ADDR_TYPE *p_peer_addr_type,
tBLE_ADDR_TYPE *p_own_addr_type)
{
- UINT8 evt_type;
+ UINT8 evt_type, i = BTM_SEC_MAX_DEVICE_RECORDS;
+ tBTM_SEC_DEV_REC *p_dev_rec;
- UNUSED(p_own_addr_type);
+ evt_type = (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) ? \
+ ((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
+ : BTM_BLE_CONNECT_EVT;
- if ( p_cb->directed_conn)
+ if (evt_type == BTM_BLE_CONNECT_EVT)
{
- /* direct adv mode does not have privacy if privacy
- is not enabled or no reconn addr config */
+ evt_type = p_cb->directed_conn;
- *p_init_addr_type = p_cb->direct_bda.type;
- memcpy(p_addr_ptr, p_cb->direct_bda.bda, BD_ADDR_LEN);
- evt_type = BTM_BLE_CONNECT_DIR_EVT;
+ if ( p_cb->directed_conn == BTM_BLE_CONNECT_DIR_EVT ||
+ p_cb->directed_conn == BTM_BLE_CONNECT_LO_DUTY_DIR_EVT)
+ {
+
+#if BLE_PRIVACY_SPT == TRUE
+ /* for privacy 1.2, convert peer address as static, own address set as ID addr */
+ if (btm_cb.ble_ctr_cb.privacy_mode == BTM_PRIVACY_1_2 ||
+ btm_cb.ble_ctr_cb.privacy_mode == BTM_PRIVACY_MIXED)
+ {
+ /* only do so for bonded device */
+ if ((p_dev_rec = btm_find_or_alloc_dev (p_cb->direct_bda.bda)) != NULL &&
+ p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
+ {
+ btm_ble_enable_resolving_list();
+ memcpy(p_peer_addr_ptr, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
+ *p_peer_addr_type = p_dev_rec->ble.static_addr_type;
+ *p_own_addr_type = BLE_ADDR_RANDOM_ID;
+ return evt_type;
+ }
+ /* otherwise fall though as normal directed adv */
+ }
+#endif
+ /* direct adv mode does not have privacy, if privacy is not enabled */
+ *p_peer_addr_type = p_cb->direct_bda.type;
+ memcpy(p_peer_addr_ptr, p_cb->direct_bda.bda, BD_ADDR_LEN);
+ return evt_type;
+ }
}
- else /* undirect adv mode */
- {
- evt_type = BTM_BLE_CONNECT_EVT;
- /* may need to reset random address if privacy is enabled */
- if (btm_cb.ble_ctr_cb.privacy && /* own addr_type is random */
- !BTM_BLE_IS_RESOLVE_BDA(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr))
+ /* undirect adv mode or non-connectable mode*/
+#if BLE_PRIVACY_SPT == TRUE
+ /* when privacy 1.2 privacy only mode is used, or mixed mode */
+ if ((btm_cb.ble_ctr_cb.privacy_mode == BTM_PRIVACY_1_2 && p_cb->afp != AP_SCAN_CONN_ALL) ||
+ btm_cb.ble_ctr_cb.privacy_mode == BTM_PRIVACY_MIXED)
+ {
+ /* if enhanced privacy is required, set Identity address and matching IRK peer */
+ for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++)
{
- /* need to generate RRA and update random addresss in controller */
- btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low);
+ if ((btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE) != 0 &&
+ (btm_cb.sec_dev_rec[i].ble.in_controller_list & BTM_RESOLVING_LIST_BIT) != 0)
+ {
+ memcpy(p_peer_addr_ptr, btm_cb.sec_dev_rec[i].ble.static_addr, BD_ADDR_LEN);
+ *p_peer_addr_type = btm_cb.sec_dev_rec[i].ble.static_addr_type;
+ break;
+ }
}
+
+ if (i != BTM_SEC_MAX_DEVICE_RECORDS)
+ *p_own_addr_type = BLE_ADDR_RANDOM_ID;
+ else
+ /* resolving list is empty, not enabled */
+ *p_own_addr_type = BLE_ADDR_RANDOM;
}
- return evt_type;
+ /* privacy 1.1, or privacy 1.2, general discoverable/connectable mode, disable privacy in */
+ /* controller fall back to host based privacy */
+ else if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
+ {
+ *p_own_addr_type = BLE_ADDR_RANDOM;
+ btm_ble_disable_resolving_list ();
+ }
+#endif
+ /* if no privacy,do not set any peer address,*/
+ /* local address type go by global privacy setting */
+ return evt_type;
}
/*******************************************************************************
btm_ble_stop_adv();
- if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE)
- p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
+ p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type,
+ &own_addr_type);
/* update adv params */
btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
switch (evt_type)
{
case BTM_BLE_CONNECT_EVT:
+ case BTM_BLE_CONNECT_LO_DUTY_DIR_EVT:
*p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_FAST_INT_1;
break;
case BTM_BLE_DISCOVER_EVT:
*p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_FAST_INT_2;
break;
+
/* connectable directed event */
case BTM_BLE_CONNECT_DIR_EVT:
*p_adv_int_min = BTM_BLE_GAP_ADV_DIR_MIN_INT;
}
return;
}
+
/*******************************************************************************
**
** Function btm_ble_update_dmt_flag_bits
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT16 mode = (combined_mode & BTM_BLE_DISCOVERABLE_MASK);
UINT8 new_mode = BTM_BLE_ADV_ENABLE;
- UINT8 evt_type = (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) ? \
- ((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
- : BTM_BLE_CONNECT_EVT;
+ UINT8 evt_type;
tBTM_STATUS status = BTM_SUCCESS;
BD_ADDR p_addr_ptr= {0};
tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC,
own_addr_type = p_addr_cb->own_addr_type;
UINT16 adv_int_min, adv_int_max;
- BTM_TRACE_EVENT ("btm_ble_set_discoverability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
+ BTM_TRACE_EVENT ("%s mode=0x%0x combined_mode=0x%x", __FUNCTION__, mode, combined_mode);
/*** Check mode parameter ***/
if (mode > BTM_BLE_MAX_DISCOVERABLE)
return(BTM_ILLEGAL_VALUE);
- btm_ble_set_adv_flag (btm_cb.btm_inq_vars.connectable_mode, combined_mode);
+ p_cb->discoverable_mode = mode;
evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
/* update adv params if start advertising */
BTM_TRACE_EVENT ("evt_type=0x%x p-cb->evt_type=0x%x ", evt_type, p_cb->evt_type);
- if (new_mode == BTM_BLE_ADV_ENABLE &&
- (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type || !p_cb->fast_adv_on))
+ if (new_mode == BTM_BLE_ADV_ENABLE)
{
- btm_ble_stop_adv();
+ btm_ble_set_adv_flag (btm_cb.btm_inq_vars.connectable_mode, combined_mode);
- /* update adv params */
- if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
- adv_int_max,
- evt_type,
- own_addr_type,
- init_addr_type,
- p_addr_ptr,
- p_cb->adv_chnl_map,
- p_cb->afp))
-
- status = BTM_NO_RESOURCES;
- else
+ if (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type
+ || !p_cb->fast_adv_on)
{
- p_cb->evt_type = evt_type;
- p_cb->adv_addr_type = own_addr_type;
+ btm_ble_stop_adv();
+
+ /* update adv params */
+ if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
+ adv_int_max,
+ evt_type,
+ own_addr_type,
+ init_addr_type,
+ p_addr_ptr,
+ p_cb->adv_chnl_map,
+ p_cb->afp))
+ {
+ status = BTM_NO_RESOURCES;
+ }
+ else
+ {
+ p_cb->evt_type = evt_type;
+ p_cb->adv_addr_type = own_addr_type;
+ }
}
-
}
if (status == BTM_SUCCESS && p_cb->adv_mode != new_mode)
tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
UINT16 mode = (combined_mode & BTM_BLE_CONNECTABLE_MASK);
UINT8 new_mode = BTM_BLE_ADV_ENABLE;
- UINT8 evt_type = (p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
+ UINT8 evt_type;
tBTM_STATUS status = BTM_SUCCESS;
BD_ADDR p_addr_ptr = {0};
- tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC,
+ tBLE_ADDR_TYPE peer_addr_type = BLE_ADDR_PUBLIC,
own_addr_type = p_addr_cb->own_addr_type;
UINT16 adv_int_min, adv_int_max;
- BTM_TRACE_EVENT ("btm_ble_set_connectability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
+ BTM_TRACE_EVENT ("%s mode=0x%0x combined_mode=0x%x", __FUNCTION__, mode, combined_mode);
/*** Check mode parameter ***/
if (mode > BTM_BLE_MAX_CONNECTABLE)
p_cb->connectable_mode = mode;
- btm_ble_set_adv_flag (combined_mode, btm_cb.btm_inq_vars.discoverable_mode);
-
- evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
+ evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &peer_addr_type, &own_addr_type);
if (mode == BTM_BLE_NON_CONNECTABLE && p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE)
new_mode = BTM_BLE_ADV_DISABLE;
btu_stop_timer(&p_cb->fast_adv_timer);
/* update adv params if needed */
- if ((p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type || !p_cb->fast_adv_on))
+ if (new_mode == BTM_BLE_ADV_ENABLE)
{
- btm_ble_stop_adv();
-
- if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
- adv_int_max,
- evt_type,
- own_addr_type,
- init_addr_type,
- p_addr_ptr,
- p_cb->adv_chnl_map,
- p_cb->afp))
- status = BTM_NO_RESOURCES;
- else
+ btm_ble_set_adv_flag (combined_mode, btm_cb.btm_inq_vars.discoverable_mode);
+ if (p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type
+ || !p_cb->fast_adv_on)
{
- p_cb->evt_type = evt_type;
- p_cb->adv_addr_type = own_addr_type;
+ btm_ble_stop_adv();
+
+ if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
+ adv_int_max,
+ evt_type,
+ own_addr_type,
+ peer_addr_type,
+ p_addr_ptr,
+ p_cb->adv_chnl_map,
+ p_cb->afp))
+ {
+ status = BTM_NO_RESOURCES;
+ }
+ else
+ {
+ p_cb->evt_type = evt_type;
+ p_cb->adv_addr_type = own_addr_type;
+ }
}
}
else
status = btm_ble_stop_adv();
}
+
if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
{
p_cb->fast_adv_on = TRUE;
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
/* enable IRK list */
- btm_ble_vendor_irk_list_known_dev (TRUE);
+ btm_ble_enable_resolving_list_for_platform();
#endif
status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
}
/*******************************************************************************
**
+** Function btm_clear_all_pending_le_entry
+**
+** Description This function is called to clear all LE pending entry in
+** inquiry database.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_clear_all_pending_le_entry(void)
+{
+ UINT16 xx;
+ tINQ_DB_ENT *p_ent = btm_cb.btm_inq_vars.inq_db;
+
+ for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
+ {
+ /* mark all pending LE entry as unused if an LE only device has scan response outstanding */
+ if ((p_ent->in_use) &&
+ (p_ent->inq_info.results.device_type == BT_DEVICE_TYPE_BLE) &&
+ !p_ent->scan_rsp)
+ p_ent->in_use = FALSE;
+ }
+}
+
+/*******************************************************************************
+**
** Function btm_send_sel_conn_callback
**
** Description send selection connection request callback.
BOOLEAN match = FALSE;
#endif
+ /* Only process the results if the inquiry is still active */
+ if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
+ return;
+
/* Extract the number of reports in this event. */
STREAM_TO_UINT8(num_reports, p);
STREAM_TO_UINT8 (addr_type, p);
STREAM_TO_BDADDR (bda, p);
-#ifdef BTM_BLE_PC_ADV_TEST_MODE /* For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include */
- if (BTM_BLE_PC_ADV_TEST_MODE) /* For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode */
- {
- if (btm_cb.ble_ctr_cb.p_scan_req_cback)
- (*btm_cb.ble_ctr_cb.p_scan_req_cback)(bda, addr_type, evt_type);
- }
-#endif
-
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
- /* map address to security record */
- btm_public_addr_to_random_pseudo(bda, &addr_type);
- BTM_TRACE_DEBUG("new address: %02x:%02x:%02x:%02x:%02x:%02x",
- bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
-#endif
+ /* map address to security record */
+ match = btm_identity_addr_to_random_pseudo(bda, &addr_type, FALSE);
- /* Only process the results if the inquiry is still active */
- if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
- return;
-
- BTM_TRACE_DEBUG("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x",
+ BTM_TRACE_DEBUG("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x",
bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
-#if SMP_INCLUDED == TRUE
/* always do RRA resolution on host */
if (!match && BTM_BLE_IS_RESOLVE_BDA(bda))
{
}
else
#endif
-#endif
- {
btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
- }
STREAM_TO_UINT8(data_len, p);
tBTM_STATUS status = BTM_CMD_STARTED;
/* start scan, disable duplicate filtering */
- if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, filter_enable)) {
+ if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, filter_enable))
+ {
status = BTM_NO_RESOURCES;
- btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN;
}
else
{
- btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_SCAN;
if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI)
btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
else
rt = (*p_handler) (BTM_BLE_STATE_SCAN_ADV_BIT);
break;
+ case BTM_BLE_CONNECT_LO_DUTY_DIR_EVT:
+ rt = (*p_handler) (BTM_BLE_STATE_LO_DUTY_DIR_ADV_BIT);
+ break;
+
default:
BTM_TRACE_ERROR("unknown adv event : %d", adv_evt);
break;
if (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type))
return BTM_WRONG_MODE;
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ /* When privacy 1.2 goes into general connection/discoverable mode, */
+ /* disable controller privacy */
+ if (p_cb->afp == AP_SCAN_CONN_ALL && btm_cb.ble_ctr_cb.privacy_mode == BTM_PRIVACY_1_2)
+ btm_ble_disable_resolving_list();
+ else
+ /* enable resolving list is desired*/
+ btm_ble_enable_resolving_list_for_platform();
+#endif
+
if (p_cb->afp != AP_SCAN_CONN_ALL)
{
btm_execute_wl_dev_operation();
if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
{
- if (p_cb->afp != AP_SCAN_CONN_ALL)
- btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV;
-
p_cb->adv_mode = BTM_BLE_ADV_ENABLE;
-
+ btm_ble_adv_states_operation(btm_ble_set_topology_mask, p_cb->evt_type);
rt = BTM_SUCCESS;
}
else
}
return rt;
}
+
/*******************************************************************************
**
** Function btm_ble_stop_adv
/*******************************************************************************
**
-** Function btm_ble_set_topology_mask
-**
-** Description set BLE topology mask
-**
-** Returns TRUE is request is allowed, FALSE otherwise.
-**
-*******************************************************************************/
-BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state_mask)
-{
- BOOLEAN rt = TRUE;
-
- request_state_mask &= BTM_BLE_STATE_ALL_MASK;
-
- btm_cb.ble_ctr_cb.cur_states |= request_state_mask;
-
- return rt;
-}
-/*******************************************************************************
-**
-** Function btm_ble_clear_topology_mask
-**
-** Description Clear BLE topology bit mask
-**
-** Returns TRUE is request is allowed, FALSE otherwise.
-**
-*******************************************************************************/
-BOOLEAN btm_ble_clear_topology_mask (tBTM_BLE_STATE_MASK request_state_mask)
-{
- request_state_mask &= BTM_BLE_STATE_ALL_MASK;
-
- btm_cb.ble_ctr_cb.cur_states &= ~request_state_mask;
-
- return TRUE;
-}
-/*******************************************************************************
-**
-** Function btm_ble_update_mode_operation
-**
-** Description This function update the GAP role operation when a link status
-** is updated.
-**
-** Returns void
-**
-*******************************************************************************/
-void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 status)
-{
- tACL_CONN *pa = &btm_cb.acl_db[0];
- UINT16 xx;
- UINT16 mask = BTM_BLE_STATE_ALL_CONN_MASK;
-
- UNUSED(bd_addr);
-
- if (link_role == HCI_ROLE_SLAVE)
- {
- btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
- /* clear all adv states */
- mask |= BTM_BLE_STATE_ALL_ADV_MASK;
- }
-
- btm_ble_clear_topology_mask (mask);
-
- /* check the device link role maps */
- for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
- {
- if (pa->in_use && pa->transport == BT_TRANSPORT_LE)
- {
- if (pa->link_role == HCI_ROLE_MASTER)
- btm_ble_set_topology_mask (BTM_BLE_STATE_MASTER_BIT);
- else
- btm_ble_set_topology_mask (BTM_BLE_STATE_SLAVE_BIT);
- }
- }
-
- if (btm_cb.cmn_ble_vsc_cb.adv_inst_max == 0 &&
- btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
- {
- btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
- }
-
- if (btm_ble_get_conn_st() == BLE_CONN_IDLE && status != HCI_ERR_HOST_REJECT_RESOURCES)
- {
- if (!btm_send_pending_direct_conn())
- {
- btm_ble_resume_bg_conn();
- }
- }
-}
-
-/*******************************************************************************
-**
** Function btm_ble_start_slow_adv
**
** Description Restart adv with slow adv interval
*******************************************************************************/
static void btm_ble_start_slow_adv (void)
{
- tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
- BD_ADDR p_addr_ptr= {0};
+ tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
{
+ tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+ BD_ADDR p_addr_ptr = {0};
+ tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
+ tBLE_ADDR_TYPE own_addr_type = p_addr_cb->own_addr_type;
+
btm_ble_stop_adv();
- btsnd_hcic_ble_write_adv_params (BTM_BLE_GAP_ADV_SLOW_INT,
- BTM_BLE_GAP_ADV_SLOW_INT,
- p_cb->evt_type,
- p_cb->adv_addr_type,
- btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,/* slow adv
- mode never goes into directed adv */
- p_addr_ptr,
- p_cb->adv_chnl_map,
- p_cb->afp);
+ p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type,
+ &own_addr_type);
+
+ /* slow adv mode never goes into directed adv */
+ btsnd_hcic_ble_write_adv_params (BTM_BLE_GAP_ADV_SLOW_INT, BTM_BLE_GAP_ADV_SLOW_INT,
+ p_cb->evt_type, own_addr_type,
+ init_addr_type, p_addr_ptr,
+ p_cb->adv_chnl_map, p_cb->afp);
btm_ble_start_adv();
}
BTM_TRACE_EVENT ("btm_ble_read_remote_features_complete ");
STREAM_TO_UINT8(status, p);
- /* if LE read remote feature failed, expect disconnect complete to be received */
- if (status == HCI_SUCCESS)
+
+ // if LE read remote feature failed for HCI_ERR_CONN_FAILED_ESTABLISHMENT,
+ // expect disconnect complete to be received
+ if (status != HCI_ERR_CONN_FAILED_ESTABLISHMENT)
{
STREAM_TO_UINT16 (handle, p);
/*******************************************************************************
**
+** Function btm_ble_set_topology_mask
+**
+** Description set BLE topology mask
+**
+** Returns TRUE is request is allowed, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state_mask)
+{
+ request_state_mask &= BTM_BLE_STATE_ALL_MASK;
+ btm_cb.ble_ctr_cb.cur_states |= (request_state_mask & BTM_BLE_STATE_ALL_MASK);
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_clear_topology_mask
+**
+** Description Clear BLE topology bit mask
+**
+** Returns TRUE is request is allowed, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_clear_topology_mask (tBTM_BLE_STATE_MASK request_state_mask)
+{
+ request_state_mask &= BTM_BLE_STATE_ALL_MASK;
+ btm_cb.ble_ctr_cb.cur_states &= ~request_state_mask;
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_update_link_topology_mask
+**
+** Description This function update the link topology mask
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_update_link_topology_mask(UINT8 link_role, BOOLEAN increase)
+{
+ btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_CONN_MASK);
+
+ if (increase)
+ btm_cb.ble_ctr_cb.link_count[link_role]++;
+ else if (btm_cb.ble_ctr_cb.link_count[link_role] > 0)
+ btm_cb.ble_ctr_cb.link_count[link_role]--;
+
+ if (btm_cb.ble_ctr_cb.link_count[HCI_ROLE_MASTER])
+ btm_ble_set_topology_mask (BTM_BLE_STATE_MASTER_BIT);
+
+ if (btm_cb.ble_ctr_cb.link_count[HCI_ROLE_SLAVE])
+ btm_ble_set_topology_mask(BTM_BLE_STATE_SLAVE_BIT);
+
+ if (link_role == HCI_ROLE_SLAVE && increase)
+ {
+ btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+ /* make device fall back into undirected adv mode by default */
+ btm_cb.ble_ctr_cb.inq_var.directed_conn = BTM_BLE_CONNECT_EVT;
+ /* clear all adv states */
+ btm_ble_clear_topology_mask(BTM_BLE_STATE_ALL_ADV_MASK);
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_update_mode_operation
+**
+** Description This function update the GAP role operation when a link status
+** is updated.
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 status)
+{
+ if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
+ {
+ btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+ /* make device fall back into undirected adv mode by default */
+ btm_cb.ble_ctr_cb.inq_var.directed_conn = BTM_BLE_CONNECT_EVT;
+ /* clear all adv states */
+ btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK);
+ }
+
+ if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
+ {
+ btm_ble_set_connectability(btm_cb.btm_inq_vars.connectable_mode |
+ btm_cb.ble_ctr_cb.inq_var.connectable_mode);
+ }
+
+ /* when no connection is attempted, and controller is not rejecting last request
+ due to resource limitation, start next direct connection or background connection
+ now in order */
+ if (btm_ble_get_conn_st() == BLE_CONN_IDLE && status != HCI_ERR_HOST_REJECT_RESOURCES &&
+ !btm_send_pending_direct_conn())
+ {
+ btm_ble_resume_bg_conn();
+ }
+}
+
+/*******************************************************************************
+**
** Function btm_ble_init
**
** Description Initialize the control block variable values.
p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT;
#if BLE_VND_INCLUDED == FALSE
- btm_ble_vendor_init(BTM_CS_IRK_LIST_MAX);
btm_ble_adv_filter_init();
#endif
}
#define BTM_BLE_IS_OBS_ACTIVE(x) ((x) & BTM_LE_OBSERVE_ACTIVE)
#define BTM_BLE_IS_SEL_CONN_ACTIVE(x) ((x) & BTM_LE_SELECT_CONN_ACTIVE)
+/* BLE ADDR type ID bit */
+#define BLE_ADDR_TYPE_ID_BIT 0x02
+
typedef struct
{
UINT16 data_mask;
UINT8 evt_type;
UINT8 adv_mode;
tBLE_BD_ADDR direct_bda;
- BOOLEAN directed_conn;
+ tBTM_BLE_EVT directed_conn;
BOOLEAN fast_adv_on;
TIMER_LIST_ENT fast_adv_timer;
#define BTM_BLE_STATE_ALL_SCAN_MASK (BTM_BLE_STATE_PASSIVE_SCAN_BIT|BTM_BLE_STATE_ACTIVE_SCAN_BIT)
#define BTM_BLE_STATE_ALL_CONN_MASK (BTM_BLE_STATE_MASTER_BIT|BTM_BLE_STATE_SLAVE_BIT)
+#ifndef BTM_LE_RESOLVING_LIST_MAX
+#define BTM_LE_RESOLVING_LIST_MAX 0x20
+#endif
+
+typedef struct
+{
+ BD_ADDR *resolve_q_random_pseudo;
+ UINT8 *resolve_q_action;
+ UINT8 q_next;
+ UINT8 q_pending;
+} tBTM_BLE_RESOLVE_Q;
+
typedef struct
{
BOOLEAN in_use;
BD_ADDR bd_addr;
UINT8 attr;
}tBTM_BLE_WL_OP;
+
+/* BLE privacy mode */
+#define BTM_PRIVACY_NONE 0 /* BLE no privacy */
+#define BTM_PRIVACY_1_1 1 /* BLE privacy 1.1, do not support privacy 1.0 */
+#define BTM_PRIVACY_1_2 2 /* BLE privacy 1.2 */
+#define BTM_PRIVACY_MIXED 3 /* BLE privacy mixed mode, broadcom propietary mode */
+typedef UINT8 tBTM_PRIVACY_MODE;
+
+/* data length change event callback */
+typedef void (tBTM_DATA_LENGTH_CHANGE_CBACK) (UINT16 max_tx_length, UINT16 max_rx_length);
+
/* Define BLE Device Management control structure
*/
typedef struct
UINT16 scan_int;
UINT16 scan_win;
tBTM_BLE_SEL_CBACK *p_select_cback;
- TIMER_LIST_ENT scan_param_idle_timer;
/* white list information */
UINT8 num_empty_filter; /* Number of entries in white list */
tBTM_LE_RANDOM_CB addr_mgnt_cb;
BOOLEAN enabled;
- BOOLEAN privacy; /* local privacy enabled or disabled */
- tBTM_BLE_WL_OP wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
-#ifdef BTM_BLE_PC_ADV_TEST_MODE
- tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback;
+#if BLE_PRIVACY_SPT == TRUE
+ BOOLEAN mixed_mode; /* privacy 1.2 mixed mode is on or not */
+ tBTM_PRIVACY_MODE privacy_mode; /* privacy mode */
+ UINT8 resolving_list_avail_size; /* resolving list available size */
+ tBTM_BLE_RESOLVE_Q resolving_list_pend_q;
#endif
+ tBTM_BLE_WL_OP wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
/* current BLE link state */
tBTM_BLE_STATE_MASK cur_states; /* bit mask of tBTM_BLE_STATE */
-
+ UINT8 link_count[2]; /* total link count master and slave*/
} tBTM_BLE_CB;
#ifdef __cplusplus
extern tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode);
extern tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode);
extern tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration);
-extern void btm_ble_dir_adv_tout(void);
+extern void btm_ble_stop_scan(void);
+extern void btm_clear_all_pending_le_entry(void);
extern void btm_ble_stop_scan();
extern void btm_ble_stop_inquiry(void);
extern void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched);
extern void btm_ble_read_remote_features_complete(UINT8 *p);
extern void btm_ble_write_adv_enable_complete(UINT8 * p);
-extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced);
extern void btm_read_ble_local_supported_states_complete(UINT8 *p, UINT16 evt_len);
extern tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
extern void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
extern BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr);
extern BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr);
extern void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy);
-extern void btm_update_scan_filter_policy(tBTM_BLE_AFP adv_policy);
+extern void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy);
extern void btm_ble_clear_white_list (void);
+extern void btm_read_white_list_size_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_add_2_white_list_complete(UINT8 status);
+extern void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len);
/* background connection function */
extern void btm_ble_suspend_bg_conn(void);
extern void btm_write_dir_conn_wl(BD_ADDR target_addr);
extern void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bda, UINT8 status);
extern BOOLEAN btm_execute_wl_dev_operation(void);
+extern void btm_ble_update_link_topology_mask(UINT8 role, BOOLEAN increase);
/* direct connection utility */
extern BOOLEAN btm_send_pending_direct_conn(void);
extern void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback);
extern void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p);
extern void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p);
-extern void btm_ble_update_reconnect_address(BD_ADDR bd_addr);
extern void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p);
+/* privacy function */
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+/* BLE address mapping with CS feature */
+extern BOOLEAN btm_identity_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN refresh);
+extern BOOLEAN btm_random_pseudo_to_identity_addr(BD_ADDR random_pseudo, UINT8 *p_static_addr_type);
+extern void btm_ble_refresh_peer_resolvable_private_addr(BD_ADDR pseudo_bda, BD_ADDR rra, UINT8 rra_type);
+extern void btm_ble_refresh_local_resolvable_private_addr(BD_ADDR pseudo_addr, BD_ADDR local_rpa);
+extern void btm_ble_read_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len) ;
+extern void btm_ble_remove_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_add_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_clear_resolving_list_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_read_ble_resolving_list_size_complete (UINT8 *p, UINT16 evt_len);
+extern void btm_ble_enable_resolving_list(void);
+extern void btm_ble_disable_resolving_list(void);
+extern void btm_ble_enable_resolving_list_for_platform (void);
+extern void btm_ble_resolving_list_init(UINT8 max_irk_list_sz);
+extern void btm_ble_resolving_list_cleanup(void);
+#endif
+
extern void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst);
extern void btm_ble_multi_adv_init(void);
extern void* btm_ble_multi_adv_get_ref(UINT8 inst_id);
extern BOOLEAN btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state);
extern BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state);
-/* BLE address mapping with CS feature */
-extern BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type);
-extern BOOLEAN btm_random_pseudo_to_public(BD_ADDR random_pseudo, UINT8 *p_static_addr_type);
-extern void btm_ble_refresh_rra(BD_ADDR pseudo_bda, BD_ADDR rra);
-
#if BTM_BLE_CONFORMANCE_TESTING == TRUE
extern void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc);
extern void btm_ble_set_test_mac_value (BOOLEAN enable, UINT8 *p_test_mac_val);
UINT16_TO_STREAM (pp, p_params->adv_int_max);
UINT8_TO_STREAM (pp, p_params->adv_type);
-#if BLE_PRIVACY_SPT
- if (btm_cb.ble_ctr_cb.privacy)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
{
UINT8_TO_STREAM (pp, BLE_ADDR_RANDOM);
BDADDR_TO_STREAM (pp, p_inst->rpa);
{
p_inst->adv_evt = p_params->adv_type;
-#if BLE_PRIVACY_SPT
- if (btm_cb.ble_ctr_cb.privacy)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
{
/* start timer */
p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
if ((idx = btm_handle_to_acl_index(conn_handle)) != MAX_L2CAP_LINKS)
{
- if (btm_cb.ble_ctr_cb.privacy &&
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE &&
adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst != BTM_BLE_MULTI_ADV_DEFAULT_STD)
{
memcpy(btm_cb.acl_db[idx].conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa,
BD_ADDR_LEN);
}
+#endif
}
if (adv_inst < BTM_BleMaxMultiAdvInstanceCount() &&
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains functions for BLE controller based privacy.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bt_target.h"
+
+#if (BLE_INCLUDED == TRUE && BLE_PRIVACY_SPT == TRUE)
+#include "bt_types.h"
+#include "hcimsgs.h"
+#include "btu.h"
+#include "vendor_hcidefs.h"
+#include "btm_int.h"
+#include "device/include/controller.h"
+
+/* RPA offload VSC specifics */
+#define BTM_BLE_META_IRK_ENABLE 0x01
+#define BTM_BLE_META_ADD_IRK_ENTRY 0x02
+#define BTM_BLE_META_REMOVE_IRK_ENTRY 0x03
+#define BTM_BLE_META_CLEAR_IRK_LIST 0x04
+#define BTM_BLE_META_READ_IRK_ENTRY 0x05
+#define BTM_BLE_META_CS_RESOLVE_ADDR 0x00000001
+#define BTM_BLE_IRK_ENABLE_LEN 2
+
+#define BTM_BLE_META_ADD_IRK_LEN 24
+#define BTM_BLE_META_REMOVE_IRK_LEN 8
+#define BTM_BLE_META_CLEAR_IRK_LEN 1
+#define BTM_BLE_META_READ_IRK_LEN 2
+#define BTM_BLE_META_ADD_WL_ATTR_LEN 9
+
+/*******************************************************************************
+** Functions implemented controller based privacy using Resolving List
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function btm_ble_enq_resolving_list_pending
+**
+** Description add target address into resolving pending operation queue
+**
+** Parameters target_bda: target device address
+** add_entry: TRUE for add entry, FALSE for remove entry
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_enq_resolving_list_pending(BD_ADDR psuedo_bda, UINT8 op_code)
+{
+ tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+ memcpy(p_q->resolve_q_random_pseudo[p_q->q_next], psuedo_bda, BD_ADDR_LEN);
+ p_q->resolve_q_action[p_q->q_next] = op_code;
+
+ p_q->q_next ++;
+ p_q->q_next %= controller_get_interface()->get_ble_resolving_list_max_size();
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_brcm_find_resolving_pending_entry
+**
+** Description check to see if the action is in pending list
+**
+** Parameters TRUE: action pending;
+** FALSE: new action
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN btm_ble_brcm_find_resolving_pending_entry(BD_ADDR psuedo_addr, UINT8 action)
+{
+ tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+ for (UINT8 i = p_q->q_pending; i != p_q->q_next; )
+ {
+ if (memcmp(p_q->resolve_q_random_pseudo[i], psuedo_addr, BD_ADDR_LEN) == 0 &&
+ action == p_q->resolve_q_action[i])
+ return TRUE;
+
+ i ++;
+ i %= controller_get_interface()->get_ble_resolving_list_max_size();
+ }
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_deq_resolving_pending
+**
+** Description dequeue target address from resolving pending operation queue
+**
+** Parameters psuedo_addr: psuedo_addr device address
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN btm_ble_deq_resolving_pending(BD_ADDR psuedo_addr)
+{
+ tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+ if (p_q->q_next != p_q->q_pending)
+ {
+ memcpy(psuedo_addr, p_q->resolve_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
+ memset(p_q->resolve_q_random_pseudo[p_q->q_pending], 0, BD_ADDR_LEN);
+
+ p_q->q_pending ++;
+ p_q->q_pending %= controller_get_interface()->get_ble_resolving_list_max_size();
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_find_resolving_list_entry
+**
+** Description find the device record if the pseudo address is currently in
+** the resolving list
+**
+** Returns pointer to the security device record; NULL otherwise
+**
+*******************************************************************************/
+tBTM_SEC_DEV_REC * btm_ble_find_resolving_list_entry(BD_ADDR pseudo_bda)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+
+ for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec++)
+ {
+ if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) &&
+ (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
+ memcmp(p_dev_rec->bd_addr, pseudo_bda, BD_ADDR_LEN) == 0)
+ {
+ return p_dev_rec ;
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_update_resolving_list
+**
+** Description update resolving list entry in host maintained record
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_update_resolving_list(BD_ADDR pseudo_bda, BOOLEAN add)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (pseudo_bda);
+
+ if (p_dev_rec == NULL)
+ return;
+
+ if (add)
+ {
+ p_dev_rec->ble.in_controller_list |= BTM_RESOLVING_LIST_BIT;
+ /* set resolving list entry index : = max- available - 1*/
+ p_dev_rec->ble.resolving_list_index =
+ controller_get_interface()->get_ble_resolving_list_max_size() -
+ btm_cb.ble_ctr_cb.resolving_list_avail_size - 1;
+ } else {
+ p_dev_rec->ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
+ p_dev_rec->ble.resolving_list_index = 0;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_clear_resolving_list_complete
+**
+** Description This function is called when command complete for
+** clear resolving list
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_clear_resolving_list_complete(UINT8 *p, UINT16 evt_len)
+{
+ UINT8 status;
+ STREAM_TO_UINT8(status, p);
+
+ BTM_TRACE_DEBUG("%s status = %d", __func__, status);
+
+ /* standard HCI status only have one status byte, if greater than 3, VSC complete received */
+ if (evt_len >= 3)
+ {
+ /* VSC complete has one extra byte for op code and list size, skip it here */
+ p ++;
+ /* updated the available list size, and current list size */
+ UINT8 max_resolving_list_size;
+ STREAM_TO_UINT8(max_resolving_list_size, p);
+ controller_get_interface()->set_ble_resolving_list_max_size(max_resolving_list_size);
+ }
+
+ if (status == HCI_SUCCESS)
+ {
+ btm_cb.ble_ctr_cb.resolving_list_avail_size =
+ controller_get_interface()->get_ble_resolving_list_max_size();
+
+ BTM_TRACE_DEBUG("%s resolving_list_avail_size = %d",
+ __func__, btm_cb.ble_ctr_cb.resolving_list_avail_size);
+
+ for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++)
+ btm_cb.sec_dev_rec[i].ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_add_resolving_list_entry_complete
+**
+** Description This function is called when command complete for
+** add resolving list entry
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_add_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
+{
+ UINT8 status;
+ STREAM_TO_UINT8(status, p);
+
+ BTM_TRACE_DEBUG("%s status = %d", __func__, status);
+
+ BD_ADDR pseudo_bda;
+ if (!btm_ble_deq_resolving_pending( pseudo_bda))
+ {
+ BTM_TRACE_DEBUG("no pending resolving list operation");
+ return;
+ }
+
+ if (status == HCI_SUCCESS)
+ {
+ /* privacy 1.2 command complete does not have these extra byte */
+ if (evt_len > 2)
+ {
+ /* VSC complete has one extra byte for op code, skip it here */
+ p ++;
+ STREAM_TO_UINT8(btm_cb.ble_ctr_cb.resolving_list_avail_size, p);
+ }
+ else
+ btm_cb.ble_ctr_cb.resolving_list_avail_size --;
+
+ }
+ else if (status == HCI_ERR_MEMORY_FULL) /* BT_ERROR_CODE_MEMORY_CAPACITY_EXCEEDED */
+ {
+ btm_cb.ble_ctr_cb.resolving_list_avail_size = 0;
+ BTM_TRACE_DEBUG("%s Resolving list Full ", __func__);
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_remove_resolving_list_entry_complete
+**
+** Description This function is called when command complete for
+** remove resolving list entry
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_remove_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
+{
+ BD_ADDR pseudo_bda;
+
+ UINT8 status;
+ STREAM_TO_UINT8 (status, p);
+
+ BTM_TRACE_DEBUG("%s status = %d", __func__, status);
+
+ if (!btm_ble_deq_resolving_pending(pseudo_bda))
+ {
+ BTM_TRACE_ERROR("%s no pending resolving list operation", __func__);
+ return;
+ }
+
+ if (status == HCI_SUCCESS)
+ {
+ /* proprietary: spec does not have these extra bytes */
+ if (evt_len > 2)
+ {
+ p ++; /* skip opcode */
+ STREAM_TO_UINT8(btm_cb.ble_ctr_cb.resolving_list_avail_size, p);
+ }
+ else
+ btm_cb.ble_ctr_cb.resolving_list_avail_size ++;
+
+ }
+}
+/*******************************************************************************
+**
+** Function btm_ble_read_resolving_list_entry_complete
+**
+** Description This function is called when command complete for
+** remove resolving list entry
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_read_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
+{
+ UINT8 status, rra_type = BTM_BLE_ADDR_PSEUDO;
+ BD_ADDR rra, pseudo_bda;
+
+ STREAM_TO_UINT8 (status, p);
+
+ BTM_TRACE_DEBUG("%s status = %d", __func__, status);
+
+ if (!btm_ble_deq_resolving_pending(pseudo_bda))
+ {
+ BTM_TRACE_ERROR("no pending resolving list operation");
+ return;
+ }
+
+ if (status == HCI_SUCCESS)
+ {
+ /* proprietary spec has extra bytes */
+ if (evt_len > 8)
+ {
+ p += (2 + 16 + 1 + 6); /* skip subcode, index, IRK value, address type, identity addr type */
+ STREAM_TO_BDADDR(rra, p);
+
+ BTM_TRACE_ERROR("%s peer_addr: %02x:%02x:%02x:%02x:%02x:%02x",
+ __func__, rra[0], rra[1], rra[2], rra[3], rra[4], rra[5]);
+ }
+ else
+ {
+ STREAM_TO_BDADDR(rra, p);
+ }
+ btm_ble_refresh_peer_resolvable_private_addr(pseudo_bda, rra, rra_type);
+ }
+}
+/*******************************************************************************
+ VSC that implement controller based privacy
+********************************************************************************/
+/*******************************************************************************
+**
+** Function btm_ble_resolving_list_vsc_op_cmpl
+**
+** Description IRK operation VSC complete handler
+**
+** Parameters
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_resolving_list_vsc_op_cmpl (tBTM_VSC_CMPL *p_params)
+{
+ UINT8 *p = p_params->p_param_buf, op_subcode;
+ UINT16 evt_len = p_params->param_len;
+
+ op_subcode = *(p + 1);
+
+ BTM_TRACE_DEBUG("%s op_subcode = %d", __func__, op_subcode);
+
+ if (op_subcode == BTM_BLE_META_CLEAR_IRK_LIST)
+ {
+ btm_ble_clear_resolving_list_complete(p, evt_len);
+ }
+ else if (op_subcode == BTM_BLE_META_ADD_IRK_ENTRY)
+ {
+ btm_ble_add_resolving_list_entry_complete(p, evt_len);
+ }
+ else if (op_subcode == BTM_BLE_META_REMOVE_IRK_ENTRY)
+ {
+ btm_ble_remove_resolving_list_entry_complete(p, evt_len);
+ }
+ else if (op_subcode == BTM_BLE_META_READ_IRK_ENTRY)
+ {
+ btm_ble_read_resolving_list_entry_complete(p, evt_len);
+ }
+ else if (op_subcode == BTM_BLE_META_IRK_ENABLE)
+ {
+ /* RPA offloading enable/disabled */
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_remove_resolving_list_entry
+**
+** Description This function to remove an IRK entry from the list
+**
+** Parameters ble_addr_type: address type
+** ble_addr: LE adddress
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_remove_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ tBTM_STATUS st = BTM_NO_RESOURCES;
+
+ if (controller_get_interface()->supports_ble_privacy())
+ {
+ if (btsnd_hcic_ble_rm_device_resolving_list (p_dev_rec->ble.static_addr_type,
+ p_dev_rec->ble.static_addr))
+ st = BTM_CMD_STARTED;
+ } else {
+ UINT8 param[20]= {0};
+ UINT8 *p = param;
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_REMOVE_IRK_ENTRY);
+ UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
+ BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
+
+ st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_REMOVE_IRK_LEN,
+ param,
+ btm_ble_resolving_list_vsc_op_cmpl);
+ }
+
+ if (st == BTM_CMD_STARTED)
+ {
+ btm_ble_enq_resolving_list_pending( p_dev_rec->bd_addr, BTM_BLE_META_REMOVE_IRK_ENTRY);
+ }
+
+ return st;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_clear_resolving_list
+**
+** Description This function clears the resolving list
+**
+** Parameters None.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_clear_resolving_list(void)
+{
+ tBTM_STATUS st = BTM_NO_RESOURCES;
+
+ if (controller_get_interface()->supports_ble_privacy())
+ {
+ if (btsnd_hcic_ble_clear_resolving_list())
+ st = BTM_SUCCESS;
+ }
+ else
+ {
+ UINT8 param[20] = {0};
+ UINT8 *p = param;
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_CLEAR_IRK_LIST);
+ st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_CLEAR_IRK_LEN,
+ param,
+ btm_ble_resolving_list_vsc_op_cmpl);
+ }
+
+ return st;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_read_resolving_list_entry
+**
+** Description This function read an IRK entry by index
+**
+** Parameters entry index.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ tBTM_STATUS st = BTM_NO_RESOURCES;
+
+ if (!(p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT))
+ return BTM_WRONG_MODE;
+
+ if (controller_get_interface()->supports_ble_privacy())
+ {
+ if (btsnd_hcic_ble_read_resolvable_addr_peer(p_dev_rec->ble.static_addr_type,
+ p_dev_rec->ble.static_addr))
+ st = BTM_CMD_STARTED;
+ }
+ else
+ {
+ UINT8 param[20] = {0};
+ UINT8 *p = param;
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_READ_IRK_ENTRY);
+ UINT8_TO_STREAM(p, p_dev_rec->ble.resolving_list_index);
+
+ st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_READ_IRK_LEN,
+ param,
+ btm_ble_resolving_list_vsc_op_cmpl);
+ }
+
+ if (st == BTM_CMD_STARTED)
+ {
+ btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr, BTM_BLE_META_READ_IRK_ENTRY);
+ }
+
+ return st;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_resolving_list_load_dev
+**
+** Description This function add a device which is using RPA into white list
+**
+** Parameters pointer to device security record
+**
+** Returns TRUE if device added, otherwise falase.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ BOOLEAN rt = FALSE;
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+
+ BTM_TRACE_DEBUG("%s btm_cb.ble_ctr_cb.privacy_mode = %d", __func__,
+ btm_cb.ble_ctr_cb.privacy_mode);
+
+ if (p_dev_rec != NULL && /* RPA is being used and PID is known */
+ p_dev_rec->sec_flags & BTM_SEC_IN_USE &&
+ /* only add RPA enabled device into resolving list */
+ (((p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0
+ && BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
+ || ((p_dev_rec->ble.key_type & BTM_LE_KEY_LID) != 0
+ && btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)))
+ {
+ if (!(p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
+ btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
+ BTM_BLE_META_ADD_IRK_ENTRY) == FALSE)
+ {
+ if (p_cb->resolving_list_avail_size > 0)
+ {
+ btm_ble_update_resolving_list( p_dev_rec->bd_addr, TRUE);
+
+ if (controller_get_interface()->supports_ble_privacy())
+ {
+ UINT8 dummy_irk[HCIC_BLE_IRK_SIZE];
+ memset(dummy_irk, 0, HCIC_BLE_IRK_SIZE);
+
+ UINT8 *peer_irk;
+ if (BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
+ peer_irk = p_dev_rec->ble.keys.irk;
+ else
+ peer_irk = dummy_irk;
+
+ UINT8 *local_irk;
+ if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
+ local_irk = btm_cb.devcb.id_keys.irk;
+ else
+ local_irk = dummy_irk;
+
+ BD_ADDR dummy_bda = {0};
+ /* for device not assigning static address, use pseudo address as identity */
+ if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) == 0)
+ {
+ memcpy(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
+ p_dev_rec->ble.static_addr_type = p_dev_rec->ble.ble_addr_type;
+ }
+
+ rt = btsnd_hcic_ble_add_device_resolving_list(p_dev_rec->ble.static_addr_type,
+ p_dev_rec->ble.static_addr, peer_irk, local_irk); // use identical IRK for now
+ }
+ else
+ {
+ UINT8 param[40] = {0};
+ UINT8 *p = param;
+
+ UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY);
+ ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN);
+ UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
+ BDADDR_TO_STREAM(p,p_dev_rec->ble.static_addr);
+
+ if (BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_ADD_IRK_LEN,
+ param,
+ btm_ble_resolving_list_vsc_op_cmpl)
+ == BTM_CMD_STARTED)
+ rt = TRUE;
+ }
+
+ if (rt)
+ btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+ BTM_BLE_META_ADD_IRK_ENTRY);
+ }
+ }
+ else
+ {
+ BTM_TRACE_ERROR("Device already in Resolving list");
+ rt = TRUE;
+ }
+ }
+ else
+ {
+ BTM_TRACE_DEBUG("Device not a RPA enabled device");
+ }
+ return rt;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_resolving_list_remove_dev
+**
+** Description This function removes the device from resolving list
+**
+** Parameters
+**
+** Returns status
+**
+*******************************************************************************/
+void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ btm_ble_update_resolving_list( p_dev_rec->bd_addr, FALSE);
+
+ if ((p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
+ btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
+ BTM_BLE_META_REMOVE_IRK_ENTRY) == FALSE)
+ {
+ btm_ble_remove_resolving_list_entry(p_dev_rec);
+ } else {
+ BTM_TRACE_DEBUG("Device not in resolving list");
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_vendor_enable_irk_feature
+**
+** Description This function is called to enable or disable the RRA
+** offloading feature.
+**
+** Parameters enable: enable or disable the RRA offloading feature
+**
+** Returns BTM_SUCCESS if successful
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_vendor_enable_irk_feature(BOOLEAN enable)
+{
+ UINT8 param[20] = {0};
+ UINT8 *p = param;
+
+ /* select feature based on control block settings */
+ UINT8_TO_STREAM(p, BTM_BLE_META_IRK_ENABLE);
+ UINT8_TO_STREAM(p, enable ? 0x01 : 0x00);
+
+ return BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_IRK_ENABLE_LEN,
+ param, btm_ble_resolving_list_vsc_op_cmpl);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_disable_resolving_list
+**
+** Description disable LE resolve address feature
+**
+** Returns none
+**
+*******************************************************************************/
+void btm_ble_disable_resolving_list(void)
+{
+ if (btm_cb.ble_ctr_cb.enabled)
+ {
+ if (!controller_get_interface()->supports_ble_privacy())
+ btm_ble_vendor_enable_irk_feature(FALSE);
+ else
+ btsnd_hcic_ble_set_addr_resolution_enable(FALSE);
+
+ btm_cb.ble_ctr_cb.enabled = FALSE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_enable_resolving_list
+**
+** Description enable LE resolve address list
+**
+** Returns none
+**
+*******************************************************************************/
+void btm_ble_enable_resolving_list(void)
+{
+ if (!btm_cb.ble_ctr_cb.enabled &&
+ controller_get_interface()->get_ble_resolving_list_max_size() != 0)
+ {
+ if (!controller_get_interface()->supports_ble_privacy())
+ btm_ble_vendor_enable_irk_feature(TRUE);
+ else
+ btsnd_hcic_ble_set_addr_resolution_enable(TRUE);
+
+ btm_cb.ble_ctr_cb.enabled = TRUE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_resolving_list_empty
+**
+** Description check to see if resoving list is empty or not
+**
+** Returns TRUE: empty; FALSE non-empty
+**
+*******************************************************************************/
+BOOLEAN btm_ble_resolving_list_empty(void)
+{
+ return (controller_get_interface()->get_ble_resolving_list_max_size() ==
+ btm_cb.ble_ctr_cb.resolving_list_avail_size);
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_enable_resolving_list_for_platform
+**
+** Description enable/disable resolving list feature depending on if any
+** resolving list is empty and whitelist is involoved in the
+** operation.
+**
+** Returns none
+**
+*******************************************************************************/
+void btm_ble_enable_resolving_list_for_platform (void)
+{
+ /* if controller does not support, skip */
+ if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+ return;
+
+ if (btm_cb.ble_ctr_cb.wl_state == BTM_BLE_WL_IDLE)
+ {
+ if (controller_get_interface()->get_ble_resolving_list_max_size() >
+ btm_cb.ble_ctr_cb.resolving_list_avail_size)
+ btm_ble_enable_resolving_list();
+ else
+ btm_ble_disable_resolving_list();
+
+ return;
+ }
+
+ tBTM_SEC_DEV_REC *p_dev = &btm_cb.sec_dev_rec[0];
+ for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev ++)
+ {
+ if ((p_dev->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
+ (p_dev->ble.in_controller_list & BTM_WHITE_LIST_BIT))
+ {
+ btm_ble_enable_resolving_list();
+ return;
+ }
+ }
+ btm_ble_disable_resolving_list();
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_resolving_list_init
+**
+** Description Initialize resolving list in host stack
+**
+** Parameters Max resolving list size
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_resolving_list_init(UINT8 max_irk_list_sz)
+{
+ tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+ if (max_irk_list_sz > 0)
+ {
+ p_q->resolve_q_random_pseudo = (BD_ADDR*)GKI_getbuf (sizeof (BD_ADDR) *
+ max_irk_list_sz);
+ p_q->resolve_q_action = (UINT8*) GKI_getbuf (max_irk_list_sz);
+
+ BTM_TRACE_DEBUG ("%s max_irk_list_sz = %d", __func__, max_irk_list_sz);
+ }
+
+ controller_get_interface()->set_ble_resolving_list_max_size(max_irk_list_sz);
+ btm_ble_clear_resolving_list();
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_resolving_list_cleanup
+**
+** Description Cleanup resolving list dynamic memory
+**
+** Parameters
+**
+** Returns void
+**
+*******************************************************************************/
+void btm_ble_resolving_list_cleanup(void)
+{
+ tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+ if (p_q->resolve_q_random_pseudo)
+ GKI_freebuf(p_q->resolve_q_random_pseudo);
+
+ if (p_q->resolve_q_action)
+ GKI_freebuf(p_q->resolve_q_action);
+
+ controller_get_interface()->set_ble_resolving_list_max_size(0);
+}
+#endif
#include "btm_int.h"
#include "hcidefs.h"
#include "l2c_api.h"
-#include "vendor_ble.h"
static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void);
if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
return(FALSE);
-#if BLE_INCLUDED == TRUE && BLE_PRIVACY_SPT == TRUE
- btm_ble_vendor_irk_list_remove_dev(p_dev_rec);
-#endif
btm_sec_free_dev (p_dev_rec);
/* Tell controller to get rid of the link key if it has one stored */
l2c_link_processs_num_bufs(controller->get_acl_buffer_count_classic());
#if (BLE_INCLUDED == TRUE)
+
+ /* Set up the BLE privacy settings */
+ if (controller->supports_ble() && controller->supports_ble_privacy() &&
+ controller->get_ble_resolving_list_max_size() > 0) {
+ btm_ble_resolving_list_init (controller->get_ble_resolving_list_max_size());
+ /* set the default random private address timeout */
+ btsnd_hcic_ble_set_rand_priv_addr_timeout(BTM_BLE_PRIVATE_ADDR_INT);
+ }
+
if (controller->supports_ble()) {
l2c_link_processs_ble_num_bufs(controller->get_acl_buffer_count_ble());
}
/* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0)
{
+#if BLE_INCLUDED == TRUE
+ btm_clear_all_pending_le_entry();
+#endif
p_inq->state = BTM_INQ_INACTIVE_STATE;
/* Increment so the start of a next inquiry has a new count */
BD_ADDR read_tx_pwr_addr; /* read TX power target address */
- tBTM_BLE_LOCAL_ID_KEYS id_keys; /* local BLE ID keys */
- BT_OCTET16 er; /* BLE encryption key */
+#define BTM_LE_SUPPORT_STATE_SIZE 8
+UINT8 le_supported_states[BTM_LE_SUPPORT_STATE_SIZE];
+
+tBTM_BLE_LOCAL_ID_KEYS id_keys; /* local BLE ID keys */
+BT_OCTET16 ble_encryption_key_value; /* BLE encryption key */
#if BTM_BLE_CONFORMANCE_TESTING == TRUE
BOOLEAN no_disc_if_pair_fail;
UINT32 test_local_sign_cntr;
#endif
-
#endif /* BLE_INCLUDED */
tBTM_IO_CAP loc_io_caps; /* IO capability of the local device */
typedef struct
{
BT_OCTET16 irk; /* peer diverified identity root */
+ BT_OCTET16 pltk; /* peer long term key */
+ BT_OCTET16 pcsrk; /* peer SRK peer device used to secured sign local data */
+
+ BT_OCTET16 lltk; /* local long term key */
+ BT_OCTET16 lcsrk; /* local SRK peer device used to secured sign local data */
BT_OCTET16 ltk; /* peer long term key */
BT_OCTET16 csrk; /* peer SRK peer device used to secured sign local data */
tBLE_ADDR_TYPE ble_addr_type; /* LE device type: public or random address */
tBLE_ADDR_TYPE static_addr_type; /* static address type */
BD_ADDR static_addr; /* static address */
+
+#define BTM_WHITE_LIST_BIT 0x01
+#define BTM_RESOLVING_LIST_BIT 0x02
+ UINT8 in_controller_list; /* in controller resolving list or not */
+ UINT8 resolving_list_index;
#if BLE_PRIVACY_SPT == TRUE
BD_ADDR cur_rand_addr; /* current random address */
#define BTM_BLE_ADDR_PSEUDO 0 /* address index device record */
#define BTM_BLE_ADDR_RRA 1 /* cur_rand_addr */
-#define BTM_BLE_ADDR_RECONN 2 /* reconnection address */
-#define BTM_BLE_ADDR_STATIC 3 /* static_addr */
+#define BTM_BLE_ADDR_STATIC 2 /* static_addr */
UINT8 active_addr_type;
-
- BOOLEAN privacy_enabled; /* remote device privacy enabled or not */
#endif
#if SMP_INCLUDED == TRUE
#define BTM_SEC_ENCRYPTED BTM_SEC_FLAG_ENCRYPTED /* 0x04 */
#define BTM_SEC_NAME_KNOWN 0x08
#define BTM_SEC_LINK_KEY_KNOWN BTM_SEC_FLAG_LKEY_KNOWN /* 0x10 */
-#define BTM_SEC_LINK_KEY_AUTHED 0x20
+#define BTM_SEC_LINK_KEY_AUTHED BTM_SEC_FLAG_LKEY_AUTHED /* 0x20 */
#define BTM_SEC_ROLE_SWITCHED 0x40
#define BTM_SEC_IN_USE 0x80
/* LE link security flag */
-#define BTM_SEC_LE_AUTHENTICATED 0x0200 /* 0x0200 */
-#define BTM_SEC_LE_ENCRYPTED 0x0400 /* 0x04 */
-#define BTM_SEC_LE_NAME_KNOWN 0x0800
-#define BTM_SEC_LE_LINK_KEY_KNOWN 0x1000 /* 0x10 */
-#define BTM_SEC_LE_LINK_KEY_AUTHED 0x2000
+#define BTM_SEC_LE_AUTHENTICATED 0x0200 /* LE link is encrypted after pairing with MITM */
+#define BTM_SEC_LE_ENCRYPTED 0x0400 /* LE link is encrypted */
+#define BTM_SEC_LE_NAME_KNOWN 0x0800 /* not used */
+#define BTM_SEC_LE_LINK_KEY_KNOWN 0x1000 /* bonded with peer (peer LTK and/or SRK is saved) */
+#define BTM_SEC_LE_LINK_KEY_AUTHED 0x2000 /* pairing is done with MITM */
UINT16 sec_flags; /* Current device security state */
BD_FEATURES features[HCI_EXT_FEATURES_PAGE_MAX + 1]; /* Features supported by the device */
UINT8 num_read_pages;
-#define BTM_SEC_STATE_IDLE 0
-#define BTM_SEC_STATE_AUTHENTICATING 1
-#define BTM_SEC_STATE_ENCRYPTING 2
-#define BTM_SEC_STATE_GETTING_NAME 3
-#define BTM_SEC_STATE_AUTHORIZING 4
-#define BTM_SEC_STATE_SWITCHING_ROLE 5
-#define BTM_SEC_STATE_DISCONNECTING 6
-#define BTM_SEC_STATE_DELAY_FOR_ENC 7 /* delay to check for encryption to work around controller problems */
+#define BTM_SEC_STATE_IDLE 0
+#define BTM_SEC_STATE_AUTHENTICATING 1
+#define BTM_SEC_STATE_ENCRYPTING 2
+#define BTM_SEC_STATE_GETTING_NAME 3
+#define BTM_SEC_STATE_AUTHORIZING 4
+#define BTM_SEC_STATE_SWITCHING_ROLE 5
+#define BTM_SEC_STATE_DISCONNECTING 6 /* disconnecting BR/EDR */
+#define BTM_SEC_STATE_DELAY_FOR_ENC 7 /* delay to check for encryption to work around */
+ /* controller problems */
+#define BTM_SEC_STATE_DISCONNECTING_BLE 8 /* disconnecting BLE */
+#define BTM_SEC_STATE_DISCONNECTING_BOTH 9 /* disconnecting BR/EDR and BLE */
UINT8 sec_state; /* Operating state */
BOOLEAN is_originator; /* TRUE if device is originating connection */
tBTM_SEC_BLE ble;
tBT_DEVICE_TYPE device_type;
tBTM_LE_CONN_PRAMS conn_params;
+ BOOLEAN new_encryption_key_is_p256; /* Set to TRUE when the newly generated LK
+ ** is generated from P-256.
+ ** Link encrypted with such LK can be used
+ ** for SM over BR/EDR.
+ */
#endif
// btla-specific ++
void *p_ref_data;
UINT32 mx_proto_id;
UINT32 mx_chan_id;
+ tBT_TRANSPORT transport;
} tBTM_SEC_QUEUE_ENTRY;
#if (L2CAP_UCD_INCLUDED == TRUE)
#if (!defined(BT_TRACE_VERBOSE) || (BT_TRACE_VERBOSE == FALSE))
char state_temp_buffer[BTM_STATE_BUFFER_SIZE];
#endif
-
} tBTM_CB;
extern void btm_ble_add_2_white_list_complete(UINT8 status);
extern void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
extern void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len);
+extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
+extern BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec);
+extern void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec);
+extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
#endif /* BLE_INCLUDED */
/* Vendor Specific Command complete evt handler */
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_queue_encrypt_request (BD_ADDR bd_addr, tBT_TRANSPORT transport,
+ tBTM_SEC_CALLBACK *p_callback, void *p_ref_data);
+static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT transport) ;
+static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC *p_dev_rec, tBT_TRANSPORT transport,
+ UINT8 encr_enable);
+static BOOLEAN btm_sec_acceptor_rejects_bonding (tBTM_SEC_DEV_REC *p_dev_rec);
+
+static BOOLEAN btm_sec_use_smp_br_chnl(tBTM_SEC_DEV_REC *p_dev_rec);
+static BOOLEAN btm_sec_is_master(tBTM_SEC_DEV_REC *p_dev_rec);
+
/* TRUE - authenticated link key is possible */
static const BOOLEAN btm_sec_io_map [BTM_IO_CAP_MAX][BTM_IO_CAP_MAX] =
{
if (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)
{
/* If some other thread disconnecting, we do not send second command */
- if (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING)
+ if ((p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING) ||
+ (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING_BOTH))
return(BTM_CMD_STARTED);
/* If the HCI link was set up by Bonding process */
return(BTM_UNKNOWN_ADDR);
}
+/*******************************************************************************
+**
+** Function BTM_SecGetDeviceLinkKeyType
+**
+** Description This function is called to obtain link key type for the
+** device.
+** it returns BTM_SUCCESS if link key is available, or
+** BTM_UNKNOWN_ADDR if Security Manager does not know about
+** the device or device record does not contain link key info
+**
+** Returns BTM_LKEY_TYPE_IGNORE if link key is unknown, link type
+** otherwise.
+**
+*******************************************************************************/
+tBTM_LINK_KEY_TYPE BTM_SecGetDeviceLinkKeyType (BD_ADDR bd_addr)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+
+ if ((p_dev_rec != NULL) && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN))
+ {
+ return p_dev_rec->link_key_type;
+ }
+ return BTM_LKEY_TYPE_IGNORE;
+}
/*******************************************************************************
**
** p_ref_data - pointer to any data the caller wishes to receive
** in the callback function upon completion.
* can be set to NULL if not used.
-** transport - TRUE to encryption the link over LE trasnport
-** or FALSE for BR/EDR trasnport
+** transport - TRUE to encryption the link over LE transport
+** or FALSE for BR/EDR transport
**
** Returns BTM_SUCCESS - already encrypted
** BTM_PENDING - command will be returned in the callback
tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CBACK *p_callback,
void *p_ref_data)
{
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_STATUS rc;
-#if BLE_INCLUDED == TRUE
- tACL_CONN *p = btm_bda_to_acl(bd_addr, transport);
-#endif
-
- p_dev_rec = btm_find_dev (bd_addr);
+ tBTM_STATUS rc = 0;
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
if (!p_dev_rec ||
(transport == BT_TRANSPORT_BR_EDR && p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE)
#if BLE_INCLUDED == TRUE
return(BTM_SUCCESS);
}
- if (p_dev_rec->p_callback)
+ /* enqueue security request if security is active */
+ if (p_dev_rec->p_callback || (p_dev_rec->sec_state != BTM_SEC_STATE_IDLE))
{
- /* Connection should be up and runnning */
- BTM_TRACE_WARNING ("Security Manager: BTM_SetEncryption busy");
-
- if (p_callback)
- (*p_callback) (bd_addr, transport, p_ref_data, BTM_BUSY);
+ BTM_TRACE_WARNING ("Security Manager: BTM_SetEncryption busy, enqueue request");
- return(BTM_BUSY);
+ if (btm_sec_queue_encrypt_request(bd_addr, transport, p_callback, p_ref_data))
+ {
+ return BTM_CMD_STARTED;
+ }
+ else
+ {
+ if (p_callback)
+ (*p_callback) (bd_addr, transport, p_ref_data, BTM_NO_RESOURCES);
+ return BTM_NO_RESOURCES;
+ }
}
p_dev_rec->p_callback = p_callback;
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
if (transport == BT_TRANSPORT_LE)
{
- rc = btm_ble_set_encryption(bd_addr, p_ref_data, p->link_role);
+ tACL_CONN *p = btm_bda_to_acl(bd_addr, transport);
+ if (p)
+ {
+ rc = btm_ble_set_encryption(bd_addr, p_ref_data, p->link_role);
+ }
+ else
+ {
+ rc = BTM_WRONG_MODE;
+ BTM_TRACE_WARNING("%s: cannot call btm_ble_set_encryption, p is NULL", __FUNCTION__);
+ }
}
else
#endif
-
rc = btm_sec_execute_procedure (p_dev_rec);
if (rc != BTM_CMD_STARTED && rc != BTM_BUSY)
(*p_callback) (bd_addr, transport, p_dev_rec->p_ref_data, rc);
}
}
+
return(rc);
}
BTM_TRACE_EVENT ("btm_sec_send_hci_disconnect: handle:0x%x, reason=0x%x",
conn_handle, reason);
- /* if some other thread disconnecting, we do not send second command */
- if (BTM_SEC_STATE_DISCONNECTING != old_state)
+ /* send HCI_Disconnect on a transport only once */
+ switch (old_state)
{
- p_dev_rec->sec_state = BTM_SEC_STATE_DISCONNECTING;
+ case BTM_SEC_STATE_DISCONNECTING:
+ if (conn_handle == p_dev_rec->hci_handle)
+ return status;
-#if BTM_DISC_DURING_RS == TRUE
- /* If a Role Switch is in progress, delay the HCI Disconnect to avoid controller problem (4329B1) */
- if (p_dev_rec->rs_disc_pending == BTM_SEC_RS_PENDING &&
- p_dev_rec->hci_handle == conn_handle)
+ p_dev_rec->sec_state = BTM_SEC_STATE_DISCONNECTING_BOTH;
+ break;
- {
- BTM_TRACE_DEBUG("RS in progress - Set DISC Pending flag in btm_sec_send_hci_disconnect to delay disconnect");
- p_dev_rec->rs_disc_pending = BTM_SEC_DISC_PENDING;
- status = BTM_SUCCESS;
- }
- else
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+ case BTM_SEC_STATE_DISCONNECTING_BLE:
+ if (conn_handle == p_dev_rec->ble_hci_handle)
+ return status;
+
+ p_dev_rec->sec_state = BTM_SEC_STATE_DISCONNECTING_BOTH;
+ break;
+
+ case BTM_SEC_STATE_DISCONNECTING_BOTH:
+ return status;
#endif
- /* Tear down the HCI link */
- if (!btsnd_hcic_disconnect (conn_handle, reason))
- {
- /* could not send disconnect. restore old state */
- p_dev_rec->sec_state = old_state;
- status = BTM_NO_RESOURCES;
- }
+
+ default:
+ p_dev_rec->sec_state = (conn_handle == p_dev_rec->hci_handle) ?
+ BTM_SEC_STATE_DISCONNECTING : BTM_SEC_STATE_DISCONNECTING_BLE;
+
+ break;
+ }
+
+ /* If a role switch is in progress, delay the HCI Disconnect to avoid controller problem */
+ if (p_dev_rec->rs_disc_pending == BTM_SEC_RS_PENDING && p_dev_rec->hci_handle == conn_handle)
+ {
+ BTM_TRACE_DEBUG("RS in progress - Set DISC Pending flag in btm_sec_send_hci_disconnect to delay disconnect");
+ p_dev_rec->rs_disc_pending = BTM_SEC_DISC_PENDING;
+ status = BTM_SUCCESS;
+ }
+ /* Tear down the HCI link */
+ else if (!btsnd_hcic_disconnect (conn_handle, reason))
+ {
+ /* could not send disconnect. restore old state */
+ p_dev_rec->sec_state = old_state;
+ status = BTM_NO_RESOURCES;
}
- return (status);
+
+ return status;
}
/*******************************************************************************
#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
void BTM_PasskeyReqReply(tBTM_STATUS res, BD_ADDR bd_addr, UINT32 passkey)
{
- tBTM_SEC_DEV_REC *p_dev_rec;
-
BTM_TRACE_API ("BTM_PasskeyReqReply: State: %s res:%d",
btm_pair_state_descr(btm_cb.pairing_state), res);
/* If timeout already expired or has been canceled, ignore the reply */
if ( (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_AUTH_COMPLETE) && (res != BTM_SUCCESS) )
{
- if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL)
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+ if (p_dev_rec != NULL)
{
btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
/* use BTM_PAIR_STATE_WAIT_AUTH_COMPLETE to report authentication failed event */
btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
btsnd_hcic_user_passkey_neg_reply (bd_addr);
- }
- else
- {
+ } else {
btm_cb.acl_disc_reason = HCI_SUCCESS;
btsnd_hcic_user_passkey_reply (bd_addr, passkey);
}
*******************************************************************************/
void BTM_RemoteOobDataReply(tBTM_STATUS res, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 r)
{
- BTM_TRACE_EVENT ("BTM_RemoteOobDataReply(): State: %s res:%d",
+ BTM_TRACE_EVENT ("%s() - State: %s res: %d", __func__,
btm_pair_state_descr(btm_cb.pairing_state), res);
/* If timeout already expired or has been canceled, ignore the reply */
/* use BTM_PAIR_STATE_WAIT_AUTH_COMPLETE to report authentication failed event */
btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
btsnd_hcic_rem_oob_neg_reply (bd_addr);
- }
- else
- {
+ } else {
btm_cb.acl_disc_reason = HCI_SUCCESS;
btsnd_hcic_rem_oob_reply (bd_addr, c, r);
}
{
UINT8 *p = p_data;
UINT16 len = 0;
- UINT16 delta;
#if BTM_MAX_LOC_BD_NAME_LEN > 0
UINT16 name_size;
UINT8 name_type = BTM_EIR_SHORTENED_LOCAL_NAME_TYPE;
/* now optional part */
/* add Hash C */
- delta = BTM_OOB_HASH_C_SIZE + 2;
+ UINT16 delta = BTM_OOB_HASH_C_SIZE + 2;
if (max_len >= delta)
{
*p++ = BTM_OOB_HASH_C_SIZE + 1;
/*******************************************************************************
**
+** Function BTM_IsLeScSuppLocally
+**
+** Description This function is called to check if LE SC is supported.
+**
+** Parameters: None.
+**
+** Returns Boolean - TRUE if LE SC is supported.
+*******************************************************************************/
+BOOLEAN BTM_IsLeScSuppLocally (void)
+{
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
+/*******************************************************************************
+**
** Function BTM_ReadOobData
**
** Description This function is called to parse the OOB data payload
{
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
- int i;
btm_cb.p_out_serv = p_serv_rec;
p_dev_rec = btm_find_dev (bd_addr);
- for (i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_serv_rec++)
+ for (int i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_serv_rec++)
{
if ((p_serv_rec->security_flags & BTM_SEC_IN_USE)
&& (p_serv_rec->service_id == service_id)
is_possible = FALSE;
if(p_dev_rec->p_cur_service)
{
- BTM_TRACE_DEBUG ("btm_sec_is_upgrade_possible id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x",
- p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps,
- mtm_check, p_dev_rec->p_cur_service->security_flags);
+ BTM_TRACE_DEBUG ("%s() id: %d, link_key_typet: %d, rmt_io_caps: %d, chk flags: 0x%x, flags: 0x%x",
+ __func__, p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type,
+ p_dev_rec->rmt_io_caps, mtm_check, p_dev_rec->p_cur_service->security_flags);
}
else
{
- BTM_TRACE_DEBUG ("btm_sec_is_upgrade_possible link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, ",
- p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps, mtm_check);
+ BTM_TRACE_DEBUG ("%s() link_key_typet: %d, rmt_io_caps: %d, chk flags: 0x%x",
+ __func__, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps, mtm_check);
}
/* Already have a link key to the connected peer. Is the link key secure enough?
** Is a link key upgrade even possible?
is_possible = TRUE;
}
}
- BTM_TRACE_DEBUG ("btm_sec_is_upgrade_possible is_possible:%d sec_flags:0x%x", is_possible, p_dev_rec->sec_flags);
+ BTM_TRACE_DEBUG ("%s() is_possible: %d sec_flags: 0x%x", __func__, is_possible, p_dev_rec->sec_flags);
return is_possible;
}
*******************************************************************************/
static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN is_originator)
{
- tBTM_SP_UPGRADE evt_data;
- BTM_TRACE_DEBUG ("btm_sec_check_upgrade...");
+ BTM_TRACE_DEBUG ("%s()", __func__);
/* Only check if link key already exists */
if (!(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN))
return;
+
if (btm_sec_is_upgrade_possible (p_dev_rec, is_originator) == TRUE)
{
BTM_TRACE_DEBUG ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags);
/* upgrade is possible: check if the application wants the upgrade.
* If the application is configured to use a global MITM flag,
* it probably would not want to upgrade the link key based on the security level database */
+ tBTM_SP_UPGRADE evt_data;
memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
evt_data.upgrade = TRUE;
if (btm_cb.api.p_sp_callback)
else
is_originator = FALSE;
- BTM_TRACE_DEBUG ("btm_sec_l2cap_access_req conn_type:0x%x, 0x%x", conn_type, p_ref_data);
+ BTM_TRACE_DEBUG ("%s() conn_type: 0x%x, 0x%x", __func__, conn_type, p_ref_data);
#else
is_originator = conn_type;
- BTM_TRACE_DEBUG ("btm_sec_l2cap_access_req is_originator:%d, 0x%x", is_originator, p_ref_data);
+ BTM_TRACE_DEBUG ("%s() is_originator:%d, 0x%x", __func__, is_originator, p_ref_data);
#endif
/* Find or get oldest record */
/* If there is no application registered with this PSM do not allow connection */
if (!p_serv_rec)
{
- BTM_TRACE_WARNING ("btm_sec_l2cap_access_req() PSM:%d no application registerd", psm);
-
+ BTM_TRACE_WARNING ("%s() PSM: %d no application registerd", __func__, psm);
(*p_callback) (bd_addr, transport, p_ref_data, BTM_MODE_UNSUPPORTED);
-
return(BTM_MODE_UNSUPPORTED);
}
if (BT_PSM_SDP == psm)
{
(*p_callback) (bd_addr,transport, p_ref_data, BTM_SUCCESS_NO_SECURITY);
-
return(BTM_SUCCESS);
}
#if (L2CAP_UCD_INCLUDED == TRUE)
/* we will process one after another */
if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) )
{
- BTM_TRACE_EVENT ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed state: %s mode:%d, sm4:0x%x",
+ BTM_TRACE_EVENT ("%s() - busy - PSM:%d delayed state: %s mode:%d, sm4:0x%x", __func__,
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 (p_callback)
(*p_callback) (bd_addr, transport, (void *)p_ref_data, BTM_SUCCESS);
-
return(BTM_SUCCESS);
}
}
/* 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)
{
}
}
- BTM_TRACE_DEBUG ("btm_sec_l2cap_access_req() sm4:0x%x, sec_flags:0x%x, security_required:0x%x chk:%d",
+ BTM_TRACE_DEBUG ("%s() sm4:0x%x, sec_flags:0x%x, security_required:0x%x chk:%d", __func__,
p_dev_rec->sm4, p_dev_rec->sec_flags, security_required, chk_acp_auth_done);
old_security_required = p_dev_rec->security_required;
p_dev_rec->sec_state = BTM_SEC_STATE_DELAY_FOR_ENC;
(*p_callback) (bd_addr, transport, p_ref_data, rc);
- return(BTM_CMD_STARTED);
+ return BTM_SUCCESS;
}
}
btm_sec_check_upgrade(p_dev_rec, is_originator);
}
- BTM_TRACE_EVENT ("Security Manager: l2cap_access_req PSM:%d Handle:%d State:%d Flags:0x%x Required:0x%x Service ID:%d",
- psm, handle, p_dev_rec->sec_state, p_dev_rec->sec_flags, p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
+ BTM_TRACE_EVENT ("%s() PSM:%d Handle:%d State:%d Flags: 0x%x Required: 0x%x Service ID:%d",
+ __func__, psm, handle, p_dev_rec->sec_state, p_dev_rec->sec_flags,
+ p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
if ((rc = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
{
tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator,
UINT32 mx_proto_id, UINT32 mx_chan_id,
tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
-
{
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_SEC_SERV_REC *p_serv_rec;
UINT16 security_required;
BOOLEAN transport = FALSE;/* should check PSM range in LE connection oriented L2CAP connection */
- BTM_TRACE_DEBUG ("btm_sec_mx_access_request is_originator:%d", is_originator);
+ BTM_TRACE_DEBUG ("%s() is_originator: %d", __func__, is_originator);
/* Find or get oldest record */
p_dev_rec = btm_find_or_alloc_dev (bd_addr);
/* we will process one after another */
if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) )
{
- BTM_TRACE_EVENT ("btm_sec_mx_access_request service PSM:%d Proto:%d SCN:%d delayed state: %s",
+ BTM_TRACE_EVENT ("%s() service PSM:%d Proto:%d SCN:%d delayed state: %s", __func__,
psm, mx_proto_id, mx_chan_id, btm_pair_state_descr(btm_cb.pairing_state));
rc = BTM_CMD_STARTED;
/* scn, we need to request user's permission again. */
p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED);
- BTM_TRACE_EVENT ("Security Manager: mx_access_req proto_id:%d chan_id:%d State:%d Flags:0x%x Required:0x%x Service ID:%d",
- mx_proto_id, mx_chan_id, p_dev_rec->sec_state, p_dev_rec->sec_flags, p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
+ BTM_TRACE_EVENT ("%s() proto_id:%d chan_id:%d State:%d Flags:0x%x Required:0x%x Service ID:%d",
+ __func__, mx_proto_id, mx_chan_id, p_dev_rec->sec_state, p_dev_rec->sec_flags,
+ p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
if ((rc = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
{
if (p_callback)
{
p_dev_rec->p_callback = NULL;
-
(*p_callback) (bd_addr,transport, p_ref_data, (UINT8)rc);
}
}
while ((p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_dequeue (&bq)) != NULL)
{
/* Check that the ACL is still up before starting security procedures */
- if (btm_bda_to_acl(p_e->bd_addr, BT_TRANSPORT_BR_EDR) != NULL)
+ if (btm_bda_to_acl(p_e->bd_addr, p_e->transport) != NULL)
{
- BTM_TRACE_EVENT ("btm_sec_check_pending_reqs() submitting PSM: 0x%04x Is_Orig: %u mx_proto_id: %u mx_chan_id: %u",
- p_e->psm, p_e->is_orig, p_e->mx_proto_id, p_e->mx_chan_id);
+ if (p_e->psm != 0)
+ {
+ BTM_TRACE_EVENT("%s PSM:0x%04x Is_Orig:%u mx_proto_id:%u mx_chan_id:%u",
+ __FUNCTION__, p_e->psm, p_e->is_orig,
+ p_e->mx_proto_id, p_e->mx_chan_id);
- btm_sec_mx_access_request (p_e->bd_addr, p_e->psm, p_e->is_orig,
+ btm_sec_mx_access_request (p_e->bd_addr, p_e->psm, p_e->is_orig,
p_e->mx_proto_id, p_e->mx_chan_id,
p_e->p_callback, p_e->p_ref_data);
+ }
+ else
+ {
+ BTM_SetEncryption(p_e->bd_addr, p_e->transport, p_e->p_callback,
+ p_e->p_ref_data);
+ }
}
GKI_freebuf (p_e);
*******************************************************************************/
void btm_sec_init (UINT8 sec_mode)
{
-#if 0 /* cleared in btm_init; put back in if calling from anywhere else! */
- int i;
-
- memset (btm_cb.sec_serv_rec, 0, sizeof (btm_cb.sec_serv_rec));
- memset (btm_cb.sec_dev_rec, 0, sizeof (btm_cb.sec_dev_rec));
- memset (&btm_cb.pairing_tle, 0, sizeof(TIMER_LIST_ENT));
-
-#endif
btm_cb.security_mode = sec_mode;
memset (btm_cb.pairing_bda, 0xff, BD_ADDR_LEN);
btm_cb.max_collision_delay = BTM_SEC_MAX_COLLISION_DELAY;
*******************************************************************************/
void btm_sec_device_down (void)
{
- BTM_TRACE_EVENT ("btm_sec_device_down() State: %s", btm_pair_state_descr(btm_cb.pairing_state));
-
+ BTM_TRACE_EVENT ("%s() State: %s", __func__, btm_pair_state_descr(btm_cb.pairing_state));
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
}
btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_PEER_USER, p_dev_rec->hci_handle);
}
else
- l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
+ {
+ BTM_TRACE_DEBUG ("TRYING TO DECIDE IF CAN USE SMP_BR_CHNL");
+ if (p_dev_rec->new_encryption_key_is_p256 && (btm_sec_use_smp_br_chnl(p_dev_rec)))
+ {
+ BTM_TRACE_DEBUG ("link encrypted afer dedic bonding can use SMP_BR_CHNL");
+ if (btm_sec_is_master(p_dev_rec))
+ {
+ // Encryption is required to start SM over BR/EDR.
+ // Indicate that this is encryption after authentication.
+ BTM_SetEncryption(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, NULL, NULL);
+ }
+ }
+
+ l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
+ }
return;
}
if (acl_idx != MAX_L2CAP_LINKS )
p_acl = &btm_cb.acl_db[acl_idx];
+ btm_sec_check_pending_enc_req (p_dev_rec, p_acl->transport, encr_enable);
+
if (p_acl && p_acl->transport == BT_TRANSPORT_LE)
{
- if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE
- ||status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)
+ if (status == HCI_ERR_KEY_MISSING ||
+ status == HCI_ERR_AUTH_FAILURE ||
+ status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)
+ {
p_dev_rec->sec_flags &= ~ (BTM_SEC_LE_LINK_KEY_KNOWN);
+ p_dev_rec->ble.key_type = BTM_LE_KEY_NONE;
+ }
btm_ble_link_encrypted(p_dev_rec->bd_addr, encr_enable);
return;
}
else
/* BR/EDR connection, update the encryption key size to be 16 as always */
p_dev_rec->enc_key_size = 16;
-#endif
+
+ BTM_TRACE_DEBUG ("in btm_sec_encrypt_change new_encr_key_256 is %d",
+ p_dev_rec->new_encryption_key_is_p256);
+
+ if ((status == HCI_SUCCESS) && encr_enable && (p_dev_rec->hci_handle == handle))
+ {
+ if (p_dev_rec->new_encryption_key_is_p256)
+ {
+ if (btm_sec_use_smp_br_chnl(p_dev_rec) &&
+ btm_sec_is_master(p_dev_rec))
+ {
+ /* BR/EDR is encrypted with LK that can be used to derive LE LTK */
+ p_dev_rec->new_encryption_key_is_p256 = FALSE;
+
+ BTM_TRACE_DEBUG ("btm_sec_encrypt_change start SM over BR/EDR");
+ SMP_BR_PairWith(p_dev_rec->bd_addr);
+ }
+ }
+ else
+ { /* BR/EDR is successfully encrypted. Correct LK type if needed
+ (BR/EDR LK derived from LE LTK was used for encryption) */
+ if ((encr_enable == 1) && /* encryption is ON for SSP */
+ /* LK type is for BR/EDR SC */
+ (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256 ||
+ p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256))
+ {
+ if (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256)
+ p_dev_rec->link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB;
+ else /* BTM_LKEY_TYPE_AUTH_COMB_P_256 */
+ p_dev_rec->link_key_type = BTM_LKEY_TYPE_AUTH_COMB;
+
+ BTM_TRACE_DEBUG("updated link key type to %d", p_dev_rec->link_key_type);
+ btm_send_link_key_notif(p_dev_rec);
+ }
+ }
+ }
+#else
+ btm_sec_check_pending_enc_req (p_dev_rec, BT_TRANSPORT_BR_EDR, encr_enable);
+#endif /* BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE */
/* If this encryption was started by peer do not need to do anything */
if (p_dev_rec->sec_state != BTM_SEC_STATE_ENCRYPTING)
p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
}
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+ if (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING_BOTH)
+ {
+ p_dev_rec->sec_state = (transport == BT_TRANSPORT_LE) ?
+ BTM_SEC_STATE_DISCONNECTING : BTM_SEC_STATE_DISCONNECTING_BLE;
+ return;
+ }
+#endif
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
p_dev_rec->security_required = BTM_SEC_NONE;
void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_type)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_bda);
- BOOLEAN we_are_bonding = FALSE;
+ BOOLEAN we_are_bonding = FALSE;
+ BOOLEAN ltk_derived_lk = FALSE;
BTM_TRACE_EVENT ("btm_sec_link_key_notification() BDA:%04x%08x, TYPE: %d",
(p_bda[0]<<8)+p_bda[1], (p_bda[2]<<24)+(p_bda[3]<<16)+(p_bda[4]<<8)+p_bda[5],
key_type);
+ if ((key_type >= BTM_LTK_DERIVED_LKEY_OFFSET + BTM_LKEY_TYPE_COMBINATION) &&
+ (key_type <= BTM_LTK_DERIVED_LKEY_OFFSET + BTM_LKEY_TYPE_AUTH_COMB_P_256))
+ {
+ ltk_derived_lk = TRUE;
+ key_type -= BTM_LTK_DERIVED_LKEY_OFFSET;
+ }
/* If connection was made to do bonding restore link security if changed */
btm_restore_mode();
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
}
+ /* save LTK derived LK no matter what */
+ if (ltk_derived_lk)
+ {
+ if (btm_cb.api.p_link_key_callback)
+ {
+ BTM_TRACE_DEBUG ("%s() Save LTK derived LK (key_type = %d)",
+ __FUNCTION__, p_dev_rec->link_key_type);
+ (*btm_cb.api.p_link_key_callback) (p_bda, p_dev_rec->dev_class,
+ p_dev_rec->sec_bd_name,
+ p_link_key, p_dev_rec->link_key_type);
+ }
+ }
+#if BTM_CROSS_TRANSP_KEY_DERIVATION == TRUE
+ else
+ {
+ if ((p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256) ||
+ (p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256))
+ {
+ p_dev_rec->new_encr_key_256 = TRUE;
+ BTM_TRACE_DEBUG ("%s set new_encr_key_256 to %d",
+ __func__, p_dev_rec->new_encr_key_256);
+ }
+ }
+#endif
+
/* If name is not known at this point delay calling callback until the name is */
/* resolved. Unless it is a HID Device and we really need to send all link keys. */
if ((!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN)
&& ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) != BTM_COD_MAJOR_PERIPHERAL)) )
{
BTM_TRACE_EVENT ("btm_sec_link_key_notification() Delayed BDA: %08x%04x Type:%d",
- (p_bda[0]<<24) + (p_bda[1]<<16) + (p_bda[2]<<8) + p_bda[3], (p_bda[4] << 8) + p_bda[5], key_type);
+ (p_bda[0]<<24) + (p_bda[1]<<16) + (p_bda[2]<<8) + p_bda[3],
+ (p_bda[4] << 8) + p_bda[5], key_type);
p_dev_rec->link_key_not_sent = TRUE;
tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
int i;
- BTM_TRACE_DEBUG ("btm_sec_find_mx_serv");
+ BTM_TRACE_DEBUG ("%s()", __func__);
if (is_originator && p_out_serv && p_out_serv->psm == psm
&& p_out_serv->mx_proto_id == mx_proto_id
&& p_out_serv->orig_mx_chan_id == mx_chan_id)
*******************************************************************************/
static void btm_sec_collision_timeout (TIMER_LIST_ENT *p_tle)
{
- tBTM_STATUS status;
UNUSED(p_tle);
- BTM_TRACE_EVENT ("btm_sec_collision_timeout()");
+ BTM_TRACE_EVENT ("%s()", __func__);
btm_cb.sec_collision_tle.param = 0;
- status = btm_sec_execute_procedure (btm_cb.p_collided_dev_rec);
+ tBTM_STATUS status = btm_sec_execute_procedure (btm_cb.p_collided_dev_rec);
/* If result is pending reply from the user or from the device is pending */
if (status != BTM_CMD_STARTED)
*******************************************************************************/
UINT32 * BTM_ReadTrustedMask (BD_ADDR bd_addr)
{
- tBTM_SEC_DEV_REC *p_dev_rec;
-
- if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL)
- {
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+ if (p_dev_rec != NULL)
return(p_dev_rec->trusted_mask);
- }
- else
- {
- return NULL;
- }
+ return NULL;
}
/*******************************************************************************
if (btm_cb.security_mode_changed)
{
btm_cb.security_mode_changed = FALSE;
- BTM_TRACE_DEBUG("btm_restore_mode: Authen Enable -> %d", (btm_cb.security_mode == BTM_SEC_MODE_LINK));
+ BTM_TRACE_DEBUG("%s() Auth enable -> %d", __func__, (btm_cb.security_mode == BTM_SEC_MODE_LINK));
btsnd_hcic_write_auth_enable ((UINT8)(btm_cb.security_mode == BTM_SEC_MODE_LINK));
}
tBTM_SEC_DEV_REC *btm_sec_find_dev_by_sec_state (UINT8 state)
{
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
- int i;
- for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
+ for (int i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
{
if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
&& (p_dev_rec->sec_state == state))
{
tBTM_PAIRING_STATE old_state = btm_cb.pairing_state;
- BTM_TRACE_EVENT ("btm_sec_change_pairing_state Old: %s", btm_pair_state_descr(btm_cb.pairing_state));
- BTM_TRACE_EVENT ("btm_sec_change_pairing_state New: %s pairing_flags:0x%x",btm_pair_state_descr(new_state), btm_cb.pairing_flags);
+ BTM_TRACE_EVENT ("%s() Old: %s", __func__, btm_pair_state_descr(btm_cb.pairing_state));
+ BTM_TRACE_EVENT ("%s() New: %s pairing_flags:0x%x", __func__,
+ btm_pair_state_descr(new_state), btm_cb.pairing_flags);
btm_cb.pairing_state = new_state;
}
#endif
-
/*******************************************************************************
**
** Function btm_sec_dev_rec_cback_event
if (p_dev_rec->p_callback)
{
p_dev_rec->p_callback = NULL;
-
(*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, res);
-
}
+
btm_sec_check_pending_reqs();
}
UINT32 mx_proto_id, UINT32 mx_chan_id,
tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
{
- tBTM_SEC_QUEUE_ENTRY *p_e;
-
- p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getbuf (sizeof(tBTM_SEC_QUEUE_ENTRY));
+ tBTM_SEC_QUEUE_ENTRY *p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getbuf (sizeof(tBTM_SEC_QUEUE_ENTRY));
if (p_e)
{
p_e->p_ref_data = p_ref_data;
p_e->mx_proto_id = mx_proto_id;
p_e->mx_chan_id = mx_chan_id;
+ p_e->transport = BT_TRANSPORT_BR_EDR;
memcpy (p_e->bd_addr, bd_addr, BD_ADDR_LEN);
- BTM_TRACE_EVENT ("btm_sec_queue_mx_request() PSM: 0x%04x Is_Orig: %u mx_proto_id: %u mx_chan_id: %u",
- psm, is_orig, mx_proto_id, mx_chan_id);
+ BTM_TRACE_EVENT ("%s() PSM: 0x%04x Is_Orig: %u mx_proto_id: %u mx_chan_id: %u",
+ __func__, psm, is_orig, mx_proto_id, mx_chan_id);
GKI_enqueue (&btm_cb.sec_pending_q, p_e);
if ((major == BTM_COD_MAJOR_AUDIO)
&& ((minor == BTM_COD_MINOR_CONFM_HANDSFREE) || (minor == BTM_COD_MINOR_CAR_AUDIO)) )
{
- BTM_TRACE_EVENT ("btm_sec_check_prefetch_pin: Skipping pre-fetch PIN for carkit COD Major: 0x%02x Minor: 0x%02x", major, minor);
+ BTM_TRACE_EVENT ("%s() Skipping pre-fetch PIN for carkit COD Major: 0x%02x Minor: 0x%02x",
+ __func__, major, minor);
if (btm_cb.security_mode_changed == FALSE)
{
/* pin was not supplied - pre-fetch pin code now */
if (btm_cb.api.p_pin_callback && ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_PIN_REQD) == 0))
{
- BTM_TRACE_DEBUG("btm_sec_check_prefetch_pin: PIN code callback called");
+ BTM_TRACE_DEBUG("%s() PIN code callback called", __func__);
if (btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR) == NULL)
btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD;
(btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, p_dev_rec->sec_bd_name);
return rv;
}
+/*******************************************************************************
+**
+** Function btm_sec_auth_payload_tout
+**
+** Description Processes the HCI Autheniticated Payload Timeout Event
+** indicating that a packet containing a valid MIC on the
+** connection handle was not received within the programmed
+** timeout value. (Spec Default is 30 secs, but can be
+** changed via the BTM_SecSetAuthPayloadTimeout() function.
+**
+*******************************************************************************/
+void btm_sec_auth_payload_tout (UINT8 *p, UINT16 hci_evt_len)
+{
+ UINT16 handle;
+
+ STREAM_TO_UINT16 (handle, p);
+ handle = HCID_GET_HANDLE (handle);
+
+ /* Will be exposed to upper layers in the future if/when determined necessary */
+ BTM_TRACE_ERROR ("%s on handle 0x%02x", __func__, handle);
+}
+
+/*******************************************************************************
+**
+** Function btm_sec_queue_encrypt_request
+**
+** Description encqueue encryption request when device has active security
+** process pending.
+**
+*******************************************************************************/
+static BOOLEAN btm_sec_queue_encrypt_request (BD_ADDR bd_addr, tBT_TRANSPORT transport,
+ tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
+{
+ tBTM_SEC_QUEUE_ENTRY *p_e;
+ p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getbuf(sizeof(tBTM_SEC_QUEUE_ENTRY) + 1);
+
+ if (p_e)
+ {
+ p_e->psm = 0; /* if PSM 0, encryption request */
+ p_e->p_callback = p_callback;
+ p_e->p_ref_data = (void *)(p_e + 1);
+ *(UINT8 *)p_e->p_ref_data = *(UINT8 *)(p_ref_data);
+ p_e->transport = transport;
+ memcpy(p_e->bd_addr, bd_addr, BD_ADDR_LEN);
+ GKI_enqueue(&btm_cb.sec_pending_q, p_e);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function btm_sec_clean_pending_req_queue
+**
+** Description This function cleans up the pending security request when the
+** link to the target device dropped.
+**
+** Returns void
+**
+*******************************************************************************/
+static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT transport)
+{
+ tBTM_SEC_QUEUE_ENTRY *p_e;
+ BUFFER_Q *bq = &btm_cb.sec_pending_q;
+
+ p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getfirst(bq);
+
+ if (p_e != NULL)
+ {
+ if (memcmp(p_e->bd_addr, remote_bda, BD_ADDR_LEN) == 0
+#if BLE_INCLUDED == TRUE
+ && p_e->transport == transport
+#endif
+ )
+ {
+ (*p_e->p_callback) (remote_bda, transport, p_e->p_ref_data, BTM_ERR_PROCESSING);
+ GKI_remove_from_queue(bq, (void *)p_e);
+ }
+ p_e = (tBTM_SEC_QUEUE_ENTRY *) GKI_getnext ((void *)p_e);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function btm_sec_check_pending_enc_req
+**
+** Description This function is called to send pending encryption callback if
+** waiting
+**
+** Returns void
+**
+*******************************************************************************/
+static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC *p_dev_rec, tBT_TRANSPORT transport,
+ UINT8 encr_enable)
+{
+ tBTM_SEC_QUEUE_ENTRY *p_e;
+ BUFFER_Q *bq = &btm_cb.sec_pending_q;
+ UINT8 res = encr_enable ? BTM_SUCCESS : BTM_ERR_PROCESSING;
+ UINT8 sec_act ;
+
+ p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getfirst(bq);
+
+ while (p_e != NULL)
+ {
+ if (memcmp(p_e->bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0 && p_e->psm == 0
+#if BLE_INCLUDED == TRUE
+ && p_e->transport == transport
+#endif
+ )
+ {
+ sec_act = *(UINT8 *)(p_e->p_ref_data);
+
+ if (encr_enable == 0 || transport == BT_TRANSPORT_BR_EDR
+#if BLE_INCLUDED == TRUE
+ || (sec_act == BTM_BLE_SEC_ENCRYPT || sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM)
+ || (sec_act == BTM_BLE_SEC_ENCRYPT_MITM && p_dev_rec->sec_flags
+ & BTM_SEC_LE_AUTHENTICATED)
+#endif
+ )
+ {
+ (*p_e->p_callback) (p_dev_rec->bd_addr, transport, p_e->p_ref_data, res);
+ GKI_remove_from_queue(bq, (void *)p_e);
+ }
+ }
+ p_e = (tBTM_SEC_QUEUE_ENTRY *) GKI_getnext ((void *)p_e);
+ }
+ return;
+}
+
#if (BLE_INCLUDED == TRUE)
/*******************************************************************************
**
void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec)
{
- BTM_TRACE_DEBUG ("btm_sec_clear_ble_keys: Clearing BLE Keys");
+ BTM_TRACE_DEBUG ("%s() Clearing BLE Keys", __func__);
#if (SMP_INCLUDED== TRUE)
- p_dev_rec->ble.key_type = 0;
+ p_dev_rec->ble.key_type = BTM_LE_KEY_NONE;
memset (&p_dev_rec->ble.keys, 0, sizeof(tBTM_SEC_BLE_KEYS));
+
+#if (BLE_PRIVACY_SPT == TRUE)
+ btm_ble_resolving_list_remove_dev(p_dev_rec);
+#endif
#endif
- gatt_delete_dev_from_srv_chg_clt_list(p_dev_rec->bd_addr);
}
{
is_bonded = TRUE;
}
- BTM_TRACE_DEBUG ("btm_sec_is_a_bonded_dev is_bonded=%d", is_bonded);
+ BTM_TRACE_DEBUG ("%s() is_bonded=%d", __func__, is_bonded);
return(is_bonded);
}
break;
}
}
- BTM_TRACE_DEBUG ("btm_sec_find_bonded_dev=%d", found);
+ BTM_TRACE_DEBUG ("%s() found=%d", __func__, found);
#endif
return(found);
}
+
+
+/*******************************************************************************
+**
+** Function btm_sec_use_smp_br_chnl
+**
+** Description The function checks if SMP BR connection can be used with
+** the peer.
+** Is called when authentication for dedicated bonding is
+** successfully completed.
+**
+** Returns TRUE - if SMP BR connection can be used (the link key is
+** generated from P-256 and the peer supports Security
+** Manager over BR).
+**
+*******************************************************************************/
+static BOOLEAN btm_sec_use_smp_br_chnl(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ UINT32 ext_feat;
+ UINT8 chnl_mask[L2CAP_FIXED_CHNL_ARRAY_SIZE];
+
+ BTM_TRACE_DEBUG ("%s() link_key_type = 0x%x", __func__,
+ p_dev_rec->link_key_type);
+
+ if ((p_dev_rec->link_key_type != BTM_LKEY_TYPE_UNAUTH_COMB_P_256) &&
+ (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256))
+ return FALSE;
+
+ if (!L2CA_GetPeerFeatures (p_dev_rec->bd_addr, &ext_feat, chnl_mask))
+ return FALSE;
+
+ if (!(chnl_mask[0] & L2CAP_FIXED_CHNL_SMP_BR_BIT))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function btm_sec_is_master
+**
+** Description The function checks if the device is BR/EDR master after
+** pairing is completed.
+**
+** Returns TRUE - if the device is master.
+**
+*******************************************************************************/
+static BOOLEAN btm_sec_is_master(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ tACL_CONN *p= btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR);
+ return (p && (p->link_role == BTM_ROLE_MASTER));
+}
+
#endif /* BLE_INCLUDED */
#if (BLE_LLT_INCLUDED == TRUE)
static void btu_ble_rc_param_req_evt(UINT8 *p);
#endif
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+static void btu_ble_proc_enhanced_conn_cmpl (UINT8 *p, UINT16 evt_len);
+#endif
+
#endif
/*******************************************************************************
case HCI_BLE_LTK_REQ_EVT: /* received only at slave device */
btu_ble_proc_ltk_req(p);
break;
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ case HCI_BLE_ENHANCED_CONN_COMPLETE_EVT:
+ btu_ble_proc_enhanced_conn_cmpl(p, hci_evt_len);
+ break;
+#endif
#if (BLE_LLT_INCLUDED == TRUE)
case HCI_BLE_RC_PARAM_REQ_EVT:
btu_ble_rc_param_req_evt(p);
case HCI_BLE_TEST_END:
btm_ble_test_command_complete(p);
break;
+
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+ case HCI_BLE_ADD_DEV_RESOLVING_LIST:
+ btm_ble_add_resolving_list_entry_complete(p, evt_len);
+ break;
+
+ case HCI_BLE_RM_DEV_RESOLVING_LIST:
+ btm_ble_remove_resolving_list_entry_complete(p, evt_len);
+ break;
+
+ case HCI_BLE_CLEAR_RESOLVING_LIST:
+ btm_ble_clear_resolving_list_complete(p, evt_len);
+ break;
+
+ case HCI_BLE_READ_RESOLVABLE_ADDR_PEER:
+ btm_ble_read_resolving_list_entry_complete(p, evt_len);
+ break;
+
+ case HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL:
+ case HCI_BLE_SET_ADDR_RESOLUTION_ENABLE:
+ case HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT:
+ break;
+#endif
#endif /* (BLE_INCLUDED == TRUE) */
default:
static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
{
- btm_ble_conn_complete(p, evt_len);
+ btm_ble_conn_complete(p, evt_len, FALSE);
}
-
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+static void btu_ble_proc_enhanced_conn_cmpl( UINT8 *p, UINT16 evt_len)
+{
+ btm_ble_conn_complete(p, evt_len, TRUE);
+}
+#endif
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len)
{
/* LE connection update has completed successfully as a master. */
#define GAP_CHAR_ICON_SIZE 2
#define GAP_CHAR_DEV_NAME_SIZE 248
-#define GAP_BLE_PRIVACY_FLAG_SIZE 1
-
#define GAP_MAX_NUM_INC_SVR 0
#define GAP_MAX_ATTR_NUM (2 * GAP_MAX_CHAR_NUM + GAP_MAX_NUM_INC_SVR + 1)
#define GAP_MAX_CHAR_VALUE_SIZE (30 + GAP_CHAR_DEV_NAME_SIZE)
#define GAP_ATTR_DB_SIZE GATT_DB_MEM_SIZE(GAP_MAX_NUM_INC_SVR, GAP_MAX_CHAR_NUM, GAP_MAX_CHAR_VALUE_SIZE)
#endif
-/* privacy flag readable and writable with encryption on */
-#ifndef GAP_BLE_PRIVACY_FLAG_PERM
-#define GAP_BLE_PRIVACY_FLAG_PERM (GATT_PERM_READ|GATT_PERM_WRITE)
-#endif
-
-#define GATT_READ_GAP_PRIVACY_FLAG 1
-#define GATT_SET_GAP_PRIVACY_FLAG 2
-#define GATT_READ_GAP_REMOTE_NAME 3
-#define GATT_UPDATE_RECONN_ADDR 4
-
-#define GAP_BLE_PRIVACY_UNKNOWN 0xff
-
static void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE op_code, tGATTS_DATA *p_data);
/* client connection callback */
** Returns NULL if not found. Otherwise pointer to the connection link block.
**
*******************************************************************************/
-tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
+tGAP_CLCB *gap_clcb_alloc (BD_ADDR bda)
{
UINT8 i_clcb = 0;
tGAP_CLCB *p_clcb = NULL;
{
if (!p_clcb->in_use)
{
- p_clcb->in_use = TRUE;
- p_clcb->conn_id = conn_id;
- p_clcb->connected = TRUE;
+ memset(p_clcb, 0, sizeof(tGAP_CLCB));
+ p_clcb->in_use = TRUE;
memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
break;
}
/*******************************************************************************
**
-** Function gap_find_alloc_clcb
+** Function gap_ble_dealloc_clcb
**
-** Description The function find or allocates a GAP connection link control block
+** Description The function clean up the pending request queue in GAP
**
-** Returns NULL if not found. Otherwise pointer to the connection link block.
+** Returns none
**
*******************************************************************************/
-tGAP_CLCB *gap_find_alloc_clcb (UINT16 conn_id, BD_ADDR bda)
+void gap_ble_dealloc_clcb(tGAP_CLCB *p_clcb)
{
- UINT8 i_clcb = 0;
- tGAP_CLCB *p_clcb = NULL;
+ tGAP_BLE_REQ *p_q;
- for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+ while((p_q = (tGAP_BLE_REQ *)GKI_dequeue(&p_clcb->pending_req_q)) != NULL)
{
- if (!p_clcb->in_use)
- {
- p_clcb->in_use = TRUE;
- p_clcb->conn_id = conn_id;
- p_clcb->connected = TRUE;
- memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
- break;
- }
+ /* send callback to all pending requests if being removed*/
+ if (p_q->p_cback != NULL)
+ (*p_q->p_cback)(FALSE, p_clcb->bda, 0, NULL);
+
+ GKI_freebuf (p_q);
}
- return p_clcb;
+
+ memset(p_clcb, 0, sizeof(tGAP_CLCB));
}
/*******************************************************************************
**
-** Function gap_get_conn_id_if_connected
+** Function gap_ble_enqueue_request
**
-** Description This function returns a connecttion handle to a ATT server
-** if the server is already connected
+** Description The function enqueue a GAP client request
**
-** Parameters client_if: client interface.
-** bd_addr: peer device address.
-**
-** Returns Connection handle or invalid handle value
+** Returns TRUE is successul; FALSE otherwise
**
*******************************************************************************/
-UINT16 gap_get_conn_id_if_connected (BD_ADDR bd_addr)
+BOOLEAN gap_ble_enqueue_request (tGAP_CLCB *p_clcb, UINT16 uuid, tGAP_BLE_CMPL_CBACK *p_cback)
{
- tGAP_CLCB *p_clcb;
- UINT16 i;
-
- GAP_TRACE_EVENT ("gap_get_conn_id_if_connected() - BDA: %08x%04x ",
- (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
- (bd_addr[4]<<8)+bd_addr[5]);
+ tGAP_BLE_REQ *p_q = (tGAP_BLE_REQ *)GKI_getbuf(sizeof(tGAP_BLE_REQ));
- for (i = 0, p_clcb = gap_cb.clcb; i < GAP_MAX_CL; i++, p_clcb++)
+ if (p_q != NULL)
{
- if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bd_addr, BD_ADDR_LEN) )
- {
- return(p_clcb->conn_id);
- }
+ p_q->p_cback = p_cback;
+ p_q->uuid = uuid;
+ GKI_enqueue(&p_clcb->pending_req_q, p_q);
+ return TRUE;
}
- /* If here, failed to allocate a client control block */
- GATT_TRACE_DEBUG ("gap_get_conn_id_if_connected: not connected");
- return(GATT_INVALID_CONN_ID);
+ return FALSE;
}
+/*******************************************************************************
+**
+** Function gap_ble_dequeue_request
+**
+** Description The function dequeue a GAP client request if any
+**
+** Returns TRUE is successul; FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN gap_ble_dequeue_request (tGAP_CLCB *p_clcb, UINT16 * p_uuid, tGAP_BLE_CMPL_CBACK **p_cback)
+{
+ tGAP_BLE_REQ *p_q = (tGAP_BLE_REQ *)GKI_dequeue(&p_clcb->pending_req_q);;
+ if (p_q != NULL)
+ {
+ *p_cback = p_q->p_cback;
+ *p_uuid = p_q->uuid;
+ GKI_freebuf((void *)p_q);
+ return TRUE;
+ }
+
+ return FALSE;
+}
/*******************************************************************************
** GAP Attributes Database Request callback
UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.sp_tout); /* sp_tout */
p_value->len =8;
break;
+
+ /* address resolution */
+ case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
+ UINT8_TO_STREAM(p, p_db_attr->attr_value.addr_resolution);
+ p_value->len =1;
+ break;
}
return GATT_SUCCESS;
}
p_db_attr ++;
#endif
+ /* add Central address resolution Characteristic */
+ uuid.len = LEN_UUID_16;
+ uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
+ p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
+ GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
+ p_db_attr->attr_value.addr_resolution = 0;
+ p_db_attr++;
+
/* start service now */
memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
break;
case GATT_UUID_GAP_PREF_CONN_PARAM:
- memcpy((void *)&p_db_attr->attr_value.conn_param, (const void *)&p_value->conn_param, sizeof(tGAP_BLE_PREF_PARAM));
+ memcpy((void *)&p_db_attr->attr_value.conn_param,
+ (const void *)&p_value->conn_param, sizeof(tGAP_BLE_PREF_PARAM));
break;
case GATT_UUID_GAP_DEVICE_NAME:
BTM_SetLocalDeviceName((char *)p_value->p_dev_name);
break;
+ case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
+ p_db_attr->attr_value.addr_resolution = p_value->addr_resolution;
+ break;
+
}
break;
}
/*******************************************************************************
**
+** Function gap_ble_send_cl_read_request
+**
+** Description utility function to send a read request for a GAP charactersitic
+**
+** Returns TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN gap_ble_send_cl_read_request(tGAP_CLCB *p_clcb)
+{
+ tGATT_READ_PARAM param;
+ UINT16 uuid = 0;
+ BOOLEAN started = FALSE;
+
+ if (gap_ble_dequeue_request(p_clcb, &uuid, &p_clcb->p_cback))
+ {
+ memset(¶m, 0, sizeof(tGATT_READ_PARAM));
+
+ param.service.uuid.len = LEN_UUID_16;
+ param.service.uuid.uu.uuid16 = uuid;
+ param.service.s_handle = 1;
+ param.service.e_handle = 0xFFFF;
+ param.service.auth_req = 0;
+
+ if (GATTC_Read(p_clcb->conn_id, GATT_READ_BY_TYPE, ¶m) == GATT_SUCCESS)
+ {
+ p_clcb->cl_op_uuid = uuid;
+ started = TRUE;
+ }
+ }
+
+ return started;
+}
+
+/*******************************************************************************
+**
** Function gap_ble_cl_op_cmpl
**
** Description GAP client operation complete callback
*******************************************************************************/
void gap_ble_cl_op_cmpl(tGAP_CLCB *p_clcb, BOOLEAN status, UINT16 len, UINT8 *p_name)
{
- tGAP_BLE_DEV_NAME_CBACK *p_dev_name_cback = (tGAP_BLE_DEV_NAME_CBACK *)(p_clcb->p_cback);
+ tGAP_BLE_CMPL_CBACK *p_cback = p_clcb->p_cback;
UINT16 op = p_clcb->cl_op_uuid;
GAP_TRACE_EVENT("gap_ble_cl_op_cmpl status: %d", status);
p_clcb->cl_op_uuid = 0;
p_clcb->p_cback=NULL;
- if (p_dev_name_cback)
+ if (p_cback && op)
{
GAP_TRACE_EVENT("calling gap_ble_cl_op_cmpl");
-
- if (op == GATT_UUID_GAP_DEVICE_NAME)
- (* p_dev_name_cback)(status, p_clcb->bda, len, (char *)p_name);
+ (* p_cback)(status, p_clcb->bda, len, (char *)p_name);
}
-
+ /* if no further activity is requested in callback, drop the link */
+ if (p_clcb->connected)
+ {
+ if (!gap_ble_send_cl_read_request(p_clcb))
+ {
+ GATT_Disconnect(p_clcb->conn_id);
+ gap_ble_dealloc_clcb(p_clcb);
+ }
+ }
}
/*******************************************************************************
tGATT_TRANSPORT transport)
{
tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (bda);
- UINT16 cl_op_uuid;
UNUSED(gatt_if);
UNUSED(transport);
- GAP_TRACE_EVENT ("gap_ble_c_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
- (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
- (bda[4]<<8)+bda[5], connected, conn_id, reason);
-
-
- if (connected)
+ if (p_clcb != NULL)
{
- if (p_clcb == NULL)
+ if (connected)
{
- if ((p_clcb = gap_clcb_alloc(conn_id, bda))== NULL)
- {
- GAP_TRACE_ERROR ("gap_ble_c_connect_cback: no_resource");
- return;
- }
+ p_clcb->conn_id = conn_id;
+ p_clcb->connected = TRUE;
+ /* start operation is pending */
+ gap_ble_send_cl_read_request(p_clcb);
}
- p_clcb->conn_id = conn_id;
- p_clcb->connected = TRUE;
-
- }
- else
- {
- if (p_clcb != NULL)
- p_clcb->connected = FALSE;
- }
-
- if (p_clcb)
- {
- cl_op_uuid = p_clcb->cl_op_uuid;
-
- GAP_TRACE_EVENT ("cl_op_uuid=0x%04x", cl_op_uuid );
-
- if (p_clcb->connected)
- {
- p_clcb->cl_op_uuid = 0;
- if (cl_op_uuid == GATT_UUID_GAP_DEVICE_NAME)
- {
- GAP_BleReadPeerDevName (bda, (tGAP_BLE_DEV_NAME_CBACK *)p_clcb->p_cback);
- }
- else if (cl_op_uuid == GATT_UUID_GAP_PREF_CONN_PARAM)
- {
- GAP_BleReadPeerPrefConnParams(bda);
- }
- }
- /* current link disconnect */
else
{
+ p_clcb->connected = FALSE;
gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
- memset(p_clcb, 0, sizeof(tGAP_CLCB));
+ /* clean up clcb */
+ gap_ble_dealloc_clcb(p_clcb);
}
}
-
}
/*******************************************************************************
len = GAP_CHAR_DEV_NAME_SIZE;
gap_ble_cl_op_cmpl(p_clcb, TRUE, len, pp);
break;
- case GATT_UUID_GAP_ICON:
+
+ case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
+ gap_ble_cl_op_cmpl(p_clcb, TRUE, 1, pp);
break;
}
}
+
/*******************************************************************************
**
-** Function gap_ble_cl_read_request
+** Function gap_ble_accept_cl_operation
**
-** Description utility function to start a read request for a GAP charactersitic
+** Description Start a process to read peer address resolution capability
**
-** Returns TRUE if read started, else FALSE if GAP is busy
+** Returns TRUE if request accepted
**
*******************************************************************************/
-BOOLEAN gap_ble_cl_read_request(tGAP_CLCB *p_clcb, UINT16 uuid, void * p_cback)
+BOOLEAN gap_ble_accept_cl_operation(BD_ADDR peer_bda, UINT16 uuid, tGAP_BLE_CMPL_CBACK *p_cback)
{
- tGATT_READ_PARAM param;
-
- memset(¶m, 0, sizeof(tGATT_READ_PARAM));
+ tGAP_CLCB *p_clcb;
+ BOOLEAN started = FALSE;
- param.service.uuid.len = LEN_UUID_16;
- param.service.uuid.uu.uuid16 = uuid;
- param.service.s_handle = 1;
- param.service.e_handle = 0xFFFF;
- param.service.auth_req = 0;
+ if (p_cback == NULL && uuid != GATT_UUID_GAP_PREF_CONN_PARAM)
+ return(started);
- if (GATTC_Read(p_clcb->conn_id, GATT_READ_BY_TYPE, ¶m) != GATT_SUCCESS)
- {
- GAP_TRACE_ERROR ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
- /* release the link here */
- GATT_Disconnect(p_clcb->conn_id);
- return(FALSE);
- }
- else
+ if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL)
{
- p_clcb->p_cback = p_cback;
- p_clcb->cl_op_uuid = uuid;
- return TRUE;
+ if ((p_clcb = gap_clcb_alloc(peer_bda)) == NULL)
+ {
+ GAP_TRACE_ERROR("gap_ble_accept_cl_operation max connection reached");
+ return started;
+ }
}
-}
+ GAP_TRACE_EVENT ("%s() - BDA: %08x%04x cl_op_uuid: 0x%04x",
+ __FUNCTION__,
+ (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+ (peer_bda[4]<<8)+peer_bda[5], uuid);
+
+ if (GATT_GetConnIdIfConnected(gap_cb.gatt_if, peer_bda, &p_clcb->conn_id, BT_TRANSPORT_LE))
+ p_clcb->connected = TRUE;
+
+ /* hold the link here */
+ if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
+ return started;
+ /* enqueue the request */
+ gap_ble_enqueue_request(p_clcb, uuid, p_cback);
+
+ if (p_clcb->connected && p_clcb->cl_op_uuid == 0)
+ started = gap_ble_send_cl_read_request(p_clcb);
+ else /* wait for connection up or pending operation to finish */
+ started = TRUE;
+
+ return started;
+}
/*******************************************************************************
**
** Function GAP_BleReadPeerPrefConnParams
*******************************************************************************/
BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
{
-
- tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
-
- if (p_clcb == NULL)
- {
- if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
- {
- GAP_TRACE_ERROR("GAP_BleReadPeerPrefConnParams max connection reached");
- return FALSE;
- }
- p_clcb->connected = FALSE;
- }
-
- GAP_TRACE_API ("GAP_BleReadPeerPrefConnParams() - BDA: %08x%04x cl_op_uuid: 0x%04x",
- (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
- (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
-
- /* For now we only handle one at a time */
- if (p_clcb->cl_op_uuid != 0)
- return(FALSE);
-
- /* hold the link here */
- if (GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
- {
-
- if (p_clcb->connected)
- {
- return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
- }
- /* Mark currently active operation */
- p_clcb->cl_op_uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
-
- return(TRUE);
- }
- else
- return FALSE;
+ return gap_ble_accept_cl_operation (peer_bda, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
}
/*******************************************************************************
** Returns TRUE if request accepted
**
*******************************************************************************/
-BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback)
+BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_CMPL_CBACK *p_cback)
{
- tGAP_CLCB *p_clcb = NULL;
-
- if (p_cback == NULL)
- return(FALSE);
-
- if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL)
- {
- if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
- {
- GAP_TRACE_ERROR("GAP_BleReadPeerDevName max connection reached");
- return FALSE;
- }
- p_clcb->connected = FALSE;
- }
-
- GAP_TRACE_EVENT ("GAP_BleReadPeerDevName() - BDA: %08x%04x cl_op_uuid: 0x%04x",
- (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
- (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
-
- /* For now we only handle one at a time */
- if (p_clcb->cl_op_uuid != 0)
- return(FALSE);
-
- /* hold the link here */
-
- if (GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
- {
- if (p_clcb->connected)
- {
- return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_DEVICE_NAME, (void *)p_cback);
- }
-
- p_clcb->p_cback = (void *)p_cback;
- /* Mark currently active operation */
- p_clcb->cl_op_uuid = GATT_UUID_GAP_DEVICE_NAME;
-
-
- return(TRUE);
- }
- else
- return FALSE;
+ return gap_ble_accept_cl_operation (peer_bda, GATT_UUID_GAP_DEVICE_NAME, p_cback);
}
+/*******************************************************************************
+**
+** Function GAP_BleReadPeerAddressResolutionCap
+**
+** Description Start a process to read peer address resolution capability
+**
+** Returns TRUE if request accepted
+**
+*******************************************************************************/
+BOOLEAN GAP_BleReadPeerAddressResolutionCap (BD_ADDR peer_bda, tGAP_BLE_CMPL_CBACK *p_cback)
+{
+ return gap_ble_accept_cl_operation(peer_bda, GATT_UUID_GAP_CENTRAL_ADDR_RESOL, p_cback);
+}
/*******************************************************************************
**
(peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
(peer_bda[4]<<8)+peer_bda[5], (p_clcb == NULL)? 0 : p_clcb->cl_op_uuid);
- if (p_clcb == NULL || p_clcb->cl_op_uuid != GATT_UUID_GAP_DEVICE_NAME)
+ if (p_clcb == NULL)
{
GAP_TRACE_ERROR ("Cannot cancel current op is not get dev name");
return FALSE;
#if BLE_INCLUDED == TRUE
-#define GAP_MAX_CHAR_NUM 5
+#define GAP_MAX_CHAR_NUM 4
typedef struct
{
typedef struct
{
- union
- {
- BD_ADDR reconn_addr;
- UINT8 privacy_flag;
- } pending_data;
- UINT8 op;
- void *p_pending_cback;
-}tGAP_BLE_PENDING_OP;
+ UINT16 uuid;
+ tGAP_BLE_CMPL_CBACK *p_cback;
+} tGAP_BLE_REQ;
typedef struct
{
BD_ADDR bda;
- BD_ADDR reconn_addr;
- void * p_cback;
+ tGAP_BLE_CMPL_CBACK *p_cback;
UINT16 conn_id;
UINT16 cl_op_uuid;
- UINT16 disc_handle;
BOOLEAN in_use;
BOOLEAN connected;
- UINT8 privacy_flag;
- BUFFER_Q pending_op_q;
+ BUFFER_Q pending_req_q;
+
}tGAP_CLCB;
typedef struct
/* LE GAP attribute database */
#if BLE_INCLUDED == TRUE
tGAP_ATTR gatt_attr[GAP_MAX_CHAR_NUM];
- BD_ADDR reconn_bda;
tGAP_CLCB clcb[GAP_MAX_CL]; /* connection link*/
-
tGATT_IF gatt_if;
#endif
} tGAP_CB;
if (p_tcb->att_lcid == L2CAP_ATT_CID)
{
status = L2CA_SetFixedChannelTout (bd_addr, L2CAP_ATT_CID, idle_tout);
+
+ if (idle_tout == GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP)
+ L2CA_SetIdleTimeoutByBdAddr(p_tcb->peer_bda,
+ GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, BT_TRANSPORT_LE);
}
else
{
#define GATT_CH_CONN 2
#define GATT_CH_CFG 3
#define GATT_CH_OPEN 4
-#define GATT_CH_W4_SEC_COMP 5
-#define GATT_CH_W4_DATA_SIGN_COMP 6
typedef UINT8 tGATT_CH_STATE;
GATT_TRACE_DEBUG("gatt_init()");
memset (&gatt_cb, 0, sizeof(tGATT_CB));
+ memset (&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG));
#if defined(GATT_INITIAL_TRACE_LEVEL)
gatt_cb.trace_level = GATT_INITIAL_TRACE_LEVEL;
*******************************************************************************/
void gatt_add_a_bonded_dev_for_srv_chg (BD_ADDR bda)
{
- tGATTS_SRV_CHG *p_buf;
tGATTS_SRV_CHG_REQ req;
tGATTS_SRV_CHG srv_chg_clt;
memcpy(srv_chg_clt.bda, bda, BD_ADDR_LEN);
srv_chg_clt.srv_changed = FALSE;
- if ((p_buf = gatt_add_srv_chg_clt(&srv_chg_clt)) != NULL)
+ if (gatt_add_srv_chg_clt(&srv_chg_clt) != NULL)
{
memcpy(req.srv_chg.bda, bda, BD_ADDR_LEN);
req.srv_chg.srv_changed = FALSE;
if (gatt_cb.cb_info.p_srv_chg_callback)
(*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_ADD_CLIENT, &req, NULL);
}
-
}
/*******************************************************************************
sr_data.write_req.need_rsp = TRUE;
sr_data.write_req.handle = handle;
sr_data.write_req.len = len;
- memcpy (sr_data.write_req.value, p, len);
+ if (len != 0 && p != NULL)
+ {
+ memcpy (sr_data.write_req.value, p, len);
+ }
break;
}
GATT_TRACE_DEBUG ("gatt_end_operation status=%d op=%d subtype=%d",
status, p_clcb->operation, p_clcb->op_subtype);
+ memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
if (p_cmpl_cb != NULL && p_clcb->operation != 0)
{
if (p_clcb->operation == GATTC_OPTYPE_READ)
{
- memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
cb_data.att_value.handle = p_clcb->s_handle;
cb_data.att_value.len = p_clcb->counter;
- if (p_data)
+
+ if (p_data && p_clcb->counter)
memcpy (cb_data.att_value.value, p_data, cb_data.att_value.len);
}
BOOLEAN btsnd_hcic_ble_write_adv_params (UINT16 adv_int_min, UINT16 adv_int_max,
UINT8 adv_type, UINT8 addr_type_own,
UINT8 addr_type_dir, BD_ADDR direct_bda,
- UINT8 channel_map, UINT8 scan_filter_policy)
+ UINT8 channel_map, UINT8 adv_filter_policy)
{
BT_HDR *p;
UINT8 *pp;
UINT8_TO_STREAM (pp, addr_type_dir);
BDADDR_TO_STREAM (pp, direct_bda);
UINT8_TO_STREAM (pp, channel_map);
- UINT8_TO_STREAM (pp, scan_filter_policy);
+ UINT8_TO_STREAM (pp, adv_filter_policy);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
return (TRUE);
}
#endif
+BOOLEAN btsnd_hcic_ble_add_device_resolving_list (UINT8 addr_type_peer, BD_ADDR bda_peer,
+ UINT8 irk_peer[HCIC_BLE_IRK_SIZE],
+ UINT8 irk_local[HCIC_BLE_IRK_SIZE])
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_ADD_DEV_RESOLVING_LIST);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST);
+ UINT8_TO_STREAM (pp, addr_type_peer);
+ BDADDR_TO_STREAM (pp, bda_peer);
+ ARRAY_TO_STREAM (pp, irk_peer, HCIC_BLE_ENCRYT_KEY_SIZE);
+ ARRAY_TO_STREAM (pp, irk_local, HCIC_BLE_ENCRYT_KEY_SIZE);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_rm_device_resolving_list (UINT8 addr_type_peer, BD_ADDR bda_peer)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_RM_DEV_RESOLVING_LIST);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST);
+ UINT8_TO_STREAM (pp, addr_type_peer);
+ BDADDR_TO_STREAM (pp, bda_peer);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_clear_resolving_list (void)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_CLEAR_RESOLVING_LIST);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_resolvable_addr_peer (UINT8 addr_type_peer, BD_ADDR bda_peer)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_READ_RESOLVABLE_ADDR_PEER);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER);
+ UINT8_TO_STREAM (pp, addr_type_peer);
+ BDADDR_TO_STREAM (pp, bda_peer);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_resolvable_addr_local (UINT8 addr_type_peer, BD_ADDR bda_peer)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL);
+ UINT8_TO_STREAM (pp, addr_type_peer);
+ BDADDR_TO_STREAM (pp, bda_peer);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_set_addr_resolution_enable (UINT8 addr_resolution_enable)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_SET_ADDR_RESOLUTION_ENABLE);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE);
+ UINT8_TO_STREAM (pp, addr_resolution_enable);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+ return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_set_rand_priv_addr_timeout (UINT16 rpa_timout)
+{
+ BT_HDR *p;
+ UINT8 *pp;
+
+ if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT)) == NULL)
+ return (FALSE);
+
+ pp = (UINT8 *)(p + 1);
+
+ p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT;
+ p->offset = 0;
+
+ UINT16_TO_STREAM (pp, HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT);
+ UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT);
+ UINT16_TO_STREAM (pp, rpa_timout);
+
+ btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+ return (TRUE);
+}
+
+
#endif
/* Set l2cap idle timeout to 0 (so ACL link is disconnected
* immediately after last channel is closed) */
- L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0);
+ L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0, BT_TRANSPORT_BR_EDR);
/* Disconnect both interrupt and control channels */
if (p_hcon->intr_cid)
L2CA_DisconnectReq (p_hcon->intr_cid);
typedef UINT8 PIN_CODE[PIN_CODE_LEN]; /* Pin Code (upto 128 bits) MSB is 0 */
typedef UINT8 *PIN_CODE_PTR; /* Pointer to Pin Code */
+#define BT_OCTET32_LEN 32
+typedef UINT8 BT_OCTET32[BT_OCTET32_LEN]; /* octet array: size 32 */
+
#define DEV_CLASS_LEN 3
typedef UINT8 DEV_CLASS[DEV_CLASS_LEN]; /* Device class */
typedef UINT8 *DEV_CLASS_PTR; /* Pointer to Device class */
*/
#define BLE_ADDR_PUBLIC 0x00
#define BLE_ADDR_RANDOM 0x01
-#define BLE_ADDR_TYPE_MASK (BLE_ADDR_RANDOM | BLE_ADDR_PUBLIC)
+#define BLE_ADDR_PUBLIC_ID 0x02
+#define BLE_ADDR_RANDOM_ID 0x03
typedef UINT8 tBLE_ADDR_TYPE;
+#define BLE_ADDR_TYPE_MASK (BLE_ADDR_RANDOM | BLE_ADDR_PUBLIC)
+
#define BT_TRANSPORT_BR_EDR 1
#define BT_TRANSPORT_LE 2
#include "sdp_api.h"
#include "hcidefs.h"
-#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
#include "smp_api.h"
-#endif
/*****************************************************************************
** DEVICE CONTROL and COMMON
*****************************************************************************/
#define BTM_SSP_INQUIRY_ACTIVE 0x4 /* SSP is active, so inquiry is disallowed (work around for FW bug) */
#define BTM_LE_GENERAL_INQUIRY_ACTIVE BTM_BLE_GENERAL_INQUIRY /* a general inquiry is in progress */
#define BTM_LE_LIMITED_INQUIRY_ACTIVE BTM_BLE_LIMITED_INQUIRY /* a limited inquiry is in progress */
-#define BTM_LE_SELECT_CONN_ACTIVE 0x40 /* selection connection is in progress */
-#define BTM_LE_OBSERVE_ACTIVE 0x80 /* selection connection is in progress */
/* inquiry activity mask */
#define BTM_BR_INQ_ACTIVE_MASK (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE|BTM_PERIODIC_INQUIRY_ACTIVE) /* BR/EDR inquiry activity mask */
#define BTM_SEC_MODE_LINK 3
#define BTM_SEC_MODE_SP 4
#define BTM_SEC_MODE_SP_DEBUG 5
+#define BTM_SEC_MODE_SC 6
/* Security Service Levels [bit mask] (BTM_SetSecurityLevel)
** Encryption should not be used without authentication
#define BTM_LKEY_TYPE_UNAUTH_COMB HCI_LKEY_TYPE_UNAUTH_COMB
#define BTM_LKEY_TYPE_AUTH_COMB HCI_LKEY_TYPE_AUTH_COMB
#define BTM_LKEY_TYPE_CHANGED_COMB HCI_LKEY_TYPE_CHANGED_COMB
+
+#define BTM_LKEY_TYPE_UNAUTH_COMB_P_256 HCI_LKEY_TYPE_UNAUTH_COMB_P_256
+#define BTM_LKEY_TYPE_AUTH_COMB_P_256 HCI_LKEY_TYPE_AUTH_COMB_P_256
+
+#define BTM_LTK_DERIVED_LKEY_OFFSET 0x20 /* "easy" requirements for LK derived from LTK */
#define BTM_LKEY_TYPE_IGNORE 0xff /* used when event is response from
hci return link keys request */
+typedef UINT8 tBTM_LINK_KEY_TYPE;
+
/* Protocol level security (BTM_SetSecurityLevel) */
#define BTM_SEC_PROTO_L2CAP 0
#define BTM_SEC_PROTO_SDP 1
enum
{
- BTM_SP_KEY_STARTED, /* passkey entry started */
- BTM_SP_KEY_ENTERED, /* passkey digit entered */
- BTM_SP_KEY_ERASED, /* passkey digit erased */
- BTM_SP_KEY_CLEARED, /* passkey cleared */
- BTM_SP_KEY_COMPLT /* passkey entry completed */
+ BTM_SP_KEY_STARTED, /* 0 - passkey entry started */
+ BTM_SP_KEY_ENTERED, /* 1 - passkey digit entered */
+ BTM_SP_KEY_ERASED, /* 2 - passkey digit erased */
+ BTM_SP_KEY_CLEARED, /* 3 - passkey cleared */
+ BTM_SP_KEY_COMPLT, /* 4 - passkey entry completed */
+ BTM_SP_KEY_OUT_OF_RANGE /* 5 - out of range */
};
typedef UINT8 tBTM_SP_KEY_TYPE;
/* LE related event and data structure
*/
-enum
-{
- BTM_LE_IO_REQ_EVT = 1, /* received IO_CAPABILITY_REQUEST event */
- BTM_LE_SEC_REQUEST_EVT, /* security request event */
- BTM_LE_KEY_NOTIF_EVT, /* received USER_PASSKEY_NOTIFY event */
- BTM_LE_KEY_REQ_EVT, /* received USER_PASSKEY_REQUEST event */
- BTM_LE_OOB_REQ_EVT, /* OOB data request event */
- BTM_LE_COMPLT_EVT, /* received SIMPLE_PAIRING_COMPLETE event */
- BTM_LE_KEY_EVT /* KEY update event */
-};
+#define BTM_LE_IO_REQ_EVT SMP_IO_CAP_REQ_EVT /* received IO_CAPABILITY_REQUEST event */
+#define BTM_LE_SEC_REQUEST_EVT SMP_SEC_REQUEST_EVT /* security request event */
+#define BTM_LE_KEY_NOTIF_EVT SMP_PASSKEY_NOTIF_EVT /* received USER_PASSKEY_NOTIFY event */
+#define BTM_LE_KEY_REQ_EVT SMP_PASSKEY_REQ_EVT /* received USER_PASSKEY_REQUEST event */
+#define BTM_LE_OOB_REQ_EVT SMP_OOB_REQ_EVT /* OOB data request event */
+#define BTM_LE_NC_REQ_EVT SMP_NC_REQ_EVT /* Numeric Comparison request event */
+#define BTM_LE_PR_KEYPR_NOT_EVT SMP_PEER_KEYPR_NOT_EVT /* Peer keypress notification recd event */
+/* SC OOB request event (both local and peer OOB data) can be expected in response */
+#define BTM_LE_SC_OOB_REQ_EVT SMP_SC_OOB_REQ_EVT
+/* SC OOB local data set is created (as result of SMP_CrLocScOobData(...)) */
+#define BTM_LE_SC_LOC_OOB_EVT SMP_SC_LOC_OOB_DATA_UP_EVT
+#define BTM_LE_BR_KEYS_REQ_EVT SMP_BR_KEYS_REQ_EVT /* SMP over BR keys request event */
+#define BTM_LE_COMPLT_EVT SMP_COMPLT_EVT /* SMP complete event */
+#define BTM_LE_LAST_FROM_SMP BTM_LE_BR_KEYS_REQ_EVT
+#define BTM_LE_KEY_EVT BTM_LE_LAST_FROM_SMP + 1 /* KEY update event */
typedef UINT8 tBTM_LE_EVT;
+#define BTM_LE_KEY_NONE 0
#define BTM_LE_KEY_PENC SMP_SEC_KEY_TYPE_ENC /* encryption information of peer device */
#define BTM_LE_KEY_PID SMP_SEC_KEY_TYPE_ID /* identity key of the peer device */
-#define BTM_LE_KEY_PCSRK SMP_SEC_KEY_TYPE_CSRK /* peer SRK */
-#define BTM_LE_KEY_LENC (SMP_SEC_KEY_TYPE_ENC << 3) /* master role security information:div */
-#define BTM_LE_KEY_LID (SMP_SEC_KEY_TYPE_ID << 3) /* master device ID key */
-#define BTM_LE_KEY_LCSRK (SMP_SEC_KEY_TYPE_CSRK << 3) /* local CSRK has been deliver to peer */
+#define BTM_LE_KEY_PCSRK SMP_SEC_KEY_TYPE_CSRK /* peer SRK */
+#define BTM_LE_KEY_PLK SMP_SEC_KEY_TYPE_LK
+#define BTM_LE_KEY_LLK (SMP_SEC_KEY_TYPE_LK << 4)
+#define BTM_LE_KEY_LENC (SMP_SEC_KEY_TYPE_ENC << 4) /* master role security information:div */
+#define BTM_LE_KEY_LID (SMP_SEC_KEY_TYPE_ID << 4) /* master device ID key */
+#define BTM_LE_KEY_LCSRK (SMP_SEC_KEY_TYPE_CSRK << 4) /* local CSRK has been deliver to peer */
typedef UINT8 tBTM_LE_KEY_TYPE;
#define BTM_LE_AUTH_REQ_NO_BOND SMP_AUTH_NO_BOND /* 0 */
#define BTM_LE_AUTH_REQ_BOND SMP_AUTH_GEN_BOND /* 1 << 0 */
#define BTM_LE_AUTH_REQ_MITM SMP_AUTH_YN_BIT /* 1 << 2 */
typedef UINT8 tBTM_LE_AUTH_REQ;
+#define BTM_LE_SC_SUPPORT_BIT SMP_SC_SUPPORT_BIT /* (1 << 3) */
+#define BTM_LE_KP_SUPPORT_BIT SMP_KP_SUPPORT_BIT /* (1 << 4) */
-#define BTM_LE_AUTH_REQ_MASK SMP_AUTH_MASK /* 0x03*/
+#define BTM_LE_AUTH_REQ_SC_ONLY SMP_AUTH_SC_ENC_ONLY /* 1 << 3 */
+#define BTM_LE_AUTH_REQ_SC_BOND SMP_AUTH_SC_GB /* 1001 */
+#define BTM_LE_AUTH_REQ_SC_MITM SMP_AUTH_SC_MITM_NB /* 1100 */
+#define BTM_LE_AUTH_REQ_SC_MITM_BOND SMP_AUTH_SC_MITM_GB /* 1101 */
+#define BTM_LE_AUTH_REQ_MASK SMP_AUTH_MASK /* 0x1D */
/* LE security level */
#define BTM_LE_SEC_NONE SMP_SEC_NONE
{
UINT8 reason;
UINT8 sec_level;
- BOOLEAN privacy_supported;
BOOLEAN is_pair_cancel;
}tBTM_LE_COMPLT;
#endif
/* BLE Encryption reproduction keys */
typedef struct
{
+ BT_OCTET16 ltk;
UINT16 div;
UINT8 key_size;
UINT8 sec_level;
UINT32 counter;
UINT16 div;
UINT8 sec_level;
-
+ BT_OCTET16 csrk;
}tBTM_LE_LCSRK_KEYS;
typedef struct
typedef union
{
tBTM_LE_PENC_KEYS penc_key; /* received peer encryption key */
- tBTM_LE_PCSRK_KEYS pcsrk_key; /* received peer device SRK */
+ tBTM_LE_PCSRK_KEYS pcsrk_key; /* received peer device SRK */
tBTM_LE_PID_KEYS pid_key; /* peer device ID key */
tBTM_LE_LENC_KEYS lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
- tBTM_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
+ tBTM_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
}tBTM_LE_KEY_VALUE;
typedef struct
{
tBTM_LE_IO_REQ io_req; /* BTM_LE_IO_REQ_EVT */
UINT32 key_notif; /* BTM_LE_KEY_NOTIF_EVT */
- /* no callback dta for BTM_LE_KEY_REQ_EVT & BTM_LE_OOB_REQ_EVT */
+ /* BTM_LE_NC_REQ_EVT */
+ /* no callback data for BTM_LE_KEY_REQ_EVT */
+ /* and BTM_LE_OOB_REQ_EVT */
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
tBTM_LE_COMPLT complt; /* BTM_LE_COMPLT_EVT */
+ tSMP_OOB_DATA_TYPE req_oob_type;
#endif
tBTM_LE_KEY key;
} tBTM_LE_EVT_DATA;
/*******************************************************************************
**
+** Function BTM_SecGetDeviceLinkKeyType
+**
+** Description This function is called to obtain link key type for the
+** device.
+** it returns BTM_SUCCESS if link key is available, or
+** BTM_UNKNOWN_ADDR if Security Manager does not know about
+** the device or device record does not contain link key info
+**
+** Returns BTM_LKEY_TYPE_IGNORE if link key is unknown, link type
+** otherwise.
+**
+*******************************************************************************/
+extern tBTM_LINK_KEY_TYPE BTM_SecGetDeviceLinkKeyType (BD_ADDR bd_addr);
+
+
+/*******************************************************************************
+**
** Function BTM_PINCodeReply
**
** Description This function is called after Security Manager submitted
/*******************************************************************************
**
+** Function BTM_IsLeScSuppLocally
+**
+** Description This function is called to check if LE SC is supported.
+**
+** Parameters: None.
+**
+** Returns Boolean - TRUE if LE SC is supported.
+*******************************************************************************/
+extern BOOLEAN BTM_IsLeScSuppLocally (void);
+
+/*******************************************************************************
+**
** Function BTM_ReadOobData
**
** Description This function is called to parse the OOB data payload
#define BTM_BLE_UNKNOWN_EVT 0xff
+typedef UINT8 tBTM_BLE_EVT;
+typedef UINT8 tBTM_BLE_CONN_MODE;
+
typedef UINT32 tBTM_BLE_REF_VALUE;
#define BTM_BLE_SCAN_MODE_PASS 0
#endif
/* scanning filter policy */
-#define SP_ADV_ALL 0x00 /* accept adv pakt from all, directed adv pkt not directed to me is ignored */
-#define SP_ADV_WL 0x01 /* accept adv pakt from device in white list, directed adv pkt not directed to me is ignored */
+#define SP_ADV_ALL 0x00 /* 0: accept adv packet from all, directed adv pkt not directed */
+ /* to local device is ignored */
+#define SP_ADV_WL 0x01 /* 1: accept adv packet from device in white list, directed adv */
+ /* packet not directed to local device is ignored */
+#define SP_ADV_ALL_RPA_DIR_ADV 0x02 /* 2: accept adv packet from all, directed adv pkt */
+ /* not directed to me is ignored except direct adv with RPA */
+#define SP_ADV_WL_RPA_DIR_ADV 0x03 /* 3: accept adv packet from device in white list, directed */
+ /* adv pkt not directed to me is ignored except direct adv */
+ /* with RPA */
typedef UINT8 tBTM_BLE_SFP;
#ifndef BTM_BLE_DEFAULT_SFP
#define BTM_BLE_AD_TYPE_MANU HCI_EIR_MANUFACTURER_SPECIFIC_TYPE /* 0xff */
typedef UINT8 tBTM_BLE_AD_TYPE;
+/* security settings used with L2CAP LE COC */
+#define BTM_SEC_LE_LINK_ENCRYPTED 0x01
+#define BTM_SEC_LE_LINK_PAIRED_WITHOUT_MITM 0x02
+#define BTM_SEC_LE_LINK_PAIRED_WITH_MITM 0x04
/* adv tx power level */
#define BTM_BLE_ADV_TX_POWER_MIN 0 /* minimum tx power */
#define BTM_BLE_ADV_TX_POWER_LOW 1 /* low tx power */
/*******************************************************************************
**
+** Function BTM_BleConfirmReply
+**
+** Description This function is called after Security Manager submitted
+** numeric comparison request to the application.
+**
+** Parameters: bd_addr - Address of the device with which numeric
+** comparison was requested
+** res - comparison result BTM_SUCCESS if success
+**
+*******************************************************************************/
+extern void BTM_BleConfirmReply (BD_ADDR bd_addr, UINT8 res);
+
+/*******************************************************************************
+**
** Function BTM_LeOobDataReply
**
** Description This function is called to provide the OOB data for
/*******************************************************************************
**
-** Function BTM_RegisterScanReqEvt
-**
-** Description This function is called to register a scan request callback
-** on the advertiser.
-**
-** Parameters p_scan_req_cback: scan request callback. If NULL, remove the
-** registration.
-**
-** Returns void
-**
-*******************************************************************************/
-extern void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback);
-
-/*******************************************************************************
-**
** Function BTM_BleConfigPrivacy
**
** Description This function is called to enable or disable the privacy in
**
** Parameters enable: TRUE to enable it; FALSE to disable it.
**
-** Returns void
+** Returns BOOLEAN privacy mode set success; otherwise failed.
**
*******************************************************************************/
-extern void BTM_BleConfigPrivacy(BOOLEAN enable);
+extern BOOLEAN BTM_BleConfigPrivacy(BOOLEAN enable);
/*******************************************************************************
**
** Returns Return TRUE if local privacy is enabled else FALSE
**
*******************************************************************************/
-extern BOOLEAN BTM_BleLocalPrivacyEnabled();
+extern BOOLEAN BTM_BleLocalPrivacyEnabled(void);
+
+/*******************************************************************************
+**
+** Function BTM_BleEnableMixedPrivacyMode
+**
+** Description This function is called to enabled Mixed mode if privacy 1.2
+** is applicable in controller.
+**
+** Parameters mixed_on: mixed mode to be used or not.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void BTM_BleEnableMixedPrivacyMode(BOOLEAN mixed_on);
/*******************************************************************************
**
/*******************************************************************************
**
-** Function BTM_BleSetConnMode
+** Function BTM_BleSetConnectableMode
**
** Description This function is called to set BLE connectable mode for a
** peripheral device.
**
-** Parameters directed: is directed connectable mode, or non-directed.
-** p_dir_bda: connectable direct initiator's LE device address
+** Parameters connectable_mode: directed connectable mode, or non-directed.It can
+** be BTM_BLE_CONNECT_EVT, BTM_BLE_CONNECT_DIR_EVT or
+** BTM_BLE_CONNECT_LO_DUTY_DIR_EVT
**
-** Returns void
+** Returns BTM_ILLEGAL_VALUE if controller does not support BLE.
+** BTM_SUCCESS is status set successfully; otherwise failure.
**
*******************************************************************************/
-extern tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed);
+extern tBTM_STATUS BTM_BleSetConnectableMode(tBTM_BLE_CONN_MODE connectable_mode);
/*******************************************************************************
**
extern void BTM_BleTurnOnPrivacyOnRemote(BD_ADDR bd_addr,
BOOLEAN privacy_on);
-
/*******************************************************************************
**
** Function BTM_BleUpdateAdvWhitelist
*******************************************************************************/
extern tBTM_STATUS BTM_BleStackEnable (BOOLEAN enable);
+/*******************************************************************************
+**
+** Function BTM_GetLeSecurityState
+**
+** Description This function is called to get security mode 1 flags and
+** encryption key size for LE peer.
+**
+** Returns BOOLEAN TRUE if LE device is found, FALSE otherwise.
+**
+*******************************************************************************/
+extern BOOLEAN BTM_GetLeSecurityState (BD_ADDR bd_addr,
+ UINT8 *p_le_dev_sec_flags,
+ UINT8 *p_le_key_size);
+
+/*******************************************************************************
+**
+** Function BTM_BleSecurityProcedureIsRunning
+**
+** Description This function indicates if LE security procedure is
+** currently running with the peer.
+**
+** Returns BOOLEAN TRUE if security procedure is running, FALSE otherwise.
+**
+*******************************************************************************/
+extern BOOLEAN BTM_BleSecurityProcedureIsRunning (BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTM_BleGetSupportedKeySize
+**
+** Description This function gets the maximum encryption key size in bytes
+** the local device can suport.
+** record.
+**
+** Returns the key size or 0 if the size can't be retrieved.
+**
+*******************************************************************************/
+extern UINT8 BTM_BleGetSupportedKeySize (BD_ADDR bd_addr);
+
/*******************************************************************************/
/* Multi ADV API */
/*******************************************************************************
BD_ADDR reconn_bda;
UINT16 icon;
UINT8 *p_dev_name;
- UINT8 privacy;
+ UINT8 addr_resolution;
}tGAP_BLE_ATTR_VALUE;
-typedef void (tGAP_BLE_DEV_NAME_CBACK)(BOOLEAN status, BD_ADDR addr, UINT16 length, char *p_name);
+typedef void (tGAP_BLE_CMPL_CBACK)(BOOLEAN status, BD_ADDR addr, UINT16 length, char *p_name);
-typedef void (tGAP_BLE_RECONN_ADDR_CBACK)(BOOLEAN status, BD_ADDR addr, BD_ADDR reconn_bda);
/*****************************************************************************
** External Function Declarations
** Returns TRUE if request accepted
**
*******************************************************************************/
-extern BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback);
+extern BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_CMPL_CBACK *p_cback);
/*******************************************************************************
**
-** Function GAP_BleCancelReadPeerDevName
+** Function GAP_BleReadPeerAddressResolutionCap
**
-** Description Cancel reading a peripheral's device name.
+** Description Start a process to read peer address resolution capability
**
** Returns TRUE if request accepted
**
*******************************************************************************/
-extern BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda);
+extern BOOLEAN GAP_BleReadPeerAddressResolutionCap (BD_ADDR peer_bda,
+ tGAP_BLE_CMPL_CBACK *p_cback);
/*******************************************************************************
**
-** Function GAP_BleUpdateReconnectAddr
+** Function GAP_BleCancelReadPeerDevName
**
-** Description Start a process to udpate the reconnect address if remote devive
-** has privacy enabled.
+** Description Cancel reading a peripheral's device name.
**
-** Returns TRUE if read started, else FALSE if GAP is busy
+** Returns TRUE if request accepted
**
*******************************************************************************/
-extern BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda,
- BD_ADDR reconn_addr,
- tGAP_BLE_RECONN_ADDR_CBACK *p_cback);
+extern BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda);
+
#endif
/* GAP Profile Attributes
*/
-#define GATT_UUID_GAP_DEVICE_NAME 0x2A00
-#define GATT_UUID_GAP_ICON 0x2A01
-#define GATT_UUID_GAP_PRIVACY_FLAG 0x2A02
-#define GATT_UUID_GAP_RECONN_ADDR 0x2A03
-#define GATT_UUID_GAP_PREF_CONN_PARAM 0x2A04
+#define GATT_UUID_GAP_DEVICE_NAME 0x2A00
+#define GATT_UUID_GAP_ICON 0x2A01
+#define GATT_UUID_GAP_PREF_CONN_PARAM 0x2A04
+#define GATT_UUID_GAP_CENTRAL_ADDR_RESOL 0x2A05
/* Attribute Profile Attribute UUID */
-#define GATT_UUID_GATT_SRV_CHGD 0x2A05
+#define GATT_UUID_GATT_SRV_CHGD 0x2A05
/* Attribute Protocol Test */
/* Link Loss Service */
#define GATT_UUID_NW_TRIGGER 0x2A1A /* Network availability trigger */
/* phone alert */
-#define GATT_UUID_ALERT_STATUS 0x2A40 /* alert status */
-#define GATT_UUID_RINGER_CP 0x2A42 /* ringer control point */
+#define GATT_UUID_ALERT_STATUS 0x2A3F /* alert status */
+#define GATT_UUID_RINGER_CP 0x2A40 /* ringer control point */
#define GATT_UUID_RINGER_SETTING 0x2A41 /* ringer setting */
/* Glucose Service */
#define HCI_OCF(p) ( 0x3FF & (p))
/*
-** Defentions for Link Control Commands
+** Definitions for Link Control Commands
*/
/* Following opcode is used only in command complete event for flow control */
#define HCI_COMMAND_NONE 0x0000
#define HCI_READ_SYNC_TRAIN_PARAM (0x0077 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_WRITE_SYNC_TRAIN_PARAM (0x0078 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SECURE_CONNS_SUPPORT (0x0079 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SECURE_CONNS_SUPPORT (0x007A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
#define HCI_CONT_BASEBAND_CMDS_FIRST HCI_SET_EVENT_MASK
#define HCI_CONT_BASEBAND_CMDS_LAST HCI_READ_SYNC_TRAIN_PARAM
#define HCI_BLE_LTK_REQ_NEG_REPLY (0x001B | HCI_GRP_BLE_CMDS)
#define HCI_BLE_READ_SUPPORTED_STATES (0x001C | HCI_GRP_BLE_CMDS)
/*0x001D, 0x001E and 0x001F are reserved*/
-
+#define HCI_BLE_RECEIVER_TEST (0x001D | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_TRANSMITTER_TEST (0x001E | HCI_GRP_BLE_CMDS)
+/* BLE TEST COMMANDS */
+#define HCI_BLE_TEST_END (0x001F | HCI_GRP_BLE_CMDS)
#define HCI_BLE_RC_PARAM_REQ_REPLY (0x0020 | HCI_GRP_BLE_CMDS)
#define HCI_BLE_RC_PARAM_REQ_NEG_REPLY (0x0021 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_ADD_DEV_RESOLVING_LIST (0x0027 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_RM_DEV_RESOLVING_LIST (0x0028 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_CLEAR_RESOLVING_LIST (0x0029 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_RESOLVING_LIST_SIZE (0x002A | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_RESOLVABLE_ADDR_PEER (0x002B | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL (0x002C | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_ADDR_RESOLUTION_ENABLE (0x002D | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT (0x002E | HCI_GRP_BLE_CMDS)
-/* BLE TEST COMMANDS */
-#define HCI_BLE_RECEIVER_TEST (0x001D | HCI_GRP_BLE_CMDS)
-#define HCI_BLE_TRANSMITTER_TEST (0x001E | HCI_GRP_BLE_CMDS)
-#define HCI_BLE_TEST_END (0x001F | HCI_GRP_BLE_CMDS)
/* LE Get Vendor Capabilities Command OCF */
#define HCI_BLE_VENDOR_CAP_OCF (0x0153 | HCI_GRP_VENDOR_SPECIFIC)
#define HCI_SUPP_LE_STATES_INIT_MASTER_OFF 3
#define HCI_LE_STATES_INIT_MASTER_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_INIT_MASTER_OFF] & HCI_SUPP_LE_STATES_INIT_MASTER_MASK)
+/*Low Duty Cycle Directed Advertising State . 0x0000000020000000 */
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASK 0x20
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_OFF 3
+#define HCI_LE_STATES_LOW_DUTY_DIR_ADV_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_LOW_DUTY_DIR_ADV_OFF] & HCI_SUPP_LE_STATES_LOW_DUTY_DIR_ADV_MASK)
+
+/*Low Duty Cycle Directed Advertising State and Passive scan combination. 0x0000000040000000 */
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_MASK 0x40
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_OFF 3
+#define HCI_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_OFF] & HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_MASK)
+
+/*Low Duty Cycle Directed Advertising State and Active scan combination . 0x0000000080000000 */
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_MASK 0x80
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_OFF 3
+#define HCI_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_SUPPORTED(x) ((x)[HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_OFF] & HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_MASK)
+
/* Connectable Advertising State and Initiating State combination supported. 0x0000000100000000 */
#define HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK 0x01
#define HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF 4
#define HCI_SET_TRIGGERED_CLOCK_CAPTURE_EVT 0x4E
/* ULP HCI Event */
-#define HCI_BLE_EVENT 0x03E
+#define HCI_BLE_EVENT 0x3e
/* ULP Event sub code */
#define HCI_BLE_CONN_COMPLETE_EVT 0x01
#define HCI_BLE_ADV_PKT_RPT_EVT 0x02
#define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT 0x04
#define HCI_BLE_LTK_REQ_EVT 0x05
#define HCI_BLE_RC_PARAM_REQ_EVT 0x06
+#define HCI_BLE_DATA_LENGTH_CHANGE_EVT 0x07
+#define HCI_BLE_ENHANCED_CONN_COMPLETE_EVT 0x0a
+#define HCI_BLE_DIRECT_ADV_EVT 0x0b
/* Definitions for LE Channel Map */
#define HCI_BLE_CHNL_MAP_SIZE 5
because conflict w/ TCI_EVT and per
specification compliant */
-/* the event mask for BLE event mask */
-#define HCI_BLE_EVENT_MASK_DEF "\x00\x00\x00\x00\x00\x00\x00\x3f"
-
-
-
/*
** Defentions for HCI Error Codes that are past in the events
*/
0x0000000000200000 Connectionless Broadcast Channel Map Change Event
0x0000000000400000 Inquiry Response Notification Event
*/
-
+#if BLE_PRIVACY_SPT == TRUE
+/* BLE event mask */
+#define HCI_BLE_EVENT_MASK_DEF "\x00\x00\x00\x00\x00\x00\x07\xff"
+#else
+#define HCI_BLE_EVENT_MASK_DEF "\x00\x00\x00\x00\x00\x00\x00\x7f"
+#endif
/*
** Definitions for packet type masks (BT1.2 and BT2.0 definitions)
*/
#define HCI_SPD_MODE_DISABLED 0x00
#define HCI_SPD_MODE_ENABLED 0x01
+/* Definitions for Write Secure Connections Host Support */
+#define HCI_SC_MODE_DISABLED 0x00
+#define HCI_SC_MODE_ENABLED 0x01
+
/* Definitions for IO Capability Response/Command */
#define HCI_IO_CAP_DISPLAY_ONLY 0x00
#define HCI_IO_CAP_DISPLAY_YESNO 0x01
#define HCI_LKEY_TYPE_UNAUTH_COMB 0x04
#define HCI_LKEY_TYPE_AUTH_COMB 0x05
#define HCI_LKEY_TYPE_CHANGED_COMB 0x06
+#define HCI_LKEY_TYPE_UNAUTH_COMB_P_256 0x07
+#define HCI_LKEY_TYPE_AUTH_COMB_P_256 0x08
/* Internal definitions - not used over HCI */
#define HCI_LKEY_TYPE_AMP_WIFI 0x80
#define HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_OFF 0
#define HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(x) ((x)[HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_OFF] & HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_MASK)
+/* Enhanced privacy Feature: bit 6 */
+#define HCI_LE_FEATURE_ENHANCED_PRIVACY_MASK 0x40
+#define HCI_LE_FEATURE_ENHANCED_PRIVACY_OFF 0
+#define HCI_LE_ENHANCED_PRIVACY_SUPPORTED(x) ((x)[HCI_LE_FEATURE_ENHANCED_PRIVACY_OFF] & HCI_LE_FEATURE_ENHANCED_PRIVACY_MASK)
+
+
+/* Extended scanner filter policy : 7 */
+#define HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_MASK 0x80
+#define HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_OFF 0
+#define HCI_LE_EXT_SCAN_FILTER_POLICY_SUPPORTED(x) ((x)[HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_OFF] & HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_MASK)
+
/*
** Local Supported Commands encoding
*/
** BLE Commands
** Note: "local_controller_id" is for transport, not counted in HCI message size
*********************************************************************************/
+#define HCIC_BLE_RAND_DI_SIZE 8
+#define HCIC_BLE_ENCRYT_KEY_SIZE 16
+#define HCIC_BLE_IRK_SIZE 16
+
#define HCIC_PARAM_SIZE_SET_USED_FEAT_CMD 8
#define HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD 6
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS 15
#define HCIC_BLE_CHNL_MAP_SIZE 5
#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31
+#define HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST (7 + HCIC_BLE_IRK_SIZE * 2)
+#define HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST 7
+#define HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST 0
+#define HCIC_PARAM_SIZE_BLE_READ_RESOLVING_LIST_SIZE 0
+#define HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER 7
+#define HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL 7
+#define HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE 1
+#define HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT 2
+
/* ULP HCI command */
extern BOOLEAN btsnd_hcic_ble_set_evt_mask (BT_EVENT_MASK event_mask);
extern BOOLEAN btsnd_hcic_ble_write_adv_params (UINT16 adv_int_min, UINT16 adv_int_max,
UINT8 adv_type, UINT8 addr_type_own,
UINT8 addr_type_dir, BD_ADDR direct_bda,
- UINT8 channel_map, UINT8 scan_filter_policy);
+ UINT8 channel_map, UINT8 adv_filter_policy);
extern BOOLEAN btsnd_hcic_ble_read_adv_chnl_tx_power (void);
#endif /* BLE_LLT_INCLUDED */
+extern BOOLEAN btsnd_hcic_ble_add_device_resolving_list (UINT8 addr_type_peer,
+ BD_ADDR bda_peer,
+ UINT8 irk_peer[HCIC_BLE_IRK_SIZE],
+ UINT8 irk_local[HCIC_BLE_IRK_SIZE]);
+
+extern BOOLEAN btsnd_hcic_ble_rm_device_resolving_list (UINT8 addr_type_peer,
+ BD_ADDR bda_peer);
+
+extern BOOLEAN btsnd_hcic_ble_clear_resolving_list (void);
+
+extern BOOLEAN btsnd_hcic_ble_read_resolvable_addr_peer (UINT8 addr_type_peer,
+ BD_ADDR bda_peer);
+
+extern BOOLEAN btsnd_hcic_ble_read_resolvable_addr_local (UINT8 addr_type_peer,
+ BD_ADDR bda_peer);
+
+extern BOOLEAN btsnd_hcic_ble_set_addr_resolution_enable (UINT8 addr_resolution_enable);
+
+extern BOOLEAN btsnd_hcic_ble_set_rand_priv_addr_timeout (UINT16 rpa_timout);
+
#endif /* BLE_INCLUDED */
+extern BOOLEAN btsnd_hcic_read_authenticated_payload_tout(UINT16 handle);
+
+extern BOOLEAN btsnd_hcic_write_authenticated_payload_tout(UINT16 handle,
+ UINT16 timeout);
+
+#define HCIC_PARAM_SIZE_WRITE_AUTHENT_PAYLOAD_TOUT 4
+
+#define HCI__WRITE_AUTHENT_PAYLOAD_TOUT_HANDLE_OFF 0
+#define HCI__WRITE_AUTHENT_PAYLOAD_TOUT_TOUT_OFF 2
+
#endif
** NOTE This timeout applies to all logical channels active on the
** ACL link.
*******************************************************************************/
-extern BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout);
+extern BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout,
+ tBT_TRANSPORT transport);
/*******************************************************************************
**
tL2CAP_FCR_OPTS fixed_chnl_opts;
UINT16 default_idle_tout;
+ tL2CA_TX_COMPLETE_CB *pL2CA_FixedTxComplete_Cb; /* fixed channel tx complete callback */
} tL2CAP_FIXED_CHNL_REG;
#define L2CAP_CMD_REJ_INVALID_CID 2
-/* L2CAP Predefined CIDs (0x0004-0x003E Reserved)
+/* L2CAP Predefined CIDs
*/
#define L2CAP_SIGNALLING_CID 1
#define L2CAP_CONNECTIONLESS_CID 2
#define L2CAP_ATT_CID 4
#define L2CAP_BLE_SIGNALLING_CID 5
#define L2CAP_SMP_CID 6
+#define L2CAP_SMP_BR_CID 7
#define L2CAP_AMP_TEST_CID 0x003F
#define L2CAP_BASE_APPL_CID 0x0040
+#define L2CAP_BLE_CONN_MAX_CID 0x007F
-/* Fixed Channels mask bits
-*/
-#define L2CAP_FIXED_CHNL_SIG_BIT (1 << L2CAP_SIGNALLING_CID) /* Signal Channel Supported (Mandatory) */
-#define L2CAP_FIXED_CHNL_CNCTLESS_BIT (1 << L2CAP_CONNECTIONLESS_CID) /* Connectionless Reception */
-#define L2CAP_FIXED_CHNL_AMP_BIT (1 << L2CAP_AMP_CID) /* AMP Manager Supported */
-#define L2CAP_FIXED_CHNL_ATT_BIT (1 << L2CAP_ATT_CID) /* Attribute protocol Supported */
-#define L2CAP_FIXED_CHNL_BLE_SIG_BIT (1 << L2CAP_BLE_SIGNALLING_CID) /* BLE Signalling Supported */
-#define L2CAP_FIXED_CHNL_SMP_BIT (1 << L2CAP_SMP_CID) /* BLE Security Manager Supported */
+/* Fixed Channels mask bits */
+
+/* Signal channel supported (Mandatory) */
+#define L2CAP_FIXED_CHNL_SIG_BIT (1 << L2CAP_SIGNALLING_CID)
+
+/* Connectionless reception */
+#define L2CAP_FIXED_CHNL_CNCTLESS_BIT (1 << L2CAP_CONNECTIONLESS_CID)
+
+/* AMP Manager supported */
+#define L2CAP_FIXED_CHNL_AMP_BIT (1 << L2CAP_AMP_CID)
+
+/* Attribute protocol supported */
+#define L2CAP_FIXED_CHNL_ATT_BIT (1 << L2CAP_ATT_CID)
+
+/* BLE Signalling supported */
+#define L2CAP_FIXED_CHNL_BLE_SIG_BIT (1 << L2CAP_BLE_SIGNALLING_CID)
+
+/* BLE Security Mgr supported */
+#define L2CAP_FIXED_CHNL_SMP_BIT (1 << L2CAP_SMP_CID)
+
+/* Security Mgr over BR supported */
+#define L2CAP_FIXED_CHNL_SMP_BR_BIT (1 << L2CAP_SMP_BR_CID)
#define SMP_PIN_CODE_LEN_MAX PIN_CODE_LEN
#define SMP_PIN_CODE_LEN_MIN 6
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+/* SMP command code */
+#define SMP_OPCODE_PAIRING_REQ 0x01
+#define SMP_OPCODE_PAIRING_RSP 0x02
+#define SMP_OPCODE_CONFIRM 0x03
+#define SMP_OPCODE_RAND 0x04
+#define SMP_OPCODE_PAIRING_FAILED 0x05
+#define SMP_OPCODE_ENCRYPT_INFO 0x06
+#define SMP_OPCODE_MASTER_ID 0x07
+#define SMP_OPCODE_IDENTITY_INFO 0x08
+#define SMP_OPCODE_ID_ADDR 0x09
+#define SMP_OPCODE_SIGN_INFO 0x0A
+#define SMP_OPCODE_SEC_REQ 0x0B
+#define SMP_OPCODE_PAIR_PUBLIC_KEY 0x0C
+#define SMP_OPCODE_PAIR_DHKEY_CHECK 0x0D
+#define SMP_OPCODE_PAIR_KEYPR_NOTIF 0x0E
+#define SMP_OPCODE_MAX SMP_OPCODE_PAIR_KEYPR_NOTIF
+#define SMP_OPCODE_MIN SMP_OPCODE_PAIRING_REQ
+#define SMP_OPCODE_PAIR_COMMITM 0x0F
+#endif
+
/* SMP event type */
#define SMP_IO_CAP_REQ_EVT 1 /* IO capability request event */
#define SMP_SEC_REQUEST_EVT 2 /* SMP pairing request */
#define SMP_PASSKEY_NOTIF_EVT 3 /* passkey notification event */
#define SMP_PASSKEY_REQ_EVT 4 /* passkey request event */
#define SMP_OOB_REQ_EVT 5 /* OOB request event */
-#define SMP_COMPLT_EVT 6 /* SMP complete event */
+#define SMP_NC_REQ_EVT 6 /* Numeric Comparison request event */
+#define SMP_COMPLT_EVT 7 /* SMP complete event */
+#define SMP_PEER_KEYPR_NOT_EVT 8 /* Peer keypress notification received event */
+#define SMP_SC_OOB_REQ_EVT 9 /* SC OOB request event (both local and peer OOB data */
+ /* can be expected in response) */
+#define SMP_SC_LOC_OOB_DATA_UP_EVT 10 /* SC OOB local data set is created */
+ /* (as result of SMP_CrLocScOobData(...)) */
+#define SMP_BR_KEYS_REQ_EVT 12 /* SMP over BR keys request event */
typedef UINT8 tSMP_EVT;
#define SMP_INVALID_CMD 0x07
#define SMP_PAIR_FAIL_UNKNOWN 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
-#define SMP_PAIR_FAILURE_MAX SMP_REPEATED_ATTEMPTS
+#define SMP_INVALID_PARAMETERS 0x0A
+#define SMP_DHKEY_CHK_FAIL 0x0B
+#define SMP_NUMERIC_COMPAR_FAIL 0x0C
+#define SMP_BR_PARING_IN_PROGR 0x0D
+#define SMP_XTRANS_DERIVE_NOT_ALLOW 0x0E
+#define SMP_MAX_FAIL_RSN_PER_SPEC SMP_XTRANS_DERIVE_NOT_ALLOW
+
/* self defined error code */
-#define SMP_PAIR_INTERNAL_ERR 0x0A
-#define SMP_UNKNOWN_IO_CAP 0x0B /* unknown IO capability, unable to decide associatino model */
-#define SMP_INIT_FAIL 0x0C
-#define SMP_CONFIRM_FAIL 0x0D
-#define SMP_BUSY 0x0E
-#define SMP_ENC_FAIL 0x0F
-#define SMP_STARTED 0x10
-#define SMP_RSP_TIMEOUT 0x11
-#define SMP_DIV_NOT_AVAIL 0x12
-#define SMP_FAIL 0x13 /* unspecified failed reason */
-#define SMP_CONN_TOUT 0x14 /* unspecified failed reason */
+#define SMP_PAIR_INTERNAL_ERR (SMP_MAX_FAIL_RSN_PER_SPEC + 0x01) /* 0x0E */
+
+/* 0x0F unknown IO capability, unable to decide association model */
+#define SMP_UNKNOWN_IO_CAP (SMP_MAX_FAIL_RSN_PER_SPEC + 0x02) /* 0x0F */
+
+#define SMP_INIT_FAIL (SMP_MAX_FAIL_RSN_PER_SPEC + 0x03) /* 0x10 */
+#define SMP_CONFIRM_FAIL (SMP_MAX_FAIL_RSN_PER_SPEC + 0x04) /* 0x11 */
+#define SMP_BUSY (SMP_MAX_FAIL_RSN_PER_SPEC + 0x05) /* 0x12 */
+#define SMP_ENC_FAIL (SMP_MAX_FAIL_RSN_PER_SPEC + 0x06) /* 0x13 */
+#define SMP_STARTED (SMP_MAX_FAIL_RSN_PER_SPEC + 0x07) /* 0x14 */
+#define SMP_RSP_TIMEOUT (SMP_MAX_FAIL_RSN_PER_SPEC + 0x08) /* 0x15 */
+#define SMP_DIV_NOT_AVAIL (SMP_MAX_FAIL_RSN_PER_SPEC + 0x09) /* 0x16 */
+
+/* 0x17 unspecified failed reason */
+#define SMP_FAIL (SMP_MAX_FAIL_RSN_PER_SPEC + 0x0A) /* 0x17 */
+
+#define SMP_CONN_TOUT (SMP_MAX_FAIL_RSN_PER_SPEC + 0x0B)
#define SMP_SUCCESS 0
typedef UINT8 tSMP_STATUS;
};
typedef UINT8 tSMP_OOB_FLAG;
+/* type of OOB data required from application */
+enum
+{
+ SMP_OOB_INVALID_TYPE,
+ SMP_OOB_PEER,
+ SMP_OOB_LOCAL,
+ SMP_OOB_BOTH
+};
+typedef UINT8 tSMP_OOB_DATA_TYPE;
+
#define SMP_AUTH_NO_BOND 0x00
#define SMP_AUTH_GEN_BOND 0x01 //todo sdh change GEN_BOND to BOND
/* SMP Authentication requirement */
-#define SMP_AUTH_YN_BIT (1 << 2)
-#define SMP_AUTH_MASK (SMP_AUTH_GEN_BOND|SMP_AUTH_YN_BIT)
+#define SMP_AUTH_YN_BIT (1 << 2)
+#define SMP_SC_SUPPORT_BIT (1 << 3)
+#define SMP_KP_SUPPORT_BIT (1 << 4)
+#define SMP_AUTH_MASK (SMP_AUTH_GEN_BOND|SMP_AUTH_YN_BIT|SMP_SC_SUPPORT_BIT|SMP_KP_SUPPORT_BIT)
#define SMP_AUTH_BOND SMP_AUTH_GEN_BOND
-#define SMP_AUTH_NB_ENC_ONLY 0x00 //(SMP_AUTH_MASK | BTM_AUTH_SP_NO) /* no MITM, No Bonding, Encryptino only */
-#define SMP_AUTH_NB_IOCAP (SMP_AUTH_NO_BOND | SMP_AUTH_YN_BIT) /* MITM, No Bonding, Use IO Capability
- to detrermine authenticaion procedure */
-#define SMP_AUTH_GB_ENC_ONLY (SMP_AUTH_GEN_BOND ) /* no MITM, General Bonding, Encryptino only */
-#define SMP_AUTH_GB_IOCAP (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT) /* MITM, General Bonding, Use IO Capability
- to detrermine authenticaion procedure */
+/* no MITM, No Bonding, encryption only */
+#define SMP_AUTH_NB_ENC_ONLY 0x00 //(SMP_AUTH_MASK | BTM_AUTH_SP_NO)
+
+/* MITM, No Bonding, Use IO Capability to determine authentication procedure */
+#define SMP_AUTH_NB_IOCAP (SMP_AUTH_NO_BOND | SMP_AUTH_YN_BIT)
+
+/* No MITM, General Bonding, Encryption only */
+#define SMP_AUTH_GB_ENC_ONLY (SMP_AUTH_GEN_BOND )
+
+/* MITM, General Bonding, Use IO Capability to determine authentication procedure */
+#define SMP_AUTH_GB_IOCAP (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT)
+
+/* Secure Connections, no MITM, no Bonding */
+#define SMP_AUTH_SC_ENC_ONLY (SMP_SC_SUPPORT_BIT)
+
+/* Secure Connections, no MITM, Bonding */
+#define SMP_AUTH_SC_GB (SMP_SC_SUPPORT_BIT | SMP_AUTH_GEN_BOND)
+
+/* Secure Connections, MITM, no Bonding */
+#define SMP_AUTH_SC_MITM_NB (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_NO_BOND)
+
+/* Secure Connections, MITM, Bonding */
+#define SMP_AUTH_SC_MITM_GB (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_GEN_BOND)
+
+ /* All AuthReq RFU bits are set to 1 - NOTE: reserved bit in Bonding_Flags is not set */
+#define SMP_AUTH_ALL_RFU_SET 0xF8
+
typedef UINT8 tSMP_AUTH_REQ;
#define SMP_SEC_NONE 0
#define SMP_SEC_AUTHENTICATED (1 << 2)
typedef UINT8 tSMP_SEC_LEVEL;
+/* Maximum Encryption Key Size range */
+#define SMP_ENCR_KEY_SIZE_MIN 7
+#define SMP_ENCR_KEY_SIZE_MAX 16
+
/* SMP key types */
#define SMP_SEC_KEY_TYPE_ENC (1 << 0) /* encryption key */
#define SMP_SEC_KEY_TYPE_ID (1 << 1) /* identity key */
#define SMP_SEC_KEY_TYPE_CSRK (1 << 2) /* slave CSRK */
+#define SMP_SEC_KEY_TYPE_LK (1 << 3) /* BR/EDR link key */
typedef UINT8 tSMP_KEYS;
+#define SMP_BR_SEC_DEFAULT_KEY (SMP_SEC_KEY_TYPE_ENC | SMP_SEC_KEY_TYPE_ID | \
+ SMP_SEC_KEY_TYPE_CSRK)
+
/* default security key distribution value */
-#define SMP_SEC_DEFAULT_KEY (SMP_SEC_KEY_TYPE_ENC | SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK)
+#define SMP_SEC_DEFAULT_KEY (SMP_SEC_KEY_TYPE_ENC | SMP_SEC_KEY_TYPE_ID | \
+ SMP_SEC_KEY_TYPE_CSRK | SMP_SEC_KEY_TYPE_LK)
/* data type for BTM_SP_IO_REQ_EVT */
typedef struct
typedef struct
{
- tSMP_STATUS reason;
- tSMP_SEC_LEVEL sec_level;
- BOOLEAN is_pair_cancel;
+ tSMP_STATUS reason;
+ tSMP_SEC_LEVEL sec_level;
+ BOOLEAN is_pair_cancel;
} tSMP_CMPL;
+typedef struct
+{
+ BT_OCTET32 x;
+ BT_OCTET32 y;
+} tSMP_PUBLIC_KEY;
+
+/* the data associated with the info sent to the peer via OOB interface */
+typedef struct
+{
+ BOOLEAN present;
+ BT_OCTET16 randomizer;
+ BT_OCTET16 commitment;
+
+ tBLE_BD_ADDR addr_sent_to;
+ BT_OCTET32 private_key_used; /* is used to calculate: */
+ /* publ_key_used = P-256(private_key_used, curve_p256.G) - send it to the */
+ /* other side */
+ /* dhkey = P-256(private_key_used, publ key rcvd from the other side) */
+ tSMP_PUBLIC_KEY publ_key_used; /* P-256(private_key_used, curve_p256.G) */
+} tSMP_LOC_OOB_DATA;
+
+/* the data associated with the info received from the peer via OOB interface */
+typedef struct
+{
+ BOOLEAN present;
+ BT_OCTET16 randomizer;
+ BT_OCTET16 commitment;
+ tBLE_BD_ADDR addr_rcvd_from;
+} tSMP_PEER_OOB_DATA;
+
+typedef struct
+{
+ tSMP_LOC_OOB_DATA loc_oob_data;
+ tSMP_PEER_OOB_DATA peer_oob_data;
+} tSMP_SC_OOB_DATA;
+
+
typedef union
{
UINT32 passkey;
tSMP_IO_REQ io_req; /* IO request */
tSMP_CMPL cmplt;
-
+ tSMP_OOB_DATA_TYPE req_oob_type;
+ tSMP_LOC_OOB_DATA loc_oob_data;
}tSMP_EVT_DATA;
UINT8 param_buf[BT_OCTET16_LEN];
} tSMP_ENC;
-/* Simple Pairing Events. Called by the stack when Simple Pairing related
-** events occur.
-*/
+/* Security Manager events - Called by the stack when Security Manager related events occur.*/
typedef UINT8 (tSMP_CALLBACK) (tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data);
/* callback function for CMAC algorithm
**
*******************************************************************************/
extern tSMP_STATUS SMP_Pair (BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function SMP_BR_PairWith
+**
+** Description This function is called to start a SMP pairing over BR/EDR.
+**
+** Returns SMP_STARTED if pairing started, otherwise reason for failure.
+**
+*******************************************************************************/
+extern tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr);
+
/*******************************************************************************
**
** Function SMP_PairCancel
** Passkey request to the application.
**
** Parameters: bd_addr - Address of the device for which PIN was requested
-** res - result of the operation BTM_SUCCESS if success
+** res - result of the operation SMP_SUCCESS if success
** passkey - numeric value in the range of
** BTM_MIN_PASSKEY_VAL(0) - BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
**
/*******************************************************************************
**
+** Function SMP_ConfirmReply
+**
+** Description This function is called after Security Manager submitted
+** numeric comparison request to the application.
+**
+** Parameters: bd_addr - Address of the device with which numeric
+** comparison was requested
+** res - comparison result SMP_SUCCESS if success
+**
+*******************************************************************************/
+extern void SMP_ConfirmReply (BD_ADDR bd_addr, UINT8 res);
+
+/*******************************************************************************
+**
** Function SMP_OobDataReply
**
** Description This function is called to provide the OOB data for
-** Simple Pairing in response to BTM_SP_RMT_OOB_EVT
+** SMP in response to SMP_OOB_REQ_EVT
**
** Parameters: bd_addr - Address of the peer device
** res - result of the operation SMP_SUCCESS if success
-** p_data - simple pairing Randomizer C.
+** p_data - SM Randomizer C.
**
*******************************************************************************/
extern void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len,
/*******************************************************************************
**
+** Function SMP_SecureConnectionOobDataReply
+**
+** Description This function is called to provide the SC OOB data for
+** SMP in response to SMP_SC_OOB_REQ_EVT
+**
+** Parameters: p_data - pointer to the data
+**
+*******************************************************************************/
+extern void SMP_SecureConnectionOobDataReply(UINT8 *p_data);
+
+/*******************************************************************************
+**
** Function SMP_Encrypt
**
** Description This function is called to encrypt the data with the specified
UINT8 *plain_text, UINT8 pt_len,
tSMP_ENC *p_out);
+/*******************************************************************************
+**
+** Function SMP_KeypressNotification
+**
+** Description This function is called to notify SM about Keypress Notification.
+**
+** Parameters: bd_addr - Address of the device to send keypress
+** notification to
+** value - keypress notification parameter value
+**
+*******************************************************************************/
+extern void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value);
+
+/*******************************************************************************
+**
+** Function SMP_CreateLocalSecureConnectionsOobData
+**
+** Description This function is called to start creation of local SC OOB
+** data set (tSMP_LOC_OOB_DATA).
+**
+** Parameters: bd_addr - Address of the device to send OOB data block
+** to.
+**
+** Returns Boolean - TRUE: creation of local SC OOB data set started.
+*******************************************************************************/
+extern BOOLEAN SMP_CreateLocalSecureConnectionsOobData (
+ tBLE_BD_ADDR *addr_to_send_to);
+
#ifdef __cplusplus
}
#endif
** NOTE This timeout applies to all logical channels active on the
** ACL link.
*******************************************************************************/
-BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout)
+BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout, tBT_TRANSPORT transport)
{
tL2C_LCB *p_lcb;
if (memcmp (BT_BD_ANY, bd_addr, BD_ADDR_LEN))
{
- p_lcb = l2cu_find_lcb_by_bd_addr( bd_addr, BT_TRANSPORT_BR_EDR);
+ p_lcb = l2cu_find_lcb_by_bd_addr( bd_addr, transport);
if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED))
+ {
p_lcb->idle_timeout = timeout;
+
+ if (!p_lcb->ccb_queue.p_first_ccb)
+ l2cu_no_dynamic_ccbs (p_lcb);
+ }
else
- return (FALSE);
+ return FALSE;
}
else
{
if ((p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED))
{
p_lcb->idle_timeout = timeout;
+
+ if (!p_lcb->ccb_queue.p_first_ccb)
+ l2cu_no_dynamic_ccbs (p_lcb);
}
}
}
- return (TRUE);
+ return TRUE;
}
/*******************************************************************************
p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = NULL;
p_lcb->disc_reason = HCI_ERR_CONN_CAUSE_LOCAL_HOST;
-#if BLE_INCLUDED == TRUE
- /* retain the link for a few more seconds after SMP pairing is done, since Android
- platformalways do service discovery after pairing complete. This way would avoid
- the link down (pairing is complete) and an immediate reconnection for service
- discovery. Some devices do not do auto advertising when link is dropped, thus fail
- the second connection and service discovery.
- BEFORE :if ((fixed_cid == L2CAP_ATT_CID || fixed_cid == L2CAP_SMP_CID)
- && !p_lcb->ccb_queue.p_first_ccb)*/
- if ((fixed_cid == L2CAP_ATT_CID ) && !p_lcb->ccb_queue.p_first_ccb)
- p_lcb->idle_timeout = 0;
-#endif
-
l2cu_release_ccb (p_ccb);
return (TRUE);
l2cu_no_dynamic_ccbs (p_lcb);
}
- return (TRUE);
+ return TRUE;
}
#endif /* #if (L2CAP_NUM_FIXED_CHNLS > 0) */
#if (BLE_INCLUDED == TRUE)
static void l2cble_start_conn_update (tL2C_LCB *p_lcb);
-#include "vendor_ble.h"
/*******************************************************************************
**
** Function L2CA_CancelBleConnectReq
void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
{
+ btm_ble_update_link_topology_mask(role, TRUE);
+
if (role == HCI_ROLE_MASTER)
{
l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
*******************************************************************************/
BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
{
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
- UINT16 scan_int, scan_win;
- BD_ADDR init_addr;
- UINT8 init_addr_type = BLE_ADDR_PUBLIC,
- own_addr_type = BLE_ADDR_PUBLIC;
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
+ tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+ UINT16 scan_int;
+ UINT16 scan_win;
+ BD_ADDR peer_addr;
+ UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
+ UINT8 own_addr_type = BLE_ADDR_PUBLIC;
/* There can be only one BLE connection request outstanding at a time */
if (p_dev_rec == NULL)
scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
- init_addr_type = p_lcb->ble_addr_type;
- memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
+ peer_addr_type = p_lcb->ble_addr_type;
+ memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
-#if BLE_PRIVACY_SPT == TRUE
- /* if RPA offloading supported */
- if (btm_ble_vendor_irk_list_load_dev(p_dev_rec))
- btm_random_pseudo_to_public(init_addr, &init_addr_type);
- /* otherwise, if remote is RPA enabled, use latest RPA */
- else if (p_dev_rec->ble.active_addr_type == BTM_BLE_ADDR_RRA)
+#if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
+ own_addr_type = btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
+ if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
{
- init_addr_type = BLE_ADDR_RANDOM;
- memcpy(init_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
+ if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2)
+ own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+
+ btm_ble_enable_resolving_list();
+ btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
}
- /* if privacy is on and current do not consider using reconnection address */
- if (btm_cb.ble_ctr_cb.privacy ) /* && p_dev_rec->ble.use_reconn_addr */
- own_addr_type = BLE_ADDR_RANDOM;
+ else
+ btm_ble_disable_resolving_list();
#endif
if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
scan_win, /* UINT16 scan_win */
FALSE, /* UINT8 white_list */
- init_addr_type, /* UINT8 addr_type_peer */
- init_addr, /* BD_ADDR bda_peer */
+ peer_addr_type, /* UINT8 addr_type_peer */
+ peer_addr, /* BD_ADDR bda_peer */
own_addr_type, /* UINT8 addr_type_own */
(UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), /* UINT16 conn_int_min */
if (num_lowpri_links > low_quota)
{
l2cb.ble_round_robin_quota = low_quota;
- qq = qq_remainder = 1;
+ qq = qq_remainder = 0;
}
/* If each low priority link can have at least one buffer */
else if (num_lowpri_links > 0)
{
l2cb.ble_round_robin_quota = 0;
l2cb.ble_round_robin_unacked = 0;
- qq = qq_remainder = 1;
+ qq = qq_remainder = 0;
}
L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation num_hipri: %u num_lowpri: %u low_quota: %u round_robin_quota: %u qq: %u",
num_hipri_links, num_lowpri_links, low_quota,
/* Just in case app decides to try again in the callback context */
p_lcb->link_state = LST_DISCONNECTING;
+#if (BLE_INCLUDED == TRUE)
+ /* Check for BLE and handle that differently */
+ if (p_lcb->transport == BT_TRANSPORT_LE)
+ btm_ble_update_link_topology_mask(p_lcb->link_role, FALSE);
+#endif
/* Link is disconnected. For all channels, send the event through */
/* their FSMs. The CCBs should remove themselves from the LCB */
for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; )
for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++)
{
/* If controller window is full, nothing to do */
+ if (((l2cb.controller_xmit_window == 0 ||
+ (l2cb.round_robin_unacked >= l2cb.round_robin_quota))
#if (BLE_INCLUDED == TRUE)
- if ( (l2cb.controller_xmit_window == 0
- && (p_lcb->transport == BT_TRANSPORT_BR_EDR))
- || (p_lcb->transport == BT_TRANSPORT_LE
- && l2cb.controller_le_xmit_window == 0 )
- || (l2cb.round_robin_unacked >= l2cb.round_robin_quota
- && (p_lcb->transport == BT_TRANSPORT_BR_EDR))
- || ((p_lcb->transport == BT_TRANSPORT_LE)
- && (l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota)))
-#else
- if ((l2cb.controller_xmit_window == 0)
- || (l2cb.round_robin_unacked >= l2cb.round_robin_quota))
+ && (p_lcb->transport == BT_TRANSPORT_BR_EDR)
#endif
- break;
+ )
+ || (p_lcb->transport == BT_TRANSPORT_LE &&
+ (l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota ||
+ l2cb.controller_le_xmit_window == 0 )))
+ break;
+
/* Check for wraparound */
if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS])
void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
{
#if (BLE_INCLUDED == TRUE)
- /* always exclude LE fixed channel on BR/EDR fix channel capability */
- if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
- p_lcb->peer_chnl_mask[0] &= ~(L2CAP_FIXED_CHNL_ATT_BIT| \
- L2CAP_FIXED_CHNL_BLE_SIG_BIT| \
- L2CAP_FIXED_CHNL_SMP_BIT);
- else
- p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
+ if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
+ {
+ /* ignore all not assigned BR/EDR channels */
+ p_lcb->peer_chnl_mask[0] &= (L2CAP_FIXED_CHNL_SIG_BIT| \
+ L2CAP_FIXED_CHNL_CNCTLESS_BIT| \
+ L2CAP_FIXED_CHNL_SMP_BR_BIT);
+ }
+ else
+ p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
#endif
/* Tell all registered fixed channels about the connection */
L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
return (NULL);
}
+ /* send tx complete */
+ if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)
+ (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
+
l2cu_check_channel_congestion (p_ccb);
l2cu_set_acl_hci_header (p_buf, p_ccb);
return (p_buf);
q_count += p_ccb->p_lcb->ucd_out_sec_pending_q.count;
}
#endif
-
/* If the CCB queue limit is subject to a quota, check for congestion */
-
/* if this channel has outgoing traffic */
if (p_ccb->buff_quota != 0)
{
#include <stdlib.h>
+/* add the target configuration to allow using internal data types and compilation options */
+#include "bt_target.h"
+
/* define if you have fast 32-bit types on your system */
#if 1
# define HAVE_UINT_32T
#include "aes.h"
#if defined( HAVE_UINT_32T )
- typedef unsigned long uint_32t;
+ typedef UINT32 uint_32t;
#endif
/* functions for finite field multiplication in the AES Galois field */
#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
/* Set the cipher key for the pre-keyed version */
+/* NOTE: If the length_type used for the key length is an
+ unsigned 8-bit character, a key length of 256 bits must
+ be entered as a length in bytes (valid inputs are hence
+ 128, 192, 16, 24 and 32).
+*/
return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] )
{
switch( keylen )
{
case 16:
- case 128:
+ case 128: /* length in bits (128 = 8*16) */
keylen = 16;
break;
case 24:
- case 192:
+ case 192: /* length in bits (192 = 8*24) */
keylen = 24;
break;
case 32:
- /* case 256: length in bits (256 = 8*32) */
+/* case 256: length in bits (256 = 8*32) */
keylen = 32;
break;
default:
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * This file contains simple pairing algorithms
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "p_256_ecc_pp.h"
+
+void p_256_init_curve(UINT32 keyLength)
+{
+ elliptic_curve_t *ec;
+
+ if(keyLength == KEY_LENGTH_DWORDS_P256)
+ {
+ ec = &curve_p256;
+
+ ec->p[7] = 0xFFFFFFFF;
+ ec->p[6] = 0x00000001;
+ ec->p[5] = 0x0;
+ ec->p[4] = 0x0;
+ ec->p[3] = 0x0;
+ ec->p[2] = 0xFFFFFFFF;
+ ec->p[1] = 0xFFFFFFFF;
+ ec->p[0] = 0xFFFFFFFF;
+
+ memset(ec->omega, 0, KEY_LENGTH_DWORDS_P256);
+ memset(ec->a, 0, KEY_LENGTH_DWORDS_P256);
+
+ ec->a_minus3 = TRUE;
+
+ //b
+ ec->b[7] = 0x5ac635d8;
+ ec->b[6] = 0xaa3a93e7;
+ ec->b[5] = 0xb3ebbd55;
+ ec->b[4] = 0x769886bc;
+ ec->b[3] = 0x651d06b0;
+ ec->b[2] = 0xcc53b0f6;
+ ec->b[1] = 0x3bce3c3e;
+ ec->b[0] = 0x27d2604b;
+
+ //base point
+ ec->G.x[7] = 0x6b17d1f2;
+ ec->G.x[6] = 0xe12c4247;
+ ec->G.x[5] = 0xf8bce6e5;
+ ec->G.x[4] = 0x63a440f2;
+ ec->G.x[3] = 0x77037d81;
+ ec->G.x[2] = 0x2deb33a0;
+ ec->G.x[1] = 0xf4a13945;
+ ec->G.x[0] = 0xd898c296;
+
+ ec->G.y[7] = 0x4fe342e2;
+ ec->G.y[6] = 0xfe1a7f9b;
+ ec->G.y[5] = 0x8ee7eb4a;
+ ec->G.y[4] = 0x7c0f9e16;
+ ec->G.y[3] = 0x2bce3357;
+ ec->G.y[2] = 0x6b315ece;
+ ec->G.y[1] = 0xcbb64068;
+ ec->G.y[0] = 0x37bf51f5;
+ }
+}
+
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * This file contains simple pairing algorithms using Elliptic Curve Cryptography for private public key
+ *
+ ******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "p_256_ecc_pp.h"
+#include "p_256_multprecision.h"
+
+elliptic_curve_t curve;
+elliptic_curve_t curve_p256;
+
+static void p_256_init_point(Point *q)
+{
+ memset(q, 0, sizeof(Point));
+}
+
+static void p_256_copy_point(Point *q, Point *p)
+{
+ memcpy(q, p, sizeof(Point));
+}
+
+// q=2q
+static void ECC_Double(Point *q, Point *p, uint32_t keyLength)
+{
+ DWORD t1[KEY_LENGTH_DWORDS_P256];
+ DWORD t2[KEY_LENGTH_DWORDS_P256];
+ DWORD t3[KEY_LENGTH_DWORDS_P256];
+ DWORD *x1;
+ DWORD *x3;
+ DWORD *y1;
+ DWORD *y3;
+ DWORD *z1;
+ DWORD *z3;
+
+ if (multiprecision_iszero(p->z, keyLength))
+ {
+ multiprecision_init(q->z, keyLength);
+ return; // return infinity
+ }
+
+ x1=p->x; y1=p->y; z1=p->z;
+ x3=q->x; y3=q->y; z3=q->z;
+
+ multiprecision_mersenns_squa_mod(t1, z1, keyLength); // t1=z1^2
+ multiprecision_sub_mod(t2, x1, t1, keyLength); // t2=x1-t1
+ multiprecision_add_mod(t1, x1, t1, keyLength); // t1=x1+t1
+ multiprecision_mersenns_mult_mod(t2, t1, t2, keyLength); // t2=t2*t1
+ multiprecision_lshift_mod(t3, t2, keyLength);
+ multiprecision_add_mod(t2, t3, t2, keyLength); // t2=3t2
+
+ multiprecision_mersenns_mult_mod(z3, y1, z1, keyLength); // z3=y1*z1
+ multiprecision_lshift_mod(z3, z3, keyLength);
+
+ multiprecision_mersenns_squa_mod(y3, y1, keyLength); // y3=y1^2
+ multiprecision_lshift_mod(y3, y3, keyLength);
+ multiprecision_mersenns_mult_mod(t3, y3, x1, keyLength); // t3=y3*x1=x1*y1^2
+ multiprecision_lshift_mod(t3, t3, keyLength);
+ multiprecision_mersenns_squa_mod(y3, y3, keyLength); // y3=y3^2=y1^4
+ multiprecision_lshift_mod(y3, y3, keyLength);
+
+ multiprecision_mersenns_squa_mod(x3, t2, keyLength); // x3=t2^2
+ multiprecision_lshift_mod(t1, t3, keyLength); // t1=2t3
+ multiprecision_sub_mod(x3, x3, t1, keyLength); // x3=x3-t1
+ multiprecision_sub_mod(t1, t3, x3, keyLength); // t1=t3-x3
+ multiprecision_mersenns_mult_mod(t1, t1, t2, keyLength); // t1=t1*t2
+ multiprecision_sub_mod(y3, t1, y3, keyLength); // y3=t1-y3
+}
+
+// q=q+p, zp must be 1
+static void ECC_Add(Point *r, Point *p, Point *q, uint32_t keyLength)
+{
+ DWORD t1[KEY_LENGTH_DWORDS_P256];
+ DWORD t2[KEY_LENGTH_DWORDS_P256];
+ DWORD *x1;
+ DWORD *x2;
+ DWORD *x3;
+ DWORD *y1;
+ DWORD *y2;
+ DWORD *y3;
+ DWORD *z1;
+ DWORD *z2;
+ DWORD *z3;
+
+ x1=p->x; y1=p->y; z1=p->z;
+ x2=q->x; y2=q->y; z2=q->z;
+ x3=r->x; y3=r->y; z3=r->z;
+
+ // if Q=infinity, return p
+ if (multiprecision_iszero(z2, keyLength))
+ {
+ p_256_copy_point(r, p);
+ return;
+ }
+
+ // if P=infinity, return q
+ if (multiprecision_iszero(z1, keyLength))
+ {
+ p_256_copy_point(r, q);
+ return;
+ }
+
+ multiprecision_mersenns_squa_mod(t1, z1, keyLength); // t1=z1^2
+ multiprecision_mersenns_mult_mod(t2, z1, t1, keyLength); // t2=t1*z1
+ multiprecision_mersenns_mult_mod(t1, x2, t1, keyLength); // t1=t1*x2
+ multiprecision_mersenns_mult_mod(t2, y2, t2, keyLength); // t2=t2*y2
+
+ multiprecision_sub_mod(t1, t1, x1, keyLength); // t1=t1-x1
+ multiprecision_sub_mod(t2, t2, y1, keyLength); // t2=t2-y1
+
+ if (multiprecision_iszero(t1, keyLength))
+ {
+ if (multiprecision_iszero(t2, keyLength))
+ {
+ ECC_Double(r, q, keyLength) ;
+ return;
+ }
+ else
+ {
+ multiprecision_init(z3, keyLength);
+ return; // return infinity
+ }
+ }
+
+ multiprecision_mersenns_mult_mod(z3, z1, t1, keyLength); // z3=z1*t1
+ multiprecision_mersenns_squa_mod(y3, t1, keyLength); // t3=t1^2
+ multiprecision_mersenns_mult_mod(z1, y3, t1, keyLength); // t4=t3*t1
+ multiprecision_mersenns_mult_mod(y3, y3, x1, keyLength); // t3=t3*x1
+ multiprecision_lshift_mod(t1, y3, keyLength); // t1=2*t3
+ multiprecision_mersenns_squa_mod(x3, t2, keyLength); // x3=t2^2
+ multiprecision_sub_mod(x3, x3, t1, keyLength); // x3=x3-t1
+ multiprecision_sub_mod(x3, x3, z1, keyLength); // x3=x3-t4
+ multiprecision_sub_mod(y3, y3, x3, keyLength); // t3=t3-x3
+ multiprecision_mersenns_mult_mod(y3, y3, t2, keyLength); // t3=t3*t2
+ multiprecision_mersenns_mult_mod(z1, z1, y1, keyLength); // t4=t4*t1
+ multiprecision_sub_mod(y3, y3, z1, keyLength);
+}
+
+// Computing the Non-Adjacent Form of a positive integer
+static void ECC_NAF(uint8_t *naf, uint32_t *NumNAF, DWORD *k, uint32_t keyLength)
+{
+ uint32_t sign;
+ int i=0;
+ int j;
+ uint32_t var;
+
+ while ((var = multiprecision_most_signbits(k, keyLength))>=1)
+ {
+ if (k[0] & 0x01) // k is odd
+ {
+ sign = (k[0] & 0x03); // 1 or 3
+
+ // k = k-naf[i]
+ if (sign == 1)
+ k[0] = k[0] & 0xFFFFFFFE;
+ else
+ {
+ k[0] = k[0] + 1;
+ if (k[0] == 0) //overflow
+ {
+ j = 1;
+ do
+ {
+ k[j]++;
+ } while (k[j++]==0); //overflow
+ }
+ }
+ }
+ else
+ sign = 0;
+
+ multiprecision_rshift(k, k, keyLength);
+ naf[i / 4] |= (sign) << ((i % 4) * 2);
+ i++;
+ }
+
+ *NumNAF=i;
+}
+
+// Binary Non-Adjacent Form for point multiplication
+void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength)
+{
+ uint32_t sign;
+ UINT8 naf[256 / 4 +1];
+ uint32_t NumNaf;
+ Point minus_p;
+ Point r;
+ DWORD *modp;
+
+ if (keyLength == KEY_LENGTH_DWORDS_P256)
+ {
+ modp = curve_p256.p;
+ }
+ else
+ {
+ modp = curve.p;
+ }
+
+ p_256_init_point(&r);
+ multiprecision_init(p->z, keyLength);
+ p->z[0] = 1;
+
+ // initialization
+ p_256_init_point(q);
+
+ // -p
+ multiprecision_copy(minus_p.x, p->x, keyLength);
+ multiprecision_sub(minus_p.y, modp, p->y, keyLength);
+
+ multiprecision_init(minus_p.z, keyLength);
+ minus_p.z[0]=1;
+
+ // NAF
+ memset(naf, 0, sizeof(naf));
+ ECC_NAF(naf, &NumNaf, n, keyLength);
+
+ for (int i = NumNaf - 1; i >= 0; i--)
+ {
+ p_256_copy_point(&r, q);
+ ECC_Double(q, &r, keyLength);
+ sign = (naf[i / 4] >> ((i % 4) * 2)) & 0x03;
+
+ if (sign == 1)
+ {
+ p_256_copy_point(&r, q);
+ ECC_Add(q, &r, p, keyLength);
+ }
+ else if (sign == 3)
+ {
+ p_256_copy_point(&r, q);
+ ECC_Add(q, &r, &minus_p, keyLength);
+ }
+ }
+
+ multiprecision_inv_mod(minus_p.x, q->z, keyLength);
+ multiprecision_mersenns_squa_mod(q->z, minus_p.x, keyLength);
+ multiprecision_mersenns_mult_mod(q->x, q->x, q->z, keyLength);
+ multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, keyLength);
+ multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength);
+}
+
+
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * This file contains simple pairing algorithms using Elliptic Curve Cryptography for private public key
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "p_256_multprecision.h"
+
+typedef unsigned long DWORD;
+
+typedef struct {
+ DWORD x[KEY_LENGTH_DWORDS_P256];
+ DWORD y[KEY_LENGTH_DWORDS_P256];
+ DWORD z[KEY_LENGTH_DWORDS_P256];
+} Point;
+
+typedef struct {
+ // curve's coefficients
+ DWORD a[KEY_LENGTH_DWORDS_P256];
+ DWORD b[KEY_LENGTH_DWORDS_P256];
+
+ //whether a is -3
+ int a_minus3;
+
+ // prime modulus
+ DWORD p[KEY_LENGTH_DWORDS_P256];
+
+ // Omega, p = 2^m -omega
+ DWORD omega[KEY_LENGTH_DWORDS_P256];
+
+ // base point, a point on E of order r
+ Point G;
+
+} elliptic_curve_t;
+
+extern elliptic_curve_t curve;
+extern elliptic_curve_t curve_p256;
+
+void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength);
+
+#define ECC_PointMult(q, p, n, keyLength) ECC_PointMult_Bin_NAF(q, p, n, keyLength)
+
+void p_256_init_curve(UINT32 keyLength);
+
+
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * This file contains simple pairing algorithms
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bt_target.h"
+#include "p_256_ecc_pp.h"
+#include "p_256_multprecision.h"
+
+void multiprecision_init(DWORD *c, uint32_t keyLength)
+{
+ for (uint32_t i = 0; i < keyLength; i++)
+ c[i] = 0;
+}
+
+void multiprecision_copy(DWORD *c, DWORD *a, uint32_t keyLength)
+{
+ for (uint32_t i = 0; i < keyLength; i++)
+ c[i] = a[i];
+}
+
+int multiprecision_compare(DWORD *a, DWORD *b, uint32_t keyLength)
+{
+ for (int i = keyLength - 1; i >= 0; i--)
+ {
+ if (a[i] > b[i])
+ return 1;
+ if (a[i] < b[i])
+ return -1;
+ }
+ return 0;
+}
+
+int multiprecision_iszero(DWORD *a, uint32_t keyLength)
+{
+ for (uint32_t i = 0; i < keyLength; i++)
+ if (a[i])
+ return 0;
+
+ return 1;
+}
+
+UINT32 multiprecision_dword_bits(DWORD a)
+{
+ uint32_t i;
+ for (i = 0; i < DWORD_BITS; i++, a >>= 1)
+ if (a == 0)
+ break;
+
+ return i;
+}
+
+UINT32 multiprecision_most_signdwords(DWORD *a, uint32_t keyLength)
+{
+ int i;
+ for (i = keyLength - 1; i >= 0; i--)
+ if (a[i])
+ break;
+ return (i + 1);
+}
+
+UINT32 multiprecision_most_signbits(DWORD *a, uint32_t keyLength)
+{
+ int aMostSignDWORDs;
+
+ aMostSignDWORDs = multiprecision_most_signdwords(a, keyLength);
+ if (aMostSignDWORDs == 0)
+ return 0;
+
+ return (((aMostSignDWORDs-1) << DWORD_BITS_SHIFT) +
+ multiprecision_dword_bits(a[aMostSignDWORDs-1]) );
+}
+
+DWORD multiprecision_add(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+ DWORD carrier;
+ DWORD temp;
+
+ carrier=0;
+ for (uint32_t i = 0; i < keyLength; i++)
+ {
+ temp = a[i] + carrier;
+ carrier = (temp < carrier);
+ temp += b[i];
+ carrier |= (temp < b[i]);
+ c[i]=temp;
+ }
+
+ return carrier;
+}
+
+//c=a-b
+DWORD multiprecision_sub(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+ DWORD borrow;
+ DWORD temp;
+
+ borrow=0;
+ for (uint32_t i=0; i < keyLength; i++)
+ {
+ temp = a[i] - borrow;
+ borrow = (temp > a[i]);
+ c[i] = temp - b[i];
+ borrow |= (c[i] > temp);
+ }
+
+ return borrow;
+}
+
+// c = a << 1
+void multiprecision_lshift_mod(DWORD * c, DWORD * a, uint32_t keyLength)
+{
+ DWORD carrier;
+ DWORD *modp;
+
+ if (keyLength == KEY_LENGTH_DWORDS_P192)
+ {
+ modp = curve.p;
+ }
+ else if (keyLength == KEY_LENGTH_DWORDS_P256)
+ {
+ modp = curve_p256.p;
+ }
+ else
+ return;
+
+ carrier = multiprecision_lshift(c, a, keyLength);
+ if (carrier)
+ {
+ multiprecision_sub(c, c, modp, keyLength);
+ }
+ else if (multiprecision_compare(c, modp, keyLength)>=0)
+ {
+ multiprecision_sub(c, c, modp, keyLength);
+ }
+}
+
+// c=a>>1
+void multiprecision_rshift(DWORD * c, DWORD * a, uint32_t keyLength)
+{
+ int j;
+ DWORD b = 1;
+
+ j = DWORD_BITS - b;
+
+ DWORD carrier = 0;
+ DWORD temp;
+ for (int i = keyLength-1; i >= 0; i--)
+ {
+ temp = a[i]; // in case of c==a
+ c[i] = (temp >> b) | carrier;
+ carrier = temp << j;
+ }
+}
+
+// Curve specific optimization when p is a pseudo-Mersenns prime, p=2^(KEY_LENGTH_BITS)-omega
+void multiprecision_mersenns_mult_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+ DWORD cc[2*KEY_LENGTH_DWORDS_P256];
+
+ multiprecision_mult(cc, a, b, keyLength);
+ if (keyLength == 6)
+ {
+ multiprecision_fast_mod(c, cc);
+ }
+ else if (keyLength == 8)
+ {
+ multiprecision_fast_mod_P256(c, cc);
+ }
+}
+
+// Curve specific optimization when p is a pseudo-Mersenns prime
+void multiprecision_mersenns_squa_mod(DWORD *c, DWORD *a, uint32_t keyLength)
+{
+ multiprecision_mersenns_mult_mod(c, a, a, keyLength);
+}
+
+// c=(a+b) mod p, b<p, a<p
+void multiprecision_add_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+ DWORD carrier;
+ DWORD *modp;
+
+ if (keyLength == KEY_LENGTH_DWORDS_P192)
+ {
+ modp = curve.p;
+ }
+ else if (keyLength == KEY_LENGTH_DWORDS_P256)
+ {
+ modp = curve_p256.p;
+ }
+ else
+ return;
+
+ carrier = multiprecision_add(c, a, b, keyLength);
+ if (carrier)
+ {
+ multiprecision_sub(c, c, modp, keyLength);
+ }
+ else if (multiprecision_compare(c, modp, keyLength) >= 0)
+ {
+ multiprecision_sub(c, c, modp, keyLength);
+ }
+}
+
+// c=(a-b) mod p, a<p, b<p
+void multiprecision_sub_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+ DWORD borrow;
+ DWORD *modp;
+
+ if (keyLength == KEY_LENGTH_DWORDS_P192)
+ {
+ modp = curve.p;
+ }
+ else if(keyLength == KEY_LENGTH_DWORDS_P256)
+ {
+ modp = curve_p256.p;
+ }
+ else
+ return;
+
+ borrow = multiprecision_sub(c, a, b, keyLength);
+ if(borrow)
+ multiprecision_add(c, c, modp, keyLength);
+}
+
+// c=a<<b, b<DWORD_BITS, c has a buffer size of NumDWORDs+1
+DWORD multiprecision_lshift(DWORD * c, DWORD * a, uint32_t keyLength)
+{
+ int j;
+ uint32_t b = 1;
+ j = DWORD_BITS - b;
+
+ DWORD carrier = 0;
+ DWORD temp;
+
+ for (uint32_t i = 0; i < keyLength; i++)
+ {
+ temp = a[i]; // in case c==a
+ c[i] = (temp << b) | carrier;
+ carrier = temp >> j;
+ }
+
+ return carrier;
+}
+
+// c=a*b; c must have a buffer of 2*Key_LENGTH_DWORDS, c != a != b
+void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+ DWORD W;
+ DWORD U;
+ DWORD V;
+
+ U = V = W = 0;
+ multiprecision_init(c, keyLength);
+
+ //assume little endian right now
+ for (uint32_t i = 0; i < keyLength; i++)
+ {
+ U = 0;
+ for (uint32_t j = 0; j < keyLength; j++)
+ {
+ uint64_t result;
+ result = ((UINT64)a[i]) * ((uint64_t) b[j]);
+ W = result >> 32;
+ V = a[i] * b[j];
+ V = V + U;
+ U = (V < U);
+ U += W;
+ V = V + c[i+j];
+ U += (V < c[i+j]);
+ c[i+j] = V;
+ }
+ c[i+keyLength] = U;
+ }
+}
+
+void multiprecision_fast_mod(DWORD *c, DWORD *a)
+{
+ DWORD U;
+ DWORD V;
+ DWORD *modp = curve.p;
+
+ c[0] = a[0] + a[6];
+ U=c[0] < a[0];
+ c[0] += a[10];
+ U += c[0] < a[10];
+
+ c[1] = a[1] + U;
+ U = c[1] < a[1];
+ c[1] += a[7];
+ U += c[1] < a[7];
+ c[1] += a[11];
+ U += c[1]< a[11];
+
+ c[2] = a[2] + U;
+ U = c[2] < a[2];
+ c[2] += a[6];
+ U += c[2] < a[6];
+ c[2] += a[8];
+ U += c[2] < a[8];
+ c[2] += a[10];
+ U += c[2] < a[10];
+
+ c[3] = a[3]+U;
+ U = c[3] < a[3];
+ c[3] += a[7];
+ U += c[3] < a[7];
+ c[3] += a[9];
+ U += c[3] < a[9];
+ c[3] += a[11];
+ U += c[3] < a[11];
+
+ c[4] = a[4]+U;
+ U = c[4] < a[4];
+ c[4] += a[8];
+ U += c[4] < a[8];
+ c[4] += a[10];
+ U += c[4] < a[10];
+
+ c[5] = a[5]+U;
+ U = c[5] < a[5];
+ c[5] += a[9];
+ U += c[5] < a[9];
+ c[5] += a[11];
+ U += c[5] < a[11];
+
+ c[0] += U;
+ V = c[0] < U;
+ c[1] += V;
+ V = c[1] < V;
+ c[2] += V;
+ V = c[2] < V;
+ c[2] += U;
+ V = c[2] < U;
+ c[3] += V;
+ V = c[3] < V;
+ c[4] += V;
+ V = c[4] < V;
+ c[5] += V;
+ V = c[5] < V;
+
+ if (V)
+ {
+ multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P192);
+ }
+ else if(multiprecision_compare(c, modp, KEY_LENGTH_DWORDS_P192) >= 0)
+ {
+ multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P192);
+ }
+}
+
+void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
+{
+ DWORD A;
+ DWORD B;
+ DWORD C;
+ DWORD D;
+ DWORD E;
+ DWORD F;
+ DWORD G;
+ uint8_t UA;
+ uint8_t UB;
+ uint8_t UC;
+ uint8_t UD;
+ uint8_t UE;
+ uint8_t UF;
+ uint8_t UG;
+ DWORD U;
+ DWORD *modp = curve_p256.p;
+
+ // C = a[13] + a[14] + a[15];
+ C = a[13];
+ C += a[14];
+ UC = (C < a[14]);
+ C += a[15];
+ UC += (C < a[15]);
+
+ // E = a[8] + a[9];
+ E = a[8];
+ E += a[9];
+ UE = (E < a[9]);
+
+ // F = a[9] + a[10];
+ F = a[9];
+ F += a[10];
+ UF = (F < a[10]);
+
+ // G = a[10] + a[11]
+ G = a[10];
+ G += a[11];
+ UG = (G < a[11]);
+
+ // B = a[12] + a[13] + a[14] + a[15] == C + a[12]
+ B = C;
+ UB = UC;
+ B += a[12];
+ UB += (B < a[12]);
+
+ // A = a[11] + a[12] + a[13] + a[14] == B + a[11] - a[15]
+ A = B;
+ UA = UB;
+ A += a[11];
+ UA += (A < a[11]);
+ UA -= (A < a[15]);
+ A -= a[15];
+
+ // D = a[10] + a[11] + a[12] + a[13] == A + a[10] - a[14]
+ D = A;
+ UD = UA;
+ D += a[10];
+ UD += (D < a[10]);
+ UD -= (D < a[14]);
+ D -= a[14];
+
+ c[0] = a[0];
+ c[0] += E;
+ U = (c[0] < E);
+ U += UE;
+ U -= (c[0] < A);
+ U -= UA;
+ c[0] -= A;
+
+ if (U & 0x80000000)
+ {
+ DWORD UU;
+ UU = 0 - U;
+ U = (a[1] < UU);
+ c[1] = a[1] - UU;
+ }
+ else
+ {
+ c[1] = a[1] + U;
+ U = (c[1] < a[1]);
+ }
+
+ c[1] += F;
+ U += (c[1] < F);
+ U += UF;
+ U -= (c[1] < B);
+ U -= UB;
+ c[1] -= B;
+
+ if (U & 0x80000000)
+ {
+ DWORD UU;
+ UU = 0 - U;
+ U = (a[2] < UU);
+ c[2] = a[2] - UU;
+ }
+ else
+ {
+ c[2] = a[2] + U;
+ U = (c[2] < a[2]);
+ }
+
+ c[2] += G;
+ U += (c[2] < G);
+ U += UG;
+ U -= (c[2] < C);
+ U -= UC;
+ c[2] -= C;
+
+ if (U & 0x80000000)
+ {
+ DWORD UU;
+ UU = 0 - U;
+ U = (a[3] < UU);
+ c[3] = a[3] - UU;
+ }
+ else
+ {
+ c[3] = a[3] + U;
+ U = (c[3] < a[3]);
+ }
+
+ c[3] += A;
+ U += (c[3] < A);
+ U += UA;
+ c[3] += a[11];
+ U += (c[3] < a[11]);
+ c[3] += a[12];
+ U += (c[3] < a[12]);
+ U -= (c[3] < a[14]);
+ c[3] -= a[14];
+ U -= (c[3] < a[15]);
+ c[3] -= a[15];
+ U -= (c[3] < E);
+ U -= UE;
+ c[3] -= E;
+
+ if (U & 0x80000000)
+ {
+ DWORD UU;
+ UU = 0 - U;
+ U = (a[4] < UU);
+ c[4] = a[4] - UU;
+ }
+ else
+ {
+ c[4] = a[4] + U;
+ U = (c[4] < a[4]);
+ }
+
+ c[4] += B;
+ U += (c[4] < B);
+ U += UB;
+ U -= (c[4] < a[15]);
+ c[4] -= a[15];
+ c[4] += a[12];
+ U += (c[4] < a[12]);
+ c[4] += a[13];
+ U += (c[4] < a[13]);
+ U -= (c[4] < F);
+ U -= UF;
+ c[4] -= F;
+
+ if (U & 0x80000000)
+ {
+ DWORD UU;
+ UU = 0 - U;
+ U = (a[5] < UU);
+ c[5] = a[5] - UU;
+ }
+ else
+ {
+ c[5] = a[5] + U;
+ U = (c[5] < a[5]);
+ }
+
+ c[5] += C;
+ U += (c[5] < C);
+ U += UC;
+ c[5] += a[13];
+ U += (c[5] < a[13]);
+ c[5] += a[14];
+ U += (c[5] < a[14]);
+ U -= (c[5] < G);
+ U -= UG;
+ c[5] -= G;
+
+ if (U & 0x80000000)
+ {
+ DWORD UU;
+ UU = 0 - U;
+ U = (a[6] < UU);
+ c[6] = a[6] - UU;
+ }
+ else
+ {
+ c[6] = a[6] + U;
+ U = (c[6] < a[6]);
+ }
+
+ c[6] += C;
+ U += (c[6] < C);
+ U += UC;
+ c[6] += a[14];
+ U += (c[6] < a[14]);
+ c[6] += a[14];
+ U += (c[6] < a[14]);
+ c[6] += a[15];
+ U += (c[6] < a[15]);
+ U -= (c[6] < E);
+ U -= UE;
+ c[6] -= E;
+
+ if (U & 0x80000000)
+ {
+ DWORD UU;
+ UU = 0 - U;
+ U = (a[7] < UU);
+ c[7] = a[7] - UU;
+ }
+ else
+ {
+ c[7] = a[7] + U;
+ U = (c[7] < a[7]);
+ }
+
+ c[7] += a[15];
+ U += (c[7] < a[15]);
+ c[7] += a[15];
+ U += (c[7] < a[15]);
+ c[7] += a[15];
+ U += (c[7] < a[15]);
+ c[7] += a[8];
+ U += (c[7] < a[8]);
+ U -= (c[7] < D);
+ U -= UD;
+ c[7] -= D;
+
+ if (U & 0x80000000)
+ {
+ while (U)
+ {
+ multiprecision_add(c, c, modp, KEY_LENGTH_DWORDS_P256);
+ U++;
+ }
+ }
+ else if (U)
+ {
+ while (U)
+ {
+ multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P256);
+ U--;
+ }
+ }
+
+ if (multiprecision_compare(c, modp, KEY_LENGTH_DWORDS_P256)>=0)
+ multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P256);
+
+}
+
+void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength)
+{
+ DWORD v[KEY_LENGTH_DWORDS_P256];
+ DWORD A[KEY_LENGTH_DWORDS_P256+1];
+ DWORD C[KEY_LENGTH_DWORDS_P256+1];
+ DWORD *modp;
+
+ if(keyLength == KEY_LENGTH_DWORDS_P256)
+ {
+ modp = curve_p256.p;
+ }
+ else
+ {
+ modp = curve.p;
+ }
+
+ multiprecision_copy(v, modp, keyLength);
+ multiprecision_init(A, keyLength);
+ multiprecision_init(C, keyLength);
+ A[0] = 1;
+
+ while (!multiprecision_iszero(u, keyLength))
+ {
+ while (!(u[0] & 0x01)) // u is even
+ {
+ multiprecision_rshift(u, u, keyLength);
+ if(!(A[0] & 0x01)) // A is even
+ multiprecision_rshift(A, A, keyLength);
+ else
+ {
+ A[keyLength]=multiprecision_add(A, A, modp, keyLength); // A =A+p
+ multiprecision_rshift(A, A, keyLength);
+ A[keyLength-1] |= (A[keyLength]<<31);
+ }
+ }
+
+ while (!(v[0] & 0x01)) // v is even
+ {
+ multiprecision_rshift(v, v, keyLength);
+ if (!(C[0] & 0x01)) // C is even
+ {
+ multiprecision_rshift(C, C, keyLength);
+ }
+ else
+ {
+ C[keyLength] = multiprecision_add(C, C, modp, keyLength); // C =C+p
+ multiprecision_rshift(C, C, keyLength);
+ C[keyLength-1] |= (C[keyLength] << 31);
+ }
+ }
+
+ if (multiprecision_compare(u, v, keyLength) >= 0)
+ {
+ multiprecision_sub(u, u, v, keyLength);
+ multiprecision_sub_mod(A, A, C, keyLength);
+ }
+ else
+ {
+ multiprecision_sub(v, v, u, keyLength);
+ multiprecision_sub_mod(C, C, A, keyLength);
+ }
+ }
+
+ if (multiprecision_compare(C, modp, keyLength) >= 0)
+ multiprecision_sub(aminus, C, modp, keyLength);
+ else
+ multiprecision_copy(aminus, C, keyLength);
+}
+
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * This file contains simple pairing algorithms
+ *
+ ******************************************************************************/
+#pragma once
+
+#include "bt_types.h"
+
+/* Type definitions */
+typedef unsigned long DWORD;
+
+#define DWORD_BITS 32
+#define DWORD_BYTES 4
+#define DWORD_BITS_SHIFT 5
+
+#define KEY_LENGTH_DWORDS_P192 6
+#define KEY_LENGTH_DWORDS_P256 8
+/* Arithmetic Operations */
+
+int multiprecision_compare(DWORD *a, DWORD *b, uint32_t keyLength);
+int multiprecision_iszero(DWORD *a, uint32_t keyLength);
+void multiprecision_init(DWORD *c, uint32_t keyLength);
+void multiprecision_copy(DWORD *c, DWORD *a, uint32_t keyLength);
+UINT32 multiprecision_dword_bits (DWORD a);
+UINT32 multiprecision_most_signdwords(DWORD *a, uint32_t keyLength);
+UINT32 multiprecision_most_signbits(DWORD *a, uint32_t keyLength);
+void multiprecision_inv_mod(DWORD *aminus, DWORD *a, uint32_t keyLength);
+DWORD multiprecision_add(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a+b
+void multiprecision_add_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
+DWORD multiprecision_sub(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a-b
+void multiprecision_sub_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
+void multiprecision_rshift(DWORD * c, DWORD * a, uint32_t keyLength); // c=a>>1, return carrier
+void multiprecision_lshift_mod(DWORD * c, DWORD * a, uint32_t keyLength); // c=a<<b, return carrier
+DWORD multiprecision_lshift(DWORD * c, DWORD * a, uint32_t keyLength); // c=a<<b, return carrier
+void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a*b
+void multiprecision_mersenns_mult_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
+void multiprecision_mersenns_squa_mod(DWORD *c, DWORD *a, uint32_t keyLength);
+DWORD multiprecision_lshift(DWORD * c, DWORD * a, uint32_t keyLength);
+void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
+void multiprecision_fast_mod(DWORD *c, DWORD *a);
+void multiprecision_fast_mod_P256(DWORD *c, DWORD *a);
+
+
*
******************************************************************************/
+#include <string.h>
#include "bt_target.h"
#include "bt_utils.h"
-
-#if SMP_INCLUDED == TRUE
-
- #include <string.h>
- #include "btm_int.h"
- #include "l2c_api.h"
- #include "smp_int.h"
-
-#define MAX_KEY_DISTRIBUTION_TYPES 3
+#include "btm_int.h"
+#include "l2c_api.h"
+#include "smp_int.h"
const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
{
/* initiator */
- {{SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY}, /* Display Only */
- {SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY}, /* SMP_CAP_IO = 1 */
- {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* keyboard only */
- {SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY},/* No Input No Output */
- {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}}, /* keyboard display */
+ {{SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}, /* Display Only */
+ {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}, /* SMP_CAP_IO = 1 */
+ {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}, /* keyboard only */
+ {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY},/* No Input No Output */
+ {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}}, /* keyboard display */
/* responder */
- {{SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* Display Only */
- {SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
- {SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY}, /* keyboard only */
- {SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY},/* No Input No Output */
- {SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY, SMP_MODEL_PASSKEY}} /* keyboard display */
+ {{SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}, /* Display Only */
+ {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
+ {SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}, /* keyboard only */
+ {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY},/* No Input No Output */
+ {SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}} /* keyboard display */
/* display only */ /*SMP_CAP_IO = 1 */ /* keyboard only */ /* No InputOutput */ /* keyboard display */
};
+#define SMP_KEY_DIST_TYPE_MAX 4
const tSMP_ACT smp_distribute_act [] =
{
smp_generate_ltk,
smp_send_id_info,
- smp_generate_csrk
+ smp_generate_csrk,
+ smp_derive_link_key_from_long_term_key
};
/*******************************************************************************
*******************************************************************************/
static void smp_update_key_mask (tSMP_CB *p_cb, UINT8 key_type, BOOLEAN recv)
{
- SMP_TRACE_DEBUG ("smp_update_key_mask ");
- SMP_TRACE_DEBUG("before update role=%d recv=%d loc_i_key = %02x, loc_r_key = %02x", p_cb->role, recv, p_cb->loc_i_key, p_cb->loc_r_key);
+ SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x",
+ __func__, p_cb->role, recv, p_cb->local_i_key, p_cb->local_r_key);
+
+ if (((p_cb->le_secure_connections_mode_is_used) || (p_cb->smp_over_br)) &&
+ ((key_type == SMP_SEC_KEY_TYPE_ENC) || (key_type == SMP_SEC_KEY_TYPE_LK)))
+ {
+ /* in LE SC mode LTK, CSRK and BR/EDR LK are derived locally instead of
+ ** being exchanged with the peer */
+ p_cb->local_i_key &= ~key_type;
+ p_cb->local_r_key &= ~key_type;
+ }
+ else
if (p_cb->role == HCI_ROLE_SLAVE)
{
if (recv)
- p_cb->loc_i_key &= ~key_type;
+ p_cb->local_i_key &= ~key_type;
else
- p_cb->loc_r_key &= ~key_type;
+ p_cb->local_r_key &= ~key_type;
}
else
{
if (recv)
- p_cb->loc_r_key &= ~key_type;
+ p_cb->local_r_key &= ~key_type;
else
- p_cb->loc_i_key &= ~key_type;
+ p_cb->local_i_key &= ~key_type;
}
- SMP_TRACE_DEBUG("updated loc_i_key = %02x, loc_r_key = %02x", p_cb->loc_i_key, p_cb->loc_r_key);
+ SMP_TRACE_DEBUG("updated local_i_key = %02x, local_r_key = %02x", p_cb->local_i_key,
+ p_cb->local_r_key);
}
+
/*******************************************************************************
-** Function smp_io_cap_req
-** Description send SMP IO request
+** Function smp_send_app_cback
+** Description notifies application about the events the application is interested in
*******************************************************************************/
void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
tSMP_EVT_DATA cb_data;
tSMP_STATUS callback_rc;
- UNUSED(p_data);
-
- SMP_TRACE_DEBUG ("smp_send_app_cback p_cb->cb_evt=%d", p_cb->cb_evt );
+ SMP_TRACE_DEBUG("%s p_cb->cb_evt=%d", __func__, p_cb->cb_evt);
if (p_cb->p_callback && p_cb->cb_evt != 0)
{
- if (p_cb->cb_evt == SMP_IO_CAP_REQ_EVT)
+ switch (p_cb->cb_evt)
{
- cb_data.io_req.auth_req = p_cb->peer_auth_req;
- cb_data.io_req.oob_data = SMP_OOB_NONE;
- cb_data.io_req.io_cap = SMP_DEFAULT_IO_CAPS;
- cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
- cb_data.io_req.init_keys = p_cb->loc_i_key ;
- cb_data.io_req.resp_keys = p_cb->loc_r_key ;
-
- SMP_TRACE_WARNING( "io_cap = %d",cb_data.io_req.io_cap);
+ case SMP_IO_CAP_REQ_EVT:
+ cb_data.io_req.auth_req = p_cb->peer_auth_req;
+ cb_data.io_req.oob_data = SMP_OOB_NONE;
+ cb_data.io_req.io_cap = SMP_DEFAULT_IO_CAPS;
+ cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
+ cb_data.io_req.init_keys = p_cb->local_i_key ;
+ cb_data.io_req.resp_keys = p_cb->local_r_key ;
+ SMP_TRACE_WARNING ( "io_cap = %d",cb_data.io_req.io_cap);
+ break;
+
+ case SMP_NC_REQ_EVT:
+ cb_data.passkey = p_data->passkey;
+ break;
+ case SMP_SC_OOB_REQ_EVT:
+ cb_data.req_oob_type = p_data->req_oob_type;
+ break;
+ case SMP_SC_LOC_OOB_DATA_UP_EVT:
+ cb_data.loc_oob_data = p_cb->sc_oob_data.loc_oob_data;
+ break;
+
+ case SMP_BR_KEYS_REQ_EVT:
+ cb_data.io_req.auth_req = 0;
+ cb_data.io_req.oob_data = SMP_OOB_NONE;
+ cb_data.io_req.io_cap = 0;
+ cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
+ cb_data.io_req.init_keys = SMP_BR_SEC_DEFAULT_KEY;
+ cb_data.io_req.resp_keys = SMP_BR_SEC_DEFAULT_KEY;
+ break;
+
+ default:
+ break;
}
+
callback_rc = (*p_cb->p_callback)(p_cb->cb_evt, p_cb->pairing_bda, &cb_data);
- SMP_TRACE_DEBUG ("callback_rc=%d p_cb->cb_evt=%d",callback_rc, p_cb->cb_evt );
+ SMP_TRACE_DEBUG("callback_rc=%d p_cb->cb_evt=%d",callback_rc, p_cb->cb_evt );
- if (callback_rc == SMP_SUCCESS && p_cb->cb_evt == SMP_IO_CAP_REQ_EVT)
+ if (callback_rc == SMP_SUCCESS)
{
- p_cb->loc_auth_req = cb_data.io_req.auth_req;
- p_cb->loc_io_caps = cb_data.io_req.io_cap;
- p_cb->loc_oob_flag = cb_data.io_req.oob_data;
- p_cb->loc_enc_size = cb_data.io_req.max_key_size;
- p_cb->loc_i_key = cb_data.io_req.init_keys;
- p_cb->loc_r_key = cb_data.io_req.resp_keys;
+ switch (p_cb->cb_evt)
+ {
+ case SMP_IO_CAP_REQ_EVT:
+ p_cb->loc_auth_req = cb_data.io_req.auth_req;
+ p_cb->local_io_capability = cb_data.io_req.io_cap;
+ p_cb->loc_oob_flag = cb_data.io_req.oob_data;
+ p_cb->loc_enc_size = cb_data.io_req.max_key_size;
+ p_cb->local_i_key = cb_data.io_req.init_keys;
+ p_cb->local_r_key = cb_data.io_req.resp_keys;
+
+ if (!(p_cb->loc_auth_req & SMP_AUTH_BOND))
+ {
+ SMP_TRACE_WARNING ("Non bonding: No keys will be exchanged");
+ p_cb->local_i_key = 0;
+ p_cb->local_r_key = 0;
+ }
+
+ SMP_TRACE_WARNING ( "rcvd auth_req: 0x%02x, io_cap: %d \
+ loc_oob_flag: %d loc_enc_size: %d,"
+ "local_i_key: 0x%02x, local_r_key: 0x%02x",
+ p_cb->loc_auth_req, p_cb->local_io_capability, p_cb->loc_oob_flag,
+ p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key);
+
+ p_cb->secure_connections_only_mode_required =
+ (btm_cb.security_mode == BTM_SEC_MODE_SC) ? TRUE : FALSE;
+
+ if (p_cb->secure_connections_only_mode_required)
+ {
+ p_cb->loc_auth_req |= SMP_SC_SUPPORT_BIT;
+ }
+
+ if (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT))
+ {
+ p_cb->loc_auth_req &= ~SMP_KP_SUPPORT_BIT;
+ p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+ p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+ }
+
+#if BTM_CROSS_TRANSP_KEY_DERIVATION == FALSE
+ SMP_TRACE_WARNING ("Cross transport key derivation is not supported");
+ p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+ p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+#endif
+
+ SMP_TRACE_WARNING("set auth_req: 0x%02x, local_i_key: 0x%02x, local_r_key: 0x%02x",
+ p_cb->loc_auth_req, p_cb->local_i_key, p_cb->local_r_key);
- SMP_TRACE_WARNING( "new io_cap = %d p_cb->loc_enc_size = %d",p_cb->loc_io_caps, p_cb->loc_enc_size);
+ smp_sm_event(p_cb, SMP_IO_RSP_EVT, NULL);
+ break;
- smp_sm_event(p_cb, SMP_IO_RSP_EVT, NULL);
+ case SMP_BR_KEYS_REQ_EVT:
+ p_cb->loc_enc_size = cb_data.io_req.max_key_size;
+ p_cb->local_i_key = cb_data.io_req.init_keys;
+ p_cb->local_r_key = cb_data.io_req.resp_keys;
+
+ p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+ p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+
+ SMP_TRACE_WARNING ( "for SMP over BR max_key_size: 0x%02x,\
+ local_i_key: 0x%02x, local_r_key: 0x%02x",
+ p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key);
+
+ smp_br_state_machine_event(p_cb, SMP_BR_KEYS_RSP_EVT, NULL);
+ break;
+ }
}
}
p_cb->discard_sec_req = FALSE;
smp_sm_event(p_cb, SMP_DISCARD_SEC_REQ_EVT, NULL);
}
- SMP_TRACE_DEBUG ("smp_send_app_cback return");
+
+ SMP_TRACE_DEBUG("%s return", __func__);
}
+
/*******************************************************************************
** Function smp_send_pair_fail
** Description pairing failure to peer device if needed.
p_cb->status = *(UINT8 *)p_data;
p_cb->failure = *(UINT8 *)p_data;
- SMP_TRACE_DEBUG ("smp_send_pair_fail status=%d failure=%d ",p_cb->status, p_cb->failure);
+ SMP_TRACE_DEBUG("%s status=%d failure=%d ", __func__, p_cb->status, p_cb->failure);
- if (p_cb->status <= SMP_REPEATED_ATTEMPTS && p_cb->status != SMP_SUCCESS)
+ if (p_cb->status <= SMP_MAX_FAIL_RSN_PER_SPEC && p_cb->status != SMP_SUCCESS)
{
smp_send_cmd(SMP_OPCODE_PAIRING_FAILED, p_cb);
+ p_cb->wait_for_authorization_complete = TRUE;
}
}
/*******************************************************************************
** Function smp_send_pair_req
-** Description process pairing request to slave device
+** Description actions related to sending pairing request
*******************************************************************************/
void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
- UNUSED(p_data);
-
- SMP_TRACE_DEBUG ("smp_send_pair_req ");
-
-#if BLE_INCLUDED == TRUE
- /* Disable L2CAP connection parameter updates while bonding since
- some peripherals are not able to revert to fast connection parameters
- during the start of service discovery. Connection paramter updates
- get enabled again once service discovery completes. */
- if (L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE) == FALSE)
- {
- SMP_TRACE_ERROR ("smp pair failed...!");
- return;
- }
-#endif
+ SMP_TRACE_DEBUG("%s", __func__);
/* erase all keys when master sends pairing req*/
if (p_dev_rec)
leave out to BTM to mandate key distribution for bonding case */
smp_send_cmd(SMP_OPCODE_PAIRING_REQ, p_cb);
}
+
/*******************************************************************************
** Function smp_send_pair_rsp
-** Description process pairing response to slave device
+** Description actions related to sending pairing response
*******************************************************************************/
void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
+ SMP_TRACE_DEBUG("%s", __func__);
- SMP_TRACE_DEBUG ("smp_send_pair_rsp ");
-
- p_cb->loc_i_key &= p_cb->peer_i_key;
- p_cb->loc_r_key &= p_cb->peer_r_key;
+ p_cb->local_i_key &= p_cb->peer_i_key;
+ p_cb->local_r_key &= p_cb->peer_r_key;
if (smp_send_cmd (SMP_OPCODE_PAIRING_RSP, p_cb))
{
- smp_decide_asso_model(p_cb, NULL);
+ if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB)
+ smp_use_oob_private_key(p_cb, NULL);
+ else
+ smp_decide_association_model(p_cb, NULL);
}
}
/*******************************************************************************
-** Function smp_send_pair_request
-** Description process pairing request to slave device
+** Function smp_send_confirm
+** Description send confirmation to the peer
*******************************************************************************/
void smp_send_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
-
- SMP_TRACE_DEBUG ("smp_send_confirm ");
+ SMP_TRACE_DEBUG("%s", __func__);
smp_send_cmd(SMP_OPCODE_CONFIRM, p_cb);
}
+
/*******************************************************************************
** Function smp_send_init
** Description process pairing initializer to slave device
*******************************************************************************/
void smp_send_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_send_cmd(SMP_OPCODE_INIT, p_cb);
+}
+
+/*******************************************************************************
+** Function smp_send_rand
+** Description send pairing random to the peer
+*******************************************************************************/
+void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_send_cmd(SMP_OPCODE_RAND, p_cb);
+}
- SMP_TRACE_DEBUG ("smp_send_init ");
+/*******************************************************************************
+** Function smp_send_pair_public_key
+** Description send pairing public key command to the peer
+*******************************************************************************/
+void smp_send_pair_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_send_cmd(SMP_OPCODE_PAIR_PUBLIC_KEY, p_cb);
+}
-#if SMP_CONFORMANCE_TESTING == TRUE
- if (p_cb->enable_test_rand_val)
- {
- SMP_TRACE_DEBUG ("Use rand value from script");
- memcpy(p_cb->rand, p_cb->test_rand, BT_OCTET16_LEN);
- }
-#endif
+/*******************************************************************************
+** Function SMP_SEND_COMMITMENT
+** Description send commitment command to the peer
+*******************************************************************************/
+void smp_send_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_send_cmd(SMP_OPCODE_PAIR_COMMITM, p_cb);
+}
- smp_send_cmd(SMP_OPCODE_INIT, p_cb);
+/*******************************************************************************
+** Function smp_send_dhkey_check
+** Description send DHKey Check command to the peer
+*******************************************************************************/
+void smp_send_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_send_cmd(SMP_OPCODE_PAIR_DHKEY_CHECK, p_cb);
+}
+
+/*******************************************************************************
+** Function smp_send_keypress_notification
+** Description send Keypress Notification command to the peer
+*******************************************************************************/
+void smp_send_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ p_cb->local_keypress_notification = *(UINT8 *) p_data;
+ smp_send_cmd(SMP_OPCODE_PAIR_KEYPR_NOTIF, p_cb);
}
+
/*******************************************************************************
** Function smp_send_enc_info
-** Description send security information command.
+** Description send encryption information command.
*******************************************************************************/
void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
tBTM_LE_LENC_KEYS le_key;
- UNUSED(p_data);
- SMP_TRACE_DEBUG ("smp_send_enc_info p_cb->loc_enc_size = %d", p_cb->loc_enc_size);
+ SMP_TRACE_DEBUG("%s p_cb->loc_enc_size = %d", __func__, p_cb->loc_enc_size);
smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
smp_send_cmd(SMP_OPCODE_ENCRYPT_INFO, p_cb);
smp_send_cmd(SMP_OPCODE_MASTER_ID, p_cb);
/* save the DIV and key size information when acting as slave device */
+ memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
le_key.div = p_cb->div;
le_key.key_size = p_cb->loc_enc_size;
le_key.sec_level = p_cb->sec_level;
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
- SMP_TRACE_WARNING( "smp_send_enc_info");
+ if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC,
+ (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+
+ SMP_TRACE_WARNING ("%s", __func__);
smp_key_distribution(p_cb, NULL);
}
+
/*******************************************************************************
** Function smp_send_id_info
** Description send ID information command.
*******************************************************************************/
void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
-
- SMP_TRACE_DEBUG ("smp_send_id_info ");
+ tBTM_LE_KEY_VALUE le_key;
+ SMP_TRACE_DEBUG("%s", __func__);
smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, FALSE);
smp_send_cmd(SMP_OPCODE_IDENTITY_INFO, p_cb);
smp_send_cmd(SMP_OPCODE_ID_ADDR, p_cb);
- SMP_TRACE_WARNING( "smp_send_id_info");
+ if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LID,
+ &le_key, TRUE);
- smp_key_distribution(p_cb, NULL);
+ SMP_TRACE_WARNING ("%s", __func__);
+ smp_key_distribution_by_transport(p_cb, NULL);
}
+
/*******************************************************************************
** Function smp_send_csrk_info
** Description send CSRK command.
*******************************************************************************/
void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- tBTM_LE_KEY_VALUE key;
- UNUSED(p_data);
-
- SMP_TRACE_DEBUG ("smp_send_csrk_info ");
+ tBTM_LE_LCSRK_KEYS key;
+ SMP_TRACE_DEBUG("%s", __func__);
smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, FALSE);
if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb))
{
- key.lcsrk_key.div = p_cb->div;
- key.lcsrk_key.sec_level = p_cb->sec_level;
- key.lcsrk_key.counter = 0; /* initialize the local counter */
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, &key, TRUE);
+ key.div = p_cb->div;
+ key.sec_level = p_cb->sec_level;
+ key.counter = 0; /* initialize the local counter */
+ memcpy (key.csrk, p_cb->csrk, BT_OCTET16_LEN);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, (tBTM_LE_KEY_VALUE *)&key, TRUE);
}
- smp_key_distribution(p_cb, NULL);
+ smp_key_distribution_by_transport(p_cb, NULL);
}
/*******************************************************************************
*******************************************************************************/
void smp_send_ltk_reply(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- SMP_TRACE_DEBUG ("smp_send_ltk_reply ");
+ SMP_TRACE_DEBUG("%s", __func__);
/* send stk as LTK response */
btm_ble_ltk_request_reply(p_cb->pairing_bda, TRUE, p_data->key.p_data);
}
+
/*******************************************************************************
** Function smp_proc_sec_req
** Description process security request.
*******************************************************************************/
void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- tBTM_LE_AUTH_REQ auth_req = *(tBTM_LE_AUTH_REQ *)p_data;
- tBTM_BLE_SEC_REQ_ACT sec_req_act;
-
+ tBTM_LE_AUTH_REQ auth_req = *(tBTM_LE_AUTH_REQ *)p_data;
+ tBTM_BLE_SEC_REQ_ACT sec_req_act;
+ UINT8 reason;
- SMP_TRACE_DEBUG ("smp_proc_sec_req auth_req=0x%x",auth_req);
+ SMP_TRACE_DEBUG("%s auth_req=0x%x", __func__, auth_req);
p_cb->cb_evt = 0;
btm_ble_link_sec_check(p_cb->pairing_bda, auth_req, &sec_req_act);
- SMP_TRACE_DEBUG ("smp_proc_sec_req sec_req_act=0x%x",sec_req_act);
+ SMP_TRACE_DEBUG("%s sec_req_act=0x%x", __func__, sec_req_act);
switch (sec_req_act)
{
case BTM_BLE_SEC_REQ_ACT_ENCRYPT:
- SMP_TRACE_DEBUG ("smp_proc_sec_req BTM_BLE_SEC_REQ_ACT_ENCRYPT");
+ SMP_TRACE_DEBUG("%s BTM_BLE_SEC_REQ_ACT_ENCRYPT", __func__);
smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
break;
case BTM_BLE_SEC_REQ_ACT_PAIR:
- /* initialize local i/r key to be default keys */
- SMP_TRACE_DEBUG ("smp_proc_sec_req BTM_BLE_SEC_REQ_ACT_PAIR");
- p_cb->peer_auth_req = auth_req;
- p_cb->loc_r_key = p_cb->loc_i_key = SMP_SEC_DEFAULT_KEY ;
- p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
- btu_stop_timer (&p_cb->rsp_timer_ent);
- btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
- SMP_WAIT_FOR_RSP_TOUT);
+ p_cb->secure_connections_only_mode_required =
+ (btm_cb.security_mode == BTM_SEC_MODE_SC) ? TRUE : FALSE;
+
+ /* respond to non SC pairing request as failure in SC only mode */
+ if (p_cb->secure_connections_only_mode_required &&
+ (auth_req & SMP_SC_SUPPORT_BIT) == 0)
+ {
+ reason = SMP_PAIR_AUTH_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ }
+ else
+ {
+ /* initialize local i/r key to be default keys */
+ p_cb->peer_auth_req = auth_req;
+ p_cb->local_r_key = p_cb->local_i_key = SMP_SEC_DEFAULT_KEY ;
+ p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
+ }
break;
case BTM_BLE_SEC_REQ_ACT_DISCARD:
break;
}
}
+
/*******************************************************************************
** Function smp_proc_sec_grant
** Description process security grant.
void smp_proc_sec_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 res= *(UINT8 *)p_data;
- SMP_TRACE_DEBUG ("smp_proc_sec_grant ");
+ SMP_TRACE_DEBUG("%s", __func__);
if (res != SMP_SUCCESS)
{
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, p_data);
p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
}
}
+
/*******************************************************************************
** Function smp_proc_pair_fail
** Description process pairing failure from peer device
*******************************************************************************/
void smp_proc_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- SMP_TRACE_DEBUG ("smp_proc_pair_fail ");
+ SMP_TRACE_DEBUG("%s", __func__);
p_cb->status = *(UINT8 *)p_data;
}
+
/*******************************************************************************
** Function smp_proc_pair_cmd
** Description Process the SMP pairing request/response from peer device
UINT8 reason = SMP_ENC_KEY_SIZE;
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
- SMP_TRACE_DEBUG ("smp_proc_pair_cmd ");
+ SMP_TRACE_DEBUG("%s", __func__);
/* erase all keys if it is slave proc pairing req*/
if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE))
btm_sec_clear_ble_keys(p_dev_rec);
STREAM_TO_UINT8(p_cb->peer_i_key, p);
STREAM_TO_UINT8(p_cb->peer_r_key, p);
-#if SMP_CONFORMANCE_TESTING == TRUE
- if (p_cb->enable_test_pair_fail)
+ if (smp_command_has_invalid_parameters(p_cb))
{
- SMP_TRACE_DEBUG ("Forced pair fair");
- if (p_cb->peer_enc_size < SMP_MIN_ENC_KEY_SIZE)
- {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
- }
- else
- {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &(p_cb->pair_fail_status));
- }
+ reason = SMP_INVALID_PARAMETERS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
-#endif
-
- if (p_cb->peer_enc_size < SMP_MIN_ENC_KEY_SIZE)
- {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
- }
- else if (p_cb->role == HCI_ROLE_SLAVE)
+ if (p_cb->role == HCI_ROLE_SLAVE)
{
if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
{
- p_cb->loc_i_key = p_cb->peer_i_key;
- p_cb->loc_r_key = p_cb->peer_r_key;
+ /* peer (master) started pairing sending Pairing Request */
+ p_cb->local_i_key = p_cb->peer_i_key;
+ p_cb->local_r_key = p_cb->peer_r_key;
+
+ p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
}
else /* update local i/r key according to pairing request */
{
- p_cb->loc_i_key &= p_cb->peer_i_key;
- p_cb->loc_r_key &= p_cb->peer_r_key;
+ /* paring started with this side (slave) sending Security Request */
+ p_cb->local_i_key &= p_cb->peer_i_key;
+ p_cb->local_r_key &= p_cb->peer_r_key;
+ p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+ if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB)
+ {
+ if (smp_request_oob_data(p_cb)) return;
+ }
+ else
+ {
+ smp_send_pair_rsp(p_cb, NULL);
+ }
+ }
+ }
+ else /* Master receives pairing response */
+ {
+ p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+ if (p_cb->secure_connections_only_mode_required &&
+ (!(p_cb->le_secure_connections_mode_is_used) ||
+ (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS)))
+ {
+ SMP_TRACE_ERROR ("Master requires secure connection only mode \
+ but it can't be provided -> Master fails pairing");
+ reason = SMP_PAIR_AUTH_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
}
- p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
+ if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB)
+ {
+ if (smp_request_oob_data(p_cb)) return;
+ }
+ else
+ {
+ smp_decide_association_model(p_cb, NULL);
+ }
}
}
+
/*******************************************************************************
** Function smp_proc_confirm
** Description process pairing confirm from peer device
void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 *p = (UINT8 *)p_data;
+ UINT8 reason = SMP_INVALID_PARAMETERS;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ if (smp_command_has_invalid_parameters(p_cb))
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
- SMP_TRACE_DEBUG ("smp_proc_confirm ");
if (p != NULL)
{
/* save the SConfirm for comparison later */
void smp_proc_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 *p = (UINT8 *)p_data;
- SMP_TRACE_DEBUG ("smp_proc_init ");
+ UINT8 reason = SMP_INVALID_PARAMETERS;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ if (smp_command_has_invalid_parameters(p_cb))
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
+
/* save the SRand for comparison */
STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
-
}
+
/*******************************************************************************
-** Function smp_proc_enc_info
-** Description process encryption information from peer device
+** Function smp_proc_rand
+** Description process pairing random (nonce) from peer device
*******************************************************************************/
-void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_proc_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 *p = (UINT8 *)p_data;
+ UINT8 *p = (UINT8 *)p_data;
+ UINT8 reason = SMP_INVALID_PARAMETERS;
- SMP_TRACE_DEBUG ("smp_proc_enc_info ");
- STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
+ SMP_TRACE_DEBUG("%s", __func__);
- smp_key_distribution(p_cb, NULL);
+ if (smp_command_has_invalid_parameters(p_cb))
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
+
+ /* save the SRand for comparison */
+ STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
}
+
/*******************************************************************************
-** Function smp_proc_master_id
-** Description process master ID from slave device
+** Function smp_process_pairing_public_key
+** Description process pairing public key command from the peer device
+** - saves the peer public key;
+** - sets the flag indicating that the peer public key is received;
+** - calls smp_wait_for_both_public_keys(...).
+**
*******************************************************************************/
-void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 *p = (UINT8 *)p_data;
- tBTM_LE_PENC_KEYS le_key;
+ UINT8 *p = (UINT8 *)p_data;
+ UINT8 reason = SMP_INVALID_PARAMETERS;
- SMP_TRACE_DEBUG (" smp_proc_master_id");
- smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, TRUE);
+ SMP_TRACE_DEBUG("%s", __func__);
- STREAM_TO_UINT16(le_key.ediv, p);
- STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN );
+ if (smp_command_has_invalid_parameters(p_cb))
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
- /* store the encryption keys from peer device */
- memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
- le_key.sec_level = p_cb->sec_level;
- le_key.key_size = p_cb->loc_enc_size;
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+ STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN);
+ STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN);
+ p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY;
- smp_key_distribution(p_cb, NULL);
+ smp_wait_for_both_public_keys(p_cb, NULL);
}
-/*******************************************************************************
-** Function smp_proc_enc_info
-** Description process identity information from peer device
-*******************************************************************************/
-void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
-{
- UINT8 *p = (UINT8 *)p_data;
- SMP_TRACE_DEBUG ("smp_proc_id_info ");
- STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */
-
- smp_key_distribution(p_cb, NULL);
-}
/*******************************************************************************
-** Function smp_proc_id_addr
-** Description process identity address from peer device
+** Function smp_process_pairing_commitment
+** Description process pairing commitment from peer device
*******************************************************************************/
-void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_pairing_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 *p = (UINT8 *)p_data;
- tBTM_LE_PID_KEYS pid_key;
+ UINT8 *p = (UINT8 *)p_data;
+ UINT8 reason = SMP_INVALID_PARAMETERS;
- SMP_TRACE_DEBUG ("smp_proc_id_addr ");
- smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
+ SMP_TRACE_DEBUG("%s", __func__);
- STREAM_TO_UINT8(pid_key.addr_type, p);
- STREAM_TO_BDADDR(pid_key.static_addr, p);
- memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
+ if (smp_command_has_invalid_parameters(p_cb))
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
- /* store the ID key from peer device */
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, (tBTM_LE_KEY_VALUE *)&pid_key, TRUE);
+ p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_COMM;
- smp_key_distribution(p_cb, NULL);
+ if (p != NULL)
+ {
+ STREAM_TO_ARRAY(p_cb->remote_commitment, p, BT_OCTET16_LEN);
+ }
}
+
/*******************************************************************************
-** Function smp_proc_srk_info
-** Description process security information from peer device
+** Function smp_process_dhkey_check
+** Description process DHKey Check from peer device
*******************************************************************************/
-void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- tBTM_LE_PCSRK_KEYS le_key;
+ UINT8 *p = (UINT8 *)p_data;
+ UINT8 reason = SMP_INVALID_PARAMETERS;
- SMP_TRACE_DEBUG ("smp_proc_srk_info ");
- smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, TRUE);
+ SMP_TRACE_DEBUG("%s", __func__);
- /* save CSRK to security record */
- le_key.sec_level = p_cb->sec_level;
- memcpy (le_key.csrk, p_data, BT_OCTET16_LEN); /* get peer CSRK */
- le_key.counter = 0; /* initialize the peer counter */
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK, (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+ if (smp_command_has_invalid_parameters(p_cb))
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
- smp_key_distribution(p_cb, NULL);
+ if (p != NULL)
+ {
+ STREAM_TO_ARRAY(p_cb->remote_dhkey_check, p, BT_OCTET16_LEN);
+ }
+
+ p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK;
}
/*******************************************************************************
-** Function smp_proc_compare
-** Description process compare value
+** Function smp_process_keypress_notification
+** Description process pairing keypress notification from peer device
*******************************************************************************/
-void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 reason;
-
- SMP_TRACE_DEBUG ("smp_proc_compare ");
- if (
-#if SMP_CONFORMANCE_TESTING == TRUE
- p_cb->skip_test_compare_check ||
-#endif
- !memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN))
- {
- /* compare the max encryption key size, and save the smaller one for the link */
- if ( p_cb->peer_enc_size < p_cb->loc_enc_size)
- p_cb->loc_enc_size = p_cb->peer_enc_size;
+ UINT8 *p = (UINT8 *)p_data;
+ UINT8 reason = SMP_INVALID_PARAMETERS;
- if (p_cb->role == HCI_ROLE_SLAVE)
- smp_sm_event(p_cb, SMP_RAND_EVT, NULL);
- else
- {
- /* master device always use received i/r key as keys to distribute */
- p_cb->loc_i_key = p_cb->peer_i_key;
- p_cb->loc_r_key = p_cb->peer_r_key;
+ SMP_TRACE_DEBUG("%s", __func__);
+ p_cb->status = *(UINT8 *)p_data;
- smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
- }
+ if (smp_command_has_invalid_parameters(p_cb))
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
+ if (p != NULL)
+ {
+ STREAM_TO_UINT8(p_cb->peer_keypress_notification, p);
}
else
{
- reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ p_cb->peer_keypress_notification = BTM_SP_KEY_OUT_OF_RANGE;
}
+ p_cb->cb_evt = SMP_PEER_KEYPR_NOT_EVT;
}
+
/*******************************************************************************
-** Function smp_proc_sl_key
-** Description process key ready events.
+** Function smp_br_process_pairing_command
+** Description Process the SMP pairing request/response from peer device via
+** BR/EDR transport.
*******************************************************************************/
-void smp_proc_sl_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 key_type = p_data->key.key_type;
+ UINT8 *p = (UINT8 *)p_data;
+ UINT8 reason = SMP_ENC_KEY_SIZE;
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
- SMP_TRACE_DEBUG ("smp_proc_sl_keysmp_proc_sl_key ");
- if (key_type == SMP_KEY_TYPE_TK)
+ SMP_TRACE_DEBUG("%s", __func__);
+ /* rejecting BR pairing request over non-SC BR link */
+ if (!p_dev_rec->new_encryption_key_is_p256 && p_cb->role == HCI_ROLE_SLAVE)
{
- smp_generate_confirm(p_cb, NULL);
+ reason = SMP_XTRANS_DERIVE_NOT_ALLOW;
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+ return;
}
- else if (key_type == SMP_KEY_TYPE_CFM)
- {
- smp_set_state(SMP_ST_WAIT_CONFIRM);
- if (p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM)
- smp_sm_event(p_cb, SMP_CONFIRM_EVT, NULL);
+ /* erase all keys if it is slave proc pairing req*/
+ if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE))
+ btm_sec_clear_ble_keys(p_dev_rec);
- }
-}
-/*******************************************************************************
-** Function smp_start_enc
-** Description start encryption
-*******************************************************************************/
-void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
-{
- tBTM_STATUS cmd;
- UINT8 reason = SMP_ENC_FAIL;
+ p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
- SMP_TRACE_DEBUG ("smp_start_enc ");
- if (p_data != NULL)
- cmd = btm_ble_start_encrypt(p_cb->pairing_bda, TRUE, p_data->key.p_data);
+ STREAM_TO_UINT8(p_cb->peer_io_caps, p);
+ STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
+ STREAM_TO_UINT8(p_cb->peer_auth_req, p);
+ STREAM_TO_UINT8(p_cb->peer_enc_size, p);
+ STREAM_TO_UINT8(p_cb->peer_i_key, p);
+ STREAM_TO_UINT8(p_cb->peer_r_key, p);
+
+ if (smp_command_has_invalid_parameters(p_cb))
+ {
+ reason = SMP_INVALID_PARAMETERS;
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+ return;
+ }
+
+ /* peer (master) started pairing sending Pairing Request */
+ /* or being master device always use received i/r key as keys to distribute */
+ p_cb->local_i_key = p_cb->peer_i_key;
+ p_cb->local_r_key = p_cb->peer_r_key;
+
+ if (p_cb->role == HCI_ROLE_SLAVE)
+ {
+ p_dev_rec->new_encryption_key_is_p256 = FALSE;
+ p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
+ }
+ else /* Master receives pairing response */
+ {
+ SMP_TRACE_DEBUG("%s master rcvs valid PAIRING RESPONSE."
+ " Supposed to move to key distribution phase. ", __func__);
+ }
+
+ /* auth_req received via BR/EDR SM channel is set to 0,
+ but everything derived/exchanged has to be saved */
+ p_cb->peer_auth_req |= SMP_AUTH_BOND;
+ p_cb->loc_auth_req |= SMP_AUTH_BOND;
+}
+
+/*******************************************************************************
+** Function smp_br_process_security_grant
+** Description process security grant in case of pairing over BR/EDR transport.
+*******************************************************************************/
+void smp_br_process_security_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 res= *(UINT8 *)p_data;
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (res != SMP_SUCCESS)
+ {
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, p_data);
+ }
+ else /*otherwise, start pairing */
+ {
+ /* send IO request callback */
+ p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT;
+ }
+}
+
+/*******************************************************************************
+** Function smp_br_check_authorization_request
+** Description sets the SMP kes to be derived/distribute over BR/EDR transport
+** before starting the distribution/derivation
+*******************************************************************************/
+void smp_br_check_authorization_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 reason = SMP_SUCCESS;
+
+ SMP_TRACE_DEBUG("%s rcvs i_keys=0x%x r_keys=0x%x "
+ "(i-initiator r-responder)", __FUNCTION__, p_cb->local_i_key,
+ p_cb->local_r_key);
+
+ /* In LE SC mode LK field is ignored when BR/EDR transport is used */
+ p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+ p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+
+ /* In LE SC mode only IRK, IAI, CSRK are exchanged with the peer.
+ ** Set local_r_key on master to expect only these keys. */
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK);
+ }
+
+ SMP_TRACE_DEBUG("%s rcvs upgrades: i_keys=0x%x r_keys=0x%x "
+ "(i-initiator r-responder)", __FUNCTION__, p_cb->local_i_key,
+ p_cb->local_r_key);
+
+ if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
+ (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
+ (p_cb->local_i_key || p_cb->local_r_key))
+ {
+ smp_br_state_machine_event(p_cb, SMP_BR_BOND_REQ_EVT, NULL);
+
+ /* if no peer key is expected, start master key distribution */
+ if (p_cb->role == HCI_ROLE_MASTER && p_cb->local_r_key == 0)
+ smp_key_distribution_by_transport(p_cb, NULL);
+ }
else
- cmd = btm_ble_start_encrypt(p_cb->pairing_bda, FALSE, NULL);
+ {
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+ }
+}
- if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY)
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+/*******************************************************************************
+** Function smp_br_select_next_key
+** Description selects the next key to derive/send when BR/EDR transport is
+** used.
+*******************************************************************************/
+void smp_br_select_next_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 reason = SMP_SUCCESS;
+ SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
+ __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
+ if (p_cb->role == HCI_ROLE_SLAVE||
+ (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER))
+ {
+ smp_key_pick_key(p_cb, p_data);
+ }
+
+ if (!p_cb->local_i_key && !p_cb->local_r_key)
+ {
+ /* state check to prevent re-entrance */
+ if (p_cb->smp_over_br)
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+ }
}
/*******************************************************************************
-** Function smp_proc_discard
-** Description processing for discard security request
+** Function smp_proc_enc_info
+** Description process encryption information from peer device
*******************************************************************************/
-void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
+ UINT8 *p = (UINT8 *)p_data;
- SMP_TRACE_DEBUG ("smp_proc_discard ");
- if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
- smp_reset_control_value(p_cb);
+ SMP_TRACE_DEBUG("%s", __func__);
+ STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
+
+ smp_key_distribution(p_cb, NULL);
}
/*******************************************************************************
-** Function smp_proc_release_delay
-** Description process the release delay request
+** Function smp_proc_master_id
+** Description process master ID from slave device
*******************************************************************************/
-void smp_proc_release_delay(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
+ UINT8 *p = (UINT8 *)p_data;
+ tBTM_LE_PENC_KEYS le_key;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, TRUE);
+
+ STREAM_TO_UINT16(le_key.ediv, p);
+ STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN );
+
+ /* store the encryption keys from peer device */
+ memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+ le_key.sec_level = p_cb->sec_level;
+ le_key.key_size = p_cb->loc_enc_size;
- SMP_TRACE_DEBUG ("smp_proc_release_delay ");
- btu_stop_timer (&p_cb->rsp_timer_ent);
- btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
- SMP_WAIT_FOR_REL_DELAY_TOUT);
+ if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+ btm_sec_save_le_key(p_cb->pairing_bda,
+ BTM_LE_KEY_PENC,
+ (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+
+ smp_key_distribution(p_cb, NULL);
}
/*******************************************************************************
-** Function smp_proc_release_delay_tout
-** Description processing the release delay timeout
+** Function smp_proc_enc_info
+** Description process identity information from peer device
*******************************************************************************/
-void smp_proc_release_delay_tout(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
+ UINT8 *p = (UINT8 *)p_data;
- SMP_TRACE_DEBUG ("smp_proc_release_delay_tout ");
- btu_stop_timer (&p_cb->rsp_timer_ent);
- smp_proc_pairing_cmpl(p_cb);
+ SMP_TRACE_DEBUG("%s", __func__);
+ STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */
+ smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function smp_proc_id_addr
+** Description process identity address from peer device
+*******************************************************************************/
+void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 *p = (UINT8 *)p_data;
+ tBTM_LE_PID_KEYS pid_key;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
+
+ STREAM_TO_UINT8(pid_key.addr_type, p);
+ STREAM_TO_BDADDR(pid_key.static_addr, p);
+ memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
+
+ /* store the ID key from peer device */
+ if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
+ (tBTM_LE_KEY_VALUE *)&pid_key, TRUE);
+ smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function smp_proc_srk_info
+** Description process security information from peer device
+*******************************************************************************/
+void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ tBTM_LE_PCSRK_KEYS le_key;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, TRUE);
+
+ /* save CSRK to security record */
+ le_key.sec_level = p_cb->sec_level;
+ memcpy (le_key.csrk, p_data, BT_OCTET16_LEN); /* get peer CSRK */
+ le_key.counter = 0; /* initialize the peer counter */
+
+ if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+ btm_sec_save_le_key(p_cb->pairing_bda,
+ BTM_LE_KEY_PCSRK,
+ (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+ smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function smp_proc_compare
+** Description process compare value
+*******************************************************************************/
+void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 reason;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (!memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN))
+ {
+ /* compare the max encryption key size, and save the smaller one for the link */
+ if ( p_cb->peer_enc_size < p_cb->loc_enc_size)
+ p_cb->loc_enc_size = p_cb->peer_enc_size;
+
+ if (p_cb->role == HCI_ROLE_SLAVE)
+ smp_sm_event(p_cb, SMP_RAND_EVT, NULL);
+ else
+ {
+ /* master device always use received i/r key as keys to distribute */
+ p_cb->local_i_key = p_cb->peer_i_key;
+ p_cb->local_r_key = p_cb->peer_r_key;
+
+ smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
+ }
+
+ }
+ else
+ {
+ reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ }
+}
+
+/*******************************************************************************
+** Function smp_proc_sl_key
+** Description process key ready events.
+*******************************************************************************/
+void smp_proc_sl_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 key_type = p_data->key.key_type;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (key_type == SMP_KEY_TYPE_TK)
+ {
+ smp_generate_srand_mrand_confirm(p_cb, NULL);
+ }
+ else if (key_type == SMP_KEY_TYPE_CFM)
+ {
+ smp_set_state(SMP_STATE_WAIT_CONFIRM);
+
+ if (p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM)
+ smp_sm_event(p_cb, SMP_CONFIRM_EVT, NULL);
+ }
+}
+
+/*******************************************************************************
+** Function smp_start_enc
+** Description start encryption
+*******************************************************************************/
+void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ tBTM_STATUS cmd;
+ UINT8 reason = SMP_ENC_FAIL;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (p_data != NULL)
+ cmd = btm_ble_start_encrypt(p_cb->pairing_bda, TRUE, p_data->key.p_data);
+ else
+ cmd = btm_ble_start_encrypt(p_cb->pairing_bda, FALSE, NULL);
+
+ if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY)
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
}
+/*******************************************************************************
+** Function smp_proc_discard
+** Description processing for discard security request
+*******************************************************************************/
+void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
+ smp_reset_control_value(p_cb);
+}
/*******************************************************************************
** Function smp_enc_cmpl
UINT8 enc_enable = *(UINT8 *)p_data;
UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
- SMP_TRACE_DEBUG ("smp_enc_cmpl ");
+ SMP_TRACE_DEBUG("%s", __func__);
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
}
+/*******************************************************************************
+** Function smp_check_auth_req
+** Description check authentication request
+*******************************************************************************/
+void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 enc_enable = *(UINT8 *)p_data;
+ UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+
+ SMP_TRACE_DEBUG("%s rcvs enc_enable=%d i_keys=0x%x r_keys=0x%x "
+ "(i-initiator r-responder)",
+ __func__, enc_enable, p_cb->local_i_key, p_cb->local_r_key);
+ if (enc_enable == 1)
+ {
+ if (p_cb->le_secure_connections_mode_is_used)
+ {
+ /* In LE SC mode LTK is used instead of STK and has to be always saved */
+ p_cb->local_i_key |= SMP_SEC_KEY_TYPE_ENC;
+ p_cb->local_r_key |= SMP_SEC_KEY_TYPE_ENC;
+
+ /* In LE SC mode LK is derived from LTK only if both sides request it */
+ if (!(p_cb->local_i_key & SMP_SEC_KEY_TYPE_LK) ||
+ !(p_cb->local_r_key & SMP_SEC_KEY_TYPE_LK))
+ {
+ p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+ p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+ }
+
+ /* In LE SC mode only IRK, IAI, CSRK are exchanged with the peer.
+ ** Set local_r_key on master to expect only these keys.
+ */
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK);
+ }
+ }
+ else
+ {
+ /* in legacy mode derivation of BR/EDR LK is not supported */
+ p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+ p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+ }
+ SMP_TRACE_DEBUG("%s rcvs upgrades: i_keys=0x%x r_keys=0x%x "
+ "(i-initiator r-responder)",
+ __func__, p_cb->local_i_key, p_cb->local_r_key);
+
+ if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
+ (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
+ (p_cb->local_i_key || p_cb->local_r_key))
+ {
+ smp_sm_event(p_cb, SMP_BOND_REQ_EVT, NULL);
+ }
+ else
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ }
+ else if (enc_enable == 0)
+ {
+ /* if failed for encryption after pairing, send callback */
+ if (p_cb->flags & SMP_PAIR_FLAG_ENC_AFTER_PAIR)
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ /* if enc failed for old security information */
+ /* if master device, clean up and abck to idle; slave device do nothing */
+ else if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ }
+ }
+}
+
+/*******************************************************************************
+** Function smp_key_pick_key
+** Description Pick a key distribution function based on the key mask.
+*******************************************************************************/
+void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 key_to_dist = (p_cb->role == HCI_ROLE_SLAVE) ? p_cb->local_r_key : p_cb->local_i_key;
+ UINT8 i = 0;
+
+ SMP_TRACE_DEBUG("%s key_to_dist=0x%x", __func__, key_to_dist);
+ while (i < SMP_KEY_DIST_TYPE_MAX)
+ {
+ SMP_TRACE_DEBUG("key to send = %02x, i = %d", key_to_dist, i);
+
+ if (key_to_dist & (1 << i))
+ {
+ SMP_TRACE_DEBUG("smp_distribute_act[%d]", i);
+ (* smp_distribute_act[i])(p_cb, p_data);
+ break;
+ }
+ i ++;
+ }
+}
+/*******************************************************************************
+** Function smp_key_distribution
+** Description start key distribution if required.
+*******************************************************************************/
+void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 reason = SMP_SUCCESS;
+ SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
+ __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
+
+ if (p_cb->role == HCI_ROLE_SLAVE||
+ (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER))
+ {
+ smp_key_pick_key(p_cb, p_data);
+ }
+
+ if (!p_cb->local_i_key && !p_cb->local_r_key)
+ {
+ /* state check to prevent re-entrant */
+ if (smp_get_state() == SMP_STATE_BOND_PENDING)
+ {
+ if (p_cb->total_tx_unacked == 0)
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ else
+ p_cb->wait_for_authorization_complete = TRUE;
+ }
+ }
+}
+
+/*******************************************************************************
+** Function smp_decide_association_model
+** Description This function is called to select assoc model to be used for
+** STK generation and to start STK generation process.
+**
+*******************************************************************************/
+void smp_decide_association_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 failure = SMP_UNKNOWN_IO_CAP;
+ UINT8 int_evt = 0;
+ tSMP_KEY key;
+ tSMP_INT_DATA *p = NULL;
+
+ SMP_TRACE_DEBUG("%s Association Model = %d", __func__, p_cb->selected_association_model);
+
+ switch (p_cb->selected_association_model)
+ {
+ case SMP_MODEL_ENCRYPTION_ONLY: /* TK = 0, go calculate Confirm */
+ if (p_cb->role == HCI_ROLE_MASTER &&
+ ((p_cb->peer_auth_req & SMP_AUTH_YN_BIT) != 0) &&
+ ((p_cb->loc_auth_req & SMP_AUTH_YN_BIT) == 0))
+ {
+ SMP_TRACE_ERROR ("IO capability does not meet authentication requirement");
+ failure = SMP_PAIR_AUTH_FAIL;
+ p = (tSMP_INT_DATA *)&failure;
+ int_evt = SMP_AUTH_CMPL_EVT;
+ }
+ else
+ {
+ p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
+ SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ", p_cb->sec_level );
+
+ key.key_type = SMP_KEY_TYPE_TK;
+ key.p_data = p_cb->tk;
+ p = (tSMP_INT_DATA *)&key;
+
+ memset(p_cb->tk, 0, BT_OCTET16_LEN);
+ /* TK, ready */
+ int_evt = SMP_KEY_READY_EVT;
+ }
+ break;
+
+ case SMP_MODEL_PASSKEY:
+ p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+ SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
+
+ p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
+ int_evt = SMP_TK_REQ_EVT;
+ break;
+
+ case SMP_MODEL_OOB:
+ SMP_TRACE_ERROR ("Association Model = SMP_MODEL_OOB");
+ p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+ SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
+
+ p_cb->cb_evt = SMP_OOB_REQ_EVT;
+ int_evt = SMP_TK_REQ_EVT;
+ break;
+
+ case SMP_MODEL_KEY_NOTIF:
+ p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+ SMP_TRACE_DEBUG("Need to generate Passkey");
+
+ /* generate passkey and notify application */
+ smp_generate_passkey(p_cb, NULL);
+ break;
+
+ case SMP_MODEL_SEC_CONN_JUSTWORKS:
+ case SMP_MODEL_SEC_CONN_NUM_COMP:
+ case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+ case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+ case SMP_MODEL_SEC_CONN_OOB:
+ int_evt = SMP_PUBL_KEY_EXCH_REQ_EVT;
+ break;
+
+ case SMP_MODEL_OUT_OF_RANGE:
+ SMP_TRACE_ERROR("Association Model = SMP_MODEL_OUT_OF_RANGE (failed)");
+ p = (tSMP_INT_DATA *)&failure;
+ int_evt = SMP_AUTH_CMPL_EVT;
+ break;
+
+ default:
+ SMP_TRACE_ERROR("Association Model = %d (SOMETHING IS WRONG WITH THE CODE)",
+ p_cb->selected_association_model);
+ p = (tSMP_INT_DATA *)&failure;
+ int_evt = SMP_AUTH_CMPL_EVT;
+ }
+
+ SMP_TRACE_EVENT ("sec_level=%d ", p_cb->sec_level );
+ if (int_evt)
+ smp_sm_event(p_cb, int_evt, p);
+}
+
+/*******************************************************************************
+** Function smp_process_io_response
+** Description process IO response for a slave device.
+*******************************************************************************/
+void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ uint8_t reason = SMP_PAIR_AUTH_FAIL;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
+ {
+ /* pairing started by local (slave) Security Request */
+ smp_set_state(SMP_STATE_SEC_REQ_PENDING);
+ smp_send_cmd(SMP_OPCODE_SEC_REQ, p_cb);
+ }
+ else /* plan to send pairing respond */
+ {
+ /* pairing started by peer (master) Pairing Request */
+ p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+ if (p_cb->secure_connections_only_mode_required &&
+ (!(p_cb->le_secure_connections_mode_is_used) ||
+ (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS)))
+ {
+ SMP_TRACE_ERROR ("Slave requires secure connection only mode \
+ but it can't be provided -> Slave fails pairing");
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
+
+ if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB)
+ {
+ if (smp_request_oob_data(p_cb)) return;
+ }
+ smp_send_pair_rsp(p_cb, NULL);
+ }
+}
+
+/*******************************************************************************
+** Function smp_br_process_slave_keys_response
+** Description process application keys response for a slave device
+** (BR/EDR transport).
+*******************************************************************************/
+void smp_br_process_slave_keys_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ smp_br_send_pair_response(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function smp_br_send_pair_response
+** Description actions related to sending pairing response over BR/EDR transport.
+*******************************************************************************/
+void smp_br_send_pair_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ p_cb->local_i_key &= p_cb->peer_i_key;
+ p_cb->local_r_key &= p_cb->peer_r_key;
+
+ smp_send_cmd (SMP_OPCODE_PAIRING_RSP, p_cb);
+}
+
+/*******************************************************************************
+** Function smp_pairing_cmpl
+** Description This function is called to send the pairing complete callback
+** and remove the connection if needed.
+*******************************************************************************/
+void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ if (p_cb->total_tx_unacked == 0)
+ {
+ /* update connection parameter to remote preferred */
+ L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, TRUE);
+ /* process the pairing complete */
+ smp_proc_pairing_cmpl(p_cb);
+ }
+}
+
+/*******************************************************************************
+** Function smp_pair_terminate
+** Description This function is called to send the pairing complete callback
+** and remove the connection if needed.
+*******************************************************************************/
+void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+ p_cb->status = SMP_CONN_TOUT;
+ smp_proc_pairing_cmpl(p_cb);
+}
+
+/*******************************************************************************
+** Function smp_idle_terminate
+** Description This function calledin idle state to determine to send authentication
+** complete or not.
+*******************************************************************************/
+void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
+ {
+ SMP_TRACE_DEBUG("Pairing terminated at IDLE state.");
+ p_cb->status = SMP_FAIL;
+ smp_proc_pairing_cmpl(p_cb);
+ }
+}
+
+/*******************************************************************************
+** Function smp_fast_conn_param
+** Description apply default connection parameter for pairing process
+*******************************************************************************/
+void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ /* disable connection parameter update */
+ L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+}
+
+/*******************************************************************************
+** Function smp_both_have_public_keys
+** Description The function is called when both local and peer public keys are
+** saved.
+** Actions:
+** - invokes DHKey computation;
+** - on slave side invokes sending local public key to the peer.
+** - invokes SC phase 1 process.
+*******************************************************************************/
+void smp_both_have_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s",__func__);
+
+ /* invokes DHKey computation */
+ smp_compute_dhkey(p_cb);
+
+ /* on slave side invokes sending local public key to the peer */
+ if (p_cb->role == HCI_ROLE_SLAVE)
+ smp_send_pair_public_key(p_cb, NULL);
+
+ smp_sm_event(p_cb, SMP_SC_DHKEY_CMPLT_EVT, NULL);
+}
/*******************************************************************************
-** Function smp_check_auth_req
-** Description check authentication request
+** Function smp_start_secure_connection_phase1
+** Description The function starts Secure Connection phase1 i.e. invokes initialization of Secure Connection
+** phase 1 parameters and starts building/sending to the peer
+** messages appropriate for the role and association model.
*******************************************************************************/
-void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_start_secure_connection_phase1(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 enc_enable = *(UINT8 *)p_data;
- UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+ SMP_TRACE_DEBUG("%s", __func__);
- SMP_TRACE_DEBUG ("smp_check_auth_req enc_enable=%d i_keys=0x%x r_keys=0x%x (i-initiator r-responder)",
- enc_enable, p_cb->loc_i_key, p_cb->loc_r_key);
- if (enc_enable == 1)
+ if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS)
{
- if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
- (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
- (p_cb->loc_i_key || p_cb->loc_r_key))
- {
- smp_sm_event(p_cb, SMP_BOND_REQ_EVT, NULL);
- }
- else
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
+ SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ", p_cb->sec_level );
}
- else if (enc_enable == 0)
+ else
{
- /* if failed for encryption after pairing, send callback */
- if (p_cb->flags & SMP_PAIR_FLAG_ENC_AFTER_PAIR)
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
- /* if enc failed for old security information */
- /* if master device, clean up and abck to idle; slave device do nothing */
- else if (p_cb->role == HCI_ROLE_MASTER)
- {
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
- }
+ p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+ SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
}
-}
-
-/*******************************************************************************
-** Function smp_key_pick_key
-** Description Pick a key distribution function based on the key mask.
-*******************************************************************************/
-void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
-{
- UINT8 key_to_dist = (p_cb->role == HCI_ROLE_SLAVE) ? p_cb->loc_r_key : p_cb->loc_i_key;
- UINT8 i = 0;
- SMP_TRACE_DEBUG ("smp_key_pick_key key_to_dist=0x%x", key_to_dist);
- while (i < MAX_KEY_DISTRIBUTION_TYPES)
+ switch(p_cb->selected_association_model)
{
- SMP_TRACE_DEBUG("key to send = %02x, i = %d", key_to_dist, i);
-
- if (key_to_dist & (1 << i))
- {
- SMP_TRACE_DEBUG ("smp_distribute_act[%d]", i);
- (* smp_distribute_act[i])(p_cb, p_data);
+ case SMP_MODEL_SEC_CONN_JUSTWORKS:
+ case SMP_MODEL_SEC_CONN_NUM_COMP:
+ memset(p_cb->local_random, 0, BT_OCTET16_LEN);
+ smp_start_nonce_generation(p_cb);
+ break;
+ case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+ /* user has to provide passkey */
+ p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
+ smp_sm_event(p_cb, SMP_TK_REQ_EVT, NULL);
+ break;
+ case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+ /* passkey has to be provided to user */
+ SMP_TRACE_DEBUG("Need to generate SC Passkey");
+ smp_generate_passkey(p_cb, NULL);
+ break;
+ case SMP_MODEL_SEC_CONN_OOB:
+ /* use the available OOB information */
+ smp_process_secure_connection_oob_data(p_cb, NULL);
+ break;
+ default:
+ SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC",
+ p_cb->selected_association_model);
break;
- }
- i ++;
}
}
+
/*******************************************************************************
-** Function smp_key_distribution
-** Description start key distribution if required.
+** Function smp_process_local_nonce
+** Description The function processes new local nonce.
+**
+** Note It is supposed to be called in SC phase1.
*******************************************************************************/
-void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 reason = SMP_SUCCESS;
- SMP_TRACE_DEBUG ("smp_key_distribution role=%d (0-master) r_keys=0x%x i_keys=0x%x",
- p_cb->role, p_cb->loc_r_key, p_cb->loc_i_key);
+ SMP_TRACE_DEBUG("%s", __func__);
- if (p_cb->role == HCI_ROLE_SLAVE||
- (!p_cb->loc_r_key && p_cb->role == HCI_ROLE_MASTER))
+ switch(p_cb->selected_association_model)
{
- smp_key_pick_key(p_cb, p_data);
- }
+ case SMP_MODEL_SEC_CONN_JUSTWORKS:
+ case SMP_MODEL_SEC_CONN_NUM_COMP:
+ if (p_cb->role == HCI_ROLE_SLAVE)
+ {
+ /* slave calculates and sends local commitment */
+ smp_calculate_local_commitment(p_cb);
+ smp_send_commitment(p_cb, NULL);
+ /* slave has to wait for peer nonce */
+ smp_set_state(SMP_STATE_WAIT_NONCE);
+ }
+ else /* i.e. master */
+ {
+ if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_COMM)
+ {
+ /* slave commitment is already received, send local nonce, wait for remote nonce*/
+ SMP_TRACE_DEBUG("master in assoc mode = %d \
+ already rcvd slave commitment - race condition",
+ p_cb->selected_association_model);
+ p_cb->flags &= ~SMP_PAIR_FLAG_HAVE_PEER_COMM;
+ smp_send_rand(p_cb, NULL);
+ smp_set_state(SMP_STATE_WAIT_NONCE);
+ }
+ }
+ break;
+ case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+ case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+ smp_calculate_local_commitment(p_cb);
- if (!p_cb->loc_i_key && !p_cb->loc_r_key)
- {
- /* state check to prevent re-entrant */
- if (smp_get_state() == SMP_ST_BOND_PENDING)
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ smp_send_commitment(p_cb, NULL);
+ }
+ else /* slave */
+ {
+ if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_COMM)
+ {
+ /* master commitment is already received */
+ smp_send_commitment(p_cb, NULL);
+ smp_set_state(SMP_STATE_WAIT_NONCE);
+ }
+ }
+ break;
+ case SMP_MODEL_SEC_CONN_OOB:
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ smp_send_rand(p_cb, NULL);
+ }
+
+ smp_set_state(SMP_STATE_WAIT_NONCE);
+ break;
+ default:
+ SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC",
+ p_cb->selected_association_model);
+ break;
}
}
+
/*******************************************************************************
-** Function smp_decide_asso_model
-** Description This function is called to compare both sides' io capability
-** oob data flag and authentication request, and decide the
-** association model to use for the authentication.
+** Function smp_process_peer_nonce
+** Description The function processes newly received and saved in CB peer nonce.
+** The actions depend on the selected association model and the role.
+**
+** Note It is supposed to be called in SC phase1.
*******************************************************************************/
-void smp_decide_asso_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 failure = SMP_UNKNOWN_IO_CAP;
- tSMP_ASSO_MODEL model = SMP_MODEL_MAX;
- UINT8 int_evt = 0;
- tSMP_KEY key;
- tSMP_INT_DATA *p = NULL;
- UNUSED(p_data);
+ UINT8 reason;
- SMP_TRACE_DEBUG ("smp_decide_asso_model p_cb->peer_io_caps = %d p_cb->loc_io_caps = %d \
- p_cb->peer_auth_req = %02x",
- p_cb->peer_io_caps, p_cb->loc_io_caps, p_cb->peer_auth_req);
+ SMP_TRACE_DEBUG("%s start ", __func__);
- /* OOB data present on both devices, use OOB association model */
- if (p_cb->peer_oob_flag == SMP_OOB_PRESENT && p_cb->loc_oob_flag == SMP_OOB_PRESENT)
- {
- model = SMP_MODEL_OOB;
- }
- /* no MITM required, ignore IO cap, use encryption only */
- else if (SMP_NO_MITM_REQUIRED (p_cb->peer_auth_req) &&
- SMP_NO_MITM_REQUIRED(p_cb->loc_auth_req))
+ switch(p_cb->selected_association_model)
{
- model = SMP_MODEL_ENC_ONLY;
- }
- else/* use IO capability to decide assiciation model */
- {
- if (p_cb->peer_io_caps < SMP_IO_CAP_MAX && p_cb->loc_io_caps < SMP_IO_CAP_MAX)
- {
+ case SMP_MODEL_SEC_CONN_JUSTWORKS:
+ case SMP_MODEL_SEC_CONN_NUM_COMP:
+ /* in these models only master receives commitment */
if (p_cb->role == HCI_ROLE_MASTER)
- model = smp_association_table[p_cb->role][p_cb->peer_io_caps][p_cb->loc_io_caps];
+ {
+ if (!smp_check_commitment(p_cb))
+ {
+ reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ break;
+ }
+ }
else
- model = smp_association_table[p_cb->role][p_cb->loc_io_caps][p_cb->peer_io_caps];
- }
+ {
+ /* slave sends local nonce */
+ smp_send_rand(p_cb, NULL);
+ }
+
+ if(p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS)
+ {
+ /* go directly to phase 2 */
+ smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+ }
+ else /* numeric comparison */
+ {
+ smp_set_state(SMP_STATE_WAIT_NONCE);
+ smp_sm_event(p_cb, SMP_SC_CALC_NC_EVT, NULL);
+ }
+ break;
+ case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+ case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+ if (!smp_check_commitment(p_cb))
+ {
+ reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ break;
+ }
+
+ if (p_cb->role == HCI_ROLE_SLAVE)
+ {
+ smp_send_rand(p_cb, NULL);
+ }
+
+ if (++p_cb->round < 20)
+ {
+ smp_set_state(SMP_STATE_SEC_CONN_PHS1_START);
+ p_cb->flags &= ~SMP_PAIR_FLAG_HAVE_PEER_COMM;
+ smp_start_nonce_generation(p_cb);
+ break;
+ }
+
+ smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+ break;
+ case SMP_MODEL_SEC_CONN_OOB:
+ if (p_cb->role == HCI_ROLE_SLAVE)
+ {
+ smp_send_rand(p_cb, NULL);
+ }
+
+ smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+ break;
+ default:
+ SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC",
+ p_cb->selected_association_model);
+ break;
}
- SMP_TRACE_DEBUG("Association Model = %d", model);
+ SMP_TRACE_DEBUG("%s end ",__FUNCTION__);
+}
- if (model == SMP_MODEL_OOB)
- {
- SMP_TRACE_ERROR("Association Model = SMP_MODEL_OOB");
- p_cb->sec_level = SMP_SEC_AUTHENTICATED;
- SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
- p_cb->cb_evt = SMP_OOB_REQ_EVT;
+/*******************************************************************************
+** Function smp_match_dhkey_checks
+** Description checks if the calculated peer DHKey Check value is the same as
+** received from the peer DHKey check value.
+*******************************************************************************/
+void smp_match_dhkey_checks(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 reason = SMP_DHKEY_CHK_FAIL;
- int_evt = SMP_TK_REQ_EVT;
- }
- else if (model == SMP_MODEL_PASSKEY)
- {
- p_cb->sec_level = SMP_SEC_AUTHENTICATED;
- SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
+ SMP_TRACE_DEBUG("%s", __func__);
- p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
- int_evt = SMP_TK_REQ_EVT;
- }
- else if (model == SMP_MODEL_KEY_NOTIF)
+ if (memcmp(p_data->key.p_data, p_cb->remote_dhkey_check, BT_OCTET16_LEN))
{
- p_cb->sec_level = SMP_SEC_AUTHENTICATED;
-
- SMP_TRACE_DEBUG("Need to generate Passkey");
- /* generate passkey and notify application */
- smp_generate_passkey(p_cb, NULL);
+ SMP_TRACE_WARNING ("dhkey chcks do no match");
+ p_cb->failure = reason;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
}
- else if (model == SMP_MODEL_ENC_ONLY) /* TK = 0, go calculate Confirm */
- {
- if (p_cb->role == HCI_ROLE_MASTER &&
- ((p_cb->peer_auth_req & SMP_AUTH_YN_BIT) != 0) &&
- ((p_cb->loc_auth_req & SMP_AUTH_YN_BIT) == 0))
- {
- SMP_TRACE_ERROR("IO capability does not meet authentication requirement");
- failure = SMP_PAIR_AUTH_FAIL;
- p = (tSMP_INT_DATA *)&failure;
- int_evt = SMP_AUTH_CMPL_EVT;
- }
- else
- {
- p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
- SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ", p_cb->sec_level );
- key.key_type = SMP_KEY_TYPE_TK;
- key.p_data = p_cb->tk;
- p = (tSMP_INT_DATA *)&key;
+ SMP_TRACE_EVENT ("dhkey chcks match");
- memset(p_cb->tk, 0, BT_OCTET16_LEN);
- /* TK, ready */
- int_evt = SMP_KEY_READY_EVT;
- }
+ /* compare the max encryption key size, and save the smaller one for the link */
+ if (p_cb->peer_enc_size < p_cb->loc_enc_size)
+ p_cb->loc_enc_size = p_cb->peer_enc_size;
+
+ if (p_cb->role == HCI_ROLE_SLAVE)
+ {
+ smp_sm_event(p_cb, SMP_PAIR_DHKEY_CHCK_EVT, NULL);
}
- else if (model == SMP_MODEL_MAX)
+ else
{
- SMP_TRACE_ERROR("Association Model = SMP_MODEL_MAX (failed)");
- p = (tSMP_INT_DATA *)&failure;
- int_evt = SMP_AUTH_CMPL_EVT;
+ /* master device always use received i/r key as keys to distribute */
+ p_cb->local_i_key = p_cb->peer_i_key;
+ p_cb->local_r_key = p_cb->peer_r_key;
+ smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
}
+}
- SMP_TRACE_EVENT ("sec_level=%d ", p_cb->sec_level );
- if (int_evt)
- smp_sm_event(p_cb, int_evt, p);
+/*******************************************************************************
+** Function smp_move_to_secure_connections_phase2
+** Description Signal State Machine to start SC phase 2 initialization (to
+** compute local DHKey Check value).
+**
+** Note SM is supposed to be in the state SMP_STATE_SEC_CONN_PHS2_START.
+*******************************************************************************/
+void smp_move_to_secure_connections_phase2(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s",__func__);
+ smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
}
/*******************************************************************************
-** Function smp_proc_io_rsp
-** Description process IO response for a slave device.
+** Function smp_phase_2_dhkey_checks_are_present
+** Description generates event if dhkey check from the peer is already received.
+**
+** Note It is supposed to be used on slave to prevent race condition.
+** It is supposed to be called after slave dhkey check is calculated.
*******************************************************************************/
-void smp_proc_io_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_phase_2_dhkey_checks_are_present(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
+ SMP_TRACE_DEBUG("%s",__func__);
- SMP_TRACE_DEBUG ("smp_proc_io_rsp ");
- if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
- {
- smp_set_state(SMP_ST_SEC_REQ_PENDING);
- smp_send_cmd(SMP_OPCODE_SEC_REQ, p_cb);
- }
- else /* respond to pairing request */
- {
- smp_send_pair_rsp(p_cb, NULL);
- }
+ if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK)
+ smp_sm_event(p_cb, SMP_SC_2_DHCK_CHKS_PRES_EVT, NULL);
}
+
/*******************************************************************************
-** Function smp_pairing_cmpl
-** Description This function is called to send the pairing complete callback
-** and remove the connection if needed.
+** Function smp_wait_for_both_public_keys
+** Description generates SMP_BOTH_PUBL_KEYS_RCVD_EVT event when both local and master
+** public keys are available.
+**
+** Note on the slave it is used to prevent race condition.
+**
*******************************************************************************/
-void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_wait_for_both_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
+ SMP_TRACE_DEBUG("%s",__func__);
- SMP_TRACE_DEBUG ("smp_pairing_cmpl ");
-
- if ((p_cb->status == SMP_SUCCESS) ||
- (p_cb->status <= SMP_REPEATED_ATTEMPTS && p_cb->status != SMP_SUCCESS))
- {
- smp_sm_event(p_cb, SMP_RELEASE_DELAY_EVT, p_data);
- }
- else
+ if ((p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY) &&
+ (p_cb->flags & SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY))
{
- /* this will transition to idle state right away */
- smp_sm_event(p_cb, SMP_RELEASE_DELAY_TOUT_EVT, p_data);
+ if ((p_cb->role == HCI_ROLE_SLAVE) &&
+ ((p_cb->req_oob_type == SMP_OOB_LOCAL) || (p_cb->req_oob_type == SMP_OOB_BOTH)))
+ {
+ smp_set_state(SMP_STATE_PUBLIC_KEY_EXCH);
+ }
+ smp_sm_event(p_cb, SMP_BOTH_PUBL_KEYS_RCVD_EVT, NULL);
}
-
}
+
/*******************************************************************************
-** Function smp_pair_terminate
-** Description This function is called to send the pairing complete callback
-** and remove the connection if needed.
+** Function smp_start_passkey_verification
+** Description Starts SC passkey entry verification.
*******************************************************************************/
-void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
+ UINT8 *p = NULL;
- SMP_TRACE_DEBUG ("smp_pair_terminate ");
+ SMP_TRACE_DEBUG("%s", __func__);
+ p = p_cb->local_random;
+ UINT32_TO_STREAM(p, p_data->passkey);
- p_cb->status = SMP_CONN_TOUT;
+ p = p_cb->peer_random;
+ UINT32_TO_STREAM(p, p_data->passkey);
- smp_proc_pairing_cmpl(p_cb);
+ p_cb->round = 0;
+ smp_start_nonce_generation(p_cb);
}
/*******************************************************************************
-** Function smp_delay_terminate
-** Description This function is called when connection dropped when smp delay
-** timer is still active.
+** Function smp_process_secure_connection_oob_data
+** Description Processes local/peer SC OOB data received from somewhere.
*******************************************************************************/
-void smp_delay_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- SMP_TRACE_DEBUG ("smp_delay_terminate ");
+ SMP_TRACE_DEBUG("%s", __func__);
- btu_stop_timer (&p_cb->rsp_timer_ent);
+ tSMP_SC_OOB_DATA *p_sc_oob_data = &p_cb->sc_oob_data;
+ if (p_sc_oob_data->loc_oob_data.present)
+ {
+ memcpy(p_cb->local_random, p_sc_oob_data->loc_oob_data.randomizer,
+ sizeof(p_cb->local_random));
+ }
+ else
+ {
+ SMP_TRACE_EVENT ("local OOB randomizer is absent");
+ memset(p_cb->local_random, 0, sizeof (p_cb->local_random));
+ }
+
+ if (!p_sc_oob_data->peer_oob_data.present)
+ {
+ SMP_TRACE_EVENT ("peer OOB data is absent");
+ memset(p_cb->peer_random, 0, sizeof (p_cb->peer_random));
+ }
+ else
+ {
+ memcpy(p_cb->peer_random, p_sc_oob_data->peer_oob_data.randomizer,
+ sizeof(p_cb->peer_random));
+ memcpy(p_cb->remote_commitment, p_sc_oob_data->peer_oob_data.commitment,
+ sizeof(p_cb->remote_commitment));
+
+ UINT8 reason = SMP_CONFIRM_VALUE_ERR;
+ /* check commitment */
+ if (!smp_check_commitment(p_cb))
+ {
+ p_cb->failure = reason;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
- /* if remote user terminate connection, keep the previous status */
- /* this is to avoid reporting reverse status to uplayer */
- if (p_data->reason != HCI_ERR_PEER_USER)
- p_cb->status = SMP_CONN_TOUT;
+ if (p_cb->peer_oob_flag != SMP_OOB_PRESENT)
+ {
+ /* the peer doesn't have local randomiser */
+ SMP_TRACE_EVENT ("peer didn't receive local OOB data, set local randomizer to 0");
+ memset(p_cb->local_random, 0, sizeof (p_cb->local_random));
+ }
+ }
- smp_proc_pairing_cmpl(p_cb);
+ print128(p_cb->local_random, (const UINT8 *)"local OOB randomizer");
+ print128(p_cb->peer_random, (const UINT8 *)"peer OOB randomizer");
+ smp_start_nonce_generation(p_cb);
}
+
/*******************************************************************************
-** Function smp_idle_terminate
-** Description This function called in idle state to determine to send authentication
-** complete or not.
+** Function smp_set_local_oob_keys
+** Description Saves calculated private/public keys in sc_oob_data.loc_oob_data,
+** starts nonce generation
+** (to be saved in sc_oob_data.loc_oob_data.randomizer).
*******************************************************************************/
-void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UNUSED(p_data);
- if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
- {
- SMP_TRACE_DEBUG("Pairing terminated at IDLE state.");
- p_cb->status = SMP_FAIL;
- smp_proc_pairing_cmpl(p_cb);
- }
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ memcpy(p_cb->sc_oob_data.loc_oob_data.private_key_used, p_cb->private_key,
+ BT_OCTET32_LEN);
+ p_cb->sc_oob_data.loc_oob_data.publ_key_used = p_cb->loc_publ_key;
+ smp_start_nonce_generation(p_cb);
}
/*******************************************************************************
-** Function smp_fast_conn_param
-** Description apply default connection parameter for pairing process
+** Function smp_set_local_oob_random_commitment
+** Description Saves calculated randomizer and commitment in sc_oob_data.loc_oob_data,
+** passes sc_oob_data.loc_oob_data up for safekeeping.
*******************************************************************************/
-void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- /* disable connection parameter update */
- (void)L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
-}
+ SMP_TRACE_DEBUG("%s", __func__);
+ memcpy(p_cb->sc_oob_data.loc_oob_data.randomizer, p_cb->rand,
+ BT_OCTET16_LEN);
+
+ smp_calculate_f4(p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
+ p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
+ p_cb->sc_oob_data.loc_oob_data.randomizer, 0,
+ p_cb->sc_oob_data.loc_oob_data.commitment);
+
+#if SMP_DEBUG == TRUE
+ UINT8 *p_print = NULL;
+ SMP_TRACE_DEBUG("local SC OOB data set:");
+ p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.addr_sent_to;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"addr_sent_to",
+ sizeof(tBLE_BD_ADDR));
+ p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.private_key_used;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"private_key_used",
+ BT_OCTET32_LEN);
+ p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.publ_key_used.x;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"publ_key_used.x",
+ BT_OCTET32_LEN);
+ p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.publ_key_used.y;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"publ_key_used.y",
+ BT_OCTET32_LEN);
+ p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.randomizer;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"randomizer",
+ BT_OCTET16_LEN);
+ p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.commitment;
+ smp_debug_print_nbyte_little_endian (p_print,(const UINT8 *) "commitment",
+ BT_OCTET16_LEN);
+ SMP_TRACE_DEBUG("");
+#endif
+ /* pass created OOB data up */
+ p_cb->cb_evt = SMP_SC_LOC_OOB_DATA_UP_EVT;
+ smp_send_app_cback(p_cb, NULL);
+
+ smp_cb_cleanup(p_cb);
+}
/*******************************************************************************
**
{
tSMP_CB *p_cb = &smp_cb;
- SMP_TRACE_DEBUG ("smp_link_encrypted encr_enable=%d",encr_enable);
+ SMP_TRACE_DEBUG("%s encr_enable=%d", __func__, encr_enable);
if (memcmp(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN) == 0)
{
smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
}
}
+
/*******************************************************************************
**
** Function smp_proc_ltk_request
*******************************************************************************/
BOOLEAN smp_proc_ltk_request(BD_ADDR bda)
{
- SMP_TRACE_DEBUG ("smp_proc_ltk_request state = %d", smp_cb.state);
- if ( smp_cb.state == SMP_ST_ENC_PENDING &&
+ SMP_TRACE_DEBUG("%s state = %d", __func__, smp_cb.state);
+ if ( smp_cb.state == SMP_STATE_ENCRYPTION_PENDING &&
!memcmp(bda, smp_cb.pairing_bda, BD_ADDR_LEN))
{
smp_sm_event(&smp_cb, SMP_ENC_REQ_EVT, NULL);
return FALSE;
}
-#endif
+
+/*******************************************************************************
+**
+** Function smp_process_secure_connection_long_term_key
+**
+** Description This function is called to process SC LTK.
+** SC LTK is calculated and used instead of STK.
+** Here SC LTK is saved in BLE DB.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_process_secure_connection_long_term_key(void)
+{
+ tSMP_CB *p_cb = &smp_cb;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ smp_save_secure_connections_long_term_key(p_cb);
+
+ smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
+ smp_key_distribution(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function smp_derive_link_key_from_long_term_key
+**
+** Description This function is called to derive BR/EDR LK from LTK.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (!smp_calculate_link_key_from_long_term_key(p_cb))
+ {
+ SMP_TRACE_ERROR ("%s failed", __FUNCTION__);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ return;
+ }
+
+ smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_LK, FALSE);
+
+ SMP_TRACE_DEBUG("%s successfully completed", __FUNCTION__);
+ smp_key_distribution(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function smp_br_process_link_key
+**
+** Description This function is called to process BR/EDR LK:
+** - to derive SMP LTK from BR/EDR LK;
+*8 - to save SMP LTK.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_br_process_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (!smp_calculate_long_term_key_from_link_key(p_cb))
+ {
+ SMP_TRACE_ERROR ("%s failed",__FUNCTION__);
+ smp_sm_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+ return;
+ }
+
+ SMP_TRACE_DEBUG("%s: LTK derivation from LK successfully completed", __FUNCTION__);
+ smp_save_secure_connections_long_term_key(p_cb);
+ smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
+ smp_br_select_next_key(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function smp_key_distribution_by_transport
+** Description depending on the transport used at the moment calls either
+** smp_key_distribution(...) or smp_br_key_distribution(...).
+*******************************************************************************/
+void smp_key_distribution_by_transport(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+ if (p_cb->smp_over_br)
+ {
+ smp_br_select_next_key(p_cb, NULL);
+ }
+ else
+ {
+ smp_key_distribution(p_cb, NULL);
+ }
+}
+
+/*******************************************************************************
+** Function smp_br_pairing_complete
+** Description This function is called to send the pairing complete callback
+** and remove the connection if needed.
+*******************************************************************************/
+void smp_br_pairing_complete(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+ /* process the pairing complete */
+ smp_proc_pairing_cmpl(p_cb);
+}
+
#include "hcimsgs.h"
#include "btu.h"
-
+ #include "p_256_ecc_pp.h"
/*******************************************************************************
**
*******************************************************************************/
void SMP_Init(void)
{
-
- SMP_TRACE_EVENT ("SMP_Init");
memset(&smp_cb, 0, sizeof(tSMP_CB));
#if defined(SMP_INITIAL_TRACE_LEVEL)
#else
smp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
#endif
+ SMP_TRACE_EVENT ("%s", __FUNCTION__);
smp_l2cap_if_init();
+ /* initialization of P-256 parameters */
+ p_256_init_curve(KEY_LENGTH_DWORDS_P256);
}
tSMP_CB *p_cb = &smp_cb;
UINT8 status = SMP_PAIR_INTERNAL_ERR;
- BTM_TRACE_EVENT ("SMP_Pair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
- if (p_cb->state != SMP_ST_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
+ SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ",
+ __FUNCTION__, p_cb->state, p_cb->br_state, p_cb->flags);
+ if (p_cb->state != SMP_STATE_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD ||
+ p_cb->smp_over_br)
{
/* pending security on going, reject this one */
return SMP_BUSY;
if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr))
{
- SMP_TRACE_ERROR("SMP_Pair: L2C connect fixed channel failed.");
+ SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __FUNCTION__);
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
return status;
}
}
}
+/*******************************************************************************
+**
+** Function SMP_BR_PairWith
+**
+** Description This function is called to start a SMP pairing over BR/EDR.
+** Device support one SMP pairing at one time.
+**
+** Parameters bd_addr - peer device bd address.
+**
+** Returns SMP_STARTED if pairing started, otherwise reason for failure.
+**
+*******************************************************************************/
+tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr)
+{
+ tSMP_CB *p_cb = &smp_cb;
+ UINT8 status = SMP_PAIR_INTERNAL_ERR;
+
+ SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ",
+ __func__, p_cb->state, p_cb->br_state, p_cb->flags);
+
+ if (p_cb->state != SMP_STATE_IDLE ||
+ p_cb->smp_over_br ||
+ p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
+ {
+ /* pending security on going, reject this one */
+ return SMP_BUSY;
+ }
+
+ p_cb->role = HCI_ROLE_MASTER;
+ p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
+ p_cb->smp_over_br = TRUE;
+
+ memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);
+
+ if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr))
+ {
+ SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.",__FUNCTION__);
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+ return status;
+ }
+
+ return SMP_STARTED;
+}
/*******************************************************************************
**
BOOLEAN status = FALSE;
BTM_TRACE_EVENT ("SMP_CancelPair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
- if ( (p_cb->state != SMP_ST_IDLE) &&
+ if ( (p_cb->state != SMP_STATE_IDLE) &&
(!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) )
{
p_cb->is_pair_cancel = TRUE;
void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res)
{
SMP_TRACE_EVENT ("SMP_SecurityGrant ");
- if (smp_cb.state != SMP_ST_WAIT_APP_RSP ||
+
+ if (smp_cb.smp_over_br)
+ {
+ if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP ||
+ smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
+ memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN))
+ {
+ return;
+ }
+
+ /* clear the SMP_SEC_REQUEST_EVT event after get grant */
+ /* avoid generating duplicate pair request */
+ smp_cb.cb_evt = 0;
+ smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &res);
+ return;
+ }
+
+ if (smp_cb.state != SMP_STATE_WAIT_APP_RSP ||
smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN))
return;
-
/* clear the SMP_SEC_REQUEST_EVT event after get grant */
/* avoid generate duplicate pair request */
smp_cb.cb_evt = 0;
{
tSMP_CB *p_cb = & smp_cb;
UINT8 failure = SMP_PASSKEY_ENTRY_FAIL;
- tBTM_SEC_DEV_REC *p_dev_rec;
SMP_TRACE_EVENT ("SMP_PasskeyReply: Key: %d Result:%d",
passkey, res);
return;
}
- if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
+ if (btm_find_dev (bd_addr) == NULL)
{
SMP_TRACE_ERROR ("SMP_PasskeyReply() - no dev CB");
return;
}
-
if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS)
{
SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail", passkey);
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
}
+ else if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_ENT)
+ {
+ smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &passkey);
+ }
else
{
smp_convert_string_to_tk(p_cb->tk, passkey);
/*******************************************************************************
**
+** Function SMP_ConfirmReply
+**
+** Description This function is called after Security Manager submitted
+** numeric comparison request to the application.
+**
+** Parameters: bd_addr - Address of the device with which numeric
+** comparison was requested
+** res - comparison result SMP_SUCCESS if success
+**
+*******************************************************************************/
+void SMP_ConfirmReply (BD_ADDR bd_addr, UINT8 res)
+{
+ tSMP_CB *p_cb = & smp_cb;
+ UINT8 failure = SMP_NUMERIC_COMPAR_FAIL;
+
+ SMP_TRACE_EVENT ("%s: Result:%d", __FUNCTION__, res);
+
+ /* If timeout already expired or has been canceled, ignore the reply */
+ if (p_cb->cb_evt != SMP_NC_REQ_EVT)
+ {
+ SMP_TRACE_WARNING ("%s() - Wrong State: %d", __FUNCTION__,p_cb->state);
+ return;
+ }
+
+ if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0)
+ {
+ SMP_TRACE_ERROR ("%s() - Wrong BD Addr",__FUNCTION__);
+ return;
+ }
+
+ if (btm_find_dev (bd_addr) == NULL)
+ {
+ SMP_TRACE_ERROR ("%s() - no dev CB",__FUNCTION__);
+ return;
+ }
+
+ if (res != SMP_SUCCESS)
+ {
+ SMP_TRACE_WARNING ("%s() - Numeric Comparison fails",__FUNCTION__);
+ /* send pairing failure */
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ }
+ else
+ {
+ smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL);
+ }
+}
+
+/*******************************************************************************
+**
** Function SMP_OobDataReply
**
** Description This function is called to provide the OOB data for
tSMP_CB *p_cb = & smp_cb;
UINT8 failure = SMP_OOB_FAIL;
tSMP_KEY key;
- UNUSED(bd_addr);
- SMP_TRACE_EVENT ("SMP_OobDataReply State: %d res:%d",
- smp_cb.state, res);
+ SMP_TRACE_EVENT ("%s State: %d res:%d", __FUNCTION__, smp_cb.state, res);
/* If timeout already expired or has been canceled, ignore the reply */
- if (p_cb->state != SMP_ST_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT)
+ if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT)
return;
if (res != SMP_SUCCESS || len == 0 || !p_data)
/*******************************************************************************
**
+** Function SMP_SecureConnectionOobDataReply
+**
+** Description This function is called to provide the SC OOB data for
+** SMP in response to SMP_SC_OOB_REQ_EVT
+**
+** Parameters: p_data - pointer to the data
+**
+*******************************************************************************/
+void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
+{
+ tSMP_CB *p_cb = &smp_cb;
+
+ UINT8 failure = SMP_OOB_FAIL;
+ tSMP_SC_OOB_DATA *p_oob = (tSMP_SC_OOB_DATA *) p_data;
+ if (!p_oob)
+ {
+ SMP_TRACE_ERROR("%s received no data",__FUNCTION__);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ return;
+ }
+
+ SMP_TRACE_EVENT ("%s req_oob_type: %d, loc_oob_data.present: %d, "
+ "peer_oob_data.present: %d",
+ __FUNCTION__, p_cb->req_oob_type, p_oob->loc_oob_data.present,
+ p_oob->peer_oob_data.present);
+
+ if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT)
+ return;
+
+ BOOLEAN data_missing = FALSE;
+ switch (p_cb->req_oob_type)
+ {
+ case SMP_OOB_PEER:
+ if (!p_oob->peer_oob_data.present)
+ data_missing = TRUE;
+ break;
+ case SMP_OOB_LOCAL:
+ if (!p_oob->loc_oob_data.present)
+ data_missing = TRUE;
+ break;
+ case SMP_OOB_BOTH:
+ if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present)
+ data_missing = TRUE;
+ break;
+ default:
+ SMP_TRACE_EVENT ("Unexpected OOB data type requested. Fail OOB");
+ data_missing = TRUE;
+ break;
+ }
+
+ if (data_missing)
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ return;
+ }
+
+ p_cb->sc_oob_data = *p_oob;
+
+ smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, p_data);
+}
+
+/*******************************************************************************
+**
** Function SMP_Encrypt
**
** Description This function is called to encrypt the data with the specified
status = smp_encrypt_data(key, key_len, plain_text, pt_len, p_out);
return status;
}
+
+/*******************************************************************************
+**
+** Function SMP_KeypressNotification
+**
+** Description This function is called to notify Security Manager about Keypress Notification.
+**
+** Parameters: bd_addr Address of the device to send keypress notification to
+** value Keypress notification parameter value
+**
+*******************************************************************************/
+void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value)
+{
+ tSMP_CB *p_cb = &smp_cb;
+
+ SMP_TRACE_EVENT ("%s: Value: %d", __FUNCTION__,value);
+
+ if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0)
+ {
+ SMP_TRACE_ERROR ("%s() - Wrong BD Addr",__FUNCTION__);
+ return;
+ }
+
+ if (btm_find_dev (bd_addr) == NULL)
+ {
+ SMP_TRACE_ERROR ("%s() - no dev CB",__FUNCTION__);
+ return;
+ }
+
+ /* Keypress Notification is used by a device with KeyboardOnly IO capabilities */
+ /* during the passkey entry protocol */
+ if (p_cb->local_io_capability != SMP_IO_CAP_IN)
+ {
+ SMP_TRACE_ERROR ("%s() - wrong local IO capabilities %d",
+ __FUNCTION__, p_cb->local_io_capability);
+ return;
+ }
+
+ if (p_cb->selected_association_model != SMP_MODEL_SEC_CONN_PASSKEY_ENT)
+ {
+ SMP_TRACE_ERROR ("%s() - wrong protocol %d", __FUNCTION__,
+ p_cb->selected_association_model);
+ return;
+ }
+
+ smp_sm_event(p_cb, SMP_KEYPRESS_NOTIFICATION_EVENT, &value);
+}
+
+/*******************************************************************************
+**
+** Function SMP_CreateLocalSecureConnectionsOobData
+**
+** Description This function is called to start creation of local SC OOB
+** data set (tSMP_LOC_OOB_DATA).
+**
+** Parameters: bd_addr - Address of the device to send OOB data block to
+**
+** Returns Boolean - TRUE: creation of local SC OOB data set started.
+*******************************************************************************/
+BOOLEAN SMP_CreateLocalSecureConnectionsOobData (tBLE_BD_ADDR *addr_to_send_to)
+{
+ tSMP_CB *p_cb = &smp_cb;
+ UINT8 *bd_addr;
+
+ if (addr_to_send_to == NULL)
+ {
+ SMP_TRACE_ERROR ("%s addr_to_send_to is not provided",__FUNCTION__);
+ return FALSE;
+ }
+
+ bd_addr = addr_to_send_to->bda;
+
+ SMP_TRACE_EVENT ("%s addr type: %u, BDA: %08x%04x, state: %u, br_state: %u",
+ __FUNCTION__, addr_to_send_to->type,
+ (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3],
+ (bd_addr[4]<<8)+bd_addr[5],
+ p_cb->state,
+ p_cb->br_state);
+
+ if ((p_cb->state != SMP_STATE_IDLE) || (p_cb->smp_over_br))
+ {
+ SMP_TRACE_WARNING ("%s creation of local OOB data set "\
+ "starts only in IDLE state",__FUNCTION__);
+ return FALSE;
+ }
+
+ p_cb->sc_oob_data.loc_oob_data.addr_sent_to = *addr_to_send_to;
+ smp_sm_event(p_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, NULL);
+
+ return TRUE;
+}
+
#endif /* SMP_INCLUDED */
--- /dev/null
+/******************************************************************************
+ *
+ * Copyright (C) 2014-2015 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#include <string.h>
+#include "smp_int.h"
+
+const char *const smp_br_state_name [SMP_BR_STATE_MAX+1] =
+{
+ "SMP_BR_STATE_IDLE",
+ "SMP_BR_STATE_WAIT_APP_RSP",
+ "SMP_BR_STATE_PAIR_REQ_RSP",
+ "SMP_BR_STATE_BOND_PENDING",
+ "SMP_BR_STATE_OUT_OF_RANGE"
+};
+
+const char *const smp_br_event_name [SMP_BR_MAX_EVT] =
+{
+ "BR_PAIRING_REQ_EVT",
+ "BR_PAIRING_RSP_EVT",
+ "BR_CONFIRM_EVT",
+ "BR_RAND_EVT",
+ "BR_PAIRING_FAILED_EVT",
+ "BR_ENCRPTION_INFO_EVT",
+ "BR_MASTER_ID_EVT",
+ "BR_ID_INFO_EVT",
+ "BR_ID_ADDR_EVT",
+ "BR_SIGN_INFO_EVT",
+ "BR_SECURITY_REQ_EVT",
+ "BR_PAIR_PUBLIC_KEY_EVT",
+ "BR_PAIR_DHKEY_CHCK_EVT",
+ "BR_PAIR_KEYPR_NOTIF_EVT",
+ "BR_KEY_READY_EVT",
+ "BR_ENCRYPTED_EVT",
+ "BR_L2CAP_CONN_EVT",
+ "BR_L2CAP_DISCONN_EVT",
+ "BR_KEYS_RSP_EVT",
+ "BR_API_SEC_GRANT_EVT",
+ "BR_TK_REQ_EVT",
+ "BR_AUTH_CMPL_EVT",
+ "BR_ENC_REQ_EVT",
+ "BR_BOND_REQ_EVT",
+ "BR_DISCARD_SEC_REQ_EVT",
+ "BR_OUT_OF_RANGE_EVT"
+};
+
+const char *smp_get_br_event_name(tSMP_BR_EVENT event);
+const char *smp_get_br_state_name(tSMP_BR_STATE state);
+
+#define SMP_BR_SM_IGNORE 0
+#define SMP_BR_NUM_ACTIONS 2
+#define SMP_BR_SME_NEXT_STATE 2
+#define SMP_BR_SM_NUM_COLS 3
+typedef const UINT8 (*tSMP_BR_SM_TBL)[SMP_BR_SM_NUM_COLS];
+
+enum
+{
+ SMP_SEND_PAIR_REQ,
+ SMP_BR_SEND_PAIR_RSP,
+ SMP_SEND_PAIR_FAIL,
+ SMP_SEND_ID_INFO,
+ SMP_BR_PROC_PAIR_CMD,
+ SMP_PROC_PAIR_FAIL,
+ SMP_PROC_ID_INFO,
+ SMP_PROC_ID_ADDR,
+ SMP_PROC_SRK_INFO,
+ SMP_BR_PROC_SEC_GRANT,
+ SMP_BR_PROC_SL_KEYS_RSP,
+ SMP_BR_KEY_DISTRIBUTION,
+ SMP_BR_PAIRING_COMPLETE,
+ SMP_SEND_APP_CBACK,
+ SMP_BR_CHECK_AUTH_REQ,
+ SMP_PAIR_TERMINATE,
+ SMP_IDLE_TERMINATE,
+ SMP_BR_SM_NO_ACTION
+};
+
+static const tSMP_ACT smp_br_sm_action[] =
+{
+ smp_send_pair_req,
+ smp_br_send_pair_response,
+ smp_send_pair_fail,
+ smp_send_id_info,
+ smp_br_process_pairing_command,
+ smp_proc_pair_fail,
+ smp_proc_id_info,
+ smp_proc_id_addr,
+ smp_proc_srk_info,
+ smp_br_process_security_grant,
+ smp_br_process_slave_keys_response,
+ smp_br_select_next_key,
+ smp_br_pairing_complete,
+ smp_send_app_cback,
+ smp_br_check_authorization_request,
+ smp_pair_terminate,
+ smp_idle_terminate
+};
+
+static const UINT8 smp_br_all_table[][SMP_BR_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* BR_PAIRING_FAILED */ {SMP_PROC_PAIR_FAIL, SMP_BR_PAIRING_COMPLETE, SMP_BR_STATE_IDLE},
+/* BR_AUTH_CMPL */ {SMP_SEND_PAIR_FAIL, SMP_BR_PAIRING_COMPLETE, SMP_BR_STATE_IDLE},
+/* BR_L2CAP_DISCONN */ {SMP_PAIR_TERMINATE, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_IDLE}
+};
+
+/************ SMP Master FSM State/Event Indirection Table **************/
+static const UINT8 smp_br_master_entry_map[][SMP_BR_STATE_MAX] =
+{
+/* br_state name: Idle WaitApp Pair Bond
+ Rsp ReqRsp Pend */
+/* BR_PAIRING_REQ */ { 0, 0, 0, 0 },
+/* BR_PAIRING_RSP */ { 0, 0, 1, 0 },
+/* BR_CONFIRM */ { 0, 0, 0, 0 },
+/* BR_RAND */ { 0, 0, 0, 0 },
+/* BR_PAIRING_FAILED */ { 0, 0x81, 0x81, 0 },
+/* BR_ENCRPTION_INFO */ { 0, 0, 0, 0 },
+/* BR_MASTER_ID */ { 0, 0, 0, 0 },
+/* BR_ID_INFO */ { 0, 0, 0, 1 },
+/* BR_ID_ADDR */ { 0, 0, 0, 2 },
+/* BR_SIGN_INFO */ { 0, 0, 0, 3 },
+/* BR_SECURITY_REQ */ { 0, 0, 0, 0 },
+/* BR_PAIR_PUBLIC_KEY_EVT */ { 0, 0, 0, 0 },
+/* BR_PAIR_DHKEY_CHCK_EVT */ { 0, 0, 0, 0 },
+/* BR_PAIR_KEYPR_NOTIF_EVT */ { 0, 0, 0, 0 },
+/* BR_KEY_READY */ { 0, 0, 0, 0 },
+/* BR_ENCRYPTED */ { 0, 0, 0, 0 },
+/* BR_L2CAP_CONN */ { 1, 0, 0, 0 },
+/* BR_L2CAP_DISCONN */ { 2, 0x83, 0x83, 0x83 },
+/* BR_KEYS_RSP */ { 0, 1, 0, 0 },
+/* BR_API_SEC_GRANT */ { 0, 0, 0, 0 },
+/* BR_TK_REQ */ { 0, 0, 0, 0 },
+/* BR_AUTH_CMPL */ { 0, 0x82, 0x82, 0x82 },
+/* BR_ENC_REQ */ { 0, 0, 0, 0 },
+/* BR_BOND_REQ */ { 0, 0, 2, 0 },
+/* BR_DISCARD_SEC_REQ */ { 0, 0, 0, 0 }
+};
+
+static const UINT8 smp_br_master_idle_table[][SMP_BR_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* BR_L2CAP_CONN */ {SMP_SEND_APP_CBACK, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_WAIT_APP_RSP},
+/* BR_L2CAP_DISCONN */ {SMP_IDLE_TERMINATE, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_IDLE}
+};
+
+static const UINT8 smp_br_master_wait_appln_response_table[][SMP_BR_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* BR_KEYS_RSP */{SMP_SEND_PAIR_REQ, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_PAIR_REQ_RSP}
+};
+
+static const UINT8 smp_br_master_pair_request_response_table [][SMP_BR_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* BR_PAIRING_RSP */ {SMP_BR_PROC_PAIR_CMD, SMP_BR_CHECK_AUTH_REQ, SMP_BR_STATE_PAIR_REQ_RSP},
+/* BR_BOND_REQ */ {SMP_BR_SM_NO_ACTION, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
+};
+
+static const UINT8 smp_br_master_bond_pending_table[][SMP_BR_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* BR_ID_INFO */{SMP_PROC_ID_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
+/* BR_ID_ADDR */{SMP_PROC_ID_ADDR, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
+/* BR_SIGN_INFO */{SMP_PROC_SRK_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
+};
+
+static const UINT8 smp_br_slave_entry_map[][SMP_BR_STATE_MAX] =
+{
+/* br_state name: Idle WaitApp Pair Bond
+ Rsp ReqRsp Pend */
+/* BR_PAIRING_REQ */ { 1, 0, 0, 0 },
+/* BR_PAIRING_RSP */ { 0, 0, 0, 0 },
+/* BR_CONFIRM */ { 0, 0, 0, 0 },
+/* BR_RAND */ { 0, 0, 0, 0 },
+/* BR_PAIRING_FAILED */ { 0, 0x81, 0x81, 0x81 },
+/* BR_ENCRPTION_INFO */ { 0, 0, 0, 0 },
+/* BR_MASTER_ID */ { 0, 0, 0, 0 },
+/* BR_ID_INFO */ { 0, 0, 0, 1 },
+/* BR_ID_ADDR */ { 0, 0, 0, 2 },
+/* BR_SIGN_INFO */ { 0, 0, 0, 3 },
+/* BR_SECURITY_REQ */ { 0, 0, 0, 0 },
+/* BR_PAIR_PUBLIC_KEY_EVT */ { 0, 0, 0, 0 },
+/* BR_PAIR_DHKEY_CHCK_EVT */ { 0, 0, 0, 0 },
+/* BR_PAIR_KEYPR_NOTIF_EVT */ { 0, 0, 0, 0 },
+/* BR_KEY_READY */ { 0, 0, 0, 0 },
+/* BR_ENCRYPTED */ { 0, 0, 0, 0 },
+/* BR_L2CAP_CONN */ { 0, 0, 0, 0 },
+/* BR_L2CAP_DISCONN */ { 0, 0x83, 0x83, 0x83 },
+/* BR_KEYS_RSP */ { 0, 2, 0, 0 },
+/* BR_API_SEC_GRANT */ { 0, 1, 0, 0 },
+/* BR_TK_REQ */ { 0, 0, 0, 0 },
+/* BR_AUTH_CMPL */ { 0, 0x82, 0x82, 0x82 },
+/* BR_ENC_REQ */ { 0, 0, 0, 0 },
+/* BR_BOND_REQ */ { 0, 3, 0, 0 },
+/* BR_DISCARD_SEC_REQ */ { 0, 0, 0, 0 }
+};
+
+static const UINT8 smp_br_slave_idle_table[][SMP_BR_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* BR_PAIRING_REQ */ {SMP_BR_PROC_PAIR_CMD, SMP_SEND_APP_CBACK, SMP_BR_STATE_WAIT_APP_RSP}
+};
+
+static const UINT8 smp_br_slave_wait_appln_response_table [][SMP_BR_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* BR_API_SEC_GRANT */ {SMP_BR_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_BR_STATE_WAIT_APP_RSP},
+/* BR_KEYS_RSP */{SMP_BR_PROC_SL_KEYS_RSP, SMP_BR_CHECK_AUTH_REQ,SMP_BR_STATE_WAIT_APP_RSP},
+/* BR_BOND_REQ */ {SMP_BR_KEY_DISTRIBUTION, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
+};
+
+static const UINT8 smp_br_slave_bond_pending_table[][SMP_BR_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* BR_ID_INFO */ {SMP_PROC_ID_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
+/* BR_ID_ADDR */ {SMP_PROC_ID_ADDR, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
+/* BR_SIGN_INFO */ {SMP_PROC_SRK_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
+};
+
+static const tSMP_BR_SM_TBL smp_br_state_table[][2] =
+{
+ /* SMP_BR_STATE_IDLE */
+ {smp_br_master_idle_table, smp_br_slave_idle_table},
+
+ /* SMP_BR_STATE_WAIT_APP_RSP */
+ {smp_br_master_wait_appln_response_table, smp_br_slave_wait_appln_response_table},
+
+ /* SMP_BR_STATE_PAIR_REQ_RSP */
+ {smp_br_master_pair_request_response_table, NULL},
+
+ /* SMP_BR_STATE_BOND_PENDING */
+ {smp_br_master_bond_pending_table, smp_br_slave_bond_pending_table},
+};
+
+typedef const UINT8 (*tSMP_BR_ENTRY_TBL)[SMP_BR_STATE_MAX];
+
+static const tSMP_BR_ENTRY_TBL smp_br_entry_table[] =
+{
+ smp_br_master_entry_map,
+ smp_br_slave_entry_map
+};
+
+#define SMP_BR_ALL_TABLE_MASK 0x80
+
+/*******************************************************************************
+** Function smp_set_br_state
+** Returns None
+*******************************************************************************/
+void smp_set_br_state(tSMP_BR_STATE br_state)
+{
+ if (br_state < SMP_BR_STATE_MAX)
+ {
+ SMP_TRACE_DEBUG( "BR_State change: %s(%d) ==> %s(%d)",
+ smp_get_br_state_name(smp_cb.br_state), smp_cb.br_state,
+ smp_get_br_state_name(br_state), br_state );
+ smp_cb.br_state = br_state;
+ }
+ else
+ {
+ SMP_TRACE_DEBUG("%s invalid br_state =%d", __FUNCTION__,br_state );
+ }
+}
+
+/*******************************************************************************
+** Function smp_get_br_state
+** Returns The smp_br state
+*******************************************************************************/
+tSMP_BR_STATE smp_get_br_state(void)
+{
+ return smp_cb.br_state;
+}
+
+/*******************************************************************************
+** Function smp_get_br_state_name
+** Returns The smp_br state name.
+*******************************************************************************/
+const char *smp_get_br_state_name(tSMP_BR_STATE br_state)
+{
+ const char *p_str = smp_br_state_name[SMP_BR_STATE_MAX];
+
+ if (br_state < SMP_BR_STATE_MAX)
+ p_str = smp_br_state_name[br_state];
+
+ return p_str;
+}
+/*******************************************************************************
+** Function smp_get_br_event_name
+** Returns The smp_br event name.
+*******************************************************************************/
+const char * smp_get_br_event_name(tSMP_BR_EVENT event)
+{
+ const char * p_str = smp_br_event_name[SMP_BR_MAX_EVT - 1];
+
+ if (event < SMP_BR_MAX_EVT)
+ {
+ p_str = smp_br_event_name[event- 1];
+ }
+ return p_str;
+}
+
+/*******************************************************************************
+**
+** Function smp_br_state_machine_event
+**
+** Description Handle events to the state machine. It looks up the entry
+** in the smp_br_entry_table array.
+** If it is a valid entry, it gets the state table.Set the next state,
+** if not NULL state. Execute the action function according to the
+** state table. If the state returned by action function is not NULL
+** state, adjust the new state to the returned state.
+**
+** Returns void.
+**
+*******************************************************************************/
+void smp_br_state_machine_event(tSMP_CB *p_cb, tSMP_BR_EVENT event, void *p_data)
+{
+ tSMP_BR_STATE curr_state = p_cb->br_state;
+ tSMP_BR_SM_TBL state_table;
+ UINT8 action, entry;
+ tSMP_BR_ENTRY_TBL entry_table = smp_br_entry_table[p_cb->role];
+
+ SMP_TRACE_EVENT("main %s", __func__);
+ if (curr_state >= SMP_BR_STATE_MAX)
+ {
+ SMP_TRACE_DEBUG( "Invalid br_state: %d", curr_state) ;
+ return;
+ }
+
+ SMP_TRACE_DEBUG( "SMP Role: %s State: [%s (%d)], Event: [%s (%d)]",
+ (p_cb->role == HCI_ROLE_SLAVE) ? "Slave" : "Master",
+ smp_get_br_state_name( p_cb->br_state),
+ p_cb->br_state, smp_get_br_event_name(event), event) ;
+
+ /* look up the state table for the current state */
+ /* lookup entry / w event & curr_state */
+ /* If entry is ignore, return.
+ * Otherwise, get state table (according to curr_state or all_state) */
+ if ((event <= SMP_BR_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state])
+ != SMP_BR_SM_IGNORE ))
+ {
+ if (entry & SMP_BR_ALL_TABLE_MASK)
+ {
+ entry &= ~SMP_BR_ALL_TABLE_MASK;
+ state_table = smp_br_all_table;
+ }
+ else
+ {
+ state_table = smp_br_state_table[curr_state][p_cb->role];
+ }
+ }
+ else
+ {
+ SMP_TRACE_DEBUG( "Ignore event [%s (%d)] in state [%s (%d)]",
+ smp_get_br_event_name(event), event,
+ smp_get_br_state_name(curr_state), curr_state);
+ return;
+ }
+
+ /* Get possible next state from state table. */
+
+ smp_set_br_state(state_table[entry - 1][SMP_BR_SME_NEXT_STATE]);
+
+ /* If action is not ignore, clear param, exec action and get next state.
+ * The action function may set the Param for cback.
+ * Depending on param, call cback or free buffer. */
+ /* execute action functions */
+ for (UINT8 i = 0; i < SMP_BR_NUM_ACTIONS; i++)
+ {
+ if ((action = state_table[entry - 1][i]) != SMP_BR_SM_NO_ACTION)
+ {
+ (*smp_br_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+ SMP_TRACE_DEBUG( "result state = %s", smp_get_br_state_name( p_cb->br_state ) ) ;
+}
+
+
void print128(BT_OCTET16 x, const UINT8 *key_name)
{
-#if SMP_DEBUG == TRUE
+#if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
UINT8 *p = (UINT8 *)x;
UINT8 i;
}
/*******************************************************************************
**
-** Function AES_CMAC
+** Function aes_cipher_msg_auth_code
**
** Description This is the AES-CMAC Generation Function with tlen implemented.
**
** tlen - lenth of mac desired
** p_signature - data pointer to where signed data to be stored, tlen long.
**
-** Returns void
+** Returns FALSE if out of resources, TRUE in other cases.
**
*******************************************************************************/
-BOOLEAN AES_CMAC ( BT_OCTET16 key, UINT8 *input, UINT16 length,
- UINT16 tlen, UINT8 *p_signature)
+BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
+ UINT16 tlen, UINT8 *p_signature)
{
UINT16 len, diff;
UINT16 n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN; /* n is number of rounds */
BOOLEAN ret = FALSE;
- SMP_TRACE_EVENT ("AES_CMAC ");
+ SMP_TRACE_EVENT ("%s", __func__);
if (n == 0) n = 1;
len = n * BT_OCTET16_LEN;
SMP_TRACE_WARNING("\n Example 1: len = %d\n", len);
- AES_CMAC(key, M, len, 128, test_cmac_cback, 0);
+ aes_cipher_msg_auth_code(key, M, len, 128, test_cmac_cback, 0);
}
#endif
* This file contains internally used SMP definitions
*
******************************************************************************/
-
#ifndef SMP_INT_H
#define SMP_INT_H
#include "btu.h"
+#include "btm_ble_api.h"
+#include "btm_api.h"
#include "smp_api.h"
-#define SMP_MODEL_ENC_ONLY 0
-#define SMP_MODEL_PASSKEY 1
-#define SMP_MODEL_OOB 2
-#define SMP_MODEL_KEY_NOTIF 3
-#define SMP_MODEL_MAX 4
+#define SMP_MODEL_ENCRYPTION_ONLY 0 /* Legacy mode, Just Works model */
+#define SMP_MODEL_PASSKEY 1 /* Legacy mode, Passkey Entry model, this side inputs the key */
+#define SMP_MODEL_OOB 2 /* Legacy mode, OOB model */
+#define SMP_MODEL_KEY_NOTIF 3 /* Legacy mode, Passkey Entry model, this side displays the key */
+#define SMP_MODEL_SEC_CONN_JUSTWORKS 4 /* Secure Connections mode, Just Works model */
+#define SMP_MODEL_SEC_CONN_NUM_COMP 5 /* Secure Connections mode, Numeric Comparison model */
+#define SMP_MODEL_SEC_CONN_PASSKEY_ENT 6 /* Secure Connections mode, Passkey Entry model, */
+ /* this side inputs the key */
+#define SMP_MODEL_SEC_CONN_PASSKEY_DISP 7 /* Secure Connections mode, Passkey Entry model, */
+ /* this side displays the key */
+#define SMP_MODEL_SEC_CONN_OOB 8 /* Secure Connections mode, OOB model */
+#define SMP_MODEL_OUT_OF_RANGE 9
typedef UINT8 tSMP_ASSO_MODEL;
#define SMP_MAX_CONN 2
#endif
-#define SMP_WAIT_FOR_RSP_TOUT 30
-#define SMP_WAIT_FOR_REL_DELAY_TOUT 5
-/* SMP L2CAP command code */
-#define SMP_OPCODE_PAIRING_REQ 0x01
-#define SMP_OPCODE_PAIRING_RSP 0x02
-#define SMP_OPCODE_CONFIRM 0x03
+#define SMP_WAIT_FOR_RSP_TOUT 30
+
#define SMP_OPCODE_INIT 0x04
-#define SMP_OPCODE_PAIRING_FAILED 0x05
-#define SMP_OPCODE_ENCRYPT_INFO 0x06
-#define SMP_OPCODE_MASTER_ID 0x07
-#define SMP_OPCODE_IDENTITY_INFO 0x08
-#define SMP_OPCODE_ID_ADDR 0x09
-#define SMP_OPCODE_SIGN_INFO 0x0A
-#define SMP_OPCODE_SEC_REQ 0x0B
-#define SMP_OPCODE_MAX (SMP_OPCODE_SEC_REQ + 1)
/* SMP events */
#define SMP_PAIRING_REQ_EVT SMP_OPCODE_PAIRING_REQ
#define SMP_PAIRING_RSP_EVT SMP_OPCODE_PAIRING_RSP
#define SMP_CONFIRM_EVT SMP_OPCODE_CONFIRM
-#define SMP_RAND_EVT SMP_OPCODE_INIT
+#define SMP_RAND_EVT SMP_OPCODE_RAND
#define SMP_PAIRING_FAILED_EVT SMP_OPCODE_PAIRING_FAILED
#define SMP_ENCRPTION_INFO_EVT SMP_OPCODE_ENCRYPT_INFO
#define SMP_MASTER_ID_EVT SMP_OPCODE_MASTER_ID
#define SMP_SIGN_INFO_EVT SMP_OPCODE_SIGN_INFO
#define SMP_SECURITY_REQ_EVT SMP_OPCODE_SEC_REQ
-#define SMP_SELF_DEF_EVT SMP_SECURITY_REQ_EVT
-#define SMP_KEY_READY_EVT (SMP_SELF_DEF_EVT + 1)
-#define SMP_ENCRYPTED_EVT (SMP_SELF_DEF_EVT + 2)
-#define SMP_L2CAP_CONN_EVT (SMP_SELF_DEF_EVT + 3)
-#define SMP_L2CAP_DISCONN_EVT (SMP_SELF_DEF_EVT + 4)
-#define SMP_IO_RSP_EVT (SMP_SELF_DEF_EVT + 5)
-#define SMP_API_SEC_GRANT_EVT (SMP_SELF_DEF_EVT + 6)
-#define SMP_TK_REQ_EVT (SMP_SELF_DEF_EVT + 7)
-#define SMP_AUTH_CMPL_EVT (SMP_SELF_DEF_EVT + 8)
-#define SMP_ENC_REQ_EVT (SMP_SELF_DEF_EVT + 9)
-#define SMP_BOND_REQ_EVT (SMP_SELF_DEF_EVT + 10)
-#define SMP_DISCARD_SEC_REQ_EVT (SMP_SELF_DEF_EVT + 11)
-#define SMP_RELEASE_DELAY_EVT (SMP_SELF_DEF_EVT + 12)
-#define SMP_RELEASE_DELAY_TOUT_EVT (SMP_SELF_DEF_EVT + 13)
+#define SMP_PAIR_PUBLIC_KEY_EVT SMP_OPCODE_PAIR_PUBLIC_KEY
+#define SMP_PAIR_KEYPRESS_NOTIFICATION_EVT SMP_OPCODE_PAIR_KEYPR_NOTIF
+
+#define SMP_PAIR_COMMITM_EVT SMP_OPCODE_PAIR_COMMITM
+
+#define SMP_SELF_DEF_EVT (SMP_PAIR_COMMITM_EVT + 1)
+#define SMP_KEY_READY_EVT (SMP_SELF_DEF_EVT)
+#define SMP_ENCRYPTED_EVT (SMP_SELF_DEF_EVT + 1)
+#define SMP_L2CAP_CONN_EVT (SMP_SELF_DEF_EVT + 2)
+#define SMP_L2CAP_DISCONN_EVT (SMP_SELF_DEF_EVT + 3)
+#define SMP_IO_RSP_EVT (SMP_SELF_DEF_EVT + 4)
+#define SMP_API_SEC_GRANT_EVT (SMP_SELF_DEF_EVT + 5)
+#define SMP_TK_REQ_EVT (SMP_SELF_DEF_EVT + 6)
+#define SMP_AUTH_CMPL_EVT (SMP_SELF_DEF_EVT + 7)
+#define SMP_ENC_REQ_EVT (SMP_SELF_DEF_EVT + 8)
+#define SMP_BOND_REQ_EVT (SMP_SELF_DEF_EVT + 9)
+#define SMP_DISCARD_SEC_REQ_EVT (SMP_SELF_DEF_EVT + 10)
+
+#define SMP_PAIR_DHKEY_CHCK_EVT SMP_OPCODE_PAIR_DHKEY_CHECK
+
+#define SMP_PUBL_KEY_EXCH_REQ_EVT (SMP_SELF_DEF_EVT + 11) /* request to start public */
+ /* key exchange */
+
+#define SMP_LOC_PUBL_KEY_CRTD_EVT (SMP_SELF_DEF_EVT + 12) /* local public key created */
+
+#define SMP_BOTH_PUBL_KEYS_RCVD_EVT (SMP_SELF_DEF_EVT + 13) /* both local and peer public */
+ /* keys are saved in cb */
+
+#define SMP_SC_DHKEY_CMPLT_EVT (SMP_SELF_DEF_EVT + 14) /* DHKey computation is completed,*/
+ /* time to start SC phase1 */
+
+#define SMP_HAVE_LOC_NONCE_EVT (SMP_SELF_DEF_EVT + 15) /* new local nonce is generated */
+ /*and saved in p_cb->rand */
+
+#define SMP_SC_PHASE1_CMPLT_EVT (SMP_SELF_DEF_EVT + 16) /* time to start SC phase2 */
+
+#define SMP_SC_CALC_NC_EVT (SMP_SELF_DEF_EVT + 17) /* request to calculate number */
+ /* for user check. Used only in the */
+ /* numeric compare protocol */
+
+/* Request to display the number for user check to the user.*/
+/* Used only in the numeric compare protocol */
+#define SMP_SC_DSPL_NC_EVT (SMP_SELF_DEF_EVT + 18)
+
+#define SMP_SC_NC_OK_EVT (SMP_SELF_DEF_EVT + 19) /* user confirms 'OK' numeric */
+ /*comparison request */
+
+/* both local and peer DHKey Checks are already present - it is used on slave to prevent race condition */
+#define SMP_SC_2_DHCK_CHKS_PRES_EVT (SMP_SELF_DEF_EVT + 20)
+
+/* same meaning as SMP_KEY_READY_EVT to separate between SC and legacy actions */
+#define SMP_SC_KEY_READY_EVT (SMP_SELF_DEF_EVT + 21)
+#define SMP_KEYPRESS_NOTIFICATION_EVENT (SMP_SELF_DEF_EVT + 22)
+
+#define SMP_SC_OOB_DATA_EVT (SMP_SELF_DEF_EVT + 23) /* SC OOB data from some */
+ /* repository is provided */
+
+#define SMP_CR_LOC_SC_OOB_DATA_EVT (SMP_SELF_DEF_EVT + 24)
+#define SMP_MAX_EVT SMP_CR_LOC_SC_OOB_DATA_EVT
+
typedef UINT8 tSMP_EVENT;
-#define SMP_MAX_EVT SMP_RELEASE_DELAY_TOUT_EVT + 1
-/* auumption it's only using the low 8 bits, if bigger than that, need to expand it to be 16 bits */
+/* Assumption it's only using the low 8 bits, if bigger than that, need to expand it to 16 bits */
#define SMP_SEC_KEY_MASK 0x00ff
/* SMP pairing state */
enum
{
- SMP_ST_IDLE,
- SMP_ST_WAIT_APP_RSP,
- SMP_ST_SEC_REQ_PENDING,
- SMP_ST_PAIR_REQ_RSP,
- SMP_ST_WAIT_CONFIRM,
- SMP_ST_CONFIRM,
- SMP_ST_RAND,
- SMP_ST_ENC_PENDING,
- SMP_ST_BOND_PENDING,
- SMP_ST_RELEASE_DELAY,
- SMP_ST_MAX
+ SMP_STATE_IDLE,
+ SMP_STATE_WAIT_APP_RSP,
+ SMP_STATE_SEC_REQ_PENDING,
+ SMP_STATE_PAIR_REQ_RSP,
+ SMP_STATE_WAIT_CONFIRM,
+ SMP_STATE_CONFIRM,
+ SMP_STATE_RAND,
+ SMP_STATE_PUBLIC_KEY_EXCH,
+ SMP_STATE_SEC_CONN_PHS1_START,
+ SMP_STATE_WAIT_COMMITMENT,
+ SMP_STATE_WAIT_NONCE,
+ SMP_STATE_SEC_CONN_PHS2_START,
+ SMP_STATE_WAIT_DHK_CHECK,
+ SMP_STATE_DHK_CHECK,
+ SMP_STATE_ENCRYPTION_PENDING,
+ SMP_STATE_BOND_PENDING,
+ SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA,
+ SMP_STATE_MAX
};
typedef UINT8 tSMP_STATE;
+/* SMP over BR/EDR events */
+#define SMP_BR_PAIRING_REQ_EVT SMP_OPCODE_PAIRING_REQ
+#define SMP_BR_PAIRING_RSP_EVT SMP_OPCODE_PAIRING_RSP
+#define SMP_BR_CONFIRM_EVT SMP_OPCODE_CONFIRM /* not expected over BR/EDR */
+#define SMP_BR_RAND_EVT SMP_OPCODE_RAND /* not expected over BR/EDR */
+#define SMP_BR_PAIRING_FAILED_EVT SMP_OPCODE_PAIRING_FAILED
+#define SMP_BR_ENCRPTION_INFO_EVT SMP_OPCODE_ENCRYPT_INFO /* not expected over BR/EDR */
+#define SMP_BR_MASTER_ID_EVT SMP_OPCODE_MASTER_ID /* not expected over BR/EDR */
+#define SMP_BR_ID_INFO_EVT SMP_OPCODE_IDENTITY_INFO
+#define SMP_BR_ID_ADDR_EVT SMP_OPCODE_ID_ADDR
+#define SMP_BR_SIGN_INFO_EVT SMP_OPCODE_SIGN_INFO
+#define SMP_BR_SECURITY_REQ_EVT SMP_OPCODE_SEC_REQ /* not expected over BR/EDR */
+#define SMP_BR_PAIR_PUBLIC_KEY_EVT SMP_OPCODE_PAIR_PUBLIC_KEY /* not expected over BR/EDR */
+#define SMP_BR_PAIR_DHKEY_CHCK_EVT SMP_OPCODE_PAIR_DHKEY_CHECK /* not expected over BR/EDR */
+#define SMP_BR_PAIR_KEYPR_NOTIF_EVT SMP_OPCODE_PAIR_KEYPR_NOTIF /* not expected over BR/EDR */
+#define SMP_BR_SELF_DEF_EVT SMP_BR_PAIR_KEYPR_NOTIF_EVT
+#define SMP_BR_KEY_READY_EVT (SMP_BR_SELF_DEF_EVT + 1)
+#define SMP_BR_ENCRYPTED_EVT (SMP_BR_SELF_DEF_EVT + 2)
+#define SMP_BR_L2CAP_CONN_EVT (SMP_BR_SELF_DEF_EVT + 3)
+#define SMP_BR_L2CAP_DISCONN_EVT (SMP_BR_SELF_DEF_EVT + 4)
+#define SMP_BR_KEYS_RSP_EVT (SMP_BR_SELF_DEF_EVT + 5)
+#define SMP_BR_API_SEC_GRANT_EVT (SMP_BR_SELF_DEF_EVT + 6)
+#define SMP_BR_TK_REQ_EVT (SMP_BR_SELF_DEF_EVT + 7)
+#define SMP_BR_AUTH_CMPL_EVT (SMP_BR_SELF_DEF_EVT + 8)
+#define SMP_BR_ENC_REQ_EVT (SMP_BR_SELF_DEF_EVT + 9)
+#define SMP_BR_BOND_REQ_EVT (SMP_BR_SELF_DEF_EVT + 10)
+#define SMP_BR_DISCARD_SEC_REQ_EVT (SMP_BR_SELF_DEF_EVT + 11)
+#define SMP_BR_MAX_EVT (SMP_BR_SELF_DEF_EVT + 12)
+typedef UINT8 tSMP_BR_EVENT;
+
+/* SMP over BR/EDR pairing states */
+enum
+{
+ SMP_BR_STATE_IDLE = SMP_STATE_IDLE,
+ SMP_BR_STATE_WAIT_APP_RSP,
+ SMP_BR_STATE_PAIR_REQ_RSP,
+ SMP_BR_STATE_BOND_PENDING,
+ SMP_BR_STATE_MAX
+};
+typedef UINT8 tSMP_BR_STATE;
+
/* random and encrption activity state */
enum
{
SMP_GEN_RAND_V,
SMP_GEN_TK,
SMP_GEN_SRAND_MRAND,
- SMP_GEN_SRAND_MRAND_CONT
+ SMP_GEN_SRAND_MRAND_CONT,
+ SMP_GENERATE_PRIVATE_KEY_0_7,
+ SMP_GENERATE_PRIVATE_KEY_8_15,
+ SMP_GENERATE_PRIVATE_KEY_16_23,
+ SMP_GENERATE_PRIVATE_KEY_24_31,
+ SMP_GEN_NONCE_0_7,
+ SMP_GEN_NONCE_8_15
};
enum
SMP_KEY_TYPE_TK,
SMP_KEY_TYPE_CFM,
SMP_KEY_TYPE_CMP,
+ SMP_KEY_TYPE_PEER_DHK_CHCK,
SMP_KEY_TYPE_STK,
SMP_KEY_TYPE_LTK
};
UINT8 *p_data; /* UINT8 type data pointer */
tSMP_KEY key;
UINT16 reason;
+ UINT32 passkey;
+ tSMP_OOB_DATA_TYPE req_oob_type;
}tSMP_INT_DATA;
/* internal status mask */
#define SMP_PAIR_FLAGS_PEER_STARTED_DD (1 << 1)
#define SMP_PAIR_FLAGS_CMD_CONFIRM (1 << SMP_OPCODE_CONFIRM) /* 1 << 3 */
#define SMP_PAIR_FLAG_ENC_AFTER_PAIR (1 << 4)
+#define SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK (1 << 5) /* used on slave to resolve race condition */
+#define SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY (1 << 6) /* used on slave to resolve race condition */
+#define SMP_PAIR_FLAG_HAVE_PEER_COMM (1 << 7) /* used to resolve race condition */
+#define SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY (1 << 8) /* used on slave to resolve race condition */
/* check if authentication requirement need MITM protection */
#define SMP_NO_MITM_REQUIRED(x) (((x) & SMP_AUTH_YN_BIT) == 0)
#define SMP_ENCRYT_DATA_SIZE 16
#define SMP_ECNCRPYT_STATUS HCI_SUCCESS
+typedef struct
+{
+ BD_ADDR bd_addr;
+ BT_HDR* p_copy;
+} tSMP_REQ_Q_ENTRY;
+
/* SMP control block */
typedef struct
{
tSMP_CALLBACK *p_callback;
TIMER_LIST_ENT rsp_timer_ent;
UINT8 trace_level;
-
BD_ADDR pairing_bda;
-
tSMP_STATE state;
+ BOOLEAN smp_over_br;
+ tSMP_BR_STATE br_state; /* if SMP over BR/ERD has priority over SMP */
UINT8 failure;
UINT8 status;
UINT8 role;
- UINT8 flags;
+ UINT16 flags;
UINT8 cb_evt;
-
tSMP_SEC_LEVEL sec_level;
BOOLEAN connect_initialized;
BT_OCTET16 confirm;
BT_OCTET16 rconfirm;
- BT_OCTET16 rrand;
- BT_OCTET16 rand;
+ BT_OCTET16 rrand; /* for SC this is peer nonce */
+ BT_OCTET16 rand; /* for SC this is local nonce */
+ BT_OCTET32 private_key;
+ BT_OCTET32 dhkey;
+ BT_OCTET16 commitment;
+ BT_OCTET16 remote_commitment;
+ BT_OCTET16 local_random; /* local randomizer - passkey or OOB randomizer */
+ BT_OCTET16 peer_random; /* peer randomizer - passkey or OOB randomizer */
+ BT_OCTET16 dhkey_check;
+ BT_OCTET16 remote_dhkey_check;
+ tSMP_PUBLIC_KEY loc_publ_key;
+ tSMP_PUBLIC_KEY peer_publ_key;
+ tSMP_OOB_DATA_TYPE req_oob_type;
+ tSMP_SC_OOB_DATA sc_oob_data;
tSMP_IO_CAP peer_io_caps;
- tSMP_IO_CAP loc_io_caps;
+ tSMP_IO_CAP local_io_capability;
tSMP_OOB_FLAG peer_oob_flag;
tSMP_OOB_FLAG loc_oob_flag;
tSMP_AUTH_REQ peer_auth_req;
tSMP_AUTH_REQ loc_auth_req;
+ BOOLEAN secure_connections_only_mode_required;/* TRUE if locally SM is required to operate */
+ /* either in Secure Connections mode or not at all */
+ tSMP_ASSO_MODEL selected_association_model;
+ BOOLEAN le_secure_connections_mode_is_used;
+ tBTM_SP_KEY_TYPE local_keypress_notification;
+ tBTM_SP_KEY_TYPE peer_keypress_notification;
+ UINT8 round; /* authentication stage 1 round for passkey association model */
+ UINT32 number_to_display;
+ BT_OCTET16 mac_key;
UINT8 peer_enc_size;
UINT8 loc_enc_size;
UINT8 peer_i_key;
UINT8 peer_r_key;
- UINT8 loc_i_key;
- UINT8 loc_r_key;
+ UINT8 local_i_key;
+ UINT8 local_r_key;
BT_OCTET16 tk;
BT_OCTET16 ltk;
BT_OCTET16 csrk; /* storage for local CSRK */
UINT16 ediv;
BT_OCTET8 enc_rand;
-
- UINT8 rand_enc_proc;
- BOOLEAN last_cmd;
+ UINT8 rand_enc_proc_state;
UINT8 addr_type;
BD_ADDR local_bda;
BOOLEAN is_pair_cancel;
BOOLEAN discard_sec_req;
UINT8 rcvd_cmd_code;
UINT8 rcvd_cmd_len;
-#if SMP_CONFORMANCE_TESTING == TRUE
- BOOLEAN enable_test_confirm_val;
- BT_OCTET16 test_confirm;
- BOOLEAN enable_test_rand_val;
- BT_OCTET16 test_rand;
- BOOLEAN enable_test_pair_fail;
- UINT8 pair_fail_status;
- BOOLEAN remove_fixed_channel_disable;
- BOOLEAN skip_test_compare_check;
-#endif
-
+ UINT16 total_tx_unacked;
+ BOOLEAN wait_for_authorization_complete;
}tSMP_CB;
/* Server Action functions are of this type */
/* Functions provided by att_main.c */
extern void smp_init (void);
-#if SMP_CONFORMANCE_TESTING == TRUE
-/* Used only for conformance testing */
-extern void smp_set_test_confirm_value (BOOLEAN enable, UINT8 *p_c_value);
-extern void smp_set_test_rand_value (BOOLEAN enable, UINT8 *p_c_value);
-extern void smp_set_test_pair_fail_status (BOOLEAN enable, UINT8 status);
-extern void smp_remove_fixed_channel_disable (BOOLEAN disable);
-extern void smp_skip_compare_check (BOOLEAN enable);
-#endif
/* smp main */
extern void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data);
extern void smp_proc_sec_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_set_fail_nc (BOOLEAN enable);
+extern void smp_set_fail_conf (BOOLEAN enable);
+extern void smp_set_passk_entry_fail(BOOLEAN enable);
+extern void smp_set_oob_fail(BOOLEAN enable);
+extern void smp_set_peer_sc_notif(BOOLEAN enable);
+extern void smp_aes_cmac_rfc4493_chk (UINT8 *key, UINT8 *msg, UINT8 msg_len,
+ UINT8 mac_len, UINT8 *mac);
+extern void smp_f4_calc_chk (UINT8 *U, UINT8 *V, UINT8 *X, UINT8 *Z, UINT8 *mac);
+extern void smp_g2_calc_chk (UINT8 *U, UINT8 *V, UINT8 *X, UINT8 *Y);
+extern void smp_h6_calc_chk (UINT8 *key, UINT8 *key_id, UINT8 *mac);
+extern void smp_f5_key_calc_chk (UINT8 *w, UINT8 *mac);
+extern void smp_f5_mackey_or_ltk_calc_chk(UINT8 *t, UINT8 *counter,
+ UINT8 *key_id, UINT8 *n1,
+ UINT8 *n2, UINT8 *a1, UINT8 *a2,
+ UINT8 *length, UINT8 *mac);
+extern void smp_f5_calc_chk (UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
+ UINT8 *mac_key, UINT8 *ltk);
+extern void smp_f6_calc_chk (UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r,
+ UINT8 *iocap, UINT8 *a1, UINT8 *a2, UINT8 *mac);
+/* smp_main */
+extern void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data);
+extern tSMP_STATE smp_get_state(void);
+extern void smp_set_state(tSMP_STATE state);
+
+/* smp_br_main */
+extern void smp_br_state_machine_event(tSMP_CB *p_cb, tSMP_BR_EVENT event, void *p_data);
+extern tSMP_BR_STATE smp_get_br_state(void);
+extern void smp_set_br_state(tSMP_BR_STATE state);
+
+
+/* smp_act.c */
extern void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_send_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_send_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_send_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_sec_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_pair_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_proc_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_proc_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_enc_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_release_delay(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_release_delay_tout(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_decide_asso_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_decide_association_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_io_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_delay_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_both_have_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_start_secure_connection_phase1(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_pairing_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_match_dhkey_checks(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_move_to_secure_connections_phase2(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_phase_2_dhkey_checks_are_present(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_wait_for_both_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_secure_connection_long_term_key(void);
+extern void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_process_security_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_process_slave_keys_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_send_pair_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_check_authorization_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_select_next_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_process_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_key_distribution_by_transport(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_pairing_complete(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
/* smp_l2c */
extern void smp_l2cap_if_init (void);
+extern void smp_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf);
-/* smp utility */
+/* smp_util.c */
extern BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
extern void smp_cb_cleanup(tSMP_CB *p_cb);
extern void smp_reset_control_value(tSMP_CB *p_cb);
extern BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
UINT8 *plain_text, UINT8 pt_len,
tSMP_ENC *p_out);
-/* smp key */
-extern void smp_generate_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern BOOLEAN smp_command_has_invalid_parameters(tSMP_CB *p_cb);
+extern void smp_reject_unexpected_pairing_command(BD_ADDR bd_addr);
+extern tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB *p_cb);
+extern void smp_reverse_array(UINT8 *arr, UINT8 len);
+extern UINT8 smp_calculate_random_input(UINT8 *random, UINT8 round);
+extern void smp_collect_local_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb);
+extern void smp_collect_peer_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb);
+extern void smp_collect_local_ble_address(UINT8 *le_addr, tSMP_CB *p_cb);
+extern void smp_collect_peer_ble_address(UINT8 *le_addr, tSMP_CB *p_cb);
+extern BOOLEAN smp_check_commitment(tSMP_CB *p_cb);
+extern void smp_save_secure_connections_long_term_key(tSMP_CB *p_cb);
+extern BOOLEAN smp_calculate_f5_mackey_and_long_term_key(tSMP_CB *p_cb);
+extern void smp_remove_fixed_channel(tSMP_CB *p_cb);
+extern BOOLEAN smp_request_oob_data(tSMP_CB *p_cb);
+
+/* smp_keys.c */
+extern void smp_generate_srand_mrand_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_generate_compare (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_generate_stk (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_generate_ltk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_generate_passkey (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_genenrate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_generate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_create_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_use_oob_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_compute_dhkey(tSMP_CB *p_cb);
+extern void smp_calculate_local_commitment(tSMP_CB *p_cb);
+extern void smp_calculate_peer_commitment(tSMP_CB *p_cb, BT_OCTET16 output_buf);
+extern void smp_calculate_numeric_comparison_display_number(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_calculate_local_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_calculate_peer_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_start_nonce_generation(tSMP_CB *p_cb);
+extern BOOLEAN smp_calculate_link_key_from_long_term_key(tSMP_CB *p_cb);
+extern BOOLEAN smp_calculate_long_term_key_from_link_key(tSMP_CB *p_cb);
+extern void smp_calculate_f4(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 z, UINT8 *c);
+extern UINT32 smp_calculate_g2(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 *y);
+extern BOOLEAN smp_calculate_f5(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
+ UINT8 *mac_key, UINT8 *ltk);
+extern BOOLEAN smp_calculate_f5_mackey_or_long_term_key(UINT8 *t, UINT8 *counter,
+ UINT8 *key_id, UINT8 *n1, UINT8 *n2, UINT8 *a1,
+ UINT8 *a2, UINT8 *length, UINT8 *mac);
+extern BOOLEAN smp_calculate_f5_key(UINT8 *w, UINT8 *t);
+extern BOOLEAN smp_calculate_f6(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r, UINT8 *iocap,
+ UINT8 *a1, UINT8 *a2, UINT8 *f3);
+extern BOOLEAN smp_calculate_h6(UINT8 *w, UINT8 *keyid, UINT8 *h2);
+#if SMP_DEBUG == TRUE
+extern void smp_debug_print_nbyte_little_endian (UINT8 *p, const UINT8 *key_name,
+ UINT8 len);
+#endif
-/* smp main util */
-extern void smp_set_state(tSMP_STATE state);
-extern tSMP_STATE smp_get_state(void);
-extern void smp_reject_unexp_pair_req(BD_ADDR bd_addr);
+/* smp_cmac.c */
+extern BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
+ UINT16 tlen, UINT8 *p_signature);
+extern void print128(BT_OCTET16 x, const UINT8 *key_name);
#endif /* SMP_INT_H */
/******************************************************************************
*
- * Copyright (C) 2008-2012 Broadcom Corporation
+ * Copyright (C) 1999-2012 Broadcom Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/******************************************************************************
*
- * This file contains the implementation of the SMP utility functions used
- * by SMP.
+ * This file contains security manager protocol utility functions
*
******************************************************************************/
-
#include "bt_target.h"
-#include "bt_utils.h"
#if SMP_INCLUDED == TRUE
- #if SMP_DEBUG == TRUE
- #include <stdio.h>
- #endif
- #include <string.h>
-
- #include "btm_ble_api.h"
- #include "smp_int.h"
- #include "btm_int.h"
- #include "btm_ble_int.h"
- #include "hcimsgs.h"
- #include "aes.h"
- #ifndef SMP_MAX_ENC_REPEAT
- #define SMP_MAX_ENC_REPEAT 3
- #endif
+#if SMP_DEBUG == TRUE
+ #include <stdio.h>
+#endif
+#include <string.h>
+#include "bt_utils.h"
+#include "btm_ble_api.h"
+#include "smp_int.h"
+#include "btm_int.h"
+#include "btm_ble_int.h"
+#include "hcimsgs.h"
+#include "aes.h"
+#include "p_256_ecc_pp.h"
+#include "device/include/controller.h"
+
+#ifndef SMP_MAX_ENC_REPEAT
+ #define SMP_MAX_ENC_REPEAT 3
+#endif
static void smp_rand_back(tBTM_RAND_ENC *p);
-static void smp_genenrate_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+static void smp_generate_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+static void smp_generate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
static void smp_generate_y(tSMP_CB *p_cb, tSMP_INT_DATA *p);
static void smp_generate_rand_vector (tSMP_CB *p_cb, tSMP_INT_DATA *p);
static void smp_process_stk(tSMP_CB *p_cb, tSMP_ENC *p);
static void smp_process_confirm(tSMP_CB *p_cb, tSMP_ENC *p);
static void smp_process_compare(tSMP_CB *p_cb, tSMP_ENC *p);
static void smp_process_ediv(tSMP_CB *p_cb, tSMP_ENC *p);
+static BOOLEAN smp_calculate_legacy_short_term_key(tSMP_CB *p_cb, tSMP_ENC *output);
+static void smp_continue_private_key_creation(tSMP_CB *p_cb, tBTM_RAND_ENC *p);
+static void smp_process_private_key(tSMP_CB *p_cb);
+static void smp_finish_nonce_generation(tSMP_CB *p_cb);
+static void smp_process_new_nonce(tSMP_CB *p_cb);
static const tSMP_ACT smp_encrypt_action[] =
{
smp_generate_compare, /* SMP_GEN_COMPARE */
- smp_genenrate_confirm, /* SMP_GEN_CONFIRM*/
+ smp_generate_confirm, /* SMP_GEN_CONFIRM*/
smp_generate_stk, /* SMP_GEN_STK*/
- smp_genenrate_ltk_cont, /* SMP_GEN_LTK */
+ smp_generate_ltk_cont, /* SMP_GEN_LTK */
smp_generate_ltk, /* SMP_GEN_DIV_LTK */
smp_generate_rand_vector, /* SMP_GEN_RAND_V */
smp_generate_y, /* SMP_GEN_EDIV */
smp_generate_passkey, /* SMP_GEN_TK */
- smp_generate_confirm, /* SMP_GEN_SRAND_MRAND */
- smp_genenrate_rand_cont /* SMP_GEN_SRAND_MRAND_CONT */
+ smp_generate_srand_mrand_confirm, /* SMP_GEN_SRAND_MRAND */
+ smp_generate_rand_cont /* SMP_GEN_SRAND_MRAND_CONT */
};
+#define SMP_PASSKEY_MASK 0xfff00000
+
+void smp_debug_print_nbyte_little_endian(UINT8 *p, const UINT8 *key_name, UINT8 len)
+{
+#if SMP_DEBUG == TRUE
+ int ind, x;
+ int col_count = 32;
+ int row_count;
+ UINT8 p_buf[512];
+
+ SMP_TRACE_WARNING("%s(LSB ~ MSB):", key_name);
+ memset(p_buf, 0, sizeof(p_buf));
+ row_count = len % col_count ? len / col_count + 1: len / col_count;
- #define SMP_PASSKEY_MASK 0xfff00000
+ ind = 0;
+ for (int row = 0; row < row_count; row++)
+ {
+ for (int column = 0, x = 0; (ind < len) && (column < col_count); column++, ind++)
+ {
+ x += sprintf((char *)&p_buf[x], "%02x ", p[ind]);
+ }
+ SMP_TRACE_WARNING(" [%03d]: %s", row * col_count, p_buf);
+ }
+#endif
+}
- #if SMP_DEBUG == TRUE
-static void smp_debug_print_nbyte_little_endian (UINT8 *p, const UINT8 *key_name, UINT8 len)
+void smp_debug_print_nbyte_big_endian (UINT8 *p, const UINT8 *key_name, UINT8 len)
{
- int i, x = 0;
- UINT8 p_buf[100];
- memset(p_buf, 0, 100);
+#if SMP_DEBUG == TRUE
+ UINT8 p_buf[512];
+
+ SMP_TRACE_WARNING("%s(MSB ~ LSB):", key_name);
+ memset(p_buf, 0, sizeof(p_buf));
+ nrows = len % ncols ? len / ncols + 1: len / ncols;
- for (i = 0; i < len; i ++)
+ int ind = 0;
+ int ncols = 32; /* num entries in one line */
+ int nrows; /* num lines */
+ int x;
+
+ for (int row = 0; row < nrows; row++)
{
- x += sprintf ((char *)&p_buf[x], "%02x ", p[i]);
+ for (int col = 0, x = 0; (ind < len) && (col < ncols); col++, ind++)
+ {
+ x += sprintf ((char *)&p_buf[len-x-1], "%02x ", p[ind]);
+ }
+ SMP_TRACE_WARNING("[%03d]: %s", row * ncols, p_buf);
}
- SMP_TRACE_DEBUG("%s(LSB ~ MSB) = %s", key_name, p_buf);
+#endif
}
- #else
- #define smp_debug_print_nbyte_little_endian(p, key_name, len)
- #endif
/*******************************************************************************
**
** Function smp_encrypt_data
**
-** Description This function is called to generate passkey.
+** Description This function is called to encrypt data.
+** It uses AES-128 encryption algorithm.
+** Plain_text is encrypted using key, the result is at p_out.
**
** Returns void
**
UINT8 *plain_text, UINT8 pt_len,
tSMP_ENC *p_out)
{
- aes_context ctx;
- UINT8 *p_start = NULL;
- UINT8 *p = NULL;
- UINT8 *p_rev_data = NULL; /* input data in big endilan format */
- UINT8 *p_rev_key = NULL; /* input key in big endilan format */
- UINT8 *p_rev_output = NULL; /* encrypted output in big endilan format */
-
- SMP_TRACE_DEBUG ("smp_encrypt_data");
+ aes_context ctx;
+ UINT8 *p_start = NULL;
+ UINT8 *p = NULL;
+ UINT8 *p_rev_data = NULL; /* input data in big endilan format */
+ UINT8 *p_rev_key = NULL; /* input key in big endilan format */
+ UINT8 *p_rev_output = NULL; /* encrypted output in big endilan format */
+
+ SMP_TRACE_DEBUG ("%s", __func__);
if ( (p_out == NULL ) || (key_len != SMP_ENCRYT_KEY_SIZE) )
{
- BTM_TRACE_ERROR ("smp_encrypt_data Failed");
- return(FALSE);
+ SMP_TRACE_ERROR ("%s failed", __func__);
+ return FALSE;
}
if ((p_start = (UINT8 *)GKI_getbuf((SMP_ENCRYT_DATA_SIZE*4))) == NULL)
{
- BTM_TRACE_ERROR ("smp_encrypt_data Failed unable to allocate buffer");
- return(FALSE);
+ SMP_TRACE_ERROR ("%s failed unable to allocate buffer", __func__);
+ return FALSE;
}
if (pt_len > SMP_ENCRYT_DATA_SIZE)
p_rev_key = p; /* start at byte 32 */
REVERSE_ARRAY_TO_STREAM (p, key, SMP_ENCRYT_KEY_SIZE); /* byte 32 to byte 47 */
+#if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
smp_debug_print_nbyte_little_endian(key, (const UINT8 *)"Key", SMP_ENCRYT_KEY_SIZE);
smp_debug_print_nbyte_little_endian(p_start, (const UINT8 *)"Plain text", SMP_ENCRYT_DATA_SIZE);
+#endif
p_rev_output = p;
aes_set_key(p_rev_key, SMP_ENCRYT_KEY_SIZE, &ctx);
aes_encrypt(p_rev_data, p, &ctx); /* outputs in byte 48 to byte 63 */
p = p_out->param_buf;
REVERSE_ARRAY_TO_STREAM (p, p_rev_output, SMP_ENCRYT_DATA_SIZE);
+#if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
smp_debug_print_nbyte_little_endian(p_out->param_buf, (const UINT8 *)"Encrypted text", SMP_ENCRYT_KEY_SIZE);
+#endif
p_out->param_len = SMP_ENCRYT_KEY_SIZE;
p_out->status = HCI_SUCCESS;
GKI_freebuf(p_start);
- return(TRUE);
+ return TRUE;
}
-
/*******************************************************************************
**
** Function smp_generate_passkey
{
UNUSED(p_data);
- SMP_TRACE_DEBUG ("smp_generate_passkey");
- p_cb->rand_enc_proc = SMP_GEN_TK;
+ SMP_TRACE_DEBUG ("%s", __func__);
+ p_cb->rand_enc_proc_state = SMP_GEN_TK;
/* generate MRand or SRand */
if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
smp_rand_back(NULL);
}
+
/*******************************************************************************
**
** Function smp_proc_passkey
UINT32 passkey; /* 19655 test number; */
UINT8 *pp = p->param_buf;
- SMP_TRACE_DEBUG ("smp_proc_passkey ");
+ SMP_TRACE_DEBUG ("%s", __func__);
STREAM_TO_UINT32(passkey, pp);
passkey &= ~SMP_PASSKEY_MASK;
(*p_cb->p_callback)(SMP_PASSKEY_NOTIF_EVT, p_cb->pairing_bda, (tSMP_EVT_DATA *)&passkey);
}
- smp_sm_event(p_cb, SMP_KEY_READY_EVT, (tSMP_INT_DATA *)&key);
+ if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_DISP)
+ {
+ smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &passkey);
+ }
+ else
+ {
+ smp_sm_event(p_cb, SMP_KEY_READY_EVT, (tSMP_INT_DATA *)&key);
+ }
}
-
/*******************************************************************************
**
** Function smp_generate_stk
** Returns void
**
*******************************************************************************/
-void smp_generate_stk (tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_generate_stk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- BT_OCTET16 ptext;
- UINT8 *p = ptext;
- tSMP_ENC output;
- tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
UNUSED(p_data);
- SMP_TRACE_DEBUG ("smp_generate_stk ");
+ tSMP_ENC output;
+ tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
- memset(p, 0, BT_OCTET16_LEN);
- if (p_cb->role == HCI_ROLE_MASTER)
- {
- memcpy(p, p_cb->rand, BT_OCTET8_LEN);
- memcpy(&p[BT_OCTET8_LEN], p_cb->rrand, BT_OCTET8_LEN);
- }
- else
- {
- memcpy(p, p_cb->rrand, BT_OCTET8_LEN);
- memcpy(&p[BT_OCTET8_LEN], p_cb->rand, BT_OCTET8_LEN);
- }
+ SMP_TRACE_DEBUG ("%s", __func__);
- /* generate STK = Etk(rand|rrand)*/
- if (!SMP_Encrypt( p_cb->tk, BT_OCTET16_LEN, ptext, BT_OCTET16_LEN, &output))
+ if (p_cb->le_secure_connections_mode_is_used)
{
- SMP_TRACE_ERROR("smp_generate_stk failed");
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ SMP_TRACE_WARNING ("FOR LE SC LTK IS USED INSTEAD OF STK");
+ output.param_len = SMP_ENCRYT_KEY_SIZE;
+ output.status = HCI_SUCCESS;
+ output.opcode = HCI_BLE_ENCRYPT;
+ memcpy(output.param_buf, p_cb->ltk, SMP_ENCRYT_DATA_SIZE);
}
- else
+ else if (!smp_calculate_legacy_short_term_key(p_cb, &output))
{
- smp_process_stk(p_cb, &output);
+ SMP_TRACE_ERROR("%s failed", __func__);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ return;
}
+ smp_process_stk(p_cb, &output);
}
+
/*******************************************************************************
**
-** Function smp_generate_confirm
+** Function smp_generate_srand_mrand_confirm
**
** Description This function is called to start the second pairing phase by
-** start generating initializer random number.
+** start generating random number.
**
**
** Returns void
**
*******************************************************************************/
-void smp_generate_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_generate_srand_mrand_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UNUSED(p_data);
- SMP_TRACE_DEBUG ("smp_generate_confirm");
- p_cb->rand_enc_proc = SMP_GEN_SRAND_MRAND;
+ SMP_TRACE_DEBUG ("%s", __func__);
+ p_cb->rand_enc_proc_state = SMP_GEN_SRAND_MRAND;
/* generate MRand or SRand */
if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
smp_rand_back(NULL);
}
+
/*******************************************************************************
**
-** Function smp_genenrate_rand_cont
+** Function smp_generate_rand_cont
**
** Description This function is called to generate another 64 bits random for
** MRand or Srand.
** Returns void
**
*******************************************************************************/
-void smp_genenrate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_generate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UNUSED(p_data);
- SMP_TRACE_DEBUG ("smp_genenrate_rand_cont ");
- p_cb->rand_enc_proc = SMP_GEN_SRAND_MRAND_CONT;
+ SMP_TRACE_DEBUG ("%s", __func__);
+ p_cb->rand_enc_proc_state = SMP_GEN_SRAND_MRAND_CONT;
/* generate 64 MSB of MRand or SRand */
-
if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
smp_rand_back(NULL);
}
+
/*******************************************************************************
**
** Function smp_generate_ltk
**
-** Description This function is called to calculate LTK, starting with DIV
-** generation.
-**
+** Description This function is called:
+** - in legacy pairing - to calculate LTK, starting with DIV
+** generation;
+** - in LE Secure Connections pairing over LE transport - to process LTK
+** already generated to encrypt LE link;
+** - in LE Secure Connections pairing over BR/EDR transport - to start
+** BR/EDR Link Key processing.
**
** Returns void
**
*******************************************************************************/
void smp_generate_ltk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- BOOLEAN div_status;
UNUSED(p_data);
- SMP_TRACE_DEBUG ("smp_generate_ltk ");
+ BOOLEAN div_status;
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+ if (smp_get_br_state() == SMP_BR_STATE_BOND_PENDING)
+ {
+ smp_br_process_link_key(p_cb, NULL);
+ return;
+ }
+ else if (p_cb->le_secure_connections_mode_is_used)
+ {
+ smp_process_secure_connection_long_term_key();
+ return;
+ }
div_status = btm_get_local_div(p_cb->pairing_bda, &p_cb->div);
if (div_status)
{
- smp_genenrate_ltk_cont(p_cb, NULL);
+ smp_generate_ltk_cont(p_cb, NULL);
}
else
{
SMP_TRACE_DEBUG ("Generate DIV for LTK");
- p_cb->rand_enc_proc = SMP_GEN_DIV_LTK;
+ p_cb->rand_enc_proc_state = SMP_GEN_DIV_LTK;
/* generate MRand or SRand */
if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
smp_rand_back(NULL);
}
}
-
/*******************************************************************************
**
** Function smp_compute_csrk
*******************************************************************************/
void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
+ UNUSED(p_data);
+
BT_OCTET16 er;
UINT8 buffer[4]; /* for (r || DIV) r=1*/
UINT16 r=1;
UINT8 *p=buffer;
tSMP_ENC output;
tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
- UNUSED(p_data);
SMP_TRACE_DEBUG ("smp_compute_csrk div=%x", p_cb->div);
BTM_GetDeviceEncRoot(er);
if (!SMP_Encrypt(er, BT_OCTET16_LEN, buffer, 4, &output))
{
SMP_TRACE_ERROR("smp_generate_csrk failed");
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ if (p_cb->smp_over_br)
+ {
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+ }
+ else
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ }
}
else
{
**
** Function smp_generate_csrk
**
-** Description This function is called to calculate LTK, starting with DIV
+** Description This function is called to calculate CSRK, starting with DIV
** generation.
**
**
*******************************************************************************/
void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- BOOLEAN div_status;
UNUSED(p_data);
+ BOOLEAN div_status;
+
SMP_TRACE_DEBUG ("smp_generate_csrk");
div_status = btm_get_local_div(p_cb->pairing_bda, &p_cb->div);
else
{
SMP_TRACE_DEBUG ("Generate DIV for CSRK");
- p_cb->rand_enc_proc = SMP_GEN_DIV_CSRK;
+ p_cb->rand_enc_proc_state = SMP_GEN_DIV_CSRK;
if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
smp_rand_back(NULL);
}
}
-
/*******************************************************************************
** Function smp_concatenate_peer
** add pairing command sent from local device into p1.
{
UINT8 *p = *p_data;
- SMP_TRACE_DEBUG ("smp_concatenate_local ");
+ SMP_TRACE_DEBUG ("%s", __func__);
UINT8_TO_STREAM(p, op_code);
- UINT8_TO_STREAM(p, p_cb->loc_io_caps);
+ UINT8_TO_STREAM(p, p_cb->local_io_capability);
UINT8_TO_STREAM(p, p_cb->loc_oob_flag);
UINT8_TO_STREAM(p, p_cb->loc_auth_req);
UINT8_TO_STREAM(p, p_cb->loc_enc_size);
- UINT8_TO_STREAM(p, p_cb->loc_i_key);
- UINT8_TO_STREAM(p, p_cb->loc_r_key);
+ UINT8_TO_STREAM(p, p_cb->local_i_key);
+ UINT8_TO_STREAM(p, p_cb->local_r_key);
*p_data = p;
}
+
/*******************************************************************************
** Function smp_concatenate_peer
** add pairing command received from peer device into p1.
*p_data = p;
}
+
/*******************************************************************************
**
** Function smp_gen_p1_4_confirm
smp_debug_print_nbyte_little_endian ((UINT8 *)p1, (const UINT8 *)"P1", 16);
#endif
}
+
/*******************************************************************************
**
** Function smp_gen_p2_4_confirm
smp_debug_print_nbyte_little_endian(p2, (const UINT8 *)"p2", 16);
#endif
}
+
/*******************************************************************************
**
** Function smp_calculate_comfirm
*******************************************************************************/
void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda)
{
+ UNUSED(bda);
+
BT_OCTET16 p1;
tSMP_ENC output;
tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
- UNUSED(bda);
SMP_TRACE_DEBUG ("smp_calculate_comfirm ");
/* generate p1 = pres || preq || rat' || iat' */
smp_calculate_comfirm_cont(p_cb, &output);
}
}
+
/*******************************************************************************
**
** Function smp_calculate_comfirm_cont
}
else
{
- switch (p_cb->rand_enc_proc)
+ switch (p_cb->rand_enc_proc_state)
{
case SMP_GEN_CONFIRM:
smp_process_confirm(p_cb, &output);
}
}
}
+
/*******************************************************************************
**
-** Function smp_genenrate_confirm
+** Function smp_generate_confirm
**
** Description This function is called when a 48 bits random number is generated
** as SRand or MRand, continue to calculate Sconfirm or MConfirm.
** Returns void
**
*******************************************************************************/
-static void smp_genenrate_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+static void smp_generate_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UNUSED(p_data);
- SMP_TRACE_DEBUG ("smp_genenrate_confirm ");
- p_cb->rand_enc_proc = SMP_GEN_CONFIRM;
-
+ SMP_TRACE_DEBUG ("%s", __func__);
+ p_cb->rand_enc_proc_state = SMP_GEN_CONFIRM;
smp_debug_print_nbyte_little_endian ((UINT8 *)p_cb->rand, (const UINT8 *)"local rand", 16);
-
smp_calculate_comfirm(p_cb, p_cb->rand, p_cb->pairing_bda);
}
+
/*******************************************************************************
**
** Function smp_generate_compare
UNUSED(p_data);
SMP_TRACE_DEBUG ("smp_generate_compare ");
- p_cb->rand_enc_proc = SMP_GEN_COMPARE;
-
+ p_cb->rand_enc_proc_state = SMP_GEN_COMPARE;
smp_debug_print_nbyte_little_endian ((UINT8 *)p_cb->rrand, (const UINT8 *)"peer rand", 16);
-
smp_calculate_comfirm(p_cb, p_cb->rrand, p_cb->local_bda);
}
+
/*******************************************************************************
**
** Function smp_process_confirm
{
tSMP_KEY key;
- SMP_TRACE_DEBUG ("smp_process_confirm ");
-#if SMP_CONFORMANCE_TESTING == TRUE
- if (p_cb->enable_test_confirm_val)
- {
- BTM_TRACE_DEBUG ("Use confirm value from script");
- memcpy(p_cb->confirm, p_cb->test_confirm, BT_OCTET16_LEN);
- }
- else
- memcpy(p_cb->confirm, p->param_buf, BT_OCTET16_LEN);
-#else
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
memcpy(p_cb->confirm, p->param_buf, BT_OCTET16_LEN);
-#endif
-
#if (SMP_DEBUG == TRUE)
SMP_TRACE_DEBUG("Confirm Generated");
key.key_type = SMP_KEY_TYPE_CFM;
key.p_data = p->param_buf;
-
smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
}
+
/*******************************************************************************
**
** Function smp_process_compare
/*******************************************************************************
**
-** Function smp_genenrate_ltk_cont
+** Function smp_generate_ltk_cont
**
** Description This function is to calculate LTK = d1(ER, DIV, 0)= e(ER, DIV)
**
** Returns void
**
*******************************************************************************/
-static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+static void smp_generate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
+ UNUSED(p_data);
+
BT_OCTET16 er;
tSMP_ENC output;
tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
- UNUSED(p_data);
- SMP_TRACE_DEBUG ("smp_genenrate_ltk_cont ");
+ SMP_TRACE_DEBUG ("%s", __func__);
BTM_GetDeviceEncRoot(er);
/* LTK = d1(ER, DIV, 0)= e(ER, DIV)*/
if (!SMP_Encrypt(er, BT_OCTET16_LEN, (UINT8 *)&p_cb->div,
sizeof(UINT16), &output))
{
- SMP_TRACE_ERROR("smp_genenrate_ltk_cont failed");
+ SMP_TRACE_ERROR("%s failed", __func__);
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
}
else
memcpy((void *)p_cb->ltk, output.param_buf, BT_OCTET16_LEN);
smp_generate_rand_vector(p_cb, NULL);
}
-
}
/*******************************************************************************
*******************************************************************************/
static void smp_generate_y(tSMP_CB *p_cb, tSMP_INT_DATA *p)
{
+ UNUSED(p);
+
BT_OCTET16 dhk;
tSMP_ENC output;
tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
- UNUSED(p);
+
SMP_TRACE_DEBUG ("smp_generate_y ");
BTM_GetDeviceDHK(dhk);
smp_process_ediv(p_cb, &output);
}
}
+
/*******************************************************************************
**
** Function smp_generate_rand_vector
/* generate EDIV and rand now */
/* generate random vector */
SMP_TRACE_DEBUG ("smp_generate_rand_vector ");
- p_cb->rand_enc_proc = SMP_GEN_RAND_V;
+ p_cb->rand_enc_proc_state = SMP_GEN_RAND_V;
if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
smp_rand_back(NULL);
-
}
+
/*******************************************************************************
**
-** Function smp_genenrate_smp_process_edivltk_cont
+** Function smp_process_ediv
**
** Description This function is to calculate EDIV = Y xor DIV
**
/*******************************************************************************
**
-** Function smp_rand_back
+** Function smp_calculate_legacy_short_term_key
**
-** Description This function is to process the rand command finished,
-** process the random/encrypted number for further action.
+** Description The function calculates legacy STK.
+**
+** Returns FALSE if out of resources, TRUE in other cases.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_legacy_short_term_key(tSMP_CB *p_cb, tSMP_ENC *output)
+{
+ BT_OCTET16 ptext;
+ UINT8 *p = ptext;
+
+ SMP_TRACE_DEBUG ("%s", __func__);
+ memset(p, 0, BT_OCTET16_LEN);
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ memcpy(p, p_cb->rand, BT_OCTET8_LEN);
+ memcpy(&p[BT_OCTET8_LEN], p_cb->rrand, BT_OCTET8_LEN);
+ }
+ else
+ {
+ memcpy(p, p_cb->rrand, BT_OCTET8_LEN);
+ memcpy(&p[BT_OCTET8_LEN], p_cb->rand, BT_OCTET8_LEN);
+ }
+
+ BOOLEAN encrypted;
+ /* generate STK = Etk(rand|rrand)*/
+ encrypted = SMP_Encrypt( p_cb->tk, BT_OCTET16_LEN, ptext, BT_OCTET16_LEN, output);
+ if (!encrypted)
+ {
+ SMP_TRACE_ERROR("%s failed", __func__);
+ }
+ return encrypted;
+}
+
+/*******************************************************************************
+**
+** Function smp_create_private_key
+**
+** Description This function is called to create private key used to
+** calculate public key and DHKey.
+** The function starts private key creation requesting controller
+** to generate [0-7] octets of private key.
**
** Returns void
**
*******************************************************************************/
-static void smp_rand_back(tBTM_RAND_ENC *p)
+void smp_create_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- tSMP_CB *p_cb = &smp_cb;
- UINT8 *pp = p->param_buf;
- UINT8 failure = SMP_PAIR_FAIL_UNKNOWN;
- UINT8 state = p_cb->rand_enc_proc & ~0x80;
+ SMP_TRACE_DEBUG ("%s",__FUNCTION__);
+ p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_0_7;
+ if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+ smp_rand_back(NULL);
+}
- SMP_TRACE_DEBUG ("smp_rand_back state=0x%x", state);
- if (p && p->status == HCI_SUCCESS)
+/*******************************************************************************
+**
+** Function smp_use_oob_private_key
+**
+** Description This function is called
+** - to save the secret key used to calculate the public key used
+** in calculations of commitment sent OOB to a peer
+** - to use this secret key to recalculate the public key and
+** start the process of sending this public key to the peer
+** if secret/public keys have to be reused.
+** If the keys aren't supposed to be reused, continue from the
+** point from which request for OOB data was issued.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_use_oob_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG ("%s req_oob_type: %d, role: %d",
+ __func__, p_cb->req_oob_type, p_cb->role);
+
+ switch (p_cb->req_oob_type)
{
- switch (state)
- {
+ case SMP_OOB_BOTH:
+ case SMP_OOB_LOCAL:
+ SMP_TRACE_DEBUG("%s restore secret key", __func__)
+ memcpy(p_cb->private_key, p_cb->sc_oob_data.loc_oob_data.private_key_used, BT_OCTET32_LEN);
+ smp_process_private_key(p_cb);
+ break;
+ default:
+ SMP_TRACE_DEBUG("%s create secret key anew", __func__);
+ smp_set_state(SMP_STATE_PAIR_REQ_RSP);
+ smp_decide_association_model(p_cb, NULL);
+ break;
+ }
+}
- case SMP_GEN_SRAND_MRAND:
- memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
- smp_genenrate_rand_cont(p_cb, NULL);
- break;
+/*******************************************************************************
+**
+** Function smp_continue_private_key_creation
+**
+** Description This function is used to continue private key creation.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_continue_private_key_creation (tSMP_CB *p_cb, tBTM_RAND_ENC *p)
+{
+ UINT8 state = p_cb->rand_enc_proc_state & ~0x80;
+ SMP_TRACE_DEBUG ("%s state=0x%x", __func__, state);
- case SMP_GEN_SRAND_MRAND_CONT:
- memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
- smp_genenrate_confirm(p_cb, NULL);
- break;
+ switch (state)
+ {
+ case SMP_GENERATE_PRIVATE_KEY_0_7:
+ memcpy((void *)p_cb->private_key, p->param_buf, p->param_len);
+ p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_8_15;
+ if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+ smp_rand_back(NULL);
+ break;
+
+ case SMP_GENERATE_PRIVATE_KEY_8_15:
+ memcpy((void *)&p_cb->private_key[8], p->param_buf, p->param_len);
+ p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_16_23;
+ if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+ smp_rand_back(NULL);
+ break;
+
+ case SMP_GENERATE_PRIVATE_KEY_16_23:
+ memcpy((void *)&p_cb->private_key[16], p->param_buf, p->param_len);
+ p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_24_31;
+ if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+ smp_rand_back(NULL);
+ break;
+
+ case SMP_GENERATE_PRIVATE_KEY_24_31:
+ memcpy((void *)&p_cb->private_key[24], p->param_buf, p->param_len);
+ smp_process_private_key (p_cb);
+ break;
+
+ default:
+ break;
+ }
- case SMP_GEN_DIV_LTK:
- STREAM_TO_UINT16(p_cb->div, pp);
- smp_genenrate_ltk_cont(p_cb, NULL);
- break;
+ return;
+}
- case SMP_GEN_DIV_CSRK:
- STREAM_TO_UINT16(p_cb->div, pp);
- smp_compute_csrk(p_cb, NULL);
- break;
+/*******************************************************************************
+**
+** Function smp_process_private_key
+**
+** Description This function processes private key.
+** It calculates public key and notifies SM that private key /
+** public key pair is created.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_process_private_key(tSMP_CB *p_cb)
+{
+ Point public_key;
+ BT_OCTET32 private_key;
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+ memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN);
+ ECC_PointMult(&public_key, &(curve_p256.G), (DWORD*) private_key, KEY_LENGTH_DWORDS_P256);
+ memcpy(p_cb->loc_publ_key.x, public_key.x, BT_OCTET32_LEN);
+ memcpy(p_cb->loc_publ_key.y, public_key.y, BT_OCTET32_LEN);
+
+ smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private",
+ BT_OCTET32_LEN);
+ smp_debug_print_nbyte_little_endian (p_cb->loc_publ_key.x, (const UINT8 *)"local public(x)",
+ BT_OCTET32_LEN);
+ smp_debug_print_nbyte_little_endian (p_cb->loc_publ_key.y, (const UINT8 *)"local public(y)",
+ BT_OCTET32_LEN);
+ p_cb->flags |= SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY;
+ smp_sm_event(p_cb, SMP_LOC_PUBL_KEY_CRTD_EVT, NULL);
+}
- case SMP_GEN_TK:
- smp_proc_passkey(p_cb, p);
- break;
+/*******************************************************************************
+**
+** Function smp_compute_dhkey
+**
+** Description The function:
+** - calculates a new public key using as input local private
+** key and peer public key;
+** - saves the new public key x-coordinate as DHKey.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_compute_dhkey (tSMP_CB *p_cb)
+{
+ Point peer_publ_key, new_publ_key;
+ BT_OCTET32 private_key;
- case SMP_GEN_RAND_V:
- memcpy(p_cb->enc_rand, p->param_buf, BT_OCTET8_LEN);
- smp_generate_y(p_cb, NULL);
- break;
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
- }
+ memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN);
+ memcpy(peer_publ_key.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN);
+ memcpy(peer_publ_key.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN);
- return;
+ ECC_PointMult(&new_publ_key, &peer_publ_key, (DWORD*) private_key, KEY_LENGTH_DWORDS_P256);
+
+ memcpy(p_cb->dhkey, new_publ_key.x, BT_OCTET32_LEN);
+
+ smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"Old DHKey",
+ BT_OCTET32_LEN);
+
+ smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private",
+ BT_OCTET32_LEN);
+ smp_debug_print_nbyte_little_endian (p_cb->peer_publ_key.x, (const UINT8 *)"rem public(x)",
+ BT_OCTET32_LEN);
+ smp_debug_print_nbyte_little_endian (p_cb->peer_publ_key.y, (const UINT8 *)"rem public(y)",
+ BT_OCTET32_LEN);
+ smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"Reverted DHKey",
+ BT_OCTET32_LEN);
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_local_commitment
+**
+** Description The function calculates and saves local commmitment in CB.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_calculate_local_commitment(tSMP_CB *p_cb)
+{
+ UINT8 random_input;
+
+ SMP_TRACE_DEBUG("%s", __FUNCTION__);
+
+ switch (p_cb->selected_association_model)
+ {
+ case SMP_MODEL_SEC_CONN_JUSTWORKS:
+ case SMP_MODEL_SEC_CONN_NUM_COMP:
+ if (p_cb->role == HCI_ROLE_MASTER)
+ SMP_TRACE_WARNING ("local commitment calc on master is not expected \
+ for Just Works/Numeric Comparison models");
+ smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand, 0,
+ p_cb->commitment);
+ break;
+ case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+ case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+ random_input = smp_calculate_random_input(p_cb->local_random, p_cb->round);
+ smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand,
+ random_input, p_cb->commitment);
+ break;
+ case SMP_MODEL_SEC_CONN_OOB:
+ SMP_TRACE_WARNING ("local commitment calc is expected for OOB model BEFORE pairing");
+ smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->loc_publ_key.x, p_cb->local_random, 0,
+ p_cb->commitment);
+ break;
+ default:
+ SMP_TRACE_ERROR("Association Model = %d is not used in LE SC",
+ p_cb->selected_association_model);
+ return;
}
- SMP_TRACE_ERROR("smp_rand_back Key generation failed: (%d)", p_cb->rand_enc_proc);
+ SMP_TRACE_EVENT ("local commitment calculation is completed");
+}
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+/*******************************************************************************
+**
+** Function smp_calculate_peer_commitment
+**
+** Description The function calculates and saves peer commmitment at the
+** provided output buffer.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_calculate_peer_commitment(tSMP_CB *p_cb, BT_OCTET16 output_buf)
+{
+ UINT8 ri;
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+ switch (p_cb->selected_association_model)
+ {
+ case SMP_MODEL_SEC_CONN_JUSTWORKS:
+ case SMP_MODEL_SEC_CONN_NUM_COMP:
+ if (p_cb->role == HCI_ROLE_SLAVE)
+ SMP_TRACE_WARNING ("peer commitment calc on slave is not expected \
+ for Just Works/Numeric Comparison models");
+ smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand, 0,
+ output_buf);
+ break;
+ case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+ case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+ ri = smp_calculate_random_input(p_cb->peer_random, p_cb->round);
+ smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand, ri,
+ output_buf);
+ break;
+ case SMP_MODEL_SEC_CONN_OOB:
+ smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->peer_publ_key.x, p_cb->peer_random, 0,
+ output_buf);
+ break;
+ default:
+ SMP_TRACE_ERROR("Association Model = %d is not used in LE SC",
+ p_cb->selected_association_model);
+ return;
+ }
+ SMP_TRACE_EVENT ("peer commitment calculation is completed");
}
+
+/*******************************************************************************
+**
+** Function smp_calculate_f4
+**
+** Description The function calculates
+** C = f4(U, V, X, Z) = AES-CMAC (U||V||Z)
+** X
+** where
+** input: U is 256 bit,
+** V is 256 bit,
+** X is 128 bit,
+** Z is 8 bit,
+** output: C is 128 bit.
+**
+** Returns void
+**
+** Note The LSB is the first octet, the MSB is the last octet of
+** the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+void smp_calculate_f4(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 z, UINT8 *c)
+{
+ UINT8 msg_len = BT_OCTET32_LEN /* U size */ + BT_OCTET32_LEN /* V size */ + 1 /* Z size */;
+ UINT8 msg[BT_OCTET32_LEN + BT_OCTET32_LEN + 1];
+ UINT8 key[BT_OCTET16_LEN];
+ UINT8 cmac[BT_OCTET16_LEN];
+ UINT8 *p = NULL;
+#if SMP_DEBUG == TRUE
+ UINT8 *p_prnt = NULL;
+#endif
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+#if SMP_DEBUG == TRUE
+ p_prnt = u;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"U", BT_OCTET32_LEN);
+ p_prnt = v;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"V", BT_OCTET32_LEN);
+ p_prnt = x;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"X", BT_OCTET16_LEN);
+ p_prnt = &z;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"Z", 1);
+#endif
+
+ p = msg;
+ UINT8_TO_STREAM(p, z);
+ ARRAY_TO_STREAM(p, v, BT_OCTET32_LEN);
+ ARRAY_TO_STREAM(p, u, BT_OCTET32_LEN);
+#if SMP_DEBUG == TRUE
+ p_prnt = msg;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"M", msg_len);
+#endif
+
+ p = key;
+ ARRAY_TO_STREAM(p, x, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+ p_prnt = key;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+ aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac);
+#if SMP_DEBUG == TRUE
+ p_prnt = cmac;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"AES_CMAC", BT_OCTET16_LEN);
+#endif
+
+ p = c;
+ ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_numeric_comparison_display_number
+**
+** Description The function calculates and saves number to display in numeric
+** comparison association mode.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_calculate_numeric_comparison_display_number(tSMP_CB *p_cb,
+ tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG ("%s", __func__);
+
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ p_cb->number_to_display =
+ smp_calculate_g2(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand,
+ p_cb->rrand);
+ }
+ else
+ {
+ p_cb->number_to_display =
+ smp_calculate_g2(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand,
+ p_cb->rand);
+ }
+
+ if (p_cb->number_to_display >= (BTM_MAX_PASSKEY_VAL + 1))
+ {
+ UINT8 reason;
+ reason = p_cb->failure = SMP_PAIR_FAIL_UNKNOWN;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
+
+ SMP_TRACE_EVENT("Number to display in numeric comparison = %d", p_cb->number_to_display);
+ p_cb->cb_evt = SMP_NC_REQ_EVT;
+ smp_sm_event(p_cb, SMP_SC_DSPL_NC_EVT, &p_cb->number_to_display);
+ return;
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_g2
+**
+** Description The function calculates
+** g2(U, V, X, Y) = AES-CMAC (U||V||Y) mod 2**32 mod 10**6
+** X
+** and
+** Vres = g2(U, V, X, Y) mod 10**6
+** where
+** input: U is 256 bit,
+** V is 256 bit,
+** X is 128 bit,
+** Y is 128 bit,
+**
+** Returns Vres.
+** Expected value has to be in the range [0 - 999999] i.e. [0 - 0xF423F].
+** Vres = 1000000 means that the calculation fails.
+**
+** Note The LSB is the first octet, the MSB is the last octet of
+** the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+UINT32 smp_calculate_g2(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 *y)
+{
+ UINT8 msg_len = BT_OCTET32_LEN /* U size */ + BT_OCTET32_LEN /* V size */
+ + BT_OCTET16_LEN /* Y size */;
+ UINT8 msg[BT_OCTET32_LEN + BT_OCTET32_LEN + BT_OCTET16_LEN];
+ UINT8 key[BT_OCTET16_LEN];
+ UINT8 cmac[BT_OCTET16_LEN];
+ UINT8 *p = NULL;
+ UINT32 vres;
+#if SMP_DEBUG == TRUE
+ UINT8 *p_prnt = NULL;
+#endif
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+ p = msg;
+ ARRAY_TO_STREAM(p, y, BT_OCTET16_LEN);
+ ARRAY_TO_STREAM(p, v, BT_OCTET32_LEN);
+ ARRAY_TO_STREAM(p, u, BT_OCTET32_LEN);
+#if SMP_DEBUG == TRUE
+ p_prnt = u;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"U", BT_OCTET32_LEN);
+ p_prnt = v;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"V", BT_OCTET32_LEN);
+ p_prnt = x;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"X", BT_OCTET16_LEN);
+ p_prnt = y;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"Y", BT_OCTET16_LEN);
+#endif
+
+ p = key;
+ ARRAY_TO_STREAM(p, x, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+ p_prnt = key;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+ if(!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+ {
+ SMP_TRACE_ERROR("%s failed",__FUNCTION__);
+ return (BTM_MAX_PASSKEY_VAL + 1);
+ }
+
+#if SMP_DEBUG == TRUE
+ p_prnt = cmac;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+ /* vres = cmac mod 2**32 mod 10**6 */
+ p = &cmac[0];
+ STREAM_TO_UINT32(vres, p);
+#if SMP_DEBUG == TRUE
+ p_prnt = (UINT8 *) &vres;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"cmac mod 2**32", 4);
+#endif
+
+ while (vres > BTM_MAX_PASSKEY_VAL)
+ vres -= (BTM_MAX_PASSKEY_VAL + 1);
+#if SMP_DEBUG == TRUE
+ p_prnt = (UINT8 *) &vres;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"cmac mod 2**32 mod 10**6", 4);
+#endif
+
+ SMP_TRACE_ERROR("Value for numeric comparison = %d", vres);
+ return vres;
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_f5
+**
+** Description The function provides two AES-CMAC that are supposed to be used as
+** - MacKey (MacKey is used in pairing DHKey check calculation);
+** - LTK (LTK is used to ecrypt the link after completion of Phase 2
+** and on reconnection, to derive BR/EDR LK).
+** The function inputs are W, N1, N2, A1, A2.
+** F5 rules:
+** - the value used as key in MacKey/LTK (T) is calculated
+** (function smp_calculate_f5_key(...));
+** The formula is:
+** T = AES-CMAC (W)
+** salt
+** where salt is internal parameter of smp_calculate_f5_key(...).
+** - MacKey and LTK are calculated as AES-MAC values received with the
+** key T calculated in the previous step and the plaintext message
+** built from the external parameters N1, N2, A1, A2 and the internal
+** parameters counter, keyID, length.
+** The function smp_calculate_f5_mackey_or_long_term_key(...) is used in the
+** calculations.
+** The same formula is used in calculation of MacKey and LTK and the
+** same parameter values except the value of the internal parameter
+** counter:
+** - in MacKey calculations the value is 0;
+** - in LTK calculations the value is 1.
+** MacKey = AES-CMAC (Counter=0||keyID||N1||N2||A1||A2||Length=256)
+** T
+** LTK = AES-CMAC (Counter=1||keyID||N1||N2||A1||A2||Length=256)
+** T
+** The parameters are
+** input:
+** W is 256 bits,
+** N1 is 128 bits,
+** N2 is 128 bits,
+** A1 is 56 bit,
+** A2 is 56 bit.
+** internal:
+** Counter is 8 bits, its value is 0 for MacKey,
+** 1 for LTK;
+** KeyId is 32 bits, its value is
+** 0x62746c65 (MSB~LSB);
+** Length is 16 bits, its value is 0x0100
+** (MSB~LSB).
+** output:
+** MacKey is 128 bits;
+** LTK is 128 bits
+**
+** Returns FALSE if out of resources, TRUE in other cases.
+**
+** Note The LSB is the first octet, the MSB is the last octet of
+** the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f5(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
+ UINT8 *mac_key, UINT8 *ltk)
+{
+ BT_OCTET16 t; /* AES-CMAC output in smp_calculate_f5_key(...), key in */
+ /* smp_calculate_f5_mackey_or_long_term_key(...) */
+#if SMP_DEBUG == TRUE
+ UINT8 *p_prnt = NULL;
+#endif
+ /* internal parameters: */
+
+ /*
+ counter is 0 for MacKey,
+ is 1 for LTK
+ */
+ UINT8 counter_mac_key[1] = {0};
+ UINT8 counter_ltk[1] = {1};
+ /*
+ keyID 62746c65
+ */
+ UINT8 key_id[4] = {0x65, 0x6c, 0x74, 0x62};
+ /*
+ length 0100
+ */
+ UINT8 length[2] = {0x00, 0x01};
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+#if SMP_DEBUG == TRUE
+ p_prnt = w;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"W", BT_OCTET32_LEN);
+ p_prnt = n1;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"N1", BT_OCTET16_LEN);
+ p_prnt = n2;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"N2", BT_OCTET16_LEN);
+ p_prnt = a1;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"A1", 7);
+ p_prnt = a2;
+ smp_debug_print_nbyte_little_endian (p_prnt,(const UINT8 *) "A2", 7);
+#endif
+
+ if (!smp_calculate_f5_key(w, t))
+ {
+ SMP_TRACE_ERROR("%s failed to calc T",__FUNCTION__);
+ return FALSE;
+ }
+#if SMP_DEBUG == TRUE
+ p_prnt = t;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"T", BT_OCTET16_LEN);
+#endif
+
+ if (!smp_calculate_f5_mackey_or_long_term_key(t, counter_mac_key, key_id, n1, n2, a1, a2,
+ length, mac_key))
+ {
+ SMP_TRACE_ERROR("%s failed to calc MacKey", __FUNCTION__);
+ return FALSE;
+ }
+#if SMP_DEBUG == TRUE
+ p_prnt = mac_key;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"MacKey", BT_OCTET16_LEN);
+#endif
+
+ if (!smp_calculate_f5_mackey_or_long_term_key(t, counter_ltk, key_id, n1, n2, a1, a2,
+ length, ltk))
+ {
+ SMP_TRACE_ERROR("%s failed to calc LTK",__FUNCTION__);
+ return FALSE;
+ }
+#if SMP_DEBUG == TRUE
+ p_prnt = ltk;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"LTK", BT_OCTET16_LEN);
+#endif
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_f5_mackey_or_long_term_key
+**
+** Description The function calculates the value of MacKey or LTK by the rules
+** defined for f5 function.
+** At the moment exactly the same formula is used to calculate
+** LTK and MacKey.
+** The difference is the value of input parameter Counter:
+** - in MacKey calculations the value is 0;
+** - in LTK calculations the value is 1.
+** The formula:
+** mac = AES-CMAC (Counter||keyID||N1||N2||A1||A2||Length)
+** T
+** where
+** input: T is 256 bits;
+** Counter is 8 bits, its value is 0 for MacKey,
+** 1 for LTK;
+** keyID is 32 bits, its value is 0x62746c65;
+** N1 is 128 bits;
+** N2 is 128 bits;
+** A1 is 56 bits;
+** A2 is 56 bits;
+** Length is 16 bits, its value is 0x0100
+** output: LTK is 128 bit.
+**
+** Returns FALSE if out of resources, TRUE in other cases.
+**
+** Note The LSB is the first octet, the MSB is the last octet of
+** the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f5_mackey_or_long_term_key(UINT8 *t, UINT8 *counter,
+ UINT8 *key_id, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
+ UINT8 *length, UINT8 *mac)
+{
+ UINT8 *p = NULL;
+ UINT8 cmac[BT_OCTET16_LEN];
+ UINT8 key[BT_OCTET16_LEN];
+ UINT8 msg_len = 1 /* Counter size */ + 4 /* keyID size */ +
+ BT_OCTET16_LEN /* N1 size */ + BT_OCTET16_LEN /* N2 size */ +
+ 7 /* A1 size*/ + 7 /* A2 size*/ + 2 /* Length size */;
+ UINT8 msg[1 + 4 + BT_OCTET16_LEN + BT_OCTET16_LEN + 7 + 7 + 2];
+ BOOLEAN ret = TRUE;
+#if SMP_DEBUG == TRUE
+ UINT8 *p_prnt = NULL;
+#endif
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+#if SMP_DEBUG == TRUE
+ p_prnt = t;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"T", BT_OCTET16_LEN);
+ p_prnt = counter;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"Counter", 1);
+ p_prnt = key_id;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"KeyID", 4);
+ p_prnt = n1;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"N1", BT_OCTET16_LEN);
+ p_prnt = n2;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"N2", BT_OCTET16_LEN);
+ p_prnt = a1;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"A1", 7);
+ p_prnt = a2;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"A2", 7);
+ p_prnt = length;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"Length", 2);
+#endif
+
+ p = key;
+ ARRAY_TO_STREAM(p, t, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+ p_prnt = key;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+ p = msg;
+ ARRAY_TO_STREAM(p, length, 2);
+ ARRAY_TO_STREAM(p, a2, 7);
+ ARRAY_TO_STREAM(p, a1, 7);
+ ARRAY_TO_STREAM(p, n2, BT_OCTET16_LEN);
+ ARRAY_TO_STREAM(p, n1, BT_OCTET16_LEN);
+ ARRAY_TO_STREAM(p, key_id, 4);
+ ARRAY_TO_STREAM(p, counter, 1);
+#if SMP_DEBUG == TRUE
+ p_prnt = msg;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"M", msg_len);
+#endif
+
+ if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+ {
+ SMP_TRACE_ERROR("%s failed", __FUNCTION__);
+ ret = FALSE;
+ }
+
+#if SMP_DEBUG == TRUE
+ p_prnt = cmac;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+ p = mac;
+ ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_f5_key
+**
+** Description The function calculates key T used in calculation of
+** MacKey and LTK (f5 output is defined as MacKey || LTK).
+** T = AES-CMAC (W)
+** salt
+** where
+** Internal: salt is 128 bit.
+** input: W is 256 bit.
+** Output: T is 128 bit.
+**
+** Returns FALSE if out of resources, TRUE in other cases.
+**
+** Note The LSB is the first octet, the MSB is the last octet of
+** the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f5_key(UINT8 *w, UINT8 *t)
+{
+ UINT8 *p = NULL;
+ /* Please see 2.2.7 LE Secure Connections Key Generation Function f5 */
+ /*
+ salt: 6C88 8391 AAF5 A538 6037 0BDB 5A60 83BE
+ */
+ BT_OCTET16 salt = {
+ 0xBE, 0x83, 0x60, 0x5A, 0xDB, 0x0B, 0x37, 0x60,
+ 0x38, 0xA5, 0xF5, 0xAA, 0x91, 0x83, 0x88, 0x6C
+ };
+#if SMP_DEBUG == TRUE
+ UINT8 *p_prnt = NULL;
+#endif
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+#if SMP_DEBUG == TRUE
+ p_prnt = salt;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"salt", BT_OCTET16_LEN);
+ p_prnt = w;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"W", BT_OCTET32_LEN);
+#endif
+
+ BT_OCTET16 key;
+ BT_OCTET32 msg;
+
+ p = key;
+ ARRAY_TO_STREAM(p, salt, BT_OCTET16_LEN);
+ p = msg;
+ ARRAY_TO_STREAM(p, w, BT_OCTET32_LEN);
+#if SMP_DEBUG == TRUE
+ p_prnt = key;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"K", BT_OCTET16_LEN);
+ p_prnt = msg;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"M", BT_OCTET32_LEN);
+#endif
+
+ BT_OCTET16 cmac;
+ BOOLEAN ret = TRUE;
+ if (!aes_cipher_msg_auth_code(key, msg, BT_OCTET32_LEN, BT_OCTET16_LEN, cmac))
+ {
+ SMP_TRACE_ERROR("%s failed", __FUNCTION__);
+ ret = FALSE;
+ }
+
+#if SMP_DEBUG == TRUE
+ p_prnt = cmac;
+ smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+ p = t;
+ ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_local_dhkey_check
+**
+** Description The function calculates and saves local device DHKey check
+** value in CB.
+** Before doing this it calls smp_calculate_f5_mackey_and_long_term_key(...).
+** to calculate MacKey and LTK.
+** MacKey is used in dhkey calculation.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_calculate_local_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 iocap[3], a[7], b[7];
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+ smp_calculate_f5_mackey_and_long_term_key(p_cb);
+
+ smp_collect_local_io_capabilities(iocap, p_cb);
+
+ smp_collect_local_ble_address(a, p_cb);
+ smp_collect_peer_ble_address(b, p_cb);
+ smp_calculate_f6(p_cb->mac_key, p_cb->rand, p_cb->rrand, p_cb->peer_random, iocap, a, b,
+ p_cb->dhkey_check);
+
+ SMP_TRACE_EVENT ("local DHKey check calculation is completed");
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_peer_dhkey_check
+**
+** Description The function calculates peer device DHKey check value.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_calculate_peer_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ UINT8 iocap[3], a[7], b[7];
+ BT_OCTET16 param_buf;
+ BOOLEAN ret;
+ tSMP_KEY key;
+ tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+ smp_collect_peer_io_capabilities(iocap, p_cb);
+
+ smp_collect_local_ble_address(a, p_cb);
+ smp_collect_peer_ble_address(b, p_cb);
+ ret = smp_calculate_f6(p_cb->mac_key, p_cb->rrand, p_cb->rand, p_cb->local_random, iocap,
+ b, a, param_buf);
+
+ if (ret)
+ {
+ SMP_TRACE_EVENT ("peer DHKey check calculation is completed");
+#if (SMP_DEBUG == TRUE)
+ smp_debug_print_nbyte_little_endian (param_buf, (const UINT8 *)"peer DHKey check",
+ BT_OCTET16_LEN);
+#endif
+ key.key_type = SMP_KEY_TYPE_PEER_DHK_CHCK;
+ key.p_data = param_buf;
+ smp_sm_event(p_cb, SMP_SC_KEY_READY_EVT, &key);
+ }
+ else
+ {
+ SMP_TRACE_EVENT ("peer DHKey check calculation failed");
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+ }
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_f6
+**
+** Description The function calculates
+** C = f6(W, N1, N2, R, IOcap, A1, A2) = AES-CMAC (N1||N2||R||IOcap||A1||A2)
+** W
+** where
+** input: W is 128 bit,
+** N1 is 128 bit,
+** N2 is 128 bit,
+** R is 128 bit,
+** IOcap is 24 bit,
+** A1 is 56 bit,
+** A2 is 56 bit,
+** output: C is 128 bit.
+**
+** Returns FALSE if out of resources, TRUE in other cases.
+**
+** Note The LSB is the first octet, the MSB is the last octet of
+** the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f6(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r, UINT8 *iocap, UINT8 *a1,
+ UINT8 *a2, UINT8 *c)
+{
+ UINT8 *p = NULL;
+ UINT8 msg_len = BT_OCTET16_LEN /* N1 size */ + BT_OCTET16_LEN /* N2 size */ +
+ BT_OCTET16_LEN /* R size */ + 3 /* IOcap size */ + 7 /* A1 size*/
+ + 7 /* A2 size*/;
+ UINT8 msg[BT_OCTET16_LEN + BT_OCTET16_LEN + BT_OCTET16_LEN + 3 + 7 + 7];
+#if SMP_DEBUG == TRUE
+ UINT8 *p_print = NULL;
+#endif
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+#if SMP_DEBUG == TRUE
+ p_print = w;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"W", BT_OCTET16_LEN);
+ p_print = n1;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"N1", BT_OCTET16_LEN);
+ p_print = n2;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"N2", BT_OCTET16_LEN);
+ p_print = r;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"R", BT_OCTET16_LEN);
+ p_print = iocap;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"IOcap", 3);
+ p_print = a1;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"A1", 7);
+ p_print = a2;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"A2", 7);
+#endif
+
+ UINT8 cmac[BT_OCTET16_LEN];
+ UINT8 key[BT_OCTET16_LEN];
+
+ p = key;
+ ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+ p_print = key;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+ p = msg;
+ ARRAY_TO_STREAM(p, a2, 7);
+ ARRAY_TO_STREAM(p, a1, 7);
+ ARRAY_TO_STREAM(p, iocap, 3);
+ ARRAY_TO_STREAM(p, r, BT_OCTET16_LEN);
+ ARRAY_TO_STREAM(p, n2, BT_OCTET16_LEN);
+ ARRAY_TO_STREAM(p, n1, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+ p_print = msg;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"M", msg_len);
+#endif
+
+ BOOLEAN ret = TRUE;
+ if(!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+ {
+ SMP_TRACE_ERROR("%s failed", __FUNCTION__);
+ ret = FALSE;
+ }
+
+#if SMP_DEBUG == TRUE
+ p_print = cmac;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+ p = c;
+ ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_link_key_from_long_term_key
+**
+** Description The function calculates and saves BR/EDR link key derived from
+** LE SC LTK.
+**
+** Returns FALSE if out of resources, TRUE in other cases.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_link_key_from_long_term_key(tSMP_CB *p_cb)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec;
+
+ SMP_TRACE_DEBUG ("%s", __func__);
+
+ if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
+ {
+ SMP_TRACE_ERROR("%s failed to find Security Record", __func__);
+ return FALSE;
+ }
+
+ BT_OCTET16 intermediate_link_key;
+ BOOLEAN ret = TRUE;
+
+ ret = smp_calculate_h6(p_cb->ltk, (UINT8 *)"1pmt" /* reversed "tmp1" */,intermediate_link_key);
+ if (!ret)
+ {
+ SMP_TRACE_ERROR("%s failed to derive intermediate_link_key", __func__);
+ return ret;
+ }
+
+ BT_OCTET16 link_key;
+ ret = smp_calculate_h6(intermediate_link_key, (UINT8 *) "rbel" /* reversed "lebr" */, link_key);
+ if (!ret)
+ {
+ SMP_TRACE_ERROR("%s failed", __func__);
+ }
+ else
+ {
+ UINT8 link_key_type;
+ if (btm_cb.security_mode == BTM_SEC_MODE_SC)
+ {
+ /* Secure Connections Only Mode */
+ link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
+ }
+ else if (controller_get_interface()->supports_secure_connections())
+ {
+ /* both transports are SC capable */
+ if (p_cb->sec_level == SMP_SEC_AUTHENTICATED)
+ link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
+ else
+ link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB_P_256;
+ }
+ else if (btm_cb.security_mode == BTM_SEC_MODE_SP)
+ {
+ /* BR/EDR transport is SSP capable */
+ if (p_cb->sec_level == SMP_SEC_AUTHENTICATED)
+ link_key_type = BTM_LKEY_TYPE_AUTH_COMB;
+ else
+ link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB;
+ }
+ else
+ {
+ SMP_TRACE_ERROR ("%s failed to update link_key. Sec Mode = %d, sm4 = 0x%02x",
+ __func__, btm_cb.security_mode, p_dev_rec->sm4);
+ return FALSE;
+ }
+
+ link_key_type += BTM_LTK_DERIVED_LKEY_OFFSET;
+
+ UINT8 *p;
+ BT_OCTET16 notif_link_key;
+ p = notif_link_key;
+ ARRAY16_TO_STREAM(p, link_key);
+
+ btm_sec_link_key_notification (p_cb->pairing_bda, notif_link_key, link_key_type);
+
+ SMP_TRACE_EVENT ("%s is completed", __func__);
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_long_term_key_from_link_key
+**
+** Description The function calculates and saves SC LTK derived from BR/EDR
+** link key.
+**
+** Returns FALSE if out of resources, TRUE in other cases.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_long_term_key_from_link_key(tSMP_CB *p_cb)
+{
+ BOOLEAN ret = TRUE;
+ tBTM_SEC_DEV_REC *p_dev_rec;
+ UINT8 rev_link_key[16];
+
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+ if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
+ {
+ SMP_TRACE_ERROR("%s failed to find Security Record",__FUNCTION__);
+ return FALSE;
+ }
+
+ UINT8 br_link_key_type;
+ if ((br_link_key_type = BTM_SecGetDeviceLinkKeyType (p_cb->pairing_bda))
+ == BTM_LKEY_TYPE_IGNORE)
+ {
+ SMP_TRACE_ERROR("%s failed to retrieve BR link type",__FUNCTION__);
+ return FALSE;
+ }
+
+ if ((br_link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256) &&
+ (br_link_key_type != BTM_LKEY_TYPE_UNAUTH_COMB_P_256))
+ {
+ SMP_TRACE_ERROR("%s LE SC LTK can't be derived from LK %d",
+ __FUNCTION__, br_link_key_type);
+ return FALSE;
+ }
+
+ UINT8 *p1;
+ UINT8 *p2;
+ p1 = rev_link_key;
+ p2 = p_dev_rec->link_key;
+ REVERSE_ARRAY_TO_STREAM(p1, p2, 16);
+
+ BT_OCTET16 intermediate_long_term_key;
+ /* "tmp2" obtained from the spec */
+ ret = smp_calculate_h6(rev_link_key, (UINT8 *) "2pmt" /* reversed "tmp2" */,
+ intermediate_long_term_key);
+
+ if (!ret)
+ {
+ SMP_TRACE_ERROR("%s failed to derive intermediate_long_term_key",__FUNCTION__);
+ return ret;
+ }
+
+ /* "brle" obtained from the spec */
+ ret = smp_calculate_h6(intermediate_long_term_key, (UINT8 *) "elrb" /* reversed "brle" */,
+ p_cb->ltk);
+
+ if (!ret)
+ {
+ SMP_TRACE_ERROR("%s failed",__FUNCTION__);
+ }
+ else
+ {
+ p_cb->sec_level = (br_link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256)
+ ? SMP_SEC_AUTHENTICATED : SMP_SEC_UNAUTHENTICATE;
+ SMP_TRACE_EVENT ("%s is completed",__FUNCTION__);
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function smp_calculate_h6
+**
+** Description The function calculates
+** C = h6(W, KeyID) = AES-CMAC (KeyID)
+** W
+** where
+** input: W is 128 bit,
+** KeyId is 32 bit,
+** output: C is 128 bit.
+**
+** Returns FALSE if out of resources, TRUE in other cases.
+**
+** Note The LSB is the first octet, the MSB is the last octet of
+** the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_h6(UINT8 *w, UINT8 *keyid, UINT8 *c)
+{
+#if SMP_DEBUG == TRUE
+ UINT8 *p_print = NULL;
+#endif
+
+ SMP_TRACE_DEBUG ("%s",__FUNCTION__);
+#if SMP_DEBUG == TRUE
+ p_print = w;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"W", BT_OCTET16_LEN);
+ p_print = keyid;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"keyID", 4);
+#endif
+
+ UINT8 *p = NULL;
+ UINT8 key[BT_OCTET16_LEN];
+
+ p = key;
+ ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN);
+
+#if SMP_DEBUG == TRUE
+ p_print = key;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+ UINT8 msg_len = 4 /* KeyID size */;
+ UINT8 msg[4];
+
+ p = msg;
+ ARRAY_TO_STREAM(p, keyid, 4);
+
+#if SMP_DEBUG == TRUE
+ p_print = msg;
+ smp_debug_print_nbyte_little_endian (p_print,(const UINT8 *) "M", msg_len);
+#endif
+
+ BOOLEAN ret = TRUE;
+ UINT8 cmac[BT_OCTET16_LEN];
+ if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+ {
+ SMP_TRACE_ERROR("%s failed",__FUNCTION__);
+ ret = FALSE;
+ }
+
+#if SMP_DEBUG == TRUE
+ p_print = cmac;
+ smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+ p = c;
+ ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function smp_start_nonce_generation
+**
+** Description This function starts nonce generation.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_start_nonce_generation(tSMP_CB *p_cb)
+{
+ SMP_TRACE_DEBUG("%s", __FUNCTION__);
+ p_cb->rand_enc_proc_state = SMP_GEN_NONCE_0_7;
+ if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+ smp_rand_back(NULL);
+}
+
+/*******************************************************************************
+**
+** Function smp_finish_nonce_generation
+**
+** Description This function finishes nonce generation.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_finish_nonce_generation(tSMP_CB *p_cb)
+{
+ SMP_TRACE_DEBUG("%s", __FUNCTION__);
+ p_cb->rand_enc_proc_state = SMP_GEN_NONCE_8_15;
+ if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+ smp_rand_back(NULL);
+}
+
+/*******************************************************************************
+**
+** Function smp_process_new_nonce
+**
+** Description This function notifies SM that it has new nonce.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_process_new_nonce(tSMP_CB *p_cb)
+{
+ SMP_TRACE_DEBUG ("%s round %d", __FUNCTION__, p_cb->round);
+ smp_sm_event(p_cb, SMP_HAVE_LOC_NONCE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function smp_rand_back
+**
+** Description This function is to process the rand command finished,
+** process the random/encrypted number for further action.
+**
+** Returns void
+**
+*******************************************************************************/
+static void smp_rand_back(tBTM_RAND_ENC *p)
+{
+ tSMP_CB *p_cb = &smp_cb;
+ UINT8 *pp = p->param_buf;
+ UINT8 failure = SMP_PAIR_FAIL_UNKNOWN;
+ UINT8 state = p_cb->rand_enc_proc_state & ~0x80;
+
+ SMP_TRACE_DEBUG ("%s state=0x%x", __FUNCTION__, state);
+ if (p && p->status == HCI_SUCCESS)
+ {
+ switch (state)
+ {
+ case SMP_GEN_SRAND_MRAND:
+ memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
+ smp_generate_rand_cont(p_cb, NULL);
+ break;
+
+ case SMP_GEN_SRAND_MRAND_CONT:
+ memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
+ smp_generate_confirm(p_cb, NULL);
+ break;
+
+ case SMP_GEN_DIV_LTK:
+ STREAM_TO_UINT16(p_cb->div, pp);
+ smp_generate_ltk_cont(p_cb, NULL);
+ break;
+
+ case SMP_GEN_DIV_CSRK:
+ STREAM_TO_UINT16(p_cb->div, pp);
+ smp_compute_csrk(p_cb, NULL);
+ break;
+
+ case SMP_GEN_TK:
+ smp_proc_passkey(p_cb, p);
+ break;
+
+ case SMP_GEN_RAND_V:
+ memcpy(p_cb->enc_rand, p->param_buf, BT_OCTET8_LEN);
+ smp_generate_y(p_cb, NULL);
+ break;
+
+ case SMP_GENERATE_PRIVATE_KEY_0_7:
+ case SMP_GENERATE_PRIVATE_KEY_8_15:
+ case SMP_GENERATE_PRIVATE_KEY_16_23:
+ case SMP_GENERATE_PRIVATE_KEY_24_31:
+ smp_continue_private_key_creation(p_cb, p);
+ break;
+
+ case SMP_GEN_NONCE_0_7:
+ memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
+ smp_finish_nonce_generation(p_cb);
+ break;
+
+ case SMP_GEN_NONCE_8_15:
+ memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
+ smp_process_new_nonce(p_cb);
+ break;
+ }
+
+ return;
+ }
+
+ SMP_TRACE_ERROR("%s key generation failed: (%d)", __FUNCTION__, p_cb->rand_enc_proc_state);
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+}
+
#endif
#include "smp_int.h"
+static void smp_tx_complete_callback(UINT16 cid, UINT16 num_pkt);
-static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
- UINT16 reason, tBT_TRANSPORT transport);
-static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf);
+static void smp_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
+ tBT_TRANSPORT transport);
+static void smp_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf);
+
+static void smp_br_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
+ tBT_TRANSPORT transport);
+static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf);
/*******************************************************************************
**
void smp_l2cap_if_init (void)
{
tL2CAP_FIXED_CHNL_REG fixed_reg;
- SMP_TRACE_EVENT ("SMDBG l2c smp_l2cap_if_init");
+ SMP_TRACE_EVENT ("SMDBG l2c %s", __func__);
fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE;
fixed_reg.fixed_chnl_opts.max_transmit = 0;
fixed_reg.fixed_chnl_opts.rtrans_tout = 0;
fixed_reg.fixed_chnl_opts.mps = 0;
fixed_reg.fixed_chnl_opts.tx_win_sz = 0;
- fixed_reg.pL2CA_FixedConn_Cb = smp_connect_cback;
- fixed_reg.pL2CA_FixedData_Cb = smp_data_ind;
+ fixed_reg.pL2CA_FixedConn_Cb = smp_connect_callback;
+ fixed_reg.pL2CA_FixedData_Cb = smp_data_received;
+ fixed_reg.pL2CA_FixedTxComplete_Cb = smp_tx_complete_callback;
+
fixed_reg.pL2CA_FixedCong_Cb = NULL; /* do not handle congestion on this channel */
fixed_reg.default_idle_tout = 60; /* set 60 seconds timeout, 0xffff default idle timeout */
- /* Now, register with L2CAP */
L2CA_RegisterFixedChannel (L2CAP_SMP_CID, &fixed_reg);
+
+ fixed_reg.pL2CA_FixedConn_Cb = smp_br_connect_callback;
+ fixed_reg.pL2CA_FixedData_Cb = smp_br_data_received;
+
+ L2CA_RegisterFixedChannel (L2CAP_SMP_BR_CID, &fixed_reg);
}
/*******************************************************************************
**
-** Function smp_connect_cback
+** Function smp_connect_callback
**
** Description This callback function is called by L2CAP to indicate that
** SMP channel is
** connected (conn = TRUE)/disconnected (conn = FALSE).
**
*******************************************************************************/
-static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
- tBT_TRANSPORT transport)
+static void smp_connect_callback (UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
+ tBT_TRANSPORT transport)
{
tSMP_CB *p_cb = &smp_cb;
tSMP_INT_DATA int_data;
+ BD_ADDR dummy_bda = {0};
- SMP_TRACE_EVENT ("SMDBG l2c smp_connect_cback ");
+ SMP_TRACE_EVENT ("SMDBG l2c %s", __FUNCTION__);
- if (transport == BT_TRANSPORT_BR_EDR)
- {
- SMP_TRACE_ERROR ("smp_connect_cback : Wrong transport");
+ if (transport == BT_TRANSPORT_BR_EDR || memcmp(bd_addr, dummy_bda, BD_ADDR_LEN) == 0)
return;
- }
if (memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0)
{
- SMP_TRACE_EVENT ("smp_connect_cback() for pairing BDA: %08x%04x Event: %s",
+ SMP_TRACE_EVENT ("%s() for pairing BDA: %08x%04x Event: %s",
+ __FUNCTION__,
(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3],
- (bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected");
+ (bd_addr[4]<<8)+bd_addr[5],
+ (connected) ? "connected" : "disconnected");
if (connected)
{
p_cb->role = L2CA_GetBleConnRole(bd_addr);
/* initialize local i/r key to be default keys */
- p_cb->loc_r_key = p_cb->loc_i_key = SMP_SEC_DEFAULT_KEY;
+ p_cb->local_r_key = p_cb->local_i_key = SMP_SEC_DEFAULT_KEY;
p_cb->loc_auth_req = p_cb->peer_auth_req = SMP_DEFAULT_AUTH_REQ;
p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
smp_sm_event(p_cb, SMP_L2CAP_CONN_EVT, NULL);
/*******************************************************************************
**
-** Function smp_data_ind
+** Function smp_data_received
**
** Description This function is called when data is received from L2CAP on
** SMP channel.
** Returns void
**
*******************************************************************************/
-static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
+static void smp_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
{
tSMP_CB *p_cb = &smp_cb;
UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
UINT8 cmd ;
- SMP_TRACE_EVENT ("SMDBG l2c smp_data_ind");
-
- SMP_TRACE_EVENT ("Got smp_data_ind");
+ SMP_TRACE_EVENT ("SMDBG l2c %s", __FUNCTION__);
STREAM_TO_UINT8(cmd, p);
/* sanity check */
- if ((SMP_OPCODE_MAX <= cmd) || (cmd == 0))
+ if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd))
{
SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x", cmd);
GKI_freebuf (p_buf);
/* reject the pairing request if there is an on-going SMP pairing */
if (SMP_OPCODE_PAIRING_REQ == cmd || SMP_OPCODE_SEC_REQ == cmd)
{
- if (p_cb->state == SMP_ST_IDLE)
+ if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE))
{
p_cb->role = L2CA_GetBleConnRole(bd_addr);
memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN);
else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN))
{
GKI_freebuf (p_buf);
- smp_reject_unexp_pair_req(bd_addr);
+ smp_reject_unexpected_pairing_command(bd_addr);
return;
}
/* else, out of state pairing request/security request received, passed into SM */
if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0)
{
- if (p_cb->state != SMP_ST_RELEASE_DELAY)
- {
- btu_stop_timer (&p_cb->rsp_timer_ent);
- btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
+ btu_stop_timer (&p_cb->rsp_timer_ent);
+ btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
SMP_WAIT_FOR_RSP_TOUT);
+
+ if (cmd == SMP_OPCODE_CONFIRM)
+ {
+ SMP_TRACE_DEBUG ("in %s cmd = 0x%02x, peer_auth_req = 0x%02x,"
+ "loc_auth_req = 0x%02x",
+ __FUNCTION__, cmd, p_cb->peer_auth_req, p_cb->loc_auth_req);
+
+ if ((p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT) &&
+ (p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT))
+ {
+ cmd = SMP_OPCODE_PAIR_COMMITM;
+ }
}
+
p_cb->rcvd_cmd_code = cmd;
p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
smp_sm_event(p_cb, cmd, p);
GKI_freebuf (p_buf);
}
-#endif
+
+/*******************************************************************************
+**
+** Function smp_tx_complete_callback
+**
+** Description SMP channel tx complete callback
+**
+*******************************************************************************/
+static void smp_tx_complete_callback (UINT16 cid, UINT16 num_pkt)
+{
+ tSMP_CB *p_cb = &smp_cb;
+
+ if (p_cb->total_tx_unacked >= num_pkt)
+ p_cb->total_tx_unacked -= num_pkt;
+ else
+ SMP_TRACE_ERROR("Unexpected %s: num_pkt = %d", __FUNCTION__,num_pkt);
+
+ UINT8 reason = SMP_SUCCESS;
+ if (p_cb->total_tx_unacked == 0 && p_cb->wait_for_authorization_complete)
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+}
+
+/*******************************************************************************
+**
+** Function smp_br_connect_callback
+**
+** Description This callback function is called by L2CAP to indicate that
+** SMP BR channel is
+** connected (conn = TRUE)/disconnected (conn = FALSE).
+**
+*******************************************************************************/
+static void smp_br_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected,
+ UINT16 reason, tBT_TRANSPORT transport)
+{
+ tSMP_CB *p_cb = &smp_cb;
+ tSMP_INT_DATA int_data;
+
+ SMP_TRACE_EVENT ("%s", __func__);
+
+ if (transport != BT_TRANSPORT_BR_EDR)
+ {
+ SMP_TRACE_WARNING("%s is called on unexpected transport %d",
+ __func__, transport);
+ return;
+ }
+
+ if (!(memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0))
+ return;
+
+ SMP_TRACE_EVENT ("%s for pairing BDA: %08x%04x Event: %s",
+ __func__,
+ (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3],
+ (bd_addr[4]<<8)+bd_addr[5],
+ (connected) ? "connected" : "disconnected");
+
+ if (connected)
+ {
+ if(!p_cb->connect_initialized)
+ {
+ p_cb->connect_initialized = TRUE;
+ /* initialize local i/r key to be default keys */
+ p_cb->local_r_key = p_cb->local_i_key = SMP_BR_SEC_DEFAULT_KEY;
+ p_cb->loc_auth_req = p_cb->peer_auth_req = 0;
+ p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT;
+ smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_CONN_EVT, NULL);
+ }
+ }
+ else
+ {
+ int_data.reason = reason;
+ /* Disconnected while doing security */
+ smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_DISCONN_EVT, &int_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function smp_br_data_received
+**
+** Description This function is called when data is received from L2CAP on
+** SMP BR channel.
+**
+** Returns void
+**
+*******************************************************************************/
+static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
+{
+ tSMP_CB *p_cb = &smp_cb;
+ UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+ UINT8 cmd ;
+ SMP_TRACE_EVENT ("SMDBG l2c %s", __func__);
+
+ STREAM_TO_UINT8(cmd, p);
+
+ /* sanity check */
+ if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd))
+ {
+ SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x", cmd);
+ GKI_freebuf(p_buf);
+ return;
+ }
+
+ /* reject the pairing request if there is an on-going SMP pairing */
+ if (SMP_OPCODE_PAIRING_REQ == cmd)
+ {
+ if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE))
+ {
+ p_cb->role = HCI_ROLE_SLAVE;
+ p_cb->smp_over_br = TRUE;
+ memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN);
+ }
+ else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN))
+ {
+ GKI_freebuf (p_buf);
+ smp_reject_unexpected_pairing_command(bd_addr);
+ return;
+ }
+ /* else, out of state pairing request received, passed into State Machine */
+ }
+
+ if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0)
+ {
+ btu_stop_timer (&p_cb->rsp_timer_ent);
+ btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
+ SMP_WAIT_FOR_RSP_TOUT);
+
+ p_cb->rcvd_cmd_code = cmd;
+ p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
+ smp_br_state_machine_event(p_cb, cmd, p);
+ }
+
+ GKI_freebuf (p_buf);
+}
+#endif /* SMP_INCLUDED == TRUE */
#if SMP_INCLUDED == TRUE
- #include <string.h>
- #include "smp_int.h"
+#include <string.h>
+#include "smp_int.h"
-
-const char * const smp_state_name [] =
+const char *const smp_state_name [] =
{
- "SMP_ST_IDLE",
- "SMP_ST_WAIT_APP_RSP",
- "SMP_ST_SEC_REQ_PENDING",
- "SMP_ST_PAIR_REQ_RSP",
- "SMP_ST_WAIT_CONFIRM",
- "SMP_ST_CONFIRM",
- "SMP_ST_RAND",
- "SMP_ST_ENC_PENDING",
- "SMP_ST_BOND_PENDING",
- "SMP_ST_RELEASE_DELAY",
- "SMP_ST_MAX"
+ "SMP_STATE_IDLE",
+ "SMP_STATE_WAIT_APP_RSP",
+ "SMP_STATE_SEC_REQ_PENDING",
+ "SMP_STATE_PAIR_REQ_RSP",
+ "SMP_STATE_WAIT_CONFIRM",
+ "SMP_STATE_CONFIRM",
+ "SMP_STATE_RAND",
+ "SMP_STATE_PUBLIC_KEY_EXCH",
+ "SMP_STATE_SEC_CONN_PHS1_START",
+ "SMP_STATE_WAIT_COMMITMENT",
+ "SMP_STATE_WAIT_NONCE",
+ "SMP_STATE_SEC_CONN_PHS2_START",
+ "SMP_STATE_WAIT_DHK_CHECK",
+ "SMP_STATE_DHK_CHECK",
+ "SMP_STATE_ENCRYPTION_PENDING",
+ "SMP_STATE_BOND_PENDING",
+ "SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA",
+ "SMP_STATE_MAX"
};
-const char * const smp_event_name [] =
+
+const char *const smp_event_name [] =
{
"PAIRING_REQ_EVT",
"PAIRING_RSP_EVT",
"ID_ADDR_EVT",
"SIGN_INFO_EVT",
"SECURITY_REQ_EVT",
+ "PAIR_PUBLIC_KEY_EVT",
+ "PAIR_DHKEY_CHECK_EVT",
+ "PAIR_KEYPRESS_NOTIFICATION_EVT",
+ "PAIR_COMMITMENT_EVT",
"KEY_READY_EVT",
"ENCRYPTED_EVT",
"L2CAP_CONN_EVT",
"ENC_REQ_EVT",
"BOND_REQ_EVT",
"DISCARD_SEC_REQ_EVT",
- "RELEASE_DELAY_EVT",
- "RELEASE_DELAY_TOUT_EVT",
- "MAX_EVT"
+ "PUBLIC_KEY_EXCHANGE_REQ_EVT",
+ "LOCAL_PUBLIC_KEY_CRTD_EVT",
+ "BOTH_PUBLIC_KEYS_RCVD_EVT",
+ "SEC_CONN_DHKEY_COMPLETE_EVT",
+ "HAVE_LOCAL_NONCE_EVT",
+ "SEC_CONN_PHASE1_CMPLT_EVT",
+ "SEC_CONN_CALC_NC_EVT",
+ "SEC_CONN_DISPLAY_NC_EVT",
+ "SEC_CONN_OK_EVT",
+ "SEC_CONN_2_DHCK_CHECKS_PRESENT_EVT",
+ "SEC_CONN_KEY_READY_EVT",
+ "KEYPRESS_NOTIFICATION_EVT",
+ "SEC_CONN_OOB_DATA_EVT",
+ "CREATE_LOCAL_SEC_CONN_OOB_DATA_EVT",
+ "OUT_OF_RANGE_EVT"
};
-const char * smp_get_event_name(tSMP_EVENT event);
-const char * smp_get_state_name(tSMP_STATE state);
- #define SMP_SM_IGNORE 0
- #define SMP_NUM_ACTIONS 2
- #define SMP_SME_NEXT_STATE 2
- #define SMP_SM_NUM_COLS 3
-typedef const UINT8 (*tSMP_SM_TBL)[SMP_SM_NUM_COLS];
+const char *smp_get_event_name(tSMP_EVENT event);
+const char *smp_get_state_name(tSMP_STATE state);
+
+#define SMP_SM_IGNORE 0
+#define SMP_NUM_ACTIONS 2
+#define SMP_SME_NEXT_STATE 2
+#define SMP_SM_NUM_COLS 3
+
+typedef const UINT8(*tSMP_SM_TBL)[SMP_SM_NUM_COLS];
enum
{
SMP_SEND_PAIR_RSP,
SMP_SEND_CONFIRM,
SMP_SEND_PAIR_FAIL,
- SMP_SEND_INIT,
- SMP_SEND_SECU_INFO,
+ SMP_SEND_RAND,
+ SMP_SEND_ENC_INFO,
SMP_SEND_ID_INFO,
SMP_SEND_LTK_REPLY,
SMP_PROC_PAIR_CMD,
SMP_PROC_PAIR_FAIL,
SMP_PROC_CONFIRM,
- SMP_PROC_INIT,
+ SMP_PROC_RAND,
SMP_PROC_ENC_INFO,
SMP_PROC_MASTER_ID,
SMP_PROC_ID_INFO,
SMP_PAIR_TERMINATE,
SMP_ENC_CMPL,
SMP_PROC_DISCARD,
- SMP_PROC_REL_DELAY,
- SMP_PROC_REL_DELAY_TOUT,
- SMP_DELAY_TERMINATE,
+ SMP_CREATE_PRIVATE_KEY,
+ SMP_USE_OOB_PRIVATE_KEY,
+ SMP_SEND_PAIR_PUBLIC_KEY,
+ SMP_PROCESS_PAIR_PUBLIC_KEY,
+ SMP_HAVE_BOTH_PUBLIC_KEYS,
+ SMP_START_SEC_CONN_PHASE1,
+ SMP_PROCESS_LOCAL_NONCE,
+ SMP_SEND_COMMITMENT,
+ SMP_PROCESS_PAIRING_COMMITMENT,
+ SMP_PROCESS_PEER_NONCE,
+ SMP_CALCULATE_LOCAL_DHKEY_CHECK,
+ SMP_SEND_DHKEY_CHECK,
+ SMP_PROCESS_DHKEY_CHECK,
+ SMP_CALCULATE_PEER_DHKEY_CHECK,
+ SMP_MATCH_DHKEY_CHECKS,
+ SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER,
+ SMP_MOVE_TO_SEC_CONN_PHASE2,
+ SMP_PH2_DHKEY_CHECKS_ARE_PRESENT,
+ SMP_WAIT_FOR_BOTH_PUBLIC_KEYS,
+ SMP_START_PASSKEY_VERIFICATION,
+ SMP_SEND_KEYPRESS_NOTIFICATION,
+ SMP_PROCESS_KEYPRESS_NOTIFICATION,
+ SMP_PROCESS_SECURE_CONNECTION_OOB_DATA,
+ SMP_SET_LOCAL_OOB_KEYS,
+ SMP_SET_LOCAL_OOB_RAND_COMMITMENT,
SMP_IDLE_TERMINATE,
SMP_FAST_CONN_PARAM,
SMP_SM_NO_ACTION
smp_send_pair_rsp,
smp_send_confirm,
smp_send_pair_fail,
- smp_send_init,
+ smp_send_rand,
smp_send_enc_info,
smp_send_id_info,
smp_send_ltk_reply,
smp_proc_pair_cmd,
smp_proc_pair_fail,
smp_proc_confirm,
- smp_proc_init,
+ smp_proc_rand,
smp_proc_enc_info,
smp_proc_master_id,
smp_proc_id_info,
smp_proc_sec_grant,
smp_proc_sl_key,
smp_proc_compare,
- smp_proc_io_rsp,
+ smp_process_io_response,
smp_generate_compare,
- smp_generate_confirm,
+ smp_generate_srand_mrand_confirm,
smp_generate_stk,
smp_key_distribution,
smp_start_enc,
smp_pairing_cmpl,
- smp_decide_asso_model,
+ smp_decide_association_model,
smp_send_app_cback,
smp_check_auth_req,
smp_pair_terminate,
smp_enc_cmpl,
smp_proc_discard,
- smp_proc_release_delay,
- smp_proc_release_delay_tout,
- smp_delay_terminate,
+ smp_create_private_key,
+ smp_use_oob_private_key,
+ smp_send_pair_public_key,
+ smp_process_pairing_public_key,
+ smp_both_have_public_keys,
+ smp_start_secure_connection_phase1,
+ smp_process_local_nonce,
+ smp_send_commitment,
+ smp_process_pairing_commitment,
+ smp_process_peer_nonce,
+ smp_calculate_local_dhkey_check,
+ smp_send_dhkey_check,
+ smp_process_dhkey_check,
+ smp_calculate_peer_dhkey_check,
+ smp_match_dhkey_checks,
+ smp_calculate_numeric_comparison_display_number,
+ smp_move_to_secure_connections_phase2,
+ smp_phase_2_dhkey_checks_are_present,
+ smp_wait_for_both_public_keys,
+ smp_start_passkey_verification,
+ smp_send_keypress_notification,
+ smp_process_keypress_notification,
+ smp_process_secure_connection_oob_data,
+ smp_set_local_oob_keys,
+ smp_set_local_oob_random_commitment,
smp_idle_terminate,
smp_fast_conn_param
};
+
/************ SMP Master FSM State/Event Indirection Table **************/
-static const UINT8 smp_ma_entry_map[][SMP_ST_MAX] =
-{
-/* state name: Idle WaitApp SecReq Pair Wait Confirm Init Enc Bond Rel
- Rsp Pend ReqRsp Cfm Pend Pend Delay */
-/* PAIR_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* PAIR_RSP */{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
-/* CONFIRM */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
-/* INIT */{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
-/* PAIR_FAIL */{ 0, 0x81, 0, 0x81, 0x81,0x81, 0x81,0, 0, 0 },
-/* ENC_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
-/* MASTER_ID */{ 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
-/* ID_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
-/* ID_ADDR */{ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
-/* SIGN_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 },
-/* SEC_REQ */{ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* KEY_READY */{ 0, 3, 0, 3, 1, 0, 2, 1, 6, 0 },
-/* ENC_CMPL */{ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 },
-/* L2C_CONN */{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* L2C_DISC */{ 3, 0x83, 0, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 3 },
-/* IO_RSP */{ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* SEC_GRANT */{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* TK_REQ */{ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 },
-/* AUTH_CMPL */{ 0, 0x82, 0, 0x82, 0x82,0x82, 0x82,0x82, 0x82, 0 },
-/* ENC_REQ */{ 0, 4, 0, 0, 0, 0, 3, 0, 0, 0 },
-/* BOND_REQ */{ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
-/* DISCARD_SEC_REQ */{ 0, 5, 0, 0, 0, 0, 0, 3, 0, 0 },
-/* RELEASE_DELAY */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
-/* RELEASE_DELAY_TOUT */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
-};
-
-static const UINT8 smp_all_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* PAIR_FAIL */ {SMP_PROC_PAIR_FAIL, SMP_PROC_REL_DELAY_TOUT, SMP_ST_IDLE},
-/* AUTH_CMPL */ {SMP_SEND_PAIR_FAIL, SMP_PAIRING_CMPL, SMP_ST_RELEASE_DELAY},
-/* L2C_DISC */ {SMP_PAIR_TERMINATE, SMP_SM_NO_ACTION, SMP_ST_IDLE}
-};
-
-static const UINT8 smp_ma_idle_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* L2C_CONN */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_ST_WAIT_APP_RSP},
-/* SEC_REQ */ {SMP_PROC_SEC_REQ, SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP},
-/* L2C_DISC */ {SMP_IDLE_TERMINATE, SMP_SM_NO_ACTION, SMP_ST_IDLE}
-};
-
-static const UINT8 smp_ma_wait_app_rsp_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* SEC_GRANT */ { SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP},
-/* IO_RSP */ { SMP_SEND_PAIR_REQ, SMP_FAST_CONN_PARAM, SMP_ST_PAIR_REQ_RSP},
-/* KEY_READY */ { SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION, SMP_ST_WAIT_CONFIRM},/* TK ready */
-/* ENC_REQ */ { SMP_START_ENC, SMP_FAST_CONN_PARAM, SMP_ST_ENC_PENDING},/* start enc mode setup */
-/* DISCARD_SEC_REQ */ { SMP_PROC_DISCARD, SMP_SM_NO_ACTION, SMP_ST_IDLE}
-};
-
-static const UINT8 smp_ma_pair_req_rsp_table [][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* PAIR_RSP */ { SMP_PROC_PAIR_CMD, SMP_DECIDE_ASSO_MODEL, SMP_ST_PAIR_REQ_RSP},
-/* TK_REQ */ { SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_ST_WAIT_APP_RSP},
-/* KEY_READY */{ SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION, SMP_ST_WAIT_CONFIRM} /* TK ready */
-};
-
-static const UINT8 smp_ma_wait_confirm_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* KEY_READY*/ {SMP_SEND_CONFIRM, SMP_SM_NO_ACTION, SMP_ST_CONFIRM}/* CONFIRM ready */
-};
-
-static const UINT8 smp_ma_confirm_table [][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* CONFIRM */ { SMP_PROC_CONFIRM, SMP_SEND_INIT, SMP_ST_RAND}
-};
-
-static const UINT8 smp_ma_init_table [][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* INIT */ { SMP_PROC_INIT, SMP_GENERATE_COMPARE, SMP_ST_RAND},
-/* KEY_READY*/ { SMP_PROC_COMPARE, SMP_SM_NO_ACTION, SMP_ST_RAND}, /* Compare ready */
-/* ENC_REQ */ { SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_ST_ENC_PENDING}
-};
-static const UINT8 smp_ma_enc_pending_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* KEY_READY */ { SMP_START_ENC, SMP_SM_NO_ACTION, SMP_ST_ENC_PENDING}, /* STK ready */
-/* ENCRYPTED */ { SMP_CHECK_AUTH_REQ, SMP_SM_NO_ACTION, SMP_ST_ENC_PENDING},
-/* BOND_REQ */ { SMP_KEY_DISTRIBUTE, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING}
-};
-static const UINT8 smp_ma_bond_pending_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* ENC_INFO */ { SMP_PROC_ENC_INFO, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING},
-/* ID_INFO */ { SMP_PROC_ID_INFO, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING},
-/* SIGN_INFO*/ { SMP_PROC_SRK_INFO, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING},
-/* MASTER_ID*/ { SMP_PROC_MASTER_ID, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING},
-/* ID_ADDR */ { SMP_PROC_ID_ADDR, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING},
-/* KEY_READY */ {SMP_SEND_SECU_INFO, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING} /* LTK ready */
-};
-
-static const UINT8 smp_ma_rel_delay_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* RELEASE_DELAY*/ {SMP_PROC_REL_DELAY, SMP_SM_NO_ACTION, SMP_ST_RELEASE_DELAY},
-/* RELEASE_DELAY_TOUT*/ {SMP_PROC_REL_DELAY_TOUT, SMP_SM_NO_ACTION, SMP_ST_IDLE},
-/* L2C_DISC*/ {SMP_DELAY_TERMINATE, SMP_SM_NO_ACTION, SMP_ST_IDLE}
+static const UINT8 smp_master_entry_map[][SMP_STATE_MAX] =
+{
+/* state name: Idle WaitApp SecReq Pair Wait Confirm Rand PublKey SCPhs1 Wait Wait SCPhs2 Wait DHKChk Enc Bond CrLocSc
+ Rsp Pend ReqRsp Cfm Exch Strt Cmtm Nonce Strt DHKChk Pend Pend OobData */
+/* PAIR_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* PAIR_RSP */{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* CONFIRM */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* RAND */{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
+/* PAIR_FAIL */{ 0, 0x81, 0, 0x81, 0x81,0x81, 0x81,0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0, 0, 0 },
+/* ENC_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
+/* MASTER_ID */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
+/* ID_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
+/* ID_ADDR */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
+/* SIGN_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 },
+/* SEC_REQ */{ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* PAIR_PUBLIC_KEY */{ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* PAIR_DHKEY_CHCK */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 },
+/* PAIR_KEYPR_NOTIF */{ 0, 8, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0 },
+/* PAIR_COMMITM */{ 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0 },
+/* KEY_READY */{ 0, 3, 0, 3, 1, 0, 2, 0, 4, 0, 0, 0, 0, 0, 1, 6, 0 },
+/* ENC_CMPL */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 },
+/* L2C_CONN */{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* L2C_DISC */{ 3, 0x83, 0, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0 },
+/* IO_RSP */{ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SEC_GRANT */{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* TK_REQ */{ 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* AUTH_CMPL */{ 4, 0x82, 0, 0x82, 0x82,0x82, 0x82,0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0 },
+/* ENC_REQ */{ 0, 4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 },
+/* BOND_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
+/* DISCARD_SEC_REQ */{ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
+/* PUBL_KEY_EXCH_REQ */{ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* LOC_PUBL_KEY_CRTD */{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+/* BOTH_PUBL_KEYS_RCVD */{ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SC_DHKEY_CMPLT */{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* HAVE_LOC_NONCE */{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2 },
+/* SC_PHASE1_CMPLT */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
+/* SC_CALC_NC */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 },
+/* SC_DSPL_NC */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 },
+/* SC_NC_OK */{ 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SC_2_DHCK_CHKS_PRES */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SC_KEY_READY */{ 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
+/* KEYPR_NOTIF */{ 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SC_OOB_DATA */{ 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* CR_LOC_SC_OOB_DATA */{ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static const UINT8 smp_all_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* PAIR_FAIL */ {SMP_PROC_PAIR_FAIL, SMP_PAIRING_CMPL, SMP_STATE_IDLE},
+/* AUTH_CMPL */ {SMP_SEND_PAIR_FAIL, SMP_PAIRING_CMPL, SMP_STATE_IDLE},
+/* L2C_DISC */ {SMP_PAIR_TERMINATE, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
+};
+
+static const UINT8 smp_master_idle_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* L2C_CONN */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SEC_REQ */ {SMP_PROC_SEC_REQ, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+/* L2C_DISC */ {SMP_IDLE_TERMINATE, SMP_SM_NO_ACTION, SMP_STATE_IDLE},
+/* AUTH_CMPL */ {SMP_PAIRING_CMPL, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
+/* CR_LOC_SC_OOB_DATA */ ,{SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA}
+
+};
+
+static const UINT8 smp_master_wait_for_app_response_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* SEC_GRANT */ {SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+/* IO_RSP */ {SMP_SEND_PAIR_REQ, SMP_FAST_CONN_PARAM, SMP_STATE_PAIR_REQ_RSP},
+
+ /* TK ready */
+/* KEY_READY */ {SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_WAIT_CONFIRM},
+
+ /* start enc mode setup */
+/* ENC_REQ */ { SMP_START_ENC, SMP_FAST_CONN_PARAM, SMP_STATE_ENCRYPTION_PENDING},
+/* DISCARD_SEC_REQ */ { SMP_PROC_DISCARD, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
+/* user confirms NC 'OK', i.e. phase 1 is completed */
+/* SC_NC_OK */,{ SMP_MOVE_TO_SEC_CONN_PHASE2, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS2_START},
+/* user-provided passkey is rcvd */
+/* SC_KEY_READY */ { SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_KEYPR_NOTIF */ { SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+/* KEYPR_NOTIF */ { SMP_SEND_KEYPRESS_NOTIFICATION, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SC_OOB_DATA */ { SMP_USE_OOB_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH}
+};
+
+static const UINT8 smp_master_pair_request_response_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* PAIR_RSP */ { SMP_PROC_PAIR_CMD, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
+/* TK_REQ */ { SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+
+ /* TK ready */
+/* KEY_READY */{ SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_WAIT_CONFIRM}
+/* PUBL_KEY_EXCH_REQ */,{ SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH}
+};
+
+static const UINT8 smp_master_wait_for_confirm_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* KEY_READY*/ {SMP_SEND_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_CONFIRM}/* CONFIRM ready */
+};
+
+static const UINT8 smp_master_confirm_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* CONFIRM */ { SMP_PROC_CONFIRM, SMP_SEND_RAND, SMP_STATE_RAND}
+};
+
+static const UINT8 smp_master_rand_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* RAND */ { SMP_PROC_RAND, SMP_GENERATE_COMPARE, SMP_STATE_RAND},
+/* KEY_READY*/ { SMP_PROC_COMPARE, SMP_SM_NO_ACTION, SMP_STATE_RAND}, /* Compare ready */
+/* ENC_REQ */ { SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING}
+};
+
+static const UINT8 smp_master_public_key_exchange_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* LOC_PUBL_KEY_CRTD */{ SMP_SEND_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* PAIR_PUBLIC_KEY */{ SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* BOTH_PUBL_KEYS_RCVD */{ SMP_HAVE_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+};
+
+static const UINT8 smp_master_sec_conn_phs1_start_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* SC_DHKEY_CMPLT */{ SMP_START_SEC_CONN_PHASE1, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* HAVE_LOC_NONCE */{ SMP_PROCESS_LOCAL_NONCE, SMP_SM_NO_ACTION, SMP_STATE_WAIT_COMMITMENT},
+/* TK_REQ */{ SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SMP_MODEL_SEC_CONN_PASSKEY_DISP model, passkey is sent up to display,*/
+/* It's time to start commitment calculation */
+/* KEY_READY */{ SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_KEYPR_NOTIF */{ SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_COMMITM */{ SMP_PROCESS_PAIRING_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+};
+
+static const UINT8 smp_master_wait_commitment_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* PAIR_COMMITM */{ SMP_PROCESS_PAIRING_COMMITMENT, SMP_SEND_RAND, SMP_STATE_WAIT_NONCE},
+/* PAIR_KEYPR_NOTIF */{ SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_COMMITMENT},
+};
+
+static const UINT8 smp_master_wait_nonce_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* peer nonce is received */
+/* RAND */{SMP_PROC_RAND, SMP_PROCESS_PEER_NONCE, SMP_STATE_SEC_CONN_PHS2_START},
+/* NC model, time to calculate number for NC */
+/* SC_CALC_NC */{SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER, SMP_SM_NO_ACTION, SMP_STATE_WAIT_NONCE},
+/* NC model, time to display calculated number for NC to the user */
+/* SC_DSPL_NC */{SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+};
+
+static const UINT8 smp_master_sec_conn_phs2_start_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* SC_PHASE1_CMPLT */{SMP_CALCULATE_LOCAL_DHKEY_CHECK, SMP_SEND_DHKEY_CHECK, SMP_STATE_WAIT_DHK_CHECK},
+};
+
+static const UINT8 smp_master_wait_dhk_check_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* PAIR_DHKEY_CHCK */{SMP_PROCESS_DHKEY_CHECK, SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_STATE_DHK_CHECK},
+};
+
+static const UINT8 smp_master_dhk_check_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* locally calculated peer dhkey check is ready -> compare it withs DHKey Check actually received from peer */
+/* SC_KEY_READY */{SMP_MATCH_DHKEY_CHECKS, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
+/* locally calculated peer dhkey check is ready -> calculate STK, go to sending */
+/* HCI LE Start Encryption command */
+/* ENC_REQ */{SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+};
+
+static const UINT8 smp_master_enc_pending_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* STK ready */
+/* KEY_READY */ { SMP_START_ENC, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+/* ENCRYPTED */ { SMP_CHECK_AUTH_REQ, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+/* BOND_REQ */ { SMP_KEY_DISTRIBUTE, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
+};
+static const UINT8 smp_master_bond_pending_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* ENC_INFO */ { SMP_PROC_ENC_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ID_INFO */ { SMP_PROC_ID_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* SIGN_INFO*/ { SMP_PROC_SRK_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* MASTER_ID*/ { SMP_PROC_MASTER_ID, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ID_ADDR */ { SMP_PROC_ID_ADDR, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* KEY_READY */{SMP_SEND_ENC_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING} /* LTK ready */
+};
+
+static const UINT8 smp_master_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* LOC_PUBL_KEY_CRTD */ {SMP_SET_LOCAL_OOB_KEYS, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA},
+/* HAVE_LOC_NONCE */ {SMP_SET_LOCAL_OOB_RAND_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
};
/************ SMP Slave FSM State/Event Indirection Table **************/
-static const UINT8 smp_sl_entry_map[][SMP_ST_MAX] =
-{
-/* state name: Idle Wait SecReq Pair Wait Confirm Init Enc Bond Rel
- AppRsp Pend ReqRsp Cfm Pend Pend Delay */
-/* PAIR_REQ */ { 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
-/* PAIR_RSP */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* CONFIRM */ { 0, 4, 0, 1, 1, 0, 0, 0, 0, 0 },
-/* INIT */ { 0, 0, 0, 0, 0, 1, 2, 0, 0, 0 },
-/* PAIR_FAIL*/ { 0, 0x81, 0x81, 0x81, 0x81,0x81, 0x81,0x81, 0, 0 },
-/* ENC_INFO */ { 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 },
-/* MASTER_ID*/ { 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
-/* ID_INFO */ { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
-/* ID_ADDR */ { 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 },
-/* SIGN_INFO*/ { 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
-/* SEC_REQ */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-
-/* KEY_READY*/ { 0, 3, 0, 3, 2, 2, 1, 2, 1, 0 },
-/* ENC_CMPL */ { 0, 0, 2, 0, 0, 0, 0, 3, 0, 0 },
-/* L2C_CONN */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* L2C_DISC */ { 0, 0x83, 0x83, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 2 },
-/* IO_RSP */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* SEC_GRANT*/ { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
-
-/* TK_REQ */ { 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 },
-/* AUTH_CMPL*/ { 0, 0x82, 0x82, 0x82, 0x82,0x82, 0x82,0x82, 0x82, 0 },
-/* ENC_REQ */ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
-/* BOND_REQ */ { 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 },
-/* DISCARD_SEC_REQ */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-/* RELEASE_DELAY */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
-/* RELEASE_DELAY_TOUT */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
-};
-
-static const UINT8 smp_sl_idle_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* L2C_CONN */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_ST_WAIT_APP_RSP},
-/* PAIR_REQ */ {SMP_PROC_PAIR_CMD, SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP}
-};
-
-static const UINT8 smp_sl_wait_app_rsp_table [][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* IO_RSP */ {SMP_PROC_IO_RSP, SMP_SM_NO_ACTION, SMP_ST_PAIR_REQ_RSP},
-/* SEC_GRANT */ {SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP},
-/* KEY_READY */ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_ST_WAIT_APP_RSP},/* TK ready */
-/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SM_NO_ACTION, SMP_ST_CONFIRM}
-};
-
-static const UINT8 smp_sl_sec_request_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* PAIR_REQ */{SMP_PROC_PAIR_CMD, SMP_SEND_PAIR_RSP, SMP_ST_PAIR_REQ_RSP},
-/* ENCRYPTED*/{SMP_ENC_CMPL, SMP_SM_NO_ACTION, SMP_ST_PAIR_REQ_RSP},
-};
-
-static const UINT8 smp_sl_pair_req_rsp_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SM_NO_ACTION, SMP_ST_CONFIRM},
-/* TK_REQ */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_ST_WAIT_APP_RSP},
-/* KEY_READY */{SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_ST_PAIR_REQ_RSP} /* TK/Confirm ready */
-
-};
-
-static const UINT8 smp_sl_wait_confirm_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SEND_CONFIRM, SMP_ST_CONFIRM},
-/* KEY_READY*/ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_ST_WAIT_CONFIRM}
-};
-static const UINT8 smp_sl_confirm_table [][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* INIT_EVT */{ SMP_PROC_INIT, SMP_GENERATE_COMPARE, SMP_ST_RAND},
-/* KEY_READY*/ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_ST_CONFIRM} /* TK/Confirm ready */
-};
-static const UINT8 smp_sl_init_table [][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* KEY_READY */ {SMP_PROC_COMPARE, SMP_SM_NO_ACTION, SMP_ST_RAND}, /* compare match */
-/* INIT_EVT */ {SMP_SEND_INIT, SMP_SM_NO_ACTION, SMP_ST_ENC_PENDING}
-};
-static const UINT8 smp_sl_enc_pending_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* ENC_REQ */ {SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_ST_ENC_PENDING},
-/* KEY_READY */ {SMP_SEND_LTK_REPLY, SMP_SM_NO_ACTION, SMP_ST_ENC_PENDING},/* STK ready */
-/* ENCRYPTED */ {SMP_CHECK_AUTH_REQ, SMP_SM_NO_ACTION, SMP_ST_ENC_PENDING},
-/* BOND_REQ */ {SMP_KEY_DISTRIBUTE, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING}
-};
-static const UINT8 smp_sl_bond_pending_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* KEY_READY */ {SMP_SEND_SECU_INFO, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING}, /* LTK ready */
-/* SIGN_INFO */ {SMP_PROC_SRK_INFO, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING}, /* rev SRK */
-/* ENC_INFO */ { SMP_PROC_ENC_INFO, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING},
-/* ID_INFO */ { SMP_PROC_ID_INFO, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING},
-/* MASTER_ID*/ { SMP_PROC_MASTER_ID, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING},
-/* ID_ADDR */ { SMP_PROC_ID_ADDR, SMP_SM_NO_ACTION, SMP_ST_BOND_PENDING}
-
-};
-
-static const UINT8 smp_sl_rel_delay_table[][SMP_SM_NUM_COLS] = {
-/* Event Action Next State */
-/* RELEASE_DELAY*/ {SMP_PROC_REL_DELAY, SMP_SM_NO_ACTION, SMP_ST_RELEASE_DELAY},
-/* RELEASE_DELAY_TOUT*/ {SMP_PROC_REL_DELAY_TOUT, SMP_SM_NO_ACTION, SMP_ST_IDLE}
-};
-
-static const tSMP_SM_TBL smp_state_table[][2] = {
- {smp_ma_idle_table, smp_sl_idle_table}, /* SMP_ST_IDLE*/
- {smp_ma_wait_app_rsp_table, smp_sl_wait_app_rsp_table}, /* SMP_ST_WAIT_APP_RSP */
- {NULL, smp_sl_sec_request_table}, /* SMP_ST_SEC_REQ_PENDING */
- {smp_ma_pair_req_rsp_table, smp_sl_pair_req_rsp_table}, /* SMP_ST_PAIR_REQ_RSP */
- {smp_ma_wait_confirm_table, smp_sl_wait_confirm_table}, /* SMP_ST_WAIT_CONFIRM */
- {smp_ma_confirm_table, smp_sl_confirm_table}, /* SMP_ST_CONFIRM */
- {smp_ma_init_table, smp_sl_init_table}, /* SMP_ST_RAND */
- {smp_ma_enc_pending_table, smp_sl_enc_pending_table}, /* SMP_ST_ENC_PENDING */
- {smp_ma_bond_pending_table, smp_sl_bond_pending_table}, /* SMP_ST_BOND_PENDING */
- {smp_ma_rel_delay_table, smp_sl_rel_delay_table} /* SMP_ST_RELEASE_DELAY */
-};
+static const UINT8 smp_slave_entry_map[][SMP_STATE_MAX] =
+{
+/* state name: Idle WaitApp SecReq Pair Wait Confirm Rand PublKey SCPhs1 Wait Wait SCPhs2 Wait DHKChk Enc Bond CrLocSc
+ Rsp Pend ReqRsp Cfm Exch Strt Cmtm Nonce Strt DHKChk Pend Pend OobData */
+/* PAIR_REQ */{ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* PAIR_RSP */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* CONFIRM */{ 0, 4, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* RAND */{ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
+/* PAIR_FAIL */{ 0, 0x81, 0x81, 0x81, 0x81,0x81, 0x81,0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0, 0 },
+/* ENC_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0 },
+/* MASTER_ID */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 },
+/* ID_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
+/* ID_ADDR */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 },
+/* SIGN_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
+/* SEC_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* PAIR_PUBLIC_KEY */{ 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* PAIR_DHKEY_CHCK */{ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0 },
+/* PAIR_KEYPR_NOTIF */{ 0, 9, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0 },
+/* PAIR_COMMITM */{ 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
+/* KEY_READY */{ 0, 3, 0, 3, 2, 2, 1, 0, 4, 0, 0, 0, 0, 0, 2, 1, 0 },
+/* ENC_CMPL */{ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 },
+/* L2C_CONN */{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* L2C_DISC */{ 0, 0x83, 0x83, 0x83, 0x83,0x83, 0x83,0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0 },
+/* IO_RSP */{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SEC_GRANT */{ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* TK_REQ */{ 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* AUTH_CMPL */{ 0, 0x82, 0x82, 0x82, 0x82,0x82, 0x82,0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0 },
+/* ENC_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 },
+/* BOND_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 },
+/* DISCARD_SEC_REQ */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* PUBL_KEY_EXCH_REQ */{ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* LOC_PUBL_KEY_CRTD */{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+/* BOTH_PUBL_KEYS_RCVD */{ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SC_DHKEY_CMPLT */{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* HAVE_LOC_NONCE */{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2 },
+/* SC_PHASE1_CMPLT */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
+/* SC_CALC_NC */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 },
+/* SC_DSPL_NC */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0 },
+/* SC_NC_OK */{ 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SC_2_DHCK_CHKS_PRES */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0 },
+/* SC_KEY_READY */{ 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 },
+/* KEYPR_NOTIF */{ 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* SC_OOB_DATA */{ 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+/* CR_LOC_SC_OOB_DATA */{ 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+static const UINT8 smp_slave_idle_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* L2C_CONN */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* PAIR_REQ */ {SMP_PROC_PAIR_CMD, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP}
+/* CR_LOC_SC_OOB_DATA */ ,{SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA}
+};
+
+static const UINT8 smp_slave_wait_for_app_response_table [][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* IO_RSP */ {SMP_PROC_IO_RSP, SMP_FAST_CONN_PARAM, SMP_STATE_PAIR_REQ_RSP},
+/* SEC_GRANT */ {SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+
+ /* TK ready */
+/* KEY_READY */ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_CONFIRM}
+/* DHKey Check from master is received before phase 1 is completed - race */
+/* PAIR_DHKEY_CHCK */,{SMP_PROCESS_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* user confirms NC 'OK', i.e. phase 1 is completed */
+/* SC_NC_OK */ {SMP_MOVE_TO_SEC_CONN_PHASE2, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS2_START},
+/* user-provided passkey is rcvd */
+/* SC_KEY_READY */ {SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_COMMITM */ {SMP_PROCESS_PAIRING_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* PAIR_KEYPR_NOTIF */ {SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+/* KEYPR_NOTIF */ {SMP_SEND_KEYPRESS_NOTIFICATION, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SC_OOB_DATA */ {SMP_SEND_PAIR_RSP, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
+};
+
+static const UINT8 smp_slave_sec_request_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* PAIR_REQ */{SMP_PROC_PAIR_CMD, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
+/* ENCRYPTED*/{SMP_ENC_CMPL, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
+};
+
+static const UINT8 smp_slave_pair_request_response_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SM_NO_ACTION, SMP_STATE_CONFIRM},
+/* TK_REQ */ {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+
+ /* TK/Confirm ready */
+/* KEY_READY */{SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP}
+/* PUBL_KEY_EXCH_REQ */,{ SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* PAIR_PUBLIC_KEY */ { SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
+};
+
+static const UINT8 smp_slave_wait_confirm_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* CONFIRM */ {SMP_PROC_CONFIRM, SMP_SEND_CONFIRM, SMP_STATE_CONFIRM},
+/* KEY_READY*/ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_STATE_WAIT_CONFIRM}
+};
+
+static const UINT8 smp_slave_confirm_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* RAND */ {SMP_PROC_RAND, SMP_GENERATE_COMPARE, SMP_STATE_RAND},
+
+ /* TK/Confirm ready */
+/* KEY_READY*/ {SMP_PROC_SL_KEY, SMP_SM_NO_ACTION, SMP_STATE_CONFIRM}
+};
+
+static const UINT8 smp_slave_rand_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* KEY_READY */ {SMP_PROC_COMPARE, SMP_SM_NO_ACTION, SMP_STATE_RAND}, /* compare match */
+/* RAND */ {SMP_SEND_RAND, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING}
+};
+
+static const UINT8 smp_slave_public_key_exch_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* LOC_PUBL_KEY_CRTD */{ SMP_WAIT_FOR_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* PAIR_PUBLIC_KEY */{ SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* BOTH_PUBL_KEYS_RCVD */{ SMP_HAVE_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+};
+
+static const UINT8 smp_slave_sec_conn_phs1_start_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* SC_DHKEY_CMPLT */{ SMP_START_SEC_CONN_PHASE1, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* HAVE_LOC_NONCE */{ SMP_PROCESS_LOCAL_NONCE,SMP_SM_NO_ACTION, SMP_STATE_WAIT_COMMITMENT},
+/* TK_REQ */{ SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SMP_MODEL_SEC_CONN_PASSKEY_DISP model, passkey is sent up to display, it's time to start */
+/* commitment calculation */
+/* KEY_READY */{ SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_KEYPR_NOTIF */{ SMP_PROCESS_KEYPRESS_NOTIFICATION,SMP_SEND_APP_CBACK, SMP_STATE_SEC_CONN_PHS1_START},
+};
+
+static const UINT8 smp_slave_wait_commitment_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* PAIR_COMMITM */{SMP_PROCESS_PAIRING_COMMITMENT, SMP_SEND_COMMITMENT, SMP_STATE_WAIT_NONCE},
+/* PAIR_KEYPR_NOTIF */{SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_COMMITMENT},
+};
+
+static const UINT8 smp_slave_wait_nonce_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* peer nonce is received */
+/* RAND */{SMP_PROC_RAND, SMP_PROCESS_PEER_NONCE, SMP_STATE_SEC_CONN_PHS2_START},
+/* NC model, time to calculate number for NC */
+/* SC_CALC_NC */{SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER, SMP_SM_NO_ACTION, SMP_STATE_WAIT_NONCE},
+/* NC model, time to display calculated number for NC to the user */
+/* SC_DSPL_NC */{SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+};
+
+static const UINT8 smp_slave_sec_conn_phs2_start_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* SC_PHASE1_CMPLT */{SMP_CALCULATE_LOCAL_DHKEY_CHECK, SMP_PH2_DHKEY_CHECKS_ARE_PRESENT, SMP_STATE_WAIT_DHK_CHECK},
+/* DHKey Check from master is received before slave DHKey calculation is completed - race */
+/* PAIR_DHKEY_CHCK */{SMP_PROCESS_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS2_START},
+};
+
+static const UINT8 smp_slave_wait_dhk_check_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* PAIR_DHKEY_CHCK */{SMP_PROCESS_DHKEY_CHECK, SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_STATE_DHK_CHECK},
+/* DHKey Check from master was received before slave came to this state */
+/* SC_2_DHCK_CHKS_PRES */{SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
+};
+
+static const UINT8 smp_slave_dhk_check_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+
+/* locally calculated peer dhkey check is ready -> compare it withs DHKey Check */
+/* actually received from peer */
+/* SC_KEY_READY */{SMP_MATCH_DHKEY_CHECKS, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
-typedef const UINT8 (*tSMP_ENTRY_TBL)[SMP_ST_MAX];
-static const tSMP_ENTRY_TBL smp_entry_table[] ={
- smp_ma_entry_map,
- smp_sl_entry_map
+/* dhkey checks match -> send local dhkey check to master, go to wait for HCI LE */
+/* Long Term Key Request Event */
+/* PAIR_DHKEY_CHCK */{SMP_SEND_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+};
+
+static const UINT8 smp_slave_enc_pending_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* ENC_REQ */ {SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+
+ /* STK ready */
+/* KEY_READY */ {SMP_SEND_LTK_REPLY, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+/* ENCRYPTED */ {SMP_CHECK_AUTH_REQ, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+/* BOND_REQ */ {SMP_KEY_DISTRIBUTE, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
+};
+static const UINT8 smp_slave_bond_pending_table[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+
+ /* LTK ready */
+/* KEY_READY */{ SMP_SEND_ENC_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+
+ /* rev SRK */
+/* SIGN_INFO */{ SMP_PROC_SRK_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ENC_INFO */ { SMP_PROC_ENC_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ID_INFO */ { SMP_PROC_ID_INFO, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* MASTER_ID*/ { SMP_PROC_MASTER_ID, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ID_ADDR */ { SMP_PROC_ID_ADDR, SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
+
+};
+
+static const UINT8 smp_slave_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS] =
+{
+/* Event Action Next State */
+/* LOC_PUBL_KEY_CRTD */ {SMP_SET_LOCAL_OOB_KEYS, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA},
+/* HAVE_LOC_NONCE */ {SMP_SET_LOCAL_OOB_RAND_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
+};
+
+static const tSMP_SM_TBL smp_state_table[][2] =
+{
+ /* SMP_STATE_IDLE */
+ {smp_master_idle_table, smp_slave_idle_table},
+
+ /* SMP_STATE_WAIT_APP_RSP */
+ {smp_master_wait_for_app_response_table, smp_slave_wait_for_app_response_table},
+
+ /* SMP_STATE_SEC_REQ_PENDING */
+ {NULL, smp_slave_sec_request_table},
+
+ /* SMP_STATE_PAIR_REQ_RSP */
+ {smp_master_pair_request_response_table, smp_slave_pair_request_response_table},
+
+ /* SMP_STATE_WAIT_CONFIRM */
+ {smp_master_wait_for_confirm_table, smp_slave_wait_confirm_table},
+
+ /* SMP_STATE_CONFIRM */
+ {smp_master_confirm_table, smp_slave_confirm_table},
+
+ /* SMP_STATE_RAND */
+ {smp_master_rand_table, smp_slave_rand_table},
+
+ /* SMP_STATE_PUBLIC_KEY_EXCH */
+ {smp_master_public_key_exchange_table,smp_slave_public_key_exch_table},
+
+ /* SMP_STATE_SEC_CONN_PHS1_START */
+ {smp_master_sec_conn_phs1_start_table, smp_slave_sec_conn_phs1_start_table},
+
+ /* SMP_STATE_WAIT_COMMITMENT */
+ {smp_master_wait_commitment_table, smp_slave_wait_commitment_table},
+
+ /* SMP_STATE_WAIT_NONCE */
+ {smp_master_wait_nonce_table, smp_slave_wait_nonce_table},
+
+ /* SMP_STATE_SEC_CONN_PHS2_START */
+ {smp_master_sec_conn_phs2_start_table, smp_slave_sec_conn_phs2_start_table},
+
+ /* SMP_STATE_WAIT_DHK_CHECK */
+ {smp_master_wait_dhk_check_table, smp_slave_wait_dhk_check_table},
+
+ /* SMP_STATE_DHK_CHECK */
+ {smp_master_dhk_check_table, smp_slave_dhk_check_table},
+
+ /* SMP_STATE_ENCRYPTION_PENDING */
+ {smp_master_enc_pending_table, smp_slave_enc_pending_table},
+
+ /* SMP_STATE_BOND_PENDING */
+ {smp_master_bond_pending_table, smp_slave_bond_pending_table},
+
+ /* SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA */
+ {smp_master_create_local_sec_conn_oob_data, smp_slave_create_local_sec_conn_oob_data}
+};
+
+typedef const UINT8 (*tSMP_ENTRY_TBL)[SMP_STATE_MAX];
+static const tSMP_ENTRY_TBL smp_entry_table[] =
+{
+ smp_master_entry_map,
+ smp_slave_entry_map
};
#if SMP_DYNAMIC_MEMORY == FALSE
#endif
#define SMP_ALL_TBL_MASK 0x80
-
/*******************************************************************************
** Function smp_set_state
** Returns None
*******************************************************************************/
void smp_set_state(tSMP_STATE state)
{
- if (state < SMP_ST_MAX)
+ if (state < SMP_STATE_MAX)
{
SMP_TRACE_DEBUG( "State change: %s(%d) ==> %s(%d)",
smp_get_state_name(smp_cb.state), smp_cb.state,
return smp_cb.state;
}
-
/*******************************************************************************
**
** Function smp_sm_event
tSMP_ENTRY_TBL entry_table = smp_entry_table[p_cb->role];
SMP_TRACE_EVENT("main smp_sm_event");
- if (curr_state >= SMP_ST_MAX)
+ if (curr_state >= SMP_STATE_MAX)
{
SMP_TRACE_DEBUG( "Invalid state: %d", curr_state) ;
return;
/* lookup entry /w event & curr_state */
/* If entry is ignore, return.
* Otherwise, get state table (according to curr_state or all_state) */
- if ((event < SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE ))
+ if ((event <= SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE ))
{
if (entry & SMP_ALL_TBL_MASK)
{
else
{
SMP_TRACE_DEBUG( "Ignore event [%s (%d)] in state [%s (%d)]",
- smp_get_event_name(event), event, smp_get_state_name(curr_state), curr_state);
+ smp_get_event_name(event), event, smp_get_state_name(curr_state),
+ curr_state);
return;
}
SMP_TRACE_DEBUG( "result state = %s", smp_get_state_name( p_cb->state ) ) ;
}
-
/*******************************************************************************
** Function smp_get_state_name
** Returns The smp state name.
*******************************************************************************/
const char * smp_get_state_name(tSMP_STATE state)
{
- const char * p_str = smp_state_name[SMP_ST_MAX];
+ const char *p_str = smp_state_name[SMP_STATE_MAX];
- if (state < SMP_ST_MAX)
+ if (state < SMP_STATE_MAX)
{
p_str = smp_state_name[state];
}
return p_str;
}
+
/*******************************************************************************
** Function smp_get_event_name
** Returns The smp event name.
*******************************************************************************/
const char * smp_get_event_name(tSMP_EVENT event)
{
- const char * p_str = smp_event_name[SMP_MAX_EVT - 1];
+ const char *p_str = smp_event_name[SMP_MAX_EVT];
- if (event < SMP_MAX_EVT)
+ if (event <= SMP_MAX_EVT)
{
p_str = smp_event_name[event- 1];
}
return p_str;
}
+
#endif
* See the License for the specific language governing permissions and
* limitations under the License.
*
- ******************************************************************************/
+******************************************************************************/
/******************************************************************************
*
- * This file contains functions for the SMP L2Cap utility functions
+ * This file contains functions for the SMP L2CAP utility functions
*
******************************************************************************/
#include "bt_target.h"
#include "l2c_int.h"
#include "smp_int.h"
#include "device/include/controller.h"
-
+#include "btm_int.h"
#define SMP_PAIRING_REQ_SIZE 7
#define SMP_CONFIRM_CMD_SIZE (BT_OCTET16_LEN + 1)
+#define SMP_RAND_CMD_SIZE (BT_OCTET16_LEN + 1)
#define SMP_INIT_CMD_SIZE (BT_OCTET16_LEN + 1)
#define SMP_ENC_INFO_SIZE (BT_OCTET16_LEN + 1)
#define SMP_MASTER_ID_SIZE (BT_OCTET8_LEN + 2 + 1)
#define SMP_ID_ADDR_SIZE (BD_ADDR_LEN + 1 + 1)
#define SMP_SIGN_INFO_SIZE (BT_OCTET16_LEN + 1)
#define SMP_PAIR_FAIL_SIZE 2
+#define SMP_SECURITY_REQUEST_SIZE 2
+#define SMP_PAIR_PUBL_KEY_SIZE (1 /* opcode */ + (2*BT_OCTET32_LEN))
+#define SMP_PAIR_COMMITM_SIZE (1 /* opcode */ + BT_OCTET16_LEN /*Commitment*/)
+#define SMP_PAIR_DHKEY_CHECK_SIZE (1 /* opcode */ + BT_OCTET16_LEN /*DHKey Check*/)
+#define SMP_PAIR_KEYPR_NOTIF_SIZE (1 /* opcode */ + 1 /*Notif Type*/)
+
+/* SMP command sizes per spec */
+static const UINT8 smp_cmd_size_per_spec[] =
+{
+ 0,
+ SMP_PAIRING_REQ_SIZE, /* 0x01: pairing request */
+ SMP_PAIRING_REQ_SIZE, /* 0x02: pairing response */
+ SMP_CONFIRM_CMD_SIZE, /* 0x03: pairing confirm */
+ SMP_RAND_CMD_SIZE, /* 0x04: pairing random */
+ SMP_PAIR_FAIL_SIZE, /* 0x05: pairing failed */
+ SMP_ENC_INFO_SIZE, /* 0x06: encryption information */
+ SMP_MASTER_ID_SIZE, /* 0x07: master identification */
+ SMP_ID_INFO_SIZE, /* 0x08: identity information */
+ SMP_ID_ADDR_SIZE, /* 0x09: identity address information */
+ SMP_SIGN_INFO_SIZE, /* 0x0A: signing information */
+ SMP_SECURITY_REQUEST_SIZE, /* 0x0B: security request */
+ SMP_PAIR_PUBL_KEY_SIZE, /* 0x0C: pairing public key */
+ SMP_PAIR_DHKEY_CHECK_SIZE, /* 0x0D: pairing dhkey check */
+ SMP_PAIR_KEYPR_NOTIF_SIZE, /* 0x0E: pairing keypress notification */
+ SMP_PAIR_COMMITM_SIZE /* 0x0F: pairing commitment */
+};
+static BOOLEAN smp_parameter_unconditionally_valid(tSMP_CB *p_cb);
+static BOOLEAN smp_parameter_unconditionally_invalid(tSMP_CB *p_cb);
+
+/* type for SMP command length validation functions */
+typedef BOOLEAN (*tSMP_CMD_LEN_VALID)(tSMP_CB *p_cb);
+
+static BOOLEAN smp_command_has_valid_fixed_length(tSMP_CB *p_cb);
+
+static const tSMP_CMD_LEN_VALID smp_cmd_len_is_valid[] =
+{
+ smp_parameter_unconditionally_invalid,
+ smp_command_has_valid_fixed_length, /* 0x01: pairing request */
+ smp_command_has_valid_fixed_length, /* 0x02: pairing response */
+ smp_command_has_valid_fixed_length, /* 0x03: pairing confirm */
+ smp_command_has_valid_fixed_length, /* 0x04: pairing random */
+ smp_command_has_valid_fixed_length, /* 0x05: pairing failed */
+ smp_command_has_valid_fixed_length, /* 0x06: encryption information */
+ smp_command_has_valid_fixed_length, /* 0x07: master identification */
+ smp_command_has_valid_fixed_length, /* 0x08: identity information */
+ smp_command_has_valid_fixed_length, /* 0x09: identity address information */
+ smp_command_has_valid_fixed_length, /* 0x0A: signing information */
+ smp_command_has_valid_fixed_length, /* 0x0B: security request */
+ smp_command_has_valid_fixed_length, /* 0x0C: pairing public key */
+ smp_command_has_valid_fixed_length, /* 0x0D: pairing dhkey check */
+ smp_command_has_valid_fixed_length, /* 0x0E: pairing keypress notification */
+ smp_command_has_valid_fixed_length /* 0x0F: pairing commitment */
+};
+
+/* type for SMP command parameter ranges validation functions */
+typedef BOOLEAN (*tSMP_CMD_PARAM_RANGES_VALID)(tSMP_CB *p_cb);
+
+static BOOLEAN smp_pairing_request_response_parameters_are_valid(tSMP_CB *p_cb);
+static BOOLEAN smp_pairing_keypress_notification_is_valid(tSMP_CB *p_cb);
+
+static const tSMP_CMD_PARAM_RANGES_VALID smp_cmd_param_ranges_are_valid[] =
+{
+ smp_parameter_unconditionally_invalid,
+ smp_pairing_request_response_parameters_are_valid, /* 0x01: pairing request */
+ smp_pairing_request_response_parameters_are_valid, /* 0x02: pairing response */
+ smp_parameter_unconditionally_valid, /* 0x03: pairing confirm */
+ smp_parameter_unconditionally_valid, /* 0x04: pairing random */
+ smp_parameter_unconditionally_valid, /* 0x05: pairing failed */
+ smp_parameter_unconditionally_valid, /* 0x06: encryption information */
+ smp_parameter_unconditionally_valid, /* 0x07: master identification */
+ smp_parameter_unconditionally_valid, /* 0x08: identity information */
+ smp_parameter_unconditionally_valid, /* 0x09: identity address information */
+ smp_parameter_unconditionally_valid, /* 0x0A: signing information */
+ smp_parameter_unconditionally_valid, /* 0x0B: security request */
+ smp_parameter_unconditionally_valid, /* 0x0C: pairing public key */
+ smp_parameter_unconditionally_valid, /* 0x0D: pairing dhkey check */
+ smp_pairing_keypress_notification_is_valid, /* 0x0E: pairing keypress notification */
+ smp_parameter_unconditionally_valid /* 0x0F: pairing commitment */
+};
/* type for action functions */
typedef BT_HDR * (*tSMP_CMD_ACT)(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_pairing_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_confirm_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_rand_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_encrypt_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_signing_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_master_id_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_id_addr_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-
-const tSMP_CMD_ACT smp_cmd_build_act[] =
+static BT_HDR *smp_build_pairing_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_confirm_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_rand_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_encrypt_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_signing_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_master_id_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_id_addr_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pair_public_key_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pairing_commitment_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pair_dhkey_check_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pairing_keypress_notification_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+
+static const tSMP_CMD_ACT smp_cmd_build_act[] =
{
NULL,
- smp_build_pairing_cmd, /* 0x01: pairing request */
- smp_build_pairing_cmd, /* 0x02: pairing response */
- smp_build_confirm_cmd, /* 0x03: pairing confirm */
- smp_build_rand_cmd, /* 0x04: pairing initializer request */
- smp_build_pairing_fail, /* 0x05: pairing failure */
- smp_build_encrypt_info_cmd, /* 0x06: security information command */
- smp_build_master_id_cmd, /* 0x07: master identity command */
- smp_build_identity_info_cmd, /* 0x08: identity information command */
- smp_build_id_addr_cmd, /* 0x09: signing information */
- smp_build_signing_info_cmd, /* 0x0A: signing information */
- smp_build_security_request /* 0x0B: security request */
+ smp_build_pairing_cmd, /* 0x01: pairing request */
+ smp_build_pairing_cmd, /* 0x02: pairing response */
+ smp_build_confirm_cmd, /* 0x03: pairing confirm */
+ smp_build_rand_cmd, /* 0x04: pairing random */
+ smp_build_pairing_fail, /* 0x05: pairing failure */
+ smp_build_encrypt_info_cmd, /* 0x06: encryption information */
+ smp_build_master_id_cmd, /* 0x07: master identification */
+ smp_build_identity_info_cmd, /* 0x08: identity information */
+ smp_build_id_addr_cmd, /* 0x09: identity address information */
+ smp_build_signing_info_cmd, /* 0x0A: signing information */
+ smp_build_security_request, /* 0x0B: security request */
+ smp_build_pair_public_key_cmd, /* 0x0C: pairing public key */
+ smp_build_pair_dhkey_check_cmd, /* 0x0D: pairing DHKey check */
+ smp_build_pairing_keypress_notification_cmd, /* 0x0E: pairing keypress notification */
+ smp_build_pairing_commitment_cmd /* 0x0F: pairing commitment */
+};
+
+static const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
+{
+ /* display only */ /* Display Yes/No */ /* keyboard only */
+ /* No Input/Output */ /* keyboard display */
+
+ /* initiator */
+ /* model = tbl[peer_io_caps][loc_io_caps] */
+ /* Display Only */
+ {{SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY},
+
+ /* Display Yes/No */
+ {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY},
+
+ /* Keyboard only */
+ {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF},
+
+ /* No Input No Output */
+ {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY},
+
+ /* keyboard display */
+ {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}},
+
+ /* responder */
+ /* model = tbl[loc_io_caps][peer_io_caps] */
+ /* Display Only */
+ {{SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF},
+
+ /* Display Yes/No */
+ {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF},
+
+ /* keyboard only */
+ {SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY},
+
+ /* No Input No Output */
+ {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY},
+
+ /* keyboard display */
+ {SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_KEY_NOTIF,
+ SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}}
+};
+
+static const UINT8 smp_association_table_sc[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
+{
+ /* display only */ /* Display Yes/No */ /* keyboard only */
+ /* No InputOutput */ /* keyboard display */
+
+ /* initiator */
+ /* model = tbl[peer_io_caps][loc_io_caps] */
+
+ /* Display Only */
+ {{SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_ENT},
+
+ /* Display Yes/No */
+ {SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP},
+
+ /* keyboard only */
+ {SMP_MODEL_SEC_CONN_PASSKEY_DISP, SMP_MODEL_SEC_CONN_PASSKEY_DISP, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_DISP},
+
+ /* No Input No Output */
+ {SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS},
+
+ /* keyboard display */
+ {SMP_MODEL_SEC_CONN_PASSKEY_DISP, SMP_MODEL_SEC_CONN_NUM_COMP, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP}},
+
+ /* responder */
+ /* model = tbl[loc_io_caps][peer_io_caps] */
+
+ /* Display Only */
+ {{SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_DISP,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_DISP},
+
+ /* Display Yes/No */
+ {SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP, SMP_MODEL_SEC_CONN_PASSKEY_DISP,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP},
+
+ /* keyboard only */
+ {SMP_MODEL_SEC_CONN_PASSKEY_ENT, SMP_MODEL_SEC_CONN_PASSKEY_ENT, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_ENT},
+
+ /* No Input No Output */
+ {SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS},
+
+ /* keyboard display */
+ {SMP_MODEL_SEC_CONN_PASSKEY_ENT, SMP_MODEL_SEC_CONN_NUM_COMP, SMP_MODEL_SEC_CONN_PASSKEY_DISP,
+ SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP}}
};
+
+static tSMP_ASSO_MODEL smp_select_legacy_association_model(tSMP_CB *p_cb);
+static tSMP_ASSO_MODEL smp_select_association_model_secure_connections(tSMP_CB *p_cb);
+
/*******************************************************************************
**
** Function smp_send_msg_to_L2CAP
*******************************************************************************/
BOOLEAN smp_send_msg_to_L2CAP(BD_ADDR rem_bda, BT_HDR *p_toL2CAP)
{
- UINT16 l2cap_ret;
+ UINT16 l2cap_ret;
+ UINT16 fixed_cid = L2CAP_SMP_CID;
+
+ if (smp_cb.smp_over_br)
+ {
+ fixed_cid = L2CAP_SMP_BR_CID;
+ }
- SMP_TRACE_EVENT("smp_send_msg_to_L2CAP");
+ SMP_TRACE_EVENT("%s", __FUNCTION__);
+ smp_cb.total_tx_unacked += 1;
- if ((l2cap_ret = L2CA_SendFixedChnlData (L2CAP_SMP_CID, rem_bda, p_toL2CAP)) == L2CAP_DW_FAILED)
+ if ((l2cap_ret = L2CA_SendFixedChnlData (fixed_cid, rem_bda, p_toL2CAP)) == L2CAP_DW_FAILED)
{
+ smp_cb.total_tx_unacked -= 1;
SMP_TRACE_ERROR("SMP failed to pass msg:0x%0x to L2CAP",
*((UINT8 *)(p_toL2CAP + 1) + p_toL2CAP->offset));
- GKI_freebuf(p_toL2CAP);
return FALSE;
}
else
- {
return TRUE;
- }
}
+
/*******************************************************************************
**
** Function smp_send_cmd
BOOLEAN sent = FALSE;
UINT8 failure = SMP_PAIR_INTERNAL_ERR;
SMP_TRACE_EVENT("smp_send_cmd on l2cap cmd_code=0x%x", cmd_code);
- if ( cmd_code < SMP_OPCODE_MAX &&
+ if ( cmd_code <= (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */) &&
smp_cmd_build_act[cmd_code] != NULL)
{
p_buf = (*smp_cmd_build_act[cmd_code])(cmd_code, p_cb);
if (!sent)
{
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ if (p_cb->smp_over_br)
+ {
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &failure);
+ }
+ else
+ {
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+ }
}
return sent;
}
-
-
/*******************************************************************************
**
** Function smp_rsp_timeout
UINT8 failure = SMP_RSP_TIMEOUT;
UNUSED(p_tle);
- SMP_TRACE_EVENT("smp_rsp_timeout state:%d", p_cb->state);
+ SMP_TRACE_EVENT("%s state:%d br_state:%d", __FUNCTION__, p_cb->state, p_cb->br_state);
- if (smp_get_state() == SMP_ST_RELEASE_DELAY)
+ if (p_cb->smp_over_br)
{
- smp_sm_event(p_cb, SMP_RELEASE_DELAY_TOUT_EVT, NULL);
+ smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &failure);
}
else
{
{
BT_HDR *p_buf = NULL ;
UINT8 *p;
+
SMP_TRACE_EVENT("smp_build_pairing_cmd");
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIRING_REQ_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
UINT8_TO_STREAM (p, cmd_code);
- UINT8_TO_STREAM (p, p_cb->loc_io_caps);
+ UINT8_TO_STREAM (p, p_cb->local_io_capability);
UINT8_TO_STREAM (p, p_cb->loc_oob_flag);
UINT8_TO_STREAM (p, p_cb->loc_auth_req);
UINT8_TO_STREAM (p, p_cb->loc_enc_size);
- UINT8_TO_STREAM (p, p_cb->loc_i_key);
- UINT8_TO_STREAM (p, p_cb->loc_r_key);
+ UINT8_TO_STREAM (p, p_cb->local_i_key);
+ UINT8_TO_STREAM (p, p_cb->local_r_key);
p_buf->offset = L2CAP_MIN_OFFSET;
/* 1B ERR_RSP op code + 1B cmd_op_code + 2B handle + 1B status */
**
** Function smp_build_rand_cmd
**
-** Description Build Initializer command.
+** Description Build Random command.
**
*******************************************************************************/
static BT_HDR * smp_build_rand_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
UINT8 *p;
UNUSED(cmd_code);
- SMP_TRACE_EVENT("smp_build_rand_cmd");
- if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_INIT_CMD_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+ SMP_TRACE_EVENT("%s", __func__);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_RAND_CMD_SIZE + L2CAP_MIN_OFFSET))
+ != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
- UINT8_TO_STREAM (p, SMP_OPCODE_INIT);
+ UINT8_TO_STREAM (p, SMP_OPCODE_RAND);
ARRAY_TO_STREAM (p, p_cb->rand, BT_OCTET16_LEN);
p_buf->offset = L2CAP_MIN_OFFSET;
- p_buf->len = SMP_INIT_CMD_SIZE;
+ p_buf->len = SMP_RAND_CMD_SIZE;
}
return p_buf;
return p_buf;
}
+
/*******************************************************************************
**
** Function smp_build_master_id_cmd
UINT8 *p;
UNUSED(cmd_code);
- SMP_TRACE_EVENT("smp_build_master_id_cmd ");
+ SMP_TRACE_EVENT("%s", __func__);
+
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_MASTER_ID_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
return p_buf;
}
+
/*******************************************************************************
**
** Function smp_build_identity_info_cmd
return p_buf;
}
+
/*******************************************************************************
**
** Function smp_build_id_addr_cmd
*******************************************************************************/
static BT_HDR * smp_build_id_addr_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
{
- BT_HDR *p_buf = NULL ;
- UINT8 *p;
+ BT_HDR *p_buf = NULL;
+ UINT8 *p;
+
UNUSED(cmd_code);
UNUSED(p_cb);
-
SMP_TRACE_EVENT("smp_build_id_addr_cmd");
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_ID_ADDR_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
UINT8_TO_STREAM (p, SMP_OPCODE_ID_ADDR);
- UINT8_TO_STREAM (p, 0); /* TODO: update with local address type */
+ UINT8_TO_STREAM (p, 0);
BDADDR_TO_STREAM (p, controller_get_interface()->get_address()->address);
p_buf->offset = L2CAP_MIN_OFFSET;
return p_buf;
}
+
/*******************************************************************************
**
** Function smp_build_pairing_fail
UINT8 *p;
UNUSED(cmd_code);
- SMP_TRACE_EVENT("smp_build_pairing_fail");
+ SMP_TRACE_EVENT("%s", __func__);
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIR_FAIL_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
return p_buf;
}
+
/*******************************************************************************
**
** Function smp_build_security_request
** Description Build security request command.
**
*******************************************************************************/
-static BT_HDR * smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb)
+static BT_HDR *smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb)
{
BT_HDR *p_buf = NULL ;
UINT8 *p;
UNUSED(cmd_code);
- SMP_TRACE_EVENT("smp_build_security_request");
-
+ SMP_TRACE_EVENT("%s", __func__);
if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + 2 + L2CAP_MIN_OFFSET)) != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
UINT8_TO_STREAM (p, p_cb->loc_auth_req);
p_buf->offset = L2CAP_MIN_OFFSET;
- p_buf->len = 2;
+ p_buf->len = SMP_SECURITY_REQUEST_SIZE;
SMP_TRACE_EVENT("opcode=%d auth_req=0x%x",SMP_OPCODE_SEC_REQ, p_cb->loc_auth_req );
}
/*******************************************************************************
**
+** Function smp_build_pair_public_key_cmd
+**
+** Description Build pairing public key command.
+**
+*******************************************************************************/
+static BT_HDR *smp_build_pair_public_key_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
+{
+ BT_HDR *p_buf = NULL ;
+ UINT8 *p;
+ UINT8 publ_key[2*BT_OCTET32_LEN];
+ UINT8 *p_publ_key = publ_key;
+ UNUSED(cmd_code);
+
+ SMP_TRACE_EVENT("%s", __FUNCTION__);
+
+ memcpy(p_publ_key, p_cb->loc_publ_key.x, BT_OCTET32_LEN);
+ memcpy(p_publ_key + BT_OCTET32_LEN, p_cb->loc_publ_key.y, BT_OCTET32_LEN);
+
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) +
+ SMP_PAIR_PUBL_KEY_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+ {
+ p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+ UINT8_TO_STREAM (p, SMP_OPCODE_PAIR_PUBLIC_KEY);
+ ARRAY_TO_STREAM (p, p_publ_key, 2*BT_OCTET32_LEN);
+
+ p_buf->offset = L2CAP_MIN_OFFSET;
+ p_buf->len = SMP_PAIR_PUBL_KEY_SIZE;
+ }
+
+ return p_buf;
+}
+
+/*******************************************************************************
+**
+** Function smp_build_pairing_commitment_cmd
+**
+** Description Build pairing commitment command.
+**
+*******************************************************************************/
+static BT_HDR *smp_build_pairing_commitment_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
+{
+ BT_HDR *p_buf = NULL;
+ UINT8 *p;
+ UNUSED(cmd_code);
+
+ SMP_TRACE_EVENT("%s", __func__);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIR_COMMITM_SIZE + L2CAP_MIN_OFFSET))
+ != NULL)
+ {
+ p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+ UINT8_TO_STREAM (p, SMP_OPCODE_CONFIRM);
+ ARRAY_TO_STREAM (p, p_cb->commitment, BT_OCTET16_LEN);
+
+ p_buf->offset = L2CAP_MIN_OFFSET;
+ p_buf->len = SMP_PAIR_COMMITM_SIZE;
+ }
+
+ return p_buf;
+}
+
+/*******************************************************************************
+**
+** Function smp_build_pair_dhkey_check_cmd
+**
+** Description Build pairing DHKey check command.
+**
+*******************************************************************************/
+static BT_HDR *smp_build_pair_dhkey_check_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
+{
+ BT_HDR *p_buf = NULL;
+ UINT8 *p;
+ UNUSED(cmd_code);
+
+ SMP_TRACE_EVENT("%s", __FUNCTION__);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) +
+ SMP_PAIR_DHKEY_CHECK_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+ {
+ p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+ UINT8_TO_STREAM (p, SMP_OPCODE_PAIR_DHKEY_CHECK);
+ ARRAY_TO_STREAM (p, p_cb->dhkey_check, BT_OCTET16_LEN);
+
+ p_buf->offset = L2CAP_MIN_OFFSET;
+ p_buf->len = SMP_PAIR_DHKEY_CHECK_SIZE;
+ }
+
+ return p_buf;
+}
+
+/*******************************************************************************
+**
+** Function smp_build_pairing_keypress_notification_cmd
+**
+** Description Build keypress notification command.
+**
+*******************************************************************************/
+static BT_HDR * smp_build_pairing_keypress_notification_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
+{
+ BT_HDR *p_buf = NULL ;
+ UINT8 *p;
+ UNUSED(cmd_code);
+
+ SMP_TRACE_EVENT("%s", __FUNCTION__);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR)\
+ + SMP_PAIR_KEYPR_NOTIF_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+ {
+ p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+ UINT8_TO_STREAM (p, SMP_OPCODE_PAIR_KEYPR_NOTIF);
+ UINT8_TO_STREAM (p, p_cb->local_keypress_notification);
+
+ p_buf->offset = L2CAP_MIN_OFFSET;
+ p_buf->len = SMP_PAIR_KEYPR_NOTIF_SIZE;
+ }
+
+ return p_buf;
+}
+
+/*******************************************************************************
+**
** Function smp_convert_string_to_tk
**
** Description This function is called to convert a 6 to 16 digits numeric
}
return;
}
+
/*******************************************************************************
**
** Function smp_xor_128
}
}
-
/*******************************************************************************
**
** Function smp_cb_cleanup
UINT8 trace_level = p_cb->trace_level;
SMP_TRACE_EVENT("smp_cb_cleanup");
+
memset(p_cb, 0, sizeof(tSMP_CB));
p_cb->p_callback = p_callback;
p_cb->trace_level = trace_level;
}
+
+/*******************************************************************************
+**
+** Function smp_remove_fixed_channel
+**
+** Description This function is called to remove the fixed channel
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_remove_fixed_channel(tSMP_CB *p_cb)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ if (p_cb->smp_over_br)
+ L2CA_RemoveFixedChnl (L2CAP_SMP_BR_CID, p_cb->pairing_bda);
+ else
+ L2CA_RemoveFixedChnl (L2CAP_SMP_CID, p_cb->pairing_bda);
+}
+
/*******************************************************************************
**
** Function smp_reset_control_value
{
SMP_TRACE_EVENT("smp_reset_control_value");
btu_stop_timer (&p_cb->rsp_timer_ent);
-#if SMP_CONFORMANCE_TESTING == TRUE
-
- SMP_TRACE_EVENT("smp_cb.remove_fixed_channel_disable=%d", smp_cb.remove_fixed_channel_disable);
- if (!smp_cb.remove_fixed_channel_disable)
- {
- L2CA_RemoveFixedChnl (L2CAP_SMP_CID, p_cb->pairing_bda);
- }
- else
- {
- SMP_TRACE_EVENT("disable the removal of the fixed channel");
- }
-
+ p_cb->flags = 0;
+ /* set the link idle timer to drop the link when pairing is done
+ usually service discovery will follow authentication complete, to avoid
+ racing condition for a link down/up, set link idle timer to be
+ SMP_LINK_TOUT_MIN to guarantee SMP key exchange */
+ L2CA_SetIdleTimeoutByBdAddr(p_cb->pairing_bda, SMP_LINK_TOUT_MIN, BT_TRANSPORT_LE);
-#else
/* We can tell L2CAP to remove the fixed channel (if it has one) */
- L2CA_RemoveFixedChnl (L2CAP_SMP_CID, p_cb->pairing_bda);
-
-#endif
+ smp_remove_fixed_channel(p_cb);
smp_cb_cleanup(p_cb);
-
}
+
/*******************************************************************************
**
** Function smp_proc_pairing_cmpl
void smp_proc_pairing_cmpl(tSMP_CB *p_cb)
{
tSMP_EVT_DATA evt_data = {0};
+ tSMP_CALLBACK *p_callback = p_cb->p_callback;
+ BD_ADDR pairing_bda;
SMP_TRACE_DEBUG ("smp_proc_pairing_cmpl ");
SMP_TRACE_DEBUG ("send SMP_COMPLT_EVT reason=0x%0x sec_level=0x%0x",
evt_data.cmplt.reason,
evt_data.cmplt.sec_level );
- if (p_cb->p_callback)
- (*p_cb->p_callback) (SMP_COMPLT_EVT, p_cb->pairing_bda, &evt_data);
-#if 0 /* TESTING CODE : as a master, reencrypt using LTK */
- if (evt_data.cmplt.reason == 0 && p_cb->role == HCI_ROLE_MASTER)
+ memcpy (pairing_bda, p_cb->pairing_bda, BD_ADDR_LEN);
+
+ smp_reset_control_value(p_cb);
+
+ if (p_callback)
+ (*p_callback) (SMP_COMPLT_EVT, pairing_bda, &evt_data);
+}
+
+/*******************************************************************************
+**
+** Function smp_command_has_invalid_parameters
+**
+** Description Checks if the received SMP command has invalid parameters i.e.
+** if the command length is valid and the command parameters are
+** inside specified range.
+** It returns TRUE if the command has invalid parameters.
+**
+** Returns TRUE if the command has invalid parameters, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN smp_command_has_invalid_parameters(tSMP_CB *p_cb)
+{
+ UINT8 cmd_code = p_cb->rcvd_cmd_code;
+
+ SMP_TRACE_DEBUG("%s for cmd code 0x%02x", __func__, cmd_code);
+
+ if ((cmd_code > (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */)) ||
+ (cmd_code < SMP_OPCODE_MIN))
{
- btm_ble_start_encrypt(p_cb->pairing_bda, FALSE, NULL);
+ SMP_TRACE_WARNING("Somehow received command with the RESERVED code 0x%02x", cmd_code);
+ return TRUE;
}
-#endif
- smp_reset_control_value(p_cb);
+ if (!(*smp_cmd_len_is_valid[cmd_code])(p_cb))
+ return TRUE;
+
+ if (!(*smp_cmd_param_ranges_are_valid[cmd_code])(p_cb))
+ return TRUE;
+
+ return FALSE;
}
/*******************************************************************************
**
-** Function smp_reject_unexp_pair_req
+** Function smp_command_has_valid_fixed_length
+**
+** Description Checks if the received command size is equal to the size
+** according to specs.
+**
+** Returns TRUE if the command size is as expected, FALSE otherwise.
**
-** Description send pairing failure to an unexpected pairing request during
+** Note The command is expected to have fixed length.
+*******************************************************************************/
+BOOLEAN smp_command_has_valid_fixed_length(tSMP_CB *p_cb)
+{
+ UINT8 cmd_code = p_cb->rcvd_cmd_code;
+
+ SMP_TRACE_DEBUG("%s for cmd code 0x%02x", __func__, cmd_code);
+
+ if (p_cb->rcvd_cmd_len != smp_cmd_size_per_spec[cmd_code])
+ {
+ SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with invalid length\
+ 0x%02x (per spec the length is 0x%02x).",
+ cmd_code, p_cb->rcvd_cmd_len, smp_cmd_size_per_spec[cmd_code]);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function smp_pairing_request_response_parameters_are_valid
+**
+** Description Validates parameter ranges in the received SMP command
+** pairing request or pairing response.
+** The parameters to validate:
+** IO capability,
+** OOB data flag,
+** Bonding_flags in AuthReq
+** Maximum encryption key size.
+** Returns FALSE if at least one of these parameters is out of range.
+**
+*******************************************************************************/
+BOOLEAN smp_pairing_request_response_parameters_are_valid(tSMP_CB *p_cb)
+{
+ UINT8 io_caps = p_cb->peer_io_caps;
+ UINT8 oob_flag = p_cb->peer_oob_flag;
+ UINT8 bond_flag = p_cb->peer_auth_req & 0x03; //0x03 is gen bond with appropriate mask
+ UINT8 enc_size = p_cb->peer_enc_size;
+
+ SMP_TRACE_DEBUG("%s for cmd code 0x%02x", __func__, p_cb->rcvd_cmd_code);
+
+ if (io_caps >= BTM_IO_CAP_MAX)
+ {
+ SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with IO Capabilty \
+ value (0x%02x) out of range).",
+ p_cb->rcvd_cmd_code, io_caps);
+ return FALSE;
+ }
+
+ if (!((oob_flag == SMP_OOB_NONE) || (oob_flag == SMP_OOB_PRESENT)))
+ {
+ SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with OOB data flag value \
+ (0x%02x) out of range).",
+ p_cb->rcvd_cmd_code, oob_flag);
+ return FALSE;
+ }
+
+ if (!((bond_flag == SMP_AUTH_NO_BOND) || (bond_flag == SMP_AUTH_BOND)))
+ {
+ SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Bonding_Flags value (0x%02x)\
+ out of range).",
+ p_cb->rcvd_cmd_code, bond_flag);
+ return FALSE;
+ }
+
+ if ((enc_size < SMP_ENCR_KEY_SIZE_MIN) || (enc_size > SMP_ENCR_KEY_SIZE_MAX))
+ {
+ SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Maximum Encryption \
+ Key value (0x%02x) out of range).",
+ p_cb->rcvd_cmd_code, enc_size);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function smp_pairing_keypress_notification_is_valid
+**
+** Description Validates Notification Type parameter range in the received SMP command
+** pairing keypress notification.
+** Returns FALSE if this parameter is out of range.
+**
+*******************************************************************************/
+BOOLEAN smp_pairing_keypress_notification_is_valid(tSMP_CB *p_cb)
+{
+ tBTM_SP_KEY_TYPE keypress_notification = p_cb->peer_keypress_notification;
+
+ SMP_TRACE_DEBUG("%s for cmd code 0x%02x", __func__, p_cb->rcvd_cmd_code);
+
+ if (keypress_notification >= BTM_SP_KEY_OUT_OF_RANGE)
+ {
+ SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Pairing Keypress \
+ Notification value (0x%02x) out of range).",
+ p_cb->rcvd_cmd_code, keypress_notification);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function smp_parameter_unconditionally_valid
+**
+** Description Always returns TRUE.
+**
+*******************************************************************************/
+BOOLEAN smp_parameter_unconditionally_valid(tSMP_CB *p_cb)
+{
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function smp_parameter_unconditionally_invalid
+**
+** Description Always returns FALSE.
+**
+*******************************************************************************/
+BOOLEAN smp_parameter_unconditionally_invalid(tSMP_CB *p_cb)
+{
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function smp_reject_unexpected_pairing_command
+**
+** Description send pairing failure to an unexpected pairing command during
** an active pairing process.
**
** Returns void
**
*******************************************************************************/
-void smp_reject_unexp_pair_req(BD_ADDR bd_addr)
+void smp_reject_unexpected_pairing_command(BD_ADDR bd_addr)
{
BT_HDR *p_buf;
UINT8 *p;
- if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIR_FAIL_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+ SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) +\
+ SMP_PAIR_FAIL_SIZE + L2CAP_MIN_OFFSET)) != NULL)
{
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
}
}
-#if SMP_CONFORMANCE_TESTING == TRUE
/*******************************************************************************
+** Function smp_select_association_model
**
-** Function smp_set_test_confirm_value
+** Description This function selects association model to use for STK
+** generation. Selection is based on both sides' io capability,
+** oob data flag and authentication request.
**
-** Description This function is called to set the test confirm value
+** Note If Secure Connections Only mode is required locally then we
+** come to this point only if both sides support Secure Connections
+** mode, i.e. if p_cb->secure_connections_only_mode_required = TRUE then we come
+** to this point only if
+** (p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT) ==
+** (p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) ==
+** SMP_SC_SUPPORT_BIT
**
-** Returns void
+*******************************************************************************/
+tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB *p_cb)
+{
+ tSMP_ASSO_MODEL model = SMP_MODEL_OUT_OF_RANGE;
+ p_cb->le_secure_connections_mode_is_used = FALSE;
+
+ SMP_TRACE_EVENT("%s", __FUNCTION__);
+ SMP_TRACE_DEBUG("%s p_cb->peer_io_caps = %d p_cb->local_io_capability = %d",
+ __FUNCTION__, p_cb->peer_io_caps, p_cb->local_io_capability);
+ SMP_TRACE_DEBUG("%s p_cb->peer_oob_flag = %d p_cb->loc_oob_flag = %d",
+ __FUNCTION__, p_cb->peer_oob_flag, p_cb->loc_oob_flag);
+ SMP_TRACE_DEBUG("%s p_cb->peer_auth_req = 0x%02x p_cb->loc_auth_req = 0x%02x",
+ __FUNCTION__, p_cb->peer_auth_req, p_cb->loc_auth_req);
+ SMP_TRACE_DEBUG("%s p_cb->secure_connections_only_mode_required = %s",
+ __FUNCTION__, p_cb->secure_connections_only_mode_required ?
+ "TRUE" : "FALSE");
+
+ if ((p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT) && (p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT))
+ {
+ p_cb->le_secure_connections_mode_is_used = TRUE;
+ }
+
+ SMP_TRACE_DEBUG("use_sc_process = %d", p_cb->le_secure_connections_mode_is_used);
+
+ if (p_cb->le_secure_connections_mode_is_used)
+ {
+ model = smp_select_association_model_secure_connections(p_cb);
+ }
+ else
+ {
+ model = smp_select_legacy_association_model(p_cb);
+ }
+ return model;
+}
+
+/*******************************************************************************
+** Function smp_select_legacy_association_model
+**
+** Description This function is called to select association mode if at least
+** one side doesn't support secure connections.
**
*******************************************************************************/
-void smp_set_test_confirm_value(BOOLEAN enable, UINT8 *p_c_val)
+tSMP_ASSO_MODEL smp_select_legacy_association_model(tSMP_CB *p_cb)
{
- SMP_TRACE_DEBUG("smp_set_test_confirm_value enable=%d", enable);
- smp_cb.enable_test_confirm_val = enable;
- memcpy(smp_cb.test_confirm, p_c_val, BT_OCTET16_LEN);
+ tSMP_ASSO_MODEL model = SMP_MODEL_OUT_OF_RANGE;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ /* if OOB data is present on both devices, then use OOB association model */
+ if (p_cb->peer_oob_flag == SMP_OOB_PRESENT && p_cb->loc_oob_flag == SMP_OOB_PRESENT)
+ return SMP_MODEL_OOB;
+
+ /* else if neither device requires MITM, then use Just Works association model */
+ if (SMP_NO_MITM_REQUIRED (p_cb->peer_auth_req) && SMP_NO_MITM_REQUIRED(p_cb->loc_auth_req))
+ return SMP_MODEL_ENCRYPTION_ONLY;
+
+ /* otherwise use IO capability to select association model */
+ if (p_cb->peer_io_caps < SMP_IO_CAP_MAX && p_cb->local_io_capability < SMP_IO_CAP_MAX)
+ {
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ model = smp_association_table[p_cb->role][p_cb->peer_io_caps]
+ [p_cb->local_io_capability];
+ }
+ else
+ {
+ model = smp_association_table[p_cb->role][p_cb->local_io_capability]
+ [p_cb->peer_io_caps];
+ }
+ }
+
+ return model;
}
+/*******************************************************************************
+** Function smp_select_association_model_secure_connections
+**
+** Description This function is called to select association mode if both
+** sides support secure connections.
+**
+*******************************************************************************/
+tSMP_ASSO_MODEL smp_select_association_model_secure_connections(tSMP_CB *p_cb)
+{
+ tSMP_ASSO_MODEL model = SMP_MODEL_OUT_OF_RANGE;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+ /* if OOB data is present on at least one device, then use OOB association model */
+ if (p_cb->peer_oob_flag == SMP_OOB_PRESENT || p_cb->loc_oob_flag == SMP_OOB_PRESENT)
+ return SMP_MODEL_SEC_CONN_OOB;
+
+ /* else if neither device requires MITM, then use Just Works association model */
+ if (SMP_NO_MITM_REQUIRED (p_cb->peer_auth_req) && SMP_NO_MITM_REQUIRED(p_cb->loc_auth_req))
+ return SMP_MODEL_SEC_CONN_JUSTWORKS;
+
+ /* otherwise use IO capability to select association model */
+ if (p_cb->peer_io_caps < SMP_IO_CAP_MAX && p_cb->local_io_capability < SMP_IO_CAP_MAX)
+ {
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ model = smp_association_table_sc[p_cb->role][p_cb->peer_io_caps]
+ [p_cb->local_io_capability];
+ }
+ else
+ {
+ model = smp_association_table_sc[p_cb->role][p_cb->local_io_capability]
+ [p_cb->peer_io_caps];
+ }
+ }
+
+ return model;
+}
/*******************************************************************************
+** Function smp_reverse_array
**
-** Function smp_set_test_confirm_value
+** Description This function reverses array bytes
**
-** Description This function is called to set the test rand value
+*******************************************************************************/
+void smp_reverse_array(UINT8 *arr, UINT8 len)
+{
+ UINT8 i =0, tmp;
+
+ SMP_TRACE_DEBUG("smp_reverse_array");
+
+ for (i = 0; i < len/2; i ++)
+ {
+ tmp = arr[i];
+ arr[i] = arr[len -1 - i];
+ arr[len -1 - i] = tmp;
+ }
+}
+
+/*******************************************************************************
+** Function smp_calculate_random_input
**
-** Returns void
+** Description This function returns random input value to be used in commitment
+** calculation for SC passkey entry association mode
+** (if bit["round"] in "random" array == 1 then returns 0x81
+** else returns 0x80).
+**
+** Returns ri value
**
*******************************************************************************/
-void smp_set_test_rand_value(BOOLEAN enable, UINT8 *p_c_val)
+UINT8 smp_calculate_random_input(UINT8 *random, UINT8 round)
{
- SMP_TRACE_DEBUG("smp_set_test_rand_value enable=%d", enable);
- smp_cb.enable_test_rand_val = enable;
- memcpy(smp_cb.test_rand, p_c_val, BT_OCTET16_LEN);
+ UINT8 i = round/8;
+ UINT8 j = round%8;
+ UINT8 ri;
+
+ SMP_TRACE_DEBUG("random: 0x%02x, round: %d, i: %d, j: %d", random[i], round, i, j);
+ ri = ((random[i] >> j) & 1) | 0x80;
+ SMP_TRACE_DEBUG("%s ri=0x%02x", __func__, ri);
+ return ri;
}
+/*******************************************************************************
+** Function smp_collect_local_io_capabilities
+**
+** Description This function puts into IOcap array local device
+** IOCapability, OOB data, AuthReq.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_collect_local_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ iocap[0] = p_cb->local_io_capability;
+ iocap[1] = p_cb->loc_oob_flag;
+ iocap[2] = p_cb->loc_auth_req;
+}
/*******************************************************************************
+** Function smp_collect_peer_io_capabilities
+**
+** Description This function puts into IOcap array peer device
+** IOCapability, OOB data, AuthReq.
**
-** Function smp_set_test_pair_fail_status
+** Returns void
**
-** Description This function is called to set the test fairing fair status
+*******************************************************************************/
+void smp_collect_peer_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb)
+{
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ iocap[0] = p_cb->peer_io_caps;
+ iocap[1] = p_cb->peer_oob_flag;
+ iocap[2] = p_cb->peer_auth_req;
+}
+
+/*******************************************************************************
+** Function smp_collect_local_ble_address
+**
+** Description This function puts into le_addr array local device le address:
+** le_addr[0-5] = local BD ADDR,
+** le_addr[6] = local le address type (PUBLIC/RANDOM).
**
** Returns void
**
*******************************************************************************/
-void smp_set_test_pair_fail_status (BOOLEAN enable, UINT8 status)
+void smp_collect_local_ble_address(UINT8 *le_addr, tSMP_CB *p_cb)
{
- SMP_TRACE_DEBUG("smp_set_test_confirm_value enable=%d", enable);
- smp_cb.enable_test_pair_fail = enable;
- smp_cb.pair_fail_status = status;
+ tBLE_ADDR_TYPE addr_type = 0;
+ BD_ADDR bda;
+ UINT8 *p = le_addr;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ BTM_ReadConnectionAddr( p_cb->pairing_bda, bda, &addr_type);
+ BDADDR_TO_STREAM(p, bda);
+ UINT8_TO_STREAM(p, addr_type);
}
/*******************************************************************************
+** Function smp_collect_peer_ble_address
**
-** Function smp_set_test_pair_fail_status
+** Description This function puts into le_addr array peer device le address:
+** le_addr[0-5] = peer BD ADDR,
+** le_addr[6] = peer le address type (PUBLIC/RANDOM).
**
-** Description This function is called to disable the removal of fixed channel
-** in smp_reset_control_value
** Returns void
**
*******************************************************************************/
-void smp_remove_fixed_channel_disable (BOOLEAN disable)
+void smp_collect_peer_ble_address(UINT8 *le_addr, tSMP_CB *p_cb)
{
- SMP_TRACE_DEBUG("smp_remove_fixed_channel_disable disable =%d", disable);
- smp_cb.remove_fixed_channel_disable = disable;
+ tBLE_ADDR_TYPE addr_type = 0;
+ BD_ADDR bda;
+ UINT8 *p = le_addr;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, bda, &addr_type))
+ {
+ SMP_TRACE_ERROR("can not collect peer le addr information for unknown device");
+ return;
+ }
+
+ BDADDR_TO_STREAM(p, bda);
+ UINT8_TO_STREAM(p, addr_type);
}
+
/*******************************************************************************
+** Function smp_check_commitment
**
-** Function smp_skip_compare_check
+** Description This function compares peer commitment values:
+** - expected (i.e. calculated locally),
+** - received from the peer.
**
-** Description This function is called to skip the compare value check
+** Returns TRUE if the values are the same
+** FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN smp_check_commitment(tSMP_CB *p_cb)
+{
+ BT_OCTET16 expected;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ smp_calculate_peer_commitment(p_cb, expected);
+ print128(expected, (const UINT8 *)"calculated peer commitment");
+ print128(p_cb->remote_commitment, (const UINT8 *)"received peer commitment");
+
+ if (memcmp(p_cb->remote_commitment, expected, BT_OCTET16_LEN))
+ {
+ SMP_TRACE_WARNING("Commitment check fails");
+ return FALSE;
+ }
+
+ SMP_TRACE_DEBUG("Commitment check succeeds");
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function smp_save_secure_connections_long_term_key
+**
+** Description The function saves SC LTK as BLE key for future use as local
+** and/or peer key.
**
** Returns void
**
*******************************************************************************/
-void smp_skip_compare_check(BOOLEAN enable)
+void smp_save_secure_connections_long_term_key(tSMP_CB *p_cb)
{
- SMP_TRACE_DEBUG("smp_skip_compare_check enable=%d", enable);
- smp_cb.skip_test_compare_check = enable;
+ tBTM_LE_LENC_KEYS lle_key;
+ tBTM_LE_PENC_KEYS ple_key;
+
+ SMP_TRACE_DEBUG("%s-Save LTK as local LTK key", __func__);
+ memcpy(lle_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+ lle_key.div = 0;
+ lle_key.key_size = p_cb->loc_enc_size;
+ lle_key.sec_level = p_cb->sec_level;
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, (tBTM_LE_KEY_VALUE *)&lle_key, TRUE);
+
+ SMP_TRACE_DEBUG("%s-Save LTK as peer LTK key", __func__);
+ ple_key.ediv = 0;
+ memset(ple_key.rand, 0, BT_OCTET8_LEN);
+ memcpy(ple_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+ ple_key.sec_level = p_cb->sec_level;
+ ple_key.key_size = p_cb->loc_enc_size;
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, (tBTM_LE_KEY_VALUE *)&ple_key, TRUE);
}
-#endif
+/*******************************************************************************
+**
+** Function smp_calculate_f5_mackey_and_long_term_key
+**
+** Description The function calculates MacKey and LTK and saves them in CB.
+** To calculate MacKey and LTK it calls smp_calc_f5(...).
+** MacKey is used in dhkey calculation, LTK is used to encrypt
+** the link.
+**
+** Returns FALSE if out of resources, TRUE otherwise.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f5_mackey_and_long_term_key(tSMP_CB *p_cb)
+{
+ UINT8 a[7];
+ UINT8 b[7];
+ UINT8 *p_na;
+ UINT8 *p_nb;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ if (p_cb->role == HCI_ROLE_MASTER)
+ {
+ smp_collect_local_ble_address(a, p_cb);
+ smp_collect_peer_ble_address(b, p_cb);
+ p_na = p_cb->rand;
+ p_nb = p_cb->rrand;
+ }
+ else
+ {
+ smp_collect_local_ble_address(b, p_cb);
+ smp_collect_peer_ble_address(a, p_cb);
+ p_na = p_cb->rrand;
+ p_nb = p_cb->rand;
+ }
+
+ if(!smp_calculate_f5(p_cb->dhkey, p_na, p_nb, a, b, p_cb->mac_key, p_cb->ltk))
+ {
+ SMP_TRACE_ERROR("%s failed", __func__);
+ return FALSE;
+ }
+
+ SMP_TRACE_EVENT ("%s is completed", __func__);
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function smp_request_oob_data
+**
+** Description Requests application to provide OOB data.
+**
+** Returns TRUE - OOB data has to be provided by application
+** FALSE - otherwise (unexpected)
+**
+*******************************************************************************/
+BOOLEAN smp_request_oob_data(tSMP_CB *p_cb)
+{
+ tSMP_OOB_DATA_TYPE req_oob_type = SMP_OOB_INVALID_TYPE;
+
+ SMP_TRACE_DEBUG("%s", __func__);
+
+ if (p_cb->peer_oob_flag == SMP_OOB_PRESENT && p_cb->loc_oob_flag == SMP_OOB_PRESENT)
+ {
+ /* both local and peer rcvd data OOB */
+ req_oob_type = SMP_OOB_BOTH;
+ }
+ else if (p_cb->peer_oob_flag == SMP_OOB_PRESENT)
+ {
+ /* peer rcvd OOB local data, local didn't receive OOB peer data */
+ req_oob_type = SMP_OOB_LOCAL;
+ }
+ else if (p_cb->loc_oob_flag == SMP_OOB_PRESENT)
+ {
+ req_oob_type = SMP_OOB_PEER;
+ }
+
+ SMP_TRACE_DEBUG("req_oob_type = %d", req_oob_type);
+
+ if (req_oob_type == SMP_OOB_INVALID_TYPE)
+ return FALSE;
+
+ p_cb->req_oob_type = req_oob_type;
+ p_cb->cb_evt = SMP_SC_OOB_REQ_EVT;
+ smp_sm_event(p_cb, SMP_TK_REQ_EVT, &req_oob_type);
+
+ return TRUE;
+}
#endif
+++ /dev/null
-/******************************************************************************
- *
- * Copyright (C) 2003-2014 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/*****************************************************************************
-**
-** Name: vendor_ble.c
-**
-** Description: This file contains vendor specific feature for BLE
-**
-******************************************************************************/
-#include <string.h>
-#include "bt_target.h"
-
-#if (BLE_INCLUDED == TRUE)
-#include "bt_types.h"
-#include "hcimsgs.h"
-#include "btu.h"
-#include "vendor_ble.h"
-#include "vendor_hcidefs.h"
-#include "gatt_int.h"
-#include "device/include/controller.h"
-
-/*** This needs to be moved to a VSC control block eventually per coding conventions ***/
-#if VENDOR_DYNAMIC_MEMORY == FALSE
-tBTM_BLE_VENDOR_CB btm_ble_vendor_cb;
-#endif
-
-static const BD_ADDR na_bda= {0};
-
-/*******************************************************************************
-** Resolve Address Using IRK List functions
-*******************************************************************************/
-
-
-/*******************************************************************************
-**
-** Function btm_ble_vendor_enq_irk_pending
-**
-** Description add target address into IRK pending operation queue
-**
-** Parameters target_bda: target device address
-** add_entry: TRUE for add entry, FALSE for remove entry
-**
-** Returns void
-**
-*******************************************************************************/
-void btm_ble_vendor_enq_irk_pending(BD_ADDR target_bda, BD_ADDR psuedo_bda, UINT8 to_add)
-{
-#if BLE_PRIVACY_SPT == TRUE
- tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q;
-
- memcpy(p_q->irk_q[p_q->q_next], target_bda, BD_ADDR_LEN);
- memcpy(p_q->irk_q_random_pseudo[p_q->q_next], psuedo_bda, BD_ADDR_LEN);
- p_q->irk_q_action[p_q->q_next] = to_add;
-
- p_q->q_next ++;
- p_q->q_next %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz;
-#endif
- return ;
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_find_irk_pending_entry
-**
-** Description check to see if the action is in pending list
-**
-** Parameters TRUE: action pending;
-** FALSE: new action
-**
-** Returns void
-**
-*******************************************************************************/
-BOOLEAN btm_ble_vendor_find_irk_pending_entry(BD_ADDR psuedo_addr, UINT8 action)
-{
-#if BLE_PRIVACY_SPT == TRUE
- tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q;
- UINT8 i;
-
- for (i = p_q->q_pending; i != p_q->q_next; )
- {
- if (memcmp(p_q->irk_q_random_pseudo[i], psuedo_addr, BD_ADDR_LEN) == 0 &&
- action == p_q->irk_q_action[i])
- return TRUE;
-
- i ++;
- i %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz;
- }
-#endif
- return FALSE;
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_deq_irk_pending
-**
-** Description add target address into IRK pending operation queue
-**
-** Parameters target_bda: target device address
-** add_entry: TRUE for add entry, FALSE for remove entry
-**
-** Returns void
-**
-*******************************************************************************/
-BOOLEAN btm_ble_vendor_deq_irk_pending(BD_ADDR target_bda, BD_ADDR psuedo_addr)
-{
-#if BLE_PRIVACY_SPT == TRUE
- tBTM_BLE_IRK_Q *p_q = &btm_ble_vendor_cb.irk_pend_q;
-
- if (p_q->q_next != p_q->q_pending)
- {
- memcpy(target_bda, p_q->irk_q[p_q->q_pending], BD_ADDR_LEN);
- memcpy(psuedo_addr, p_q->irk_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
-
- p_q->q_pending ++;
- p_q->q_pending %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz;
-
- return TRUE;
- }
-#endif
- return FALSE;
-
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_find_irk_entry
-**
-** Description find IRK entry in local host IRK list by static address
-**
-** Returns IRK list entry pointer
-**
-*******************************************************************************/
-tBTM_BLE_IRK_ENTRY * btm_ble_vendor_find_irk_entry(BD_ADDR target_bda)
-{
-#if BLE_PRIVACY_SPT == TRUE
- tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
- UINT8 i;
-
- for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++)
- {
- if (p_irk_entry->in_use && memcmp(p_irk_entry->bd_addr, target_bda, BD_ADDR_LEN) == 0)
- {
- return p_irk_entry ;
- }
- }
-#endif
- return NULL;
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_find_irk_entry_by_psuedo_addr
-**
-** Description find IRK entry in local host IRK list by psuedo address
-**
-** Returns IRK list entry pointer
-**
-*******************************************************************************/
-tBTM_BLE_IRK_ENTRY * btm_ble_vendor_find_irk_entry_by_psuedo_addr (BD_ADDR psuedo_bda)
-{
-#if BLE_PRIVACY_SPT == TRUE
- tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
- UINT8 i;
-
- if(p_irk_entry == NULL)
- return NULL;
-
- for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++)
- {
- if (p_irk_entry->in_use && memcmp(p_irk_entry->psuedo_bda, psuedo_bda, BD_ADDR_LEN) == 0)
- {
- return p_irk_entry ;
- }
- }
-#endif
- return NULL;
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_alloc_irk_entry
-**
-** Description allocate IRK entry in local host IRK list
-**
-** Returns IRK list index
-**
-*******************************************************************************/
-UINT8 btm_ble_vendor_alloc_irk_entry(BD_ADDR target_bda, BD_ADDR pseudo_bda)
-{
-#if BLE_PRIVACY_SPT == TRUE
- tBTM_BLE_IRK_ENTRY *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
- UINT8 i;
-
- for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++)
- {
- if (!p_irk_entry->in_use)
- {
- memcpy(p_irk_entry->bd_addr, target_bda, BD_ADDR_LEN);
- memcpy(p_irk_entry->psuedo_bda, pseudo_bda, BD_ADDR_LEN);
-
- p_irk_entry->index = i;
- p_irk_entry->in_use = TRUE;
-
- return i;
- }
- }
-#endif
- return BTM_CS_IRK_LIST_INVALID;
-}
-
-/*******************************************************************************
-**
-** Function btm_ble_vendor_update_irk_list
-**
-** Description update IRK entry in local host IRK list
-**
-** Returns void
-**
-*******************************************************************************/
-void btm_ble_vendor_update_irk_list(BD_ADDR target_bda, BD_ADDR pseudo_bda, BOOLEAN add)
-{
-#if BLE_PRIVACY_SPT == TRUE
- tBTM_BLE_IRK_ENTRY *p_irk_entry = btm_ble_vendor_find_irk_entry(target_bda);
- UINT8 i;
-
- if (add)
- {
- if (p_irk_entry == NULL)
- {
- if ((i = btm_ble_vendor_alloc_irk_entry(target_bda, pseudo_bda)) == BTM_CS_IRK_LIST_INVALID)
- {
- BTM_TRACE_ERROR("max IRK capacity reached");
- }
- }
- else
- {
- BTM_TRACE_WARNING(" IRK already in queue");
- }
- }
- else
- {
- if (p_irk_entry != NULL)
- {
- memset(p_irk_entry, 0, sizeof(tBTM_BLE_IRK_ENTRY));
- }
- else
- {
- BTM_TRACE_ERROR("No IRK exist in list, can not remove");
- }
- }
-#endif
- return ;
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_irk_vsc_op_cmpl
-**
-** Description IRK operation VSC complete handler
-**
-** Parameters
-**
-** Returns void
-**
-*******************************************************************************/
-void btm_ble_vendor_irk_vsc_op_cmpl (tBTM_VSC_CMPL *p_params)
-{
- UINT8 status;
- UINT8 *p = p_params->p_param_buf, op_subcode;
- UINT16 evt_len = p_params->param_len;
- UINT8 i;
- tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb;
- BD_ADDR target_bda, pseudo_bda, rra;
-
-
- STREAM_TO_UINT8(status, p);
-
- evt_len--;
-
- op_subcode = *p ++;
- BTM_TRACE_DEBUG("btm_ble_vendor_irk_vsc_op_cmpl op_subcode = %d", op_subcode);
- if (evt_len < 1)
- {
- BTM_TRACE_ERROR("cannot interpret IRK VSC cmpl callback");
- return;
- }
-
- if (BTM_BLE_META_IRK_ENABLE == op_subcode)
- {
- BTM_TRACE_DEBUG("IRK enable: %d, %d", status, op_subcode);
- return;
- }
- else
- if (op_subcode == BTM_BLE_META_CLEAR_IRK_LIST)
- {
- if (status == HCI_SUCCESS)
- {
- STREAM_TO_UINT8(p_cb->irk_avail_size, p);
- p_cb->irk_list_size = 0;
-
- BTM_TRACE_DEBUG("p_cb->irk_list_size = %d", p_cb->irk_avail_size);
-
- for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++)
- memset(&p_cb->irk_list[i], 0, sizeof(tBTM_BLE_IRK_ENTRY));
- }
- }
- else if (op_subcode == BTM_BLE_META_ADD_IRK_ENTRY)
- {
- if (!btm_ble_vendor_deq_irk_pending(target_bda, pseudo_bda))
- {
- BTM_TRACE_ERROR("no pending IRK operation");
- return;
- }
-
- if (status == HCI_SUCCESS)
- {
- STREAM_TO_UINT8(p_cb->irk_avail_size, p);
- btm_ble_vendor_update_irk_list(target_bda, pseudo_bda, TRUE);
- }
- else if (status == 0x07) /* BT_ERROR_CODE_MEMORY_CAPACITY_EXCEEDED */
- {
- p_cb->irk_avail_size = 0;
- BTM_TRACE_ERROR("IRK Full ");
- }
- else
- {
- /* give the credit back if invalid parameter failed the operation */
- p_cb->irk_list_size ++;
- }
- }
- else if (op_subcode == BTM_BLE_META_REMOVE_IRK_ENTRY)
- {
- if (!btm_ble_vendor_deq_irk_pending(target_bda, pseudo_bda))
- {
- BTM_TRACE_ERROR("no pending IRK operation");
- return;
- }
- if (status == HCI_SUCCESS)
- {
- STREAM_TO_UINT8(p_cb->irk_avail_size, p);
- btm_ble_vendor_update_irk_list(target_bda, pseudo_bda, FALSE);
- }
- else
- {
- /* give the credit back if invalid parameter failed the operation */
- if (p_cb->irk_avail_size > 0)
- p_cb->irk_list_size --;
- }
-
- }
- else if (op_subcode == BTM_BLE_META_READ_IRK_ENTRY)
- {
- if (status == HCI_SUCCESS)
- {
- //STREAM_TO_UINT8(index, p);
- p += (1 + 16 + 1); /* skip index, IRK value, address type */
- STREAM_TO_BDADDR(target_bda, p);
- STREAM_TO_BDADDR(rra, p);
- btm_ble_refresh_rra(target_bda, rra);
- }
- }
-
-}
-/*******************************************************************************
-**
-** Function btm_ble_remove_irk_entry
-**
-** Description This function to remove an IRK entry from the list
-**
-** Parameters ble_addr_type: address type
-** ble_addr: LE adddress
-**
-** Returns status
-**
-*******************************************************************************/
-tBTM_STATUS btm_ble_remove_irk_entry(tBTM_SEC_DEV_REC *p_dev_rec)
-{
-#if BLE_PRIVACY_SPT == TRUE
- UINT8 param[20], *p;
- tBTM_STATUS st;
- tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb;
-
- if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
- return BTM_MODE_UNSUPPORTED;
-
- p = param;
- memset(param, 0, 20);
-
- UINT8_TO_STREAM(p, BTM_BLE_META_REMOVE_IRK_ENTRY);
- UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
- BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
-
- if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
- BTM_BLE_META_REMOVE_IRK_LEN,
- param,
- btm_ble_vendor_irk_vsc_op_cmpl))
- != BTM_NO_RESOURCES)
- {
- btm_ble_vendor_enq_irk_pending(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, FALSE);
- p_cb->irk_list_size --;
- }
-
- return st;
-#endif
- return BTM_MODE_UNSUPPORTED;
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_clear_irk_list
-**
-** Description This function clears the IRK entry list
-**
-** Parameters None.
-**
-** Returns status
-**
-*******************************************************************************/
-tBTM_STATUS btm_ble_vendor_clear_irk_list(void)
-{
-#if BLE_PRIVACY_SPT == TRUE
- UINT8 param[20], *p;
- tBTM_STATUS st;
-
- if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
- return BTM_MODE_UNSUPPORTED;
-
- p = param;
- memset(param, 0, 20);
-
- UINT8_TO_STREAM(p, BTM_BLE_META_CLEAR_IRK_LIST);
-
- st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
- BTM_BLE_META_CLEAR_IRK_LEN,
- param,
- btm_ble_vendor_irk_vsc_op_cmpl);
-
- return st;
-#endif
- return BTM_MODE_UNSUPPORTED;
-}
-/*******************************************************************************
-**
-** Function btm_ble_read_irk_entry
-**
-** Description This function read an IRK entry by index
-**
-** Parameters entry index.
-**
-** Returns status
-**
-*******************************************************************************/
-tBTM_STATUS btm_ble_read_irk_entry(BD_ADDR target_bda)
-{
-#if BLE_PRIVACY_SPT == TRUE
- UINT8 param[20], *p;
- tBTM_STATUS st = BTM_UNKNOWN_ADDR;
- tBTM_BLE_IRK_ENTRY *p_entry;
-
- if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
- return BTM_MODE_UNSUPPORTED;
-
- if ((p_entry = btm_ble_vendor_find_irk_entry(target_bda)) == NULL)
- return st;
-
- p = param;
- memset(param, 0, 20);
-
- UINT8_TO_STREAM(p, BTM_BLE_META_READ_IRK_ENTRY);
- UINT8_TO_STREAM(p, p_entry->index);
-
- st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
- BTM_BLE_META_READ_IRK_LEN,
- param,
- btm_ble_vendor_irk_vsc_op_cmpl);
-
- return st;
-#endif
- return BTM_MODE_UNSUPPORTED;
-}
-
-
-/*******************************************************************************
-**
-** Function btm_ble_vendor_enable_irk_list_known_dev
-**
-** Description This function add all known device with random address into
-** IRK list.
-**
-** Parameters enable: enable IRK list with known device, or disable it
-**
-** Returns status
-**
-*******************************************************************************/
-void btm_ble_vendor_irk_list_known_dev(BOOLEAN enable)
-{
-#if BLE_PRIVACY_SPT == TRUE
- UINT8 i;
- UINT8 count = 0;
- tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
-
- if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
- return;
-
- /* add all known device with random address into IRK list */
- for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec ++)
- {
- if (p_dev_rec->sec_flags & BTM_SEC_IN_USE)
- {
- if (btm_ble_vendor_irk_list_load_dev(p_dev_rec))
- count ++;
- }
- }
-
- if ((count > 0 && enable) || !enable)
- btm_ble_vendor_enable_irk_feature(enable);
-#endif
- return ;
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_irk_list_load_dev
-**
-** Description This function add a device which is using RPA into white list
-**
-** Parameters
-**
-** Returns status
-**
-*******************************************************************************/
-BOOLEAN btm_ble_vendor_irk_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec)
-{
-#if BLE_PRIVACY_SPT == TRUE
- UINT8 param[40], *p;
- tBTM_BLE_VENDOR_CB *p_cb = &btm_ble_vendor_cb;
- BOOLEAN rt = FALSE;
- tBTM_BLE_IRK_ENTRY *p_irk_entry = NULL;
- BTM_TRACE_DEBUG ("btm_ble_vendor_irk_list_load_dev:max_irk_size=%d", p_cb->irk_avail_size);
- memset(param, 0, 40);
-
- if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
- return FALSE;
-
- if (p_dev_rec != NULL && /* RPA is being used and PID is known */
- (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0)
- {
-
- if ((p_irk_entry = btm_ble_vendor_find_irk_entry_by_psuedo_addr(p_dev_rec->bd_addr)) == NULL &&
- btm_ble_vendor_find_irk_pending_entry(p_dev_rec->bd_addr, TRUE) == FALSE)
- {
-
- if (p_cb->irk_avail_size > 0)
- {
- p = param;
-
- UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY);
- ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN);
- UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
- BDADDR_TO_STREAM(p,p_dev_rec->ble.static_addr);
-
- if (BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
- BTM_BLE_META_ADD_IRK_LEN,
- param,
- btm_ble_vendor_irk_vsc_op_cmpl)
- != BTM_NO_RESOURCES)
- {
- btm_ble_vendor_enq_irk_pending(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, TRUE);
- p_cb->irk_list_size ++;
- rt = TRUE;
-
- btm_ble_vendor_enable_irk_feature(TRUE);
- }
- }
- }
- else
- {
- BTM_TRACE_ERROR("Device already in IRK list");
- rt = TRUE;
- }
- }
- else
- {
- BTM_TRACE_DEBUG("Device not a RPA enabled device");
- }
- return rt;
-#endif
- return FALSE;
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_irk_list_remove_dev
-**
-** Description This function remove the device from IRK list
-**
-** Parameters
-**
-** Returns status
-**
-*******************************************************************************/
-void btm_ble_vendor_irk_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec)
-{
-#if BLE_PRIVACY_SPT == TRUE
- tBTM_BLE_VENDOR_CB *p_cs_cb = &btm_ble_vendor_cb;
- tBTM_BLE_IRK_ENTRY *p_irk_entry;
-
- if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
- return;
-
- if ((p_irk_entry = btm_ble_vendor_find_irk_entry_by_psuedo_addr(p_dev_rec->bd_addr)) != NULL &&
- btm_ble_vendor_find_irk_pending_entry(p_dev_rec->bd_addr, FALSE) == FALSE)
- {
- btm_ble_remove_irk_entry(p_dev_rec);
- }
- else
- {
- BTM_TRACE_ERROR("Device not in IRK list");
- }
-
- if (p_cs_cb->irk_list_size == 0)
- btm_ble_vendor_enable_irk_feature(FALSE);
-#endif
-}
-/*******************************************************************************
-**
-** Function btm_ble_vendor_disable_irk_list
-**
-** Description disable LE resolve address feature
-**
-** Parameters
-**
-** Returns status
-**
-*******************************************************************************/
-void btm_ble_vendor_disable_irk_list(void)
-{
-#if BLE_PRIVACY_SPT == TRUE
- btm_ble_vendor_enable_irk_feature(FALSE);
-#endif
-}
-
-/*******************************************************************************
-**
-** Function btm_ble_vendor_enable_irk_feature
-**
-** Description This function is called to enable or disable the RRA
-** offloading feature.
-**
-** Parameters enable: enable or disable the RRA offloading feature
-**
-** Returns BTM_SUCCESS if successful
-**
-*******************************************************************************/
-tBTM_STATUS btm_ble_vendor_enable_irk_feature(BOOLEAN enable)
-{
-#if BLE_PRIVACY_SPT == TRUE
- UINT8 param[20], *p;
- tBTM_STATUS st = BTM_WRONG_MODE;
- tBTM_BLE_PF_COUNT *p_bda_filter;
-
- if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
- return BTM_MODE_UNSUPPORTED;
-
- if (btm_ble_vendor_cb.enable != enable)
- {
- p = param;
- memset(param, 0, 20);
-
- /* select feature based on control block settings */
- UINT8_TO_STREAM(p, BTM_BLE_META_IRK_ENABLE);
- UINT8_TO_STREAM(p, enable ? 0x01 : 0x00);
-
- st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_IRK_ENABLE_LEN,
- param, btm_ble_vendor_irk_vsc_op_cmpl);
-
- btm_ble_vendor_cb.enable = enable;
- }
-
- return st;
-#endif
- return BTM_MODE_UNSUPPORTED;
-}
-
-/*******************************************************************************
-**
-** Function btm_ble_vendor_init
-**
-** Description Initialize customer specific feature information in host stack
-**
-** Parameters Max IRK list size
-** Max filter supported
-**
-** Returns void
-**
-*******************************************************************************/
-void btm_ble_vendor_init(UINT8 max_irk_list_sz)
-{
- memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB));
-
-#if BLE_PRIVACY_SPT == TRUE
- if (max_irk_list_sz > 0)
- {
- btm_ble_vendor_cb.irk_list = (tBTM_BLE_IRK_ENTRY*)GKI_getbuf (sizeof (tBTM_BLE_IRK_ENTRY)
- * max_irk_list_sz);
- btm_ble_vendor_cb.irk_pend_q.irk_q = (BD_ADDR*) GKI_getbuf (sizeof (BD_ADDR) *
- max_irk_list_sz);
- btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo = (BD_ADDR*)GKI_getbuf (sizeof (BD_ADDR) *
- max_irk_list_sz);
- btm_ble_vendor_cb.irk_pend_q.irk_q_action = (UINT8*) GKI_getbuf (max_irk_list_sz);
- }
-
- btm_ble_vendor_cb.irk_avail_size = max_irk_list_sz;
-#endif
-}
-
-/*******************************************************************************
-**
-** Function btm_ble_vendor_cleanup
-**
-** Description Cleanup VSC specific dynamic memory
-**
-** Parameters
-**
-** Returns void
-**
-*******************************************************************************/
-void btm_ble_vendor_cleanup(void)
-{
-#if BLE_PRIVACY_SPT == TRUE
- if (btm_ble_vendor_cb.irk_list)
- GKI_freebuf(btm_ble_vendor_cb.irk_list);
-
- if (btm_ble_vendor_cb.irk_pend_q.irk_q)
- GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q);
-
- if (btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo)
- GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo);
-
- if (btm_ble_vendor_cb.irk_pend_q.irk_q_action)
- GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q_action);
-#endif
- memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB));
-}
-
-#endif
-
+++ /dev/null
-/******************************************************************************
- *
- * Copyright (C) 2003-2014 Broadcom Corporation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************************/
-
-/*****************************************************************************
-**
-** Name: vendor_ble.h
-**
-** Description: This file contains vendor specific feature header
-** for BLE
-******************************************************************************/
-#ifndef VENDOR_BLE_H
-#define VENDOR_BLE_H
-
-#include "btm_int.h"
-#include "btm_ble_api.h"
-#include "vendor_api.h"
-
-/* RPA offload VSC specifics */
-#define BTM_BLE_META_IRK_ENABLE 0x01
-#define BTM_BLE_META_ADD_IRK_ENTRY 0x02
-#define BTM_BLE_META_REMOVE_IRK_ENTRY 0x03
-#define BTM_BLE_META_CLEAR_IRK_LIST 0x04
-#define BTM_BLE_META_READ_IRK_ENTRY 0x05
-#define BTM_BLE_META_CS_RESOLVE_ADDR 0x00000001
-#define BTM_BLE_IRK_ENABLE_LEN 2
-
-/* BLE meta vsc header: 1 bytes of sub_code, 1 byte of PCF action */
-#define BTM_BLE_META_HDR_LENGTH 3
-#define BTM_BLE_PF_FEAT_SEL_LEN 18
-#define BTM_BLE_PCF_ENABLE_LEN 2
-#define BTM_BLE_META_ADDR_LEN 7
-#define BTM_BLE_META_UUID_LEN 40
-#define BTM_BLE_META_ADD_IRK_LEN 24
-#define BTM_BLE_META_REMOVE_IRK_LEN 8
-#define BTM_BLE_META_CLEAR_IRK_LEN 1
-#define BTM_BLE_META_READ_IRK_LEN 2
-#define BTM_BLE_META_ADD_WL_ATTR_LEN 9
-
-#define BTM_BLE_PF_SELECT_NONE 0
-#define BTM_BLE_PF_ADDR_FILTER_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_ADDR_FILTER)
-#define BTM_BLE_PF_SRVC_DATA_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_DATA)
-#define BTM_BLE_PF_SRVC_UUID_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_UUID)
-#define BTM_BLE_PF_SRVC_SOL_UUID_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_SOL_UUID)
-#define BTM_BLE_PF_LOCAL_NAME_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_LOCAL_NAME)
-#define BTM_BLE_PF_MANU_DATA_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_MANU_DATA)
-#define BTM_BLE_PF_SRVC_DATA_PATTERN_BIT BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_DATA_PATTERN)
-typedef UINT8 tBTM_BLE_PF_SEL_MASK;
-
-#define BTM_BLE_MAX_FILTER_COUNTER (BTM_BLE_MAX_ADDR_FILTER + 1) /* per device filter + one generic filter indexed by 0 */
-
-#define BTM_CS_IRK_LIST_INVALID 0xff
-
-typedef struct
-{
- BOOLEAN in_use;
- BD_ADDR bd_addr; /* must be the address used in controller */
- BD_ADDR psuedo_bda; /* the random pseudo address */
- UINT8 index;
-}tBTM_BLE_IRK_ENTRY;
-
-
-typedef struct
-{
- BD_ADDR *irk_q;
- BD_ADDR *irk_q_random_pseudo;
- UINT8 *irk_q_action;
- UINT8 q_next;
- UINT8 q_pending;
-} tBTM_BLE_IRK_Q;
-
-/* control block for BLE customer specific feature */
-typedef struct
-{
- BOOLEAN enable;
-
- UINT8 op_type;
- tBLE_BD_ADDR cur_filter_target;
-
- UINT8 irk_list_size;
- UINT8 irk_avail_size;
- tBTM_BLE_IRK_ENTRY *irk_list;
- tBTM_BLE_IRK_Q irk_pend_q;
- UINT8 max_filter_supported;
- tBTM_BLE_PF_CMPL_CBACK *p_scan_pf_cback;
-}tBTM_BLE_VENDOR_CB;
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#if VENDOR_DYNAMIC_MEMORY == FALSE
-extern tBTM_BLE_VENDOR_CB btm_ble_vendor_cb;
-#else
-extern tBTM_BLE_VENDOR_CB *btm_ble_vendor_ptr;
-#define btm_ble_vendor_cb (*btm_ble_vendor_ptr)
-#endif
-
-extern void btm_ble_vendor_irk_list_known_dev(BOOLEAN enable);
-extern tBTM_STATUS btm_ble_read_irk_entry(BD_ADDR target_bda);
-extern void btm_ble_vendor_disable_irk_list(void);
-extern BOOLEAN btm_ble_vendor_irk_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec);
-extern void btm_ble_vendor_irk_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec);
-extern tBTM_STATUS btm_ble_enable_vendor_feature (BOOLEAN enable, UINT32 feature_bit);
-
-extern void btm_ble_vendor_init(UINT8 max_irk_list_sz);
-extern void btm_ble_vendor_cleanup(void);
-extern BOOLEAN btm_ble_vendor_write_device_wl_attribute (tBLE_ADDR_TYPE addr_type, BD_ADDR bd_addr, UINT8 attribute);
-extern tBTM_STATUS btm_ble_vendor_enable_irk_feature(BOOLEAN enable);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif