xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/store/config/src/ble_store_config.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 <inttypes.h>
21 #include <string.h>
22 
23 #include "sysinit/sysinit.h"
24 #include "syscfg/syscfg.h"
25 #include "host/ble_hs.h"
26 #include "config/config.h"
27 #include "base64/base64.h"
28 #include "store/config/ble_store_config.h"
29 #include "ble_store_config_priv.h"
30 
31 struct ble_store_value_sec
32     ble_store_config_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
33 int ble_store_config_num_our_secs;
34 
35 struct ble_store_value_sec
36     ble_store_config_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
37 int ble_store_config_num_peer_secs;
38 
39 struct ble_store_value_cccd
40     ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
41 int ble_store_config_num_cccds;
42 
43 /*****************************************************************************
44  * $sec                                                                      *
45  *****************************************************************************/
46 
47 static void
ble_store_config_print_value_sec(const struct ble_store_value_sec * sec)48 ble_store_config_print_value_sec(const struct ble_store_value_sec *sec)
49 {
50     if (sec->ltk_present) {
51         BLE_HS_LOG(DEBUG, "ediv=%u rand=%llu authenticated=%d ltk=",
52                        sec->ediv, sec->rand_num, sec->authenticated);
53         ble_hs_log_flat_buf(sec->ltk, 16);
54         BLE_HS_LOG(DEBUG, " ");
55     }
56     if (sec->irk_present) {
57         BLE_HS_LOG(DEBUG, "irk=");
58         ble_hs_log_flat_buf(sec->irk, 16);
59         BLE_HS_LOG(DEBUG, " ");
60     }
61     if (sec->csrk_present) {
62         BLE_HS_LOG(DEBUG, "csrk=");
63         ble_hs_log_flat_buf(sec->csrk, 16);
64         BLE_HS_LOG(DEBUG, " ");
65     }
66 
67     BLE_HS_LOG(DEBUG, "\n");
68 }
69 
70 static void
ble_store_config_print_key_sec(const struct ble_store_key_sec * key_sec)71 ble_store_config_print_key_sec(const struct ble_store_key_sec *key_sec)
72 {
73     if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) {
74         BLE_HS_LOG(DEBUG, "peer_addr_type=%d peer_addr=",
75                        key_sec->peer_addr.type);
76         ble_hs_log_flat_buf(key_sec->peer_addr.val, 6);
77         BLE_HS_LOG(DEBUG, " ");
78     }
79     if (key_sec->ediv_rand_present) {
80         BLE_HS_LOG(DEBUG, "ediv=0x%02x rand=0x%llx ",
81                        key_sec->ediv, key_sec->rand_num);
82     }
83 }
84 
85 static int
ble_store_config_find_sec(const struct ble_store_key_sec * key_sec,const struct ble_store_value_sec * value_secs,int num_value_secs)86 ble_store_config_find_sec(const struct ble_store_key_sec *key_sec,
87                           const struct ble_store_value_sec *value_secs,
88                           int num_value_secs)
89 {
90     const struct ble_store_value_sec *cur;
91     int skipped;
92     int i;
93 
94     skipped = 0;
95 
96     for (i = 0; i < num_value_secs; i++) {
97         cur = value_secs + i;
98 
99         if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) {
100             if (ble_addr_cmp(&cur->peer_addr, &key_sec->peer_addr)) {
101                 continue;
102             }
103         }
104 
105         if (key_sec->ediv_rand_present) {
106             if (cur->ediv != key_sec->ediv) {
107                 continue;
108             }
109 
110             if (cur->rand_num != key_sec->rand_num) {
111                 continue;
112             }
113         }
114 
115         if (key_sec->idx > skipped) {
116             skipped++;
117             continue;
118         }
119 
120         return i;
121     }
122 
123     return -1;
124 }
125 
126 static int
ble_store_config_read_our_sec(const struct ble_store_key_sec * key_sec,struct ble_store_value_sec * value_sec)127 ble_store_config_read_our_sec(const struct ble_store_key_sec *key_sec,
128                               struct ble_store_value_sec *value_sec)
129 {
130     int idx;
131 
132     idx = ble_store_config_find_sec(key_sec, ble_store_config_our_secs,
133                                     ble_store_config_num_our_secs);
134     if (idx == -1) {
135         return BLE_HS_ENOENT;
136     }
137 
138     *value_sec = ble_store_config_our_secs[idx];
139     return 0;
140 }
141 
142 
143 static int
ble_store_config_write_our_sec(const struct ble_store_value_sec * value_sec)144 ble_store_config_write_our_sec(const struct ble_store_value_sec *value_sec)
145 {
146     struct ble_store_key_sec key_sec;
147     int idx;
148     int rc;
149 
150     BLE_HS_LOG(DEBUG, "persisting our sec; ");
151     ble_store_config_print_value_sec(value_sec);
152 
153     ble_store_key_from_value_sec(&key_sec, value_sec);
154     idx = ble_store_config_find_sec(&key_sec, ble_store_config_our_secs,
155                                     ble_store_config_num_our_secs);
156     if (idx == -1) {
157         if (ble_store_config_num_our_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
158             BLE_HS_LOG(DEBUG, "error persisting our sec; too many entries "
159                               "(%d)\n", ble_store_config_num_our_secs);
160             return BLE_HS_ESTORE_CAP;
161         }
162 
163         idx = ble_store_config_num_our_secs;
164         ble_store_config_num_our_secs++;
165     }
166 
167     ble_store_config_our_secs[idx] = *value_sec;
168 
169     rc = ble_store_config_persist_our_secs();
170     if (rc != 0) {
171         return rc;
172     }
173 
174     return 0;
175 }
176 
177 static int
ble_store_config_delete_obj(void * values,int value_size,int idx,int * num_values)178 ble_store_config_delete_obj(void *values, int value_size, int idx,
179                             int *num_values)
180 {
181     uint8_t *dst;
182     uint8_t *src;
183     int move_count;
184 
185     (*num_values)--;
186     if (idx < *num_values) {
187         dst = values;
188         dst += idx * value_size;
189         src = dst + value_size;
190 
191         move_count = *num_values - idx;
192         memmove(dst, src, move_count * value_size);
193     }
194 
195     return 0;
196 }
197 
198 static int
ble_store_config_delete_sec(const struct ble_store_key_sec * key_sec,struct ble_store_value_sec * value_secs,int * num_value_secs)199 ble_store_config_delete_sec(const struct ble_store_key_sec *key_sec,
200                             struct ble_store_value_sec *value_secs,
201                             int *num_value_secs)
202 {
203     int idx;
204     int rc;
205 
206     idx = ble_store_config_find_sec(key_sec, value_secs, *num_value_secs);
207     if (idx == -1) {
208         return BLE_HS_ENOENT;
209     }
210 
211     rc = ble_store_config_delete_obj(value_secs, sizeof *value_secs, idx,
212                                   num_value_secs);
213     if (rc != 0) {
214         return rc;
215     }
216 
217     return 0;
218 }
219 
220 static int
ble_store_config_delete_our_sec(const struct ble_store_key_sec * key_sec)221 ble_store_config_delete_our_sec(const struct ble_store_key_sec *key_sec)
222 {
223     int rc;
224 
225     rc = ble_store_config_delete_sec(key_sec, ble_store_config_our_secs,
226                                      &ble_store_config_num_our_secs);
227     if (rc != 0) {
228         return rc;
229     }
230 
231     rc = ble_store_config_persist_our_secs();
232     if (rc != 0) {
233         return rc;
234     }
235 
236     return 0;
237 }
238 
239 static int
ble_store_config_delete_peer_sec(const struct ble_store_key_sec * key_sec)240 ble_store_config_delete_peer_sec(const struct ble_store_key_sec *key_sec)
241 {
242     int rc;
243 
244     rc = ble_store_config_delete_sec(key_sec, ble_store_config_peer_secs,
245                                   &ble_store_config_num_peer_secs);
246     if (rc != 0) {
247         return rc;
248     }
249 
250     rc = ble_store_config_persist_peer_secs();
251     if (rc != 0) {
252         return rc;
253     }
254 
255     return 0;
256 }
257 
258 static int
ble_store_config_read_peer_sec(const struct ble_store_key_sec * key_sec,struct ble_store_value_sec * value_sec)259 ble_store_config_read_peer_sec(const struct ble_store_key_sec *key_sec,
260                                struct ble_store_value_sec *value_sec)
261 {
262     int idx;
263 
264     idx = ble_store_config_find_sec(key_sec, ble_store_config_peer_secs,
265                              ble_store_config_num_peer_secs);
266     if (idx == -1) {
267         return BLE_HS_ENOENT;
268     }
269 
270     *value_sec = ble_store_config_peer_secs[idx];
271     return 0;
272 }
273 
274 static int
ble_store_config_write_peer_sec(const struct ble_store_value_sec * value_sec)275 ble_store_config_write_peer_sec(const struct ble_store_value_sec *value_sec)
276 {
277     struct ble_store_key_sec key_sec;
278     int idx;
279     int rc;
280 
281     BLE_HS_LOG(DEBUG, "persisting peer sec; ");
282     ble_store_config_print_value_sec(value_sec);
283 
284     ble_store_key_from_value_sec(&key_sec, value_sec);
285     idx = ble_store_config_find_sec(&key_sec, ble_store_config_peer_secs,
286                                  ble_store_config_num_peer_secs);
287     if (idx == -1) {
288         if (ble_store_config_num_peer_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
289             BLE_HS_LOG(DEBUG, "error persisting peer sec; too many entries "
290                              "(%d)\n", ble_store_config_num_peer_secs);
291             return BLE_HS_ESTORE_CAP;
292         }
293 
294         idx = ble_store_config_num_peer_secs;
295         ble_store_config_num_peer_secs++;
296     }
297 
298     ble_store_config_peer_secs[idx] = *value_sec;
299 
300     rc = ble_store_config_persist_peer_secs();
301     if (rc != 0) {
302         return rc;
303     }
304 
305     return 0;
306 }
307 
308 /*****************************************************************************
309  * $cccd                                                                     *
310  *****************************************************************************/
311 
312 static int
ble_store_config_find_cccd(const struct ble_store_key_cccd * key)313 ble_store_config_find_cccd(const struct ble_store_key_cccd *key)
314 {
315     struct ble_store_value_cccd *cccd;
316     int skipped;
317     int i;
318 
319     skipped = 0;
320     for (i = 0; i < ble_store_config_num_cccds; i++) {
321         cccd = ble_store_config_cccds + i;
322 
323         if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) {
324             if (ble_addr_cmp(&cccd->peer_addr, &key->peer_addr)) {
325                 continue;
326             }
327         }
328 
329         if (key->chr_val_handle != 0) {
330             if (cccd->chr_val_handle != key->chr_val_handle) {
331                 continue;
332             }
333         }
334 
335         if (key->idx > skipped) {
336             skipped++;
337             continue;
338         }
339 
340         return i;
341     }
342 
343     return -1;
344 }
345 
346 static int
ble_store_config_delete_cccd(const struct ble_store_key_cccd * key_cccd)347 ble_store_config_delete_cccd(const struct ble_store_key_cccd *key_cccd)
348 {
349     int idx;
350     int rc;
351 
352     idx = ble_store_config_find_cccd(key_cccd);
353     if (idx == -1) {
354         return BLE_HS_ENOENT;
355     }
356 
357     rc = ble_store_config_delete_obj(ble_store_config_cccds,
358                                      sizeof *ble_store_config_cccds,
359                                      idx,
360                                      &ble_store_config_num_cccds);
361     if (rc != 0) {
362         return rc;
363     }
364 
365     rc = ble_store_config_persist_cccds();
366     if (rc != 0) {
367         return rc;
368     }
369 
370     return 0;
371 }
372 
373 static int
ble_store_config_read_cccd(const struct ble_store_key_cccd * key_cccd,struct ble_store_value_cccd * value_cccd)374 ble_store_config_read_cccd(const struct ble_store_key_cccd *key_cccd,
375                            struct ble_store_value_cccd *value_cccd)
376 {
377     int idx;
378 
379     idx = ble_store_config_find_cccd(key_cccd);
380     if (idx == -1) {
381         return BLE_HS_ENOENT;
382     }
383 
384     *value_cccd = ble_store_config_cccds[idx];
385     return 0;
386 }
387 
388 static int
ble_store_config_write_cccd(const struct ble_store_value_cccd * value_cccd)389 ble_store_config_write_cccd(const struct ble_store_value_cccd *value_cccd)
390 {
391     struct ble_store_key_cccd key_cccd;
392     int idx;
393     int rc;
394 
395     ble_store_key_from_value_cccd(&key_cccd, value_cccd);
396     idx = ble_store_config_find_cccd(&key_cccd);
397     if (idx == -1) {
398         if (ble_store_config_num_cccds >= MYNEWT_VAL(BLE_STORE_MAX_CCCDS)) {
399             BLE_HS_LOG(DEBUG, "error persisting cccd; too many entries (%d)\n",
400                        ble_store_config_num_cccds);
401             return BLE_HS_ESTORE_CAP;
402         }
403 
404         idx = ble_store_config_num_cccds;
405         ble_store_config_num_cccds++;
406     }
407 
408     ble_store_config_cccds[idx] = *value_cccd;
409 
410     rc = ble_store_config_persist_cccds();
411     if (rc != 0) {
412         return rc;
413     }
414 
415     return 0;
416 }
417 
418 /*****************************************************************************
419  * $api                                                                      *
420  *****************************************************************************/
421 
422 /**
423  * Searches the database for an object matching the specified criteria.
424  *
425  * @return                      0 if a key was found; else BLE_HS_ENOENT.
426  */
427 int
ble_store_config_read(int obj_type,const union ble_store_key * key,union ble_store_value * value)428 ble_store_config_read(int obj_type, const union ble_store_key *key,
429                       union ble_store_value *value)
430 {
431     int rc;
432 
433     switch (obj_type) {
434     case BLE_STORE_OBJ_TYPE_PEER_SEC:
435         /* An encryption procedure (bonding) is being attempted.  The nimble
436          * stack is asking us to look in our key database for a long-term key
437          * corresponding to the specified ediv and random number.
438          *
439          * Perform a key lookup and populate the context object with the
440          * result.  The nimble stack will use this key if this function returns
441          * success.
442          */
443         BLE_HS_LOG(DEBUG, "looking up peer sec; ");
444         ble_store_config_print_key_sec(&key->sec);
445         BLE_HS_LOG(DEBUG, "\n");
446         rc = ble_store_config_read_peer_sec(&key->sec, &value->sec);
447         return rc;
448 
449     case BLE_STORE_OBJ_TYPE_OUR_SEC:
450         BLE_HS_LOG(DEBUG, "looking up our sec; ");
451         ble_store_config_print_key_sec(&key->sec);
452         BLE_HS_LOG(DEBUG, "\n");
453         rc = ble_store_config_read_our_sec(&key->sec, &value->sec);
454         return rc;
455 
456     case BLE_STORE_OBJ_TYPE_CCCD:
457         rc = ble_store_config_read_cccd(&key->cccd, &value->cccd);
458         return rc;
459 
460     default:
461         return BLE_HS_ENOTSUP;
462     }
463 }
464 
465 /**
466  * Adds the specified object to the database.
467  *
468  * @return                      0 on success;
469  *                              BLE_HS_ESTORE_CAP if the database is full.
470  */
471 int
ble_store_config_write(int obj_type,const union ble_store_value * val)472 ble_store_config_write(int obj_type, const union ble_store_value *val)
473 {
474     int rc;
475 
476     switch (obj_type) {
477     case BLE_STORE_OBJ_TYPE_PEER_SEC:
478         rc = ble_store_config_write_peer_sec(&val->sec);
479         return rc;
480 
481     case BLE_STORE_OBJ_TYPE_OUR_SEC:
482         rc = ble_store_config_write_our_sec(&val->sec);
483         return rc;
484 
485     case BLE_STORE_OBJ_TYPE_CCCD:
486         rc = ble_store_config_write_cccd(&val->cccd);
487         return rc;
488 
489     default:
490         return BLE_HS_ENOTSUP;
491     }
492 }
493 
494 int
ble_store_config_delete(int obj_type,const union ble_store_key * key)495 ble_store_config_delete(int obj_type, const union ble_store_key *key)
496 {
497     int rc;
498 
499     switch (obj_type) {
500     case BLE_STORE_OBJ_TYPE_PEER_SEC:
501         rc = ble_store_config_delete_peer_sec(&key->sec);
502         return rc;
503 
504     case BLE_STORE_OBJ_TYPE_OUR_SEC:
505         rc = ble_store_config_delete_our_sec(&key->sec);
506         return rc;
507 
508     case BLE_STORE_OBJ_TYPE_CCCD:
509         rc = ble_store_config_delete_cccd(&key->cccd);
510         return rc;
511 
512     default:
513         return BLE_HS_ENOTSUP;
514     }
515 }
516 
517 void
ble_store_config_init(void)518 ble_store_config_init(void)
519 {
520     /* Ensure this function only gets called by sysinit. */
521     SYSINIT_ASSERT_ACTIVE();
522 
523     ble_hs_cfg.store_read_cb = ble_store_config_read;
524     ble_hs_cfg.store_write_cb = ble_store_config_write;
525     ble_hs_cfg.store_delete_cb = ble_store_config_delete;
526 
527     /* Re-initialize BSS values in case of unit tests. */
528     ble_store_config_num_our_secs = 0;
529     ble_store_config_num_peer_secs = 0;
530     ble_store_config_num_cccds = 0;
531 
532     ble_store_config_conf_init();
533 }
534