diff --git a/Makefile.tools b/Makefile.tools
index b8df136..dc871cf 100644
--- a/Makefile.tools
+++ b/Makefile.tools
monitor/sdp.h monitor/sdp.c \
monitor/uuid.h monitor/uuid.c \
monitor/hwdb.h monitor/hwdb.c \
+ monitor/keys.h monitor/keys.c \
monitor/analyze.h monitor/analyze.c \
src/shared/util.h src/shared/util.c \
src/shared/queue.h src/shared/queue.c \
+ src/sharec/crypto.h src/shared/crypto.c \
src/shared/btsnoop.h src/shared/btsnoop.c
monitor_btmon_LDADD = lib/libbluetooth-internal.la @UDEV_LIBS@
endif
diff --git a/android/Android.mk b/android/Android.mk
index 20602f3..2481a2c 100644
--- a/android/Android.mk
+++ b/android/Android.mk
bluez/monitor/crc.c \
bluez/monitor/ll.c \
bluez/monitor/hwdb.c \
+ bluez/monitor/keys.c \
bluez/monitor/ellisys.c \
bluez/monitor/analyze.c \
bluez/src/shared/util.c \
bluez/src/shared/queue.c \
+ bluez/src/shared/crypto.c \
bluez/src/shared/btsnoop.c \
bluez/lib/hci.c \
bluez/lib/bluetooth.c \
diff --git a/monitor/keys.c b/monitor/keys.c
new file mode 100644
index 0000000..4d7c035
--- /dev/null
+++ b/monitor/keys.c
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011-2014 Intel Corporation
+ * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "src/shared/util.h"
+#include "src/shared/queue.h"
+#include "src/shared/crypto.h"
+
+#include "keys.h"
+
+static const uint8_t empty_key[16] = { 0x00, };
+static const uint8_t empty_addr[6] = { 0x00, };
+
+static struct bt_crypto *crypto;
+
+struct irk_data {
+ uint8_t key[16];
+ uint8_t addr[6];
+ uint8_t addr_type;
+};
+
+static struct queue *irk_list;
+
+void keys_setup(void)
+{
+ crypto = bt_crypto_new();
+
+ irk_list = queue_new();
+}
+
+void keys_cleanup(void)
+{
+ bt_crypto_unref(crypto);
+
+ queue_destroy(irk_list, NULL);
+}
+
+void keys_update_identity_key(const uint8_t key[16])
+{
+ struct irk_data *irk;
+
+ irk = queue_peek_tail(irk_list);
+ if (irk && !memcmp(irk->key, empty_key, 16)) {
+ memcpy(irk->key, key, 16);
+ return;
+ }
+
+ irk = new0(struct irk_data, 1);
+ if (irk) {
+ memcpy(irk->key, key, 16);
+ if (!queue_push_tail(irk_list, irk))
+ free(irk);
+ }
+}
+
+void keys_update_identity_addr(const uint8_t addr[6], uint8_t addr_type)
+{
+ struct irk_data *irk;
+
+ irk = queue_peek_tail(irk_list);
+ if (irk && !memcmp(irk->addr, empty_addr, 6)) {
+ memcpy(irk->addr, addr, 6);
+ irk->addr_type = addr_type;
+ return;
+ }
+
+ irk = new0(struct irk_data, 1);
+ if (irk) {
+ memcpy(irk->addr, addr, 6);
+ irk->addr_type = addr_type;
+ if (!queue_push_tail(irk_list, irk))
+ free(irk);
+ }
+}
+
+struct resolve_data {
+ bool found;
+ uint8_t addr[6];
+ uint8_t ident[6];
+ uint8_t ident_type;
+};
+
+static void try_resolve_irk(void *data, void *user_data)
+{
+ struct irk_data *irk = data;
+ struct resolve_data *result = user_data;
+ uint8_t local_hash[3];
+
+ if (result->found)
+ return;
+
+ bt_crypto_ah(crypto, irk->key, result->addr + 3, local_hash);
+
+ if (!memcmp(result->addr, local_hash, 3)) {
+ result->found = true;
+ memcpy(result->ident, irk->addr, 6);
+ result->ident_type = irk->addr_type;
+ }
+}
+
+bool keys_resolve_identity(const uint8_t addr[6], uint8_t ident[6],
+ uint8_t *ident_type)
+{
+ struct resolve_data result;
+
+ result.found = false;
+ memcpy(result.addr, addr, 6);
+
+ queue_foreach(irk_list, try_resolve_irk, &result);
+
+ if (result.found) {
+ memcpy(ident, result.ident, 6);
+ *ident_type = result.ident_type;
+ return true;
+ }
+
+ return false;
+}
diff --git a/monitor/keys.h b/monitor/keys.h
new file mode 100644
index 0000000..61ec50a
--- /dev/null
+++ b/monitor/keys.h
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2011-2014 Intel Corporation
+ * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+
+void keys_setup(void);
+void keys_cleanup(void);
+
+void keys_update_identity_key(const uint8_t key[16]);
+void keys_update_identity_addr(const uint8_t addr[6], uint8_t addr_type);
+
+bool keys_resolve_identity(const uint8_t addr[6], uint8_t ident[6],
+ uint8_t *ident_type);
diff --git a/monitor/l2cap.c b/monitor/l2cap.c
index bc0c5b4..58c8c5c 100644
--- a/monitor/l2cap.c
+++ b/monitor/l2cap.c
#include "display.h"
#include "l2cap.h"
#include "uuid.h"
+#include "keys.h"
#include "sdp.h"
#define MAX_CHAN 64
const struct bt_l2cap_smp_ident_info *pdu = frame->data;
print_hex_field("Identity resolving key", pdu->irk, 16);
+
+ keys_update_identity_key(pdu->irk);
}
static void smp_ident_addr_info(const struct l2cap_frame *frame)
print_addr_type(pdu->addr_type);
print_addr(pdu->addr, pdu->addr_type);
+
+ keys_update_identity_addr(pdu->addr, pdu->addr_type);
}
static void smp_signing_info(const struct l2cap_frame *frame)
diff --git a/monitor/main.c b/monitor/main.c
index b2a7cd4..d4e8e6d 100644
--- a/monitor/main.c
+++ b/monitor/main.c
#include "mainloop.h"
#include "packet.h"
#include "lmp.h"
+#include "keys.h"
#include "analyze.h"
#include "ellisys.h"
#include "control.h"
const char *ellisys_server = NULL;
unsigned short ellisys_port = 0;
const char *str;
+ int exit_status;
sigset_t mask;
mainloop_init();
printf("Bluetooth monitor ver %s\n", VERSION);
+ keys_setup();
+
packet_set_filter(filter_mask);
if (analyze_path) {
if (control_tracing() < 0)
return EXIT_FAILURE;
- return mainloop_run();
+ exit_status = mainloop_run();
+
+ keys_cleanup();
+
+ return exit_status;
}
diff --git a/monitor/packet.c b/monitor/packet.c
index e92be7a..4c5136d 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
#include "bt.h"
#include "ll.h"
#include "hwdb.h"
+#include "keys.h"
#include "uuid.h"
#include "l2cap.h"
#include "control.h"
print_error(label, error);
}
-static void print_addr(const char *label, const uint8_t *addr,
- uint8_t addr_type)
+static void print_addr_type(const char *label, uint8_t addr_type)
+{
+ const char *str;
+
+ switch (addr_type) {
+ case 0x00:
+ str = "Public";
+ break;
+ case 0x01:
+ str = "Random";
+ break;
+ default:
+ str = "Reserved";
+ break;
+ }
+
+ print_field("%s: %s (0x%2.2x)", label, str, addr_type);
+}
+
+static void print_addr_resolve(const char *label, const uint8_t *addr,
+ uint8_t addr_type, bool resolve)
{
const char *str;
char *company;
print_field("%s: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X (%s)",
label, addr[5], addr[4], addr[3],
addr[2], addr[1], addr[0], str);
+
+ if (resolve && (addr[5] & 0xc0) == 0x40) {
+ uint8_t ident[6], ident_type;
+
+ if (keys_resolve_identity(addr, ident, &ident_type)) {
+ print_addr_type(" Identity type", ident_type);
+ print_addr_resolve(" Identity", ident,
+ ident_type, false);
+ }
+ }
break;
default:
print_field("%s: %2.2X-%2.2X-%2.2X-%2.2X-%2.2X-%2.2X",
}
}
-static void print_addr_type(const char *label, uint8_t addr_type)
+static void print_addr(const char *label, const uint8_t *addr,
+ uint8_t addr_type)
{
- const char *str;
-
- switch (addr_type) {
- case 0x00:
- str = "Public";
- break;
- case 0x01:
- str = "Random";
- break;
- default:
- str = "Reserved";
- break;
- }
-
- print_field("%s: %s (0x%2.2x)", label, str, addr_type);
+ print_addr_resolve(label, addr, addr_type, true);
}
static void print_bdaddr(const uint8_t *bdaddr)