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
diff --git a/bta/dm/bta_dm_act.cc b/bta/dm/bta_dm_act.cc
index b6ca628..9cf13f4 100644
--- a/bta/dm/bta_dm_act.cc
+++ b/bta/dm/bta_dm_act.cc
@@ -4055,6 +4055,16 @@
 
       break;
 
+    case BTM_LE_CONSENT_REQ_EVT:
+      bdcpy(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:
       bdcpy(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 e27ba43..22da0b8 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -393,6 +393,7 @@
                                     */
 #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 2be6f0b..42e982b 100644
--- a/btif/include/btif_dm.h
+++ b/btif/include/btif_dm.h
@@ -100,7 +100,7 @@
                                 tBTA_BLE_LOCAL_ID_KEYS* p_id_keys);
 void btif_dm_save_ble_bonding_keys(bt_bdaddr_t 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(BD_ADDR bd_addr, BD_NAME bd_name,
                                           tBT_DEVICE_TYPE dev_type);
diff --git a/btif/src/btif_dm.cc b/btif/src/btif_dm.cc
index 2685027..7daeca4 100644
--- a/btif/src/btif_dm.cc
+++ b/btif/src/btif_dm.cc
@@ -1818,9 +1818,13 @@
           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. ");
@@ -3062,7 +3066,7 @@
  * 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_bdaddr_t bd_addr;
   bt_bdname_t bd_name;
   uint32_t cod;
@@ -3070,7 +3074,7 @@
 
   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 c21af14..32770ca 100644
--- a/stack/btm/btm_ble.cc
+++ b/stack/btm/btm_ble.cc
@@ -1888,6 +1888,7 @@
         /* fall through */
         p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
 
+      case SMP_CONSENT_REQ_EVT:
       case SMP_SEC_REQUEST_EVT:
         if (event == SMP_SEC_REQUEST_EVT &&
             btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) {
@@ -1895,7 +1896,9 @@
           break;
         }
         memcpy(btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN);
-        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;
       /* fall through */
 
diff --git a/stack/include/btm_api_types.h b/stack/include/btm_api_types.h
index a4712da..c2cf5de 100644
--- a/stack/include/btm_api_types.h
+++ b/stack/include/btm_api_types.h
@@ -1559,6 +1559,7 @@
 #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 f300ec4..f0aa457 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 de80190..b140557 100644
--- a/stack/smp/smp_act.cc
+++ b/stack/smp/smp_act.cc
@@ -1260,17 +1260,26 @@
         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);
+        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);
 
-        key.key_type = SMP_KEY_TYPE_TK;
-        key.p_data = p_cb->tk;
-        p = (tSMP_INT_DATA*)&key;
+          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;
+          memset(p_cb->tk, 0, BT_OCTET16_LEN);
+          /* TK, ready  */
+          int_evt = SMP_KEY_READY_EVT;
+        }
       }
       break;
 
@@ -1603,8 +1612,17 @@
       }
 
       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 ebd300b..120f929 100644
--- a/stack/smp/smp_api.cc
+++ b/stack/smp/smp_api.cc
@@ -246,6 +246,37 @@
 void SMP_SecurityGrant(BD_ADDR 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 */
+      uint8_t failure = SMP_NUMERIC_COMPAR_FAIL;
+      smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &failure);
+    }
+  } 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;
+      smp_int_data.key = key;
+
+      memset(smp_cb.tk, 0, BT_OCTET16_LEN);
+      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 */
+      uint8_t failure = SMP_NUMERIC_COMPAR_FAIL;
+      smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &failure);
+    }
+  }
+
   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 ||