Commit message: None
CVE: CVE-2018-9508
CWE: CWE-125
Vulnerability description: In smp_process_keypress_notification of smp_act.cc, there is a possible out of bounds read due to an incorrect 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 ID: A-111936834

Project: Android

void smp_br_check_authorization_request(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t reason = SMP_SUCCESS;

  SMP_TRACE_DEBUG("%s rcvs i_keys=0x%x r_keys=0x%x (i-initiator r-responder)",
                  __func__, 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);
 }

 /* Check if H7 function needs to be used for key derivation*/
 if ((p_cb->loc_auth_req & SMP_H7_SUPPORT_BIT) &&
 (p_cb->peer_auth_req & SMP_H7_SUPPORT_BIT)) {
    p_cb->key_derivation_h7_used = TRUE;
 }
  SMP_TRACE_DEBUG("%s: use h7 = %d", __func__, p_cb->key_derivation_h7_used);

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

Project: Android

void smp_br_process_pairing_command(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = (uint8_t*)p_data;
 uint8_t 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;
 /* 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) {
 uint8_t res = *(uint8_t*)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;
 }
}

Project: Android

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

Project: Android

void smp_check_auth_req(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t enc_enable = *(uint8_t*)p_data;
 uint8_t reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;

  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
      smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
 } else if (enc_enable == 0) {
 /* 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, &reason);
 /* 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, &reason);
 }
 }
}

Project: Android

void smp_decide_association_model(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t failure = SMP_UNKNOWN_IO_CAP;
 uint8_t int_evt = 0;
  tSMP_KEY key;
  tSMP_INT_DATA* p = NULL;

  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");
        failure = SMP_PAIR_AUTH_FAIL;
        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;

        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)");
      p = (tSMP_INT_DATA*)&failure;
      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);
      p = (tSMP_INT_DATA*)&failure;
      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, p);
}

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

    smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
 }
}

Project: Android

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

Project: Android

void smp_proc_compare(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t reason;

  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 {
    reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
 }
}

Project: Android

void smp_proc_confirm(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = (uint8_t*)p_data;
 uint8_t 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) {
 /* 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_id_addr(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = (uint8_t*)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_id_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t* p = (uint8_t*)p_data;

  SMP_TRACE_DEBUG("%s", __func__);
  STREAM_TO_ARRAY(p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */
  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 = (uint8_t*)p_data;
 uint8_t 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);
}

Project: Android

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

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

  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_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
 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__);
        reason = SMP_PAIR_AUTH_FAIL;
        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;
 } 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;
 }

 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 = *(uint8_t*)p_data;

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

Project: Android

void smp_proc_sec_grant(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t res = *(uint8_t*)p_data;
  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;
 uint8_t reason;

  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) {
        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:
      p_cb->discard_sec_req = true;
 break;

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

Project: Android

void smp_proc_srk_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  tBTM_LE_PCSRK_KEYS le_key;

  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;

 /* get peer CSRK */
  maybe_non_aligned_memcpy(le_key.csrk, p_data, BT_OCTET16_LEN);

 /* initialize the peer counter */
  le_key.counter = 0;

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

Project: Android

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

Project: Android

void smp_process_io_response(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t reason = SMP_PAIR_AUTH_FAIL;

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

 if (pts_test_send_authentication_complete_failure(p_cb)) return;

    smp_send_pair_rsp(p_cb, NULL);
 }
}

Project: Android

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

 Point pt;
  memcpy(pt.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN);
  memcpy(pt.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN);

 if (!ECC_ValidatePoint(pt)) {
    android_errorWriteLog(0x534e4554, "72377774");
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
 return;
 }

  p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY;

  smp_wait_for_both_public_keys(p_cb, NULL);
}

Project: Android

void smp_process_peer_nonce(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
 uint8_t reason;

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

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

 uint8_t 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(
 "%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_keypress_notification(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  p_cb->local_keypress_notification = *(uint8_t*)p_data;
  smp_send_cmd(SMP_OPCODE_PAIR_KEYPR_NOTIF, p_cb);
}

Project: Android

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

  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_start_enc(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  tBTM_STATUS cmd;
 uint8_t reason = SMP_ENC_FAIL;

  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
    cmd = btm_ble_start_encrypt(p_cb->pairing_bda, false, NULL);

 if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY)
    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
}