Skip to content

Commit a68689f

Browse files
committed
Add sm_sec_req_auto_pair: make auto-pairing on Security Request configurable
On a Security Request from a peer we have no keys for, the host sends a Pairing Request immediately from ble_sm_sec_req_rx(). Some peripherals never answer a Pairing Request sent in the same instant as their own Security Request (e.g. the Okida OT-2000 oven module: no Pairing Response, link dropped after its 30 s SMP timeout). They pair first try with Bluedroid, macOS and iOS, which leave initiation to the application. Core Spec Vol 3, Part H, 2.4.6 says the central "may" initiate pairing on a Security Request. Make it configurable: ble_hs_cfg.sm_sec_req_auto_pair (syscfg BLE_SM_SEC_REQ_AUTO_PAIR, default 1 = unchanged). When cleared the request is ignored and the application initiates pairing, e.g. via NimBLEClient::secureConnection(). Peers we have keys for are unaffected. Exposed as NimBLEDevice::setSecurityAutoPairOnSecReq(). Verified on ESP32-C3 / arduino-esp32 3.3.11: the oven pairs with the flag cleared; with stock behaviour it fails regardless of MTU exchange, connection interval, key distribution, address type or SC/legacy.
1 parent 2c487b7 commit a68689f

6 files changed

Lines changed: 38 additions & 1 deletion

File tree

src/NimBLEDevice.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,18 @@ void NimBLEDevice::setSecurityAuth(uint8_t auth_req) {
12211221
* * 0x03 BLE_HS_IO_NO_INPUT_OUTPUT NoInputNoOutput IO capability
12221222
* * 0x04 BLE_HS_IO_KEYBOARD_DISPLAY KeyboardDisplay Only IO capability
12231223
*/
1224+
/**
1225+
* @brief Set whether a Security Request from a peer we have no keys for
1226+
* automatically sends a Pairing Request.
1227+
* @param [in] enable true (default): pair immediately. false: ignore the
1228+
* request; the application pairs via NimBLEClient::secureConnection().
1229+
* @details Some peripherals never answer a Pairing Request sent in the same
1230+
* instant as their own Security Request.
1231+
*/
1232+
void NimBLEDevice::setSecurityAutoPairOnSecReq(bool enable) {
1233+
ble_hs_cfg.sm_sec_req_auto_pair = enable;
1234+
} // setSecurityAutoPairOnSecReq
1235+
12241236
void NimBLEDevice::setSecurityIOCap(uint8_t iocap) {
12251237
ble_hs_cfg.sm_io_cap = iocap;
12261238
} // setSecurityIOCap

src/NimBLEDevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ class NimBLEDevice {
141141
static void setSecurityAuth(bool bonding, bool mitm, bool sc);
142142
static void setSecurityAuth(uint8_t auth);
143143
static void setSecurityIOCap(uint8_t iocap);
144+
static void setSecurityAutoPairOnSecReq(bool enable);
144145
static void setSecurityInitKey(uint8_t initKey);
145146
static void setSecurityRespKey(uint8_t respKey);
146147
static void setSecurityPasskey(uint32_t passKey);

src/nimble/nimble/host/include/host/ble_hs.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,16 @@ struct ble_hs_cfg {
319319
*/
320320
unsigned sm_keypress:1;
321321

322+
/** @brief Security Manager - auto-pair on Security Request
323+
*
324+
* If set (default), a Security Request from a peer we have no keys for
325+
* immediately triggers a Pairing Request. If clear, it is ignored and the
326+
* application initiates pairing (ble_gap_security_initiate). Some
327+
* peripherals never answer a Pairing Request sent in the same instant as
328+
* their Security Request. Peers we have keys for are unaffected.
329+
*/
330+
unsigned sm_sec_req_auto_pair:1;
331+
322332
/** @brief Security Manager Local Key Distribution Mask */
323333
uint8_t sm_our_key_dist;
324334

src/nimble/nimble/host/src/ble_hs_cfg.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct ble_hs_cfg ble_hs_cfg = {
2828
.sm_mitm = MYNEWT_VAL(BLE_SM_MITM),
2929
.sm_sc = MYNEWT_VAL(BLE_SM_SC),
3030
.sm_keypress = MYNEWT_VAL(BLE_SM_KEYPRESS),
31+
.sm_sec_req_auto_pair = MYNEWT_VAL(BLE_SM_SEC_REQ_AUTO_PAIR),
3132
.sm_our_key_dist = MYNEWT_VAL(BLE_SM_OUR_KEY_DIST),
3233
.sm_their_key_dist = MYNEWT_VAL(BLE_SM_THEIR_KEY_DIST),
3334
};

src/nimble/nimble/host/src/ble_sm.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2090,7 +2090,16 @@ ble_sm_sec_req_rx(uint16_t conn_handle, struct os_mbuf **om,
20902090
}
20912091
}
20922092
} else {
2093-
/* no keys present, start pairing */
2093+
/* no keys present: start pairing, unless the application wants to
2094+
* initiate pairing itself. In that case only a clean "no keys"
2095+
* result is ignored; store errors are propagated.
2096+
*/
2097+
if (!ble_hs_cfg.sm_sec_req_auto_pair) {
2098+
if (res->app_status == BLE_HS_ENOENT) {
2099+
res->app_status = 0;
2100+
}
2101+
return;
2102+
}
20942103
start_pairing = true;
20952104
}
20962105

src/syscfg/syscfg.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,10 @@
835835
#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0)
836836
#endif
837837

838+
#ifndef MYNEWT_VAL_BLE_SM_SEC_REQ_AUTO_PAIR
839+
#define MYNEWT_VAL_BLE_SM_SEC_REQ_AUTO_PAIR (1)
840+
#endif
841+
838842
#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY
839843
#define MYNEWT_VAL_BLE_SM_SC_ONLY (0)
840844
#endif

0 commit comments

Comments
 (0)