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