xref: /btstack/src/ble/le_device_db_tlv.c (revision 751da8891fe2e078b6c3ffba9837a1c44a95ae87)
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 static void le_device_db_tlv_scan(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 void le_device_db_init(void){
159 }
160 
161 // not used
162 void le_device_db_set_local_bd_addr(bd_addr_t bd_addr){
163     (void)bd_addr;
164 }
165 
166 // @returns number of device in db
167 int le_device_db_count(void){
168 	return num_valid_entries;
169 }
170 
171 void le_device_db_remove(int index){
172 	// delete entry in TLV
173 	le_device_db_tlv_delete(index);
174 
175 	// mark as unused
176     entry_map[index] = 0;
177 
178     // keep track
179     num_valid_entries--;
180 }
181 
182 int le_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){
183 	// find unused entry in the used list
184     int i;
185     int index = -1;
186     for (i=0;i<NVM_NUM_DEVICE_DB_ENTRIES;i++){
187          if (entry_map[i]) continue;
188          index = i;
189          break;
190     }
191 
192     // no free entry found
193     if (index < 0) return -1;
194 
195     log_info("new entry for index %u", index);
196 
197     // store entry at index
198 	le_device_db_entry_t entry;
199     log_info("LE Device DB adding type %u - %s", addr_type, bd_addr_to_str(addr));
200     log_info_key("irk", irk);
201 
202     entry.addr_type = addr_type;
203     memcpy(entry.addr, addr, 6);
204     memcpy(entry.irk, irk, 16);
205 #ifdef ENABLE_LE_SIGNED_WRITE
206     entry.remote_counter = 0;
207 #endif
208 
209     // store
210     le_device_db_tlv_store(index, &entry);
211 
212     // set in entry_mape
213     entry_map[index] = 1;
214 
215     // keep track
216     num_valid_entries++;
217 
218     return index;
219 }
220 
221 
222 // get device information: addr type and address
223 void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){
224 
225 	// fetch entry
226 	le_device_db_entry_t entry;
227 	int ok = le_device_db_tlv_fetch(index, &entry);
228 	if (!ok) return;
229 
230     if (addr_type) *addr_type = entry.addr_type;
231     if (addr) memcpy(addr, entry.addr, 6);
232     if (irk) memcpy(irk, entry.irk, 16);
233 }
234 
235 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){
236 
237 	// fetch entry
238 	le_device_db_entry_t entry;
239 	int ok = le_device_db_tlv_fetch(index, &entry);
240 	if (!ok) return;
241 
242 	// update
243     log_info("LE Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u",
244         index, ediv, key_size, authenticated, authorized);
245     entry.ediv = ediv;
246     if (rand) memcpy(entry.rand, rand, 8);
247     if (ltk) memcpy(entry.ltk, ltk, 16);
248     entry.key_size = key_size;
249     entry.authenticated = authenticated;
250     entry.authorized = authorized;
251 
252     // store
253     le_device_db_tlv_store(index, &entry);
254 }
255 
256 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){
257 
258 	// fetch entry
259 	le_device_db_entry_t entry;
260 	int ok = le_device_db_tlv_fetch(index, &entry);
261 	if (!ok) return;
262 
263 	// update user fields
264     log_info("LE Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
265         index, entry.ediv, entry.key_size, entry.authenticated, entry.authorized);
266     if (ediv) *ediv = entry.ediv;
267     if (rand) memcpy(rand, entry.rand, 8);
268     if (ltk)  memcpy(ltk, entry.ltk, 16);
269     if (key_size) *key_size = entry.key_size;
270     if (authenticated) *authenticated = entry.authenticated;
271     if (authorized) *authorized = entry.authorized;
272 }
273 
274 #ifdef ENABLE_LE_SIGNED_WRITE
275 
276 // get signature key
277 void le_device_db_remote_csrk_get(int index, sm_key_t csrk){
278 
279 	// fetch entry
280 	le_device_db_entry_t entry;
281 	int ok = le_device_db_tlv_fetch(index, &entry);
282 	if (!ok) return;
283 
284     if (csrk) memcpy(csrk, entry.remote_csrk, 16);
285 }
286 
287 void le_device_db_remote_csrk_set(int index, sm_key_t csrk){
288 
289 	// fetch entry
290 	le_device_db_entry_t entry;
291 	int ok = le_device_db_tlv_fetch(index, &entry);
292 	if (!ok) return;
293 
294     if (!csrk) return;
295 
296     // update
297     memcpy(entry.remote_csrk, csrk, 16);
298 
299     // store
300     le_device_db_tlv_store(index, &entry);
301 }
302 
303 void le_device_db_local_csrk_get(int index, sm_key_t csrk){
304 
305 	// fetch entry
306 	le_device_db_entry_t entry;
307 	int ok = le_device_db_tlv_fetch(index, &entry);
308 	if (!ok) return;
309 
310     if (!csrk) return;
311 
312     // fill
313     memcpy(csrk, entry.local_csrk, 16);
314 }
315 
316 void le_device_db_local_csrk_set(int index, sm_key_t csrk){
317 
318 	// fetch entry
319 	le_device_db_entry_t entry;
320 	int ok = le_device_db_tlv_fetch(index, &entry);
321 	if (!ok) return;
322 
323     if (!csrk) return;
324 
325     // update
326     memcpy(entry.local_csrk, csrk, 16);
327 
328     // store
329     le_device_db_tlv_store(index, &entry);
330 }
331 
332 // query last used/seen signing counter
333 uint32_t le_device_db_remote_counter_get(int index){
334 
335 	// fetch entry
336 	le_device_db_entry_t entry;
337 	int ok = le_device_db_tlv_fetch(index, &entry);
338 	if (!ok) return 0;
339 
340     return entry.remote_counter;
341 }
342 
343 // update signing counter
344 void le_device_db_remote_counter_set(int index, uint32_t counter){
345 
346 	// fetch entry
347 	le_device_db_entry_t entry;
348 	int ok = le_device_db_tlv_fetch(index, &entry);
349 	if (!ok) return;
350 
351     entry.remote_counter = counter;
352 
353     // store
354     le_device_db_tlv_store(index, &entry);
355 }
356 
357 // query last used/seen signing counter
358 uint32_t le_device_db_local_counter_get(int index){
359 
360 	// fetch entry
361 	le_device_db_entry_t entry;
362 	int ok = le_device_db_tlv_fetch(index, &entry);
363 	if (!ok) return 0;
364 
365     return entry.local_counter;
366 }
367 
368 // update signing counter
369 void le_device_db_local_counter_set(int index, uint32_t counter){
370 
371 	// fetch entry
372 	le_device_db_entry_t entry;
373 	int ok = le_device_db_tlv_fetch(index, &entry);
374 	if (!ok) return;
375 
376 	// update
377     entry.local_counter = counter;
378 
379     // store
380     le_device_db_tlv_store(index, &entry);
381 }
382 
383 #endif
384 
385 void le_device_db_dump(void){
386     log_info("LE Device DB dump, devices: %d", le_device_db_count());
387     uint32_t i;
388 
389     for (i=0;i<NVM_NUM_DEVICE_DB_ENTRIES;i++){
390         if (!entry_map[i]) continue;
391 		// fetch entry
392 		le_device_db_entry_t entry;
393 		le_device_db_tlv_fetch(i, &entry);
394         log_info("%u: %u %s", i, entry.addr_type, bd_addr_to_str(entry.addr));
395         log_info_key("irk", entry.irk);
396 #ifdef ENABLE_LE_SIGNED_WRITE
397         log_info_key("local csrk", entry.local_csrk);
398         log_info_key("remote csrk", entry.remote_csrk);
399 #endif
400     }
401 }
402 
403 void le_device_db_tlv_configure(const btstack_tlv_t * btstack_tlv_impl, void * btstack_tlv_context){
404 	le_device_db_tlv_btstack_tlv_impl = btstack_tlv_impl;
405 	le_device_db_tlv_btstack_tlv_context = btstack_tlv_context;
406     le_device_db_tlv_scan();
407 }
408