diff options
author | Sebastian Chlad <sebastian.chlad@tieto.com> | 2014-05-27 11:21:58 +0200 |
---|---|---|
committer | Sebastian Chlad <sebastian.chlad@tieto.com> | 2014-05-27 11:21:58 +0200 |
commit | 9b7805a3ebc7ab3c4500290df889abedbfd377fc (patch) | |
tree | 12d87aca23319078a4cd6a2aa9aba8d82967e11e /monitor/keys.c | |
parent | 5d363eb448eacca7c3939fd6e8d6ee3c284db7e2 (diff) | |
download | bluez-9b7805a3ebc7ab3c4500290df889abedbfd377fc.tar.gz bluez-9b7805a3ebc7ab3c4500290df889abedbfd377fc.tar.bz2 bluez-9b7805a3ebc7ab3c4500290df889abedbfd377fc.zip |
Imported Upstream version 5.19upstream/5.19upstream
Diffstat (limited to 'monitor/keys.c')
-rw-r--r-- | monitor/keys.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/monitor/keys.c b/monitor/keys.c new file mode 100644 index 00000000..4ccef22c --- /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, free); +} + +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; +} |