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