Diff between afa239060fc83953f974747cb86428a744647b8f and 8addbf220ee7d47b414d55a53ce5fe1f7b94d62f

Changed Files

File Additions Deletions Status
Makefile.tools +2 -0 modified
android/Android.mk +2 -0 modified
monitor/keys.c +144 -0 added
monitor/keys.h +35 -0 added
monitor/l2cap.c +5 -0 modified
monitor/main.c +9 -1 modified
monitor/packet.c +35 -18 modified

Full Patch

diff --git a/Makefile.tools b/Makefile.tools
index b8df136..dc871cf 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -28,9 +28,11 @@ monitor_btmon_SOURCES = monitor/main.c monitor/bt.h \
 				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
@@ -195,10 +195,12 @@ LOCAL_SRC_FILES := \
 	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
@@ -0,0 +1,144 @@
+/*
+ *
+ *  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
@@ -0,0 +1,35 @@
+/*
+ *
+ *  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
@@ -39,6 +39,7 @@
 #include "display.h"
 #include "l2cap.h"
 #include "uuid.h"
+#include "keys.h"
 #include "sdp.h"
 
 #define MAX_CHAN 64
@@ -2466,6 +2467,8 @@ static void smp_ident_info(const struct l2cap_frame *frame)
 	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)
@@ -2474,6 +2477,8 @@ 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
@@ -35,6 +35,7 @@
 #include "mainloop.h"
 #include "packet.h"
 #include "lmp.h"
+#include "keys.h"
 #include "analyze.h"
 #include "ellisys.h"
 #include "control.h"
@@ -92,6 +93,7 @@ int main(int argc, char *argv[])
 	const char *ellisys_server = NULL;
 	unsigned short ellisys_port = 0;
 	const char *str;
+	int exit_status;
 	sigset_t mask;
 
 	mainloop_init();
@@ -179,6 +181,8 @@ int main(int argc, char *argv[])
 
 	printf("Bluetooth monitor ver %s\n", VERSION);
 
+	keys_setup();
+
 	packet_set_filter(filter_mask);
 
 	if (analyze_path) {
@@ -203,5 +207,9 @@ int main(int argc, char *argv[])
 	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
@@ -47,6 +47,7 @@
 #include "bt.h"
 #include "ll.h"
 #include "hwdb.h"
+#include "keys.h"
 #include "uuid.h"
 #include "l2cap.h"
 #include "control.h"
@@ -403,8 +404,27 @@ void packet_print_error(const char *label, uint8_t error)
 	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;
@@ -448,6 +468,16 @@ static void print_addr(const char *label, const uint8_t *addr,
 		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",
@@ -457,23 +487,10 @@ static void print_addr(const char *label, const uint8_t *addr,
 	}
 }
 
-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)