diff --git a/nimble/host/include/host/ble_store.h b/nimble/host/include/host/ble_store.h index 24b208a09d..83b1c4f15f 100644 --- a/nimble/host/include/host/ble_store.h +++ b/nimble/host/include/host/ble_store.h @@ -20,6 +20,13 @@ #ifndef H_BLE_STORE_ #define H_BLE_STORE_ +/** + * @brief Bluetooth Store API + * @defgroup bt_store Bluetooth Store + * @ingroup bt_host + * @{ + */ + #include #include "nimble/ble.h" @@ -27,16 +34,35 @@ 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: @@ -61,21 +87,33 @@ struct ble_store_key_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; }; @@ -106,9 +144,13 @@ struct ble_store_key_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; }; @@ -117,7 +159,9 @@ struct ble_store_value_cccd { * 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; }; @@ -126,10 +170,13 @@ union ble_store_key { * 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_[...] @@ -170,20 +217,26 @@ struct ble_store_status_event { }; }; -/* Generate LTK, EDIT and Rand */ +/** Generate LTK, EDIT and Rand. */ #define BLE_STORE_GEN_KEY_LTK 0x01 -/* Generate IRK */ +/** Generate IRK. */ #define BLE_STORE_GEN_KEY_IRK 0x02 -/* Generate CSRK */ +/** 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; }; @@ -273,59 +326,432 @@ typedef int ble_store_delete_fn(int obj_type, const union ble_store_key *key); 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); -/*** Utility functions. */ +/** + * @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 diff --git a/nimble/host/src/ble_store_util.c b/nimble/host/src/ble_store_util.c index 19b049a4c4..6dcbca25a1 100644 --- a/nimble/host/src/ble_store_util.c +++ b/nimble/host/src/ble_store_util.c @@ -59,20 +59,6 @@ ble_store_util_iter_unique_peer(int obj_type, return 0; } -/** - * Retrieves the set of peer addresses for which a bond has been established. - * - * @param out_peer_id_addrs On success, the set of bonded peer addresses - * gets written here. - * @param out_num_peers On success, the number of bonds gets written - * here. - * @param max_peers The capacity of the destination buffer. - * - * @return 0 on success; - * BLE_HS_ENOMEM if the destination buffer is too - * small; - * Other nonzero on error. - */ int ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers, int max_peers) @@ -96,15 +82,6 @@ ble_store_util_bonded_peers(ble_addr_t *out_peer_id_addrs, int *out_num_peers, return 0; } -/** - * Deletes all entries from the 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; - * Other nonzero on error. - */ int ble_store_util_delete_peer(const ble_addr_t *peer_id_addr) { @@ -135,15 +112,6 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr) return 0; } -/** - * Deletes all entries from the 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; - * Other nonzero on error. - */ int ble_store_util_delete_all(int type, const union ble_store_key *key) { @@ -216,15 +184,6 @@ ble_store_util_delete_oldest_peer(void) return 0; } -/** - * Round-robin status callback. If a there is insufficient storage capacity - * for a new record, delete the oldest bond and proceed with the persist - * operation. - * - * Note: This is not the best behavior for an actual product because - * uninteresting peers could cause important bonds to be deleted. This is - * useful for demonstrations and sample apps. - */ int ble_store_util_status_rr(struct ble_store_status_event *event, void *arg) {