From 8addbf220ee7d47b414d55a53ce5fe1f7b94d62f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 17 Feb 2014 00:21:59 -0800 Subject: [PATCH] monitor: Add support for resolving random addresses --- Makefile.tools | 2 + android/Android.mk | 2 + monitor/keys.c | 144 +++++++++++++++++++++++++++++++++++++++++++++ monitor/keys.h | 35 +++++++++++ monitor/l2cap.c | 5 ++ monitor/main.c | 10 +++- monitor/packet.c | 53 +++++++++++------ 7 files changed, 232 insertions(+), 19 deletions(-) create mode 100644 monitor/keys.c create mode 100644 monitor/keys.h diff --git a/Makefile.tools b/Makefile.tools index b8df136ef..dc871cfe0 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 20602f3ba..2481a2c08 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 000000000..4d7c0354c --- /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 + * + * + * 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 +#endif + +#include + +#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 000000000..61ec50a4c --- /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 + * + * + * 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 +#include + +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 bc0c5b4f1..58c8c5c1e 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 b2a7cd424..d4e8e6d5c 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 e92be7a8a..4c5136d02 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) -- 2.47.3