mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-09-10 20:42:48 +00:00
If privacy is enabled we always use RPA, even for active scan. This makes single point of controlling current random address making code simple and not prone to subtle bugs with concurent advertising, scanning and connecting. Currently used RPA is rotated to improve privacy. Timeout value is controlled by Kconfig and by default is 900 seconds (15 minutes). Change-Id: I27a15666a4f2e2962cf6eb20c7cd06f90b7f2bb1 Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com>
264 lines
5.4 KiB
C
264 lines
5.4 KiB
C
/* keys.c - Bluetooth key handling */
|
|
|
|
/*
|
|
* Copyright (c) 2015-2016 Intel Corporation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <nanokernel.h>
|
|
#include <atomic.h>
|
|
#include <misc/util.h>
|
|
#include <misc/nano_work.h>
|
|
|
|
#include <bluetooth/log.h>
|
|
#include <bluetooth/bluetooth.h>
|
|
#include <bluetooth/conn.h>
|
|
#include <bluetooth/hci.h>
|
|
|
|
#include "hci_core.h"
|
|
#include "smp.h"
|
|
#include "keys.h"
|
|
|
|
#if !defined(CONFIG_BLUETOOTH_DEBUG_KEYS)
|
|
#undef BT_DBG
|
|
#define BT_DBG(fmt, ...)
|
|
#endif
|
|
|
|
static struct bt_keys key_pool[CONFIG_BLUETOOTH_MAX_PAIRED];
|
|
|
|
#if defined(CONFIG_BLUETOOTH_SMP)
|
|
struct bt_keys *bt_keys_get_addr(const bt_addr_le_t *addr)
|
|
{
|
|
struct bt_keys *keys;
|
|
int i;
|
|
|
|
BT_DBG("%s", bt_addr_le_str(addr));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
|
keys = &key_pool[i];
|
|
|
|
if (!bt_addr_le_cmp(&keys->addr, addr)) {
|
|
return keys;
|
|
}
|
|
|
|
if (!bt_addr_le_cmp(&keys->addr, BT_ADDR_LE_ANY)) {
|
|
bt_addr_le_copy(&keys->addr, addr);
|
|
BT_DBG("created %p for %s", keys, bt_addr_le_str(addr));
|
|
return keys;
|
|
}
|
|
}
|
|
|
|
BT_DBG("unable to create keys for %s", bt_addr_le_str(addr));
|
|
|
|
return NULL;
|
|
}
|
|
struct bt_keys *bt_keys_find(int type, const bt_addr_le_t *addr)
|
|
{
|
|
int i;
|
|
|
|
BT_DBG("type %d %s", type, bt_addr_le_str(addr));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
|
if ((key_pool[i].keys & type) &&
|
|
!bt_addr_le_cmp(&key_pool[i].addr, addr)) {
|
|
return &key_pool[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct bt_keys *bt_keys_get_type(int type, const bt_addr_le_t *addr)
|
|
{
|
|
struct bt_keys *keys;
|
|
|
|
BT_DBG("type %d %s", type, bt_addr_le_str(addr));
|
|
|
|
keys = bt_keys_find(type, addr);
|
|
if (keys) {
|
|
return keys;
|
|
}
|
|
|
|
keys = bt_keys_get_addr(addr);
|
|
if (!keys) {
|
|
return NULL;
|
|
}
|
|
|
|
bt_keys_add_type(keys, type);
|
|
|
|
return keys;
|
|
}
|
|
|
|
struct bt_keys *bt_keys_find_irk(const bt_addr_le_t *addr)
|
|
{
|
|
int i;
|
|
|
|
BT_DBG("%s", bt_addr_le_str(addr));
|
|
|
|
if (!bt_addr_le_is_rpa(addr)) {
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
|
if (!(key_pool[i].keys & BT_KEYS_IRK)) {
|
|
continue;
|
|
}
|
|
|
|
if (!bt_addr_cmp(&addr->a, &key_pool[i].irk.rpa)) {
|
|
BT_DBG("cached RPA %s for %s",
|
|
bt_addr_str(&key_pool[i].irk.rpa),
|
|
bt_addr_le_str(&key_pool[i].addr));
|
|
return &key_pool[i];
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
|
if (!(key_pool[i].keys & BT_KEYS_IRK)) {
|
|
continue;
|
|
}
|
|
|
|
if (bt_smp_irk_matches(key_pool[i].irk.val, &addr->a)) {
|
|
BT_DBG("RPA %s matches %s",
|
|
bt_addr_str(&key_pool[i].irk.rpa),
|
|
bt_addr_le_str(&key_pool[i].addr));
|
|
|
|
bt_addr_copy(&key_pool[i].irk.rpa, &addr->a);
|
|
|
|
return &key_pool[i];
|
|
}
|
|
}
|
|
|
|
BT_DBG("No IRK for %s", bt_addr_le_str(addr));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct bt_keys *bt_keys_find_addr(const bt_addr_le_t *addr)
|
|
{
|
|
int i;
|
|
|
|
BT_DBG("%s", bt_addr_le_str(addr));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
|
if (!bt_addr_le_cmp(&key_pool[i].addr, addr)) {
|
|
return &key_pool[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif /* CONFIG_BLUETOOTH_SMP */
|
|
|
|
void bt_keys_add_type(struct bt_keys *keys, int type)
|
|
{
|
|
keys->keys |= type;
|
|
}
|
|
|
|
void bt_keys_clear(struct bt_keys *keys, int type)
|
|
{
|
|
BT_DBG("keys for %s type %d", bt_addr_le_str(&keys->addr), type);
|
|
|
|
keys->keys &= ~type;
|
|
|
|
if (!keys->keys) {
|
|
memset(keys, 0, sizeof(*keys));
|
|
}
|
|
}
|
|
|
|
#if defined(CONFIG_BLUETOOTH_BREDR)
|
|
static struct bt_keys *bt_keys_get_addr_br(const bt_addr_t *addr)
|
|
{
|
|
struct bt_keys *keys;
|
|
int i;
|
|
|
|
BT_DBG("%s", bt_addr_str(addr));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
|
keys = &key_pool[i];
|
|
|
|
/*
|
|
* When both LE and BR/EDR keys are for the same device,
|
|
* the bt_addr_le_t is the public address, i.e. the same
|
|
* as the BR/EDR address.
|
|
*/
|
|
if (keys->addr.type == BT_ADDR_LE_PUBLIC &&
|
|
!bt_addr_cmp(&keys->addr.a, addr)) {
|
|
return keys;
|
|
}
|
|
|
|
/*
|
|
* BT_ADDR_LE_ANY has the same type of as BT_ADDR_LE_PUBLIC
|
|
* value. No need to make redudant comparision against
|
|
* BT_ADDR_LE_PUBLIC.
|
|
*/
|
|
if (!bt_addr_le_cmp(&keys->addr, BT_ADDR_LE_ANY)) {
|
|
bt_addr_copy(&keys->addr.a, addr);
|
|
BT_DBG("created %p for %s", keys, bt_addr_str(addr));
|
|
return keys;
|
|
}
|
|
}
|
|
|
|
BT_DBG("unable to create keys for %s", bt_addr_str(addr));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct bt_keys *bt_keys_find_link_key(const bt_addr_t *addr)
|
|
{
|
|
struct bt_keys *keys;
|
|
int i;
|
|
|
|
BT_DBG("%s", bt_addr_str(addr));
|
|
|
|
for (i = 0; i < ARRAY_SIZE(key_pool); i++) {
|
|
keys = &key_pool[i];
|
|
|
|
/*
|
|
* When both LE and BR/EDR keys are for the same device,
|
|
* the bt_addr_le_t is the public address, i.e. the same
|
|
* as the BR/EDR address.
|
|
*/
|
|
if (keys->addr.type == BT_ADDR_LE_PUBLIC &&
|
|
(keys->keys & BT_KEYS_LINK_KEY) &&
|
|
!bt_addr_cmp(&keys->addr.a, addr)) {
|
|
return keys;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
struct bt_keys *bt_keys_get_link_key(const bt_addr_t *addr)
|
|
{
|
|
struct bt_keys *keys;
|
|
|
|
BT_DBG("%s", bt_addr_str(addr));
|
|
|
|
keys = bt_keys_find_link_key(addr);
|
|
if (keys) {
|
|
return keys;
|
|
}
|
|
|
|
keys = bt_keys_get_addr_br(addr);
|
|
if (!keys) {
|
|
return NULL;
|
|
}
|
|
|
|
bt_keys_add_type(keys, BT_KEYS_LINK_KEY);
|
|
|
|
return keys;
|
|
}
|
|
#endif /* CONFIG_BLUETOOTH_BREDR */
|