blob: 83b1c4f15f74ffc1d9b62fc9ba90b5df69294672 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#ifndef H_BLE_STORE_
#define H_BLE_STORE_
/**
* @brief Bluetooth Store API
* @defgroup bt_store Bluetooth Store
* @ingroup bt_host
* @{
*/
#include <inttypes.h>
#include "nimble/ble.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup bt_store_obj_types Bluetooth Store Object Types
* @ingroup bt_host
* @{
*/
/** Object type: Our security material. */
#define BLE_STORE_OBJ_TYPE_OUR_SEC 1
/** Object type: Peer security material. */
#define BLE_STORE_OBJ_TYPE_PEER_SEC 2
/** Object type: Client Characteristic Configuration Descriptor. */
#define BLE_STORE_OBJ_TYPE_CCCD 3
/** @} */
/**
* @defgroup bt_store_event_types Bluetooth Store Event Types
* @ingroup bt_host
* @{
*/
/** Failed to persist record; insufficient storage capacity. */
#define BLE_STORE_EVENT_OVERFLOW 1
/** About to execute a procedure that may fail due to overflow. */
#define BLE_STORE_EVENT_FULL 2
/** @} */
/**
* Used as a key for lookups of security material. This struct corresponds to
* the following store object types:
* o BLE_STORE_OBJ_TYPE_OUR_SEC
* o BLE_STORE_OBJ_TYPE_PEER_SEC
*/
struct ble_store_key_sec {
/**
* Key by peer identity address;
* peer_addr=BLE_ADDR_NONE means don't key off peer.
*/
ble_addr_t peer_addr;
/** Number of results to skip; 0 means retrieve the first match. */
uint8_t idx;
};
/**
* Represents stored security material. This struct corresponds to the
* following store object types:
* o BLE_STORE_OBJ_TYPE_OUR_SEC
* o BLE_STORE_OBJ_TYPE_PEER_SEC
*/
struct ble_store_value_sec {
/** Peer address for which the security material is stored. */
ble_addr_t peer_addr;
/** Encryption key size. */
uint8_t key_size;
/** Encrypted Diversifier used for encryption key generation. */
uint16_t ediv;
/** Random number used for encryption key generation. */
uint64_t rand_num;
/** Long Term Key. */
uint8_t ltk[16];
/** Flag indicating whether Long Term Key is present. */
uint8_t ltk_present:1;
/** Identity Resolving Key. */
uint8_t irk[16];
/** Flag indicating whether Identity Resolving Key is present. */
uint8_t irk_present:1;
/** Connection Signature Resolving Key. */
uint8_t csrk[16];
/** Flag indicating if Connection Signature Resolving Key is present. */
uint8_t csrk_present:1;
/** Flag indicating whether the connection is authenticated. */
unsigned authenticated:1;
/** Flag indicating Secure Connections support. */
uint8_t sc:1;
};
/**
* Used as a key for lookups of stored client characteristic configuration
* descriptors (CCCDs). This struct corresponds to the BLE_STORE_OBJ_TYPE_CCCD
* store object type.
*/
struct ble_store_key_cccd {
/**
* Key by peer identity address;
* peer_addr=BLE_ADDR_NONE means don't key off peer.
*/
ble_addr_t peer_addr;
/**
* Key by characteristic value handle;
* chr_val_handle=0 means don't key off characteristic handle.
*/
uint16_t chr_val_handle;
/** Number of results to skip; 0 means retrieve the first match. */
uint8_t idx;
};
/**
* Represents a stored client characteristic configuration descriptor (CCCD).
* This struct corresponds to the BLE_STORE_OBJ_TYPE_CCCD store object type.
*/
struct ble_store_value_cccd {
/** The peer address associated with the stored CCCD. */
ble_addr_t peer_addr;
/** The handle of the characteristic value. */
uint16_t chr_val_handle;
/** Flags associated with the CCCD. */
uint16_t flags;
/** Flag indicating whether the value has changed. */
unsigned value_changed:1;
};
/**
* Used as a key for store lookups. This union must be accompanied by an
* object type code to indicate which field is valid.
*/
union ble_store_key {
/** Key for security material store lookups. */
struct ble_store_key_sec sec;
/** Key for Client Characteristic Configuration Descriptor store lookups. */
struct ble_store_key_cccd cccd;
};
/**
* Represents stored data. This union must be accompanied by an object type
* code to indicate which field is valid.
*/
union ble_store_value {
/** Stored security material. */
struct ble_store_value_sec sec;
/** Stored Client Characteristic Configuration Descriptor. */
struct ble_store_value_cccd cccd;
};
/** Represents an event associated with the BLE Store. */
struct ble_store_status_event {
/**
* The type of event being reported; one of the BLE_STORE_EVENT_TYPE_[...]
* codes.
*/
int event_code;
/**
* Additional data related to the event; the valid field is inferred from
* the obj_type,event_code pair.
*/
union {
/**
* Represents a write that failed due to storage exhaustion. Valid for
* the following event types:
* o BLE_STORE_EVENT_OVERFLOW
*/
struct {
/** The type of object that failed to be written. */
int obj_type;
/** The object that failed to be written. */
const union ble_store_value *value;
} overflow;
/**
* Represents the possibility that a scheduled write will fail due to
* storage exhaustion. Valid for the following event types:
* o BLE_STORE_EVENT_FULL
*/
struct {
/** The type of object that may fail to be written. */
int obj_type;
/** The handle of the connection which prompted the write. */
uint16_t conn_handle;
} full;
};
};
/** Generate LTK, EDIT and Rand. */
#define BLE_STORE_GEN_KEY_LTK 0x01
/** Generate IRK. */
#define BLE_STORE_GEN_KEY_IRK 0x02
/** Generate CSRK. */
#define BLE_STORE_GEN_KEY_CSRK 0x03
/** Represents a storage for generated key. */
struct ble_store_gen_key {
union {
/** Long Term Key (LTK) for peripheral role. */
uint8_t ltk_periph[16];
/** Identity Resolving Key (IRK). */
uint8_t irk[16];
/** Connection Signature Resolving Key (CSRK). */
uint8_t csrk[16];
};
/** Encrypted Diversifier (EDIV). */
uint16_t ediv;
/** Random Number for key generation. */
uint64_t rand;
};
/**
* Generates key required by security module.
* This can be used to use custom routines to generate keys instead of simply
* randomizing them.
*
* \p conn_handle is set to \p BLE_HS_CONN_HANDLE_NONE if key is not requested
* for a specific connection (e.g. an IRK).
*
* @param key Key that shall be generated.
* @param gen_key Storage for generated key.
* @param conn_handle Connection handle for which keys are generated.
*
* @return 0 if keys were generated successfully
* Other nonzero on error.
*/
typedef int ble_store_gen_key_fn(uint8_t key,
struct ble_store_gen_key *gen_key,
uint16_t conn_handle);
/**
* Searches the store for an object matching the specified criteria. If a
* match is found, it is read from the store and the dst parameter is populated
* with the retrieved object.
*
* @param obj_type The type of object to search for; one of the
* BLE_STORE_OBJ_TYPE_[...] codes.
* @param key Specifies properties of the object to search
* for. An object is retrieved if it matches
* these criteria.
* @param dst On success, this is populated with the
* retrieved object.
*
* @return 0 if an object was successfully retreived;
* BLE_HS_ENOENT if no matching object was found;
* Other nonzero on error.
*/
typedef int ble_store_read_fn(int obj_type, const union ble_store_key *key,
union ble_store_value *dst);
/**
* Writes the specified object to the store. If an object with the same
* identity is already in the store, it is replaced. If the store lacks
* sufficient capacity to write the object, this function may remove previously
* stored values to make room.
*
* @param obj_type The type of object being written; one of the
* BLE_STORE_OBJ_TYPE_[...] codes.
* @param val The object to persist.
*
* @return 0 if the object was successfully written;
* Other nonzero on error.
*/
typedef int ble_store_write_fn(int obj_type, const union ble_store_value *val);
/**
* Searches the store for the first object matching the specified criteria. If
* a match is found, it is deleted from the store.
*
* @param obj_type The type of object to delete; one of the
* BLE_STORE_OBJ_TYPE_[...] codes.
* @param key Specifies properties of the object to search
* for. An object is deleted if it matches
* these criteria.
* @return 0 if an object was successfully retrieved;
* BLE_HS_ENOENT if no matching object was found;
* Other nonzero on error.
*/
typedef int ble_store_delete_fn(int obj_type, const union ble_store_key *key);
/**
* Indicates an inability to perform a store operation. This callback should
* do one of two things:
* o Address the problem and return 0, indicating that the store operation
* should proceed.
* o Return nonzero to indicate that the store operation should be aborted.
*
* @param event Describes the store event being reported.
* @param arg Optional user argument.
*
* @return 0 if the store operation should proceed;
* nonzero if the store operation should be
* aborted.
*/
typedef int ble_store_status_fn(struct ble_store_status_event *event,
void *arg);
/**
* Reads data from a storage.
*
* @param obj_type The type of the object to read.
* @param key Pointer to the key used for the lookup.
* @param val Pointer to store the retrieved data.
*
* @return 0 if the read operation is successful;
* Non-zero on error.
*/
int ble_store_read(int obj_type, const union ble_store_key *key,
union ble_store_value *val);
/**
* Writes data to a storage.
*
* @param obj_type The type of the object to write.
* @param val Pointer to the data to be written.
*
* @return 0 if the write operation is successful;
* Non-zero on error.
*/
int ble_store_write(int obj_type, const union ble_store_value *val);
/**
* Deletes data from a storage.
*
* @param obj_type The type of the object to delete.
* @param key Pointer to the key used for the lookup.
*
* @return 0 if the deletion operation is successful;
* Non-zero on error.
*/
int ble_store_delete(int obj_type, const union ble_store_key *key);
/**
* @brief Handles a storage overflow event.
*
* This function is called when a storage overflow event occurs. It constructs
* an event structure and passes it to the general storage status handler using
* the `ble_store_status` function.
*
* @param obj_type The type of the object for which the overflow
* occurred.
* @param value Pointer to the value associated with the
* overflow.
*
* @return 0 if the event is successfully handled;
* Non-zero on error.
*/
int ble_store_overflow_event(int obj_type, const union ble_store_value *value);
/**
* @brief Handles a storage full event.
*
* This function is called when a storage full event occurs, typically during
* a write operation. It constructs an event structure and passes it to the
* general storage status handler using the `ble_store_status` function.
*
* @param obj_type The type of the object that may fail to be
* written.
* @param conn_handle The connection handle associated with the write
* operation.
*
* @return 0 if the event is successfully handled;
* Non-zero on error.
*/
int ble_store_full_event(int obj_type, uint16_t conn_handle);
/**
* @brief Reads our security material from a storage.
*
* This function reads our security material from a storage, using the provided
* key and populates the `ble_store_value_sec` structure with the retrieved data.
*
* @param key_sec The key identifying the security material to
* read.
* @param value_sec A pointer to a `ble_store_value_sec` structure
* where the retrieved security material will
* be stored.
*
* @return 0 if the security material was successfully read
* from a storage;
* Non-zero on error.
*/
int ble_store_read_our_sec(const struct ble_store_key_sec *key_sec,
struct ble_store_value_sec *value_sec);
/**
* @brief Writes our security material to a storage.
*
* This function writes our security material to a storage, using the provided
* `ble_store_value_sec` structure.
*
* @param value_sec A pointer to a `ble_store_value_sec` structure
* containing the security material to be
* stored.
*
* @return 0 if the security material was successfully
* written to a storage;
* Non-zero on error.
*/
int ble_store_write_our_sec(const struct ble_store_value_sec *value_sec);
/**
* @brief Deletes our security material from a storage.
*
* This function deletes our security material from a storage, identified by the
* provided `ble_store_key_sec`.
*
* @param key_sec A pointer to a `ble_store_key_sec` structure
* that specifies the security material to be
* deleted.
*
* @return 0 if the security material was successfully
* deleted from a storage;
* Non-zero on error.
*/
int ble_store_delete_our_sec(const struct ble_store_key_sec *key_sec);
/**
* @brief Reads peer security material from a storage.
*
* This function reads peer security material from a storage, identified by the
* provided `ble_store_key_sec`. The retrieved security material is stored in
* the `ble_store_value_sec` structure.
*
* @param key_sec A pointer to a `ble_store_key_sec` structure
* that specifies the peer's security material
* to be retrieved.
* @param value_sec A pointer to a `ble_store_value_sec` structure
* where the retrieved security material will
* be stored.
*
* @return 0 if the security material was successfully
* retrieved;
* Non-zero on error.
*/
int ble_store_read_peer_sec(const struct ble_store_key_sec *key_sec,
struct ble_store_value_sec *value_sec);
/**
* @brief Writes peer security material to a storage.
*
* This function writes the provided peer security material, specified by a
* `ble_store_value_sec` structure, to a storage. Additionally, if the provided
* peer IRK is present and the peer address is not `BLE_ADDR_ANY`, it is also
* written to the controller's key cache.
*
* @param value_sec A pointer to a `ble_store_value_sec` structure
* containing the peer's security material
* to be written.
*
* @return 0 if the peer's security material was
* successfully written to a storage and
* the peer IRK was added to the controller key
* cache if present;
* Non-zero on error.
*/
int ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec);
/**
* @brief Deletes peer security material from a storage.
*
* This function deletes the peer security material associated with the provided
* key from a storage.
*
* @param key_sec A pointer to a `ble_store_key_sec` structure
* identifying the security material to be
* deleted.
*
* @return 0 if the peer's security material was
* successfully deleted from a storage;
* Non-zero on error.
*/
int ble_store_delete_peer_sec(const struct ble_store_key_sec *key_sec);
/**
* @brief Reads a Client Characteristic Configuration Descriptor (CCCD) from
* a storage.
*
* This function reads a CCCD from a storage based on the provided key and
* stores the retrieved value in the specified output structure.
*
* @param key A pointer to a `ble_store_key_cccd` structure
* representing the key to identify the CCCD to
* be read.
* @param out_value A pointer to a `ble_store_value_cccd` structure
* to store the CCCD value read from a storage.
*
* @return 0 if the CCCD was successfully read and stored
* in the `out_value` structure;
* Non-zero on error.
*/
int ble_store_read_cccd(const struct ble_store_key_cccd *key,
struct ble_store_value_cccd *out_value);
/**
* @brief Writes a Client Characteristic Configuration Descriptor (CCCD) to
* a storage.
*
* This function writes a CCCD to a storage based on the provided value.
*
* @param value A pointer to a `ble_store_value_cccd` structure
* representing the CCCD value to be written to
* a storage.
*
* @return 0 if the CCCD was successfully written to
* a storage;
* Non-zero on error.
*/
int ble_store_write_cccd(const struct ble_store_value_cccd *value);
/**
* @brief Deletes a Client Characteristic Configuration Descriptor (CCCD) from
* a storage.
*
* This function deletes a CCCD from a storage based on the provided key.
*
* @param key A pointer to a `ble_store_key_cccd` structure
* identifying the CCCD to be deleted from
* a storage.
*
* @return 0 if the CCCD was successfully deleted from
* a storage;
* Non-zero on error.
*/
int ble_store_delete_cccd(const struct ble_store_key_cccd *key);
/**
* @brief Generates a storage key for a security material entry from its value.
*
* This function generates a storage key for a security material entry based on
* the provided security material value.
*
* @param out_key A pointer to a `ble_store_key_sec` structure
* where the generated key will be stored.
* @param value A pointer to a `ble_store_value_sec` structure
* containing the security material value from
* which the key will be generated.
*/
void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key,
const struct ble_store_value_sec *value);
/**
* @brief Generates a storage key for a CCCD entry from its value.
*
* This function generates a storage key for a Client Characteristic
* Configuration Descriptor (CCCD) entry based on the provided CCCD value.
*
* @param out_key A pointer to a `ble_store_key_cccd` structure
* where the generated key will be stored.
* @param value A pointer to a `ble_store_value_cccd` structure
* containing the CCCD value from which the key
* will be generated.
*/
void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key,
const struct ble_store_value_cccd *value);
/**
* @brief Generates a storage key from a value based on the object type.
*
* This function generates a storage key from a value based on the provided
* object type.
*
* @param obj_type The type of object for which the key is
* generated.
* @param out_key A pointer to a `ble_store_key` union where
* the generated key will be stored.
* @param value A pointer to a `ble_store_value` union
* containing the value from which the key will
* be generated.
*/
void ble_store_key_from_value(int obj_type,
union ble_store_key *out_key,
const union ble_store_value *value);
/**
* @brief Function signature for the storage iterator callback.
*
* This function signature represents a callback function used for iterating
* over stored objects in a store.
*
* @param obj_type The type of object being iterated.
* @param val A pointer to the stored value of the object.
* @param cookie A user-defined pointer for additional data.
*
* @return 0 to continue iterating;
* Non-zero value to stop the iteration.
*/
typedef int ble_store_iterator_fn(int obj_type,
union ble_store_value *val,
void *cookie);
/**
* @brief Iterates over stored objects of a specific type in a store.
*
* This function allows you to iterate over stored objects of a specific type in
* the store and invoke a user-defined callback function for each object.
*
* @param obj_type The type of objects to iterate over.
* @param callback A pointer to the user-defined callback function
* that will be invoked for each stored object.
* @param cookie A user-defined pointer for additional data to
* pass to the callback function.
*
* @return 0 on success;
* Non-zero on error.
*/
int ble_store_iterate(int obj_type,
ble_store_iterator_fn *callback,
void *cookie);
/**
* @brief Clears all stored objects from a store.
*
* This function removes all stored objects from a store, effectively clearing
* the storage.
*
* @return 0 on success;
* Non-zero on error.
*/
int ble_store_clear(void);
/**
* @defgroup ble_store_util Bluetooth Store Utility Functions
* @{
*/
/**
* Retrieves the set of peer addresses for which a bond has been established.
*
* @param out_peer_id_addrs The set of bonded peer addresses.
* @param out_num_peers The number of bonds that have been established.
* @param max_peers The capacity of the destination buffer.
*
* @return 0 on success;
* BLE_HS_ENOMEM if the destination buffer is too
* small;
* Other non-zero on error.
*/
int ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs,
int *out_num_peers,
int max_peers);
/**
* Deletes all entries from a store that match the specified key.
*
* @param type The type of store entry to delete.
* @param key Entries matching this key get deleted.
*
* @return 0 on success;
* Non-zero on error.
*/
int ble_store_util_delete_all(int type, const union ble_store_key *key);
/**
* Deletes all entries from a store that are attached to the specified peer
* address. This function deletes security entries and CCCD records.
*
* @param peer_id_addr Entries with this peer address get deleted.
*
* @return 0 on success;
* Non-zero on error.
*/
int ble_store_util_delete_peer(const ble_addr_t *peer_id_addr);
/**
* @brief Deletes the oldest peer from a store.
*
* This function deletes the oldest bonded peer from the storage. If there are
* no bonded peers in the storage, the function returns success.
*
* @return 0 on success;
* Non-zero on error.
*/
int ble_store_util_delete_oldest_peer(void);
/**
* @brief Counts the number of stored objects of a given type.
*
* This function counts the number of stored objects of a specific type in
* a store and returns the count in the `out_count` parameter.
*
* @param type The type of the objects to count.
* @param out_count The count of stored objects.
*
* @return 0 on success;
* Non-zero on error.
*/
int ble_store_util_count(int type, int *out_count);
/**
* @brief Round-robin status callback for handling store status events.
*
* This function handles store status events, particularly in cases where there
* is insufficient storage capacity for new records.
* It attempts to resolve overflow issues by deleting the oldest bond and
* proceeds with the persist operation.
*
* @note This behavior may not be suitable for production use as it may lead to
* removal of important bonds by less relevant peers. It is more useful for
* demonstration purposes and sample applications.
*
* @param event A pointer to the store status event.
* @param arg A pointer to additional user-defined arguments.
*
* @return 0 on success;
* Non-zero on error.
*/
int ble_store_util_status_rr(struct ble_store_status_event *event, void *arg);
/** @} */
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif