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. 253 */ 254 struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_alloc(uint16_t net_idx); 255 256 /** @brief Delete a subnet. 257 * 258 * Delete a subnet from the CDB. 259 * 260 * @param sub The subnet to be deleted. 261 * @param store If true, the subnet will be cleared from persistent storage. 262 */ 263 void bt_mesh_cdb_subnet_del(struct bt_mesh_cdb_subnet *sub, bool store); 264 265 /** @brief Get a subnet by NetIdx 266 * 267 * Try to find the subnet with the specified NetIdx. 268 * 269 * @param net_idx NetIdx of the subnet to look for. 270 * 271 * @return The subnet with the specified NetIdx or NULL if no such subnet 272 * exists. 273 */ 274 struct bt_mesh_cdb_subnet *bt_mesh_cdb_subnet_get(uint16_t net_idx); 275 276 /** @brief Store subnet to persistent storage. 277 * 278 * @param sub Subnet to be stored. 279 */ 280 void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub); 281 282 /** @brief Get the flags for a subnet 283 * 284 * @param sub The subnet to get flags for. 285 * 286 * @return The flags for the subnet. 287 */ 288 uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub); 289 290 /** @brief Import network key for selected subnetwork. 291 * 292 * Using security library with PSA implementation access to the key by pointer 293 * will not give a valid value since the key is hidden in the library. 294 * The application has to import the key. 295 * 296 * @param sub Selected subnetwork. 297 * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. 298 * The old key has an index 0 and the new one has an index 1. 299 * Otherwise, the only key with index 0 exists. 300 * @param in key value. 301 * 302 * @return 0 on success or negative error code on failure. 303 */ 304 int bt_mesh_cdb_subnet_key_import(struct bt_mesh_cdb_subnet *sub, int key_idx, 305 const uint8_t in[16]); 306 307 /** @brief Export network key from selected subnetwork. 308 * 309 * Using security library with PSA implementation access to the key by pointer 310 * will not give a valid value since the key is hidden in the library. 311 * The application has to export the key. 312 * 313 * @param sub Selected subnetwork. 314 * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. 315 * The old key has an index 0 and the new one has an index 1. 316 * Otherwise, the only key with index 0 exists. 317 * @param out key value. 318 * 319 * @return 0 on success or negative error code on failure. 320 */ 321 int bt_mesh_cdb_subnet_key_export(const struct bt_mesh_cdb_subnet *sub, int key_idx, 322 uint8_t out[16]); 323 324 /** @brief Allocate an application key. 325 * 326 * Allocate a new application key in the CDB. 327 * 328 * @param net_idx NetIdx of NetKey that the application key is bound to. 329 * @param app_idx AppIdx of the application key. 330 * 331 * @return The new application key or NULL if it cannot be allocated. 332 */ 333 struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_alloc(uint16_t net_idx, 334 uint16_t app_idx); 335 336 /** @brief Delete an application key. 337 * 338 * Delete an application key from the CDB. 339 * 340 * @param key The application key to be deleted. 341 * @param store If true, the key will be cleared from persistent storage. 342 */ 343 void bt_mesh_cdb_app_key_del(struct bt_mesh_cdb_app_key *key, bool store); 344 345 /** @brief Get an application key by AppIdx 346 * 347 * Try to find the application key with the specified AppIdx. 348 * 349 * @param app_idx AppIdx of the application key to look for. 350 * 351 * @return The application key with the specified AppIdx or NULL if no such key 352 * exists. 353 */ 354 struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx); 355 356 /** @brief Store application key to persistent storage. 357 * 358 * @param key Application key to be stored. 359 */ 360 void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key); 361 362 /** @brief Import application key. 363 * 364 * Using security library with PSA implementation access to the key by pointer 365 * will not give a valid value since the key is hidden in the library. 366 * The application has to import the key. 367 * 368 * @param key cdb application key structure. 369 * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. 370 * The old key has an index 0 and the new one has an index 1. 371 * Otherwise, the only key with index 0 exists. 372 * @param in key value. 373 * 374 * @return 0 on success or negative error code on failure. 375 */ 376 int bt_mesh_cdb_app_key_import(struct bt_mesh_cdb_app_key *key, int key_idx, const uint8_t in[16]); 377 378 /** @brief Export application key. 379 * 380 * Using security library with PSA implementation access to the key by pointer 381 * will not give a valid value since the key is hidden in the library. 382 * The application has to export the key. 383 * 384 * @param key cdb application key structure. 385 * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. 386 * The old key has an index 0 and the new one has an index 1. 387 * Otherwise, the only key with index 0 exists. 388 * @param out key value. 389 * 390 * @return 0 on success or negative error code on failure. 391 */ 392 int bt_mesh_cdb_app_key_export(const struct bt_mesh_cdb_app_key *key, int key_idx, uint8_t out[16]); 393 394 #ifdef __cplusplus 395 } 396 #endif 397 398 #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_CDB_H_ */ 399