* [PATCH BlueZ 1/6] mgmt: Add Security Level Changed event
2026-08-20 10:52 [PATCH BlueZ 0/6] mgmt/device: report link security level to D-Bus clients Frédéric Danis
@ 2026-08-20 10:52 ` Frédéric Danis
2026-08-20 11:08 ` mgmt/device: report link security level to D-Bus clients bluez.test.bot
2026-08-20 10:52 ` [PATCH BlueZ 2/6] mgmt-tester: Add Security Level Changed event tests Frédéric Danis
` (4 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Frédéric Danis @ 2026-08-20 10:52 UTC (permalink / raw)
To: linux-bluetooth
This provides a TLV list of values related to the security level of
the connection to a remote device.
Currently Security Level and Encryption type are implemented.
---
doc/mgmt-protocol.rst | 45 +++++++++++++++++++++++++++++++++++++++++++
lib/bluetooth/mgmt.h | 15 +++++++++++++++
2 files changed, 60 insertions(+)
diff --git a/doc/mgmt-protocol.rst b/doc/mgmt-protocol.rst
index f0564075f..1693ff677 100644
--- a/doc/mgmt-protocol.rst
+++ b/doc/mgmt-protocol.rst
@@ -5521,3 +5521,48 @@ The Supervision_Timeout parameter specifies the supervision timeout in units
of 10 ms.
This event will be sent to all management sockets.
+
+Security Level Changed
+``````````````````````
+
+:Event Code: 0x0034
+:Controller Index: <controller_id>
+:Event Parameters: Address (6 Octets)
+:...: Address_Type (1 Octet)
+:...: Count (1 Octet)
+:...: TLV_List (variable)
+
+This event indicates that the security level of a device has changed.
+
+Possible values for the TLV type parameter:
+
+.. csv-table::
+ :header: "Type", "Description"
+ :widths: auto
+
+ 0x0000, Security Level
+ 0x0001, Encryption type
+
+Possible values for the Security Level type:
+
+.. csv-table::
+ :header: "Value", "Description"
+ :widths: auto
+
+ 0x00, No security
+ 0x01, Unauthenticated pairing with encryption not required
+ 0x02, Unauthenticated pairing with encryption desired
+ 0x03, Authenticated pairing with encryption
+ 0x04, FIPS authenticated pairing with encryption
+
+Possible values for the Encryption type:
+
+.. csv-table::
+ :header: "Value", "Description"
+ :widths: auto
+
+ 0x00, No encryption
+ 0x01, E0 encryption
+ 0x02, AES-CCM encryption
+
+This event will be sent to all management sockets.
diff --git a/lib/bluetooth/mgmt.h b/lib/bluetooth/mgmt.h
index 9df0c1ba2..6e0494757 100644
--- a/lib/bluetooth/mgmt.h
+++ b/lib/bluetooth/mgmt.h
@@ -1136,6 +1136,20 @@ struct mgmt_ev_conn_subrate {
uint16_t supv_timeout;
} __packed;
+#define MGMT_CONN_SEC_ENCRYPT_NONE 0x00
+#define MGMT_CONN_SEC_ENCRYPT_E0 0x01
+#define MGMT_CONN_SEC_ENCRYPT_AES_CCM 0x02
+
+#define MGMT_SEC_LEVEL_CHANGED_PARAM_LEVEL 0x0000
+#define MGMT_SEC_LEVEL_CHANGED_PARAM_ENC_TYPE 0x0001
+
+#define MGMT_EV_SECURITY_LEVEL_CHANGED 0x0034
+struct mgmt_ev_security_level_changed {
+ struct mgmt_addr_info addr;
+ uint8_t tlv_count;
+ uint8_t tlv_data[] __counted_by(tlv_count);
+} __packed;
+
static const char *mgmt_op[] = {
"<0x0000>",
"Read Version",
@@ -1285,6 +1299,7 @@ static const char *mgmt_ev[] = {
"Mesh Packet Found",
"Mesh Packet Complete",
"Connection Subrate",
+ "Security Level Changed",
};
static const char *mgmt_status[] = {
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* RE: mgmt/device: report link security level to D-Bus clients
2026-08-20 10:52 ` [PATCH BlueZ 1/6] mgmt: Add Security Level Changed event Frédéric Danis
@ 2026-08-20 11:08 ` bluez.test.bot
0 siblings, 0 replies; 8+ messages in thread
From: bluez.test.bot @ 2026-08-20 11:08 UTC (permalink / raw)
To: linux-bluetooth, frederic.danis
[-- Attachment #1: Type: text/plain, Size: 7181 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1149033
---Test result---
Test Summary:
CheckPatch FAIL 1.89 seconds
GitLint PASS 1.23 seconds
BuildEll PASS 20.44 seconds
BluezMake FAIL 8.43 seconds
MakeCheck FAIL 7.47 seconds
MakeDistcheck FAIL 31.96 seconds
CheckValgrind FAIL 8.27 seconds
CheckSmatch FAIL 9.50 seconds
bluezmakeextell FAIL 9.50 seconds
IncrementalBuild FAIL 8.83 seconds
ScanBuild FAIL 9.35 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,2/6] mgmt-tester: Add Security Level Changed event tests
WARNING:BAD_SIGN_OFF: Non-standard signature: Assisted-by:
#73:
Assisted-by: GPT:GPT-5.3-Codex
ERROR:BAD_SIGN_OFF: Unrecognized email address: 'GPT:GPT-5.3-Codex'
#73:
Assisted-by: GPT:GPT-5.3-Codex
/github/workspace/src/patch/14759012.patch total: 1 errors, 1 warnings, 163 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14759012.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: BluezMake - FAIL
Desc: Build BlueZ
Output:
In file included from src/shared/mgmt.c:21:
./lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[1]: *** [Makefile:7707: src/shared/libshared_mainloop_la-mgmt.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4215: all] Error 2
##############################
Test: MakeCheck - FAIL
Desc: Run Bluez Make Check
Output:
In file included from client/mgmt.c:40:
./lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[1]: *** [Makefile:7123: client/mgmt.o] Error 1
make: *** [Makefile:10934: check] Error 2
##############################
Test: MakeDistcheck - FAIL
Desc: Run Bluez Make Distcheck
Output:
In file included from ../../src/shared/mgmt.c:21:
../../lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[2]: *** [Makefile:7707: src/shared/libshared_mainloop_la-mgmt.lo] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [Makefile:4215: all] Error 2
make: *** [Makefile:10855: distcheck] Error 1
##############################
Test: CheckValgrind - FAIL
Desc: Run Bluez Make Check with Valgrind
Output:
In file included from src/shared/mgmt.c:21:
./lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[1]: *** [Makefile:7707: src/shared/libshared_mainloop_la-mgmt.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:10934: check] Error 2
##############################
Test: CheckSmatch - FAIL
Desc: Run smatch tool with source
Output:
src/shared/mgmt.c: note: in included file:
./lib/bluetooth/mgmt.h:1150:28: error: expected ; at end of declaration
./lib/bluetooth/mgmt.h:1150:28: error: Expected } at end of specifier
./lib/bluetooth/mgmt.h:1150:28: error: got __counted_by
./lib/bluetooth/mgmt.h:1151:1: error: Expected ; at the end of type declaration
./lib/bluetooth/mgmt.h:1151:1: error: got }
src/shared/crypto.c:271:21: warning: Variable length array is used.
src/shared/crypto.c:272:23: warning: Variable length array is used.
In file included from src/shared/mgmt.c:21:
./lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[1]: *** [Makefile:7707: src/shared/libshared_mainloop_la-mgmt.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4215: all] Error 2
##############################
Test: bluezmakeextell - FAIL
Desc: Build Bluez with External ELL
Output:
In file included from src/shared/mgmt.c:21:
./lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[1]: *** [Makefile:7707: src/shared/libshared_mainloop_la-mgmt.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4215: all] Error 2
##############################
Test: IncrementalBuild - FAIL
Desc: Incremental build with the patches in the series
Output:
In file included from src/shared/mgmt.c:21:
./lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[1]: *** [Makefile:7707: src/shared/libshared_mainloop_la-mgmt.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4215: all] Error 2
[BlueZ,1/6] mgmt: Add Security Level Changed event
In file included from src/shared/mgmt.c:21:
./lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[1]: *** [Makefile:7707: src/shared/libshared_mainloop_la-mgmt.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4215: all] Error 2
##############################
Test: ScanBuild - FAIL
Desc: Run Scan Build
Output:
In file included from src/shared/mgmt.c:21:
./lib/bluetooth/mgmt.h:1150:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘__counted_by’
1150 | uint8_t tlv_data[] __counted_by(tlv_count);
| ^~~~~~~~~~~~
make[1]: *** [Makefile:7707: src/shared/libshared_mainloop_la-mgmt.lo] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:4215: all] Error 2
https://github.com/bluez/bluez/pull/2418
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH BlueZ 2/6] mgmt-tester: Add Security Level Changed event tests
2026-08-20 10:52 [PATCH BlueZ 0/6] mgmt/device: report link security level to D-Bus clients Frédéric Danis
2026-08-20 10:52 ` [PATCH BlueZ 1/6] mgmt: Add Security Level Changed event Frédéric Danis
@ 2026-08-20 10:52 ` Frédéric Danis
2026-08-20 10:52 ` [PATCH BlueZ 3/6] monitor: Add support for Mgmt Security Level changed event Frédéric Danis
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-08-20 10:52 UTC (permalink / raw)
To: linux-bluetooth
Test that MGMT_EV_SECURITY_LEVEL_CHANGED is correctly received during
BREDR and LE secured connection.
Assisted-by: GPT:GPT-5.3-Codex
---
tools/mgmt-tester.c | 133 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 133 insertions(+)
diff --git a/tools/mgmt-tester.c b/tools/mgmt-tester.c
index 4b432002d..bd8b67209 100644
--- a/tools/mgmt-tester.c
+++ b/tools/mgmt-tester.c
@@ -3776,6 +3776,110 @@ static bool verify_link_key(const void *param, uint16_t length)
return true;
}
+static bool verify_security_level_changed(const void *param, uint16_t length)
+{
+ struct test_data *data = tester_get_data();
+ const uint8_t *event = param;
+ const uint8_t *expected_addr;
+ uint8_t expected_addr_type;
+ uint8_t expected_enc_type;
+ uint8_t tlv_count;
+ uint8_t i;
+ uint16_t offset;
+ bool saw_level = false;
+ bool saw_enc_type = false;
+
+ if (length < sizeof(struct mgmt_addr_info) + 1) {
+ tester_warn("Invalid security level changed length %u", length);
+ return false;
+ }
+
+ expected_addr = hciemu_get_client_bdaddr(data->hciemu);
+ if (!expected_addr) {
+ tester_warn("No central bdaddr");
+ return false;
+ }
+
+ expected_addr_type = data->hciemu_type == HCIEMU_TYPE_LE ?
+ BDADDR_LE_PUBLIC : BDADDR_BREDR;
+ expected_enc_type = data->hciemu_type == HCIEMU_TYPE_LE ?
+ MGMT_CONN_SEC_ENCRYPT_NONE :
+ MGMT_CONN_SEC_ENCRYPT_E0;
+
+ if (memcmp(event, expected_addr, 6)) {
+ tester_warn("Unexpected security level changed address");
+ return false;
+ }
+
+ if (event[6] != expected_addr_type) {
+ tester_warn("Unexpected security level changed address type %u != %u",
+ event[6], expected_addr_type);
+ return false;
+ }
+
+ tlv_count = event[7];
+ offset = sizeof(struct mgmt_addr_info) + 1;
+
+ for (i = 0; i < tlv_count; i++) {
+ const struct mgmt_tlv *tlv;
+ uint16_t type;
+
+ if (offset + sizeof(*tlv) > length) {
+ tester_warn("Malformed security level changed TLV header");
+ return false;
+ }
+
+ tlv = (const struct mgmt_tlv *)(event + offset);
+ type = get_le16(&tlv->type);
+
+ if (offset + sizeof(*tlv) + tlv->length > length) {
+ tester_warn("Malformed security level changed TLV payload");
+ return false;
+ }
+
+ switch (type) {
+ case MGMT_SEC_LEVEL_CHANGED_PARAM_LEVEL:
+ if (tlv->length != 1) {
+ tester_warn("Invalid security level TLV length %u",
+ tlv->length);
+ return false;
+ }
+ saw_level = true;
+ break;
+ case MGMT_SEC_LEVEL_CHANGED_PARAM_ENC_TYPE:
+ if (tlv->length != 1) {
+ tester_warn("Invalid encryption type TLV length %u",
+ tlv->length);
+ return false;
+ }
+
+ if (tlv->value[0] != expected_enc_type) {
+ tester_warn("Unexpected encryption type %u != %u",
+ tlv->value[0],
+ expected_enc_type);
+ return false;
+ }
+
+ saw_enc_type = true;
+ break;
+ }
+
+ offset += sizeof(*tlv) + tlv->length;
+ }
+
+ if (offset != length) {
+ tester_warn("Unexpected security level changed trailing bytes");
+ return false;
+ }
+
+ if (!saw_level || !saw_enc_type) {
+ tester_warn("Missing expected security level changed TLVs");
+ return false;
+ }
+
+ return true;
+}
+
static uint16_t settings_powered_le_sc_bondable[] = {
MGMT_OP_SET_LE,
MGMT_OP_SET_SSP,
@@ -3879,6 +3983,19 @@ static const struct generic_data pairing_acceptor_ssp_1 = {
.just_works = true,
};
+static const struct generic_data pairing_acceptor_ssp_sec_level_changed = {
+ .setup_settings = settings_powered_connectable_bondable_ssp,
+ .client_enable_ssp = true,
+ .expect_alt_ev = MGMT_EV_SECURITY_LEVEL_CHANGED,
+ .expect_alt_ev_len = 16,
+ .verify_alt_ev_func = verify_security_level_changed,
+ .expect_hci_command = BT_HCI_CMD_USER_CONFIRM_REQUEST_REPLY,
+ .expect_hci_func = client_bdaddr_param_func,
+ .io_cap = 0x03, /* NoInputNoOutput */
+ .client_io_cap = 0x03, /* NoInputNoOutput */
+ .just_works = true,
+};
+
static const struct generic_data pairing_acceptor_ssp_2 = {
.setup_settings = settings_powered_connectable_bondable_ssp,
.client_enable_ssp = true,
@@ -3986,6 +4103,16 @@ static const struct generic_data pairing_acceptor_le_1 = {
.verify_alt_ev_func = verify_ltk,
};
+static const struct generic_data pairing_acceptor_le_sec_level_changed = {
+ .setup_settings = settings_powered_bondable_connectable_advertising,
+ .io_cap = 0x03, /* NoInputNoOutput */
+ .client_io_cap = 0x03, /* NoInputNoOutput */
+ .just_works = true,
+ .expect_alt_ev = MGMT_EV_SECURITY_LEVEL_CHANGED,
+ .expect_alt_ev_len = 16,
+ .verify_alt_ev_func = verify_security_level_changed,
+};
+
static const struct generic_data pairing_acceptor_le_2 = {
.setup_settings = settings_powered_bondable_connectable_advertising,
.io_cap = 0x04, /* KeyboardDisplay */
@@ -13832,6 +13959,9 @@ int main(int argc, char *argv[])
test_bredrle("Pairing Acceptor - SSP 1",
&pairing_acceptor_ssp_1, setup_pairing_acceptor,
test_pairing_acceptor);
+ test_bredrle("Pairing Acceptor - SSP Security Level Changed",
+ &pairing_acceptor_ssp_sec_level_changed,
+ setup_pairing_acceptor, test_pairing_acceptor);
test_bredrle("Pairing Acceptor - SSP 2",
&pairing_acceptor_ssp_2, setup_pairing_acceptor,
test_pairing_acceptor);
@@ -13850,6 +13980,9 @@ int main(int argc, char *argv[])
test_le("Pairing Acceptor - LE 1",
&pairing_acceptor_le_1, setup_pairing_acceptor,
test_pairing_acceptor);
+ test_le("Pairing Acceptor - LE Security Level Changed",
+ &pairing_acceptor_le_sec_level_changed,
+ setup_pairing_acceptor, test_pairing_acceptor);
test_le("Pairing Acceptor - LE 2",
&pairing_acceptor_le_2, setup_pairing_acceptor,
test_pairing_acceptor);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 3/6] monitor: Add support for Mgmt Security Level changed event
2026-08-20 10:52 [PATCH BlueZ 0/6] mgmt/device: report link security level to D-Bus clients Frédéric Danis
2026-08-20 10:52 ` [PATCH BlueZ 1/6] mgmt: Add Security Level Changed event Frédéric Danis
2026-08-20 10:52 ` [PATCH BlueZ 2/6] mgmt-tester: Add Security Level Changed event tests Frédéric Danis
@ 2026-08-20 10:52 ` Frédéric Danis
2026-08-20 10:52 ` [PATCH BlueZ 4/6] device: Add SecurityLevel properties to org.bluez.Device1 Frédéric Danis
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-08-20 10:52 UTC (permalink / raw)
To: linux-bluetooth
@ MGMT Event: Security Level Changed (0x0034) plen 16
BR/EDR Address: 00:AA:01:01:00:00 (Intel Corporation)
Count: 2
Security Level: No security (0x00000000)
Encryption Type: No encryption (0x00000000)
---
monitor/packet.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/monitor/packet.c b/monitor/packet.c
index 0d3b23cc3..217fcdad1 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -17680,6 +17680,121 @@ static void mgmt_conn_subrate_evt(const void *data, uint16_t size)
print_field("Supervision timeout: %u", supv_timeout);
}
+static void mgmt_print_security_level(const char *desc, uint32_t value)
+{
+ const char *level;
+
+ switch (value) {
+ case BT_SECURITY_SDP:
+ level = "No security";
+ break;
+ case BT_SECURITY_LOW:
+ level = "Unauthenticated pairing with encryption not required";
+ break;
+ case BT_SECURITY_MEDIUM:
+ level = "Unauthenticated pairing with encryption desired";
+ break;
+ case BT_SECURITY_HIGH:
+ level = "Authenticated pairing with encryption";
+ break;
+ case BT_SECURITY_FIPS:
+ level = "FIPS authenticated pairing with encryption";
+ break;
+ default:
+ level = "Reserved";
+ break;
+ }
+
+ print_field("%s: %s (0x%8.8x)", desc, level, value);
+}
+
+static void mgmt_print_encryption_type(const char *desc, uint32_t value)
+{
+ const char *type;
+
+ switch (value) {
+ case MGMT_CONN_SEC_ENCRYPT_NONE:
+ type = "No encryption";
+ break;
+ case MGMT_CONN_SEC_ENCRYPT_E0:
+ type = "E0";
+ break;
+ case MGMT_CONN_SEC_ENCRYPT_AES_CCM:
+ type = "AES-CCM";
+ break;
+ default:
+ type = "Reserved";
+ break;
+ }
+
+ print_field("%s: %s (0x%8.8x)", desc, type, value);
+}
+
+static void mgmt_print_sec_level_tlv(void *data, void *user_data)
+{
+ const struct mgmt_tlv *entry = data;
+ uint16_t type = get_le16(&entry->type);
+ const char *desc = default_system_config(type);
+ uint32_t value;
+ char buf[8];
+
+ switch (type) {
+ case MGMT_SEC_LEVEL_CHANGED_PARAM_LEVEL:
+ desc = "Security Level";
+ break;
+ case MGMT_SEC_LEVEL_CHANGED_PARAM_ENC_TYPE:
+ desc = "Encryption Type";
+ break;
+ default:
+ snprintf(buf, sizeof(buf), "0x%4.4x", entry->type);
+ desc = buf;
+ break;
+ }
+
+ if (entry->length == 1 || entry->length == 2 || entry->length == 4) {
+ if (entry->length == 1)
+ value = get_u8(entry->value);
+ else if (entry->length == 2)
+ value = get_le16(entry->value);
+ else
+ value = get_le32(entry->value);
+
+ switch (type) {
+ case MGMT_SEC_LEVEL_CHANGED_PARAM_LEVEL:
+ mgmt_print_security_level(desc, value);
+ break;
+ case MGMT_SEC_LEVEL_CHANGED_PARAM_ENC_TYPE:
+ mgmt_print_encryption_type(desc, value);
+ break;
+ default:
+ print_field("%s: %u", desc, value);
+ break;
+ }
+ } else {
+ print_hex_field(desc, entry->value, entry->length);
+ }
+}
+
+static void mgmt_security_level_changed_evt(const void *data, uint16_t size)
+{
+ const uint8_t *addr = data;
+ uint8_t addr_type = get_u8(data + 6);
+ uint8_t count = get_u8(data + 7);
+ struct mgmt_tlv_list *tlv_list;
+
+ mgmt_print_address(addr, addr_type);
+ print_field("Count: %d", count);
+
+ tlv_list = mgmt_tlv_list_load_from_buf(data + 8, size - 8);
+ if (!tlv_list) {
+ print_text(COLOR_ERROR, " Unable to parse security level "
+ "changed event");
+ return;
+ }
+ mgmt_tlv_list_foreach(tlv_list, mgmt_print_sec_level_tlv, NULL);
+ mgmt_tlv_list_free(tlv_list);
+}
+
static const struct mgmt_data mgmt_event_table[] = {
{ 0x0001, "Command Complete",
mgmt_command_complete_evt, 3, false },
@@ -17779,6 +17894,8 @@ static const struct mgmt_data mgmt_event_table[] = {
mgmt_mesh_packet_cmplt_evt, 1, true },
{ 0x0033, "Connection Subrate",
mgmt_conn_subrate_evt, 18, true },
+ { 0x0034, "Security Level Changed",
+ mgmt_security_level_changed_evt, 8, false },
{ }
};
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 4/6] device: Add SecurityLevel properties to org.bluez.Device1
2026-08-20 10:52 [PATCH BlueZ 0/6] mgmt/device: report link security level to D-Bus clients Frédéric Danis
` (2 preceding siblings ...)
2026-08-20 10:52 ` [PATCH BlueZ 3/6] monitor: Add support for Mgmt Security Level changed event Frédéric Danis
@ 2026-08-20 10:52 ` Frédéric Danis
2026-08-20 10:52 ` [PATCH BlueZ 5/6] org.bluez.Device: Add Security Level related properties Frédéric Danis
2026-08-20 10:52 ` [PATCH BlueZ 6/6] client: Display SecurityLevel in device info Frédéric Danis
5 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-08-20 10:52 UTC (permalink / raw)
To: linux-bluetooth
This uses the new MGMT_EV_SECURITY_LEVEL_CHANGED event.
It will be used by btpclient to reduce test time.
---
src/adapter.c | 33 ++++++++++++++++++++
src/device.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/device.h | 3 ++
3 files changed, 120 insertions(+)
diff --git a/src/adapter.c b/src/adapter.c
index c21b3e7fb..2fd5e005e 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -10036,6 +10036,34 @@ static void unpaired_callback(uint16_t index, uint16_t length,
device_set_unpaired(device, ev->addr.type);
}
+static void device_sec_level_callback(uint16_t index, uint16_t length,
+ const void *param, void *user_data)
+{
+ const struct mgmt_ev_security_level_changed *ev = param;
+ struct btd_adapter *adapter = user_data;
+ struct btd_device *dev;
+ char addr[18];
+
+ if (length < sizeof(*ev)) {
+ btd_error(adapter->dev_id,
+ "Too small Device Security Level Changed event: %d",
+ length);
+ return;
+ }
+
+ ba2str(&ev->addr.bdaddr, addr);
+
+ dev = btd_adapter_find_device(adapter, &ev->addr.bdaddr, ev->addr.type);
+ if (!dev) {
+ btd_error(adapter->dev_id,
+ "Device Security Level Changed for unknown device %s",
+ addr);
+ return;
+ }
+
+ btd_device_sec_level_changed(dev, ev->tlv_data, length - 8);
+}
+
static void clear_devices_complete(uint8_t status, uint16_t length,
const void *param, void *user_data)
{
@@ -10754,6 +10782,11 @@ static void read_info_complete(uint8_t status, uint16_t length,
controller_resume_callback,
adapter, NULL);
+ mgmt_register(adapter->mgmt, MGMT_EV_SECURITY_LEVEL_CHANGED,
+ adapter->dev_id,
+ device_sec_level_callback,
+ adapter, NULL);
+
set_dev_class(adapter);
set_name(adapter, btd_adapter_get_name(adapter));
diff --git a/src/device.c b/src/device.c
index 65d84be56..c6cb0aecf 100644
--- a/src/device.c
+++ b/src/device.c
@@ -306,6 +306,9 @@ struct btd_device {
uint32_t auth_failures;
guint auth_retry_id;
+
+ uint8_t sec_level;
+ uint8_t enc_type;
};
static const uint16_t uuid_list[] = {
@@ -3689,6 +3692,26 @@ dev_property_prefer_bearer_exists(const GDBusPropertyTable *property,
return device_prefer_bearer_str(device) != NULL;
}
+static gboolean dev_get_security_level(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *dev = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &dev->sec_level);
+
+ return TRUE;
+}
+
+static gboolean dev_get_encryption_type(const GDBusPropertyTable *property,
+ DBusMessageIter *iter, void *data)
+{
+ struct btd_device *dev = data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &dev->enc_type);
+
+ return TRUE;
+}
+
static const GDBusPropertyTable device_properties[] = {
{ "Address", "s", dev_property_get_address },
{ "AddressType", "s", property_get_address_type },
@@ -3732,6 +3755,10 @@ static const GDBusPropertyTable device_properties[] = {
dev_property_set_prefer_bearer,
dev_property_prefer_bearer_exists,
G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "SecurityLevel", "y", dev_get_security_level, NULL, NULL,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "EncryptionType", "y", dev_get_encryption_type, NULL, NULL,
+ G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
{ }
};
@@ -8341,3 +8368,60 @@ next:
l = next;
}
}
+
+static void parse_sec_level_tlv(void *data, void *user_data)
+{
+ struct btd_device *dev = user_data;
+ const struct mgmt_tlv *entry = data;
+ uint16_t type = get_le16(&entry->type);
+ uint32_t value;
+
+ if (entry->length != 1 && entry->length != 2 && entry->length != 4) {
+ warn("Invalid length %u for security level TLV type %u",
+ entry->length, type);
+ return;
+ }
+
+ if (entry->length == 1)
+ value = get_u8(entry->value);
+ else if (entry->length == 2)
+ value = get_le16(entry->value);
+ else
+ value = get_le32(entry->value);
+
+ switch (type) {
+ case MGMT_SEC_LEVEL_CHANGED_PARAM_LEVEL:
+ if (dev->sec_level != value) {
+ dev->sec_level = value;
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
+ DEVICE_INTERFACE,
+ "SecurityLevel");
+ }
+ break;
+ case MGMT_SEC_LEVEL_CHANGED_PARAM_ENC_TYPE:
+ if (dev->enc_type != value) {
+ dev->enc_type = value;
+ g_dbus_emit_property_changed(dbus_conn, dev->path,
+ DEVICE_INTERFACE,
+ "EncryptionType");
+ }
+ break;
+ default:
+ DBG("Unknown security level TLV type %u", type);
+ break;
+ }
+}
+
+void btd_device_sec_level_changed(struct btd_device *dev, const uint8_t *data,
+ uint16_t size)
+{
+ struct mgmt_tlv_list *tlv_list;
+
+ tlv_list = mgmt_tlv_list_load_from_buf(data, size);
+ if (!tlv_list) {
+ error("Failed to parse security level TLV list");
+ return;
+ }
+ mgmt_tlv_list_foreach(tlv_list, parse_sec_level_tlv, dev);
+ mgmt_tlv_list_free(tlv_list);
+}
diff --git a/src/device.h b/src/device.h
index b890f23d4..3dff67eb0 100644
--- a/src/device.h
+++ b/src/device.h
@@ -245,3 +245,6 @@ void btd_device_foreach_service(struct btd_device *dev,
void *user_data);
void device_remove_pending_services(struct btd_device *dev,
uint8_t bdaddr_type);
+
+void btd_device_sec_level_changed(struct btd_device *dev, const uint8_t *data,
+ uint16_t size);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 5/6] org.bluez.Device: Add Security Level related properties
2026-08-20 10:52 [PATCH BlueZ 0/6] mgmt/device: report link security level to D-Bus clients Frédéric Danis
` (3 preceding siblings ...)
2026-08-20 10:52 ` [PATCH BlueZ 4/6] device: Add SecurityLevel properties to org.bluez.Device1 Frédéric Danis
@ 2026-08-20 10:52 ` Frédéric Danis
2026-08-20 10:52 ` [PATCH BlueZ 6/6] client: Display SecurityLevel in device info Frédéric Danis
5 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-08-20 10:52 UTC (permalink / raw)
To: linux-bluetooth
This adds the SecurityLevel and EncryptionType properties which can be
used by clients to get the security level and encryption type in use
for a connection.
---
doc/org.bluez.Device.rst | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/doc/org.bluez.Device.rst b/doc/org.bluez.Device.rst
index 3e6a30aaf..5120dbede 100644
--- a/doc/org.bluez.Device.rst
+++ b/doc/org.bluez.Device.rst
@@ -478,3 +478,39 @@ Possible values:
Examples:
:bluetoothctl: > bearer <dev> [last-seen/bredr/le]
+
+byte SecurityLevel [readonly, experimental]
+```````````````````````````````````````````
+Indicate the Security Level of a connection.
+
+Possible values:
+
+:0:
+ No security
+
+:1:
+ Unauthenticated pairing with encryption not required
+
+:2:
+ Unauthenticated pairing with encryption desired
+
+:3:
+ Authenticated pairing with encryption
+
+:4:
+ FIPS authenticated pairing with encryption
+
+byte EncryptionType [readonly, experimental]
+````````````````````````````````````````````
+Indicate the Encryption type in use for a connection.
+
+Possible values:
+
+:0:
+ No encryption
+
+:1:
+ E0 encryption
+
+:2:
+ AES-CCM encryption
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH BlueZ 6/6] client: Display SecurityLevel in device info
2026-08-20 10:52 [PATCH BlueZ 0/6] mgmt/device: report link security level to D-Bus clients Frédéric Danis
` (4 preceding siblings ...)
2026-08-20 10:52 ` [PATCH BlueZ 5/6] org.bluez.Device: Add Security Level related properties Frédéric Danis
@ 2026-08-20 10:52 ` Frédéric Danis
5 siblings, 0 replies; 8+ messages in thread
From: Frédéric Danis @ 2026-08-20 10:52 UTC (permalink / raw)
To: linux-bluetooth
---
client/main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/client/main.c b/client/main.c
index 069e20485..0531c9de1 100644
--- a/client/main.c
+++ b/client/main.c
@@ -1918,6 +1918,8 @@ static void cmd_info(int argc, char *argv[])
print_property(proxy, "WakeAllowed");
print_property(proxy, "LegacyPairing");
print_property(proxy, "CablePairing");
+ print_property(proxy, "SecurityLevel");
+ print_property(proxy, "EncryptionType");
print_uuids(proxy);
print_property(proxy, "Modalias");
print_property(proxy, "ManufacturerData");
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread