Commit message: None
CVE: CVE-2018-9510
CWE: CWE-200
Vulnerability description: In smp_proc_enc_info of smp_act.cc, there is a possible out of bounds read due to a missing bounds check. This could lead to remote information disclosure over Bluetooth with no additional execution privileges needed. User interaction is not needed for exploitation. Product: Android Versions: Android-7.0 Android-7.1.1 Android-7.1.2 Android-8.0 Android-8.1 Android-9.0 Android ID: A-111937065

Project: Android

static bool lmp_version_below(const RawAddress& bda, uint8_t version) {
  tACL_CONN* acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE);
 if (acl == NULL || acl->lmp_version == 0) {
    SMP_TRACE_WARNING("%s cannot retrieve LMP version...", __func__);
 return false;
 }
  SMP_TRACE_WARNING("%s LMP version %d < %d", __func__, acl->lmp_version,
                    version);
 return acl->lmp_version < version;
}

Project: Android

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", __func__);
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = status;
    smp_sm_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_cb->pairing_bda);
 if (p_dev_rec) {
    SMP_TRACE_DEBUG("%s: dev_type = %d ", __func__, p_dev_rec->device_type);
    p_dev_rec->device_type |= BT_DEVICE_TYPE_BLE;
 } else {
    SMP_TRACE_ERROR("%s failed to find Security Record", __func__);
 }

  SMP_TRACE_DEBUG("%s: LTK derivation from LK successfully completed",
                  __func__);
  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);
}

Project: Android

void smp_br_process_pairing_command(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;
  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) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_XTRANS_DERIVE_NOT_ALLOW;
    smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
 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)) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_INVALID_PARAMETERS;
    smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
 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;
 /* shortcut to skip Security Grant step */
    p_cb->cb_evt = SMP_BR_KEYS_REQ_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;
}

Project: Android

void smp_br_process_security_grant(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s", __func__);
 if (p_data->status != 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;
 }
}

Project: Android

void smp_br_process_slave_keys_response(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  smp_br_send_pair_response(p_cb, NULL);
}

Project: Android

void smp_br_select_next_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  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 (smp_get_br_state() == SMP_BR_STATE_BOND_PENDING) {
 if (p_cb->total_tx_unacked == 0) {
        tSMP_INT_DATA smp_int_data;
        smp_int_data.status = SMP_SUCCESS;
        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
 } else {
        p_cb->wait_for_authorization_complete = true;
 }
 }
 }
}

Project: Android

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);
}

Project: Android

void smp_check_auth_req(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t enc_enable = p_data->status;

  SMP_TRACE_DEBUG(
 "%s rcvs enc_enable=%d i_keys=0x%x r_keys=0x%x (i-initiator r-responder)",
      __func__, enc_enable, p_cb->local_i_key, p_cb->local_r_key);
 if (enc_enable == 1) {
 if (p_cb->le_secure_connections_mode_is_used) {
 /* In LE SC mode LTK is used instead of STK and has to be always saved */
      p_cb->local_i_key |= SMP_SEC_KEY_TYPE_ENC;
      p_cb->local_r_key |= SMP_SEC_KEY_TYPE_ENC;

 /* In LE SC mode LK is derived from LTK only if both sides request it */
 if (!(p_cb->local_i_key & SMP_SEC_KEY_TYPE_LK) ||
 !(p_cb->local_r_key & SMP_SEC_KEY_TYPE_LK)) {
        p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
        p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
 }

 /* In LE SC mode only IRK, IAI, CSRK are exchanged with the peer.
      ** Set local_r_key on master to expect only these keys.
      */
 if (p_cb->role == HCI_ROLE_MASTER) {
        p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK);
 }
 } else {
 /* in legacy mode derivation of BR/EDR LK is not supported */
      p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
      p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
 }
    SMP_TRACE_DEBUG(
 "%s rcvs upgrades: i_keys=0x%x r_keys=0x%x (i-initiator r-responder)",
        __func__, p_cb->local_i_key, p_cb->local_r_key);

 if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
         (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
 (p_cb->local_i_key || p_cb->local_r_key)) {
      smp_sm_event(p_cb, SMP_BOND_REQ_EVT, NULL);
 } else {
      tSMP_INT_DATA smp_int_data;
      smp_int_data.status = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
      smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 }
 } else if (enc_enable == 0) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
 /* if failed for encryption after pairing, send callback */
 if (p_cb->flags & SMP_PAIR_FLAG_ENC_AFTER_PAIR)
      smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 /* if enc failed for old security information */
 /* if master device, clean up and abck to idle; slave device do nothing */
 else if (p_cb->role == HCI_ROLE_MASTER) {
      smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 }
 }
}

Project: Android

void smp_decide_association_model(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t int_evt = 0;
  tSMP_INT_DATA smp_int_data;

  SMP_TRACE_DEBUG("%s Association Model = %d", __func__,
                  p_cb->selected_association_model);

 switch (p_cb->selected_association_model) {
 case SMP_MODEL_ENCRYPTION_ONLY: /* TK = 0, go calculate Confirm */
 if (p_cb->role == HCI_ROLE_MASTER &&
 ((p_cb->peer_auth_req & SMP_AUTH_YN_BIT) != 0) &&
 ((p_cb->loc_auth_req & SMP_AUTH_YN_BIT) == 0)) {
        SMP_TRACE_ERROR(
 "IO capability does not meet authentication requirement");
        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;
        smp_int_data.key = key;

        memset(p_cb->tk, 0, BT_OCTET16_LEN);
 /* TK, ready  */
        int_evt = SMP_KEY_READY_EVT;
 }
 break;

 case SMP_MODEL_PASSKEY:
      p_cb->sec_level = SMP_SEC_AUTHENTICATED;
      SMP_TRACE_EVENT("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ",
                      p_cb->sec_level);

      p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
      int_evt = SMP_TK_REQ_EVT;
 break;

 case SMP_MODEL_OOB:
      SMP_TRACE_ERROR("Association Model = SMP_MODEL_OOB");
      p_cb->sec_level = SMP_SEC_AUTHENTICATED;
      SMP_TRACE_EVENT("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ",
                      p_cb->sec_level);

      p_cb->cb_evt = SMP_OOB_REQ_EVT;
      int_evt = SMP_TK_REQ_EVT;
 break;

 case SMP_MODEL_KEY_NOTIF:
      p_cb->sec_level = SMP_SEC_AUTHENTICATED;
      SMP_TRACE_DEBUG("Need to generate Passkey");

 /* generate passkey and notify application */
      smp_generate_passkey(p_cb, NULL);
 break;

 case SMP_MODEL_SEC_CONN_JUSTWORKS:
 case SMP_MODEL_SEC_CONN_NUM_COMP:
 case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
 case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
 case SMP_MODEL_SEC_CONN_OOB:
      int_evt = SMP_PUBL_KEY_EXCH_REQ_EVT;
 break;

 case SMP_MODEL_OUT_OF_RANGE:
      SMP_TRACE_ERROR("Association Model = SMP_MODEL_OUT_OF_RANGE (failed)");
      smp_int_data.status = SMP_UNKNOWN_IO_CAP;
      int_evt = SMP_AUTH_CMPL_EVT;
 break;

 default:
      SMP_TRACE_ERROR(
 "Association Model = %d (SOMETHING IS WRONG WITH THE CODE)",
          p_cb->selected_association_model);
      smp_int_data.status = SMP_UNKNOWN_IO_CAP;
      int_evt = SMP_AUTH_CMPL_EVT;
 }

  SMP_TRACE_EVENT("sec_level=%d ", p_cb->sec_level);
 if (int_evt) smp_sm_event(p_cb, int_evt, &smp_int_data);
}

Project: Android

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", __func__);
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = status;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }
}

Project: Android

void smp_enc_cmpl(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t enc_enable = p_data->status;

  SMP_TRACE_DEBUG("%s", __func__);
  tSMP_INT_DATA smp_int_data;
  smp_int_data.status = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
  smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
}

Project: Android

void smp_idle_terminate(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
    SMP_TRACE_DEBUG("Pairing terminated at IDLE state.");
    p_cb->status = SMP_FAIL;
    smp_proc_pairing_cmpl(p_cb);
 }
}

Project: Android

void smp_key_distribution(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x", __func__,
                  p_cb->role, p_cb->local_r_key, p_cb->local_i_key);

 if (p_cb->role == HCI_ROLE_SLAVE ||
 (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER)) {
    smp_key_pick_key(p_cb, p_data);
 }

 if (!p_cb->local_i_key && !p_cb->local_r_key) {
 /* state check to prevent re-entrant */
 if (smp_get_state() == SMP_STATE_BOND_PENDING) {
 if (p_cb->derive_lk) {
        smp_derive_link_key_from_long_term_key(p_cb, NULL);
        p_cb->derive_lk = false;
 }

 if (p_cb->total_tx_unacked == 0) {
 /*
         * Instead of declaring authorization complete immediately,
         * delay the event from being sent by SMP_DELAYED_AUTH_TIMEOUT_MS.
         * This allows the slave to send over Pairing Failed if the
         * last key is rejected.  During this waiting window, the
         * state should remain in SMP_STATE_BOND_PENDING.
         */
 if (!alarm_is_scheduled(p_cb->delayed_auth_timer_ent)) {
          SMP_TRACE_DEBUG("%s delaying auth complete.", __func__);
          alarm_set_on_mloop(p_cb->delayed_auth_timer_ent,
                             SMP_DELAYED_AUTH_TIMEOUT_MS,
                             smp_delayed_auth_complete_timeout, NULL);
 }
 } else {
        p_cb->wait_for_authorization_complete = true;
 }
 }
 }
}

Project: Android

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);
 }
}

Project: Android

void smp_key_pick_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t key_to_dist =
 (p_cb->role == HCI_ROLE_SLAVE) ? p_cb->local_r_key : p_cb->local_i_key;
 uint8_t i = 0;

  SMP_TRACE_DEBUG("%s key_to_dist=0x%x", __func__, key_to_dist);
 while (i < SMP_KEY_DIST_TYPE_MAX) {
    SMP_TRACE_DEBUG("key to send = %02x, i = %d", key_to_dist, i);

 if (key_to_dist & (1 << i)) {
      SMP_TRACE_DEBUG("smp_distribute_act[%d]", i);
 (*smp_distribute_act[i])(p_cb, p_data);
 break;
 }
    i++;
 }
}

Project: Android

void smp_link_encrypted(const RawAddress& bda, uint8_t encr_enable) {
  tSMP_CB* p_cb = &smp_cb;

  SMP_TRACE_DEBUG("%s: encr_enable=%d", __func__, encr_enable);

 if (smp_cb.pairing_bda == bda) {
 /* encryption completed with STK, remember the key size now, could be
     * overwritten when key exchange happens                                 */
 if (p_cb->loc_enc_size != 0 && encr_enable) {
 /* update the link encryption key size if a SMP pairing just performed */
      btm_ble_update_sec_key_size(bda, p_cb->loc_enc_size);
 }

    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = encr_enable;
    smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &smp_int_data);
 }
}

Project: Android

void smp_match_dhkey_checks(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {

  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");
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_DHKEY_CHK_FAIL;
    p_cb->failure = SMP_DHKEY_CHK_FAIL;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 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);
 }
}

Project: Android

void smp_pair_terminate(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s", __func__);
  p_cb->status = SMP_CONN_TOUT;
  smp_proc_pairing_cmpl(p_cb);
}

Project: Android

void smp_pairing_cmpl(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 if (p_cb->total_tx_unacked == 0) {
 /* process the pairing complete */
    smp_proc_pairing_cmpl(p_cb);
 }
}

Project: Android

void smp_proc_compare(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s", __func__);
 if (!memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN)) {
 /* compare the max encryption key size, and save the smaller one for the
     * link */
 if (p_cb->peer_enc_size < p_cb->loc_enc_size)
      p_cb->loc_enc_size = p_cb->peer_enc_size;

 if (p_cb->role == HCI_ROLE_SLAVE)
      smp_sm_event(p_cb, SMP_RAND_EVT, NULL);
 else {
 /* master device always use received i/r key as keys to distribute */
      p_cb->local_i_key = p_cb->peer_i_key;
      p_cb->local_r_key = p_cb->peer_r_key;

      smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
 }

 } else {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
    p_cb->failure = SMP_CONFIRM_VALUE_ERR;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 }
}

Project: Android

void smp_proc_confirm(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;

  SMP_TRACE_DEBUG("%s", __func__);

 if (smp_command_has_invalid_parameters(p_cb)) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_INVALID_PARAMETERS;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 if (p != NULL) {
 /* save the SConfirm for comparison later */
    STREAM_TO_ARRAY(p_cb->rconfirm, p, BT_OCTET16_LEN);
 }

  p_cb->flags |= SMP_PAIR_FLAGS_CMD_CONFIRM;
}

Project: Android

void smp_proc_discard(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s", __func__);
 if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
    smp_reset_control_value(p_cb);
}

Project: Android

void smp_proc_id_addr(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;
  tBTM_LE_PID_KEYS pid_key;

  SMP_TRACE_DEBUG("%s", __func__);
  smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ID, true);

  STREAM_TO_UINT8(pid_key.addr_type, p);
  STREAM_TO_BDADDR(pid_key.static_addr, p);
  memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);

 /* to use as BD_ADDR for lk derived from ltk */
  p_cb->id_addr_rcvd = true;
  p_cb->id_addr_type = pid_key.addr_type;
  p_cb->id_addr = pid_key.static_addr;

 /* store the ID key from peer device */
 if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
 (p_cb->loc_auth_req & SMP_AUTH_BOND))
    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
 (tBTM_LE_KEY_VALUE*)&pid_key, true);
  smp_key_distribution_by_transport(p_cb, NULL);
}

Project: Android

void smp_proc_init(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;

  SMP_TRACE_DEBUG("%s", __func__);

 if (smp_command_has_invalid_parameters(p_cb)) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_INVALID_PARAMETERS;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 /* save the SRand for comparison */
  STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
}

Project: Android

bool smp_proc_ltk_request(const RawAddress& bda) {
  SMP_TRACE_DEBUG("%s state = %d", __func__, smp_cb.state);
 bool match = false;

 if (bda == smp_cb.pairing_bda) {
    match = true;
 } else {
    tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bda);
 if (p_dev_rec != NULL && p_dev_rec->ble.pseudo_addr == smp_cb.pairing_bda &&
        p_dev_rec->ble.pseudo_addr != RawAddress::kEmpty) {
      match = true;
 }
 }

 if (match && smp_cb.state == SMP_STATE_ENCRYPTION_PENDING) {
    smp_sm_event(&smp_cb, SMP_ENC_REQ_EVT, NULL);
 return true;
 }

 return false;
}

Project: Android

void smp_proc_master_id(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;
  tBTM_LE_PENC_KEYS le_key;

  SMP_TRACE_DEBUG("%s", __func__);

 if (p_cb->rcvd_cmd_len < 11) { // 1(Code) + 2(EDIV) + 8(Rand)
    android_errorWriteLog(0x534e4554, "111937027");
    SMP_TRACE_ERROR("%s: Invalid command length: %d, should be at least 11",
                    __func__, p_cb->rcvd_cmd_len);
 return;
 }

  smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ENC, true);

  STREAM_TO_UINT16(le_key.ediv, p);
  STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN);

 /* store the encryption keys from peer device */
  memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
  le_key.sec_level = p_cb->sec_level;
  le_key.key_size = p_cb->loc_enc_size;

 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);

 }

Project: Android

void smp_proc_pair_cmd(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;
  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_cb->pairing_bda);

  SMP_TRACE_DEBUG("%s: pairing_bda=%s", __func__,
                  p_cb->pairing_bda.ToString().c_str());

 /* 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)) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_INVALID_PARAMETERS;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 if (pts_test_send_authentication_complete_failure(p_cb)) return;

 if (p_cb->role == HCI_ROLE_SLAVE) {
 if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)) {
 /* 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 */
 {
 /* pairing 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->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(
 "%s: pairing failed - slave requires secure connection only mode",
            __func__);
        tSMP_INT_DATA smp_int_data;
        smp_int_data.status = SMP_PAIR_AUTH_FAIL;
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 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");
      tSMP_INT_DATA smp_int_data;
      smp_int_data.status = SMP_PAIR_AUTH_FAIL;
      smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 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);
 }
 }
}

Project: Android

void smp_proc_pair_fail(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s", __func__);
  p_cb->status = p_data->status;

 /* Cancel pending auth complete timer if set */
  alarm_cancel(p_cb->delayed_auth_timer_ent);
}

Project: Android

void smp_proc_rand(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;

  SMP_TRACE_DEBUG("%s", __func__);

 if (smp_command_has_invalid_parameters(p_cb)) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_INVALID_PARAMETERS;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 /* save the SRand for comparison */
  STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
}

Project: Android

void smp_proc_sec_grant(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t res = p_data->status;
  SMP_TRACE_DEBUG("%s", __func__);
 if (res != SMP_SUCCESS) {
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, p_data);
 } else /*otherwise, start pairing */
 {
 /* send IO request callback */
    p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
 }
}

Project: Android

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;

  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("%s: sec_req_act=0x%x", __func__, sec_req_act);

 switch (sec_req_act) {
 case 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:
      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) {
        tSMP_INT_DATA smp_int_data;
        smp_int_data.status = SMP_PAIR_AUTH_FAIL;
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 } 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:
      p_cb->discard_sec_req = true;
 break;

 default:
 /* do nothing */
 break;
 }
}

Project: Android

void smp_proc_sl_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t key_type = p_data->key.key_type;

  SMP_TRACE_DEBUG("%s", __func__);
 if (key_type == SMP_KEY_TYPE_TK) {
    smp_generate_srand_mrand_confirm(p_cb, NULL);
 } else if (key_type == SMP_KEY_TYPE_CFM) {
    smp_set_state(SMP_STATE_WAIT_CONFIRM);

 if (p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM)
      smp_sm_event(p_cb, SMP_CONFIRM_EVT, NULL);
 }
}

Project: Android

void smp_process_dhkey_check(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;

  SMP_TRACE_DEBUG("%s", __func__);

 if (smp_command_has_invalid_parameters(p_cb)) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_INVALID_PARAMETERS;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 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;
}

Project: Android

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 (slave) Security Request */
    smp_set_state(SMP_STATE_SEC_REQ_PENDING);
    smp_send_cmd(SMP_OPCODE_SEC_REQ, p_cb);
 } else /* plan to send pairing respond */
 {
 /* pairing started by peer (master) Pairing Request */
    p_cb->selected_association_model = smp_select_association_model(p_cb);

 if (p_cb->secure_connections_only_mode_required &&
 (!(p_cb->le_secure_connections_mode_is_used) ||
 (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS))) {
      SMP_TRACE_ERROR(
 "Slave requires secure connection only mode "
 "but it can't be provided -> Slave fails pairing");
      tSMP_INT_DATA smp_int_data;
      smp_int_data.status = SMP_PAIR_AUTH_FAIL;
      smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB) {
 if (smp_request_oob_data(p_cb)) return;
 }

 if (pts_test_send_authentication_complete_failure(p_cb)) return;

    smp_send_pair_rsp(p_cb, NULL);
 }
}

Project: Android

void smp_process_keypress_notification(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;

  SMP_TRACE_DEBUG("%s", __func__);
  p_cb->status = p_data->status;

 if (smp_command_has_invalid_parameters(p_cb)) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_INVALID_PARAMETERS;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 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;
}

Project: Android

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;
 }
}

Project: Android

void smp_process_pairing_commitment(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = p_data->p_data;

  SMP_TRACE_DEBUG("%s", __func__);

 if (smp_command_has_invalid_parameters(p_cb)) {
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_INVALID_PARAMETERS;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

  p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_COMM;

 if (p != NULL) {
    STREAM_TO_ARRAY(p_cb->remote_commitment, p, BT_OCTET16_LEN);
 }
}

Project: Android

void smp_process_peer_nonce(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s start ", __func__);

 if (p_cb->cert_failure == SMP_CONFIRM_VALUE_ERR) {
    SMP_TRACE_ERROR("%s failure case = %d", __func__, p_cb->cert_failure);
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
    p_cb->failure = SMP_CONFIRM_VALUE_ERR;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }
 if ((p_cb->cert_failure == SMP_NUMERIC_COMPAR_FAIL) &&
 (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS) &&
 (p_cb->role == HCI_ROLE_SLAVE)) {
    SMP_TRACE_ERROR("%s failure case = %d", __func__, p_cb->cert_failure);
    tSMP_INT_DATA smp_int_data;
    smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
    p_cb->failure = SMP_NUMERIC_COMPAR_FAIL;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 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)) {
          tSMP_INT_DATA smp_int_data;
          smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
          p_cb->failure = SMP_CONFIRM_VALUE_ERR;
          smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 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) &&
          p_cb->cert_failure != SMP_NUMERIC_COMPAR_FAIL) {
        tSMP_INT_DATA smp_int_data;
        smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
        p_cb->failure = SMP_CONFIRM_VALUE_ERR;
        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 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 ", __func__);
}

Project: Android

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);
}

Project: Android

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("%s: local OOB randomizer is absent", __func__);
    memset(p_cb->local_random, 0, sizeof(p_cb->local_random));
 }

 if (!p_sc_oob_data->peer_oob_data.present) {
    SMP_TRACE_EVENT("%s: peer OOB data is absent", __func__);
    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));

 /* check commitment */
 if (!smp_check_commitment(p_cb)) {
      tSMP_INT_DATA smp_int_data;
      smp_int_data.status = SMP_CONFIRM_VALUE_ERR;
      p_cb->failure = SMP_CONFIRM_VALUE_ERR;
      smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
 return;
 }

 if (p_cb->peer_oob_flag != SMP_OOB_PRESENT) {
 /* the peer doesn't have local randomiser */
      SMP_TRACE_EVENT(
 "%s: peer didn't receive local OOB data, set local randomizer to 0",
          __func__);
      memset(p_cb->local_random, 0, sizeof(p_cb->local_random));
 }
 }

  print128(p_cb->local_random, (const uint8_t*)"local OOB randomizer");
  print128(p_cb->peer_random, (const uint8_t*)"peer OOB randomizer");
  smp_start_nonce_generation(p_cb);
}

Project: Android

void smp_send_app_cback(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  tSMP_EVT_DATA cb_data;
  tSMP_STATUS callback_rc;
  SMP_TRACE_DEBUG("%s p_cb->cb_evt=%d", __func__, p_cb->cb_evt);
 if (p_cb->p_callback && p_cb->cb_evt != 0) {
 switch (p_cb->cb_evt) {
 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("%s: callback_rc=%d  p_cb->cb_evt=%d", __func__,
                    callback_rc, p_cb->cb_evt);

 if (callback_rc == SMP_SUCCESS) {
 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;
 /* just for PTS, force SC bit */
 if (p_cb->secure_connections_only_mode_required) {
            p_cb->loc_auth_req |= SMP_SC_SUPPORT_BIT;
 }

 if (!p_cb->secure_connections_only_mode_required &&
 (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) ||
               lmp_version_below(p_cb->pairing_bda, HCI_PROTO_VERSION_4_2) ||
               interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS,
 (const RawAddress*)&p_cb->pairing_bda))) {
            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 (lmp_version_below(p_cb->pairing_bda, HCI_PROTO_VERSION_5_0)) {
            p_cb->loc_auth_req &= ~SMP_H7_SUPPORT_BIT;
 }

          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->loc_auth_req |= SMP_H7_SUPPORT_BIT;

          p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
          p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;

          SMP_TRACE_WARNING(
 "for SMP over BR max_key_size: 0x%02x, local_i_key: 0x%02x, "
 "local_r_key: 0x%02x, p_cb->loc_auth_req: 0x%02x",
              p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key,
              p_cb->loc_auth_req);

          smp_br_state_machine_event(p_cb, SMP_BR_KEYS_RSP_EVT, NULL);
 break;
 }
 }
 }

 if (!p_cb->cb_evt && p_cb->discard_sec_req) {
    p_cb->discard_sec_req = false;
    smp_sm_event(p_cb, SMP_DISCARD_SEC_REQ_EVT, NULL);
 }

  SMP_TRACE_DEBUG("%s: return", __func__);
}

Project: Android

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);
}

Project: Android

void smp_send_confirm(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s", __func__);
  smp_send_cmd(SMP_OPCODE_CONFIRM, p_cb);
}

Project: Android

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);
}

Project: Android

void smp_send_id_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  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);

 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_TRACE_WARNING("%s", __func__);
  smp_key_distribution_by_transport(p_cb, NULL);
}

Project: Android

void smp_send_init(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s", __func__);
  smp_send_cmd(SMP_OPCODE_INIT, p_cb);
}

Project: Android

void smp_send_ltk_reply(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  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);
}

Project: Android

void smp_send_pair_fail(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  p_cb->status = p_data->status;
  p_cb->failure = p_data->status;

  SMP_TRACE_DEBUG("%s: status=%d failure=%d ", __func__, p_cb->status,
                  p_cb->failure);

 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;
 }
}

Project: Android

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);
}

Project: Android

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);
  SMP_TRACE_DEBUG("%s", __func__);

 /* erase all keys when master sends pairing req*/
 if (p_dev_rec) btm_sec_clear_ble_keys(p_dev_rec);
 /* do not manipulate the key, let app decide,
     leave out to BTM to mandate key distribution for bonding case */
  smp_send_cmd(SMP_OPCODE_PAIRING_REQ, p_cb);
}

Project: Android

void smp_send_pair_rsp(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;

 if (smp_send_cmd(SMP_OPCODE_PAIRING_RSP, p_cb)) {
 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);
 }
}

Project: Android

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);
}

Project: Android

void smp_set_derive_link_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  SMP_TRACE_DEBUG("%s", __func__);
  p_cb->derive_lk = true;
  smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_LK, false);
  smp_key_distribution(p_cb, NULL);
}

Project: Android

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);
}

Project: Android

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_t* p_print = NULL;
  SMP_TRACE_DEBUG("local SC OOB data set:");
  p_print = (uint8_t*)&p_cb->sc_oob_data.loc_oob_data.addr_sent_to;
  smp_debug_print_nbyte_little_endian(p_print, "addr_sent_to",
 sizeof(tBLE_BD_ADDR));
  p_print = (uint8_t*)&p_cb->sc_oob_data.loc_oob_data.private_key_used;
  smp_debug_print_nbyte_little_endian(p_print, "private_key_used",
                                      BT_OCTET32_LEN);
  p_print = (uint8_t*)&p_cb->sc_oob_data.loc_oob_data.publ_key_used.x;
  smp_debug_print_nbyte_little_endian(p_print, "publ_key_used.x",
                                      BT_OCTET32_LEN);
  p_print = (uint8_t*)&p_cb->sc_oob_data.loc_oob_data.publ_key_used.y;
  smp_debug_print_nbyte_little_endian(p_print, "publ_key_used.y",
                                      BT_OCTET32_LEN);
  p_print = (uint8_t*)&p_cb->sc_oob_data.loc_oob_data.randomizer;
  smp_debug_print_nbyte_little_endian(p_print, "randomizer", BT_OCTET16_LEN);
  p_print = (uint8_t*)&p_cb->sc_oob_data.loc_oob_data.commitment;
  smp_debug_print_nbyte_little_endian(p_print, "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);
}

Project: Android

void smp_start_passkey_verification(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* 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);
}

Project: Android

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;
 }
}

Project: Android

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);
 }
}