Bluetooth: Remove bt_storage API

The same functionality is now supported by the settings-based
solution, so remove bt_storage out of the way. There were stubs in
bt_storage to handle per-peer information (e.g. pairing keys) but this
was never actually implemented in full. The next step is to add this
support to the settings-based solution.

Leave the code for generating temporary IRK and identity address in
case BT_SETTINGS is not enabled. Also leave the code for using vendor
HCI to read the identity address, in which case the settings
implementation will not touch it.

Introduce a new bt_unpair() API to replace the removed
bt_storage_clear(), since the latter was actually doing more than just
storage management: it was also handling runtime storage of pairing
information. Later, the bt_unpair() implementation will be extended to
clear settings-based pairing storage.

There is one feature that the bt shell module looses: the ability to
give a specific identity address to the "init" command as a parameter.
We might look later in the future if this is really needed, and add a
separate API for this.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2018-04-27 10:31:13 +03:00 committed by Anas Nashif
parent b997a283f7
commit d22b7c9f2d
11 changed files with 106 additions and 592 deletions

View file

@ -126,12 +126,6 @@ Logical Link Control and Adaptation Protocol (L2CAP)
.. doxygengroup:: bt_l2cap
:project: Zephyr
Persistent Storage
******************
.. doxygengroup:: bt_storage
:project: Zephyr
Serial Port Emulation (RFCOMM)
******************************

View file

@ -474,6 +474,15 @@ int bt_br_set_discoverable(bool enable);
*/
int bt_br_set_connectable(bool enable);
/** Clear pairing information.
*
* @param addr Remote address, NULL or BT_ADDR_LE_ANY to clear all remote
* devices.
*
* @return 0 on success or negative error value on failure.
*/
int bt_unpair(const bt_addr_le_t *addr);
/**
* @}
*/

View file

@ -1,146 +0,0 @@
/** @file
* @brief Bluetooth subsystem persistent storage APIs.
*/
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __BT_STORAGE_H
#define __BT_STORAGE_H
/**
* @brief Persistent Storage
* @defgroup bt_storage Persistent Storage
* @ingroup bluetooth
* @{
*/
#include <sys/types.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Well known storage keys */
enum {
/** Identity Address.
* Type: bt_addr_le_t (7 bytes)
*/
BT_STORAGE_ID_ADDR,
/** Local Identity Resolving Key.
* Type: u8_t key[16]
*/
BT_STORAGE_LOCAL_IRK,
/** List of addresses of remote devices.
* Type: bt_addr_le_t addrs[n] (length is variable).
*
* This is only used for reading. Modification of the list happens
* implicitly by writing entries for each remote device. This value
* is only used with the local storage, i.e. NULL as the target
* bt_addr_le_t passed to the read callback.
*/
BT_STORAGE_ADDRESSES,
/** Slave Long Term Key for legacy pairing.
* Type: struct bt_storage_ltk
*/
BT_STORAGE_SLAVE_LTK,
/** Long Term Key for legacy pairing.
* Type: struct bt_storage_ltk
*/
BT_STORAGE_LTK,
/** Identity Resolving Key
* Type: u8_t key[16]
*/
BT_STORAGE_IRK,
};
/** LTK key flags */
enum {
/* Key has been generated with MITM protection */
BT_STORAGE_LTK_AUTHENTICATED = BIT(0),
/* Key has been generated using the LE Secure Connection pairing */
BT_STORAGE_LTK_SC = BIT(1),
};
struct bt_storage_ltk {
u8_t flags;
/* Encryption key size used to generate key */
u8_t size;
u16_t ediv;
u8_t rand[8];
u8_t val[16];
};
struct bt_storage {
/** Read the value of a key from storage.
*
* @param addr Remote address or NULL for local storage
* @param key BT_STORAGE_* key to read
* @param data Memory location to place the data
* @param length Maximum number of bytes to read
*
* @return Number of bytes read or negative error value on
* failure.
*/
ssize_t (*read)(const bt_addr_le_t *addr, u16_t key,
void *data, size_t length);
/** Write the value of a key to storage.
*
* @param addr Remote address or NULL for local storage
* @param key BT_STORAGE_* key to write
* @param data Memory location of the data
* @param length Number of bytes to write
*
* @return Number of bytes written or negative error value on
* failure.
*/
ssize_t (*write)(const bt_addr_le_t *addr, u16_t key,
const void *data, size_t length);
/** Clear all keys for a specific address
*
* @param addr Remote address, BT_ADDR_LE_ANY for all
* remote devices, or NULL for local storage.
*
* @return 0 on success or negative error value on failure.
*/
int (*clear)(const bt_addr_le_t *addr);
};
/** Register callbacks for storage handling.
*
* @param storage Callback struct.
*/
void bt_storage_register(const struct bt_storage *storage);
/** Clear all storage keys for a specific address
*
* @param addr Remote address, NULL for local storage or
* BT_ADDR_LE_ANY to clear all remote devices.
*
* @return 0 on success or negative error value on failure.
*/
int bt_storage_clear(const bt_addr_le_t *addr);
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* __BT_STORAGE_H */

View file

@ -1,11 +1,6 @@
zephyr_library()
zephyr_library_link_libraries(subsys__bluetooth)
if(CONFIG_BT_INTERNAL_STORAGE)
zephyr_library_sources(storage.c)
zephyr_library_link_libraries(subsys__fs)
endif()
zephyr_library_sources_ifdef(CONFIG_BT_HCI_RAW hci_raw.c)
zephyr_library_sources_ifdef(CONFIG_BT_DEBUG_MONITOR monitor.c)
zephyr_library_sources_ifdef(CONFIG_BT_TINYCRYPT_ECC hci_ecc.c)

View file

@ -148,15 +148,6 @@ config BT_SETTINGS
which case it's more efficient to load all settings in one go,
instead of each subsystem doing it independently.
config BT_INTERNAL_STORAGE
bool "Use an internal persistent storage handler"
depends on FILE_SYSTEM
depends on PRINTK
help
When selected the application doesn't need to register its own
persistent storage handlers through the bt_storage API, rather
an internal default handler is used for this.
if BT_CONN
if BT_HCI_ACL_FLOW_CONTROL

View file

@ -25,7 +25,6 @@
#include <bluetooth/hci.h>
#include <bluetooth/hci_vs.h>
#include <bluetooth/hci_driver.h>
#include <bluetooth/storage.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
#include "common/log.h"
@ -78,8 +77,6 @@ struct bt_dev bt_dev = {
static bt_ready_cb_t ready_cb;
const struct bt_storage *bt_storage;
static bt_le_scan_cb_t *scan_dev_found_cb;
static u8_t pub_key[64];
@ -1272,6 +1269,53 @@ static int set_flow_control(void)
return bt_hci_cmd_send_sync(BT_HCI_OP_SET_CTL_TO_HOST_FLOW, buf, NULL);
}
#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */
static int bt_clear_all_pairings(void)
{
bt_conn_disconnect_all();
if (IS_ENABLED(CONFIG_BT_SMP)) {
bt_keys_clear_all();
}
if (IS_ENABLED(CONFIG_BT_BREDR)) {
bt_keys_link_key_clear_addr(NULL);
}
return 0;
}
int bt_unpair(const bt_addr_le_t *addr)
{
struct bt_conn *conn;
if (!addr || !bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
return bt_clear_all_pairings();
}
conn = bt_conn_lookup_addr_le(addr);
if (conn) {
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
bt_conn_unref(conn);
}
if (IS_ENABLED(CONFIG_BT_BREDR)) {
/* LE Public may indicate BR/EDR as well */
if (addr->type == BT_ADDR_LE_PUBLIC) {
bt_keys_link_key_clear_addr(&addr->a);
}
}
if (IS_ENABLED(CONFIG_BT_SMP)) {
struct bt_keys *keys = bt_keys_find_addr(addr);
if (keys) {
bt_keys_clear(keys);
}
}
return 0;
}
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_BREDR)
@ -4050,20 +4094,30 @@ int bt_addr_le_create_static(bt_addr_le_t *addr)
return 0;
}
static int set_static_addr(void)
int bt_set_static_addr(void)
{
int err;
if (bt_storage) {
ssize_t ret;
ret = bt_storage->read(NULL, BT_STORAGE_ID_ADDR,
&bt_dev.id_addr, sizeof(bt_dev.id_addr));
if (ret == sizeof(bt_dev.id_addr)) {
goto set_addr;
}
if (bt_dev.id_addr.type != BT_ADDR_LE_RANDOM ||
(bt_dev.id_addr.a.val[5] & 0xc0) != 0xc0) {
BT_ERR("Only static random address supported as identity");
return -EINVAL;
}
err = set_random_address(&bt_dev.id_addr.a);
if (err) {
return err;
}
atomic_set_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM);
return 0;
}
static int setup_id_addr(void)
{
int err;
#if defined(CONFIG_BT_HCI_VS_EXT)
/* Check for VS_Read_Static_Addresses support */
if (bt_dev.vs_commands[1] & BIT(0)) {
@ -4082,7 +4136,7 @@ static int set_static_addr(void)
bt_dev.id_addr.type = BT_ADDR_LE_RANDOM;
bt_addr_copy(&bt_dev.id_addr.a, &rp->a[0].bdaddr);
net_buf_unref(rsp);
goto set_addr;
return bt_set_static_addr();
}
BT_WARN("No static addresses stored in controller");
@ -4093,40 +4147,21 @@ static int set_static_addr(void)
generate:
#endif
BT_DBG("Generating new static random address");
err = bt_addr_le_create_static(&bt_dev.id_addr);
if (err) {
return err;
}
if (bt_storage) {
ssize_t ret;
ret = bt_storage->write(NULL, BT_STORAGE_ID_ADDR,
&bt_dev.id_addr,
sizeof(bt_dev.id_addr));
if (ret != sizeof(bt_dev.id_addr)) {
BT_ERR("Unable to store static address");
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
BT_DBG("Expecing identity addr to be handled by settings");
return 0;
} else {
BT_WARN("Using temporary static random address");
}
err = bt_addr_le_create_static(&bt_dev.id_addr);
if (err) {
return err;
}
set_addr:
if (bt_dev.id_addr.type != BT_ADDR_LE_RANDOM ||
(bt_dev.id_addr.a.val[5] & 0xc0) != 0xc0) {
BT_ERR("Only static random address supported as identity");
return -EINVAL;
}
BT_WARN("Using temporary static random address %s",
bt_addr_str(&bt_dev.id_addr.a));
err = set_random_address(&bt_dev.id_addr.a);
if (err) {
return err;
return bt_set_static_addr();
}
atomic_set_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM);
return 0;
}
#if defined(CONFIG_BT_DEBUG)
@ -4314,7 +4349,7 @@ static int hci_init(void)
if (!bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_ANY) ||
!bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_NONE)) {
BT_DBG("No public address. Trying to set static random.");
err = set_static_addr();
err = setup_id_addr();
if (err) {
BT_ERR("Unable to set identity address");
return err;
@ -4429,30 +4464,16 @@ int bt_hci_driver_register(const struct bt_hci_driver *drv)
#if defined(CONFIG_BT_PRIVACY)
static int irk_init(void)
{
ssize_t err;
if (bt_storage) {
err = bt_storage->read(NULL, BT_STORAGE_LOCAL_IRK, &bt_dev.irk,
sizeof(bt_dev.irk));
if (err == sizeof(bt_dev.irk)) {
return 0;
}
}
BT_DBG("Generating new IRK");
err = bt_rand(bt_dev.irk, sizeof(bt_dev.irk));
if (err) {
return err;
}
if (bt_storage) {
err = bt_storage->write(NULL, BT_STORAGE_LOCAL_IRK, bt_dev.irk,
sizeof(bt_dev.irk));
if (err != sizeof(bt_dev.irk)) {
BT_ERR("Unable to store IRK");
}
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
BT_DBG("Expecting settings to handle local IRK");
} else {
int err;
err = bt_rand(bt_dev.irk, sizeof(bt_dev.irk));
if (err) {
return err;
}
BT_WARN("Using temporary IRK");
}
@ -5133,68 +5154,6 @@ int bt_br_set_discoverable(bool enable)
}
#endif /* CONFIG_BT_BREDR */
void bt_storage_register(const struct bt_storage *storage)
{
bt_storage = storage;
}
static int bt_storage_clear_all(void)
{
if (IS_ENABLED(CONFIG_BT_CONN)) {
bt_conn_disconnect_all();
}
if (IS_ENABLED(CONFIG_BT_SMP)) {
bt_keys_clear_all();
}
if (IS_ENABLED(CONFIG_BT_BREDR)) {
bt_keys_link_key_clear_addr(NULL);
}
if (bt_storage) {
return bt_storage->clear(NULL);
}
return 0;
}
int bt_storage_clear(const bt_addr_le_t *addr)
{
if (!addr) {
return bt_storage_clear_all();
}
if (IS_ENABLED(CONFIG_BT_CONN)) {
struct bt_conn *conn = bt_conn_lookup_addr_le(addr);
if (conn) {
bt_conn_disconnect(conn,
BT_HCI_ERR_REMOTE_USER_TERM_CONN);
bt_conn_unref(conn);
}
}
if (IS_ENABLED(CONFIG_BT_BREDR)) {
/* LE Public may indicate BR/EDR as well */
if (addr->type == BT_ADDR_LE_PUBLIC) {
bt_keys_link_key_clear_addr(&addr->a);
}
}
if (IS_ENABLED(CONFIG_BT_SMP)) {
struct bt_keys *keys = bt_keys_find_addr(addr);
if (keys) {
bt_keys_clear(keys);
}
}
if (bt_storage) {
return bt_storage->clear(addr);
}
return 0;
}
u16_t bt_hci_get_cmd_opcode(struct net_buf *buf)
{
return cmd(buf)->opcode;

View file

@ -166,7 +166,6 @@ struct bt_dev {
};
extern struct bt_dev bt_dev;
extern const struct bt_storage *bt_storage;
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
extern const struct bt_conn_auth_cb *bt_auth;
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
@ -191,4 +190,6 @@ struct bt_keys;
int bt_id_add(struct bt_keys *keys);
int bt_id_del(struct bt_keys *keys);
int bt_set_static_addr(void);
void bt_dev_show_info(void);

View file

@ -59,7 +59,7 @@ static void generate_static_addr(void)
return;
}
atomic_set_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM);
bt_set_static_addr();
BT_DBG("New ID Addr: %s", bt_addr_le_str(&bt_dev.id_addr));

View file

@ -1,229 +0,0 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <string.h>
#include <misc/printk.h>
#include <zephyr.h>
#include <init.h>
#include <fs.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/storage.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
#include "common/log.h"
#define STORAGE_ROOT "/bt"
/* Required file name length for full storage support. If the maximum
* file name length supported by the chosen file system is less than
* this value, then only local keys are supported (/bt/abcd).
*/
#define STORAGE_FILE_NAME_LEN 13
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
/* /bt/aabbccddeeff0/abcd */
#define STORAGE_PATH_MAX 23
#else
/* /bt/abcd */
#define STORAGE_PATH_MAX 9
#endif
enum storage_access {
STORAGE_READ,
STORAGE_WRITE
};
static int storage_open(const bt_addr_le_t *addr, u16_t key,
enum storage_access access, struct fs_file_t *file)
{
char path[STORAGE_PATH_MAX];
if (addr) {
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
int len;
len = snprintk(path, sizeof(path),
STORAGE_ROOT "/%02X%02X%02X%02X%02X%02X%u",
addr->a.val[5], addr->a.val[4], addr->a.val[3],
addr->a.val[2], addr->a.val[1], addr->a.val[0],
addr->type);
/* Create the subdirectory if necessary */
if (access == STORAGE_WRITE) {
struct fs_dirent entry;
int err;
err = fs_stat(path, &entry);
if (err) {
err = fs_mkdir(path);
if (err) {
return err;
}
}
}
snprintk(path + len, sizeof(path) - len, "/%04x", key);
#else
return -ENAMETOOLONG;
#endif
} else {
snprintk(path, sizeof(path), STORAGE_ROOT "/%04x", key);
}
return fs_open(file, path);
}
static ssize_t storage_read(const bt_addr_le_t *addr, u16_t key, void *data,
size_t length)
{
struct fs_file_t file;
ssize_t ret;
ret = storage_open(addr, key, STORAGE_READ, &file);
if (ret) {
return ret;
}
ret = fs_read(&file, data, length);
fs_close(&file);
return ret;
}
static ssize_t storage_write(const bt_addr_le_t *addr, u16_t key,
const void *data, size_t length)
{
struct fs_file_t file;
ssize_t ret;
ret = storage_open(addr, key, STORAGE_WRITE, &file);
if (ret) {
return ret;
}
ret = fs_write(&file, data, length);
fs_close(&file);
return ret;
}
static int unlink_recursive(char path[STORAGE_PATH_MAX])
{
size_t path_len;
struct fs_dir_t dir;
int err;
err = fs_opendir(&dir, path);
if (err) {
return err;
}
/* We calculate this up-front so we can keep reusing the same
* buffer for the path when recursing.
*/
path_len = strlen(path);
while (1) {
struct fs_dirent entry;
err = fs_readdir(&dir, &entry);
if (err) {
break;
}
if (entry.name[0] == '\0') {
break;
}
snprintk(path + path_len, STORAGE_PATH_MAX - path_len, "/%s",
entry.name);
if (entry.type == FS_DIR_ENTRY_DIR) {
err = unlink_recursive(path);
} else {
err = fs_unlink(path);
}
if (err) {
break;
}
}
fs_closedir(&dir);
/* Return to the original value */
path[path_len] = '\0';
fs_unlink(path);
return err;
}
static int storage_clear(const bt_addr_le_t *addr)
{
char path[STORAGE_PATH_MAX];
int err;
if (addr) {
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
snprintk(path, STORAGE_PATH_MAX,
STORAGE_ROOT "/%02X%02X%02X%02X%02X%02X%u",
addr->a.val[5], addr->a.val[4], addr->a.val[3],
addr->a.val[2], addr->a.val[1], addr->a.val[0],
addr->type);
return unlink_recursive(path);
#else
return -ENAMETOOLONG;
#endif
}
/* unlink_recursive() uses the given path as a buffer for
* constructing sub-paths, so we can't give it a string literal
* such as STORAGE_ROOT directly.
*/
strcpy(path, STORAGE_ROOT);
err = unlink_recursive(path);
if (err) {
return err;
}
return fs_mkdir(STORAGE_ROOT);
}
static int storage_init(struct device *unused)
{
static const struct bt_storage storage = {
.read = storage_read,
.write = storage_write,
.clear = storage_clear
};
struct fs_dirent entry;
int err;
err = fs_stat(STORAGE_ROOT, &entry);
if (err) {
BT_WARN("%s doesn't seem to exist (err %d). Creating it.",
STORAGE_ROOT, err);
err = fs_mkdir(STORAGE_ROOT);
if (err) {
BT_ERR("Unable to create %s (err %d)",
STORAGE_ROOT, err);
return err;
}
}
bt_storage_register(&storage);
return 0;
}
SYS_INIT(storage_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);

View file

@ -23,7 +23,6 @@
#include <bluetooth/conn.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/storage.h>
#include <bluetooth/sdp.h>
#include <shell/shell.h>
@ -39,7 +38,6 @@
#define DATA_BREDR_MTU 48
#define BT_SHELL_MODULE "bt"
static bt_addr_le_t id_addr;
#if defined(CONFIG_BT_CONN)
struct bt_conn *default_conn;
@ -506,42 +504,6 @@ static int str2bt_addr_le(const char *str, const char *type, bt_addr_le_t *addr)
return 0;
}
static ssize_t storage_read(const bt_addr_le_t *addr, u16_t key, void *data,
size_t length)
{
if (addr) {
return -ENOENT;
}
if (key == BT_STORAGE_ID_ADDR && length == sizeof(id_addr) &&
bt_addr_le_cmp(&id_addr, BT_ADDR_LE_ANY)) {
bt_addr_le_copy(data, &id_addr);
return sizeof(id_addr);
}
return -EIO;
}
static ssize_t storage_write(const bt_addr_le_t *addr, u16_t key,
const void *data, size_t length)
{
if (addr) {
return -ENOENT;
}
if (key == BT_STORAGE_ID_ADDR && length == sizeof(id_addr)) {
bt_addr_le_copy(&id_addr, data);
return sizeof(id_addr);
}
return -EIO;
}
static int storage_clear(const bt_addr_le_t *addr)
{
return -ENOSYS;
}
static void bt_ready(int err)
{
if (err) {
@ -560,29 +522,8 @@ static void bt_ready(int err)
static int cmd_init(int argc, char *argv[])
{
static const struct bt_storage storage = {
.read = storage_read,
.write = storage_write,
.clear = storage_clear,
};
int err;
if (argc > 1) {
if (argc < 3) {
printk("Invalid address\n");
return -EINVAL;
}
err = str2bt_addr_le(argv[1], argv[2], &id_addr);
if (err) {
printk("Invalid address (err %d)\n", err);
bt_addr_le_cmp(&id_addr, BT_ADDR_LE_ANY);
return -EINVAL;
}
bt_storage_register(&storage);
}
err = bt_enable(bt_ready);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
@ -944,11 +885,11 @@ static int cmd_clear(int argc, char *argv[])
}
if (strcmp(argv[1], "all") == 0) {
err = bt_storage_clear(NULL);
err = bt_unpair(NULL);
if (err) {
printk("Failed to clear storage (err %d)\n", err);
printk("Failed to clear pairings (err %d)\n", err);
} else {
printk("Storage successfully cleared\n");
printk("Pairings successfully cleared\n");
}
return 0;
@ -971,11 +912,11 @@ static int cmd_clear(int argc, char *argv[])
return 0;
}
err = bt_storage_clear(&addr);
err = bt_unpair(&addr);
if (err) {
printk("Failed to clear storage (err %d)\n", err);
printk("Failed to clear pairing (err %d)\n", err);
} else {
printk("Storage successfully cleared\n");
printk("Pairing successfully cleared\n");
}
return 0;

View file

@ -13,7 +13,6 @@
#include <toolchain.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/storage.h>
#include <misc/byteorder.h>
#include <net/buf.h>
@ -608,7 +607,7 @@ static void unpair(const u8_t *data, u16_t len)
goto rsp;
}
keys:
err = bt_storage_clear(&addr);
err = bt_unpair(&addr);
status = err < 0 ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS;
rsp: