fix(nimble): Out of order messages during SMP causing DOS vulerability

This commit is contained in:
Sumeet Singh
2024-02-29 16:23:47 +05:30
committed by Abhinav Kudnar
parent 8bcef4e241
commit 62adb830ff
3 changed files with 83 additions and 1 deletions
+72 -1
View File
@@ -755,8 +755,13 @@ static void
ble_sm_rx_noop(uint16_t conn_handle, struct os_mbuf **om,
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->sm_err = BLE_SM_ERR_CMD_NOT_SUPP;
res->out_of_order = 1;
}
static uint8_t
@@ -952,6 +957,17 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res,
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) {
ble_hs_lock();
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();
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_RANDOM, -1, NULL);
if (proc == NULL) {
/**
* Unexpectedly received pairing random value.
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->out_of_order = 1;
} else {
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();
proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_CONFIRM, -1, NULL);
if (proc == NULL) {
/**
* Unexpectedly received pairing confirm value.
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->out_of_order = 1;
} else {
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);
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.
*/
if (proc->state != BLE_SM_PROC_STATE_SEC_REQ) {
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();
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();
@@ -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_sm_sec_req *cmd;
struct ble_hs_conn *conn;
struct ble_sm_proc *proc;
int authreq_mitm;
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) {
res->app_status = ble_sm_enc_initiate(conn_handle,
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);
if (proc == NULL) {
/**
* Unexpected encryption info received
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->out_of_order = 1;
} else {
proc->rx_key_flags &= ~BLE_SM_KE_F_ENC_INFO;
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);
if (proc == NULL) {
/**
* Unexpected central indentification info recieved
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->out_of_order = 1;
} else {
proc->rx_key_flags &= ~BLE_SM_KE_F_MASTER_ID;
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);
if (proc == NULL) {
/**
* Unexpected ID info received
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->out_of_order = 1;
} else {
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);
if (proc == NULL) {
/**
* Unexpected identity address info received
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->out_of_order = 1;
} else {
proc->rx_key_flags &= ~BLE_SM_KE_F_ADDR_INFO;
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);
if (proc == NULL) {
/**
* Unexpected signing info received
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->out_of_order = 1;
} else {
proc->rx_key_flags &= ~BLE_SM_KE_F_SIGN_INFO;
+1
View File
@@ -287,6 +287,7 @@ struct ble_sm_result {
unsigned enc_cb : 1;
unsigned bonded : 1;
unsigned restore : 1;
unsigned out_of_order : 1;
};
#if MYNEWT_VAL(BLE_HS_DEBUG)
+10
View File
@@ -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,
NULL);
if (proc == NULL) {
/**
* Unexpected public key information received
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->sm_err = BLE_SM_ERR_UNSPECIFIED;
res->out_of_order = 1;
} else {
memcpy(&proc->pub_key_peer, cmd, sizeof(*cmd));
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,
NULL);
if (proc == NULL) {
/**
* Unexpected DHKey check values received
* Recommended action: Ignore
*/
res->app_status = BLE_HS_ENOENT;
res->out_of_order = 1;
} else {
ble_sm_dhkey_check_process(proc, cmd, res);
}