Linux bluetooth development
 help / color / mirror / Atom feed
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], &ltk->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


             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