Hello Nordic Team,
I am working with the nRF5340 Audio DK as a central device, trying to establish a secure connection using Security Level 4 (128-bit encryption with LE Secure Connections).
My goal is to ensure the central device enforces LESC (LE Secure Connections) with 128-bit encryption, but I am facing two major issues when connecting to different peripherals:
Issue 1: Security Level 4 Fails on Connection with Another nRF5340 board
When using another nRF5340 board as a peripheral, running the inbuilt nRF Audio Server code, the connection is established successfully. However, when I attempt to set Security Level 4, it fails with error .
[00:00:12.813,354] <inf> main: Received Command: connect 73:08:D0:98:FC:BD [00:00:12.813,446] <inf> main: Attempting to connect to 73:08:D0:98:FC:BD... [00:00:12.916,320] <inf> main: Connection initiated index : 0 [00:00:12.994,049] <inf> main: MTU exchanged: 23/23 [00:00:12.994,171] <inf> main: Connected: 73:08:D0:98:FC:BD (random) (index 0) Security level: 1 [00:00:13.196,289] <err> main: Security failed: 73:08:D0:98:FC:BD (random) level 1 err (4) [00:00:13.196,319] <inf> main: Pairing Failed (4). Disconnecting. [00:00:13.296,417] <inf> main: disconnect index : 0 [00:00:13.296,508] <inf> main: Disconnected: 73:08:D0:98:FC:BD (random), reason 0x16 (BT_HCI_ERR_LOCALHOST_TERM_CONN) Disconnected: (err 22 BT_HCI_ERR_LOCALHOST_TERM_CONN)
in nrf340_audio code i have change prj.conf file and add following config.
CONFIG_BT=y CONFIG_BT_SMP=y CONFIG_BT_BONDABLE=y CONFIG_BT_SMP_SC_PAIR_ONLY=y CONFIG_BT_PRIVACY=y
- Why does Security Level 4 fail with error 234?
- Are there additional configurations needed for enforcing LE Secure Connections (128-bit encryption with LTK)?
- Is there a way to debug or confirm why the encryption upgrade fails?
Issue 2: Connection Fails with Headset (Peripheral) - BT_HCI_ERR_UNKNOWN_CONN_ID
When attempting to connect to a headset as a peripheral, the connection fails with error 2 (BT_HCI_ERR_UNKNOWN_CONN_ID):
[00:00:36.785,827] <inf> main: Received Command: connect 7E:32:87:8B:18:4F [00:00:36.785,919] <inf> main: Attempting to connect to 7E:32:87:8B:18:4F... [00:00:36.886,810] <inf> main: Connection initiated index : 0 [00:00:37.846,679] <wrn> bt_hci_core: Connection creation timeout triggered [00:00:37.846,832] <err> main: Failed to connect to 7E:32:87:8B:18:4F (random) (err 2: BT_HCI_ERR_UNKNOWN_CONN_ID) ERROR: Failed to connect (err 2 BT_HCI_ERR_UNKNOWN_CONN_ID)
- Why does the connection timeout and fail with
BT_HCI_ERR_UNKNOWN_CONN_ID? - Do I need to manually set pairing parameters for headset support?
- Is this issue related to Security Level 4 enforcement, or is it purely a connection establishment issue?
and also security level is not work .
Central-Side Configuration & Code
prj.conf (Security Settings for Central)
CONFIG_BT=y CONFIG_LOG=y CONFIG_BT_CENTRAL=y CONFIG_BT_AUDIO=y CONFIG_BT_ISO_TX_BUF_COUNT=4 # Support an ISO channel per ASE CONFIG_BT_ISO_MAX_CHAN=4 CONFIG_BT_KEYS_OVERWRITE_OLDEST=y CONFIG_BT_HCI=y CONFIG_BT_EXT_ADV=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y CONFIG_UART_ASYNC_API=y # Security Connection(Level 4 - Authenticated Secure Connections and 128-bit key ) CONFIG_BT=y CONFIG_BT_SMP=y CONFIG_BT_BONDABLE=y CONFIG_BT_SMP_SC_PAIR_ONLY=y CONFIG_BT_PRIVACY=y CONFIG_BT_SMP_APP_PAIRING_ACCEPT=y #Converts a HCI error to string CONFIG_BT_HCI_ERR_TO_STR=y CONFIG_NRFX_UARTE1=y CONFIG_BT_MAX_CONN=5 CONFIG_BT_DEVICE_NAME="NRF5340_AUDIO_CLIENT" CONFIG_MAIN_STACK_SIZE=8192 CONFIG_IDLE_STACK_SIZE=1024 CONFIG_ISR_STACK_SIZE=4096 CONFIG_LOG_BUFFER_SIZE=2048 CONFIG_BT_SCAN_WITH_IDENTITY=y CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE=y CONFIG_GPIO=y CONFIG_PWM=y
Central-Side Connection Code
static struct bt_conn *default_conn;
/* Callback function when connection is established */
static void connected_cb(struct bt_conn *conn, uint8_t err) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (err) {
LOG_ERR("Failed to connect to %s (err %d: %s)\n", addr, err, bt_hci_err_to_str(err));
return;
}
default_conn = bt_conn_ref(conn);
LOG_INF("Connected: %s\n", addr);
/* Get current security level */
uint8_t sec_level = bt_conn_get_security(conn);
printk("Security level: %d\n", sec_level);
/* Attempt to set security level to 4 */
err = bt_conn_set_security(conn, BT_SECURITY_L4);
if (err) {
LOG_ERR("Security Level 4 failed, error code: %d", err);
}
}
/* Callback function when connection is disconnected */
static void disconnected_cb(struct bt_conn *conn, uint8_t reason) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (default_conn) {
bt_conn_unref(default_conn);
default_conn = NULL;
}
LOG_INF("Disconnected: %s, reason 0x%02x (%s)\n", addr, reason, bt_hci_err_to_str(reason));
}
/* Callback function when identity is resolved */
static void identity_resolved_cb(struct bt_conn *conn, const bt_addr_le_t *rpa, const bt_addr_le_t *identity) {
char addr_identity[BT_ADDR_LE_STR_LEN];
char addr_rpa[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));
LOG_INF("Identity resolved %s -> %s\n", addr_rpa, addr_identity);
}
/* Callback function when security level changes */
static void security_changed_cb(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (err) {
LOG_ERR("Security failed: %s level %u err %s(%d)\n", addr, level, bt_security_err_to_str(err), err);
} else {
LOG_INF("Security changed: %s level %u\n", addr, level);
}
}
/* Connection callbacks */
static struct bt_conn_cb conn_callbacks = {
.connected = connected_cb,
.disconnected = disconnected_cb,
.identity_resolved = identity_resolved_cb,
.security_changed = security_changed_cb,
};
/* Handle pairing success */
static void auth_pairing_complete_cb(struct bt_conn *conn, bool bonded) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Pairing complete with %s (Bonded: %s)\n", addr, bonded ? "Yes" : "No");
uint8_t sec_level = bt_conn_get_security(conn);
if (sec_level == 4) {
printk("Secure Connections (Level 4) established\n");
} else {
printk("Security level: %d\n", sec_level);
}
}
/* Handle pairing failure */
static void auth_pairing_failed_cb(struct bt_conn *conn, enum bt_security_err reason) {
LOG_INF("Pairing Failed (%d). Disconnecting.\n", reason);
bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
}
/* Callback function for bond deletion */
static void auth_bond_deleted_cb(uint8_t id, const bt_addr_le_t *peer) {
LOG_INF("Bond Information Deleted\n");
}
/* Bluetooth authentication info callback structure */
static struct bt_conn_auth_info_cb auth_info_callbacks = {
.pairing_complete = auth_pairing_complete_cb,
.pairing_failed = auth_pairing_failed_cb,
.bond_deleted = auth_bond_deleted_cb,
};
/* Callback when ATT MTU is updated */
static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx) {
LOG_INF("MTU exchanged: %u/%u\n", tx, rx);
}
/* GATT callbacks */
static struct bt_gatt_cb gatt_callbacks = {
.att_mtu_updated = att_mtu_updated,
};
/* Function to handle pairing accept */
static enum bt_security_err auth_pairing_accept_cb(struct bt_conn *conn, const struct bt_conn_pairing_feat *const feat) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
printk("Pairing accept for %s\n", addr);
/* Accept pairing */
return BT_SECURITY_ERR_SUCCESS;
}
/* Function to handle pairing confirmation */
static void auth_pairing_confirm_cb(struct bt_conn *conn) {
LOG_INF("Pairing Confirm\n");
bt_conn_auth_pairing_confirm(conn);
}
/* Function to handle passkey confirmation */
static void auth_passkey_confirm_cb(struct bt_conn *conn, uint32_t passkey) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
printk("Passkey confirmation for %s with passkey %u\n", addr, passkey);
/* Confirm passkey */
bt_conn_auth_passkey_confirm(conn);
}
/* Function to display passkey */
static void auth_passkey_display_cb(struct bt_conn *conn, unsigned int passkey) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Passkey for %s: %06u\n", addr, passkey);
}
/* Function to handle pairing cancellation */
static void auth_cancel_cb(struct bt_conn *conn) {
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Pairing cancelled: %s\n", addr);
}
/* Define the authentication callbacks structure */
static struct bt_conn_auth_cb auth_cb_callbacks = {
.pairing_accept = auth_pairing_accept_cb,
.pairing_confirm = auth_pairing_confirm_cb,
.passkey_confirm = auth_passkey_confirm_cb,
.passkey_display = auth_passkey_display_cb,
.cancel = auth_cancel_cb,
};
My ultimate aim is to ensure that my central device always connects using Security Level 4, which requires:
LE Secure Connections (LESC)
128-bit encryption using Long-Term Key (LTK)
MITM protection enabled
My Key Questions:
- Are my configurations correct for enforcing Security Level 4?
- What additional steps or configurations are needed to make it work with both peripherals?
- How can I debug or ensure that both devices negotiate LE Secure Connections properly?
I would greatly appreciate any insights, recommendations, or debugging steps to resolve these issues.
Thank you for your time and support!