From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v1 1/2] client/mgmt: Add options to ltks command for loading entries
Date: Wed, 3 Jun 2026 15:03:57 -0400 [thread overview]
Message-ID: <20260603190358.425835-1-luiz.dentz@gmail.com> (raw)
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Add support for optionally specifying a single LTK entry when using
the ltks command. When called without arguments it clears all LTKs
(existing behavior). When called with an address and key parameters
it loads exactly one LTK entry, useful for testing.
Options:
-a addr_type Address type (1=LE Public, 2=LE Random)
-t key_type Key type (0=Unauthenticated, 1=Authenticated)
-c central Central flag (0 or 1)
-e enc_size Encryption key size (7-16)
-d ediv Encrypted Diversifier
-r rand Random number (64-bit)
-k key 128-bit key as 32 hex characters
---
client/mgmt.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 94 insertions(+), 6 deletions(-)
diff --git a/client/mgmt.c b/client/mgmt.c
index 50558a313866..6d6ada95f43d 100644
--- a/client/mgmt.c
+++ b/client/mgmt.c
@@ -3535,21 +3535,107 @@ static void ltks_rsp(uint8_t status, uint16_t len, const void *param,
bt_shell_noninteractive_quit(EXIT_SUCCESS);
}
+static const struct option ltks_options[] = {
+ { "help", 0, 0, 'h' },
+ { "address-type", 1, 0, 'a' },
+ { "type", 1, 0, 't' },
+ { "central", 1, 0, 'c' },
+ { "enc-size", 1, 0, 'e' },
+ { "ediv", 1, 0, 'd' },
+ { "rand", 1, 0, 'r' },
+ { "key", 1, 0, 'k' },
+ { 0, 0, 0, 0 }
+};
+
static void cmd_ltks(int argc, char **argv)
{
- struct mgmt_cp_load_long_term_keys cp;
+ struct mgmt_cp_load_long_term_keys *cp;
+ uint8_t buf[sizeof(*cp) + sizeof(struct mgmt_ltk_info)];
+ uint16_t count = 0;
+ struct mgmt_ltk_info *ltk;
+ uint8_t addr_type = BDADDR_LE_PUBLIC;
+ int opt;
uint16_t index;
index = mgmt_index;
if (index == MGMT_INDEX_NONE)
index = 0;
- memset(&cp, 0, sizeof(cp));
+ cp = (void *) buf;
+ memset(buf, 0, sizeof(buf));
+ ltk = &cp->keys[0];
- if (mgmt_send(mgmt, MGMT_OP_LOAD_LONG_TERM_KEYS, index, sizeof(cp), &cp,
- ltks_rsp, NULL, NULL) == 0) {
+ while ((opt = getopt_long(argc, argv, "+a:t:c:e:d:r:k:h",
+ ltks_options, NULL)) != -1) {
+ switch (opt) {
+ case 'a':
+ addr_type = strtol(optarg, NULL, 0);
+ if (addr_type != BDADDR_LE_PUBLIC &&
+ addr_type != BDADDR_LE_RANDOM) {
+ error("Invalid address type (expected 1=LE "
+ "Public, 2=LE Random)");
+ optind = 0;
+ return bt_shell_noninteractive_quit(
+ EXIT_FAILURE);
+ }
+ break;
+ case 't':
+ ltk->type = strtol(optarg, NULL, 0);
+ break;
+ case 'c':
+ ltk->central = strtol(optarg, NULL, 0);
+ break;
+ case 'e':
+ ltk->enc_size = strtol(optarg, NULL, 0);
+ break;
+ case 'd':
+ ltk->ediv = strtol(optarg, NULL, 0);
+ break;
+ case 'r':
+ ltk->rand = strtoull(optarg, NULL, 0);
+ break;
+ case 'k':
+ if (strlen(optarg) != 32) {
+ error("Invalid key length (expected 32 hex "
+ "chars)");
+ optind = 0;
+ return bt_shell_noninteractive_quit(
+ EXIT_FAILURE);
+ }
+ for (int i = 0; i < 16; i++) {
+ char byte[3] = { optarg[i * 2],
+ optarg[i * 2 + 1], 0 };
+ ltk->val[i] = strtol(byte, NULL, 16);
+ }
+ break;
+ case 'h':
+ bt_shell_usage();
+ optind = 0;
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+ default:
+ bt_shell_usage();
+ optind = 0;
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ optind = 0;
+
+ if (argc > 0) {
+ str2ba(argv[0], <k->addr.bdaddr);
+ ltk->addr.type = addr_type;
+ count = 1;
+ }
+
+ cp->key_count = cpu_to_le16(count);
+
+ if (mgmt_send(mgmt, MGMT_OP_LOAD_LONG_TERM_KEYS, index,
+ sizeof(*cp) + count * sizeof(*ltk), cp,
+ ltks_rsp, NULL, NULL) == 0) {
error("Unable to send load_ltks cmd");
- return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
}
}
@@ -6136,7 +6222,9 @@ static const struct bt_shell_menu mgmt_menu = {
cmd_unpair, "Unpair device" },
{ "keys", NULL,
cmd_keys, "Load Link Keys" },
- { "ltks", NULL,
+ { "ltks", "[-a addr_type] [-t key_type] [-c central] "
+ "[-e enc_size] [-d ediv] [-r rand] [-k key] "
+ "[address]",
cmd_ltks, "Load Long Term Keys" },
{ "irks", "[--local index] [--file file path]",
cmd_irks, "Load Identity Resolving Keys" },
--
2.54.0
next reply other threads:[~2026-06-03 19:04 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-03 19:03 Luiz Augusto von Dentz [this message]
2026-06-03 19:03 ` [PATCH BlueZ v1 2/2] doc/bluetoothctl-mgmt: Update ltks command documentation Luiz Augusto von Dentz
2026-06-03 20:36 ` [BlueZ,v1,1/2] client/mgmt: Add options to ltks command for loading entries bluez.test.bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260603190358.425835-1-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox