diff options
74 files changed, 10464 insertions, 3171 deletions
diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c index f661a1905..1b625d18b 100644 --- a/bta/ag/bta_ag_act.c +++ b/bta/ag/bta_ag_act.c @@ -684,7 +684,7 @@ void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { /* 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)) diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c index 14b609318..062ae0631 100644 --- a/bta/dm/bta_dm_act.c +++ b/bta/dm/bta_dm_act.c @@ -413,7 +413,8 @@ void bta_dm_disable (tBTA_DM_MSG *p_data) 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); @@ -4301,10 +4302,9 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D { 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; @@ -4371,31 +4371,24 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D 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) { @@ -4417,6 +4410,7 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D 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); @@ -4545,6 +4539,28 @@ void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data) /******************************************************************************* ** +** 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. diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c index 92ab0a8f1..47b948821 100644 --- a/bta/dm/bta_dm_api.c +++ b/bta/dm/bta_dm_api.c @@ -31,7 +31,6 @@ #include "btm_int.h" #include <string.h> #include "utl.h" -#include "vendor_ble.h" /***************************************************************************** ** Constants @@ -793,6 +792,31 @@ void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passkey) } /******************************************************************************* ** +** 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. @@ -2004,7 +2028,9 @@ void BTA_VendorCleanup (void) 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) diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h index 4ab8497b7..798a90975 100644 --- a/bta/dm/bta_dm_int.h +++ b/bta/dm/bta_dm_int.h @@ -85,6 +85,7 @@ enum 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, @@ -1043,6 +1044,7 @@ extern void bta_dm_add_ampkey (tBTA_DM_MSG *p_data); 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); @@ -1106,8 +1108,6 @@ extern void bta_dm_search_cancel_transac_cmpl(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); diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c index cf810a405..75de1f3b2 100644 --- a/bta/dm/bta_dm_main.c +++ b/bta/dm/bta_dm_main.c @@ -82,6 +82,7 @@ const tBTA_DM_ACTION bta_dm_action[] = 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 */ diff --git a/bta/hf_client/bta_hf_client_act.c b/bta/hf_client/bta_hf_client_act.c index 4cf99c7bd..46f05ffcb 100644 --- a/bta/hf_client/bta_hf_client_act.c +++ b/bta/hf_client/bta_hf_client_act.c @@ -141,7 +141,7 @@ void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA *p_data) { /* 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) diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h index efa8d32d1..a3410c1fc 100644 --- a/bta/include/bta_api.h +++ b/bta/include/bta_api.h @@ -626,13 +626,15 @@ typedef UINT8 tBTA_SIG_STRENGTH_MASK; #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 */ @@ -663,6 +665,7 @@ typedef struct #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) @@ -706,6 +709,7 @@ typedef union 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 @@ -743,7 +747,7 @@ typedef struct { 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 */ @@ -756,7 +760,9 @@ typedef struct 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; @@ -806,10 +812,13 @@ typedef struct 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 @@ -833,6 +842,11 @@ typedef tBTM_AUTH_REQ tBTA_AUTH_REQ; #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 @@ -1776,6 +1790,20 @@ extern void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passke /******************************************************************************* ** +** 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 @@ -1840,8 +1868,7 @@ extern void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr, ** 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 diff --git a/btif/include/btif_dm.h b/btif/include/btif_dm.h index 297e2a957..f4bddd65d 100644 --- a/btif/include/btif_dm.h +++ b/btif/include/btif_dm.h @@ -109,6 +109,7 @@ typedef struct 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 diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c index 8679e3c00..2d1ffa615 100644 --- a/btif/src/btif_config.c +++ b/btif/src/btif_config.c @@ -281,12 +281,14 @@ size_t btif_config_get_bin_length(const char *section, const char *key) { } 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) @@ -294,7 +296,7 @@ bool btif_config_set_bin(const char *section, const char *key, const uint8_t *va 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); diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c index 7a7ec01a3..2e687e12e 100644 --- a/btif/src/btif_dm.c +++ b/btif/src/btif_dm.c @@ -228,6 +228,7 @@ static btif_dm_local_key_cb_t ble_local_key_cb; 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, @@ -1758,31 +1759,41 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) 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" @@ -1798,28 +1809,39 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) 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; @@ -1827,14 +1849,25 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) 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: @@ -1855,15 +1888,22 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) 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); @@ -1884,7 +1924,7 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param) 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; @@ -2982,6 +3022,14 @@ void btif_dm_save_ble_bonding_keys(void) 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); + } + } @@ -3080,7 +3128,28 @@ static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req) 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) diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c index 56b8f5a96..63508a9e5 100644 --- a/btif/src/btif_storage.c +++ b/btif/src/btif_storage.c @@ -970,6 +970,9 @@ bt_status_t btif_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr, 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; } @@ -1013,6 +1016,8 @@ bt_status_t btif_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr, 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; } @@ -1236,6 +1241,28 @@ bt_status_t btif_in_fetch_bonded_ble_device(const char *remote_bd_addr,int add, 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, diff --git a/device/include/controller.h b/device/include/controller.h index 2ef2332f6..af93e4742 100644 --- a/device/include/controller.h +++ b/device/include/controller.h @@ -42,6 +42,7 @@ typedef struct controller_t { 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); @@ -51,6 +52,7 @@ typedef struct controller_t { 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); @@ -65,6 +67,9 @@ typedef struct controller_t { // 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(); diff --git a/device/src/controller.c b/device/src/controller.c index c1eadc08e..6537cf1f9 100644 --- a/device/src/controller.c +++ b/device/src/controller.c @@ -66,12 +66,14 @@ static uint16_t acl_buffer_count_classic; 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)) @@ -143,6 +145,12 @@ static future_t *start_up(void) { 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; @@ -204,6 +212,13 @@ static future_t *start_up(void) { &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); @@ -281,6 +296,11 @@ static bool supports_simple_pairing(void) { 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); @@ -316,6 +336,12 @@ static bool supports_ble(void) { 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); @@ -354,6 +380,18 @@ static uint8_t get_acl_buffer_count_ble(void) { 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, @@ -367,6 +405,7 @@ static const controller_t interface = { get_ble_supported_states, supports_simple_pairing, + supports_secure_connections, supports_simultaneous_le_bredr, supports_reading_remote_extended_features, supports_interlaced_inquiry_scan, @@ -376,6 +415,7 @@ static const controller_t interface = { supports_ble, supports_ble_connection_parameters_request, + supports_ble_privacy, get_acl_data_size_classic, get_acl_data_size_ble, @@ -384,7 +424,10 @@ static const controller_t interface = { 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() { diff --git a/hci/include/hci_packet_factory.h b/hci/include/hci_packet_factory.h index b5e207c55..5a50b5199 100644 --- a/hci/include/hci_packet_factory.h +++ b/hci/include/hci_packet_factory.h @@ -30,12 +30,14 @@ typedef struct { 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; diff --git a/hci/include/hci_packet_parser.h b/hci/include/hci_packet_parser.h index 219a42432..45b934a5d 100644 --- a/hci/include/hci_packet_parser.h +++ b/hci/include/hci_packet_parser.h @@ -81,6 +81,12 @@ typedef struct { 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(); diff --git a/hci/src/hci_packet_factory.c b/hci/src/hci_packet_factory.c index 032823dd3..89b82d189 100644 --- a/hci/src/hci_packet_factory.c +++ b/hci/src/hci_packet_factory.c @@ -85,6 +85,15 @@ static BT_HDR *make_write_simple_pairing_mode(uint8_t mode) { 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); @@ -120,6 +129,10 @@ static BT_HDR *make_ble_read_local_supported_features(void) { 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); @@ -167,12 +180,14 @@ static const hci_packet_factory_t interface = { 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 }; diff --git a/hci/src/hci_packet_parser.c b/hci/src/hci_packet_parser.c index 0af9b7029..6ff3c3d85 100644 --- a/hci/src/hci_packet_parser.c +++ b/hci/src/hci_packet_parser.c @@ -147,6 +147,16 @@ static void parse_ble_read_local_supported_features_response( 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( @@ -197,7 +207,8 @@ static const hci_packet_parser_t interface = { 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() { diff --git a/include/bt_target.h b/include/bt_target.h index bf49ac30a..b2550739c 100644 --- a/include/bt_target.h +++ b/include/bt_target.h @@ -711,7 +711,7 @@ /* 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 @@ -904,11 +904,17 @@ #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 diff --git a/stack/Android.mk b/stack/Android.mk index 22f013f82..10eb44698 100644 --- a/stack/Android.mk +++ b/stack/Android.mk @@ -74,6 +74,7 @@ LOCAL_SRC_FILES:= \ ./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 \ @@ -116,6 +117,10 @@ LOCAL_SRC_FILES:= \ ./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 \ @@ -154,8 +159,7 @@ LOCAL_SRC_FILES:= \ ./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 diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c index 0b7204b64..b47564fc7 100644 --- a/stack/btm/btm_acl.c +++ b/stack/btm/btm_acl.c @@ -234,30 +234,20 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn, 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); diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c index ec09a99ca..eaaa11569 100644 --- a/stack/btm/btm_ble.c +++ b/stack/btm/btm_ble.c @@ -37,13 +37,13 @@ #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 @@ -166,7 +166,7 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_ 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", @@ -179,12 +179,12 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_ (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 @@ -207,7 +207,7 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_ 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) @@ -217,7 +217,7 @@ void BTM_BleLoadLocalKeys(UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key) 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: @@ -235,14 +235,13 @@ void BTM_BleLoadLocalKeys(UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key) ** 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); } /******************************************************************************* @@ -424,7 +423,7 @@ void BTM_BlePasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey) 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 @@ -432,6 +431,34 @@ void BTM_BlePasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey) /******************************************************************************* ** +** 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 @@ -456,7 +483,7 @@ void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data) 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 } @@ -482,8 +509,6 @@ void BTM_BleSetConnScanParams (UINT16 scan_interval, UINT16 scan_window) 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; @@ -890,12 +915,12 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY 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; @@ -926,7 +951,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY 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; @@ -944,6 +969,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY 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; @@ -957,6 +983,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY 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; @@ -968,6 +995,9 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY 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; @@ -983,6 +1013,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY { 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; @@ -1071,8 +1102,7 @@ void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE 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; } @@ -1082,7 +1112,7 @@ void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE /* 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; @@ -1132,6 +1162,8 @@ tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 lin 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) { @@ -1151,24 +1183,26 @@ tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 lin 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) { @@ -1256,7 +1290,7 @@ tBTM_STATUS btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk) 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 @@ -1357,7 +1391,7 @@ static void btm_enc_proc_slave_y(tSMP_ENC *p) { 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 @@ -1404,10 +1438,10 @@ void btm_ble_ltk_request_reply(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk) } 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); } } @@ -1480,12 +1514,48 @@ UINT8 btm_ble_io_capabilities_req(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_LE_IO_REQ *p 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 ) /******************************************************************************* ** @@ -1607,9 +1677,7 @@ void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, 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; } @@ -1620,14 +1688,14 @@ void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, ** 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); @@ -1636,18 +1704,23 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 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); } @@ -1660,8 +1733,19 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len) 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 @@ -1669,33 +1753,14 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len) 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 ** @@ -1704,7 +1769,7 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len) ******************************************************************************/ 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); @@ -1731,9 +1796,16 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) 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: @@ -1746,6 +1818,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) 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) { @@ -1763,8 +1836,6 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) 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"); @@ -1775,8 +1846,8 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) { 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 { @@ -1786,7 +1857,10 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) } #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", @@ -1796,6 +1870,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) 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) { @@ -1803,6 +1878,17 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) 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; @@ -1842,29 +1928,21 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) 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) @@ -1873,76 +1951,23 @@ BOOLEAN BTM_BleDataSignature (BD_ADDR bd_addr, UINT8 *p_text, UINT16 len, 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; } @@ -1964,10 +1989,10 @@ BOOLEAN BTM_BleDataSignature (BD_ADDR bd_addr, UINT8 *p_text, UINT16 len, 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))) { @@ -1983,9 +2008,10 @@ BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT } 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) { @@ -1999,6 +2025,148 @@ BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT } /******************************************************************************* +** +** 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 *******************************************************************************/ /******************************************************************************* @@ -2028,7 +2196,7 @@ static void btm_notify_new_key(UINT8 key_type) 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: @@ -2056,13 +2224,13 @@ static void btm_ble_process_er2(tBTM_RAND_ENC *p) 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)); } } @@ -2082,11 +2250,11 @@ static void btm_ble_process_er(tBTM_RAND_ENC *p) 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."); } } diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c index e560ee7f4..142b8d875 100644 --- a/stack/btm/btm_ble_addr.c +++ b/stack/btm/btm_ble_addr.c @@ -29,12 +29,12 @@ #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" /******************************************************************************* ** @@ -199,7 +199,8 @@ void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p) } } - #if SMP_INCLUDED == TRUE + +#if SMP_INCLUDED == TRUE /******************************************************************************* ** Utility functions for Random address resolving *******************************************************************************/ @@ -352,7 +353,8 @@ void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_ else (*p_cback)(NULL, p); } - #endif +#endif + /******************************************************************************* ** address mapping between pseudo address and real connection address *******************************************************************************/ @@ -382,62 +384,62 @@ tBLE_ADDR_TYPE btm_ble_map_bda_to_conn_bda(BD_ADDR bd_addr) /******************************************************************************* ** -** 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; } @@ -447,26 +449,25 @@ BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type) /******************************************************************************* ** -** 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; } } @@ -476,49 +477,106 @@ BOOLEAN btm_random_pseudo_to_public(BD_ADDR random_pseudo, UINT8 *p_static_addr_ /******************************************************************************* ** -** 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 } diff --git a/stack/btm/btm_ble_adv_filter.c b/stack/btm/btm_ble_adv_filter.c index 9a297985d..ad6a56ca5 100644 --- a/stack/btm/btm_ble_adv_filter.c +++ b/stack/btm/btm_ble_adv_filter.c @@ -29,13 +29,22 @@ #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)) diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c index 21d4c9ba3..a83a3c7b8 100644 --- a/stack/btm/btm_ble_bgconn.c +++ b/stack/btm/btm_ble_bgconn.c @@ -30,7 +30,7 @@ #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 */ @@ -83,40 +83,38 @@ BOOLEAN btm_add_dev_to_controller (BOOLEAN to_add, BD_ADDR bd_addr) { 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; @@ -316,6 +314,7 @@ BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr) 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) @@ -373,28 +372,39 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start) 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 */ @@ -404,11 +414,11 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start) { /* 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 @@ -422,12 +432,7 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start) { 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 { @@ -480,8 +485,8 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_c 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)) { @@ -509,17 +514,11 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK *p_select_c { 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; } @@ -669,13 +668,11 @@ tBTM_BLE_CONN_ST btm_ble_get_conn_st(void) 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); - } } /******************************************************************************* diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c index fa1d20130..fc6dae0c4 100644 --- a/stack/btm/btm_ble_gap.c +++ b/stack/btm/btm_ble_gap.c @@ -37,7 +37,6 @@ #if BLE_INCLUDED == TRUE #include "l2c_int.h" -#include "vendor_ble.h" #include "gattdefs.h" #include "gatt_int.h" @@ -67,8 +66,8 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt 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); @@ -335,8 +334,8 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration, 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); } @@ -466,7 +465,7 @@ static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_ } 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) @@ -477,10 +476,14 @@ static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_ 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(); @@ -550,27 +553,23 @@ extern void BTM_BleReadControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK *p_vsc_c /******************************************************************************* ** -** 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 } @@ -581,34 +580,54 @@ void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback) ** 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 } /******************************************************************************* @@ -620,7 +639,7 @@ void BTM_BleConfigPrivacy(BOOLEAN enable) ** 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; @@ -674,10 +693,10 @@ static void btm_ble_resolve_random_addr_on_adv(void * p_rec, void *p) ** 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 @@ -719,7 +738,7 @@ BOOLEAN BTM_BleSetBgConnType(tBTM_BLE_CONN_TYPE bg_conn_type, { 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: @@ -783,41 +802,41 @@ void BTM_BleClearBgConnDev(void) *******************************************************************************/ 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); - } /******************************************************************************* @@ -830,38 +849,87 @@ tBTM_STATUS BTM_BleSetConnMode(BOOLEAN is_directed) ** *******************************************************************************/ 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; } /******************************************************************************* @@ -914,8 +982,8 @@ tBTM_STATUS BTM_BleSetAdvParams(UINT16 adv_int_min, UINT16 adv_int_max, 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, @@ -1433,6 +1501,7 @@ void btm_ble_select_adv_interval(tBTM_BLE_INQ_CB *p_cb, UINT8 evt_type, UINT16 * 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; @@ -1440,6 +1509,7 @@ void btm_ble_select_adv_interval(tBTM_BLE_INQ_CB *p_cb, UINT8 evt_type, UINT16 * 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; @@ -1453,6 +1523,7 @@ void btm_ble_select_adv_interval(tBTM_BLE_INQ_CB *p_cb, UINT8 evt_type, UINT16 * } return; } + /******************************************************************************* ** ** Function btm_ble_update_dmt_flag_bits @@ -1546,22 +1617,20 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) 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); @@ -1575,28 +1644,33 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) /* 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) @@ -1642,14 +1716,14 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_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) @@ -1657,9 +1731,7 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) 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; @@ -1668,23 +1740,30 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) 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; + } } } @@ -1696,6 +1775,7 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) else status = btm_ble_stop_adv(); } + if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) { p_cb->fast_adv_on = TRUE; @@ -1748,7 +1828,7 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration) #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); } @@ -2379,6 +2459,31 @@ BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_t /******************************************************************************* ** +** 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. @@ -2444,6 +2549,10 @@ void btm_ble_process_adv_pkt (UINT8 *p_data) 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); @@ -2454,29 +2563,12 @@ void btm_ble_process_adv_pkt (UINT8 *p_data) 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)) { @@ -2484,10 +2576,7 @@ void btm_ble_process_adv_pkt (UINT8 *p_data) } else #endif -#endif - { btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p); - } STREAM_TO_UINT8(data_len, p); @@ -2626,13 +2715,12 @@ tBTM_STATUS btm_ble_start_scan (UINT8 filter_enable) 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 @@ -2751,6 +2839,10 @@ static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UI 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; @@ -2777,6 +2869,16 @@ tBTM_STATUS btm_ble_start_adv(void) 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(); @@ -2785,11 +2887,8 @@ tBTM_STATUS btm_ble_start_adv(void) 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 @@ -2799,6 +2898,7 @@ tBTM_STATUS btm_ble_start_adv(void) } return rt; } + /******************************************************************************* ** ** Function btm_ble_stop_adv @@ -2833,96 +2933,6 @@ tBTM_STATUS btm_ble_stop_adv(void) /******************************************************************************* ** -** 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 @@ -2932,22 +2942,25 @@ void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 statu *******************************************************************************/ 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(); } @@ -3030,8 +3043,10 @@ void btm_ble_read_remote_features_complete(UINT8 *p) 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); @@ -3090,6 +3105,109 @@ void btm_ble_dir_adv_tout(void) /******************************************************************************* ** +** 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. @@ -3122,7 +3240,6 @@ void btm_ble_init (void) 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 } diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h index 4741ca7e5..cb37ff45a 100644 --- a/stack/btm/btm_ble_int.h +++ b/stack/btm/btm_ble_int.h @@ -93,6 +93,9 @@ typedef UINT8 tBTM_BLE_SEC_REQ_ACT; #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; @@ -136,7 +139,7 @@ typedef struct 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; @@ -248,6 +251,18 @@ typedef UINT16 tBTM_BLE_STATE_MASK; #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; @@ -255,6 +270,17 @@ typedef struct 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 @@ -276,7 +302,6 @@ 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 */ @@ -292,16 +317,18 @@ typedef struct 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 @@ -317,7 +344,8 @@ extern BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda); 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); @@ -325,7 +353,7 @@ extern void btm_ble_init (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); @@ -366,8 +394,12 @@ extern UINT8 btm_ble_read_sec_key_size(BD_ADDR bd_addr); 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); @@ -380,6 +412,7 @@ extern UINT8 btm_ble_count_unconn_dev_in_whitelist(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); @@ -389,9 +422,27 @@ extern void btm_ble_enqueue_direct_conn_req(void *p_param); 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); @@ -407,11 +458,6 @@ extern BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request); 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); diff --git a/stack/btm/btm_ble_multi_adv.c b/stack/btm/btm_ble_multi_adv.c index e9800860f..7055ba930 100644 --- a/stack/btm/btm_ble_multi_adv.c +++ b/stack/btm/btm_ble_multi_adv.c @@ -266,8 +266,8 @@ tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst, 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); @@ -310,8 +310,8 @@ tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst, { 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; @@ -773,12 +773,14 @@ void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p) 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() && diff --git a/stack/btm/btm_ble_privacy.c b/stack/btm/btm_ble_privacy.c new file mode 100644 index 000000000..b905eac81 --- /dev/null +++ b/stack/btm/btm_ble_privacy.c @@ -0,0 +1,823 @@ +/****************************************************************************** + * + * 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 diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c index d3d04813a..3053dbe51 100644 --- a/stack/btm/btm_dev.c +++ b/stack/btm/btm_dev.c @@ -36,7 +36,6 @@ #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); @@ -185,9 +184,6 @@ BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr) 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 */ diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c index 03ed726f2..b725fe29c 100644 --- a/stack/btm/btm_devctl.c +++ b/stack/btm/btm_devctl.c @@ -174,6 +174,15 @@ static void reset_complete(void *result) { 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()); } diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c index 2307051c3..c680baabb 100644 --- a/stack/btm/btm_inq.c +++ b/stack/btm/btm_inq.c @@ -2149,6 +2149,9 @@ void btm_process_inq_complete (UINT8 status, UINT8 mode) /* 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 */ diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h index 37931e76a..7d5cac305 100644 --- a/stack/btm/btm_int.h +++ b/stack/btm/btm_int.h @@ -171,8 +171,11 @@ typedef struct 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; @@ -182,7 +185,6 @@ typedef struct UINT32 test_local_sign_cntr; #endif - #endif /* BLE_INCLUDED */ tBTM_IO_CAP loc_io_caps; /* IO capability of the local device */ @@ -440,6 +442,11 @@ typedef struct 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 */ @@ -460,16 +467,18 @@ typedef struct 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 @@ -503,15 +512,15 @@ typedef struct #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 */ @@ -519,14 +528,17 @@ typedef struct 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 */ @@ -560,6 +572,11 @@ typedef struct 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 ++ @@ -710,6 +727,7 @@ typedef struct void *p_ref_data; UINT32 mx_proto_id; UINT32 mx_chan_id; + tBT_TRANSPORT transport; } tBTM_SEC_QUEUE_ENTRY; #if (L2CAP_UCD_INCLUDED == TRUE) @@ -847,7 +865,6 @@ typedef struct #if (!defined(BT_TRACE_VERBOSE) || (BT_TRACE_VERBOSE == FALSE)) char state_temp_buffer[BTM_STATE_BUFFER_SIZE]; #endif - } tBTM_CB; @@ -979,6 +996,10 @@ extern void btm_read_local_name_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); +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 */ diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c index af7615105..db8622e39 100644 --- a/stack/btm/btm_sec.c +++ b/stack/btm/btm_sec.c @@ -98,6 +98,16 @@ static BOOLEAN btm_dev_encrypted(tBTM_SEC_DEV_REC *p_dev_rec); static BOOLEAN btm_dev_authorized(tBTM_SEC_DEV_REC *p_dev_rec); static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC *p_serv_rec); +static BOOLEAN btm_sec_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] = { @@ -1170,7 +1180,8 @@ tBTM_STATUS BTM_SecBondCancel (BD_ADDR bd_addr) 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 */ @@ -1230,6 +1241,30 @@ tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_addr, LINK_KEY link_key) 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; +} /******************************************************************************* ** @@ -1248,8 +1283,8 @@ tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_addr, LINK_KEY link_key) ** 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 @@ -1261,14 +1296,9 @@ tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_addr, LINK_KEY link_key) 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 @@ -1301,15 +1331,21 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SE 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; @@ -1324,11 +1360,19 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SE #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) @@ -1339,6 +1383,7 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SE (*p_callback) (bd_addr, transport, p_dev_rec->p_ref_data, rc); } } + return(rc); } @@ -1353,32 +1398,51 @@ static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UIN 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; } /******************************************************************************* @@ -1442,8 +1506,6 @@ void BTM_ConfirmReqReply(tBTM_STATUS res, BD_ADDR bd_addr) #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); @@ -1456,7 +1518,8 @@ void BTM_PasskeyReqReply(tBTM_STATUS res, BD_ADDR bd_addr, UINT32 passkey) /* 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; @@ -1484,9 +1547,7 @@ void BTM_PasskeyReqReply(tBTM_STATUS res, BD_ADDR bd_addr, UINT32 passkey) /* 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); } @@ -1585,7 +1646,7 @@ tBTM_STATUS BTM_ReadLocalOobData(void) *******************************************************************************/ 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 */ @@ -1599,9 +1660,7 @@ void BTM_RemoteOobDataReply(tBTM_STATUS res, BD_ADDR bd_addr, BT_OCTET16 c, BT_O /* 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); } @@ -1630,7 +1689,6 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, { 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; @@ -1648,7 +1706,7 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, /* 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; @@ -1705,6 +1763,25 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, /******************************************************************************* ** +** 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 @@ -1791,12 +1868,11 @@ void BTM_SetOutService(BD_ADDR bd_addr, UINT8 service_id, UINT32 mx_chan_id) { 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) @@ -1835,14 +1911,14 @@ static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN 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? @@ -1858,7 +1934,7 @@ static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN 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; } @@ -1874,19 +1950,20 @@ static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC *p_dev_rec, BOOLEAN *******************************************************************************/ 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) @@ -1948,11 +2025,11 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle 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 */ @@ -1966,10 +2043,8 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle /* 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); } @@ -1977,7 +2052,6 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle 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) @@ -2025,7 +2099,7 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle /* 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; @@ -2064,7 +2138,6 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle { if (p_callback) (*p_callback) (bd_addr, transport, (void *)p_ref_data, BTM_SUCCESS); - return(BTM_SUCCESS); } } @@ -2076,7 +2149,6 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle /* Save pointer to service record */ p_dev_rec->p_cur_service = p_serv_rec; - /* mess /w security_required in btm_sec_l2cap_access_req for Lisbon */ if (btm_cb.security_mode == BTM_SEC_MODE_SP) { @@ -2123,7 +2195,7 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle } } - 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; @@ -2195,7 +2267,7 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle 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; } } @@ -2218,8 +2290,9 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle 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) { @@ -2256,7 +2329,6 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle 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; @@ -2264,7 +2336,7 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o 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); @@ -2286,7 +2358,7 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o /* 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; @@ -2351,15 +2423,15 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o /* 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); } } @@ -2551,14 +2623,23 @@ void btm_sec_check_pending_reqs (void) 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); @@ -2577,14 +2658,6 @@ void btm_sec_check_pending_reqs (void) *******************************************************************************/ 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; @@ -2602,8 +2675,7 @@ void btm_sec_init (UINT8 sec_mode) *******************************************************************************/ 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); } @@ -3706,8 +3778,22 @@ void btm_sec_auth_complete (UINT16 handle, UINT8 status) 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; } @@ -3820,18 +3906,62 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) 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) @@ -4316,6 +4446,14 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) 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; @@ -4345,12 +4483,19 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) 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(); @@ -4373,13 +4518,39 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t 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; @@ -5147,7 +5318,7 @@ static tBTM_SEC_SERV_REC *btm_sec_find_mx_serv (UINT8 is_originator, UINT16 psm, 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) @@ -5185,13 +5356,12 @@ static tBTM_SEC_SERV_REC *btm_sec_find_mx_serv (UINT8 is_originator, UINT16 psm, *******************************************************************************/ 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) @@ -5232,16 +5402,10 @@ static void btm_send_link_key_notif (tBTM_SEC_DEV_REC *p_dev_rec) *******************************************************************************/ 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; } /******************************************************************************* @@ -5260,7 +5424,7 @@ static void btm_restore_mode(void) 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)); } @@ -5285,9 +5449,8 @@ static void btm_restore_mode(void) 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)) @@ -5307,8 +5470,9 @@ static void btm_sec_change_pairing_state (tBTM_PAIRING_STATE new_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; @@ -5376,7 +5540,6 @@ static char *btm_pair_state_descr (tBTM_PAIRING_STATE state) } #endif - /******************************************************************************* ** ** Function btm_sec_dev_rec_cback_event @@ -5395,10 +5558,9 @@ void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEA 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(); } @@ -5413,9 +5575,7 @@ static BOOLEAN btm_sec_queue_mx_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN 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) { @@ -5425,11 +5585,12 @@ static BOOLEAN btm_sec_queue_mx_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN 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); @@ -5448,7 +5609,8 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC *p_dev_rec) 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) { @@ -5473,7 +5635,7 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC *p_dev_rec) /* 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); @@ -5486,6 +5648,137 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC *p_dev_rec) 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) /******************************************************************************* ** @@ -5501,12 +5794,15 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC *p_dev_rec) 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); } @@ -5533,7 +5829,7 @@ BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda) { 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); } @@ -5593,9 +5889,62 @@ BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_D 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 */ diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c index c8a45d384..4477dfff9 100644 --- a/stack/btu/btu_hcif.c +++ b/stack/btu/btu_hcif.c @@ -122,6 +122,10 @@ static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p); #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 /******************************************************************************* @@ -318,6 +322,11 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) 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); @@ -892,6 +901,29 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l 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: @@ -1648,9 +1680,14 @@ static void btu_ble_process_adv_pkt (UINT8 *p) 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. */ diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c index 78a7819e6..a102b06d5 100644 --- a/stack/gap/gap_ble.c +++ b/stack/gap/gap_ble.c @@ -31,8 +31,6 @@ #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) @@ -42,18 +40,6 @@ #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 */ @@ -133,7 +119,7 @@ tGAP_CLCB *gap_ble_find_clcb_by_conn_id(UINT16 conn_id) ** 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; @@ -142,9 +128,8 @@ tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda) { 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; } @@ -154,67 +139,75 @@ tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda) /******************************************************************************* ** -** 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 @@ -266,6 +259,12 @@ tGATT_STATUS gap_read_attr_value (UINT16 handle, tGATT_VALUE *p_value, BOOLEAN i 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; } @@ -430,6 +429,14 @@ void gap_attr_db_init(void) 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); @@ -471,13 +478,18 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value) 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; } @@ -488,6 +500,41 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value) /******************************************************************************* ** +** 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 @@ -497,7 +544,7 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value) *******************************************************************************/ 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); @@ -505,15 +552,21 @@ void gap_ble_cl_op_cmpl(tGAP_CLCB *p_clcb, BOOLEAN status, UINT16 len, UINT8 *p_ 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); + } + } } /******************************************************************************* @@ -530,62 +583,27 @@ static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_ 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); } } - } /******************************************************************************* @@ -647,48 +665,62 @@ static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS 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 @@ -701,42 +733,7 @@ BOOLEAN gap_ble_cl_read_request(tGAP_CLCB *p_clcb, UINT16 uuid, void * p_cback) *******************************************************************************/ 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); } /******************************************************************************* @@ -748,51 +745,24 @@ BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda) ** 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); +} /******************************************************************************* ** @@ -811,7 +781,7 @@ BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda) (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; diff --git a/stack/gap/gap_int.h b/stack/gap/gap_int.h index 0f63f3aba..937db64dc 100644 --- a/stack/gap/gap_int.h +++ b/stack/gap/gap_int.h @@ -97,7 +97,7 @@ typedef struct #if BLE_INCLUDED == TRUE -#define GAP_MAX_CHAR_NUM 5 +#define GAP_MAX_CHAR_NUM 4 typedef struct { @@ -114,27 +114,20 @@ 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 @@ -152,9 +145,7 @@ 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; diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c index d7b06e40b..8822d6516 100644 --- a/stack/gatt/gatt_api.c +++ b/stack/gatt/gatt_api.c @@ -1167,6 +1167,10 @@ void GATT_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout, tBT_TRANSPORT trans 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 { diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h index ccdb14819..a1fbb9d02 100644 --- a/stack/gatt/gatt_int.h +++ b/stack/gatt/gatt_int.h @@ -296,8 +296,6 @@ typedef struct #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; diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c index e1e9564f9..d7811364d 100644 --- a/stack/gatt/gatt_main.c +++ b/stack/gatt/gatt_main.c @@ -96,6 +96,7 @@ void gatt_init (void) 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; @@ -1017,20 +1018,18 @@ void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf) *******************************************************************************/ 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); } - } /******************************************************************************* diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c index 5f9ddf01b..439666beb 100755 --- a/stack/gatt/gatt_sr.c +++ b/stack/gatt/gatt_sr.c @@ -1120,7 +1120,10 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle, 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; } diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c index 11d8dff71..5030c5328 100644 --- a/stack/gatt/gatt_utils.c +++ b/stack/gatt/gatt_utils.c @@ -2125,15 +2125,16 @@ void gatt_end_operation(tGATT_CLCB *p_clcb, tGATT_STATUS status, void *p_data) 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); } diff --git a/stack/hcic/hciblecmds.c b/stack/hcic/hciblecmds.c index fa46decaa..9a5e1069d 100644 --- a/stack/hcic/hciblecmds.c +++ b/stack/hcic/hciblecmds.c @@ -80,7 +80,7 @@ BOOLEAN btsnd_hcic_ble_set_random_addr (BD_ADDR random_bda) 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; @@ -103,7 +103,7 @@ BOOLEAN btsnd_hcic_ble_write_adv_params (UINT16 adv_int_min, UINT16 adv_int_max, 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); @@ -768,5 +768,167 @@ BOOLEAN btsnd_hcic_ble_rc_param_req_neg_reply(UINT16 handle, UINT8 reason) } #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 diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c index d8b619da2..0cc697619 100644 --- a/stack/hid/hidh_conn.c +++ b/stack/hid/hidh_conn.c @@ -138,7 +138,7 @@ tHID_STATUS hidh_conn_disconnect (UINT8 dhandle) /* 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); diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h index 441cd1754..8968af640 100644 --- a/stack/include/bt_types.h +++ b/stack/include/bt_types.h @@ -330,6 +330,9 @@ typedef UINT8 BT_OCTET16[BT_OCTET16_LEN]; /* octet array: size 16 */ 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 */ @@ -500,8 +503,11 @@ typedef struct */ #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 diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h index 731ac3462..c108439d7 100644 --- a/stack/include/btm_api.h +++ b/stack/include/btm_api.h @@ -29,9 +29,7 @@ #include "sdp_api.h" #include "hcidefs.h" -#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE #include "smp_api.h" -#endif /***************************************************************************** ** DEVICE CONTROL and COMMON *****************************************************************************/ @@ -206,8 +204,6 @@ typedef UINT8 (tBTM_FILTER_CB) (BD_ADDR bd_addr, DEV_CLASS dc); #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 */ @@ -1087,6 +1083,7 @@ typedef void (tBTM_ESCO_CBACK) (tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) #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 @@ -1129,9 +1126,16 @@ typedef void (tBTM_ESCO_CBACK) (tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) #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 @@ -1456,11 +1460,12 @@ typedef struct 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; @@ -1543,32 +1548,46 @@ typedef void (tBTM_BOND_CANCEL_CMPL_CALLBACK) (tBTM_STATUS result); /* 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 @@ -1593,7 +1612,6 @@ typedef struct { UINT8 reason; UINT8 sec_level; - BOOLEAN privacy_supported; BOOLEAN is_pair_cancel; }tBTM_LE_COMPLT; #endif @@ -1619,6 +1637,7 @@ typedef struct /* BLE Encryption reproduction keys */ typedef struct { + BT_OCTET16 ltk; UINT16 div; UINT8 key_size; UINT8 sec_level; @@ -1630,7 +1649,7 @@ typedef struct UINT32 counter; UINT16 div; UINT8 sec_level; - + BT_OCTET16 csrk; }tBTM_LE_LCSRK_KEYS; typedef struct @@ -1643,10 +1662,10 @@ 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 @@ -1659,9 +1678,12 @@ typedef union { 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; @@ -3280,6 +3302,23 @@ extern tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_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. +** +*******************************************************************************/ +extern tBTM_LINK_KEY_TYPE BTM_SecGetDeviceLinkKeyType (BD_ADDR bd_addr); + + +/******************************************************************************* +** ** Function BTM_PINCodeReply ** ** Description This function is called after Security Manager submitted @@ -3485,6 +3524,18 @@ extern UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, /******************************************************************************* ** +** 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 diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h index 307d39e34..607e6871e 100644 --- a/stack/include/btm_ble_api.h +++ b/stack/include/btm_ble_api.h @@ -47,6 +47,9 @@ typedef UINT8 tBTM_BLE_CHNL_MAP[CHNL_MAP_LEN]; #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 @@ -86,8 +89,15 @@ typedef UINT8 tBTM_BLE_AFP; #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 @@ -317,6 +327,10 @@ typedef UINT32 tBTM_BLE_AD_MASK; #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 */ @@ -1153,6 +1167,20 @@ extern void BTM_BlePasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey); /******************************************************************************* ** +** 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 @@ -1392,21 +1420,6 @@ extern tBTM_STATUS BTM_BleBroadcast(BOOLEAN start); /******************************************************************************* ** -** 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 @@ -1414,10 +1427,10 @@ extern void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback); ** ** 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); /******************************************************************************* ** @@ -1428,7 +1441,21 @@ extern void 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); /******************************************************************************* ** @@ -1443,18 +1470,20 @@ extern UINT8 BTM_BleMaxMultiAdvInstanceCount(); /******************************************************************************* ** -** 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); /******************************************************************************* ** @@ -1472,7 +1501,6 @@ extern tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed); extern void BTM_BleTurnOnPrivacyOnRemote(BD_ADDR bd_addr, BOOLEAN privacy_on); - /******************************************************************************* ** ** Function BTM_BleUpdateAdvWhitelist @@ -1560,6 +1588,45 @@ extern BOOLEAN BTM_UseLeLink (BD_ADDR bd_addr); *******************************************************************************/ 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 */ /******************************************************************************* diff --git a/stack/include/gap_api.h b/stack/include/gap_api.h index 59c1294cb..755c49c0b 100644 --- a/stack/include/gap_api.h +++ b/stack/include/gap_api.h @@ -120,13 +120,12 @@ typedef union 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 @@ -362,33 +361,32 @@ extern BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda); ** 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 diff --git a/stack/include/gattdefs.h b/stack/include/gattdefs.h index 38e18f3d4..bfbec27e6 100644 --- a/stack/include/gattdefs.h +++ b/stack/include/gattdefs.h @@ -47,14 +47,13 @@ /* 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 */ @@ -72,8 +71,8 @@ #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 */ diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h index 63a0bc5d4..31fd90b69 100644 --- a/stack/include/hcidefs.h +++ b/stack/include/hcidefs.h @@ -42,7 +42,7 @@ #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 @@ -237,6 +237,8 @@ #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 @@ -324,15 +326,22 @@ #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) @@ -536,6 +545,21 @@ #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 @@ -658,7 +682,7 @@ #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 @@ -666,6 +690,9 @@ #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 @@ -679,11 +706,6 @@ 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 */ @@ -863,7 +885,12 @@ 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) */ @@ -1065,6 +1092,10 @@ #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 @@ -1230,6 +1261,8 @@ #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 @@ -1723,6 +1756,17 @@ typedef struct #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 */ diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h index 1447ccea7..dfc0d50cb 100644 --- a/stack/include/hcimsgs.h +++ b/stack/include/hcimsgs.h @@ -639,6 +639,10 @@ extern void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode, ** 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 @@ -667,6 +671,15 @@ extern void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode, #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); @@ -681,7 +694,7 @@ extern BOOLEAN btsnd_hcic_ble_set_random_addr (BD_ADDR random_addr); 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); @@ -759,6 +772,36 @@ extern BOOLEAN btsnd_hcic_ble_rc_param_req_neg_reply(UINT16 handle, UINT8 reason #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 diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h index c89efdd76..837dbc852 100644 --- a/stack/include/l2c_api.h +++ b/stack/include/l2c_api.h @@ -567,7 +567,8 @@ extern BOOLEAN L2CA_SetIdleTimeout (UINT16 cid, UINT16 timeout, ** 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); /******************************************************************************* ** @@ -964,6 +965,7 @@ typedef struct 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; diff --git a/stack/include/l2cdefs.h b/stack/include/l2cdefs.h index 86044bf9a..a6e25eb9e 100644 --- a/stack/include/l2cdefs.h +++ b/stack/include/l2cdefs.h @@ -122,7 +122,7 @@ #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 @@ -130,17 +130,33 @@ #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) diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h index 79d1d6fa8..37669b46a 100644 --- a/stack/include/smp_api.h +++ b/stack/include/smp_api.h @@ -29,13 +29,41 @@ #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; @@ -49,19 +77,31 @@ 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; @@ -89,22 +129,55 @@ enum }; 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 @@ -112,14 +185,23 @@ typedef UINT8 tSMP_AUTH_REQ; #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 @@ -134,17 +216,55 @@ 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; @@ -157,9 +277,7 @@ typedef struct 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 @@ -219,6 +337,18 @@ extern BOOLEAN SMP_Register (tSMP_CALLBACK *p_cback); ** *******************************************************************************/ 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 @@ -253,7 +383,7 @@ extern void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res); ** 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)). ** @@ -262,14 +392,28 @@ extern void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 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 +** +*******************************************************************************/ +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, @@ -277,6 +421,18 @@ 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 @@ -295,6 +451,34 @@ extern BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len, 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 diff --git a/stack/l2cap/l2c_api.c b/stack/l2cap/l2c_api.c index 839ad1b5e..3a8d5de48 100644 --- a/stack/l2cap/l2c_api.c +++ b/stack/l2cap/l2c_api.c @@ -833,17 +833,22 @@ BOOLEAN L2CA_SetIdleTimeout (UINT16 cid, UINT16 timeout, BOOLEAN is_global) ** 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 { @@ -855,11 +860,14 @@ BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout) 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; } /******************************************************************************* @@ -1639,18 +1647,6 @@ BOOLEAN L2CA_RemoveFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda) 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); @@ -1700,7 +1696,7 @@ BOOLEAN L2CA_SetFixedChannelTout (BD_ADDR rem_bda, UINT16 fixed_cid, UINT16 idle l2cu_no_dynamic_ccbs (p_lcb); } - return (TRUE); + return TRUE; } #endif /* #if (L2CAP_NUM_FIXED_CHNLS > 0) */ diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c index a2b0a75c9..94ddf4268 100644 --- a/stack/l2cap/l2c_ble.c +++ b/stack/l2cap/l2c_ble.c @@ -35,7 +35,6 @@ #if (BLE_INCLUDED == TRUE) static void l2cble_start_conn_update (tL2C_LCB *p_lcb); -#include "vendor_ble.h" /******************************************************************************* ** ** Function L2CA_CancelBleConnectReq @@ -463,6 +462,8 @@ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE typ 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); @@ -688,12 +689,13 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len) *******************************************************************************/ 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) @@ -705,22 +707,21 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) 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)) @@ -733,8 +734,8 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) 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 */ @@ -879,7 +880,7 @@ void l2c_ble_link_adjust_allocation (void) 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) @@ -894,7 +895,7 @@ void l2c_ble_link_adjust_allocation (void) { 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, diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c index 836f4ba54..fa2fcce52 100644 --- a/stack/l2cap/l2c_link.c +++ b/stack/l2cap/l2c_link.c @@ -385,6 +385,11 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) /* 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; ) @@ -1142,20 +1147,17 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf) 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]) diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c index 00ff2e7b5..d3ee908f2 100644 --- a/stack/l2cap/l2c_utils.c +++ b/stack/l2cap/l2c_utils.c @@ -2815,13 +2815,15 @@ void l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb) 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 */ @@ -3305,6 +3307,10 @@ BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb) 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); @@ -3433,9 +3439,7 @@ void l2cu_check_channel_congestion (tL2C_CCB *p_ccb) 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) { diff --git a/stack/smp/aes.c b/stack/smp/aes.c index d2e86cd7c..54bcda667 100644 --- a/stack/smp/aes.c +++ b/stack/smp/aes.c @@ -45,6 +45,9 @@ #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 @@ -65,7 +68,7 @@ #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 */ @@ -494,6 +497,11 @@ static void inv_shift_sub_rows( uint_8t st[N_BLOCK] ) #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] ) { @@ -502,15 +510,15 @@ return_type aes_set_key( const unsigned char key[], length_type keylen, aes_cont 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: diff --git a/stack/smp/p_256_curvepara.c b/stack/smp/p_256_curvepara.c new file mode 100644 index 000000000..131e76935 --- /dev/null +++ b/stack/smp/p_256_curvepara.c @@ -0,0 +1,80 @@ +/****************************************************************************** + * + * 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; + } +} + diff --git a/stack/smp/p_256_ecc_pp.c b/stack/smp/p_256_ecc_pp.c new file mode 100644 index 000000000..2eaebd4eb --- /dev/null +++ b/stack/smp/p_256_ecc_pp.c @@ -0,0 +1,262 @@ +/****************************************************************************** + * + * 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); +} + + diff --git a/stack/smp/p_256_ecc_pp.h b/stack/smp/p_256_ecc_pp.h new file mode 100644 index 000000000..fd3dc64fe --- /dev/null +++ b/stack/smp/p_256_ecc_pp.h @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * 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); + + diff --git a/stack/smp/p_256_multprecision.c b/stack/smp/p_256_multprecision.c new file mode 100644 index 000000000..f93980957 --- /dev/null +++ b/stack/smp/p_256_multprecision.c @@ -0,0 +1,704 @@ +/****************************************************************************** + * + * 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); +} + diff --git a/stack/smp/p_256_multprecision.h b/stack/smp/p_256_multprecision.h new file mode 100644 index 000000000..0d1a964c3 --- /dev/null +++ b/stack/smp/p_256_multprecision.h @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * 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); + + diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c index 6568316ff..397a2ca4e 100644 --- a/stack/smp/smp_act.c +++ b/stack/smp/smp_act.c @@ -16,40 +16,37 @@ * ******************************************************************************/ +#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 }; /******************************************************************************* @@ -58,65 +55,154 @@ const tSMP_ACT smp_distribute_act [] = *******************************************************************************/ 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_sm_event(p_cb, SMP_IO_RSP_EVT, NULL); + break; + + 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( "new io_cap = %d p_cb->loc_enc_size = %d",p_cb->loc_io_caps, p_cb->loc_enc_size); + 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_sm_event(p_cb, SMP_IO_RSP_EVT, NULL); + smp_br_state_machine_event(p_cb, SMP_BR_KEYS_RSP_EVT, NULL); + break; + } } } @@ -125,8 +211,10 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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. @@ -136,36 +224,23 @@ void smp_send_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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) @@ -174,120 +249,167 @@ void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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 ("smp_send_pair_rsp "); + SMP_TRACE_DEBUG("%s", __func__); - 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); +} - SMP_TRACE_DEBUG ("smp_send_init "); +/******************************************************************************* +** 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); +} -#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_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); +} - smp_send_cmd(SMP_OPCODE_INIT, p_cb); +/******************************************************************************* +** 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); +} + +/******************************************************************************* +** 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); } /******************************************************************************* @@ -296,44 +418,54 @@ void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ 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: @@ -345,6 +477,7 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) break; } } + /******************************************************************************* ** Function smp_proc_sec_grant ** Description process security grant. @@ -352,7 +485,7 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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); @@ -363,15 +496,17 @@ void smp_proc_sec_grant(tSMP_CB *p_cb, tSMP_INT_DATA *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 @@ -382,7 +517,7 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *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_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); @@ -396,43 +531,66 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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 @@ -440,8 +598,16 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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 */ @@ -458,11 +624,298 @@ void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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_rand +** Description process pairing random (nonce) from peer device +*******************************************************************************/ +void smp_proc_rand(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; + } + /* save the SRand for comparison */ STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN); +} + +/******************************************************************************* +** 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_process_pairing_public_key(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; + } + + 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_wait_for_both_public_keys(p_cb, NULL); +} + +/******************************************************************************* +** Function smp_process_pairing_commitment +** Description process pairing commitment from peer device +*******************************************************************************/ +void smp_process_pairing_commitment(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; + } + + p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_COMM; + + if (p != NULL) + { + STREAM_TO_ARRAY(p_cb->remote_commitment, p, BT_OCTET16_LEN); + } +} + +/******************************************************************************* +** Function smp_process_dhkey_check +** Description process DHKey Check from peer device +*******************************************************************************/ +void smp_process_dhkey_check(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; + } + + 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_process_keypress_notification +** Description process pairing keypress notification from peer device +*******************************************************************************/ +void smp_process_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + UINT8 *p = (UINT8 *)p_data; + UINT8 reason = SMP_INVALID_PARAMETERS; + + SMP_TRACE_DEBUG("%s", __func__); + p_cb->status = *(UINT8 *)p_data; + + 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 + { + p_cb->peer_keypress_notification = BTM_SP_KEY_OUT_OF_RANGE; + } + p_cb->cb_evt = SMP_PEER_KEYPR_NOT_EVT; } + +/******************************************************************************* +** Function smp_br_process_pairing_command +** Description Process the SMP pairing request/response from peer device via +** BR/EDR transport. +*******************************************************************************/ +void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + 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("%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) + { + reason = SMP_XTRANS_DERIVE_NOT_ALLOW; + smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason); + return; + } + + /* 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); + + p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR; + + 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 + { + smp_br_state_machine_event(p_cb, SMP_BR_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_enc_info ** Description process encryption information from peer device @@ -471,7 +924,7 @@ void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { UINT8 *p = (UINT8 *)p_data; - SMP_TRACE_DEBUG ("smp_proc_enc_info "); + SMP_TRACE_DEBUG("%s", __func__); STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN); smp_key_distribution(p_cb, NULL); @@ -485,7 +938,7 @@ void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) UINT8 *p = (UINT8 *)p_data; tBTM_LE_PENC_KEYS le_key; - SMP_TRACE_DEBUG (" smp_proc_master_id"); + SMP_TRACE_DEBUG("%s", __func__); smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, TRUE); STREAM_TO_UINT16(le_key.ediv, p); @@ -495,10 +948,15 @@ void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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); + + 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_enc_info ** Description process identity information from peer device @@ -507,11 +965,11 @@ 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 "); + SMP_TRACE_DEBUG("%s", __func__); STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */ - - smp_key_distribution(p_cb, NULL); + smp_key_distribution_by_transport(p_cb, NULL); } + /******************************************************************************* ** Function smp_proc_id_addr ** Description process identity address from peer device @@ -521,7 +979,7 @@ 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 ("smp_proc_id_addr "); + 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); @@ -529,10 +987,12 @@ void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN); /* 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); - - smp_key_distribution(p_cb, NULL); + 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 @@ -541,16 +1001,19 @@ void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { tBTM_LE_PCSRK_KEYS le_key; - SMP_TRACE_DEBUG ("smp_proc_srk_info "); + 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 */ - btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK, (tBTM_LE_KEY_VALUE *)&le_key, TRUE); - smp_key_distribution(p_cb, NULL); + 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); } /******************************************************************************* @@ -561,12 +1024,8 @@ void smp_proc_compare(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)) + 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) @@ -577,8 +1036,8 @@ void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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; + 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); } @@ -590,6 +1049,7 @@ void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); } } + /******************************************************************************* ** Function smp_proc_sl_key ** Description process key ready events. @@ -598,20 +1058,20 @@ 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 ("smp_proc_sl_keysmp_proc_sl_key "); + SMP_TRACE_DEBUG("%s", __func__); if (key_type == SMP_KEY_TYPE_TK) { - smp_generate_confirm(p_cb, NULL); + smp_generate_srand_mrand_confirm(p_cb, NULL); } else if (key_type == SMP_KEY_TYPE_CFM) { - smp_set_state(SMP_ST_WAIT_CONFIRM); + 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 @@ -621,7 +1081,7 @@ void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) tBTM_STATUS cmd; UINT8 reason = SMP_ENC_FAIL; - SMP_TRACE_DEBUG ("smp_start_enc "); + 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 @@ -629,7 +1089,6 @@ void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY) smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); - } /******************************************************************************* @@ -638,39 +1097,10 @@ void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - UNUSED(p_data); - - SMP_TRACE_DEBUG ("smp_proc_discard "); + SMP_TRACE_DEBUG("%s", __func__); if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)) smp_reset_control_value(p_cb); } -/******************************************************************************* -** Function smp_proc_release_delay -** Description process the release delay request -*******************************************************************************/ -void smp_proc_release_delay(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) -{ - UNUSED(p_data); - - 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); -} - -/******************************************************************************* -** Function smp_proc_release_delay_tout -** Description processing the release delay timeout -*******************************************************************************/ -void smp_proc_release_delay_tout(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) -{ - UNUSED(p_data); - - SMP_TRACE_DEBUG ("smp_proc_release_delay_tout "); - btu_stop_timer (&p_cb->rsp_timer_ent); - smp_proc_pairing_cmpl(p_cb); -} - /******************************************************************************* ** Function smp_enc_cmpl @@ -681,11 +1111,10 @@ void smp_enc_cmpl(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 ("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 @@ -695,13 +1124,46 @@ 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 ("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); + 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->loc_i_key || p_cb->loc_r_key)) + (p_cb->local_i_key || p_cb->local_r_key)) { smp_sm_event(p_cb, SMP_BOND_REQ_EVT, NULL); } @@ -728,17 +1190,17 @@ void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ 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 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 ("smp_key_pick_key key_to_dist=0x%x", key_to_dist); - while (i < MAX_KEY_DISTRIBUTION_TYPES) + 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_TRACE_DEBUG("smp_distribute_act[%d]", i); (* smp_distribute_act[i])(p_cb, p_data); break; } @@ -752,120 +1214,114 @@ void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) void smp_key_distribution(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 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->loc_r_key && p_cb->role == HCI_ROLE_MASTER)) + (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER)) { smp_key_pick_key(p_cb, p_data); } - if (!p_cb->loc_i_key && !p_cb->loc_r_key) + if (!p_cb->local_i_key && !p_cb->local_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 (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_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_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_asso_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +void smp_decide_association_model(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); - 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 Association Model = %d", __func__, p_cb->selected_association_model); - /* 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) - { - if (p_cb->role == HCI_ROLE_MASTER) - model = smp_association_table[p_cb->role][p_cb->peer_io_caps][p_cb->loc_io_caps]; + 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 - model = smp_association_table[p_cb->role][p_cb->loc_io_caps][p_cb->peer_io_caps]; - } - } + { + 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; - SMP_TRACE_DEBUG("Association Model = %d", model); + 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 ); - 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; + p_cb->cb_evt = SMP_PASSKEY_REQ_EVT; + int_evt = SMP_TK_REQ_EVT; + break; - 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 ); + 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_PASSKEY_REQ_EVT; - int_evt = SMP_TK_REQ_EVT; - } - else if (model == SMP_MODEL_KEY_NOTIF) - { - p_cb->sec_level = SMP_SEC_AUTHENTICATED; + p_cb->cb_evt = SMP_OOB_REQ_EVT; + int_evt = SMP_TK_REQ_EVT; + break; - SMP_TRACE_DEBUG("Need to generate Passkey"); - /* generate passkey and notify application */ - smp_generate_passkey(p_cb, NULL); - } - 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; + 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; - } - 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; + break; - memset(p_cb->tk, 0, BT_OCTET16_LEN); - /* TK, ready */ - int_evt = SMP_KEY_READY_EVT; - } - } - else if (model == SMP_MODEL_MAX) - { - SMP_TRACE_ERROR("Association Model = SMP_MODEL_MAX (failed)"); - p = (tSMP_INT_DATA *)&failure; - int_evt = SMP_AUTH_CMPL_EVT; + 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 ); @@ -874,24 +1330,67 @@ void smp_decide_asso_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) } /******************************************************************************* -** Function smp_proc_io_rsp +** Function smp_process_io_response ** Description process IO response for a slave device. *******************************************************************************/ -void smp_proc_io_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - UNUSED(p_data); + uint8_t reason = SMP_PAIR_AUTH_FAIL; - SMP_TRACE_DEBUG ("smp_proc_io_rsp "); + SMP_TRACE_DEBUG("%s", __func__); if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) { - smp_set_state(SMP_ST_SEC_REQ_PENDING); + /* 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 /* respond to pairing request */ + 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 @@ -899,21 +1398,15 @@ void smp_proc_io_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - - SMP_TRACE_DEBUG ("smp_pairing_cmpl "); - - if ((p_cb->status == SMP_SUCCESS) || - (p_cb->status <= SMP_REPEATED_ATTEMPTS && p_cb->status != SMP_SUCCESS)) + if (p_cb->total_tx_unacked == 0) { - smp_sm_event(p_cb, SMP_RELEASE_DELAY_EVT, p_data); - } - else - { - /* this will transition to idle state right away */ - smp_sm_event(p_cb, SMP_RELEASE_DELAY_TOUT_EVT, p_data); + /* 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 @@ -921,41 +1414,18 @@ void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { - UNUSED(p_data); - - SMP_TRACE_DEBUG ("smp_pair_terminate "); - + SMP_TRACE_DEBUG("%s", __func__); p_cb->status = SMP_CONN_TOUT; - smp_proc_pairing_cmpl(p_cb); } /******************************************************************************* -** Function smp_delay_terminate -** Description This function is called when connection dropped when smp delay -** timer is still active. -*******************************************************************************/ -void smp_delay_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) -{ - SMP_TRACE_DEBUG ("smp_delay_terminate "); - - btu_stop_timer (&p_cb->rsp_timer_ent); - - /* 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; - - smp_proc_pairing_cmpl(p_cb); -} -/******************************************************************************* ** Function smp_idle_terminate -** Description This function called in idle state to determine to send authentication +** 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) { - UNUSED(p_data); if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) { SMP_TRACE_DEBUG("Pairing terminated at IDLE state."); @@ -971,9 +1441,460 @@ void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { /* disable connection parameter update */ - (void)L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE); + 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_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_start_secure_connection_phase1(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + SMP_TRACE_DEBUG("%s", __func__); + + if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS) + { + p_cb->sec_level = SMP_SEC_UNAUTHENTICATE; + SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ", p_cb->sec_level ); + } + else + { + p_cb->sec_level = SMP_SEC_AUTHENTICATED; + SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level ); + } + + switch(p_cb->selected_association_model) + { + 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; + } +} + +/******************************************************************************* +** Function smp_process_local_nonce +** Description The function processes new local nonce. +** +** Note It is supposed to be called in SC phase1. +*******************************************************************************/ +void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + SMP_TRACE_DEBUG("%s", __func__); + + 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) + { + /* 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->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_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_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + UINT8 reason; + + SMP_TRACE_DEBUG("%s start ", __func__); + + switch(p_cb->selected_association_model) + { + 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) + { + 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 + { + /* 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("%s end ",__FUNCTION__); +} + +/******************************************************************************* +** 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; + + SMP_TRACE_DEBUG("%s", __func__); + + if (memcmp(p_data->key.p_data, p_cb->remote_dhkey_check, BT_OCTET16_LEN)) + { + SMP_TRACE_WARNING ("dhkey chcks do no match"); + p_cb->failure = reason; + smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason); + return; + } + + SMP_TRACE_EVENT ("dhkey chcks match"); + + /* 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 + { + /* 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); + } +} + +/******************************************************************************* +** 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_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_phase_2_dhkey_checks_are_present(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + SMP_TRACE_DEBUG("%s",__func__); + + 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_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_wait_for_both_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + SMP_TRACE_DEBUG("%s",__func__); + + if ((p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY) && + (p_cb->flags & SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY)) + { + 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_start_passkey_verification +** Description Starts SC passkey entry verification. +*******************************************************************************/ +void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + UINT8 *p = NULL; + + SMP_TRACE_DEBUG("%s", __func__); + p = p_cb->local_random; + UINT32_TO_STREAM(p, p_data->passkey); + + p = p_cb->peer_random; + UINT32_TO_STREAM(p, p_data->passkey); + + p_cb->round = 0; + smp_start_nonce_generation(p_cb); +} + +/******************************************************************************* +** Function smp_process_secure_connection_oob_data +** Description Processes local/peer SC OOB data received from somewhere. +*******************************************************************************/ +void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + SMP_TRACE_DEBUG("%s", __func__); + + 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 (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)); + } + } + + 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_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_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + 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_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_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + 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); +} /******************************************************************************* ** @@ -991,7 +1912,7 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable) { 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) { @@ -1006,6 +1927,7 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable) smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable); } } + /******************************************************************************* ** ** Function smp_proc_ltk_request @@ -1018,8 +1940,8 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable) *******************************************************************************/ 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); @@ -1029,5 +1951,113 @@ BOOLEAN smp_proc_ltk_request(BD_ADDR bda) 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); +} + diff --git a/stack/smp/smp_api.c b/stack/smp/smp_api.c index 2ebf9538a..4d7b16df9 100644 --- a/stack/smp/smp_api.c +++ b/stack/smp/smp_api.c @@ -35,7 +35,7 @@ #include "hcimsgs.h" #include "btu.h" - + #include "p_256_ecc_pp.h" /******************************************************************************* ** @@ -48,8 +48,6 @@ *******************************************************************************/ void SMP_Init(void) { - - SMP_TRACE_EVENT ("SMP_Init"); memset(&smp_cb, 0, sizeof(tSMP_CB)); #if defined(SMP_INITIAL_TRACE_LEVEL) @@ -57,8 +55,11 @@ void SMP_Init(void) #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); } @@ -131,8 +132,10 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr) 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; @@ -145,7 +148,7 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr) 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; } @@ -154,6 +157,49 @@ 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. +** 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; +} /******************************************************************************* ** @@ -173,7 +219,7 @@ BOOLEAN SMP_PairCancel (BD_ADDR bd_addr) 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; @@ -200,11 +246,27 @@ BOOLEAN SMP_PairCancel (BD_ADDR bd_addr) 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; @@ -228,7 +290,6 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey) { 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); @@ -246,13 +307,12 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey) 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); @@ -260,6 +320,10 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 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); @@ -270,6 +334,56 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 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 @@ -285,13 +399,11 @@ void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data 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) @@ -314,6 +426,69 @@ void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *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 @@ -337,4 +512,96 @@ BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len, 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 */ diff --git a/stack/smp/smp_br_main.c b/stack/smp/smp_br_main.c new file mode 100644 index 000000000..573db7fbc --- /dev/null +++ b/stack/smp/smp_br_main.c @@ -0,0 +1,397 @@ +/****************************************************************************** + * + * 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 ) ) ; +} + + diff --git a/stack/smp/smp_cmac.c b/stack/smp/smp_cmac.c index 138c6f1df..9ed295735 100644 --- a/stack/smp/smp_cmac.c +++ b/stack/smp/smp_cmac.c @@ -49,7 +49,7 @@ BT_OCTET16 const_Rb = { 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; @@ -278,7 +278,7 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key) } /******************************************************************************* ** -** Function AES_CMAC +** Function aes_cipher_msg_auth_code ** ** Description This is the AES-CMAC Generation Function with tlen implemented. ** @@ -288,17 +288,17 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key) ** 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; @@ -380,7 +380,7 @@ void test_cmac(void) 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 diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h index af5102d23..24aa3ece9 100644 --- a/stack/smp/smp_int.h +++ b/stack/smp/smp_int.h @@ -21,18 +21,26 @@ * 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; @@ -40,27 +48,15 @@ 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 @@ -69,43 +65,136 @@ typedef UINT8 tSMP_ASSO_MODEL; #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 { @@ -117,7 +206,13 @@ 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 @@ -125,6 +220,7 @@ 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 }; @@ -139,6 +235,8 @@ typedef union 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 */ @@ -146,6 +244,10 @@ typedef union #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) @@ -154,40 +256,66 @@ typedef union #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; @@ -195,26 +323,15 @@ typedef struct 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 */ @@ -240,26 +357,53 @@ extern tSMP_CB *smp_cb_ptr; /* 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); @@ -270,14 +414,12 @@ extern void smp_proc_sl_key(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); @@ -289,13 +431,40 @@ extern void smp_send_pair_rsp(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); @@ -307,17 +476,58 @@ extern void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b); 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 */ diff --git a/stack/smp/smp_keys.c b/stack/smp/smp_keys.c index 31313c94f..47d0125b7 100644 --- a/stack/smp/smp_keys.c +++ b/stack/smp/smp_keys.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * 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. @@ -18,33 +18,33 @@ /****************************************************************************** * - * 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); @@ -52,46 +52,84 @@ static void smp_calculate_comfirm_cont(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 - #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]; - #if SMP_DEBUG == TRUE -static void smp_debug_print_nbyte_little_endian (UINT8 *p, const UINT8 *key_name, UINT8 len) + 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; + + 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 +} + +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; + + int ind = 0; + int ncols = 32; /* num entries in one line */ + int nrows; /* num lines */ + int x; - for (i = 0; i < len; i ++) + 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 ** @@ -100,24 +138,24 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len, 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) @@ -131,15 +169,19 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len, 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; @@ -147,10 +189,9 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len, GKI_freebuf(p_start); - return(TRUE); + return TRUE; } - /******************************************************************************* ** ** Function smp_generate_passkey @@ -164,13 +205,14 @@ void smp_generate_passkey(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) { 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 @@ -187,7 +229,7 @@ void smp_proc_passkey(tSMP_CB *p_cb , tBTM_RAND_ENC *p) 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; @@ -207,10 +249,16 @@ void smp_proc_passkey(tSMP_CB *p_cb , tBTM_RAND_ENC *p) (*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 @@ -222,64 +270,58 @@ void smp_proc_passkey(tSMP_CB *p_cb , tBTM_RAND_ENC *p) ** 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. @@ -287,52 +329,65 @@ void smp_generate_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data) ** 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 @@ -345,13 +400,14 @@ void smp_generate_ltk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ 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); @@ -362,7 +418,14 @@ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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 { @@ -375,7 +438,7 @@ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) ** ** 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. ** ** @@ -384,9 +447,10 @@ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ 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); @@ -397,13 +461,12 @@ void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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. @@ -412,17 +475,18 @@ void smp_concatenate_local( tSMP_CB *p_cb, UINT8 **p_data, UINT8 op_code) { 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. @@ -442,6 +506,7 @@ void smp_concatenate_peer( tSMP_CB *p_cb, UINT8 **p_data, UINT8 op_code) *p_data = p; } + /******************************************************************************* ** ** Function smp_gen_p1_4_confirm @@ -495,6 +560,7 @@ void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1) smp_debug_print_nbyte_little_endian ((UINT8 *)p1, (const UINT8 *)"P1", 16); #endif } + /******************************************************************************* ** ** Function smp_gen_p2_4_confirm @@ -540,6 +606,7 @@ void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2) smp_debug_print_nbyte_little_endian(p2, (const UINT8 *)"p2", 16); #endif } + /******************************************************************************* ** ** Function smp_calculate_comfirm @@ -551,10 +618,11 @@ void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2) *******************************************************************************/ 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' */ @@ -576,6 +644,7 @@ void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda) smp_calculate_comfirm_cont(p_cb, &output); } } + /******************************************************************************* ** ** Function smp_calculate_comfirm_cont @@ -612,7 +681,7 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p) } else { - switch (p_cb->rand_enc_proc) + switch (p_cb->rand_enc_proc_state) { case SMP_GEN_CONFIRM: smp_process_confirm(p_cb, &output); @@ -624,9 +693,10 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p) } } } + /******************************************************************************* ** -** 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. @@ -634,17 +704,16 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p) ** 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 @@ -661,12 +730,11 @@ void smp_generate_compare (tSMP_CB *p_cb, tSMP_INT_DATA *p_data) 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 @@ -681,19 +749,8 @@ static void smp_process_confirm(tSMP_CB *p_cb, tSMP_ENC *p) { 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"); @@ -702,9 +759,9 @@ static void smp_process_confirm(tSMP_CB *p_cb, tSMP_ENC *p) 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 @@ -758,28 +815,29 @@ static void smp_process_stk(tSMP_CB *p_cb, tSMP_ENC *p) /******************************************************************************* ** -** 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 @@ -789,7 +847,6 @@ static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) memcpy((void *)p_cb->ltk, output.param_buf, BT_OCTET16_LEN); smp_generate_rand_vector(p_cb, NULL); } - } /******************************************************************************* @@ -803,10 +860,12 @@ static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) *******************************************************************************/ 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); @@ -822,6 +881,7 @@ static void smp_generate_y(tSMP_CB *p_cb, tSMP_INT_DATA *p) smp_process_ediv(p_cb, &output); } } + /******************************************************************************* ** ** Function smp_generate_rand_vector @@ -839,14 +899,14 @@ static void smp_generate_rand_vector (tSMP_CB *p_cb, tSMP_INT_DATA *p) /* 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 ** @@ -874,6 +934,1267 @@ static void smp_process_ediv(tSMP_CB *p_cb, tSMP_ENC *p) /******************************************************************************* ** +** Function smp_calculate_legacy_short_term_key +** +** 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 +** +*******************************************************************************/ +void smp_create_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) +{ + 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); +} + +/******************************************************************************* +** +** 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) + { + 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; + } +} + +/******************************************************************************* +** +** 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); + + 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; + } + + return; +} + +/******************************************************************************* +** +** 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); +} + +/******************************************************************************* +** +** 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; + + 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); + + 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_EVENT ("local commitment calculation is completed"); +} + +/******************************************************************************* +** +** 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, @@ -887,27 +2208,26 @@ 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 & ~0x80; + UINT8 state = p_cb->rand_enc_proc_state & ~0x80; - SMP_TRACE_DEBUG ("smp_rand_back state=0x%x", state); + 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_genenrate_rand_cont(p_cb, NULL); + 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_genenrate_confirm(p_cb, NULL); + smp_generate_confirm(p_cb, NULL); break; case SMP_GEN_DIV_LTK: STREAM_TO_UINT16(p_cb->div, pp); - smp_genenrate_ltk_cont(p_cb, NULL); + smp_generate_ltk_cont(p_cb, NULL); break; case SMP_GEN_DIV_CSRK: @@ -924,15 +2244,30 @@ static void smp_rand_back(tBTM_RAND_ENC *p) 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("smp_rand_back Key generation failed: (%d)", p_cb->rand_enc_proc); - + 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 diff --git a/stack/smp/smp_l2c.c b/stack/smp/smp_l2c.c index 3c91cc08e..7ff278d9b 100644 --- a/stack/smp/smp_l2c.c +++ b/stack/smp/smp_l2c.c @@ -33,10 +33,15 @@ #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); /******************************************************************************* ** @@ -49,7 +54,7 @@ static void smp_data_ind (UINT16 chan, 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; @@ -57,43 +62,49 @@ void smp_l2cap_if_init (void) 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) { @@ -104,7 +115,7 @@ static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN 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); @@ -121,7 +132,7 @@ static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, /******************************************************************************* ** -** Function smp_data_ind +** Function smp_data_received ** ** Description This function is called when data is received from L2CAP on ** SMP channel. @@ -130,19 +141,17 @@ static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, ** 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); @@ -152,7 +161,7 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *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); @@ -160,7 +169,7 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf) 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 */ @@ -168,12 +177,23 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf) 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); @@ -181,4 +201,137 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf) 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 */ diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c index aee15dad1..9f6fde676 100644 --- a/stack/smp/smp_main.c +++ b/stack/smp/smp_main.c @@ -20,25 +20,32 @@ #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", @@ -51,6 +58,10 @@ const char * const smp_event_name [] = "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", @@ -62,18 +73,32 @@ const char * const smp_event_name [] = "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 { @@ -82,14 +107,14 @@ 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, @@ -111,9 +136,31 @@ enum 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 @@ -126,14 +173,14 @@ static const tSMP_ACT smp_sm_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, @@ -142,243 +189,531 @@ static const tSMP_ACT smp_sm_action[] = 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 @@ -386,14 +721,13 @@ tSMP_CB smp_cb; #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, @@ -415,7 +749,6 @@ tSMP_STATE smp_get_state(void) return smp_cb.state; } - /******************************************************************************* ** ** Function smp_sm_event @@ -439,7 +772,7 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data) 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; @@ -453,7 +786,7 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data) /* 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) { @@ -466,7 +799,8 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data) 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; } @@ -493,34 +827,35 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data) 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 diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c index ead44fc6f..9f2e5321a 100644 --- a/stack/smp/smp_utils.c +++ b/stack/smp/smp_utils.c @@ -14,11 +14,11 @@ * 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" @@ -35,10 +35,11 @@ #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) @@ -46,37 +47,230 @@ #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 @@ -86,22 +280,28 @@ const tSMP_CMD_ACT smp_cmd_build_act[] = *******************************************************************************/ 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 @@ -115,7 +315,7 @@ BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb) 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); @@ -133,13 +333,18 @@ BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *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 @@ -155,11 +360,11 @@ void smp_rsp_timeout(TIMER_LIST_ENT *p_tle) 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 { @@ -178,18 +383,19 @@ BT_HDR * smp_build_pairing_cmd(UINT8 cmd_code, tSMP_CB *p_cb) { 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 */ @@ -230,7 +436,7 @@ static BT_HDR * smp_build_confirm_cmd(UINT8 cmd_code, tSMP_CB *p_cb) ** ** 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) @@ -239,16 +445,17 @@ 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; @@ -280,6 +487,7 @@ static BT_HDR * smp_build_encrypt_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb) return p_buf; } + /******************************************************************************* ** ** Function smp_build_master_id_cmd @@ -293,7 +501,8 @@ static BT_HDR * smp_build_master_id_cmd(UINT8 cmd_code, tSMP_CB *p_cb) 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; @@ -308,6 +517,7 @@ static BT_HDR * smp_build_master_id_cmd(UINT8 cmd_code, tSMP_CB *p_cb) return p_buf; } + /******************************************************************************* ** ** Function smp_build_identity_info_cmd @@ -339,6 +549,7 @@ static BT_HDR * smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb) return p_buf; } + /******************************************************************************* ** ** Function smp_build_id_addr_cmd @@ -348,18 +559,18 @@ static BT_HDR * smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb) *******************************************************************************/ 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; @@ -396,6 +607,7 @@ static BT_HDR * smp_build_signing_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb) return p_buf; } + /******************************************************************************* ** ** Function smp_build_pairing_fail @@ -409,7 +621,7 @@ static BT_HDR * smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb) 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; @@ -423,6 +635,7 @@ static BT_HDR * smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb) return p_buf; } + /******************************************************************************* ** ** Function smp_build_security_request @@ -430,14 +643,13 @@ static BT_HDR * smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb) ** 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; @@ -446,7 +658,7 @@ static BT_HDR * smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb) 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 ); } @@ -457,6 +669,128 @@ static BT_HDR * smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb) /******************************************************************************* ** +** 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 @@ -500,6 +834,7 @@ void smp_mask_enc_key(UINT8 loc_enc_size, UINT8 * p_data) } return; } + /******************************************************************************* ** ** Function smp_xor_128 @@ -521,7 +856,6 @@ void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b) } } - /******************************************************************************* ** ** Function smp_cb_cleanup @@ -537,10 +871,31 @@ void smp_cb_cleanup(tSMP_CB *p_cb) 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 @@ -556,27 +911,18 @@ void smp_reset_control_value(tSMP_CB *p_cb) { 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 @@ -590,6 +936,8 @@ void smp_reset_control_value(tSMP_CB *p_cb) 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 "); @@ -607,35 +955,204 @@ void smp_proc_pairing_cmpl(tSMP_CB *p_cb) 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; @@ -649,87 +1166,412 @@ void smp_reject_unexp_pair_req(BD_ADDR bd_addr) } } -#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 diff --git a/vnd/ble/vendor_ble.c b/vnd/ble/vendor_ble.c deleted file mode 100644 index 72c50b3fb..000000000 --- a/vnd/ble/vendor_ble.c +++ /dev/null @@ -1,754 +0,0 @@ -/****************************************************************************** - * - * 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 - diff --git a/vnd/include/vendor_ble.h b/vnd/include/vendor_ble.h deleted file mode 100644 index b235ea9e9..000000000 --- a/vnd/include/vendor_ble.h +++ /dev/null @@ -1,130 +0,0 @@ -/****************************************************************************** - * - * 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 |