xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_store.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <string.h>
21 
22 #include "host/ble_store.h"
23 #include "ble_hs_priv.h"
24 
25 int
ble_store_read(int obj_type,const union ble_store_key * key,union ble_store_value * val)26 ble_store_read(int obj_type, const union ble_store_key *key,
27                union ble_store_value *val)
28 {
29     int rc;
30 
31     ble_hs_lock();
32 
33     if (ble_hs_cfg.store_read_cb == NULL) {
34         rc = BLE_HS_ENOTSUP;
35     } else {
36         rc = ble_hs_cfg.store_read_cb(obj_type, key, val);
37     }
38 
39     ble_hs_unlock();
40 
41     return rc;
42 }
43 
44 int
ble_store_write(int obj_type,const union ble_store_value * val)45 ble_store_write(int obj_type, const union ble_store_value *val)
46 {
47     int rc;
48 
49     if (ble_hs_cfg.store_write_cb == NULL) {
50         return BLE_HS_ENOTSUP;
51     }
52 
53     while (1) {
54         ble_hs_lock();
55         rc = ble_hs_cfg.store_write_cb(obj_type, val);
56         ble_hs_unlock();
57 
58         switch (rc) {
59         case 0:
60             return 0;
61         case BLE_HS_ESTORE_CAP:
62             /* Record didn't fit.  Give the application the opportunity to free
63              * up some space.
64              */
65             rc = ble_store_overflow_event(obj_type, val);
66             if (rc != 0) {
67                 return rc;
68             }
69 
70             /* Application made room for the record; try again. */
71             break;
72 
73         default:
74             return rc;
75         }
76     }
77 }
78 
79 int
ble_store_delete(int obj_type,const union ble_store_key * key)80 ble_store_delete(int obj_type, const union ble_store_key *key)
81 {
82     int rc;
83 
84     ble_hs_lock();
85 
86     if (ble_hs_cfg.store_delete_cb == NULL) {
87         rc = BLE_HS_ENOTSUP;
88     } else {
89         rc = ble_hs_cfg.store_delete_cb(obj_type, key);
90     }
91 
92     ble_hs_unlock();
93 
94     return rc;
95 }
96 
97 static int
ble_store_status(struct ble_store_status_event * event)98 ble_store_status(struct ble_store_status_event *event)
99 {
100     int rc;
101 
102     BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
103 
104     if (ble_hs_cfg.store_status_cb == NULL) {
105         rc = BLE_HS_ENOTSUP;
106     } else {
107         rc = ble_hs_cfg.store_status_cb(event, ble_hs_cfg.store_status_arg);
108     }
109 
110     return rc;
111 }
112 
113 int
ble_store_overflow_event(int obj_type,const union ble_store_value * value)114 ble_store_overflow_event(int obj_type, const union ble_store_value *value)
115 {
116     struct ble_store_status_event event;
117 
118     event.event_code = BLE_STORE_EVENT_OVERFLOW;
119     event.overflow.obj_type = obj_type;
120     event.overflow.value = value;
121 
122     return ble_store_status(&event);
123 }
124 
125 int
ble_store_full_event(int obj_type,uint16_t conn_handle)126 ble_store_full_event(int obj_type, uint16_t conn_handle)
127 {
128     struct ble_store_status_event event;
129 
130     event.event_code = BLE_STORE_EVENT_FULL;
131     event.full.obj_type = obj_type;
132     event.full.conn_handle = conn_handle;
133 
134     return ble_store_status(&event);
135 }
136 
137 int
ble_store_read_our_sec(const struct ble_store_key_sec * key_sec,struct ble_store_value_sec * value_sec)138 ble_store_read_our_sec(const struct ble_store_key_sec *key_sec,
139                        struct ble_store_value_sec *value_sec)
140 {
141     const union ble_store_key *store_key;
142     union ble_store_value *store_value;
143     int rc;
144 
145     BLE_HS_DBG_ASSERT(key_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
146                       key_sec->peer_addr.type == BLE_ADDR_RANDOM ||
147                       ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY) == 0);
148 
149     store_key = (void *)key_sec;
150     store_value = (void *)value_sec;
151     rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, store_key, store_value);
152     return rc;
153 }
154 
155 static int
ble_store_persist_sec(int obj_type,const struct ble_store_value_sec * value_sec)156 ble_store_persist_sec(int obj_type,
157                       const struct ble_store_value_sec *value_sec)
158 {
159     union ble_store_value *store_value;
160     int rc;
161 
162     BLE_HS_DBG_ASSERT(value_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
163                       value_sec->peer_addr.type == BLE_ADDR_RANDOM);
164     BLE_HS_DBG_ASSERT(value_sec->ltk_present ||
165                       value_sec->irk_present ||
166                       value_sec->csrk_present);
167 
168     store_value = (void *)value_sec;
169     rc = ble_store_write(obj_type, store_value);
170     return rc;
171 }
172 
173 int
ble_store_write_our_sec(const struct ble_store_value_sec * value_sec)174 ble_store_write_our_sec(const struct ble_store_value_sec *value_sec)
175 {
176     int rc;
177 
178     rc = ble_store_persist_sec(BLE_STORE_OBJ_TYPE_OUR_SEC, value_sec);
179     return rc;
180 }
181 
182 int
ble_store_delete_our_sec(const struct ble_store_key_sec * key_sec)183 ble_store_delete_our_sec(const struct ble_store_key_sec *key_sec)
184 {
185     union ble_store_key *store_key;
186     int rc;
187 
188     store_key = (void *)key_sec;
189     rc = ble_store_delete(BLE_STORE_OBJ_TYPE_OUR_SEC, store_key);
190     return rc;
191 }
192 
193 int
ble_store_delete_peer_sec(const struct ble_store_key_sec * key_sec)194 ble_store_delete_peer_sec(const struct ble_store_key_sec *key_sec)
195 {
196     union ble_store_key *store_key;
197     int rc;
198 
199     store_key = (void *)key_sec;
200     rc = ble_store_delete(BLE_STORE_OBJ_TYPE_PEER_SEC, store_key);
201     return rc;
202 }
203 
204 int
ble_store_read_peer_sec(const struct ble_store_key_sec * key_sec,struct ble_store_value_sec * value_sec)205 ble_store_read_peer_sec(const struct ble_store_key_sec *key_sec,
206                         struct ble_store_value_sec *value_sec)
207 {
208     union ble_store_value *store_value;
209     union ble_store_key *store_key;
210     int rc;
211 
212     BLE_HS_DBG_ASSERT(key_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
213                       key_sec->peer_addr.type == BLE_ADDR_RANDOM);
214 
215     store_key = (void *)key_sec;
216     store_value = (void *)value_sec;
217     rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_SEC, store_key, store_value);
218 
219     if (rc != 0) {
220         return rc;
221     }
222 
223     return 0;
224 }
225 
226 int
ble_store_write_peer_sec(const struct ble_store_value_sec * value_sec)227 ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec)
228 {
229     int rc;
230 
231     rc = ble_store_persist_sec(BLE_STORE_OBJ_TYPE_PEER_SEC, value_sec);
232     if (rc != 0) {
233         return rc;
234     }
235 
236     if (ble_addr_cmp(&value_sec->peer_addr, BLE_ADDR_ANY) &&
237         value_sec->irk_present) {
238 
239         /* Write the peer IRK to the controller keycache
240          * There is not much to do here if it fails */
241         rc = ble_hs_pvcy_add_entry(value_sec->peer_addr.val,
242                                           value_sec->peer_addr.type,
243                                           value_sec->irk);
244         if (rc != 0) {
245             return rc;
246         }
247     }
248 
249     return 0;
250 }
251 
252 int
ble_store_read_cccd(const struct ble_store_key_cccd * key,struct ble_store_value_cccd * out_value)253 ble_store_read_cccd(const struct ble_store_key_cccd *key,
254                     struct ble_store_value_cccd *out_value)
255 {
256     union ble_store_value *store_value;
257     union ble_store_key *store_key;
258     int rc;
259 
260     store_key = (void *)key;
261     store_value = (void *)out_value;
262     rc = ble_store_read(BLE_STORE_OBJ_TYPE_CCCD, store_key, store_value);
263     return rc;
264 }
265 
266 int
ble_store_write_cccd(const struct ble_store_value_cccd * value)267 ble_store_write_cccd(const struct ble_store_value_cccd *value)
268 {
269     union ble_store_value *store_value;
270     int rc;
271 
272     store_value = (void *)value;
273     rc = ble_store_write(BLE_STORE_OBJ_TYPE_CCCD, store_value);
274     return rc;
275 }
276 
277 int
ble_store_delete_cccd(const struct ble_store_key_cccd * key)278 ble_store_delete_cccd(const struct ble_store_key_cccd *key)
279 {
280     union ble_store_key *store_key;
281     int rc;
282 
283     store_key = (void *)key;
284     rc = ble_store_delete(BLE_STORE_OBJ_TYPE_CCCD, store_key);
285     return rc;
286 }
287 
288 void
ble_store_key_from_value_cccd(struct ble_store_key_cccd * out_key,const struct ble_store_value_cccd * value)289 ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key,
290                               const struct ble_store_value_cccd *value)
291 {
292     out_key->peer_addr = value->peer_addr;
293     out_key->chr_val_handle = value->chr_val_handle;
294     out_key->idx = 0;
295 }
296 
297 void
ble_store_key_from_value_sec(struct ble_store_key_sec * out_key,const struct ble_store_value_sec * value)298 ble_store_key_from_value_sec(struct ble_store_key_sec *out_key,
299                              const struct ble_store_value_sec *value)
300 {
301     out_key->peer_addr = value->peer_addr;
302 
303     out_key->ediv = value->ediv;
304     out_key->rand_num = value->rand_num;
305     out_key->ediv_rand_present = 1;
306     out_key->idx = 0;
307 }
308 
309 void
ble_store_key_from_value(int obj_type,union ble_store_key * out_key,const union ble_store_value * value)310 ble_store_key_from_value(int obj_type,
311                          union ble_store_key *out_key,
312                          const union ble_store_value *value)
313 {
314     switch (obj_type) {
315     case BLE_STORE_OBJ_TYPE_OUR_SEC:
316     case BLE_STORE_OBJ_TYPE_PEER_SEC:
317         ble_store_key_from_value_sec(&out_key->sec, &value->sec);
318         break;
319 
320     case BLE_STORE_OBJ_TYPE_CCCD:
321         ble_store_key_from_value_cccd(&out_key->cccd, &value->cccd);
322         break;
323 
324     default:
325         BLE_HS_DBG_ASSERT(0);
326         break;
327     }
328 }
329 
330 int
ble_store_iterate(int obj_type,ble_store_iterator_fn * callback,void * cookie)331 ble_store_iterate(int obj_type,
332                   ble_store_iterator_fn *callback,
333                   void *cookie)
334 {
335     union ble_store_key key;
336     union ble_store_value value;
337     int idx = 0;
338     uint8_t *pidx;
339     int rc;
340 
341     /* a magic value to retrieve anything */
342     memset(&key, 0, sizeof(key));
343     switch(obj_type) {
344         case BLE_STORE_OBJ_TYPE_PEER_SEC:
345         case BLE_STORE_OBJ_TYPE_OUR_SEC:
346             key.sec.peer_addr = *BLE_ADDR_ANY;
347             pidx = &key.sec.idx;
348             break;
349         case BLE_STORE_OBJ_TYPE_CCCD:
350             key.cccd.peer_addr = *BLE_ADDR_ANY;
351             pidx = &key.cccd.idx;
352             break;
353         default:
354             BLE_HS_DBG_ASSERT(0);
355             return BLE_HS_EINVAL;
356     }
357 
358     while (1) {
359         *pidx = idx;
360         rc = ble_store_read(obj_type, &key, &value);
361         switch (rc) {
362         case 0:
363             if (callback != NULL) {
364                 rc = callback(obj_type, &value, cookie);
365                 if (rc != 0) {
366                     /* User function indicates to stop iterating. */
367                     return 0;
368                 }
369             }
370             break;
371 
372         case BLE_HS_ENOENT:
373             /* No more entries. */
374             return 0;
375 
376         default:
377             /* Read error. */
378             return rc;
379         }
380 
381         idx++;
382     }
383 }
384 
385 /**
386  * Deletes all objects from the BLE host store.
387  *
388  * @return                      0 on success; nonzero on failure.
389  */
390 int
ble_store_clear(void)391 ble_store_clear(void)
392 {
393     const uint8_t obj_types[] = {
394         BLE_STORE_OBJ_TYPE_OUR_SEC,
395         BLE_STORE_OBJ_TYPE_PEER_SEC,
396         BLE_STORE_OBJ_TYPE_CCCD,
397     };
398     union ble_store_key key;
399     int obj_type;
400     int rc;
401     int i;
402 
403     /* A zeroed key will always retrieve the first value. */
404     memset(&key, 0, sizeof key);
405 
406     for (i = 0; i < sizeof obj_types / sizeof obj_types[0]; i++) {
407         obj_type = obj_types[i];
408 
409         do {
410             rc = ble_store_delete(obj_type, &key);
411         } while (rc == 0);
412 
413         /* BLE_HS_ENOENT means we deleted everything. */
414         if (rc != BLE_HS_ENOENT) {
415             return rc;
416         }
417     }
418 
419     return 0;
420 }
421