monitor: Add support key handling management commands
diff --git a/monitor/packet.c b/monitor/packet.c
index ef3066f..8c61ca8 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -9586,6 +9586,115 @@
print_text(COLOR_UNKNOWN_ADV_FLAG, " Unknown advertising flag"
" (0x%8.8x)", mask);
}
+
+static void mgmt_print_store_hint(uint8_t hint)
+{
+ const char *str;
+
+ switch (hint) {
+ case 0x00:
+ str = "No";
+ break;
+ case 0x01:
+ str = "Yes";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Store hint: %s (0x%2.2x)", str, hint);
+}
+
+static void mgmt_print_link_key(const void *data)
+{
+ uint8_t address_type = get_u8(data + 6);
+ uint8_t key_type = get_u8(data + 7);
+ uint8_t pin_len = get_u8(data + 24);
+
+ mgmt_print_address(data, address_type);
+ print_key_type(key_type);
+ print_link_key(data + 8);
+ print_field("PIN length: %d", pin_len);
+}
+
+static void mgmt_print_long_term_key(const void *data)
+{
+ uint8_t address_type = get_u8(data + 6);
+ uint8_t key_type = get_u8(data + 7);
+ uint8_t master = get_u8(data + 8);
+ uint8_t enc_size = get_u8(data + 9);
+ const char *str;
+
+ mgmt_print_address(data, address_type);
+
+ switch (key_type) {
+ case 0x00:
+ str = "Unauthenticated legacy key";
+ break;
+ case 0x01:
+ str = "Authenticated legacy key";
+ break;
+ case 0x02:
+ str = "Unauthenticated key from P-256";
+ break;
+ case 0x03:
+ str = "Authenticated key from P-256";
+ break;
+ case 0x04:
+ str = "Debug key from P-256";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Key type: %s (0x%2.2x)", str, key_type);
+ print_field("Master: 0x%2.2x", master);
+ print_field("Encryption size: %u", enc_size);
+ print_hex_field("Diversifier", data + 10, 2);
+ print_hex_field("Randomizer", data + 12, 8);
+ print_hex_field("Key", data + 20, 16);
+}
+
+static void mgmt_print_identity_resolving_key(const void *data)
+{
+ uint8_t address_type = get_u8(data + 6);
+
+ mgmt_print_address(data, address_type);
+ print_hex_field("Key", data + 7, 16);
+}
+
+static void mgmt_print_signature_resolving_key(const void *data)
+{
+ uint8_t address_type = get_u8(data + 6);
+ uint8_t key_type = get_u8(data + 7);
+ const char *str;
+
+ mgmt_print_address(data, address_type);
+
+ switch (key_type) {
+ case 0x00:
+ str = "Unauthenticated local CSRK";
+ break;
+ case 0x01:
+ str = "Unauthenticated remote CSRK";
+ break;
+ case 0x02:
+ str = "Authenticated local CSRK";
+ break;
+ case 0x03:
+ str = "Authenticated remote CSRK";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("Key type: %s (0x%2.2x)", str, key_type);
+ print_hex_field("Key", data + 8, 16);
+}
+
static void mgmt_null_cmd(const void *data, uint16_t size)
{
}
@@ -9792,6 +9901,40 @@
print_dev_class(data);
}
+static void mgmt_load_link_keys_cmd(const void *data, uint16_t size)
+{
+ uint8_t debug_keys = get_u8(data);
+ uint16_t num_keys = get_le16(data + 1);
+ int i;
+
+ mgmt_print_enable("Debug keys", debug_keys);
+ print_field("Keys: %u", num_keys);
+
+ if (size - 3 != num_keys * 25) {
+ packet_hexdump(data + 3, size - 3);
+ return;
+ }
+
+ for (i = 0; i < num_keys; i++)
+ mgmt_print_link_key(data + 3 + (i * 25));
+}
+
+static void mgmt_load_long_term_keys_cmd(const void *data, uint16_t size)
+{
+ uint16_t num_keys = get_le16(data + 1);
+ int i;
+
+ print_field("Keys: %u", num_keys);
+
+ if (size - 2 != num_keys * 36) {
+ packet_hexdump(data + 2, size - 2);
+ return;
+ }
+
+ for (i = 0; i < num_keys; i++)
+ mgmt_print_long_term_key(data + 2 + (i * 36));
+}
+
static void mgmt_disconnect_cmd(const void *data, uint16_t size)
{
uint8_t address_type = get_u8(data + 6);
@@ -9819,7 +9962,7 @@
}
for (i = 0; i < num_connections; i++) {
- uint16_t address_type = get_le16(data + 2 + (i * 7) + 6);
+ uint8_t address_type = get_u8(data + 2 + (i * 7) + 6);
mgmt_print_address(data + 2 + (i * 7), address_type);
}
@@ -10068,6 +10211,22 @@
print_field("Privacy: %s (0x%2.2x)", str, enable);
}
+static void mgmt_load_identity_resolving_keys_cmd(const void *data, uint16_t size)
+{
+ uint16_t num_keys = get_le16(data + 1);
+ int i;
+
+ print_field("Keys: %u", num_keys);
+
+ if (size - 2 != num_keys * 23) {
+ packet_hexdump(data + 2, size - 2);
+ return;
+ }
+
+ for (i = 0; i < num_keys; i++)
+ mgmt_print_identity_resolving_key(data + 2 + (i * 23));
+}
+
static void mgmt_add_device_cmd(const void *data, uint16_t size)
{
uint8_t address_type = get_u8(data + 6);
@@ -10323,8 +10482,12 @@
{ 0x0011, "Remove UUID",
mgmt_remove_uuid_cmd, 16, true,
mgmt_remove_uuid_rsp, 3, true },
- { 0x0012, "Load Link Keys" },
- { 0x0013, "Load Long Term Keys" },
+ { 0x0012, "Load Link Keys",
+ mgmt_load_link_keys_cmd, 3, false,
+ mgmt_null_rsp, 0, true },
+ { 0x0013, "Load Long Term Keys",
+ mgmt_load_long_term_keys_cmd, 2, false,
+ mgmt_null_rsp, 0, true },
{ 0x0014, "Disconnect",
mgmt_disconnect_cmd, 7, true,
mgmt_disconnect_rsp, 7, true },
@@ -10388,7 +10551,9 @@
{ 0x002f, "Set Privacy",
mgmt_set_privacy_cmd, 1, true,
mgmt_new_settings_rsp, 4, true },
- { 0x0030, "Load Identity Resolving Keys" },
+ { 0x0030, "Load Identity Resolving Keys",
+ mgmt_load_identity_resolving_keys_cmd, 2, false,
+ mgmt_null_rsp, 0, true },
{ 0x0031, "Get Connection Information" },
{ 0x0032, "Get Clock Information" },
{ 0x0033, "Add Device",
@@ -10549,6 +10714,22 @@
mgmt_print_name(data);
}
+static void mgmt_new_link_key_evt(const void *data, uint16_t size)
+{
+ uint8_t store_hint = get_u8(data);
+
+ mgmt_print_store_hint(store_hint);
+ mgmt_print_link_key(data + 1);
+}
+
+static void mgmt_new_long_term_key_evt(const void *data, uint16_t size)
+{
+ uint8_t store_hint = get_u8(data);
+
+ mgmt_print_store_hint(store_hint);
+ mgmt_print_long_term_key(data + 1);
+}
+
static void mgmt_device_connected_evt(const void *data, uint16_t size)
{
uint8_t address_type = get_u8(data + 6);
@@ -10655,6 +10836,23 @@
mgmt_print_address(data, address_type);
}
+static void mgmt_new_identity_resolving_key_evt(const void *data, uint16_t size)
+{
+ uint8_t store_hint = get_u8(data);
+
+ mgmt_print_store_hint(store_hint);
+ print_addr_resolve("Random address", data + 1, 0x01, false);
+ mgmt_print_identity_resolving_key(data + 7);
+}
+
+static void mgmt_new_signature_resolving_key_evt(const void *data, uint16_t size)
+{
+ uint8_t store_hint = get_u8(data);
+
+ mgmt_print_store_hint(store_hint);
+ mgmt_print_signature_resolving_key(data + 1);
+}
+
static void mgmt_device_added_evt(const void *data, uint16_t size)
{
uint8_t address_type = get_u8(data + 6);
@@ -10735,8 +10933,10 @@
mgmt_class_of_dev_changed_evt, 3, true },
{ 0x0008, "Local Name Changed",
mgmt_local_name_changed_evt, 260, true },
- { 0x0009, "New Link Key" },
- { 0x000a, "New Long Term Key" },
+ { 0x0009, "New Link Key",
+ mgmt_new_link_key_evt, 26, true },
+ { 0x000a, "New Long Term Key",
+ mgmt_new_long_term_key_evt, 37, true },
{ 0x000b, "Device Connected",
mgmt_device_connected_evt, 13, false },
{ 0x000c, "Device Disconnected",
@@ -10759,8 +10959,10 @@
{ 0x0016, "Device Unpaired",
mgmt_device_unpaired_evt, 7, true },
{ 0x0017, "Passkey Notify" },
- { 0x0018, "New Identity Resolving Key" },
- { 0x0019, "New Signature Resolving Key" },
+ { 0x0018, "New Identity Resolving Key",
+ mgmt_new_identity_resolving_key_evt, 30, true },
+ { 0x0019, "New Signature Resolving Key",
+ mgmt_new_signature_resolving_key_evt, 25, true },
{ 0x001a, "Device Added",
mgmt_device_added_evt, 8, true },
{ 0x001b, "Device Removed",