From fe287947a1c54efc34e82ff86f125dcbfc86aaf8 Mon Sep 17 00:00:00 2001 From: Rahul Sabnis Date: Fri, 26 Jun 2020 10:27:07 -0700 Subject: [PATCH] Shows a consent dialog on the local device when pairing a bluetooth low energy device if the local device has a display. Tag: #security Bug: 157038281 Test: Manual Merged-In: I7de396230beb84bd0fa2b0cea346523b6824472a Change-Id: I7de396230beb84bd0fa2b0cea346523b6824472a --- bta/dm/bta_dm_act.cc | 10 ++++++++++ bta/include/bta_api.h | 1 + btif/include/btif_dm.h | 2 +- btif/src/btif_dm.cc | 10 +++++++--- stack/btm/btm_ble.cc | 5 ++++- stack/include/btm_api_types.h | 1 + stack/include/smp_api_types.h | 1 + stack/smp/smp_act.cc | 46 ++++++++++++++++++++++++++++++------------- stack/smp/smp_api.cc | 33 +++++++++++++++++++++++++++++++ 9 files changed, 90 insertions(+), 19 deletions(-) diff --git a/bta/dm/bta_dm_act.cc b/bta/dm/bta_dm_act.cc index 7ba3c7425..5ca3542b1 100644 --- a/bta/dm/bta_dm_act.cc +++ b/bta/dm/bta_dm_act.cc @@ -3797,6 +3797,16 @@ static uint8_t bta_dm_ble_smp_cback(tBTM_LE_EVT event, const RawAddress& bda, break; + case BTM_LE_CONSENT_REQ_EVT: + sec_event.ble_req.bd_addr = bda; + p_name = BTM_SecReadDevName(bda); + if (p_name != NULL) + strlcpy((char*)sec_event.ble_req.bd_name, p_name, BD_NAME_LEN); + else + sec_event.ble_req.bd_name[0] = 0; + bta_dm_cb.p_sec_cback(BTA_DM_BLE_CONSENT_REQ_EVT, &sec_event); + break; + case BTM_LE_SEC_REQUEST_EVT: sec_event.ble_req.bd_addr = bda; p_name = BTM_SecReadDevName(bda); diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h index d58f18334..b12725a9d 100644 --- a/bta/include/bta_api.h +++ b/bta/include/bta_api.h @@ -387,6 +387,7 @@ typedef uint8_t tBTA_SIG_STRENGTH_MASK; */ #define BTA_DM_ENER_INFO_READ 28 /* Energy info read */ #define BTA_DM_BLE_SC_OOB_REQ_EVT 29 /* SMP SC OOB request event */ +#define BTA_DM_BLE_CONSENT_REQ_EVT 30 /* SMP consent request event */ typedef uint8_t tBTA_DM_SEC_EVT; /* Structure associated with BTA_DM_ENABLE_EVT */ diff --git a/btif/include/btif_dm.h b/btif/include/btif_dm.h index a9d4cb6c4..a6c39eb82 100644 --- a/btif/include/btif_dm.h +++ b/btif/include/btif_dm.h @@ -102,7 +102,7 @@ void btif_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK* p_key_mask, tBTA_BLE_LOCAL_ID_KEYS* p_id_keys); void btif_dm_save_ble_bonding_keys(RawAddress& bd_addr); void btif_dm_remove_ble_bonding_keys(void); -void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ* p_ble_req); +void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ* p_ble_req, bool is_consent); void btif_dm_update_ble_remote_properties(const RawAddress& bd_addr, BD_NAME bd_name, diff --git a/btif/src/btif_dm.cc b/btif/src/btif_dm.cc index 2a84aa924..503f8234b 100644 --- a/btif/src/btif_dm.cc +++ b/btif/src/btif_dm.cc @@ -1797,9 +1797,13 @@ static void btif_dm_upstreams_evt(uint16_t event, char* p_param) { break; } break; + case BTA_DM_BLE_CONSENT_REQ_EVT: + BTIF_TRACE_DEBUG("BTA_DM_BLE_CONSENT_REQ_EVT. "); + btif_dm_ble_sec_req_evt(&p_data->ble_req, true); + break; case BTA_DM_BLE_SEC_REQ_EVT: BTIF_TRACE_DEBUG("BTA_DM_BLE_SEC_REQ_EVT. "); - btif_dm_ble_sec_req_evt(&p_data->ble_req); + btif_dm_ble_sec_req_evt(&p_data->ble_req, false); break; case BTA_DM_BLE_PASSKEY_NOTIF_EVT: BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_NOTIF_EVT. "); @@ -3009,14 +3013,14 @@ void btif_dm_remove_ble_bonding_keys(void) { * Returns void * ******************************************************************************/ -void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ* p_ble_req) { +void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ* p_ble_req, bool is_consent) { bt_bdname_t bd_name; uint32_t cod; int dev_type; BTIF_TRACE_DEBUG("%s", __func__); - if (pairing_cb.state == BT_BOND_STATE_BONDING) { + if (!is_consent && pairing_cb.state == BT_BOND_STATE_BONDING) { BTIF_TRACE_DEBUG("%s Discard security request", __func__); return; } diff --git a/stack/btm/btm_ble.cc b/stack/btm/btm_ble.cc index 3f6787607..b1f4119d5 100644 --- a/stack/btm/btm_ble.cc +++ b/stack/btm/btm_ble.cc @@ -1917,6 +1917,7 @@ uint8_t btm_proc_smp_cback(tSMP_EVT event, const RawAddress& bd_addr, p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED; FALLTHROUGH_INTENDED; /* FALLTHROUGH */ + case SMP_CONSENT_REQ_EVT: case SMP_SEC_REQUEST_EVT: if (event == SMP_SEC_REQUEST_EVT && btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) { @@ -1924,7 +1925,9 @@ uint8_t btm_proc_smp_cback(tSMP_EVT event, const RawAddress& bd_addr, break; } btm_cb.pairing_bda = bd_addr; - p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING; + if (event != SMP_CONSENT_REQ_EVT) { + p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING; + } btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE; FALLTHROUGH_INTENDED; /* FALLTHROUGH */ diff --git a/stack/include/btm_api_types.h b/stack/include/btm_api_types.h index 965087cbb..0d3d7d4b6 100644 --- a/stack/include/btm_api_types.h +++ b/stack/include/btm_api_types.h @@ -1569,6 +1569,7 @@ typedef void(tBTM_BOND_CANCEL_CMPL_CALLBACK)(tBTM_STATUS result); #define BTM_LE_LAST_FROM_SMP BTM_LE_BR_KEYS_REQ_EVT /* KEY update event */ #define BTM_LE_KEY_EVT (BTM_LE_LAST_FROM_SMP + 1) +#define BTM_LE_CONSENT_REQ_EVT SMP_CONSENT_REQ_EVT typedef uint8_t tBTM_LE_EVT; #define BTM_LE_KEY_NONE 0 diff --git a/stack/include/smp_api_types.h b/stack/include/smp_api_types.h index cee120421..96e7d9efd 100644 --- a/stack/include/smp_api_types.h +++ b/stack/include/smp_api_types.h @@ -59,6 +59,7 @@ /* SC OOB local data set is created (as result of SMP_CrLocScOobData(...)) */ #define SMP_SC_LOC_OOB_DATA_UP_EVT 10 #define SMP_BR_KEYS_REQ_EVT 12 /* SMP over BR keys request event */ +#define SMP_CONSENT_REQ_EVT 14 /* Consent request event */ typedef uint8_t tSMP_EVT; /* pairing failure reason code */ diff --git a/stack/smp/smp_act.cc b/stack/smp/smp_act.cc index 21b960be6..123954222 100644 --- a/stack/smp/smp_act.cc +++ b/stack/smp/smp_act.cc @@ -1301,18 +1301,27 @@ void smp_decide_association_model(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) { smp_int_data.status = SMP_PAIR_AUTH_FAIL; 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); - - tSMP_KEY key; - key.key_type = SMP_KEY_TYPE_TK; - key.p_data = p_cb->tk.data(); - smp_int_data.key = key; - - p_cb->tk = {0}; - /* TK, ready */ - int_evt = SMP_KEY_READY_EVT; + if (p_cb->local_io_capability != SMP_IO_CAP_NONE && + p_cb->local_io_capability != SMP_IO_CAP_IN) { + /* display consent dialog if this device has a display */ + SMP_TRACE_DEBUG("ENCRYPTION_ONLY showing Consent Dialog"); + p_cb->cb_evt = SMP_CONSENT_REQ_EVT; + smp_set_state(SMP_STATE_WAIT_NONCE); + smp_sm_event(p_cb, SMP_SC_DSPL_NC_EVT, NULL); + } else { + p_cb->sec_level = SMP_SEC_UNAUTHENTICATE; + SMP_TRACE_EVENT("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ", + p_cb->sec_level); + + tSMP_KEY key; + key.key_type = SMP_KEY_TYPE_TK; + key.p_data = p_cb->tk.data(); + smp_int_data.key = key; + + p_cb->tk = {0}; + /* TK, ready */ + int_evt = SMP_KEY_READY_EVT; + } } break; @@ -1647,8 +1656,17 @@ void smp_process_peer_nonce(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) { } 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); + if (p_cb->local_io_capability != SMP_IO_CAP_NONE && + p_cb->local_io_capability != SMP_IO_CAP_IN) { + /* display consent dialog */ + SMP_TRACE_DEBUG("JUST WORKS showing Consent Dialog"); + p_cb->cb_evt = SMP_CONSENT_REQ_EVT; + smp_set_state(SMP_STATE_WAIT_NONCE); + smp_sm_event(p_cb, SMP_SC_DSPL_NC_EVT, NULL); + } else { + /* 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); diff --git a/stack/smp/smp_api.cc b/stack/smp/smp_api.cc index baa41cf02..b701f27bb 100644 --- a/stack/smp/smp_api.cc +++ b/stack/smp/smp_api.cc @@ -249,6 +249,39 @@ bool SMP_PairCancel(const RawAddress& bd_addr) { void SMP_SecurityGrant(const RawAddress& bd_addr, uint8_t res) { SMP_TRACE_EVENT("SMP_SecurityGrant "); + // If JUSTWORKS, this is used to display the consent dialog + if (smp_cb.selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS) { + if (res == SMP_SUCCESS) { + smp_sm_event(&smp_cb, SMP_SC_NC_OK_EVT, NULL); + } else { + SMP_TRACE_WARNING("%s() - Consent dialog fails for JUSTWORKS", __func__); + /* send pairing failure */ + tSMP_INT_DATA smp_int_data; + smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL; + smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &smp_int_data); + } + } else if (smp_cb.selected_association_model == SMP_MODEL_ENCRYPTION_ONLY) { + if (res == SMP_SUCCESS) { + smp_cb.sec_level = SMP_SEC_UNAUTHENTICATE; + + tSMP_KEY key; + tSMP_INT_DATA smp_int_data; + key.key_type = SMP_KEY_TYPE_TK; + key.p_data = smp_cb.tk.data(); + smp_int_data.key = key; + + smp_cb.tk = {0}; + smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data); + } else { + SMP_TRACE_WARNING("%s() - Consent dialog fails for ENCRYPTION_ONLY", + __func__); + /* send pairing failure */ + tSMP_INT_DATA smp_int_data; + smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL; + smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &smp_int_data); + } + } + 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 || smp_cb.pairing_bda != bd_addr) { -- 2.11.0