Skip to content

Commit beb5632

Browse files
Add a new implementation of security db for KVStore
This works similar to filesystem db but uses the KVStore which it assumes is initialised. This is checked by open_db. On initialisation it either reads the present db or writes a new db into all entries thus guaranteeing that after the initialisation we will not run out of space for the keys and no extra error handling is needed.
1 parent f661ce0 commit beb5632

File tree

2 files changed

+639
-0
lines changed

2 files changed

+639
-0
lines changed
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2018 ARM Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#if BLE_SECURITY_DATABASE_KVSTORE
18+
19+
#ifndef GENERIC_KFSTORE_SECURITY_DB_H_
20+
#define GENERIC_KFSTORE_SECURITY_DB_H_
21+
22+
#include "SecurityDb.h"
23+
#include "kvstore_global_api.h"
24+
#include "mbed_error.h"
25+
26+
#define STR_EXPAND(tok) #tok
27+
#define STR(tok) STR_EXPAND(tok)
28+
29+
namespace ble {
30+
namespace generic {
31+
32+
/** Filesystem implementation */
33+
class KVStoreSecurityDb : public SecurityDb {
34+
private:
35+
36+
struct entry_t {
37+
SecurityDistributionFlags_t flags;
38+
sign_count_t peer_sign_counter;
39+
uint8_t index;
40+
};
41+
42+
static constexpr uint8_t KVSTORESECURITYDB_VERSION = 1;
43+
44+
static constexpr size_t DB_PREFIX_SIZE = 7 + sizeof (STR(MBED_CONF_STORAGE_DEFAULT_KV)) - 1;
45+
static constexpr size_t DB_KEY_SIZE = 3;
46+
static constexpr size_t DB_ENTRY_KEY_SIZE = 2;
47+
static constexpr size_t DB_FULL_KEY_SIZE = DB_PREFIX_SIZE + DB_KEY_SIZE + 1;
48+
49+
static constexpr char DB_PREFIX[DB_PREFIX_SIZE + 1] = { "/" STR(MBED_CONF_STORAGE_DEFAULT_KV) "/_ble_" };
50+
51+
static constexpr char DB_ENTRIES[DB_KEY_SIZE] = { 'e','n','t' };
52+
53+
static constexpr char DB_ENTRY_PEER_IDENTITY[DB_ENTRY_KEY_SIZE] = { 'i','d' };
54+
static constexpr char DB_ENTRY_LOCAL_KEYS[DB_ENTRY_KEY_SIZE] = { 'l','k' };
55+
static constexpr char DB_ENTRY_PEER_KEYS[DB_ENTRY_KEY_SIZE] = { 'p','k' };
56+
static constexpr char DB_ENTRY_PEER_SIGNING[DB_ENTRY_KEY_SIZE] = { 'p','s' };
57+
58+
static constexpr char DB_LOCAL_IDENTITY[DB_KEY_SIZE] = { 'l','i','d' };
59+
static constexpr char DB_LOCAL_CSRK[DB_KEY_SIZE] = { 'l','c','s' };
60+
static constexpr char DB_LOCAL_SIGN_COUNT[DB_KEY_SIZE] = { 'l','s','c' };
61+
62+
static constexpr char DB_VERSION[DB_KEY_SIZE] = { 'v','e','r' };
63+
static constexpr char DB_RESTORE[DB_KEY_SIZE] = { 'r','e','s' };
64+
65+
static entry_t* as_entry(entry_handle_t db_handle) {
66+
return reinterpret_cast<entry_t*>(db_handle);
67+
}
68+
69+
template<class T>
70+
static void db_read(T *value, const char* key) {
71+
char db_key[DB_FULL_KEY_SIZE];
72+
create_key(db_key, key);
73+
size_t size;
74+
const int ret = kv_get(db_key, value, sizeof(T), &size);
75+
(void)ret;//suppress unused var warning
76+
MBED_ASSERT(ret == MBED_SUCCESS && size == sizeof(T));
77+
}
78+
79+
template<class T>
80+
static void db_write(T *value, const char* key) {
81+
char db_key[DB_FULL_KEY_SIZE];
82+
create_key(db_key, key);
83+
const int ret = kv_set(db_key, value, sizeof(T), 0);
84+
(void)ret;//suppress unused var warning
85+
MBED_ASSERT(ret == MBED_SUCCESS);
86+
}
87+
88+
template<class T>
89+
static void db_write_entry(T *value, const char* key, uint8_t index) {
90+
char db_key[DB_FULL_KEY_SIZE];
91+
create_entry_key(db_key, key, index);
92+
const int ret = kv_set(db_key, value, sizeof(T), 0);
93+
(void)ret;//suppress unused var warning
94+
MBED_ASSERT(ret == MBED_SUCCESS);
95+
}
96+
97+
template<class T>
98+
static void db_read_entry(T *value, const char* key, uint8_t index) {
99+
char db_key[DB_FULL_KEY_SIZE];
100+
create_entry_key(db_key, key, index);
101+
size_t size;
102+
const int ret = kv_get(db_key, value, sizeof(T), &size);
103+
(void)ret;//suppress unused var warning
104+
MBED_ASSERT(ret == MBED_SUCCESS && size == sizeof(T));
105+
}
106+
107+
static void create_key(char* full_key, const char* key) {
108+
memcpy(full_key, DB_PREFIX, DB_PREFIX_SIZE);
109+
memcpy(full_key + DB_PREFIX_SIZE, key, DB_KEY_SIZE);
110+
full_key[DB_PREFIX_SIZE + DB_KEY_SIZE] = '\0';
111+
}
112+
113+
static void create_entry_key(char* full_key, const char* key, uint8_t index) {
114+
memcpy(full_key, DB_PREFIX, DB_PREFIX_SIZE);
115+
memcpy(full_key + DB_PREFIX_SIZE, key, DB_ENTRY_KEY_SIZE);
116+
full_key[DB_PREFIX_SIZE + DB_ENTRY_KEY_SIZE] = (char)('0' + index);
117+
full_key[DB_PREFIX_SIZE + DB_KEY_SIZE] = '\0';
118+
}
119+
120+
public:
121+
KVStoreSecurityDb();
122+
virtual ~KVStoreSecurityDb();
123+
124+
/**
125+
* Validates or creates a kvstore entry for the security database.
126+
* @return true if KVStore works
127+
*/
128+
static bool open_db();
129+
130+
virtual SecurityDistributionFlags_t* get_distribution_flags(
131+
entry_handle_t db_handle
132+
);
133+
134+
/* local keys */
135+
136+
/* set */
137+
138+
virtual void set_entry_local_ltk(
139+
entry_handle_t db_handle,
140+
const ltk_t &ltk
141+
);
142+
143+
virtual void set_entry_local_ediv_rand(
144+
entry_handle_t db_handle,
145+
const ediv_t &ediv,
146+
const rand_t &rand
147+
);
148+
149+
/* peer's keys */
150+
151+
/* set */
152+
153+
virtual void set_entry_peer_ltk(
154+
entry_handle_t db_handle,
155+
const ltk_t &ltk
156+
);
157+
158+
virtual void set_entry_peer_ediv_rand(
159+
entry_handle_t db_handle,
160+
const ediv_t &ediv,
161+
const rand_t &rand
162+
);
163+
164+
virtual void set_entry_peer_irk(
165+
entry_handle_t db_handle,
166+
const irk_t &irk
167+
);
168+
169+
virtual void set_entry_peer_bdaddr(
170+
entry_handle_t db_handle,
171+
bool address_is_public,
172+
const address_t &peer_address
173+
);
174+
175+
virtual void set_entry_peer_csrk(
176+
entry_handle_t db_handle,
177+
const csrk_t &csrk
178+
);
179+
180+
virtual void set_entry_peer_sign_counter(
181+
entry_handle_t db_handle,
182+
sign_count_t sign_counter
183+
);
184+
185+
/* local csrk and identity */
186+
187+
virtual void set_local_csrk(
188+
const csrk_t &csrk
189+
);
190+
191+
virtual void set_local_identity(
192+
const irk_t &irk,
193+
const address_t &identity_address,
194+
bool public_address
195+
);
196+
197+
/* I am not overriding set_local_sign_counter to avoid constant filesystem writes,
198+
* instead this is synced by sync (which is called on disconnection) */
199+
200+
/* saving and loading from nvm */
201+
202+
virtual void restore();
203+
204+
virtual void sync(entry_handle_t db_handle);
205+
206+
virtual void set_restore(bool reload);
207+
208+
private:
209+
virtual uint8_t get_entry_count();
210+
211+
virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index);
212+
213+
virtual void reset_entry(entry_handle_t db_handle);
214+
215+
virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle);
216+
virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle);
217+
virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle);
218+
virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle);
219+
220+
/**
221+
* Zero the db file.
222+
* @return true if KVStore works
223+
*/
224+
static bool erase_db();
225+
226+
private:
227+
entry_t _entries[BLE_SECURITY_DATABASE_MAX_ENTRIES];
228+
uint8_t _buffer[sizeof(SecurityEntryKeys_t)];
229+
};
230+
231+
} /* namespace pal */
232+
} /* namespace ble */
233+
234+
#endif /*GENERIC_KFSTORE_SECURITY_DB_H_*/
235+
236+
#endif /*BLE_SECURITY_DATABASE_KVSTORE*/

0 commit comments

Comments
 (0)