fix(esp32): init controller encryption so LE Secure Connections pairing works

The ESP32 BLE controller glue guards ble_enc_funcs_reset() on
CONFIG_BT_CTRL_BLE_SECURITY_ENABLE, an ESP-IDF sdkconfig symbol that is never
defined in a Zephyr build. The call is therefore compiled out and the
controller's LE Secure Connections encryption table is left uninitialised, so
SC pairing derives a wrong session key and the link is terminated with HCI
reason 0x3D (MIC failure).

This breaks pairing for SC-capable centrals (e.g. Pixel 7 / recent Android);
legacy-pairing centrals use a different path and are unaffected. The existing
CONFIG_ESP32_BT_CTLR_LE_SECURITY_ENABLE=y only sets .enc_en and does not reach
this guard.

Correct the guard to BLE_SECURITY_ENABLE, which esp_bt.h already derives from
CONFIG_ESP32_BT_CTLR_LE_SECURITY_ENABLE (the Zephyr knob) and already uses for
.enc_en. Carried as a managed hal_espressif patch via the existing
zephcore_apply_patches() mechanism (mirrors the loramac-node patch).

Verified on Heltec Wireless Tracker (ESP32-S3): device reaches security
level 4, pairing complete bonded=1; Pixel 7 bonds over SC and the companion app
communicates; older Samsung still pairs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
John Millington
2026-06-17 14:28:29 +12:00
co-authored by Claude Opus 4.8
parent ad5c777f2b
commit ece01b4f7c
2 changed files with 32 additions and 0 deletions
+10
View File
@@ -170,6 +170,16 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/patches/modules/loramac-node)
)
endif()
# Apply patches to hal_espressif module (ESP32 BLE controller glue)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/patches/modules/hal-espressif)
message(STATUS "Applying ZephCore patches to hal_espressif...")
zephcore_apply_patches(
"${CMAKE_CURRENT_SOURCE_DIR}/patches/modules/hal-espressif"
"${MODULES_DIR}/hal/espressif"
"hal-espressif"
)
endif()
# Copy new files into Zephyr tree
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/patches/zephyr-new)
file(GLOB_RECURSE ZEPHCORE_NEW_FILES
@@ -0,0 +1,22 @@
diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c
index 7f47e23f4e..ab872f5654 100644
--- a/components/bt/controller/esp32c3/bt.c
+++ b/components/bt/controller/esp32c3/bt.c
@@ -1415,9 +1415,15 @@ static void btdm_funcs_table_ready_wrapper(void)
ble_cca_funcs_reset();
#endif // (BT_BLE_CCA_MODE != 0)
-#if CONFIG_BT_CTRL_BLE_SECURITY_ENABLE
+/* ZephCore patch: guard was CONFIG_BT_CTRL_BLE_SECURITY_ENABLE (an IDF sdkconfig
+ * symbol never defined in Zephyr builds), so ble_enc_funcs_reset() was never
+ * called -> the controller's LE Secure Connections encryption table stayed
+ * uninitialised -> SC pairing produced a wrong session key -> 0x3D MIC failure
+ * (e.g. Pixel 7). BLE_SECURITY_ENABLE maps to CONFIG_ESP32_BT_CTLR_LE_SECURITY_ENABLE
+ * (the Zephyr knob, =y) and is already used for .enc_en in esp_bt.h. */
+#if BLE_SECURITY_ENABLE
ble_enc_funcs_reset();
-#endif // CONFIG_BT_CTRL_BLE_SECURITY_ENABLE
+#endif // BLE_SECURITY_ENABLE
#if CONFIG_BT_CTRL_BLE_MASTER
ble_init_funcs_reset();