1 /*
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 */
20
21 #include "syscfg/syscfg.h"
22 #include "securec.h"
23 #if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST)
24
25 #include <string.h>
26 #include "sysinit/sysinit.h"
27 #include "host/ble_hs.h"
28 #include "nimble/nimble_port.h"
29 #include "store/config/ble_store_config.h"
30 #include "ble_store_config_priv.h"
31 #include "store/config/wm_bt_storage.h"
32
33 #define NIMBLE_NVS_STR_NAME_MAX_LEN 16
34
35 typedef struct ble_store_value_noaddr_cccd {
36 uint16_t chr_val_handle;
37 uint16_t flags;
38 unsigned value_changed : 1;
39 } ble_store_value_t;
40
41 typedef struct cccd_nvram {
42 ble_addr_t addr;
43 uint8_t offset;
44 ble_store_value_t value[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
45 } cccd_nvram_t;
46
47 /*****************************************************************************
48 * $ NVS *
49 *****************************************************************************/
50
51 /* Gets the database in RAM filled up with keys stored in NVS. The sequence of
52 * the keys in database may get lost.
53 */
ble_hs_log_flat_buf_tmp(const void * data,int len)54 static void ble_hs_log_flat_buf_tmp(const void *data, int len)
55 {
56 const uint8_t *u8ptr;
57 int i;
58 u8ptr = data;
59
60 for (i = 0; i < len; i++) {
61 BLE_HS_LOG(ERROR, "0x%02x ", u8ptr[i]);
62 }
63 }
64
ble_store_nvram_print_value_sec(const struct ble_store_value_sec * sec)65 static void ble_store_nvram_print_value_sec(const struct ble_store_value_sec *sec)
66 {
67 BLE_HS_LOG(ERROR, "addr=");
68 ble_hs_log_flat_buf_tmp(sec->peer_addr.val, 6); // 6:len
69 BLE_HS_LOG(ERROR, " ");
70 BLE_HS_LOG(ERROR, "peer_addr_type=%d ", sec->peer_addr.type);
71
72 if (sec->ltk_present) {
73 BLE_HS_LOG(ERROR, "ediv=%u rand=%llu authenticated=%d ltk=",
74 sec->ediv, sec->rand_num, sec->authenticated);
75 ble_hs_log_flat_buf_tmp(sec->ltk, 16); // 16:len
76 BLE_HS_LOG(ERROR, " ");
77 }
78
79 if (sec->irk_present) {
80 BLE_HS_LOG(ERROR, "irk=");
81 ble_hs_log_flat_buf_tmp(sec->irk, 16); // 16:len
82 BLE_HS_LOG(ERROR, " ");
83 }
84
85 if (sec->csrk_present) {
86 BLE_HS_LOG(ERROR, "csrk=");
87 ble_hs_log_flat_buf_tmp(sec->csrk, 16); // 16:len
88 BLE_HS_LOG(ERROR, " ");
89 }
90
91 BLE_HS_LOG(ERROR, "\n");
92 }
ble_store_nvram_print_value_cccd(const struct ble_store_value_cccd * sec)93 static void ble_store_nvram_print_value_cccd(const struct ble_store_value_cccd *sec)
94 {
95 BLE_HS_LOG(ERROR, "addr=");
96 ble_hs_log_flat_buf_tmp(sec->peer_addr.val, 6); // 6:len
97 BLE_HS_LOG(ERROR, " ");
98 BLE_HS_LOG(ERROR, "peer_addr_type=%d ", sec->peer_addr.type);
99 BLE_HS_LOG(ERROR, "chr_val_handle=%d(0x%04x) ", sec->chr_val_handle, sec->chr_val_handle);
100 BLE_HS_LOG(ERROR, "flags=%d(0x%04x) ", sec->flags, sec->flags);
101 BLE_HS_LOG(ERROR, "value_changed=%d(0x%04x) ", sec->value_changed, sec->value_changed);
102 BLE_HS_LOG(ERROR, "\n");
103 }
104
ble_nvs_restore_sec_keys()105 static int ble_nvs_restore_sec_keys()
106 {
107 int i = 0;
108 int restore_count = 0;
109 uint8_t cccd_info[sizeof(ble_store_value_t)*MYNEWT_VAL(BLE_STORE_MAX_CCCDS)];
110 struct ble_store_value_sec peer_sec;
111 struct ble_store_value_sec our_sec;
112 struct ble_store_value_cccd cccd;
113 ble_addr_t addr;
114 uint32_t nv_tag_valid;
115 uint32_t cccd_count;
116 #define OUR_SEC_VALID_BIT_MASK (0x01<<0)
117 #define PEER_SEC_VALID_BIT_MASK (0x01<<1)
118 #define CCCD_VALID_BITS_MASK (0xFFFFFFFC)
119
120 for (i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) {
121 nv_tag_valid = btif_config_get_sec_cccd_item(i, &addr, &our_sec, sizeof(our_sec), &peer_sec,
122 sizeof(peer_sec), &cccd_info[0], sizeof(cccd_info));
123 if (nv_tag_valid) {
124 if (nv_tag_valid & OUR_SEC_VALID_BIT_MASK) {
125 BLE_HS_LOG(ERROR, "load our sec; ");
126 ble_store_nvram_print_value_sec(&our_sec);
127 ble_store_config_our_secs[ble_store_config_num_our_secs] = our_sec;
128 ble_store_config_num_our_secs++;
129 restore_count++;
130 }
131
132 if (nv_tag_valid & PEER_SEC_VALID_BIT_MASK) {
133 BLE_HS_LOG(ERROR, "load peer sec; ");
134 ble_store_nvram_print_value_sec(&peer_sec);
135 ble_store_config_peer_secs[ble_store_config_num_peer_secs] = peer_sec;
136 ble_store_config_num_peer_secs++;
137 restore_count++;
138 }
139
140 if (nv_tag_valid & CCCD_VALID_BITS_MASK) {
141 int j = 0;
142 ble_store_value_t *ptr_value = (ble_store_value_t *)&cccd_info[0];
143 cccd_count = nv_tag_valid >> 2; // 2:byte alignment
144 assert(cccd_count <= 6); // 6:byte alignment
145
146 for (j = 0; j < cccd_count; j++) {
147 BLE_HS_LOG(ERROR, "load our cccd; ");
148 memcpy_s(&cccd.peer_addr, sizeof(cccd.peer_addr), &addr, sizeof(ble_addr_t));
149 cccd.chr_val_handle = ptr_value->chr_val_handle;
150 cccd.flags = ptr_value->flags;
151 cccd.value_changed = ptr_value->value_changed;
152 ble_store_nvram_print_value_cccd(&cccd);
153 ble_store_config_cccds[ble_store_config_num_cccds] = cccd;
154 ble_store_config_num_cccds++;
155 ptr_value++;
156 }
157 restore_count++;
158 }
159 }
160 }
161
162 return restore_count;
163 }
164
165 static cccd_nvram_t cccd_nvram_array[MYNEWT_VAL(BLE_STORE_MAX_BONDS)];
166
ble_store_config_persist_cccds(bool flush)167 int ble_store_config_persist_cccds(bool flush)
168 {
169 int i = 0, j = 0, rc = 0;
170 int nv_idx = 0;
171 int prefer_index = 0;
172 uint8_t *ptr_byte = NULL;
173 uint8_t found = 0;
174
175 for (i = 0; i < ble_store_config_num_cccds; i++) {
176 cccd_nvram_array[i].offset = 0;
177 }
178
179 /* prepare the nvram information */
180 for (i = 0; i < ble_store_config_num_cccds; i++) {
181 ptr_byte = (uint8_t *)&ble_store_config_cccds[i];
182 ptr_byte += 8; // 8:value offset; dword alignment
183 found = 0;
184
185 for (j = 0; j < prefer_index; j++) {
186 rc = ble_addr_cmp(&ble_store_config_cccds[i].peer_addr, &cccd_nvram_array[j].addr);
187 if (!rc) {
188 memcpy_s(&cccd_nvram_array[j].value[cccd_nvram_array[j].offset],
189 sizeof(cccd_nvram_array[j].value[cccd_nvram_array[j].offset]),
190 ptr_byte, sizeof(ble_store_value_t));
191 cccd_nvram_array[j].offset++;
192 found = 1;
193 break;
194 }
195 }
196
197 if (found) { continue; }
198
199 if (j == prefer_index) {
200 memcpy_s(&cccd_nvram_array[j].addr, sizeof(cccd_nvram_array[j].addr),
201 &ble_store_config_cccds[i].peer_addr, sizeof(ble_addr_t));
202 memcpy_s(&cccd_nvram_array[j].value[cccd_nvram_array[j].offset],
203 sizeof(cccd_nvram_array[j].value[cccd_nvram_array[j].offset]),
204 ptr_byte, sizeof(ble_store_value_t));
205 cccd_nvram_array[j].offset++;
206 prefer_index++;
207 }
208 }
209
210 BLE_HS_LOG(DEBUG, "prefer_index=%d sizeof(ble_store_value_t)=%d\r\n", prefer_index,
211 sizeof(ble_store_value_t));
212 i = 0;
213
214 for (i = 0; i < prefer_index; i++) {
215 nv_idx = btif_config_get_sec_index(&cccd_nvram_array[i].addr, &found);
216 if (nv_idx < 0) {
217 BLE_HS_LOG(DEBUG, "CCCD Full, impossible\r\n");
218 return -1;
219 }
220 if (found) nv_idx = i;
221
222 ptr_byte = (uint8_t *)&cccd_nvram_array[i].value[0];
223 btif_config_store_cccd(nv_idx, &cccd_nvram_array[i].addr, cccd_nvram_array[i].offset, ptr_byte,
224 sizeof(ble_store_value_t)*MYNEWT_VAL(BLE_STORE_MAX_CCCDS));
225 }
226
227 for (; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) {
228 btif_config_delete_cccd(i);
229 }
230
231 if (flush)ble_store_config_persist_flush();
232 return 0;
233 }
234
ble_store_config_persist_peer_secs(bool flush)235 int ble_store_config_persist_peer_secs(bool flush)
236 {
237 int i = 0;
238 int nv_idx = 0;
239 uint8_t found = 0;
240
241 for (i = 0; i < ble_store_config_num_peer_secs; i++) {
242 nv_idx = btif_config_get_sec_index(&ble_store_config_peer_secs[i].peer_addr, &found);
243 if (nv_idx < 0) {
244 BLE_HS_LOG(ERROR, "PEER SEC Full, impossible[i=%d][%d]\r\n", i, ble_store_config_num_peer_secs);
245 return -1;
246 }
247 if (found) nv_idx = i;
248
249 btif_config_store_peer_sec(nv_idx, &ble_store_config_peer_secs[i].peer_addr,
250 (void *)&ble_store_config_peer_secs[i], sizeof(ble_store_config_peer_secs[i]));
251 }
252
253 for (; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) {
254 btif_config_delete_peer_sec(i);
255 }
256
257 if (flush)ble_store_config_persist_flush();
258 return 0;
259 }
260
ble_store_config_persist_our_secs(bool flush)261 int ble_store_config_persist_our_secs(bool flush)
262 {
263 int i = 0;
264 int nv_idx = 0;
265 uint8_t found = 0;
266
267 for (i = 0; i < ble_store_config_num_our_secs; i++) {
268 nv_idx = btif_config_get_sec_index((void *)&ble_store_config_our_secs[i].peer_addr, &found);
269 if (nv_idx < 0) {
270 BLE_HS_LOG(ERROR, "OUR SEC Full, impossible[i=%d][%d]\r\n", i, ble_store_config_num_our_secs);
271 return -1;
272 }
273 if (found) nv_idx = i;
274
275 btif_config_store_our_sec(nv_idx, &ble_store_config_our_secs[i].peer_addr,
276 (void *)&ble_store_config_our_secs[i], sizeof(ble_store_config_our_secs[i]));
277 }
278
279 for (; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) {
280 btif_config_delete_our_sec(i);
281 }
282
283 if (flush)ble_store_config_persist_flush();
284 return 0;
285 }
286
ble_store_config_persist_flush()287 void ble_store_config_persist_flush()
288 {
289 btif_config_flush(1);
290 }
291
ble_store_config_delete_all()292 int ble_store_config_delete_all()
293 {
294 btif_config_delete_all();
295 return 0;
296 }
297
ble_store_config_conf_init()298 void ble_store_config_conf_init()
299 {
300 memset_s(cccd_nvram_array, sizeof(cccd_nvram_array), 0, sizeof(cccd_nvram_t)*MYNEWT_VAL(BLE_STORE_MAX_BONDS));
301 ble_nvs_restore_sec_keys();
302 return;
303 }
ble_store_config_conf_deinit()304 void ble_store_config_conf_deinit()
305 {
306 }
307
308 /***************************************************************************************/
309 #endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */