xref: /btstack/src/ble/le_device_db_memory.c (revision 3deb3ec68039c68a16974dffc53343233662f909)
1*3deb3ec6SMatthias Ringwald /*
2*3deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*3deb3ec6SMatthias Ringwald  *
4*3deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*3deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*3deb3ec6SMatthias Ringwald  * are met:
7*3deb3ec6SMatthias Ringwald  *
8*3deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*3deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*3deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*3deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*3deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*3deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*3deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*3deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
16*3deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*3deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*3deb3ec6SMatthias Ringwald  *    monetary gain.
19*3deb3ec6SMatthias Ringwald  *
20*3deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*3deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*3deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*3deb3ec6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*3deb3ec6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*3deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*3deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*3deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*3deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*3deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*3deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*3deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
32*3deb3ec6SMatthias Ringwald  *
33*3deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
34*3deb3ec6SMatthias Ringwald  * [email protected]
35*3deb3ec6SMatthias Ringwald  *
36*3deb3ec6SMatthias Ringwald  */
37*3deb3ec6SMatthias Ringwald 
38*3deb3ec6SMatthias Ringwald #include "le_device_db.h"
39*3deb3ec6SMatthias Ringwald 
40*3deb3ec6SMatthias Ringwald #include <stdio.h>
41*3deb3ec6SMatthias Ringwald #include <string.h>
42*3deb3ec6SMatthias Ringwald #include "debug.h"
43*3deb3ec6SMatthias Ringwald 
44*3deb3ec6SMatthias Ringwald // Central Device db implemenation using static memory
45*3deb3ec6SMatthias Ringwald typedef struct le_device_memory_db {
46*3deb3ec6SMatthias Ringwald 
47*3deb3ec6SMatthias Ringwald     // Identification
48*3deb3ec6SMatthias Ringwald     int addr_type;
49*3deb3ec6SMatthias Ringwald     bd_addr_t addr;
50*3deb3ec6SMatthias Ringwald     sm_key_t irk;
51*3deb3ec6SMatthias Ringwald 
52*3deb3ec6SMatthias Ringwald     // Stored pairing information allows to re-establish an enncrypted connection
53*3deb3ec6SMatthias Ringwald     // with a peripheral that doesn't have any persistent memory
54*3deb3ec6SMatthias Ringwald     sm_key_t ltk;
55*3deb3ec6SMatthias Ringwald     uint16_t ediv;
56*3deb3ec6SMatthias Ringwald     uint8_t  rand[8];
57*3deb3ec6SMatthias Ringwald     uint8_t  key_size;
58*3deb3ec6SMatthias Ringwald     uint8_t  authenticated;
59*3deb3ec6SMatthias Ringwald     uint8_t  authorized;
60*3deb3ec6SMatthias Ringwald 
61*3deb3ec6SMatthias Ringwald     // Signed Writes by remote
62*3deb3ec6SMatthias Ringwald     sm_key_t remote_csrk;
63*3deb3ec6SMatthias Ringwald     uint32_t remote_counter;
64*3deb3ec6SMatthias Ringwald 
65*3deb3ec6SMatthias Ringwald     // Signed Writes by us
66*3deb3ec6SMatthias Ringwald     sm_key_t local_csrk;
67*3deb3ec6SMatthias Ringwald     uint32_t local_counter;
68*3deb3ec6SMatthias Ringwald 
69*3deb3ec6SMatthias Ringwald } le_device_memory_db_t;
70*3deb3ec6SMatthias Ringwald 
71*3deb3ec6SMatthias Ringwald #define LE_DEVICE_MEMORY_SIZE 4
72*3deb3ec6SMatthias Ringwald #define INVALID_ENTRY_ADDR_TYPE 0xff
73*3deb3ec6SMatthias Ringwald 
74*3deb3ec6SMatthias Ringwald static le_device_memory_db_t le_devices[LE_DEVICE_MEMORY_SIZE];
75*3deb3ec6SMatthias Ringwald 
76*3deb3ec6SMatthias Ringwald void le_device_db_init(void){
77*3deb3ec6SMatthias Ringwald     int i;
78*3deb3ec6SMatthias Ringwald     for (i=0;i<LE_DEVICE_MEMORY_SIZE;i++){
79*3deb3ec6SMatthias Ringwald         le_device_db_remove(i);
80*3deb3ec6SMatthias Ringwald     }
81*3deb3ec6SMatthias Ringwald }
82*3deb3ec6SMatthias Ringwald 
83*3deb3ec6SMatthias Ringwald // @returns number of device in db
84*3deb3ec6SMatthias Ringwald int le_device_db_count(void){
85*3deb3ec6SMatthias Ringwald     int i;
86*3deb3ec6SMatthias Ringwald     int counter = 0;
87*3deb3ec6SMatthias Ringwald     for (i=0;i<LE_DEVICE_MEMORY_SIZE;i++){
88*3deb3ec6SMatthias Ringwald         if (le_devices[i].addr_type != INVALID_ENTRY_ADDR_TYPE) counter++;
89*3deb3ec6SMatthias Ringwald     }
90*3deb3ec6SMatthias Ringwald     return counter;
91*3deb3ec6SMatthias Ringwald }
92*3deb3ec6SMatthias Ringwald 
93*3deb3ec6SMatthias Ringwald // free device
94*3deb3ec6SMatthias Ringwald void le_device_db_remove(int index){
95*3deb3ec6SMatthias Ringwald     le_devices[index].addr_type = INVALID_ENTRY_ADDR_TYPE;
96*3deb3ec6SMatthias Ringwald }
97*3deb3ec6SMatthias Ringwald 
98*3deb3ec6SMatthias Ringwald int le_device_db_add(int addr_type, bd_addr_t addr, sm_key_t irk){
99*3deb3ec6SMatthias Ringwald     int i;
100*3deb3ec6SMatthias Ringwald     int index = -1;
101*3deb3ec6SMatthias Ringwald     for (i=0;i<LE_DEVICE_MEMORY_SIZE;i++){
102*3deb3ec6SMatthias Ringwald          if (le_devices[i].addr_type == INVALID_ENTRY_ADDR_TYPE){
103*3deb3ec6SMatthias Ringwald             index = i;
104*3deb3ec6SMatthias Ringwald             break;
105*3deb3ec6SMatthias Ringwald          }
106*3deb3ec6SMatthias Ringwald     }
107*3deb3ec6SMatthias Ringwald 
108*3deb3ec6SMatthias Ringwald     if (index < 0) return -1;
109*3deb3ec6SMatthias Ringwald 
110*3deb3ec6SMatthias Ringwald     log_info("Central Device DB adding type %u - %s", addr_type, bd_addr_to_str(addr));
111*3deb3ec6SMatthias Ringwald     log_key("irk", irk);
112*3deb3ec6SMatthias Ringwald 
113*3deb3ec6SMatthias Ringwald     le_devices[index].addr_type = addr_type;
114*3deb3ec6SMatthias Ringwald     memcpy(le_devices[index].addr, addr, 6);
115*3deb3ec6SMatthias Ringwald     memcpy(le_devices[index].irk, irk, 16);
116*3deb3ec6SMatthias Ringwald     le_devices[index].remote_counter = 0;
117*3deb3ec6SMatthias Ringwald 
118*3deb3ec6SMatthias Ringwald     return index;
119*3deb3ec6SMatthias Ringwald }
120*3deb3ec6SMatthias Ringwald 
121*3deb3ec6SMatthias Ringwald 
122*3deb3ec6SMatthias Ringwald // get device information: addr type and address
123*3deb3ec6SMatthias Ringwald void le_device_db_info(int index, int * addr_type, bd_addr_t addr, sm_key_t irk){
124*3deb3ec6SMatthias Ringwald     if (addr_type) *addr_type = le_devices[index].addr_type;
125*3deb3ec6SMatthias Ringwald     if (addr) memcpy(addr, le_devices[index].addr, 6);
126*3deb3ec6SMatthias Ringwald     if (irk) memcpy(irk, le_devices[index].irk, 16);
127*3deb3ec6SMatthias Ringwald }
128*3deb3ec6SMatthias Ringwald 
129*3deb3ec6SMatthias 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){
130*3deb3ec6SMatthias Ringwald     log_info("Central Device DB set encryption for %u, ediv x%04x, key size %u, authenticated %u, authorized %u",
131*3deb3ec6SMatthias Ringwald         index, ediv, key_size, authenticated, authorized);
132*3deb3ec6SMatthias Ringwald     le_device_memory_db_t * device = &le_devices[index];
133*3deb3ec6SMatthias Ringwald     device->ediv = ediv;
134*3deb3ec6SMatthias Ringwald     if (rand) memcpy(device->rand, rand, 8);
135*3deb3ec6SMatthias Ringwald     if (ltk) memcpy(device->ltk, ltk, 16);
136*3deb3ec6SMatthias Ringwald     device->key_size = key_size;
137*3deb3ec6SMatthias Ringwald     device->authenticated = authenticated;
138*3deb3ec6SMatthias Ringwald     device->authorized = authorized;
139*3deb3ec6SMatthias Ringwald }
140*3deb3ec6SMatthias Ringwald 
141*3deb3ec6SMatthias 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){
142*3deb3ec6SMatthias Ringwald     le_device_memory_db_t * device = &le_devices[index];
143*3deb3ec6SMatthias Ringwald     log_info("Central Device DB encryption for %u, ediv x%04x, keysize %u, authenticated %u, authorized %u",
144*3deb3ec6SMatthias Ringwald         index, device->ediv, device->key_size, device->authenticated, device->authorized);
145*3deb3ec6SMatthias Ringwald     if (ediv) *ediv = device->ediv;
146*3deb3ec6SMatthias Ringwald     if (rand) memcpy(rand, device->rand, 8);
147*3deb3ec6SMatthias Ringwald     if (ltk)  memcpy(ltk, device->ltk, 16);
148*3deb3ec6SMatthias Ringwald     if (key_size) *key_size = device->key_size;
149*3deb3ec6SMatthias Ringwald     if (authenticated) *authenticated = device->authenticated;
150*3deb3ec6SMatthias Ringwald     if (authorized) *authorized = device->authorized;
151*3deb3ec6SMatthias Ringwald }
152*3deb3ec6SMatthias Ringwald 
153*3deb3ec6SMatthias Ringwald // get signature key
154*3deb3ec6SMatthias Ringwald void le_device_db_remote_csrk_get(int index, sm_key_t csrk){
155*3deb3ec6SMatthias Ringwald     if (index < 0 || index >= LE_DEVICE_MEMORY_SIZE){
156*3deb3ec6SMatthias Ringwald         log_error("le_device_db_remote_csrk_get called with invalid index %d", index);
157*3deb3ec6SMatthias Ringwald         return;
158*3deb3ec6SMatthias Ringwald     }
159*3deb3ec6SMatthias Ringwald     if (csrk) memcpy(csrk, le_devices[index].remote_csrk, 16);
160*3deb3ec6SMatthias Ringwald }
161*3deb3ec6SMatthias Ringwald 
162*3deb3ec6SMatthias Ringwald void le_device_db_remote_csrk_set(int index, sm_key_t csrk){
163*3deb3ec6SMatthias Ringwald     if (index < 0 || index >= LE_DEVICE_MEMORY_SIZE){
164*3deb3ec6SMatthias Ringwald         log_error("le_device_db_remote_csrk_set called with invalid index %d", index);
165*3deb3ec6SMatthias Ringwald         return;
166*3deb3ec6SMatthias Ringwald     }
167*3deb3ec6SMatthias Ringwald     if (csrk) memcpy(le_devices[index].remote_csrk, csrk, 16);
168*3deb3ec6SMatthias Ringwald }
169*3deb3ec6SMatthias Ringwald 
170*3deb3ec6SMatthias Ringwald void le_device_db_local_csrk_get(int index, sm_key_t csrk){
171*3deb3ec6SMatthias Ringwald     if (index < 0 || index >= LE_DEVICE_MEMORY_SIZE){
172*3deb3ec6SMatthias Ringwald         log_error("le_device_db_local_csrk_get called with invalid index %d", index);
173*3deb3ec6SMatthias Ringwald         return;
174*3deb3ec6SMatthias Ringwald     }
175*3deb3ec6SMatthias Ringwald     if (csrk) memcpy(csrk, le_devices[index].local_csrk, 16);
176*3deb3ec6SMatthias Ringwald }
177*3deb3ec6SMatthias Ringwald 
178*3deb3ec6SMatthias Ringwald void le_device_db_local_csrk_set(int index, sm_key_t csrk){
179*3deb3ec6SMatthias Ringwald     if (index < 0 || index >= LE_DEVICE_MEMORY_SIZE){
180*3deb3ec6SMatthias Ringwald         log_error("le_device_db_local_csrk_set called with invalid index %d", index);
181*3deb3ec6SMatthias Ringwald         return;
182*3deb3ec6SMatthias Ringwald     }
183*3deb3ec6SMatthias Ringwald     if (csrk) memcpy(le_devices[index].local_csrk, csrk, 16);
184*3deb3ec6SMatthias Ringwald }
185*3deb3ec6SMatthias Ringwald 
186*3deb3ec6SMatthias Ringwald // query last used/seen signing counter
187*3deb3ec6SMatthias Ringwald uint32_t le_device_db_remote_counter_get(int index){
188*3deb3ec6SMatthias Ringwald     return le_devices[index].remote_counter;
189*3deb3ec6SMatthias Ringwald }
190*3deb3ec6SMatthias Ringwald 
191*3deb3ec6SMatthias Ringwald // update signing counter
192*3deb3ec6SMatthias Ringwald void le_device_db_remote_counter_set(int index, uint32_t counter){
193*3deb3ec6SMatthias Ringwald     le_devices[index].remote_counter = counter;
194*3deb3ec6SMatthias Ringwald }
195*3deb3ec6SMatthias Ringwald 
196*3deb3ec6SMatthias Ringwald // query last used/seen signing counter
197*3deb3ec6SMatthias Ringwald uint32_t le_device_db_local_counter_get(int index){
198*3deb3ec6SMatthias Ringwald     return le_devices[index].local_counter;
199*3deb3ec6SMatthias Ringwald }
200*3deb3ec6SMatthias Ringwald 
201*3deb3ec6SMatthias Ringwald // update signing counter
202*3deb3ec6SMatthias Ringwald void le_device_db_local_counter_set(int index, uint32_t counter){
203*3deb3ec6SMatthias Ringwald     le_devices[index].local_counter = counter;
204*3deb3ec6SMatthias Ringwald }
205*3deb3ec6SMatthias Ringwald 
206*3deb3ec6SMatthias Ringwald void le_device_db_dump(void){
207*3deb3ec6SMatthias Ringwald     log_info("Central Device DB dump, devices: %d", le_device_db_count());
208*3deb3ec6SMatthias Ringwald     int i;
209*3deb3ec6SMatthias Ringwald     for (i=0;i<LE_DEVICE_MEMORY_SIZE;i++){
210*3deb3ec6SMatthias Ringwald         if (le_devices[i].addr_type == INVALID_ENTRY_ADDR_TYPE) continue;
211*3deb3ec6SMatthias Ringwald         log_info("%u: %u %s", i, le_devices[i].addr_type, bd_addr_to_str(le_devices[i].addr));
212*3deb3ec6SMatthias Ringwald         log_key("irk", le_devices[i].irk);
213*3deb3ec6SMatthias Ringwald         log_key("local csrk", le_devices[i].local_csrk);
214*3deb3ec6SMatthias Ringwald         log_key("remote csrk", le_devices[i].remote_csrk);
215*3deb3ec6SMatthias Ringwald     }
216*3deb3ec6SMatthias Ringwald }
217