From 023839db31711be2b1401d76699cba4e98efd573 Mon Sep 17 00:00:00 2001 From: Sumeet Singh Date: Sat, 7 Sep 2024 17:08:40 +0800 Subject: [PATCH] feat(nimble): Added host config to enable or disable SC Only mode during runtime --- nimble/host/include/host/ble_hs.h | 8 ++++++++ nimble/host/src/ble_att_svr.c | 17 +++++++++++++++++ nimble/host/src/ble_hs_cfg.c | 1 + nimble/host/src/ble_sm.c | 18 ++++++++++++++++++ 4 files changed, 44 insertions(+) diff --git a/nimble/host/include/host/ble_hs.h b/nimble/host/include/host/ble_hs.h index 50fb9eb23..677b16dcb 100644 --- a/nimble/host/include/host/ble_hs.h +++ b/nimble/host/include/host/ble_hs.h @@ -233,6 +233,14 @@ struct ble_hs_cfg { */ unsigned sm_sc:1; + /** @brief Security Manager - Enable/Disable Secure Connections Only flag + * + * If set, this will enforce P-256 elliptic curve encryption algorithm + * during pairing. + * It will force the max key size to be used during pairing. + */ + unsigned sm_sc_only:1; + /** @brief Security Manager Key Press Notification flag * * Currently unsupported and should not be set. diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c index 5bf104f9b..d2156514c 100644 --- a/nimble/host/src/ble_att_svr.c +++ b/nimble/host/src/ble_att_svr.c @@ -321,6 +321,23 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read, } ble_att_svr_get_sec_state(conn_handle, &sec_state); + + /* In SC Only mode all characteristics requiring security + * require it on level 4 + */ + if (ble_hs_cfg.sm_sc_only) { + if (!sec_state.authenticated || + !sec_state.encrypted) { + *out_att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHEN; + return BLE_HS_ATT_ERR(*out_att_err); + } else if (sec_state.authenticated && + sec_state.encrypted && + sec_state.key_size != 16) { + *out_att_err = BLE_ATT_ERR_INSUFFICIENT_KEY_SZ; + return BLE_HS_ATT_ERR(*out_att_err); + } + } + if ((enc || authen) && !sec_state.encrypted) { ble_hs_lock(); conn = ble_hs_conn_find(conn_handle); diff --git a/nimble/host/src/ble_hs_cfg.c b/nimble/host/src/ble_hs_cfg.c index a46a604ac..b3cf33c74 100644 --- a/nimble/host/src/ble_hs_cfg.c +++ b/nimble/host/src/ble_hs_cfg.c @@ -27,6 +27,7 @@ struct ble_hs_cfg ble_hs_cfg = { .sm_bonding = MYNEWT_VAL(BLE_SM_BONDING), .sm_mitm = MYNEWT_VAL(BLE_SM_MITM), .sm_sc = MYNEWT_VAL(BLE_SM_SC), + .sm_sc_only = MYNEWT_VAL(BLE_SM_SC_ONLY), .sm_keypress = MYNEWT_VAL(BLE_SM_KEYPRESS), .sm_our_key_dist = MYNEWT_VAL(BLE_SM_OUR_KEY_DIST), .sm_their_key_dist = MYNEWT_VAL(BLE_SM_THEIR_KEY_DIST), diff --git a/nimble/host/src/ble_sm.c b/nimble/host/src/ble_sm.c index a93fba651..edf3c5725 100644 --- a/nimble/host/src/ble_sm.c +++ b/nimble/host/src/ble_sm.c @@ -1915,6 +1915,18 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om, } else if (req->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); + } else if (ble_hs_cfg.sm_sc_only) { + /* Fail if Secure Connections Only mode is on and remote does not + * meet key size requirements - MITM was checked in last step. + * Fail if SC is not supported by peer or key size is too small + */ + if (!(req->authreq & BLE_SM_PAIR_AUTHREQ_SC)) { + res->sm_err = BLE_SM_ERR_AUTHREQ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); + } else if (req->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX) { + res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); + } } else if (!ble_sm_verify_auth_requirements(req->authreq)) { res->sm_err = BLE_SM_ERR_AUTHREQ; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); @@ -1978,6 +1990,12 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om, } else if (rsp->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); + } else if (ble_hs_cfg.sm_sc_only && (rsp->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { + /* Fail if Secure Connections Only mode is on and remote does not meet + * key size requirements - MITM was checked in last step + */ + res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); } else if (!ble_sm_verify_auth_requirements(rsp->authreq)) { res->sm_err = BLE_SM_ERR_AUTHREQ; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ);