xref: /btstack/src/ble/le_device_db_tlv.c (revision 2e1f7af07f6a4d201438589c1d8aae3edfdaa45e)
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 MATTHIAS
24  * RINGWALD 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 <stdio.h>
46 #include <string.h>
47 #include "btstack_debug.h"
48 
49 // LE Device DB Implementation storing entries in btstack_tlv
50 
51 // Local cache is used to keep track of deleted entries in TLV
52 
53 #define INVALID_ENTRY_ADDR_TYPE 0xff
54 
55 // Single stored entry
56 typedef struct le_device_db_entry_t {
57 
58     // Identification
59     int addr_type;
60     bd_addr_t addr;
61     sm_key_t irk;
62 
63     // Stored pairing information allows to re-establish an enncrypted connection
64     // with a peripheral that doesn't have any persistent memory
65     sm_key_t ltk;
66     uint16_t ediv;
67     uint8_t  rand[8];
68     uint8_t  key_size;
69     uint8_t  authenticated;
70     uint8_t  authorized;
71 
72 #ifdef ENABLE_LE_SIGNED_WRITE
73     // Signed Writes by remote
74     sm_key_t remote_csrk;
75     uint32_t remote_counter;
76 
77     // Signed Writes by us
78     sm_key_t local_csrk;
79     uint32_t local_counter;
80 #endif
81 
82 } le_device_db_entry_t;
83 
84 
85 #ifndef NVM_NUM_DEVICE_DB_ENTRIES
86 #error "NVM_NUM_DEVICE_DB_ENTRIES not defined, please define in btstack_config.h"
87 #endif
88 
89 #if NVM_NUM_DEVICE_DB_ENTRIES == 0
90 #error "NVM_NUM_DEVICE_DB_ENTRIES must not be 0, please update in btstack_config.h"
91 #endif
92 
93 static uint8_t  entry_map[NVM_NUM_DEVICE_DB_ENTRIES];
94 static uint32_t num_valid_entries;
95 
96 static const btstack_tlv_t * le_device_db_tlv_btstack_tlv_impl;
97 static       void *          le_device_db_tlv_btstack_tlv_context;
98 
99 static const char tag_0 = 'B';
100 static const char tag_1 = 'T';
101 static const char tag_2 = 'D';
102 
103 static uint32_t le_device_db_tlv_tag_for_index(uint8_t index){
104     return (tag_0 << 24) | (tag_1 << 16) | (tag_2 << 8) | index;
105 }
106 
107 // @returns success
108 // @param index = entry_pos
109 static int le_device_db_tlv_fetch(int index, le_device_db_entry_t * entry){
110     if (index < 0 || index >= NVM_NUM_DEVICE_DB_ENTRIES){
111 	    log_error("le_device_db_tlv_fetch called with invalid index %d", index);
112 	    return 0;
113 	}
114     uint32_t tag = le_device_db_tlv_tag_for_index(index);
115     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));
116 	return size != 0;
117 }
118 
119 // @returns success
120 // @param index = entry_pos
121 static int le_device_db_tlv_store(int index, le_device_db_entry_t * entry){
122     if (index < 0 || index >= NVM_NUM_DEVICE_DB_ENTRIES){
123 	    log_error("le_device_db_tlv_store called with invalid index %d", index);
124 	    return 0;
125 	}
126     uint32_t tag = le_device_db_tlv_tag_for_index(index);
127     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));
128 	return 1;
129 }
130 
131 // @param index = entry_pos
132 static int le_device_db_tlv_delete(int index){
133     if (index < 0 || index >= NVM_NUM_DEVICE_DB_ENTRIES){
134 	    log_error("le_device_db_tlv_delete called with invalid index %d", index);
135 	    return 0;
136 	}
137     uint32_t tag = le_device_db_tlv_tag_for_index(index);
138     le_device_db_tlv_btstack_tlv_impl->delete_tag(le_device_db_tlv_btstack_tlv_context, tag);
139 	return 1;
140 }
141 
142 static int le_device_db_tlv_fetch_mapped(int index, le_device_db_entry_t * entry){
143     if (index < 0 || index >= num_valid_entries){
144 	    log_error("le_device_db_tlv_fetch_mapped called with invalid index %d", index);
145 	    return 0;
146 	}
147 	return le_device_db_tlv_fetch(entry_map[index], entry);
148 }
149 
150 static int le_device_db_tlv_store_mapped(int index, le_device_db_entry_t * entry){
151     if (index < 0 || index >= num_valid_entries){
152 	    log_error("le_device_tlv_store_mapped called with invalid index %d", index);
153 	    return 0;
154 	}
155 	return le_device_db_tlv_store(entry_map[index], entry);
156 }
157 
158 
159 void le_device_db_init(void){
160     int i;
161 	num_valid_entries = 0;
162 	memset(entry_map, 0, sizeof(entry_map));
163     for (i=0;i<NVM_NUM_DEVICE_DB_ENTRIES;i++){
164     	// lookup entry
165     	le_device_db_entry_t entry;
166     	int ok = le_device_db_tlv_fetch(i, &entry);
167     	if (!ok) continue;
168     	// if valid, store entry_pos in entry_map
169     	entry_map[num_valid_entries++] = i;
170     }
171     log_info("num valid le device entries %u", num_valid_entries);
172 }
173 
174 // not used
175 void le_device_db_set_local_bd_addr(bd_addr_t bd_addr){
176     (void)bd_addr;
177 }
178 
179 // @returns number of device in db
180 int le_device_db_count(void){
181 	return num_valid_entries;
182 }
183 
184 void le_device_db_remove(int index){
185 
186 	// delete entry in TLV
187 	int entry_pos = entry_map[index];
188 	le_device_db_tlv_delete(entry_pos);
189 
190 	// shift all entries down by one
191 	int i;
192     for (i=index;i<NVM_NUM_DEVICE_DB_ENTRIES - 1;i++){
193     	entry_map[i] = entry_map[i+1];
194     }
195     entry_map[NVM_NUM_DEVICE_DB_ENTRIES-1] = 0;
196 
197     // keep track
198     num_valid_entries--;
199 }
200 
201 int le_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){
202 	// find unused entry in the used list
203     int i;
204     int index = -1;
205     int expected_index = 0;
206     int new_index = -1;
207     for (i=0;i<num_valid_entries;i++){
208          if (entry_map[i] == expected_index){
209          	expected_index++;
210          	continue;
211          }
212          index = i;
213          new_index = expected_index;
214          break;
215     }
216 
217     if (i == num_valid_entries && num_valid_entries < NVM_NUM_DEVICE_DB_ENTRIES){
218     	index = num_valid_entries;
219     	new_index = num_valid_entries;
220     }
221 
222     // no free entry found
223     if (index < 0) return -1;
224 
225     log_info("new entry pos %u used for index %u", index, new_index);
226 
227     // shift all entries up by one
228     for (i = NVM_NUM_DEVICE_DB_ENTRIES - 1; i > index; i--){
229     	entry_map[i] = entry_map[i-1];
230     }
231 
232     // set in entry_mape
233     entry_map[index] = new_index;
234 
235     // store entry at entry_pos = index
236 	le_device_db_entry_t entry;
237     log_info("LE Device DB adding type %u - %s", addr_type, bd_addr_to_str(addr));
238     log_info_key("irk", irk);
239 
240     entry.addr_type = addr_type;
241     memcpy(entry.addr, addr, 6);
242     memcpy(entry.irk, irk, 16);
243 #ifdef ENABLE_LE_SIGNED_WRITE
244     entry.remote_counter = 0;
245 #endif
246 
247     // store
248     le_device_db_tlv_store(index, &entry);
249 
250     // keep track
251     num_valid_entries++;
252 
253     return index;
254 }
255 
256 
257 // get device information: addr type and address
258 void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){
259 
260 	// fetch entry
261 	le_device_db_entry_t entry;
262 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
263 	if (!ok) return;
264 
265     if (addr_type) *addr_type = entry.addr_type;
266     if (addr) memcpy(addr, entry.addr, 6);
267     if (irk) memcpy(irk, entry.irk, 16);
268 }
269 
270 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){
271 
272 	// fetch entry
273 	le_device_db_entry_t entry;
274 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
275 	if (!ok) return;
276 
277 	// update
278     log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u",
279         index, ediv, key_size, authenticated, authorized);
280     entry.ediv = ediv;
281     if (rand) memcpy(entry.rand, rand, 8);
282     if (ltk) memcpy(entry.ltk, ltk, 16);
283     entry.key_size = key_size;
284     entry.authenticated = authenticated;
285     entry.authorized = authorized;
286 
287     // store
288     le_device_db_tlv_store_mapped(index, &entry);
289 }
290 
291 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){
292 
293 	// fetch entry
294 	le_device_db_entry_t entry;
295 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
296 	if (!ok) return;
297 
298 	// update user fields
299     log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
300         index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized);
301     if (ediv) *ediv = entry.ediv;
302     if (rand) memcpy(rand, entry.rand, 8);
303     if (ltk)  memcpy(ltk, entry.ltk, 16);
304     if (key_size) *key_size = entry.key_size;
305     if (authenticated) *authenticated = entry.authenticated;
306     if (authorized) *authorized = entry.authorized;
307 }
308 
309 #ifdef ENABLE_LE_SIGNED_WRITE
310 
311 // get signature key
312 void le_device_db_remote_csrk_get(int index, sm_key_t csrk){
313 
314 	// fetch entry
315 	le_device_db_entry_t entry;
316 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
317 	if (!ok) return;
318 
319     if (csrk) memcpy(csrk, entry.remote_csrk, 16);
320 }
321 
322 void le_device_db_remote_csrk_set(int index, sm_key_t csrk){
323 
324 	// fetch entry
325 	le_device_db_entry_t entry;
326 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
327 	if (!ok) return;
328 
329     if (!csrk) return;
330 
331     // update
332     memcpy(entry.remote_csrk, csrk, 16);
333 
334     // store
335     le_device_db_tlv_store_mapped(index, &entry);
336 }
337 
338 void le_device_db_local_csrk_get(int index, sm_key_t csrk){
339 
340 	// fetch entry
341 	le_device_db_entry_t entry;
342 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
343 	if (!ok) return;
344 
345     if (!csrk) return;
346 
347     // fill
348     memcpy(csrk, entry.local_csrk, 16);
349 }
350 
351 void le_device_db_local_csrk_set(int index, sm_key_t csrk){
352 
353 	// fetch entry
354 	le_device_db_entry_t entry;
355 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
356 	if (!ok) return;
357 
358     if (!csrk) return;
359 
360     // update
361     memcpy(entry.local_csrk, csrk, 16);
362 
363     // store
364     le_device_db_tlv_store_mapped(index, &entry);
365 }
366 
367 // query last used/seen signing counter
368 uint32_t le_device_db_remote_counter_get(int index){
369 
370 	// fetch entry
371 	le_device_db_entry_t entry;
372 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
373 	if (!ok) return 0;
374 
375     return entry.remote_counter;
376 }
377 
378 // update signing counter
379 void le_device_db_remote_counter_set(int index, uint32_t counter){
380 
381 	// fetch entry
382 	le_device_db_entry_t entry;
383 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
384 	if (!ok) return;
385 
386     entry.remote_counter = counter;
387 
388     // store
389     le_device_db_tlv_store_mapped(index, &entry);
390 }
391 
392 // query last used/seen signing counter
393 uint32_t le_device_db_local_counter_get(int index){
394 
395 	// fetch entry
396 	le_device_db_entry_t entry;
397 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
398 	if (!ok) return 0;
399 
400     return entry.local_counter;
401 }
402 
403 // update signing counter
404 void le_device_db_local_counter_set(int index, uint32_t counter){
405 
406 	// fetch entry
407 	le_device_db_entry_t entry;
408 	int ok = le_device_db_tlv_fetch_mapped(index, &entry);
409 	if (!ok) return;
410 
411 	// update
412     entry.local_counter = counter;
413 
414     // store
415     le_device_db_tlv_store_mapped(index, &entry);
416 }
417 
418 #endif
419 
420 void le_device_db_dump(void){
421     log_info("LE Device DB dump, devices: %d", le_device_db_count());
422     int i;
423     for (i=0;i<num_valid_entries;i++){
424 		// fetch entry
425 		le_device_db_entry_t entry;
426 		le_device_db_tlv_fetch_mapped(i, &entry);
427         log_info("%u: %u %s", i, entry.addr_type, bd_addr_to_str(entry.addr));
428         log_info_key("irk", entry.irk);
429 #ifdef ENABLE_LE_SIGNED_WRITE
430         log_info_key("local csrk", entry.local_csrk);
431         log_info_key("remote csrk", entry.remote_csrk);
432 #endif
433     }
434 }
435 
436 void le_device_db_tlv_configure(const btstack_tlv_t * btstack_tlv_impl, void * btstack_tlv_context){
437 	le_device_db_tlv_btstack_tlv_impl = btstack_tlv_impl;
438 	le_device_db_tlv_btstack_tlv_context = btstack_tlv_context;
439 }
440