SMP: Delay authorization complete.
Delay authorization complete during Bond Pending state in SMP.
Instead of automatically advancing the Bond Pending state, create
a 500ms window to allow the slave to stop pairing by sending over
the Pairing Failed command during the Bond Pending state.
BUG: 28475887
Change-Id: Id6c30247d15258cd18eb34827694b6cd79ca753a
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index 1e3effe..7422898 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -24,6 +24,8 @@
#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] =
{
@@ -553,6 +555,9 @@
{
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);
}
/*******************************************************************************
@@ -1287,7 +1292,6 @@
*******************************************************************************/
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);
@@ -1309,9 +1313,22 @@
}
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;
+ }
}
}
}
diff --git a/stack/smp/smp_api.c b/stack/smp/smp_api.c
index b3373b5..ddf9ba4 100644
--- a/stack/smp/smp_api.c
+++ b/stack/smp/smp_api.c
@@ -52,6 +52,7 @@
{
memset(&smp_cb, 0, sizeof(tSMP_CB));
smp_cb.smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
+ smp_cb.delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
#if defined(SMP_INITIAL_TRACE_LEVEL)
smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index fbb4289..aea8538 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -51,6 +51,7 @@
#endif
#define SMP_WAIT_FOR_RSP_TIMEOUT_MS (30 * 1000)
+#define SMP_DELAYED_AUTH_TIMEOUT_MS 500
#define SMP_OPCODE_INIT 0x04
@@ -340,7 +341,8 @@
UINT16 total_tx_unacked;
BOOLEAN wait_for_authorization_complete;
UINT8 cert_failure; /*failure case for certification */
-} tSMP_CB;
+ alarm_t *delayed_auth_timer_ent;
+}tSMP_CB;
/* Server Action functions are of this type */
typedef void (*tSMP_ACT)(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
@@ -481,6 +483,7 @@
extern void smp_convert_string_to_tk(BT_OCTET16 tk, UINT32 passkey);
extern void smp_mask_enc_key(UINT8 loc_enc_size, UINT8 * p_data);
extern void smp_rsp_timeout(void *data);
+extern void smp_delayed_auth_complete_timeout(void *data);
extern void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b);
extern BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
UINT8 *plain_text, UINT8 pt_len,
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index 2d80343..c3709f8 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -240,7 +240,7 @@
/* PAIR_RSP */{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* CONFIRM */{ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* RAND */{ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
-/* PAIR_FAIL */{ 0, 0x81, 0, 0x81, 0x81,0x81, 0x81,0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0, 0, 0 },
+/* PAIR_FAIL */{ 0, 0x81, 0, 0x81, 0x81,0x81, 0x81,0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0, 0x81, 0 },
/* ENC_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
/* MASTER_ID */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 },
/* ID_INFO */{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 },
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index 0be94c4..a7357db 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -375,6 +375,30 @@
/*******************************************************************************
**
+** Function smp_delayed_auth_complete_timeout
+**
+** Description Called when no pairing failed command received within timeout
+** period.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_delayed_auth_complete_timeout(UNUSED_ATTR void *data)
+{
+ /*
+ * Waited for potential pair failure. Send SMP_AUTH_CMPL_EVT if
+ * the state is still in bond pending.
+ */
+ if (smp_get_state() == SMP_STATE_BOND_PENDING)
+ {
+ UINT8 reason = SMP_SUCCESS;
+ SMP_TRACE_EVENT("%s sending delayed auth complete.", __func__);
+ smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &reason);
+ }
+}
+
+/*******************************************************************************
+**
** Function smp_build_pairing_req_cmd
**
** Description Build pairing request command.
@@ -842,10 +866,12 @@
SMP_TRACE_EVENT("smp_cb_cleanup");
alarm_free(p_cb->smp_rsp_timer_ent);
+ alarm_free(p_cb->delayed_auth_timer_ent);
memset(p_cb, 0, sizeof(tSMP_CB));
p_cb->p_callback = p_callback;
p_cb->trace_level = trace_level;
p_cb->smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
+ p_cb->delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
}
/*******************************************************************************