Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d47674dc authored by Martin Brabham's avatar Martin Brabham
Browse files

SMP API check for cached OOB data

If OOB data was generated before the pairing was attempted then use the
cached OOB data information for the pairing.  We don't know if it is the
data for the particular device we are attempting to pair with, but it'll
either work or it won't.  And if it doesn't, then it is likely not the
device we intended to pair with.

This will mean that Pixel will only perform double sided
OOB pairing IF it has previously created OOB data.

Data is removed on successful pairing or advertisement timeout.

When the device is the connector, it doesn't need to ask the
app for the OOB data since the OOB data is provided at the time
of create_bond_out_of_band being called.

This should fix the issue with double OOB data pairing scenarios where
this device is the device that initiates the bond.

Bug: 200595320
Test: Manual, test app.
Tag: #feature
Change-Id: Idd94a4ebe9ebeed57026fd915f499d509873e4f0
Merged-In: Idd94a4ebe9ebeed57026fd915f499d509873e4f0
parent 2cf0e4c8
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@ const char* dump_dm_event(uint16_t event) {
    CASE_RETURN_STR(BTA_DM_BLE_PASSKEY_NOTIF_EVT)
    CASE_RETURN_STR(BTA_DM_BLE_PASSKEY_REQ_EVT)
    CASE_RETURN_STR(BTA_DM_BLE_OOB_REQ_EVT)
    CASE_RETURN_STR(BTA_DM_BLE_SC_OOB_REQ_EVT)
    CASE_RETURN_STR(BTA_DM_BLE_LOCAL_IR_EVT)
    CASE_RETURN_STR(BTA_DM_BLE_LOCAL_ER_EVT)
    CASE_RETURN_STR(BTA_DM_BLE_AUTH_CMPL_EVT)
+32 −7
Original line number Diff line number Diff line
@@ -1417,7 +1417,6 @@ void smp_decide_association_model(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 * Description  process IO response for a peripheral device.
 ******************************************************************************/
void smp_process_io_response(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {

  SMP_TRACE_DEBUG("%s", __func__);
  if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
    /* pairing started by local (peripheral) Security Request */
@@ -1442,12 +1441,38 @@ void smp_process_io_response(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {

    // If we are doing SMP_MODEL_SEC_CONN_OOB we don't need to request OOB data
    // locally if loc_oob_flag == 0x00 b/c there is no OOB data to give.  In the
    // event the loc_oob_flag is another value, we should request the OOB data
    // locally.  Which seems to cause it to make a TK REQUEST which is used for
    // the legacy flow which requires both sides to have OOB data.
    if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB &&
        p_cb->loc_oob_flag != 0x00) {
    // event the loc_oob_flag is present value, we should request the OOB data
    // locally; otherwise fail.
    // If we are the initiator the OOB data has already been stored and will be
    // collected in the statemachine later.
    //
    // loc_oob_flag could be one of the following tSMP_OOB_FLAG enum values:
    // SMP_OOB_NONE = 0
    // SMP_OOB_PRESENT = 1
    // SMP_OOB_UNKNOWN = 2
    //
    // The only time Android cares about needing to provide the peer oob data
    // here would be in the advertiser situation or role.  If the
    // device is doing the connecting it will not need to get the data again as
    // it was already provided in the initiation call.
    //
    // loc_oob_flag should only equal SMP_OOB_PRESENT when PEER DATA exists and
    // device is the advertiser as opposed to being the connector.
    if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
      switch (p_cb->loc_oob_flag) {
        case SMP_OOB_NONE:
          LOG_INFO("SMP_MODEL_SEC_CONN_OOB with SMP_OOB_NONE");
          smp_send_pair_rsp(p_cb, NULL);
          break;
        case SMP_OOB_PRESENT:
          LOG_INFO("SMP_MODEL_SEC_CONN_OOB with SMP_OOB_PRESENT");
          if (smp_request_oob_data(p_cb)) return;
          break;
        case SMP_OOB_UNKNOWN:
          LOG_WARN("SMP_MODEL_SEC_CONN_OOB with SMP_OOB_UNKNOWN");
          smp_send_pair_fail(p_cb, NULL);
          return;
      }
    }

    // PTS Testing failure modes
+6 −0
Original line number Diff line number Diff line
@@ -530,6 +530,12 @@ void SMP_SecureConnectionOobDataReply(uint8_t* p_data) {
      if (!p_oob->loc_oob_data.present) data_missing = true;
      break;
    case SMP_OOB_BOTH:
      // Check for previous local OOB data in cache
      // This would be in the case data was generated BEFORE pairing was
      // attempted and this instance is the connector or pairing initiator.
      // [NOTICE]: Overridding data present here if the data exists so state
      // machine asks for it later
      p_oob->loc_oob_data.present = smp_has_local_oob_data();
      if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present)
        data_missing = true;
      break;
+1 −1
Original line number Diff line number Diff line
@@ -465,5 +465,5 @@ extern void smp_xor_128(Octet16* a, const Octet16& b);
 * cleaned up */
extern void smp_save_local_oob_data(tSMP_CB* p_cb);
extern void smp_clear_local_oob_data();

extern bool smp_has_local_oob_data();
#endif /* SMP_INT_H */
+27 −6
Original line number Diff line number Diff line
@@ -70,9 +70,10 @@ static bool is_empty(tSMP_LOC_OOB_DATA* data) {
  return memcmp(data, &empty_data, sizeof(tSMP_LOC_OOB_DATA)) == 0;
}

bool smp_has_local_oob_data() { return !is_empty(&saved_local_oob_data); }

void smp_debug_print_nbyte_little_endian(uint8_t* p, const char* key_name,
                                         uint8_t len) {
}
                                         uint8_t len) {}

inline void smp_debug_print_nbyte_little_endian(const Octet16& p,
                                                const char* key_name,
@@ -82,8 +83,7 @@ inline void smp_debug_print_nbyte_little_endian(const Octet16& p,
}

void smp_debug_print_nbyte_big_endian(uint8_t* p, const char* key_name,
                                      uint8_t len) {
}
                                      uint8_t len) {}

/** This function is called to process a passkey. */
void smp_proc_passkey(tSMP_CB* p_cb, BT_OCTET8 rand) {
@@ -657,6 +657,29 @@ void smp_use_oob_private_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
    case SMP_OOB_BOTH:
    case SMP_OOB_LOCAL:
      LOG_INFO("restore secret key");
      // Only use the stored OOB data if we are in an oob association model
      if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
        LOG_INFO("OOB Association Model");
        // Make sure our data isn't empty, otherwise we generate new and
        // eventually pairing will fail Not much we can do about it at this
        // point, just have to generate new data The data will be cleared after
        // the advertiser times out, so if the advertiser times out we want the
        // pairing to fail anyway.
        if (!is_empty(&saved_local_oob_data)) {
          LOG_INFO("Found OOB data, loading keys");
          for (int i = 0; i < BT_OCTET32_LEN; i++) {
            p_cb->private_key[i] = saved_local_oob_data.private_key_used[i];
            p_cb->loc_publ_key.x[i] = saved_local_oob_data.publ_key_used.x[i];
            p_cb->loc_publ_key.y[i] = saved_local_oob_data.publ_key_used.y[i];
          }
          p_cb->sc_oob_data.loc_oob_data = saved_local_oob_data;
          p_cb->local_random = saved_local_oob_data.randomizer;
          smp_process_private_key(p_cb);
          return;
        }
        LOG_INFO("OOB Association Model with no saved data present");
      }

      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);
@@ -853,7 +876,6 @@ void smp_calculate_numeric_comparison_display_number(tSMP_CB* p_cb,
  return;
}


/*******************************************************************************
 *
 * Function         smp_calculate_local_dhkey_check
@@ -915,7 +937,6 @@ void smp_calculate_peer_dhkey_check(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  smp_sm_event(p_cb, SMP_SC_KEY_READY_EVT, &smp_int_data);
}


/*******************************************************************************
 *
 * Function         smp_calculate_link_key_from_long_term_key