Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
FileSecurityDb.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2018 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "FileSecurityDb.h" 00018 00019 namespace ble { 00020 namespace generic { 00021 00022 const uint16_t DB_VERSION = 1; 00023 00024 #define DB_STORE_OFFSET_FLAGS (0) 00025 #define DB_STORE_OFFSET_LOCAL_KEYS (DB_STORE_OFFSET_FLAGS + sizeof(SecurityDistributionFlags_t)) 00026 #define DB_STORE_OFFSET_PEER_KEYS (DB_STORE_OFFSET_LOCAL_KEYS + sizeof(SecurityEntryKeys_t)) 00027 #define DB_STORE_OFFSET_PEER_IDENTITY (DB_STORE_OFFSET_PEER_KEYS + sizeof(SecurityEntryKeys_t)) 00028 #define DB_STORE_OFFSET_PEER_SIGNING (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(SecurityEntryIdentity_t)) 00029 00030 #define DB_STORE_OFFSET_LOCAL_KEYS_LTK (DB_STORE_OFFSET_LOCAL_KEYS) 00031 #define DB_STORE_OFFSET_LOCAL_KEYS_EDIV (DB_STORE_OFFSET_LOCAL_KEYS_LTK + sizeof(ltk_t)) 00032 #define DB_STORE_OFFSET_LOCAL_KEYS_RAND (DB_STORE_OFFSET_LOCAL_KEYS_EDIV + sizeof(ediv_t)) 00033 00034 #define DB_STORE_OFFSET_PEER_KEYS_LTK (DB_STORE_OFFSET_PEER_KEYS) 00035 #define DB_STORE_OFFSET_PEER_KEYS_EDIV (DB_STORE_OFFSET_PEER_KEYS_LTK + sizeof(ltk_t)) 00036 #define DB_STORE_OFFSET_PEER_KEYS_RAND (DB_STORE_OFFSET_PEER_KEYS_EDIV + sizeof(ediv_t)) 00037 00038 #define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS (DB_STORE_OFFSET_PEER_IDENTITY) 00039 #define DB_STORE_OFFSET_PEER_IDENTITY_IRK (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(address_t)) 00040 #define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC (DB_STORE_OFFSET_PEER_IDENTITY_IRK + sizeof(irk_t)) 00041 00042 #define DB_STORE_OFFSET_PEER_SIGNING_COUNT (DB_STORE_OFFSET_PEER_SIGNING + sizeof(csrk_t)) 00043 00044 /* make size multiple of 4 */ 00045 #define PAD4(value) ((((value - 1) / 4) * 4) + 4) 00046 00047 #define DB_SIZE_STORE \ 00048 PAD4( \ 00049 sizeof(SecurityDistributionFlags_t) + \ 00050 sizeof(SecurityEntryKeys_t) + \ 00051 sizeof(SecurityEntryKeys_t) + \ 00052 sizeof(SecurityEntryIdentity_t) + \ 00053 sizeof(SecurityEntrySigning_t) \ 00054 ) 00055 00056 #define DB_SIZE_STORES \ 00057 (FileSecurityDb::MAX_ENTRIES * DB_SIZE_STORE) 00058 00059 #define DB_OFFSET_VERSION (0) 00060 #define DB_OFFSET_RESTORE (DB_OFFSET_VERSION + sizeof(DB_VERSION)) 00061 #define DB_OFFSET_LOCAL_IDENTITY (DB_OFFSET_RESTORE + sizeof(bool)) 00062 #define DB_OFFSET_LOCAL_CSRK (DB_OFFSET_LOCAL_IDENTITY + sizeof(SecurityEntryIdentity_t)) 00063 #define DB_OFFSET_LOCAL_SIGN_COUNT (DB_OFFSET_LOCAL_CSRK + sizeof(csrk_t)) 00064 #define DB_OFFSET_STORES (DB_OFFSET_LOCAL_SIGN_COUNT + sizeof(sign_count_t)) 00065 #define DB_OFFSET_MAX (DB_OFFSET_STORES + DB_SIZE_STORES) 00066 #define DB_SIZE PAD4(DB_OFFSET_MAX) 00067 00068 typedef SecurityDb::entry_handle_t entry_handle_t; 00069 00070 FileSecurityDb::FileSecurityDb(FILE *db_file) 00071 : SecurityDb(), 00072 _db_file(db_file) { 00073 /* init the offset in entries so they point to file positions */ 00074 for (size_t i = 0; i < get_entry_count(); i++) { 00075 _entries[i].file_offset = DB_OFFSET_STORES + i * DB_SIZE_STORE; 00076 } 00077 } 00078 00079 FileSecurityDb::~FileSecurityDb() { 00080 fclose(_db_file); 00081 } 00082 00083 FILE* FileSecurityDb::open_db_file(const char *db_path) { 00084 if (!db_path) { 00085 return NULL; 00086 } 00087 00088 /* try to open an existing file */ 00089 FILE *db_file = fopen(db_path, "rb+"); 00090 00091 if (!db_file) { 00092 /* file doesn't exist, create it */ 00093 db_file = fopen(db_path, "wb+"); 00094 } 00095 00096 if (!db_file) { 00097 /* failed to create a file, abort */ 00098 return NULL; 00099 } 00100 00101 /* we will check the db file and if the version or size doesn't match 00102 * what we expect we will blank it */ 00103 bool init = false; 00104 uint16_t version; 00105 00106 fseek(db_file, DB_OFFSET_VERSION, SEEK_SET); 00107 00108 if ((fread(&version, sizeof(version), 1, db_file) == 1) && 00109 (version == DB_VERSION)) { 00110 /* if file size differs from database size init the file */ 00111 fseek(db_file, 0, SEEK_END); 00112 if (ftell(db_file) != DB_SIZE) { 00113 init = true; 00114 } 00115 } else { 00116 init = true; 00117 } 00118 00119 if (init) { 00120 return erase_db_file(db_file); 00121 } 00122 00123 return db_file; 00124 } 00125 00126 FILE* FileSecurityDb::erase_db_file(FILE* db_file) { 00127 fseek(db_file, 0, SEEK_SET); 00128 00129 /* zero the file */ 00130 const uint32_t zero = 0; 00131 size_t count = DB_SIZE / 4; 00132 while (count--) { 00133 if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) { 00134 fclose(db_file); 00135 return NULL; 00136 } 00137 } 00138 00139 if (fflush(db_file)) { 00140 fclose(db_file); 00141 return NULL; 00142 } 00143 00144 return db_file; 00145 } 00146 00147 SecurityDistributionFlags_t* FileSecurityDb::get_distribution_flags( 00148 entry_handle_t db_handle 00149 ) { 00150 return reinterpret_cast<SecurityDistributionFlags_t*>(db_handle); 00151 } 00152 00153 /* local keys */ 00154 00155 /* set */ 00156 void FileSecurityDb::set_entry_local_ltk( 00157 entry_handle_t db_handle, 00158 const ltk_t <k 00159 ) { 00160 entry_t *entry = as_entry(db_handle); 00161 if (!entry) { 00162 return; 00163 } 00164 00165 entry->flags.ltk_sent = true; 00166 00167 db_write(<k, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK); 00168 } 00169 00170 void FileSecurityDb::set_entry_local_ediv_rand( 00171 entry_handle_t db_handle, 00172 const ediv_t &ediv, 00173 const rand_t &rand 00174 ) { 00175 entry_t *entry = as_entry(db_handle); 00176 if (!entry) { 00177 return; 00178 } 00179 00180 db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_EDIV); 00181 db_write(&rand, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_RAND); 00182 } 00183 00184 /* peer's keys */ 00185 00186 /* set */ 00187 00188 void FileSecurityDb::set_entry_peer_ltk( 00189 entry_handle_t db_handle, 00190 const ltk_t <k 00191 ) { 00192 entry_t *entry = as_entry(db_handle); 00193 if (!entry) { 00194 return; 00195 } 00196 00197 entry->flags.ltk_stored = true; 00198 00199 db_write(<k, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK); 00200 } 00201 00202 void FileSecurityDb::set_entry_peer_ediv_rand( 00203 entry_handle_t db_handle, 00204 const ediv_t &ediv, 00205 const rand_t &rand 00206 ) { 00207 entry_t *entry = as_entry(db_handle); 00208 if (!entry) { 00209 return; 00210 } 00211 00212 db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_EDIV); 00213 db_write(&rand, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_RAND); 00214 } 00215 00216 void FileSecurityDb::set_entry_peer_irk( 00217 entry_handle_t db_handle, 00218 const irk_t &irk 00219 ) { 00220 entry_t *entry = as_entry(db_handle); 00221 if (!entry) { 00222 return; 00223 } 00224 00225 entry->flags.irk_stored = true; 00226 00227 db_write(&irk, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_IRK); 00228 } 00229 00230 void FileSecurityDb::set_entry_peer_bdaddr( 00231 entry_handle_t db_handle, 00232 bool address_is_public, 00233 const address_t &peer_address 00234 ) { 00235 entry_t *entry = as_entry(db_handle); 00236 if (!entry) { 00237 return; 00238 } 00239 00240 db_write(&peer_address, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS); 00241 db_write(&address_is_public, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC); 00242 } 00243 00244 void FileSecurityDb::set_entry_peer_csrk( 00245 entry_handle_t db_handle, 00246 const csrk_t &csrk 00247 ) { 00248 entry_t *entry = as_entry(db_handle); 00249 if (!entry) { 00250 return; 00251 } 00252 00253 entry->flags.csrk_stored = true; 00254 00255 db_write(&csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING); 00256 } 00257 00258 void FileSecurityDb::set_entry_peer_sign_counter( 00259 entry_handle_t db_handle, 00260 sign_count_t sign_counter 00261 ) { 00262 entry_t *entry = as_entry(db_handle); 00263 if (entry) { 00264 entry->peer_sign_counter = sign_counter; 00265 } 00266 } 00267 00268 /* saving and loading from nvm */ 00269 00270 void FileSecurityDb::restore() { 00271 /* restore if requested */ 00272 bool restore_toggle = false; 00273 db_read(&restore_toggle, DB_OFFSET_RESTORE); 00274 00275 if (!restore_toggle) { 00276 erase_db_file(_db_file); 00277 00278 db_write(&DB_VERSION, DB_OFFSET_VERSION); 00279 return; 00280 } 00281 00282 db_read(&_local_identity, DB_OFFSET_LOCAL_IDENTITY); 00283 db_read(&_local_csrk, DB_OFFSET_LOCAL_CSRK); 00284 db_read(&_local_sign_counter, DB_OFFSET_LOCAL_SIGN_COUNT); 00285 00286 /* read flags and sign counters */ 00287 for (size_t i = 0; i < get_entry_count(); i++) { 00288 db_read(&_entries[i].flags, _entries[i].file_offset + DB_STORE_OFFSET_FLAGS); 00289 db_read(&_entries[i].peer_sign_counter, _entries[i].file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT); 00290 } 00291 00292 } 00293 00294 void FileSecurityDb::sync(entry_handle_t db_handle) { 00295 entry_t *entry = as_entry(db_handle); 00296 if (!entry) { 00297 return; 00298 } 00299 00300 db_write(&entry->peer_sign_counter, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT); 00301 db_write(&entry->flags, entry->file_offset + DB_STORE_OFFSET_FLAGS); 00302 } 00303 00304 void FileSecurityDb::set_restore(bool reload) { 00305 db_write(&reload, DB_OFFSET_RESTORE); 00306 } 00307 00308 /* helper functions */ 00309 00310 uint8_t FileSecurityDb::get_entry_count() { 00311 return MAX_ENTRIES; 00312 } 00313 00314 SecurityDistributionFlags_t* FileSecurityDb::get_entry_handle_by_index(uint8_t index) { 00315 if (index < MAX_ENTRIES) { 00316 return &_entries[index].flags; 00317 } else { 00318 return NULL; 00319 } 00320 } 00321 00322 void FileSecurityDb::reset_entry(entry_handle_t db_entry) { 00323 entry_t *entry = as_entry(db_entry); 00324 if (!entry) { 00325 return; 00326 } 00327 00328 fseek(_db_file, entry->file_offset, SEEK_SET); 00329 const uint32_t zero = 0; 00330 size_t count = DB_SIZE_STORE / 4; 00331 while (count--) { 00332 fwrite(&zero, sizeof(zero), 1, _db_file); 00333 } 00334 00335 entry->flags = SecurityDistributionFlags_t(); 00336 entry->peer_sign_counter = 0; 00337 } 00338 00339 SecurityEntryIdentity_t* FileSecurityDb::read_in_entry_peer_identity(entry_handle_t db_entry) { 00340 entry_t *entry = as_entry(db_entry); 00341 if (!entry) { 00342 return NULL; 00343 } 00344 00345 SecurityEntryIdentity_t* identity = reinterpret_cast<SecurityEntryIdentity_t*>(_buffer); 00346 db_read(identity, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY); 00347 00348 return identity; 00349 }; 00350 00351 SecurityEntryKeys_t* FileSecurityDb::read_in_entry_peer_keys(entry_handle_t db_entry) { 00352 entry_t *entry = as_entry(db_entry); 00353 if (!entry) { 00354 return NULL; 00355 } 00356 00357 SecurityEntryKeys_t* keys = reinterpret_cast<SecurityEntryKeys_t*>(_buffer); 00358 db_read(keys, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS); 00359 00360 return keys; 00361 }; 00362 00363 SecurityEntryKeys_t* FileSecurityDb::read_in_entry_local_keys(entry_handle_t db_entry) { 00364 entry_t *entry = as_entry(db_entry); 00365 if (!entry) { 00366 return NULL; 00367 } 00368 00369 SecurityEntryKeys_t* keys = reinterpret_cast<SecurityEntryKeys_t*>(_buffer); 00370 db_read(keys, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS); 00371 00372 return keys; 00373 }; 00374 00375 SecurityEntrySigning_t* FileSecurityDb::read_in_entry_peer_signing(entry_handle_t db_entry) { 00376 entry_t *entry = as_entry(db_entry); 00377 if (!entry) { 00378 return NULL; 00379 } 00380 00381 /* only read in the csrk */ 00382 csrk_t* csrk = reinterpret_cast<csrk_t*>(_buffer); 00383 db_read(csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING); 00384 00385 00386 /* use the counter held in memory */ 00387 SecurityEntrySigning_t* signing = reinterpret_cast<SecurityEntrySigning_t*>(_buffer); 00388 signing->counter = entry->peer_sign_counter; 00389 00390 return signing; 00391 }; 00392 00393 } /* namespace pal */ 00394 } /* namespace ble */
Generated on Tue Jul 12 2022 12:44:05 by
