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 #include "securec.h"
22 #include "ble_hs_priv.h"
23 #include "host/ble_store.h"
24
ble_store_read(int obj_type,const union ble_store_key * key,union ble_store_value * val)25 int ble_store_read(int obj_type, const union ble_store_key *key, union ble_store_value *val)
26 {
27 int rc;
28 ble_hs_lock();
29
30 if (ble_hs_cfg.store_read_cb == NULL) {
31 rc = BLE_HS_ENOTSUP;
32 } else {
33 rc = ble_hs_cfg.store_read_cb(obj_type, key, val);
34 }
35
36 ble_hs_unlock();
37 return rc;
38 }
39
ble_store_write(int obj_type,const union ble_store_value * val)40 int ble_store_write(int obj_type, const union ble_store_value *val)
41 {
42 if (ble_hs_cfg.store_write_cb == NULL) {
43 return BLE_HS_ENOTSUP;
44 }
45
46 while (1) {
47 ble_hs_lock();
48 int rc = ble_hs_cfg.store_write_cb(obj_type, val);
49 ble_hs_unlock();
50
51 switch (rc) {
52 case 0:
53 return 0;
54
55 case BLE_HS_ESTORE_CAP:
56 /* Record didn't fit. Give the application the opportunity to free
57 * up some space.
58 */
59 rc = ble_store_overflow_event(obj_type, val);
60 if (rc != 0) {
61 return rc;
62 }
63
64 /* Application made room for the record; try again. */
65 break;
66
67 default:
68 return rc;
69 }
70 }
71 }
72
ble_store_delete(int obj_type,const union ble_store_key * key)73 int ble_store_delete(int obj_type, const union ble_store_key *key)
74 {
75 int rc;
76 ble_hs_lock();
77
78 if (ble_hs_cfg.store_delete_cb == NULL) {
79 rc = BLE_HS_ENOTSUP;
80 } else {
81 rc = ble_hs_cfg.store_delete_cb(obj_type, key);
82 }
83
84 ble_hs_unlock();
85 return rc;
86 }
87
ble_store_flush(void)88 int ble_store_flush(void)
89 {
90 int rc;
91 ble_hs_lock();
92 if (ble_hs_cfg.store_flush_cb == NULL) {
93 rc = BLE_HS_ENOTSUP;
94 } else {
95 rc = ble_hs_cfg.store_flush_cb();
96 }
97
98 ble_hs_unlock();
99 return rc;
100 }
101
ble_store_status(struct ble_store_status_event * event)102 static int ble_store_status(struct ble_store_status_event *event)
103 {
104 int rc;
105 BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());
106
107 if (ble_hs_cfg.store_status_cb == NULL) {
108 rc = BLE_HS_ENOTSUP;
109 } else {
110 rc = ble_hs_cfg.store_status_cb(event, ble_hs_cfg.store_status_arg);
111 }
112
113 return rc;
114 }
115
ble_store_overflow_event(int obj_type,const union ble_store_value * value)116 int ble_store_overflow_event(int obj_type, const union ble_store_value *value)
117 {
118 struct ble_store_status_event event;
119 event.event_code = BLE_STORE_EVENT_OVERFLOW;
120 event.overflow.obj_type = obj_type;
121 event.overflow.value = value;
122 return ble_store_status(&event);
123 }
124
ble_store_full_event(int obj_type,uint16_t conn_handle)125 int ble_store_full_event(int obj_type, uint16_t conn_handle)
126 {
127 struct ble_store_status_event event;
128 event.event_code = BLE_STORE_EVENT_FULL;
129 event.full.obj_type = obj_type;
130 event.full.conn_handle = conn_handle;
131 return ble_store_status(&event);
132 }
133
ble_store_read_our_sec(const struct ble_store_key_sec * key_sec,struct ble_store_value_sec * value_sec)134 int ble_store_read_our_sec(const struct ble_store_key_sec *key_sec, struct ble_store_value_sec *value_sec)
135 {
136 const union ble_store_key *store_key;
137 union ble_store_value *store_value;
138 int rc;
139 BLE_HS_DBG_ASSERT(key_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
140 key_sec->peer_addr.type == BLE_ADDR_RANDOM ||
141 ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY) == 0);
142 store_key = (void *)key_sec;
143 store_value = (void *)value_sec;
144 rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, store_key, store_value);
145 return rc;
146 }
147
ble_store_persist_sec(int obj_type,const struct ble_store_value_sec * value_sec)148 static int ble_store_persist_sec(int obj_type, const struct ble_store_value_sec *value_sec)
149 {
150 union ble_store_value *store_value;
151 int rc;
152 BLE_HS_DBG_ASSERT(value_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
153 value_sec->peer_addr.type == BLE_ADDR_RANDOM);
154 BLE_HS_DBG_ASSERT(value_sec->ltk_present ||
155 value_sec->irk_present ||
156 value_sec->csrk_present);
157 store_value = (void *)value_sec;
158 rc = ble_store_write(obj_type, store_value);
159 return rc;
160 }
161
ble_store_write_our_sec(const struct ble_store_value_sec * value_sec)162 int ble_store_write_our_sec(const struct ble_store_value_sec *value_sec)
163 {
164 int rc;
165 rc = ble_store_persist_sec(BLE_STORE_OBJ_TYPE_OUR_SEC, value_sec);
166 return rc;
167 }
168
ble_store_delete_our_sec(const struct ble_store_key_sec * key_sec)169 int ble_store_delete_our_sec(const struct ble_store_key_sec *key_sec)
170 {
171 union ble_store_key *store_key;
172 int rc;
173 store_key = (void *)key_sec;
174 rc = ble_store_delete(BLE_STORE_OBJ_TYPE_OUR_SEC, store_key);
175 return rc;
176 }
177
ble_store_delete_peer_sec(const struct ble_store_key_sec * key_sec)178 int ble_store_delete_peer_sec(const struct ble_store_key_sec *key_sec)
179 {
180 union ble_store_key *store_key;
181 int rc;
182 store_key = (void *)key_sec;
183 rc = ble_store_delete(BLE_STORE_OBJ_TYPE_PEER_SEC, store_key);
184 return rc;
185 }
186
ble_store_read_peer_sec(const struct ble_store_key_sec * key_sec,struct ble_store_value_sec * value_sec)187 int ble_store_read_peer_sec(const struct ble_store_key_sec *key_sec, struct ble_store_value_sec *value_sec)
188 {
189 union ble_store_value *store_value;
190 union ble_store_key *store_key;
191 int rc;
192 BLE_HS_DBG_ASSERT(key_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
193 key_sec->peer_addr.type == BLE_ADDR_RANDOM);
194 store_key = (void *)key_sec;
195 store_value = (void *)value_sec;
196 rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_SEC, store_key, store_value);
197 if (rc != 0) {
198 return rc;
199 }
200
201 return 0;
202 }
203
ble_store_write_peer_sec(const struct ble_store_value_sec * value_sec)204 int ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec)
205 {
206 int rc;
207 rc = ble_store_persist_sec(BLE_STORE_OBJ_TYPE_PEER_SEC, value_sec);
208 if (rc != 0) {
209 return rc;
210 }
211
212 if (ble_addr_cmp(&value_sec->peer_addr, BLE_ADDR_ANY) &&
213 value_sec->irk_present) {
214 /* Write the peer IRK to the controller keycache
215 * There is not much to do here if it fails */
216 rc = ble_hs_pvcy_add_entry(value_sec->peer_addr.val,
217 value_sec->peer_addr.type,
218 value_sec->irk);
219 if (rc != 0) {
220 return rc;
221 }
222 }
223
224 return 0;
225 }
226
ble_store_read_cccd(const struct ble_store_key_cccd * key,struct ble_store_value_cccd * out_value)227 int ble_store_read_cccd(const struct ble_store_key_cccd *key, struct ble_store_value_cccd *out_value)
228 {
229 union ble_store_value *store_value;
230 union ble_store_key *store_key;
231 int rc;
232 store_key = (void *)key;
233 store_value = (void *)out_value;
234 rc = ble_store_read(BLE_STORE_OBJ_TYPE_CCCD, store_key, store_value);
235 return rc;
236 }
237
ble_store_write_cccd(const struct ble_store_value_cccd * value)238 int ble_store_write_cccd(const struct ble_store_value_cccd *value)
239 {
240 union ble_store_value *store_value;
241 int rc;
242 store_value = (void *)value;
243 rc = ble_store_write(BLE_STORE_OBJ_TYPE_CCCD, store_value);
244 return rc;
245 }
246
ble_store_delete_cccd(const struct ble_store_key_cccd * key)247 int ble_store_delete_cccd(const struct ble_store_key_cccd *key)
248 {
249 union ble_store_key *store_key;
250 int rc;
251 store_key = (void *)key;
252 rc = ble_store_delete(BLE_STORE_OBJ_TYPE_CCCD, store_key);
253 return rc;
254 }
255
ble_store_key_from_value_cccd(struct ble_store_key_cccd * out_key,const struct ble_store_value_cccd * value)256 void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, const struct ble_store_value_cccd *value)
257 {
258 out_key->peer_addr = value->peer_addr;
259 out_key->chr_val_handle = value->chr_val_handle;
260 out_key->idx = 0;
261 }
262
ble_store_key_from_value_sec(struct ble_store_key_sec * out_key,const struct ble_store_value_sec * value)263 void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, const struct ble_store_value_sec *value)
264 {
265 out_key->peer_addr = value->peer_addr;
266 out_key->ediv = value->ediv;
267 out_key->rand_num = value->rand_num;
268 out_key->ediv_rand_present = 1;
269 out_key->idx = 0;
270 }
271
ble_store_key_from_value(int obj_type,union ble_store_key * out_key,const union ble_store_value * value)272 void ble_store_key_from_value(int obj_type,
273 union ble_store_key *out_key,
274 const union ble_store_value *value)
275 {
276 switch (obj_type) {
277 case BLE_STORE_OBJ_TYPE_OUR_SEC:
278 case BLE_STORE_OBJ_TYPE_PEER_SEC:
279 ble_store_key_from_value_sec(&out_key->sec, &value->sec);
280 break;
281
282 case BLE_STORE_OBJ_TYPE_CCCD:
283 ble_store_key_from_value_cccd(&out_key->cccd, &value->cccd);
284 break;
285
286 default:
287 BLE_HS_DBG_ASSERT(0);
288 break;
289 }
290 }
291
ble_store_iterate(int obj_type,ble_store_iterator_fn * callback,void * cookie)292 int ble_store_iterate(int obj_type,
293 ble_store_iterator_fn *callback,
294 void *cookie)
295 {
296 union ble_store_key key;
297 union ble_store_value value;
298 int idx = 0;
299 uint8_t *pidx;
300 /* a magic value to retrieve anything */
301 memset_s(&key, sizeof(key), 0, sizeof(key));
302
303 switch (obj_type) {
304 case BLE_STORE_OBJ_TYPE_PEER_SEC:
305 case BLE_STORE_OBJ_TYPE_OUR_SEC:
306 key.sec.peer_addr = *BLE_ADDR_ANY;
307 pidx = &key.sec.idx;
308 break;
309
310 case BLE_STORE_OBJ_TYPE_CCCD:
311 key.cccd.peer_addr = *BLE_ADDR_ANY;
312 pidx = &key.cccd.idx;
313 break;
314
315 default:
316 BLE_HS_DBG_ASSERT(0);
317 return BLE_HS_EINVAL;
318 }
319
320 while (1) {
321 *pidx = idx;
322 int rc = ble_store_read(obj_type, &key, &value);
323 switch (rc) {
324 case 0:
325 if (callback != NULL) {
326 rc = callback(obj_type, &value, cookie);
327 if (rc != 0) {
328 /* User function indicates to stop iterating. */
329 return 0;
330 }
331 }
332
333 break;
334
335 case BLE_HS_ENOENT:
336 /* No more entries. */
337 return 0;
338
339 default:
340 /* Read error. */
341 return rc;
342 }
343
344 idx++;
345 }
346 }
347
348 /**
349 * Deletes all objects from the BLE host store.
350 *
351 * @return 0 on success; nonzero on failure.
352 */
ble_store_clear(void)353 int ble_store_clear(void)
354 {
355 const uint8_t obj_types[] = {
356 BLE_STORE_OBJ_TYPE_OUR_SEC,
357 BLE_STORE_OBJ_TYPE_PEER_SEC,
358 BLE_STORE_OBJ_TYPE_CCCD,
359 };
360 union ble_store_key key;
361 int rc;
362 int i;
363 /* A zeroed key will always retrieve the first value. */
364 memset_s(&key, sizeof(key), 0, sizeof key);
365
366 for (i = 0; i < sizeof obj_types / sizeof obj_types[0]; i++) {
367 int obj_type = obj_types[i];
368
369 do {
370 rc = ble_store_delete(obj_type, &key);
371 } while (rc == 0);
372
373 /* BLE_HS_ENOENT means we deleted everything. */
374 if (rc != BLE_HS_ENOENT) {
375 return rc;
376 }
377 }
378 return 0;
379 }