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