*
******************************************************************************/
+#include <log/log.h>
#include <string.h>
#include "device/include/interop.h"
#include "include/bt_target.h"
#include "stack/btm/btm_int.h"
#include "stack/include/l2c_api.h"
+#include "stack/smp/p_256_ecc_pp.h"
#include "stack/smp/smp_int.h"
#include "utils/include/bt_utils.h"
+extern fixed_queue_t *btu_general_alarm_queue;
+
#if SMP_INCLUDED == TRUE
const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
{
return acl->lmp_version < version;
}
+static bool pts_test_send_authentication_complete_failure(tSMP_CB *p_cb)
+{
+ uint8_t reason = 0;
+
+ if (p_cb->cert_failure < 2 || p_cb->cert_failure > 6)
+ return false;
+
+ SMP_TRACE_ERROR("%s failure case = %d", __func__, p_cb->cert_failure);
+
+ switch (p_cb->cert_failure)
+ {
+ case 2:
+ reason = SMP_PAIR_AUTH_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ break;
+ case 3:
+ reason = SMP_PAIR_FAIL_UNKNOWN;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ break;
+ case 4:
+ reason = SMP_PAIR_NOT_SUPPORT;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ break;
+ case 5:
+ reason = SMP_PASSKEY_ENTRY_FAIL;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ break;
+ case 6:
+ reason = SMP_REPEATED_ATTEMPTS;
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ break;
+ }
+
+ return true;;
+}
+
/*******************************************************************************
** Function smp_update_key_mask
** Description This function updates the key mask for sending or receiving.
*******************************************************************************/
void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- tBTM_LE_LENC_KEYS le_key;
+ tBTM_LE_KEY_VALUE key;
SMP_TRACE_DEBUG("%s p_cb->loc_enc_size = %d", __func__, p_cb->loc_enc_size);
smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
smp_send_cmd(SMP_OPCODE_MASTER_ID, p_cb);
/* save the DIV and key size information when acting as slave device */
- memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
- le_key.div = p_cb->div;
- le_key.key_size = p_cb->loc_enc_size;
- le_key.sec_level = p_cb->sec_level;
+ memcpy(key.lenc_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+ key.lenc_key.div = p_cb->div;
+ key.lenc_key.key_size = p_cb->loc_enc_size;
+ key.lenc_key.sec_level = p_cb->sec_level;
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_LENC,
- (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, &key, TRUE);
SMP_TRACE_WARNING ("%s", __func__);
*******************************************************************************/
void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- tBTM_LE_LCSRK_KEYS key;
+ tBTM_LE_KEY_VALUE key;
SMP_TRACE_DEBUG("%s", __func__);
smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, FALSE);
if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb))
{
- key.div = p_cb->div;
- key.sec_level = p_cb->sec_level;
- key.counter = 0; /* initialize the local counter */
- memcpy (key.csrk, p_cb->csrk, BT_OCTET16_LEN);
- btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, (tBTM_LE_KEY_VALUE *)&key, TRUE);
+ key.lcsrk_key.div = p_cb->div;
+ key.lcsrk_key.sec_level = p_cb->sec_level;
+ key.lcsrk_key.counter = 0; /* initialize the local counter */
+ memcpy (key.lcsrk_key.csrk, p_cb->csrk, BT_OCTET16_LEN);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, &key, TRUE);
}
smp_key_distribution_by_transport(p_cb, NULL);
{
SMP_TRACE_DEBUG("%s", __func__);
p_cb->status = *(UINT8 *)p_data;
+
+ /* Cancel pending auth complete timer if set */
+ alarm_cancel(p_cb->delayed_auth_timer_ent);
}
/*******************************************************************************
return;
}
+ // PTS Testing failure modes
+ 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))
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);
UINT8 reason = SMP_INVALID_PARAMETERS;
SMP_TRACE_DEBUG("%s", __func__);
- p_cb->status = *(UINT8 *)p_data;
if (smp_command_has_invalid_parameters(p_cb))
{
+ if (p_cb->rcvd_cmd_len < 2) { // 1 (opcode) + 1 (Notif Type) bytes
+ android_errorWriteLog(0x534e4554, "111936834");
+ }
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
+ p_cb->status = *(UINT8 *)p_data;
+
if (p != NULL)
{
STREAM_TO_UINT8(p_cb->peer_keypress_notification, p);
UINT8 *p = (UINT8 *)p_data;
SMP_TRACE_DEBUG("%s", __func__);
+
+ if (smp_command_has_invalid_parameters(p_cb)) {
+ uint8_t reason = SMP_INVALID_PARAMETERS;
+ android_errorWriteLog(0x534e4554, "111937065");
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
+
STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
smp_key_distribution(p_cb, NULL);
void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 *p = (UINT8 *)p_data;
- tBTM_LE_PENC_KEYS le_key;
+ tBTM_LE_KEY_VALUE 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 );
+ STREAM_TO_UINT16(le_key.penc_key.ediv, p);
+ STREAM_TO_ARRAY(le_key.penc_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;
+ memcpy(le_key.penc_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+ le_key.penc_key.sec_level = p_cb->sec_level;
+ le_key.penc_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);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, &le_key, TRUE);
smp_key_distribution(p_cb, NULL);
}
/*******************************************************************************
-** Function smp_proc_enc_info
+** Function smp_proc_id_info
** Description process identity information from peer device
*******************************************************************************/
void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
UINT8 *p = (UINT8 *)p_data;
SMP_TRACE_DEBUG("%s", __func__);
+
+ if (smp_command_has_invalid_parameters(p_cb)) {
+ uint8_t reason = SMP_INVALID_PARAMETERS;
+ android_errorWriteLog(0x534e4554, "111937065");
+ smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+ return;
+ }
+
STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */
smp_key_distribution_by_transport(p_cb, NULL);
}
void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 *p = (UINT8 *)p_data;
- tBTM_LE_PID_KEYS pid_key;
+ tBTM_LE_KEY_VALUE 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);
+ STREAM_TO_UINT8(pid_key.pid_key.addr_type, p);
+ STREAM_TO_BDADDR(pid_key.pid_key.static_addr, p);
+ memcpy(pid_key.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;
- memcpy(p_cb->id_addr, pid_key.static_addr, BD_ADDR_LEN);
+ p_cb->id_addr_type = pid_key.pid_key.addr_type;
+ memcpy(p_cb->id_addr, pid_key.pid_key.static_addr, BD_ADDR_LEN);
/* 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);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, &pid_key, TRUE);
smp_key_distribution_by_transport(p_cb, NULL);
}
*******************************************************************************/
void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- tBTM_LE_PCSRK_KEYS le_key;
+ tBTM_LE_KEY_VALUE 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;
- memcpy (le_key.csrk, p_data, BT_OCTET16_LEN); /* get peer CSRK */
- le_key.counter = 0; /* initialize the peer counter */
+ le_key.pcsrk_key.sec_level = p_cb->sec_level;
+ memcpy (le_key.pcsrk_key.csrk, p_data, BT_OCTET16_LEN); /* get peer CSRK */
+ le_key.pcsrk_key.counter = 0; /* initialize the peer counter */
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);
+ btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK, &le_key, TRUE);
smp_key_distribution_by_transport(p_cb, NULL);
}
*******************************************************************************/
void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- UINT8 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->total_tx_unacked == 0)
- smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
- else
+ {
+ /*
+ * 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_queue(p_cb->delayed_auth_timer_ent, SMP_DELAYED_AUTH_TIMEOUT_MS,
+ smp_delayed_auth_complete_timeout, NULL, btu_general_alarm_queue);
+ }
+ } else {
p_cb->wait_for_authorization_complete = TRUE;
+ }
}
}
}
{
if (smp_request_oob_data(p_cb)) return;
}
+
+ // PTS Testing failure modes
+ if (pts_test_send_authentication_complete_failure(p_cb))
+ return;
+
smp_send_pair_rsp(p_cb, NULL);
}
}
{
if (p_cb->total_tx_unacked == 0)
{
- /* update connection parameter to remote preferred */
- L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, TRUE);
/* process the pairing complete */
smp_proc_pairing_cmpl(p_cb);
}
*******************************************************************************/
void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
- /* disable connection parameter update */
- L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+ /* Disable L2CAP connection parameter updates while bonding since
+ some peripherals are not able to revert to fast connection parameters
+ during the start of service discovery. Connection paramter updates
+ get enabled again once service discovery completes. */
+ L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, false);
}
/*******************************************************************************
SMP_TRACE_DEBUG("%s start ", __func__);
+ // PTS Testing failure modes
+ if (p_cb->cert_failure == 1) {
+ 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;
+ }
+
switch(p_cb->selected_association_model)
{
case SMP_MODEL_SEC_CONN_JUSTWORKS:
break;
case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
- if (!smp_check_commitment(p_cb))
+ if (!smp_check_commitment(p_cb) && p_cb->cert_failure != 9)
{
reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);