1 /*
2 * Copyright (C) 2017 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "le_device_db_tlv.c"
39
40 #include "ble/le_device_db.h"
41 #include "ble/le_device_db_tlv.h"
42
43 #include "ble/core.h"
44
45 #include <string.h>
46 #include "btstack_debug.h"
47
48 // LE Device DB Implementation storing entries in btstack_tlv
49
50 // Local cache is used to keep track of deleted entries in TLV
51
52 #define INVALID_ENTRY_ADDR_TYPE 0xff
53
54 // Single stored entry
55 typedef struct le_device_db_entry_t {
56
57 uint32_t seq_nr; // used for "least recently stored" eviction strategy
58
59 // Identification
60 int addr_type;
61 bd_addr_t addr;
62 sm_key_t irk;
63
64 // Stored pairing information allows to re-establish an enncrypted connection
65 // with a peripheral that doesn't have any persistent memory
66 sm_key_t ltk;
67 uint16_t ediv;
68 uint8_t rand[8];
69
70 uint8_t key_size;
71 uint8_t authenticated;
72 uint8_t authorized;
73 uint8_t secure_connection;
74
75 #ifdef ENABLE_LE_SIGNED_WRITE
76 // Signed Writes by remote
77 sm_key_t remote_csrk;
78 uint32_t remote_counter;
79
80 // Signed Writes by us
81 sm_key_t local_csrk;
82 uint32_t local_counter;
83 #endif
84
85 } le_device_db_entry_t;
86
87
88 #ifndef NVM_NUM_DEVICE_DB_ENTRIES
89 #error "NVM_NUM_DEVICE_DB_ENTRIES not defined, please define in btstack_config.h"
90 #endif
91
92 #if NVM_NUM_DEVICE_DB_ENTRIES == 0
93 #error "NVM_NUM_DEVICE_DB_ENTRIES must not be 0, please update in btstack_config.h"
94 #endif
95
96 // only stores if entry present
97 static uint8_t entry_map[NVM_NUM_DEVICE_DB_ENTRIES];
98 static uint32_t num_valid_entries;
99
100 static const btstack_tlv_t * le_device_db_tlv_btstack_tlv_impl;
101 static void * le_device_db_tlv_btstack_tlv_context;
102
103
le_device_db_tlv_tag_for_index(uint8_t index)104 static uint32_t le_device_db_tlv_tag_for_index(uint8_t index){
105 static const char tag_0 = 'B';
106 static const char tag_1 = 'T';
107 static const char tag_2 = 'D';
108
109 return (tag_0 << 24u) | (tag_1 << 16u) | (tag_2 << 8u) | index;
110 }
111
112 // @return success
113 // @param index = entry_pos
le_device_db_tlv_fetch(int index,le_device_db_entry_t * entry)114 static bool le_device_db_tlv_fetch(int index, le_device_db_entry_t * entry){
115 btstack_assert(le_device_db_tlv_btstack_tlv_impl != NULL);
116 btstack_assert(index >= 0);
117 btstack_assert(index < NVM_NUM_DEVICE_DB_ENTRIES);
118
119 uint32_t tag = le_device_db_tlv_tag_for_index(index);
120 int size = le_device_db_tlv_btstack_tlv_impl->get_tag(le_device_db_tlv_btstack_tlv_context, tag, (uint8_t*) entry, sizeof(le_device_db_entry_t));
121 return size == sizeof(le_device_db_entry_t);
122 }
123
124 // @return success
125 // @param index = entry_pos
le_device_db_tlv_store(int index,le_device_db_entry_t * entry)126 static bool le_device_db_tlv_store(int index, le_device_db_entry_t * entry){
127 btstack_assert(le_device_db_tlv_btstack_tlv_impl != NULL);
128 btstack_assert(index >= 0);
129 btstack_assert(index < NVM_NUM_DEVICE_DB_ENTRIES);
130
131 uint32_t tag = le_device_db_tlv_tag_for_index(index);
132 int result = le_device_db_tlv_btstack_tlv_impl->store_tag(le_device_db_tlv_btstack_tlv_context, tag, (uint8_t*) entry, sizeof(le_device_db_entry_t));
133 return result == 0;
134 }
135
136 // @param index = entry_pos
le_device_db_tlv_delete(int index)137 static bool le_device_db_tlv_delete(int index){
138 btstack_assert(le_device_db_tlv_btstack_tlv_impl != NULL);
139 btstack_assert(index >= 0);
140 btstack_assert(index < NVM_NUM_DEVICE_DB_ENTRIES);
141
142 uint32_t tag = le_device_db_tlv_tag_for_index(index);
143 le_device_db_tlv_btstack_tlv_impl->delete_tag(le_device_db_tlv_btstack_tlv_context, tag);
144 return true;
145 }
146
le_device_db_tlv_scan(void)147 static void le_device_db_tlv_scan(void){
148 int i;
149 num_valid_entries = 0;
150 memset(entry_map, 0, sizeof(entry_map));
151 for (i=0;i<NVM_NUM_DEVICE_DB_ENTRIES;i++){
152 // lookup entry
153 le_device_db_entry_t entry;
154 if (!le_device_db_tlv_fetch(i, &entry)) continue;
155
156 entry_map[i] = 1;
157 num_valid_entries++;
158 }
159 log_info("num valid le device entries %u", (unsigned int) num_valid_entries);
160 }
161
le_device_db_init(void)162 void le_device_db_init(void){
163 if (!le_device_db_tlv_btstack_tlv_impl) {
164 log_error("btstack_tlv not initialized");
165 }
166 }
167
168 // not used
le_device_db_set_local_bd_addr(bd_addr_t bd_addr)169 void le_device_db_set_local_bd_addr(bd_addr_t bd_addr){
170 (void)bd_addr;
171 }
172
173 // @return number of device in db
le_device_db_count(void)174 int le_device_db_count(void){
175 return num_valid_entries;
176 }
177
le_device_db_max_count(void)178 int le_device_db_max_count(void){
179 return NVM_NUM_DEVICE_DB_ENTRIES;
180 }
181
le_device_db_remove(int index)182 void le_device_db_remove(int index){
183 btstack_assert(index >= 0);
184 btstack_assert(index < le_device_db_max_count());
185
186 // check if entry exists
187 if (entry_map[index] == 0u) return;
188
189 // delete entry in TLV
190 le_device_db_tlv_delete(index);
191
192 // mark as unused
193 entry_map[index] = 0;
194
195 // keep track
196 num_valid_entries--;
197 }
198
le_device_db_add(int addr_type,bd_addr_t addr,sm_key_t irk)199 int le_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){
200
201 uint32_t highest_seq_nr = 0;
202 uint32_t lowest_seq_nr = 0xFFFFFFFFU;
203 int index_for_lowest_seq_nr = -1;
204 int index_for_addr = -1;
205 int index_for_empty = -1;
206 bool new_entry = false;
207
208 // find unused entry in the used list
209 int i;
210 for (i=0;i<NVM_NUM_DEVICE_DB_ENTRIES;i++){
211 if (entry_map[i] != 0u) {
212 le_device_db_entry_t entry;
213 le_device_db_tlv_fetch(i, &entry);
214 // found addr?
215 if ((memcmp(addr, entry.addr, 6) == 0) && (addr_type == entry.addr_type)){
216 index_for_addr = i;
217 }
218 // update highest seq nr
219 if (entry.seq_nr > highest_seq_nr){
220 highest_seq_nr = entry.seq_nr;
221 }
222 // find entry with lowest seq nr
223 if ((index_for_lowest_seq_nr == -1) || (entry.seq_nr < lowest_seq_nr)){
224 index_for_lowest_seq_nr = i;
225 lowest_seq_nr = entry.seq_nr;
226 }
227 } else {
228 index_for_empty = i;
229 }
230 }
231
232 log_info("index_for_addr %x, index_for_empy %x, index_for_lowest_seq_nr %x", index_for_addr, index_for_empty, index_for_lowest_seq_nr);
233
234 uint32_t index_to_use = 0;
235 if (index_for_addr >= 0){
236 index_to_use = index_for_addr;
237 } else if (index_for_empty >= 0){
238 new_entry = true;
239 index_to_use = index_for_empty;
240 } else if (index_for_lowest_seq_nr >= 0){
241 index_to_use = index_for_lowest_seq_nr;
242 } else {
243 // should not happen
244 return -1;
245 }
246
247 log_info("new entry for index %u", (unsigned int) index_to_use);
248
249 // store entry at index
250 le_device_db_entry_t entry;
251 log_info("LE Device DB adding type %u - %s", addr_type, bd_addr_to_str(addr));
252 log_info_key("irk", irk);
253
254 memset(&entry, 0, sizeof(le_device_db_entry_t));
255
256 entry.addr_type = addr_type;
257 (void)memcpy(entry.addr, addr, 6);
258 (void)memcpy(entry.irk, irk, 16);
259 entry.seq_nr = highest_seq_nr + 1u;
260 #ifdef ENABLE_LE_SIGNED_WRITE
261 entry.remote_counter = 0;
262 #endif
263
264 // store
265 bool ok = le_device_db_tlv_store(index_to_use, &entry);
266 if (!ok){
267 log_error("tag store failed");
268 return -1;
269 }
270 // set in entry_mape
271 entry_map[index_to_use] = 1;
272
273 // keep track - don't increase if old entry found or replaced
274 if (new_entry){
275 num_valid_entries++;
276 }
277
278 return index_to_use;
279 }
280
281
282 // get device information: addr type and address
le_device_db_info(int index,int * addr_type,bd_addr_t addr,sm_key_t irk)283 void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){
284
285 // fetch entry
286 le_device_db_entry_t entry;
287 int ok = le_device_db_tlv_fetch(index, &entry);
288
289 // set defaults if not found
290 if (!ok) {
291 memset(&entry, 0, sizeof(le_device_db_entry_t));
292 entry.addr_type = BD_ADDR_TYPE_UNKNOWN;
293 }
294
295 // setup return values
296 if (addr_type != NULL) *addr_type = entry.addr_type;
297 if (addr != NULL) (void)memcpy(addr, entry.addr, 6);
298 if (irk != NULL) (void)memcpy(irk, entry.irk, 16);
299 }
300
le_device_db_encryption_set(int index,uint16_t ediv,uint8_t rand[8],sm_key_t ltk,int key_size,int authenticated,int authorized,int secure_connection)301 void le_device_db_encryption_set(int index, uint16_t ediv, uint8_t rand[8], sm_key_t ltk, int key_size, int authenticated, int authorized, int secure_connection){
302
303 // fetch entry
304 le_device_db_entry_t entry;
305 int ok = le_device_db_tlv_fetch(index, &entry);
306 if (!ok) return;
307
308 // update
309 log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u, secure connection %u",
310 index, ediv, key_size, authenticated, authorized, secure_connection);
311 entry.ediv = ediv;
312 if (rand != NULL){
313 (void)memcpy(entry.rand, rand, 8);
314 }
315 if (ltk != 0) {
316 (void)memcpy(entry.ltk, ltk, 16);
317 }
318 entry.key_size = key_size;
319 entry.authenticated = authenticated;
320 entry.authorized = authorized;
321 entry.secure_connection = secure_connection;
322
323 // store
324 ok = le_device_db_tlv_store(index, &entry);
325 if (!ok){
326 log_error("Set encryption data failed");
327 }
328 }
329
le_device_db_encryption_get(int index,uint16_t * ediv,uint8_t rand[8],sm_key_t ltk,int * key_size,int * authenticated,int * authorized,int * secure_connection)330 void le_device_db_encryption_get(int index, uint16_t * ediv, uint8_t rand[8], sm_key_t ltk, int * key_size, int * authenticated, int * authorized, int * secure_connection){
331
332 // fetch entry
333 le_device_db_entry_t entry;
334 int ok = le_device_db_tlv_fetch(index, &entry);
335 if (!ok) return;
336
337 // update user fields
338 log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u, secure connection %u",
339 index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized, entry.secure_connection);
340 if (ediv != NULL) *ediv = entry.ediv;
341 if (rand != NULL) (void)memcpy(rand, entry.rand, 8);
342 if (ltk != NULL) (void)memcpy(ltk, entry.ltk, 16);
343 if (key_size != NULL) *key_size = entry.key_size;
344 if (authenticated != NULL) *authenticated = entry.authenticated;
345 if (authorized != NULL) *authorized = entry.authorized;
346 if (secure_connection != NULL) *secure_connection = entry.secure_connection;
347 }
348
349 #ifdef ENABLE_LE_SIGNED_WRITE
350
351 // get signature key
le_device_db_remote_csrk_get(int index,sm_key_t csrk)352 void le_device_db_remote_csrk_get(int index, sm_key_t csrk){
353
354 // fetch entry
355 le_device_db_entry_t entry;
356 int ok = le_device_db_tlv_fetch(index, &entry);
357 if (!ok) return;
358
359 if (csrk) (void)memcpy(csrk, entry.remote_csrk, 16);
360 }
361
le_device_db_remote_csrk_set(int index,sm_key_t csrk)362 void le_device_db_remote_csrk_set(int index, sm_key_t csrk){
363
364 // fetch entry
365 le_device_db_entry_t entry;
366 int ok = le_device_db_tlv_fetch(index, &entry);
367 if (!ok) return;
368
369 if (!csrk) return;
370
371 // update
372 (void)memcpy(entry.remote_csrk, csrk, 16);
373
374 // store
375 le_device_db_tlv_store(index, &entry);
376 }
377
le_device_db_local_csrk_get(int index,sm_key_t csrk)378 void le_device_db_local_csrk_get(int index, sm_key_t csrk){
379
380 // fetch entry
381 le_device_db_entry_t entry;
382 int ok = le_device_db_tlv_fetch(index, &entry);
383 if (!ok) return;
384
385 if (!csrk) return;
386
387 // fill
388 (void)memcpy(csrk, entry.local_csrk, 16);
389 }
390
le_device_db_local_csrk_set(int index,sm_key_t csrk)391 void le_device_db_local_csrk_set(int index, sm_key_t csrk){
392
393 // fetch entry
394 le_device_db_entry_t entry;
395 int ok = le_device_db_tlv_fetch(index, &entry);
396 if (!ok) return;
397
398 if (!csrk) return;
399
400 // update
401 (void)memcpy(entry.local_csrk, csrk, 16);
402
403 // store
404 le_device_db_tlv_store(index, &entry);
405 }
406
407 // query last used/seen signing counter
le_device_db_remote_counter_get(int index)408 uint32_t le_device_db_remote_counter_get(int index){
409
410 // fetch entry
411 le_device_db_entry_t entry;
412 int ok = le_device_db_tlv_fetch(index, &entry);
413 if (!ok) return 0;
414
415 return entry.remote_counter;
416 }
417
418 // update signing counter
le_device_db_remote_counter_set(int index,uint32_t counter)419 void le_device_db_remote_counter_set(int index, uint32_t counter){
420
421 // fetch entry
422 le_device_db_entry_t entry;
423 int ok = le_device_db_tlv_fetch(index, &entry);
424 if (!ok) return;
425
426 entry.remote_counter = counter;
427
428 // store
429 le_device_db_tlv_store(index, &entry);
430 }
431
432 // query last used/seen signing counter
le_device_db_local_counter_get(int index)433 uint32_t le_device_db_local_counter_get(int index){
434
435 // fetch entry
436 le_device_db_entry_t entry;
437 int ok = le_device_db_tlv_fetch(index, &entry);
438 if (!ok) return 0;
439
440 return entry.local_counter;
441 }
442
443 // update signing counter
le_device_db_local_counter_set(int index,uint32_t counter)444 void le_device_db_local_counter_set(int index, uint32_t counter){
445
446 // fetch entry
447 le_device_db_entry_t entry;
448 int ok = le_device_db_tlv_fetch(index, &entry);
449 if (!ok) return;
450
451 // update
452 entry.local_counter = counter;
453
454 // store
455 le_device_db_tlv_store(index, &entry);
456 }
457
458 #endif
459
le_device_db_dump(void)460 void le_device_db_dump(void){
461 log_info("LE Device DB dump, devices: %d", le_device_db_count());
462 uint32_t i;
463
464 for (i=0;i<NVM_NUM_DEVICE_DB_ENTRIES;i++){
465 if (!entry_map[i]) continue;
466 // fetch entry
467 le_device_db_entry_t entry;
468 le_device_db_tlv_fetch(i, &entry);
469 log_info("%u: %u %s", (unsigned int) i, entry.addr_type, bd_addr_to_str(entry.addr));
470 log_info_key("ltk", entry.ltk);
471 log_info_key("irk", entry.irk);
472 #ifdef ENABLE_LE_SIGNED_WRITE
473 log_info_key("local csrk", entry.local_csrk);
474 log_info_key("remote csrk", entry.remote_csrk);
475 #endif
476 }
477 }
478
le_device_db_tlv_configure(const btstack_tlv_t * btstack_tlv_impl,void * btstack_tlv_context)479 void le_device_db_tlv_configure(const btstack_tlv_t * btstack_tlv_impl, void * btstack_tlv_context){
480 le_device_db_tlv_btstack_tlv_impl = btstack_tlv_impl;
481 le_device_db_tlv_btstack_tlv_context = btstack_tlv_context;
482 le_device_db_tlv_scan();
483 }
484