mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-11-11 15:00:34 +00:00
fix(nimble): Fix for BLERP attack
This commit is contained in:
@@ -10840,8 +10840,8 @@ ble_gap_reset_irk(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
ble_gap_unpair(const ble_addr_t *peer_addr)
|
||||
static int
|
||||
ble_gap_unpair_ex(const ble_addr_t *peer_addr, bool terminate)
|
||||
{
|
||||
|
||||
#if NIMBLE_BLE_SM
|
||||
@@ -10882,7 +10882,9 @@ ble_gap_unpair(const ble_addr_t *peer_addr)
|
||||
defer_add_pending = 1;
|
||||
}
|
||||
#endif
|
||||
ble_gap_terminate_with_conn(conn, BLE_ERR_REM_USER_CONN_TERM);
|
||||
if (terminate) {
|
||||
ble_gap_terminate_with_conn(conn, BLE_ERR_REM_USER_CONN_TERM);
|
||||
}
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
@@ -10977,10 +10979,23 @@ ble_gap_unpair(const ble_addr_t *peer_addr)
|
||||
|
||||
return 0;
|
||||
#else
|
||||
(void)terminate;
|
||||
return BLE_HS_ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
ble_gap_unpair(const ble_addr_t *peer_addr)
|
||||
{
|
||||
return ble_gap_unpair_ex(peer_addr, true);
|
||||
}
|
||||
|
||||
int
|
||||
ble_gap_unpair_keep_conn(const ble_addr_t *peer_addr)
|
||||
{
|
||||
return ble_gap_unpair_ex(peer_addr, false);
|
||||
}
|
||||
|
||||
int
|
||||
ble_gap_unpair_oldest_peer(void)
|
||||
{
|
||||
|
||||
@@ -194,6 +194,7 @@ void ble_gap_preempt(void);
|
||||
void ble_gap_preempt_done(void);
|
||||
|
||||
int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason);
|
||||
int ble_gap_unpair_keep_conn(const ble_addr_t *peer_addr);
|
||||
void ble_gap_reset_state(int reason);
|
||||
void ble_gap_conn_broken(uint16_t conn_handle, int reason);
|
||||
int32_t ble_gap_timer(void);
|
||||
|
||||
+243
-28
@@ -46,6 +46,7 @@
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "host/ble_sm.h"
|
||||
#include "host/ble_store.h"
|
||||
#include "ble_hs_priv.h"
|
||||
#include "ble_hs_resolv_priv.h"
|
||||
#include "../store/config/src/ble_store_config_priv.h"
|
||||
@@ -994,13 +995,20 @@ ble_sm_read_bond(uint16_t conn_handle, struct ble_store_value_sec *out_bond)
|
||||
static int
|
||||
ble_sm_chk_repeat_pairing(uint16_t conn_handle,
|
||||
ble_sm_proc_flags proc_flags,
|
||||
uint8_t key_size)
|
||||
uint8_t key_size, uint8_t *out_sm_err,
|
||||
bool *out_terminate, bool *out_keep_bond)
|
||||
{
|
||||
struct ble_gap_repeat_pairing rp;
|
||||
struct ble_store_value_sec bond;
|
||||
struct ble_hs_conn *conn;
|
||||
bool link_encrypted;
|
||||
int rc;
|
||||
int delete_retries;
|
||||
|
||||
*out_sm_err = 0;
|
||||
*out_terminate = false;
|
||||
*out_keep_bond = false;
|
||||
|
||||
delete_retries = 0;
|
||||
do {
|
||||
#if MYNEWT_VAL(BLE_DEFER_CONN_EVENTS)
|
||||
@@ -1033,6 +1041,21 @@ ble_sm_chk_repeat_pairing(uint16_t conn_handle,
|
||||
return rc;
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
conn = ble_hs_conn_find(conn_handle);
|
||||
link_encrypted = conn != NULL && conn->bhc_sec_state.encrypted;
|
||||
ble_hs_unlock();
|
||||
#if MYNEWT_VAL(BLE_SMP_REQUIRE_ENC_BEFORE_REPAIR)
|
||||
if (!link_encrypted) {
|
||||
*out_sm_err = BLE_SM_ERR_AUTHREQ;
|
||||
*out_terminate = true;
|
||||
*out_keep_bond = true;
|
||||
return BLE_HS_EALREADY;
|
||||
}
|
||||
#else
|
||||
(void)link_encrypted;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_DEFER_CONN_EVENTS)
|
||||
/*
|
||||
* Repeat pairing needs a synchronous app decision and cannot be
|
||||
@@ -1063,6 +1086,22 @@ ble_sm_chk_repeat_pairing(uint16_t conn_handle,
|
||||
rp.new_sc = !!(proc_flags & BLE_SM_PROC_F_SC);
|
||||
rp.new_bonding = !!(proc_flags & BLE_SM_PROC_F_BONDING);
|
||||
|
||||
/*
|
||||
* A repeat pairing must not reduce the security of an existing bond.
|
||||
* Applications may still explicitly delete the bond and retry when a
|
||||
* replacement with equal or stronger security is intentional.
|
||||
*/
|
||||
if (MYNEWT_VAL(BLE_SMP_HARDENED_REPAIRING) &&
|
||||
((bond.sc && !rp.new_sc) ||
|
||||
(bond.authenticated && !rp.new_authenticated) ||
|
||||
(key_size < bond.key_size))) {
|
||||
*out_sm_err = key_size < bond.key_size ? BLE_SM_ERR_ENC_KEY_SZ
|
||||
: BLE_SM_ERR_AUTHREQ;
|
||||
*out_terminate = true;
|
||||
*out_keep_bond = true;
|
||||
return BLE_HS_EALREADY;
|
||||
}
|
||||
|
||||
rc = ble_gap_repeat_pairing_event(&rp);
|
||||
if (rc == BLE_GAP_REPEAT_PAIRING_RETRY) {
|
||||
delete_retries++;
|
||||
@@ -1084,6 +1123,57 @@ ble_sm_chk_repeat_pairing(uint16_t conn_handle,
|
||||
return BLE_HS_EALREADY;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ble_sm_maybe_remove_bond_on_fail(uint16_t conn_handle,
|
||||
const struct ble_sm_result *res)
|
||||
{
|
||||
struct ble_hs_conn_addrs addrs;
|
||||
struct ble_hs_conn *conn;
|
||||
ble_addr_t peer;
|
||||
int is_master;
|
||||
|
||||
if (res == NULL ||
|
||||
res->keep_bond ||
|
||||
!res->enc_cb ||
|
||||
res->app_status == 0 ||
|
||||
res->app_status == BLE_HS_ENOTCONN) {
|
||||
/* Link drop is not a pairing failure. ble_sm_connection_broken()
|
||||
* still sets enc_cb with ENOTCONN while the conn object exists;
|
||||
* unpairing here would wipe IRK after a successful bond.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
#if !MYNEWT_VAL(BLE_SMP_REMOVE_BOND_ON_PAIR_FAIL_AS_CENTRAL) && \
|
||||
!MYNEWT_VAL(BLE_SMP_REMOVE_BOND_ON_PAIR_FAIL_AS_PERIPHERAL)
|
||||
return;
|
||||
#else
|
||||
ble_hs_lock();
|
||||
conn = ble_hs_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
ble_hs_unlock();
|
||||
return;
|
||||
}
|
||||
is_master = !!(conn->bhc_flags & BLE_HS_CONN_F_MASTER);
|
||||
ble_hs_conn_addrs(conn, &addrs);
|
||||
peer = addrs.peer_id_addr;
|
||||
ble_hs_unlock();
|
||||
|
||||
if (is_master) {
|
||||
#if !MYNEWT_VAL(BLE_SMP_REMOVE_BOND_ON_PAIR_FAIL_AS_CENTRAL)
|
||||
return;
|
||||
#endif
|
||||
} else {
|
||||
#if !MYNEWT_VAL(BLE_SMP_REMOVE_BOND_ON_PAIR_FAIL_AS_PERIPHERAL)
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
ble_gap_unpair_keep_conn(&peer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res,
|
||||
bool tx_fail)
|
||||
@@ -1139,12 +1229,21 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res,
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
if (res && res->terminate) {
|
||||
ble_gap_terminate(conn_handle, BLE_ERR_AUTH_FAIL);
|
||||
}
|
||||
|
||||
/* Erase bond before BLE_RESTART_PAIR so repeat-pairing sees no bond. */
|
||||
ble_sm_maybe_remove_bond_on_fail(conn_handle, res);
|
||||
|
||||
if (proc == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_RESTART_PAIR)
|
||||
if (res->app_status == BLE_HS_HCI_ERR(BLE_ERR_PINKEY_MISSING)) {
|
||||
if (!res->terminate &&
|
||||
!res->restore &&
|
||||
res->app_status == BLE_HS_HCI_ERR(BLE_ERR_PINKEY_MISSING)) {
|
||||
ble_hs_lock();
|
||||
conn = ble_hs_conn_find(conn_handle);
|
||||
if (conn == NULL) {
|
||||
@@ -1349,6 +1448,7 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
|
||||
{
|
||||
struct ble_sm_result res;
|
||||
struct ble_sm_proc *proc;
|
||||
bool terminate_conn;
|
||||
int authenticated;
|
||||
int bonded;
|
||||
int key_size;
|
||||
@@ -1359,6 +1459,7 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
|
||||
authenticated = 0;
|
||||
bonded = 0;
|
||||
key_size = 0;
|
||||
terminate_conn = false;
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
@@ -1402,6 +1503,21 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
|
||||
}
|
||||
bonded = 1;
|
||||
res.restore = 1;
|
||||
if (evt_status != 0) {
|
||||
if (evt_status == BLE_ERR_PINKEY_MISSING &&
|
||||
(proc->flags & BLE_SM_PROC_F_INITIATOR) &&
|
||||
(MYNEWT_VAL(BLE_SMP_UNBOND_ON_KEY_MISSING) ||
|
||||
MYNEWT_VAL(BLE_SMP_REMOVE_BOND_ON_PAIR_FAIL_AS_CENTRAL))) {
|
||||
/* Peer reports no LTK. Erase our bond before restart-pair. */
|
||||
res.restore = 0;
|
||||
res.enc_cb = 1;
|
||||
res.app_status = BLE_HS_HCI_ERR(evt_status);
|
||||
res.keep_bond = 0;
|
||||
} else {
|
||||
terminate_conn = true;
|
||||
res.keep_bond = 1;
|
||||
}
|
||||
}
|
||||
|
||||
key_size = proc->key_size;
|
||||
break;
|
||||
@@ -1432,10 +1548,18 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
|
||||
if (proc == NULL || proc->state == BLE_SM_PROC_STATE_NONE) {
|
||||
res.enc_cb = 1;
|
||||
res.app_status = BLE_HS_HCI_ERR(evt_status);
|
||||
if (proc == NULL && evt_status != 0) {
|
||||
/* No active security procedure owns this controller failure. */
|
||||
res.keep_bond = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
|
||||
if (terminate_conn) {
|
||||
ble_gap_terminate(conn_handle, BLE_ERR_AUTH_FAIL);
|
||||
}
|
||||
|
||||
res.bonded = bonded;
|
||||
ble_sm_process_result(conn_handle, &res, true);
|
||||
}
|
||||
@@ -1546,15 +1670,22 @@ ble_sm_ltk_start_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
|
||||
}
|
||||
}
|
||||
|
||||
struct ble_sm_ltk_restore_ctx {
|
||||
const struct ble_store_value_sec *value_sec;
|
||||
bool bond_present;
|
||||
};
|
||||
|
||||
static void
|
||||
ble_sm_ltk_restore_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
|
||||
void *arg)
|
||||
{
|
||||
struct ble_store_value_sec *value_sec;
|
||||
const struct ble_sm_ltk_restore_ctx *ctx;
|
||||
const struct ble_store_value_sec *value_sec;
|
||||
|
||||
BLE_HS_DBG_ASSERT(!(proc->flags & BLE_SM_PROC_F_INITIATOR));
|
||||
|
||||
value_sec = arg;
|
||||
ctx = arg;
|
||||
value_sec = ctx != NULL ? ctx->value_sec : NULL;
|
||||
|
||||
if (value_sec != NULL) {
|
||||
/* Store provided a key; send it to the controller. */
|
||||
@@ -1569,24 +1700,32 @@ ble_sm_ltk_restore_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
|
||||
} else {
|
||||
/* Notify the app if it provided a key and the procedure failed. */
|
||||
res->enc_cb = 1;
|
||||
res->restore = 1;
|
||||
res->terminate = 1;
|
||||
res->keep_bond = 1;
|
||||
}
|
||||
} else {
|
||||
/* Application does not have the requested key in its database. Send a
|
||||
* negative reply to the controller.
|
||||
/*
|
||||
* No LTK matched ediv/rand. If we still hold a bond for this peer,
|
||||
* treat it as a failed restore (keep bond, drop link, block
|
||||
* BLE_RESTART_PAIR). If we hold no bond, this is one-sided deletion
|
||||
* on our side; allow BLE_RESTART_PAIR so the peer can re-pair.
|
||||
*/
|
||||
int rc;
|
||||
|
||||
rc = ble_sm_ltk_req_neg_reply_tx(proc->conn_handle);
|
||||
if (rc != 0) {
|
||||
res->app_status = rc;
|
||||
res->enc_cb = 1; /* Notify application of failure, similar to reply branch */
|
||||
res->enc_cb = 1;
|
||||
} else {
|
||||
/* Neg-reply sent: do not treat as restore success. app_status=0
|
||||
* would enter ENC_RESTORE and wait for an enc-change that never
|
||||
* arrives. PINKEY_MISSING also drives BLE_RESTART_PAIR.
|
||||
*/
|
||||
res->app_status = BLE_HS_HCI_ERR(BLE_ERR_PINKEY_MISSING);
|
||||
res->enc_cb = 1;
|
||||
}
|
||||
if (ctx != NULL && ctx->bond_present) {
|
||||
res->restore = 1;
|
||||
res->terminate = 1;
|
||||
res->keep_bond = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (res->app_status == 0) {
|
||||
@@ -1599,7 +1738,10 @@ ble_sm_ltk_restore_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
|
||||
int
|
||||
ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev)
|
||||
{
|
||||
struct ble_sm_ltk_restore_ctx restore_ctx;
|
||||
struct ble_store_value_sec value_sec;
|
||||
struct ble_store_value_sec bond;
|
||||
struct ble_store_key_sec key_sec;
|
||||
struct ble_hs_conn_addrs addrs;
|
||||
struct ble_sm_result res;
|
||||
struct ble_sm_proc *proc;
|
||||
@@ -1611,6 +1753,7 @@ ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev)
|
||||
uint16_t conn_handle = le16toh(ev->conn_handle);
|
||||
|
||||
memset(&res, 0, sizeof res);
|
||||
memset(&restore_ctx, 0, sizeof restore_ctx);
|
||||
|
||||
ble_hs_lock();
|
||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, 0, NULL);
|
||||
@@ -1682,11 +1825,21 @@ ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev)
|
||||
peer_id_addr, &value_sec);
|
||||
if (store_rc == 0) {
|
||||
/* Send the key to the controller. */
|
||||
res.state_arg = &value_sec;
|
||||
restore_ctx.value_sec = &value_sec;
|
||||
} else {
|
||||
/* Send a nack to the controller. */
|
||||
res.state_arg = NULL;
|
||||
/*
|
||||
* A nonmatching ediv/rand does not imply that no bond exists.
|
||||
* Read the peer record here, outside the host lock, so the
|
||||
* LTK restore state can distinguish a stale request from
|
||||
* one-sided bond deletion.
|
||||
*/
|
||||
memset(&key_sec, 0, sizeof key_sec);
|
||||
key_sec.peer_addr = addrs.peer_id_addr;
|
||||
store_rc = ble_store_read_peer_sec(&key_sec, &bond);
|
||||
restore_ctx.bond_present =
|
||||
store_rc == 0 && bond.ltk_present;
|
||||
}
|
||||
res.state_arg = &restore_ctx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2051,6 +2204,9 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||
struct ble_hs_conn *conn;
|
||||
ble_sm_proc_flags proc_flags;
|
||||
uint8_t key_size;
|
||||
uint8_t sm_err;
|
||||
bool terminate;
|
||||
bool keep_bond;
|
||||
int rc;
|
||||
|
||||
/* Silence spurious unused-variable warnings. */
|
||||
@@ -2174,11 +2330,18 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||
* application an opportunity to delete the old bond.
|
||||
*/
|
||||
if (res->app_status == 0) {
|
||||
rc = ble_sm_chk_repeat_pairing(conn_handle, proc_flags, key_size);
|
||||
rc = ble_sm_chk_repeat_pairing(conn_handle, proc_flags, key_size,
|
||||
&sm_err, &terminate, &keep_bond);
|
||||
if (rc != 0) {
|
||||
/* The app indicated that the pairing request should be ignored. */
|
||||
res->app_status = rc;
|
||||
res->execute = 0;
|
||||
res->sm_err = sm_err;
|
||||
res->terminate = terminate;
|
||||
res->keep_bond = keep_bond;
|
||||
if (terminate) {
|
||||
res->enc_cb = 1;
|
||||
}
|
||||
if (rc == BLE_HS_EBUSY) {
|
||||
/*
|
||||
* CONNECT not yet delivered; send Pairing Failed so the peer
|
||||
@@ -2195,8 +2358,10 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||
struct ble_sm_result *res)
|
||||
{
|
||||
struct ble_sm_pair_cmd *rsp;
|
||||
struct ble_store_value_sec bond;
|
||||
struct ble_sm_proc *proc;
|
||||
uint8_t ioact;
|
||||
int bond_rc;
|
||||
int rc;
|
||||
|
||||
res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*rsp));
|
||||
@@ -2206,6 +2371,7 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||
}
|
||||
|
||||
rsp = (struct ble_sm_pair_cmd *)(*om)->om_data;
|
||||
bond_rc = ble_sm_read_bond(conn_handle, &bond);
|
||||
|
||||
ble_hs_lock();
|
||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PAIR, 1, NULL);
|
||||
@@ -2232,21 +2398,56 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||
res->sm_err = BLE_SM_ERR_AUTHREQ;
|
||||
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ);
|
||||
res->enc_cb = 1;
|
||||
} else if (MYNEWT_VAL(BLE_SMP_HARDENED_REPAIRING) &&
|
||||
bond_rc == 0 && bond.ltk_present &&
|
||||
proc->sec_req_valid &&
|
||||
((rsp->authreq &
|
||||
proc->sec_req_authreq &
|
||||
(BLE_SM_PAIR_AUTHREQ_MITM | BLE_SM_PAIR_AUTHREQ_SC)) !=
|
||||
(proc->sec_req_authreq &
|
||||
(BLE_SM_PAIR_AUTHREQ_MITM | BLE_SM_PAIR_AUTHREQ_SC)))) {
|
||||
res->sm_err = BLE_SM_ERR_AUTHREQ;
|
||||
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ);
|
||||
res->enc_cb = 1;
|
||||
res->terminate = 1;
|
||||
res->keep_bond = 1;
|
||||
} else {
|
||||
ble_sm_pair_cfg(proc);
|
||||
|
||||
rc = ble_sm_io_action(proc, &ioact);
|
||||
if (rc != 0) {
|
||||
res->sm_err = BLE_SM_ERR_AUTHREQ;
|
||||
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ);
|
||||
if (bond_rc == 0 &&
|
||||
MYNEWT_VAL(BLE_SMP_HARDENED_REPAIRING) &&
|
||||
((bond.sc && !(proc->flags & BLE_SM_PROC_F_SC)) ||
|
||||
(bond.authenticated &&
|
||||
!(proc->flags & BLE_SM_PROC_F_AUTHENTICATED)) ||
|
||||
(proc->key_size < bond.key_size))) {
|
||||
res->sm_err = proc->key_size < bond.key_size ? BLE_SM_ERR_ENC_KEY_SZ
|
||||
: BLE_SM_ERR_AUTHREQ;
|
||||
res->app_status = BLE_HS_SM_US_ERR(res->sm_err);
|
||||
res->enc_cb = 1;
|
||||
} else {
|
||||
proc->state = ble_sm_state_after_pair(proc);
|
||||
if (ble_sm_ioact_state(ioact) == proc->state) {
|
||||
res->passkey_params.action = ioact;
|
||||
}
|
||||
if (ble_sm_proc_can_advance(proc)) {
|
||||
res->execute = 1;
|
||||
res->terminate = 1;
|
||||
res->keep_bond = 1;
|
||||
} else if (bond_rc != 0 &&
|
||||
bond_rc != BLE_HS_ENOENT &&
|
||||
bond_rc != BLE_HS_ENOTSUP) {
|
||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||
res->app_status = bond_rc;
|
||||
res->enc_cb = 1;
|
||||
}
|
||||
|
||||
if (res->app_status == 0) {
|
||||
rc = ble_sm_io_action(proc, &ioact);
|
||||
if (rc != 0) {
|
||||
res->sm_err = BLE_SM_ERR_AUTHREQ;
|
||||
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ);
|
||||
res->enc_cb = 1;
|
||||
} else {
|
||||
proc->state = ble_sm_state_after_pair(proc);
|
||||
if (ble_sm_ioact_state(ioact) == proc->state) {
|
||||
res->passkey_params.action = ioact;
|
||||
}
|
||||
if (ble_sm_proc_can_advance(proc)) {
|
||||
res->execute = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2350,7 +2551,7 @@ ble_sm_sec_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||
|
||||
/* always check if we have keys for this peer */
|
||||
res->app_status = ble_store_read_peer_sec(&key_sec, &value_sec);
|
||||
if (res->app_status == 0) {
|
||||
if (res->app_status == 0 && value_sec.ltk_present) {
|
||||
/* if keys are present and link is already encrypted check if
|
||||
* pairing should be started for security level elevation.
|
||||
* Otherwise we first require link encryption.
|
||||
@@ -2371,9 +2572,13 @@ ble_sm_sec_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||
start_pairing = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (res->app_status == BLE_HS_ENOENT ||
|
||||
res->app_status == BLE_HS_ENOTSUP ||
|
||||
(res->app_status == 0 && !value_sec.ltk_present)) {
|
||||
/* no keys present, start pairing */
|
||||
start_pairing = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/** Make sure a procedure isn't already in progress for this connection. */
|
||||
@@ -2388,6 +2593,16 @@ ble_sm_sec_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
||||
|
||||
if (start_pairing) {
|
||||
res->app_status = ble_sm_pair_initiate(conn_handle);
|
||||
if (res->app_status == 0) {
|
||||
ble_hs_lock();
|
||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PAIR, 1,
|
||||
NULL);
|
||||
if (proc != NULL) {
|
||||
proc->sec_req_authreq = cmd->authreq;
|
||||
proc->sec_req_valid = 1;
|
||||
}
|
||||
ble_hs_unlock();
|
||||
}
|
||||
} else {
|
||||
res->app_status = ble_sm_enc_initiate(conn_handle,
|
||||
value_sec.key_size,
|
||||
|
||||
@@ -255,6 +255,8 @@ struct ble_sm_proc {
|
||||
uint8_t state;
|
||||
uint8_t rx_key_flags;
|
||||
uint8_t key_size;
|
||||
uint8_t sec_req_authreq;
|
||||
uint8_t sec_req_valid;
|
||||
|
||||
uint8_t pair_req[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)];
|
||||
uint8_t pair_rsp[sizeof(struct ble_sm_hdr) + sizeof(struct ble_sm_pair_cmd)];
|
||||
@@ -287,7 +289,10 @@ struct ble_sm_result {
|
||||
unsigned enc_cb : 1;
|
||||
unsigned bonded : 1;
|
||||
unsigned restore : 1;
|
||||
unsigned terminate : 1;
|
||||
unsigned out_of_order : 1;
|
||||
/* Hardened re-pair refusal: keep the stored bond despite remove-on-fail. */
|
||||
unsigned keep_bond : 1;
|
||||
};
|
||||
|
||||
#if MYNEWT_VAL(BLE_HS_DEBUG)
|
||||
|
||||
Reference in New Issue
Block a user