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