xref: /btstack/src/ble/le_device_db_tlv.c (revision e07b53a61840d4ca0866385b8fc553ed6dbd96aa)
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 // only stores if entry present
94 static uint8_t  entry_map[NVM_NUM_DEVICE_DB_ENTRIES];
95 static uint32_t num_valid_entries;
96 
97 static const btstack_tlv_t * le_device_db_tlv_btstack_tlv_impl;
98 static       void *          le_device_db_tlv_btstack_tlv_context;
99 
100 static const char tag_0 = 'B';
101 static const char tag_1 = 'T';
102 static const char tag_2 = 'D';
103 
104 static uint32_t le_device_db_tlv_tag_for_index(uint8_t index){
105     return (tag_0 << 24) | (tag_1 << 16) | (tag_2 << 8) | index;
106 }
107 
108 // @returns success
109 // @param index = entry_pos
110 static int le_device_db_tlv_fetch(int index, le_device_db_entry_t * entry){
111     if (index < 0 || index >= NVM_NUM_DEVICE_DB_ENTRIES){
112 	    log_error("le_device_db_tlv_fetch called with invalid index %d", index);
113 	    return 0;
114 	}
115     uint32_t tag = le_device_db_tlv_tag_for_index(index);
116     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));
117 	return size != 0;
118 }
119 
120 // @returns success
121 // @param index = entry_pos
122 static int le_device_db_tlv_store(int index, le_device_db_entry_t * entry){
123     if (index < 0 || index >= NVM_NUM_DEVICE_DB_ENTRIES){
124 	    log_error("le_device_db_tlv_store called with invalid index %d", index);
125 	    return 0;
126 	}
127     uint32_t tag = le_device_db_tlv_tag_for_index(index);
128     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));
129 	return 1;
130 }
131 
132 // @param index = entry_pos
133 static int le_device_db_tlv_delete(int index){
134     if (index < 0 || index >= NVM_NUM_DEVICE_DB_ENTRIES){
135 	    log_error("le_device_db_tlv_delete called with invalid index %d", index);
136 	    return 0;
137 	}
138     uint32_t tag = le_device_db_tlv_tag_for_index(index);
139     le_device_db_tlv_btstack_tlv_impl->delete_tag(le_device_db_tlv_btstack_tlv_context, tag);
140 	return 1;
141 }
142 
143 void le_device_db_init(void){
144     int i;
145 	num_valid_entries = 0;
146 	memset(entry_map, 0, sizeof(entry_map));
147     for (i=0;i<NVM_NUM_DEVICE_DB_ENTRIES;i++){
148     	// lookup entry
149     	le_device_db_entry_t entry;
150     	if (!le_device_db_tlv_fetch(i, &entry)) continue;
151 
152     	entry_map[i] = 1;
153         num_valid_entries++;
154     }
155     log_info("num valid le device entries %u", num_valid_entries);
156 }
157 
158 // not used
159 void le_device_db_set_local_bd_addr(bd_addr_t bd_addr){
160     (void)bd_addr;
161 }
162 
163 // @returns number of device in db
164 int le_device_db_count(void){
165 	return num_valid_entries;
166 }
167 
168 void le_device_db_remove(int index){
169 	// delete entry in TLV
170 	le_device_db_tlv_delete(index);
171 
172 	// mark as unused
173     entry_map[index] = 0;
174 
175     // keep track
176     num_valid_entries--;
177 }
178 
179 int le_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){
180 	// find unused entry in the used list
181     int i;
182     int index = -1;
183     for (i=0;i<NVM_NUM_DEVICE_DB_ENTRIES;i++){
184          if (entry_map[i]) continue;
185          index = i;
186          break;
187     }
188 
189     // no free entry found
190     if (index < 0) return -1;
191 
192     log_info("new entry for index %u", index);
193 
194     // store entry at index
195 	le_device_db_entry_t entry;
196     log_info("LE Device DB adding type %u - %s", addr_type, bd_addr_to_str(addr));
197     log_info_key("irk", irk);
198 
199     entry.addr_type = addr_type;
200     memcpy(entry.addr, addr, 6);
201     memcpy(entry.irk, irk, 16);
202 #ifdef ENABLE_LE_SIGNED_WRITE
203     entry.remote_counter = 0;
204 #endif
205 
206     // store
207     le_device_db_tlv_store(index, &entry);
208 
209     // set in entry_mape
210     entry_map[index] = 1;
211 
212     // keep track
213     num_valid_entries++;
214 
215     return index;
216 }
217 
218 
219 // get device information: addr type and address
220 void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){
221 
222 	// fetch entry
223 	le_device_db_entry_t entry;
224 	int ok = le_device_db_tlv_fetch(index, &entry);
225 	if (!ok) return;
226 
227     if (addr_type) *addr_type = entry.addr_type;
228     if (addr) memcpy(addr, entry.addr, 6);
229     if (irk) memcpy(irk, entry.irk, 16);
230 }
231 
232 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){
233 
234 	// fetch entry
235 	le_device_db_entry_t entry;
236 	int ok = le_device_db_tlv_fetch(index, &entry);
237 	if (!ok) return;
238 
239 	// update
240     log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u",
241         index, ediv, key_size, authenticated, authorized);
242     entry.ediv = ediv;
243     if (rand) memcpy(entry.rand, rand, 8);
244     if (ltk) memcpy(entry.ltk, ltk, 16);
245     entry.key_size = key_size;
246     entry.authenticated = authenticated;
247     entry.authorized = authorized;
248 
249     // store
250     le_device_db_tlv_store(index, &entry);
251 }
252 
253 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){
254 
255 	// fetch entry
256 	le_device_db_entry_t entry;
257 	int ok = le_device_db_tlv_fetch(index, &entry);
258 	if (!ok) return;
259 
260 	// update user fields
261     log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
262         index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized);
263     if (ediv) *ediv = entry.ediv;
264     if (rand) memcpy(rand, entry.rand, 8);
265     if (ltk)  memcpy(ltk, entry.ltk, 16);
266     if (key_size) *key_size = entry.key_size;
267     if (authenticated) *authenticated = entry.authenticated;
268     if (authorized) *authorized = entry.authorized;
269 }
270 
271 #ifdef ENABLE_LE_SIGNED_WRITE
272 
273 // get signature key
274 void le_device_db_remote_csrk_get(int index, sm_key_t csrk){
275 
276 	// fetch entry
277 	le_device_db_entry_t entry;
278 	int ok = le_device_db_tlv_fetch(index, &entry);
279 	if (!ok) return;
280 
281     if (csrk) memcpy(csrk, entry.remote_csrk, 16);
282 }
283 
284 void le_device_db_remote_csrk_set(int index, sm_key_t csrk){
285 
286 	// fetch entry
287 	le_device_db_entry_t entry;
288 	int ok = le_device_db_tlv_fetch(index, &entry);
289 	if (!ok) return;
290 
291     if (!csrk) return;
292 
293     // update
294     memcpy(entry.remote_csrk, csrk, 16);
295 
296     // store
297     le_device_db_tlv_store(index, &entry);
298 }
299 
300 void le_device_db_local_csrk_get(int index, sm_key_t csrk){
301 
302 	// fetch entry
303 	le_device_db_entry_t entry;
304 	int ok = le_device_db_tlv_fetch(index, &entry);
305 	if (!ok) return;
306 
307     if (!csrk) return;
308 
309     // fill
310     memcpy(csrk, entry.local_csrk, 16);
311 }
312 
313 void le_device_db_local_csrk_set(int index, sm_key_t csrk){
314 
315 	// fetch entry
316 	le_device_db_entry_t entry;
317 	int ok = le_device_db_tlv_fetch(index, &entry);
318 	if (!ok) return;
319 
320     if (!csrk) return;
321 
322     // update
323     memcpy(entry.local_csrk, csrk, 16);
324 
325     // store
326     le_device_db_tlv_store(index, &entry);
327 }
328 
329 // query last used/seen signing counter
330 uint32_t le_device_db_remote_counter_get(int index){
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 0;
336 
337     return entry.remote_counter;
338 }
339 
340 // update signing counter
341 void le_device_db_remote_counter_set(int index, uint32_t counter){
342 
343 	// fetch entry
344 	le_device_db_entry_t entry;
345 	int ok = le_device_db_tlv_fetch(index, &entry);
346 	if (!ok) return;
347 
348     entry.remote_counter = counter;
349 
350     // store
351     le_device_db_tlv_store(index, &entry);
352 }
353 
354 // query last used/seen signing counter
355 uint32_t le_device_db_local_counter_get(int index){
356 
357 	// fetch entry
358 	le_device_db_entry_t entry;
359 	int ok = le_device_db_tlv_fetch(index, &entry);
360 	if (!ok) return 0;
361 
362     return entry.local_counter;
363 }
364 
365 // update signing counter
366 void le_device_db_local_counter_set(int index, uint32_t counter){
367 
368 	// fetch entry
369 	le_device_db_entry_t entry;
370 	int ok = le_device_db_tlv_fetch(index, &entry);
371 	if (!ok) return;
372 
373 	// update
374     entry.local_counter = counter;
375 
376     // store
377     le_device_db_tlv_store(index, &entry);
378 }
379 
380 #endif
381 
382 void le_device_db_dump(void){
383     log_info("LE Device DB dump, devices: %d", le_device_db_count());
384     int i;
385     for (i=0;i<num_valid_entries;i++){
386 		// fetch entry
387 		le_device_db_entry_t entry;
388 		le_device_db_tlv_fetch(i, &entry);
389         log_info("%u: %u %s", i, entry.addr_type, bd_addr_to_str(entry.addr));
390         log_info_key("irk", entry.irk);
391 #ifdef ENABLE_LE_SIGNED_WRITE
392         log_info_key("local csrk", entry.local_csrk);
393         log_info_key("remote csrk", entry.remote_csrk);
394 #endif
395     }
396 }
397 
398 void le_device_db_tlv_configure(const btstack_tlv_t * btstack_tlv_impl, void * btstack_tlv_context){
399 	le_device_db_tlv_btstack_tlv_impl = btstack_tlv_impl;
400 	le_device_db_tlv_btstack_tlv_context = btstack_tlv_context;
401 }
402