1 /* 2 * Copyright (c) 2019 Tobias Svehagen 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 #ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ 7 #define ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ 8 9 #include <stdbool.h> 10 #include <stdint.h> 11 12 #include <zephyr/sys/atomic.h> 13 #include <zephyr/bluetooth/mesh.h> 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 #if defined(CONFIG_BT_MESH_CDB) 20 #define NODE_COUNT CONFIG_BT_MESH_CDB_NODE_COUNT 21 #define SUBNET_COUNT CONFIG_BT_MESH_CDB_SUBNET_COUNT 22 #define APP_KEY_COUNT CONFIG_BT_MESH_CDB_APP_KEY_COUNT 23 #else 24 #define NODE_COUNT 0 25 #define SUBNET_COUNT 0 26 #define APP_KEY_COUNT 0 27 #endif 28 29 enum { 30 BT_MESH_CDB_NODE_CONFIGURED, 31 32 BT_MESH_CDB_NODE_FLAG_COUNT 33 }; 34 35 struct bt_mesh_cdb_node { 36 uint8_t uuid[16]; 37 uint16_t addr; 38 uint16_t net_idx; 39 uint8_t num_elem; 40 struct bt_mesh_key dev_key; 41 42 ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT); 43 }; 44 45 struct bt_mesh_cdb_subnet { 46 uint16_t net_idx; 47 48 uint8_t kr_phase; 49 50 struct { 51 struct bt_mesh_key net_key; 52 } keys[2]; 53 }; 54 55 struct bt_mesh_cdb_app_key { 56 uint16_t net_idx; 57 uint16_t app_idx; 58 59 struct { 60 struct bt_mesh_key app_key; 61 } keys[2]; 62 }; 63 64 enum { 65 BT_MESH_CDB_VALID, 66 BT_MESH_CDB_SUBNET_PENDING, 67 BT_MESH_CDB_KEYS_PENDING, 68 BT_MESH_CDB_NODES_PENDING, 69 BT_MESH_CDB_IVU_IN_PROGRESS, 70 71 BT_MESH_CDB_FLAG_COUNT, 72 }; 73 74 struct bt_mesh_cdb { 75 uint32_t iv_index; 76 uint16_t lowest_avail_addr; 77 78 ATOMIC_DEFINE(flags, BT_MESH_CDB_FLAG_COUNT); 79 80 struct bt_mesh_cdb_node nodes[NODE_COUNT]; 81 struct bt_mesh_cdb_subnet subnets[SUBNET_COUNT]; 82 struct bt_mesh_cdb_app_key app_keys[APP_KEY_COUNT]; 83 }; 84 85 extern struct bt_mesh_cdb bt_mesh_cdb; 86 87 /** @brief Create the Mesh Configuration Database. 88 * 89 * Create and initialize the Mesh Configuration Database. A primary subnet, 90 * ie one with NetIdx 0, will be added and the provided key will be used as 91 * NetKey for that subnet. 92 * 93 * @param key The NetKey to be used for the primary subnet. 94 * 95 * @return 0 on success or negative error code on failure. 96 */ 97 int bt_mesh_cdb_create(const uint8_t key[16]); 98 99 /** @brief Clear the Mesh Configuration Database. 100 * 101 * Remove all nodes, subnets and app-keys stored in the database and mark 102 * the database as invalid. The data will be cleared from persistent storage 103 * if CONFIG_BT_SETTINGS is enabled. 104 */ 105 void bt_mesh_cdb_clear(void); 106 107 /** @brief Set and store the IV Index and IV Update flag. 108 * 109 * The IV Index stored in the CDB will be the one used during provisioning 110 * of new nodes. This function is generally only used from inside the stack. 111 * 112 * This function will store the data to persistent storage if 113 * CONFIG_BT_SETTINGS is enabled. 114 * 115 * @param iv_index The new IV Index to use. 116 * @param iv_update True if there is an ongoing IV Update procedure. 117 */ 118 void bt_mesh_cdb_iv_update(uint32_t iv_index, bool iv_update); 119 120 /** @brief Allocate a node. 121 * 122 * Allocate a new node in the CDB. 123 * 124 * If @c addr is 0, @ref bt_mesh_cdb_free_addr_get will be used to allocate 125 * a free address. 126 * 127 * @param uuid UUID of the node. 128 * @param addr Address of the node's primary element. If 0, the lowest 129 * possible address available will be assigned to the node. 130 * @param num_elem Number of elements that the node has. 131 * @param net_idx NetIdx that the node was provisioned to. 132 * 133 * @return The new node or NULL if CDB has already allocated 134 * :kconfig:option:`CONFIG_BT_MESH_CDB_NODE_COUNT` nodes, or reached the 135 * end of the unicast address range, or if @c addr is non-zero and less 136 * than the lowest available address or collide with the allocated addresses. 137 */ 138 struct bt_mesh_cdb_node *bt_mesh_cdb_node_alloc(const uint8_t uuid[16], uint16_t addr, 139 uint8_t num_elem, uint16_t net_idx); 140 141 /** @brief Get the first available address for the given element count. 142 * 143 * @param num_elem Number of elements to accommodate. 144 * 145 * @return The first unicast address in an address range that allows a node 146 * with the given number of elements to fit. 147 */ 148 uint16_t bt_mesh_cdb_free_addr_get(uint8_t num_elem); 149 150 /** @brief Delete a node. 151 * 152 * Delete a node from the CDB. When deleting the node and the address of the 153 * last element of the deleted node is greater than the lowest available 154 * address, CDB will update the lowest available address. The lowest 155 * available address is reset and the deleted addresses can be reused only 156 * after IV Index update. 157 * 158 * @param node The node to be deleted. 159 * @param store If true, the node will be cleared from persistent storage. 160 */ 161 void bt_mesh_cdb_node_del(struct bt_mesh_cdb_node *node, bool store); 162 163 /** @brief Update a node. 164 * 165 * Assigns the node a new address and clears the previous persistent storage 166 * entry. 167 * 168 * @param node The node to be deleted. 169 * @param addr New unicast address for the node. 170 * @param num_elem Updated number of elements in the node. 171 */ 172 void bt_mesh_cdb_node_update(struct bt_mesh_cdb_node *node, uint16_t addr, 173 uint8_t num_elem); 174 175 /** @brief Get a node by address. 176 * 177 * Try to find the node that has the provided address assigned to one of its 178 * elements. 179 * 180 * @param addr Address of the element to look for. 181 * 182 * @return The node that has an element with address addr or NULL if no such 183 * node exists. 184 */ 185 struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr); 186 187 /** @brief Store node to persistent storage. 188 * 189 * @param node Node to be stored. 190 */ 191 void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node); 192 193 /** @brief Import device key for selected node. 194 * 195 * Using security library with PSA implementation access to the key by pointer 196 * will not give a valid value since the key is hidden in the library. 197 * The application has to import the key. 198 * 199 * @param node Selected node. 200 * @param in key value. 201 * 202 * @return 0 on success or negative error code on failure. 203 */ 204 int bt_mesh_cdb_node_key_import(struct bt_mesh_cdb_node *node, const uint8_t in[16]); 205 206 /** @brief Export device key from selected node. 207 * 208 * Using security library with PSA implementation access to the key by pointer 209 * will not give a valid value since the key is hidden in the library. 210 * The application has to export the key. 211 * 212 * @param node Selected node. 213 * @param out key value. 214 * 215 * @return 0 on success or negative error code on failure. 216 */ 217 int bt_mesh_cdb_node_key_export(const struct bt_mesh_cdb_node *node, uint8_t out[16]); 218 219 enum { 220 BT_MESH_CDB_ITER_STOP = 0, 221 BT_MESH_CDB_ITER_CONTINUE, 222 }; 223 224 /** @typedef bt_mesh_cdb_node_func_t 225 * @brief Node iterator callback. 226 * 227 * @param node Node found. 228 * @param user_data Data given. 229 * 230 * @return BT_MESH_CDB_ITER_CONTINUE to continue to iterate through the nodes 231 * or BT_MESH_CDB_ITER_STOP to stop. 232 */ 233 typedef uint8_t (*bt_mesh_cdb_node_func_t)(struct bt_mesh_cdb_node *node, 234 void *user_data); 235 236 /** @brief Node iterator. 237 * 238 * Iterate nodes in the Mesh Configuration Database. The callback function 239 * will only be called for valid, ie allocated, nodes. 240 * 241 * @param func Callback function. 242 * @param user_data Data to pass to the callback. 243 */ 244 void bt_mesh_cdb_node_foreach(bt_mesh_cdb_node_func_t func, void *user_data); 245 246 /** @brief Allocate a subnet. 247 * 248 * Allocate a new subnet in the CDB. 249 * 250 * @param net_idx NetIdx of the subnet. 251 * 252 * @return The new subnet or NULL if it cannot be allocated due to 253 * lack of resources or the subnet has been already allocated. 254 */ 255 struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx); 256 257 /** @brief Delete a subnet. 258 * 259 * Delete a subnet from the CDB. 260 * 261 * @param sub The subnet to be deleted. 262 * @param store If true, the subnet will be cleared from persistent storage. 263 */ 264 void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store); 265 266 /** @brief Get a subnet by NetIdx 267 * 268 * Try to find the subnet with the specified NetIdx. 269 * 270 * @param net_idx NetIdx of the subnet to look for. 271 * 272 * @return The subnet with the specified NetIdx or NULL if no such subnet 273 * exists. 274 */ 275 struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx); 276 277 /** @brief Store subnet to persistent storage. 278 * 279 * @param sub Subnet to be stored. 280 */ 281 void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub); 282 283 /** @brief Get the flags for a subnet 284 * 285 * @param sub The subnet to get flags for. 286 * 287 * @return The flags for the subnet. 288 */ 289 uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub); 290 291 /** @brief Import network key for selected subnetwork. 292 * 293 * Using security library with PSA implementation access to the key by pointer 294 * will not give a valid value since the key is hidden in the library. 295 * The application has to import the key. 296 * 297 * @param sub Selected subnetwork. 298 * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. 299 * The old key has an index 0 and the new one has an index 1. 300 * Otherwise, the only key with index 0 exists. 301 * @param in key value. 302 * 303 * @return 0 on success or negative error code on failure. 304 */ 305 int bt_mesh_cdb_subnet_key_import(struct bt_mesh_cdb_subnet *sub, int key_idx, 306 const uint8_t in[16]); 307 308 /** @brief Export network key from selected subnetwork. 309 * 310 * Using security library with PSA implementation access to the key by pointer 311 * will not give a valid value since the key is hidden in the library. 312 * The application has to export the key. 313 * 314 * @param sub Selected subnetwork. 315 * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. 316 * The old key has an index 0 and the new one has an index 1. 317 * Otherwise, the only key with index 0 exists. 318 * @param out key value. 319 * 320 * @return 0 on success or negative error code on failure. 321 */ 322 int bt_mesh_cdb_subnet_key_export(const struct bt_mesh_cdb_subnet *sub, int key_idx, 323 uint8_t out[16]); 324 325 /** @brief Allocate an application key. 326 * 327 * Allocate a new application key in the CDB. 328 * 329 * @param net_idx NetIdx of NetKey that the application key is bound to. 330 * @param app_idx AppIdx of the application key. 331 * 332 * @return The new application key or NULL if it cannot be allocated due to 333 * lack of resources or the key has been already allocated. 334 */ 335 struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx, 336 uint16_t app_idx); 337 338 /** @brief Delete an application key. 339 * 340 * Delete an application key from the CDB. 341 * 342 * @param key The application key to be deleted. 343 * @param store If true, the key will be cleared from persistent storage. 344 */ 345 void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store); 346 347 /** @brief Get an application key by AppIdx 348 * 349 * Try to find the application key with the specified AppIdx. 350 * 351 * @param app_idx AppIdx of the application key to look for. 352 * 353 * @return The application key with the specified AppIdx or NULL if no such key 354 * exists. 355 */ 356 struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx); 357 358 /** @brief Store application key to persistent storage. 359 * 360 * @param key Application key to be stored. 361 */ 362 void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key); 363 364 /** @brief Import application key. 365 * 366 * Using security library with PSA implementation access to the key by pointer 367 * will not give a valid value since the key is hidden in the library. 368 * The application has to import the key. 369 * 370 * @param key cdb application key structure. 371 * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. 372 * The old key has an index 0 and the new one has an index 1. 373 * Otherwise, the only key with index 0 exists. 374 * @param in key value. 375 * 376 * @return 0 on success or negative error code on failure. 377 */ 378 int bt_mesh_cdb_app_key_import(struct bt_mesh_cdb_app_key *key, int key_idx, const uint8_t in[16]); 379 380 /** @brief Export application key. 381 * 382 * Using security library with PSA implementation access to the key by pointer 383 * will not give a valid value since the key is hidden in the library. 384 * The application has to export the key. 385 * 386 * @param key cdb application key structure. 387 * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. 388 * The old key has an index 0 and the new one has an index 1. 389 * Otherwise, the only key with index 0 exists. 390 * @param out key value. 391 * 392 * @return 0 on success or negative error code on failure. 393 */ 394 int bt_mesh_cdb_app_key_export(const struct bt_mesh_cdb_app_key *key, int key_idx, uint8_t out[16]); 395 396 #ifdef __cplusplus 397 } 398 #endif 399 400 #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */ 401