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