mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-15 13:40:01 +00:00
fix(nimble): Out of order messages during SMP causing DOS vulerability
This commit is contained in:
committed by
Abhinav Kudnar
parent
8bcef4e241
commit
62adb830ff
@@ -755,8 +755,13 @@ static void
|
|||||||
ble_sm_rx_noop(uint16_t conn_handle, struct os_mbuf **om,
|
ble_sm_rx_noop(uint16_t conn_handle, struct os_mbuf **om,
|
||||||
struct ble_sm_result *res)
|
struct ble_sm_result *res)
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Unsupported PDU received
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP);
|
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP);
|
||||||
res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP;
|
res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP;
|
||||||
|
res->out_of_order = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
@@ -952,6 +957,17 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res,
|
|||||||
|
|
||||||
rm = 0;
|
rm = 0;
|
||||||
|
|
||||||
|
if (res && res->out_of_order) {
|
||||||
|
/**
|
||||||
|
* An unexpected SM PDU received.
|
||||||
|
* Spec recommends ignore the PDU.
|
||||||
|
*/
|
||||||
|
memset(res, 0, sizeof *res);
|
||||||
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1,
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1,
|
||||||
@@ -1544,7 +1560,12 @@ ble_sm_random_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_RANDOM, -1, NULL);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_RANDOM, -1, NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpectedly received pairing random value.
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
memcpy(ble_sm_peer_pair_rand(proc), cmd->value, 16);
|
memcpy(ble_sm_peer_pair_rand(proc), cmd->value, 16);
|
||||||
|
|
||||||
@@ -1592,7 +1613,12 @@ ble_sm_confirm_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
ble_hs_lock();
|
ble_hs_lock();
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_CONFIRM, -1, NULL);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_CONFIRM, -1, NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpectedly received pairing confirm value.
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
memcpy(proc->confirm_peer, cmd->value, 16);
|
memcpy(proc->confirm_peer, cmd->value, 16);
|
||||||
|
|
||||||
@@ -1849,12 +1875,13 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
*/
|
*/
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, &prev);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, &prev);
|
||||||
if (proc != NULL) {
|
if (proc != NULL) {
|
||||||
/* Fail if procedure is in progress unless we sent a slave security
|
/* Ignore if procedure is in progress unless we sent a slave security
|
||||||
* request to peer.
|
* request to peer.
|
||||||
*/
|
*/
|
||||||
if (proc->state != BLE_SM_PROC_STATE_SEC_REQ) {
|
if (proc->state != BLE_SM_PROC_STATE_SEC_REQ) {
|
||||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED);
|
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED);
|
||||||
|
res->out_of_order = 1;
|
||||||
ble_hs_unlock();
|
ble_hs_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2006,6 +2033,14 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* Unexpectedly received pairing response.
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED);
|
||||||
|
res->out_of_order = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ble_hs_unlock();
|
ble_hs_unlock();
|
||||||
@@ -2046,6 +2081,7 @@ ble_sm_sec_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
struct ble_hs_conn_addrs addrs;
|
struct ble_hs_conn_addrs addrs;
|
||||||
struct ble_sm_sec_req *cmd;
|
struct ble_sm_sec_req *cmd;
|
||||||
struct ble_hs_conn *conn;
|
struct ble_hs_conn *conn;
|
||||||
|
struct ble_sm_proc *proc;
|
||||||
int authreq_mitm;
|
int authreq_mitm;
|
||||||
|
|
||||||
res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
|
res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
|
||||||
@@ -2096,6 +2132,16 @@ ble_sm_sec_req_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Make sure a procedure isn't already in progress for this connection. */
|
||||||
|
ble_hs_lock();
|
||||||
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, NULL);
|
||||||
|
ble_hs_unlock();
|
||||||
|
if (proc != NULL) {
|
||||||
|
res->out_of_order = 1;
|
||||||
|
proc = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (res->app_status == 0) {
|
if (res->app_status == 0) {
|
||||||
res->app_status = ble_sm_enc_initiate(conn_handle,
|
res->app_status = ble_sm_enc_initiate(conn_handle,
|
||||||
value_sec.key_size,
|
value_sec.key_size,
|
||||||
@@ -2391,8 +2437,13 @@ ble_sm_enc_info_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
|
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpected encryption info received
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
proc->rx_key_flags &= ~BLE_SM_KE_F_ENC_INFO;
|
proc->rx_key_flags &= ~BLE_SM_KE_F_ENC_INFO;
|
||||||
proc->peer_keys.ltk_valid = 1;
|
proc->peer_keys.ltk_valid = 1;
|
||||||
@@ -2425,8 +2476,13 @@ ble_sm_master_id_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
|
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpected central indentification info recieved
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
proc->rx_key_flags &= ~BLE_SM_KE_F_MASTER_ID;
|
proc->rx_key_flags &= ~BLE_SM_KE_F_MASTER_ID;
|
||||||
proc->peer_keys.ediv_rand_valid = 1;
|
proc->peer_keys.ediv_rand_valid = 1;
|
||||||
@@ -2460,8 +2516,13 @@ ble_sm_id_info_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
|
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpected ID info received
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
proc->rx_key_flags &= ~BLE_SM_KE_F_ID_INFO;
|
proc->rx_key_flags &= ~BLE_SM_KE_F_ID_INFO;
|
||||||
|
|
||||||
@@ -2494,8 +2555,13 @@ ble_sm_id_addr_info_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
|
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpected identity address info received
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
proc->rx_key_flags &= ~BLE_SM_KE_F_ADDR_INFO;
|
proc->rx_key_flags &= ~BLE_SM_KE_F_ADDR_INFO;
|
||||||
proc->peer_keys.addr_valid = 1;
|
proc->peer_keys.addr_valid = 1;
|
||||||
@@ -2528,8 +2594,13 @@ ble_sm_sign_info_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
|
|
||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpected signing info received
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
proc->rx_key_flags &= ~BLE_SM_KE_F_SIGN_INFO;
|
proc->rx_key_flags &= ~BLE_SM_KE_F_SIGN_INFO;
|
||||||
|
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ struct ble_sm_result {
|
|||||||
unsigned enc_cb : 1;
|
unsigned enc_cb : 1;
|
||||||
unsigned bonded : 1;
|
unsigned bonded : 1;
|
||||||
unsigned restore : 1;
|
unsigned restore : 1;
|
||||||
|
unsigned out_of_order : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if MYNEWT_VAL(BLE_HS_DEBUG)
|
#if MYNEWT_VAL(BLE_HS_DEBUG)
|
||||||
|
|||||||
@@ -624,8 +624,13 @@ ble_sm_sc_public_key_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PUBLIC_KEY, -1,
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PUBLIC_KEY, -1,
|
||||||
NULL);
|
NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpected public key information received
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
memcpy(&proc->pub_key_peer, cmd, sizeof(*cmd));
|
memcpy(&proc->pub_key_peer, cmd, sizeof(*cmd));
|
||||||
rc = ble_sm_alg_gen_dhkey(proc->pub_key_peer.x,
|
rc = ble_sm_alg_gen_dhkey(proc->pub_key_peer.x,
|
||||||
@@ -850,7 +855,12 @@ ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, struct os_mbuf **om,
|
|||||||
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_DHKEY_CHECK, -1,
|
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_DHKEY_CHECK, -1,
|
||||||
NULL);
|
NULL);
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
|
/**
|
||||||
|
* Unexpected DHKey check values received
|
||||||
|
* Recommended action: Ignore
|
||||||
|
*/
|
||||||
res->app_status = BLE_HS_ENOENT;
|
res->app_status = BLE_HS_ENOENT;
|
||||||
|
res->out_of_order = 1;
|
||||||
} else {
|
} else {
|
||||||
ble_sm_dhkey_check_process(proc, cmd, res);
|
ble_sm_dhkey_check_process(proc, cmd, res);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user