mirror of https://github.com/ARMmbed/mbed-os.git
moved logic to security db and left storage in memory and file dbs
db created at init nowpull/6932/head
parent
678d494c5a
commit
a63f38e767
|
@ -428,7 +428,7 @@ public:
|
||||||
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
||||||
const Passkey_t passkey = NULL,
|
const Passkey_t passkey = NULL,
|
||||||
bool signing = true,
|
bool signing = true,
|
||||||
const uint8_t *dbPath = NULL) {
|
const char *dbPath = NULL) {
|
||||||
/* Avoid compiler warnings about unused variables. */
|
/* Avoid compiler warnings about unused variables. */
|
||||||
(void)enableBonding;
|
(void)enableBonding;
|
||||||
(void)requireMITM;
|
(void)requireMITM;
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2018 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GENERIC_FILE_SECURITY_DB_H_
|
||||||
|
#define GENERIC_FILE_SECURITY_DB_H_
|
||||||
|
|
||||||
|
#include "SecurityDb.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
namespace ble {
|
||||||
|
namespace generic {
|
||||||
|
|
||||||
|
/** Filesystem implementation */
|
||||||
|
class FileSecurityDb : public SecurityDb {
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct entry_t {
|
||||||
|
SecurityDistributionFlags_t flags;
|
||||||
|
sign_count_t peer_sign_counter;
|
||||||
|
size_t file_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t MAX_ENTRIES = 5;
|
||||||
|
|
||||||
|
static entry_t* as_entry(entry_handle_t db_handle)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<entry_t*>(db_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileSecurityDb(FILE *db_file);
|
||||||
|
virtual ~FileSecurityDb();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates or creates a file for the security database.
|
||||||
|
* @param db_path path to the file
|
||||||
|
* @return FILE handle open and ready for use by the database or NULL if unavailable
|
||||||
|
*/
|
||||||
|
static FILE* open_db_file(const char *db_path);
|
||||||
|
|
||||||
|
virtual SecurityDistributionFlags_t* get_distribution_flags(
|
||||||
|
entry_handle_t db_handle
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/* local keys */
|
||||||
|
|
||||||
|
/* set */
|
||||||
|
virtual void set_entry_local_ltk(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const ltk_t <k
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual void set_entry_local_ediv_rand(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const ediv_t &ediv,
|
||||||
|
const rand_t &rand
|
||||||
|
);
|
||||||
|
|
||||||
|
/* peer's keys */
|
||||||
|
|
||||||
|
/* set */
|
||||||
|
|
||||||
|
virtual void set_entry_peer_ltk(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const ltk_t <k
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual void set_entry_peer_ediv_rand(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const ediv_t &ediv,
|
||||||
|
const rand_t &rand
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual void set_entry_peer_irk(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const irk_t &irk
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual void set_entry_peer_bdaddr(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
bool address_is_public,
|
||||||
|
const address_t &peer_address
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual void set_entry_peer_csrk(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const csrk_t &csrk
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual void set_entry_peer_sign_counter(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
sign_count_t sign_counter
|
||||||
|
);
|
||||||
|
|
||||||
|
/* saving and loading from nvm */
|
||||||
|
|
||||||
|
virtual void restore();
|
||||||
|
|
||||||
|
virtual void sync();
|
||||||
|
|
||||||
|
virtual void set_restore(bool reload);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual uint8_t get_entry_count();
|
||||||
|
|
||||||
|
virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index);
|
||||||
|
|
||||||
|
virtual void reset_entry(entry_handle_t db_handle);
|
||||||
|
|
||||||
|
virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle);
|
||||||
|
virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle);
|
||||||
|
virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle);
|
||||||
|
virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
entry_t _entries[MAX_ENTRIES];
|
||||||
|
FILE *_db_file;
|
||||||
|
static uint8_t _buffer[sizeof(SecurityEntryKeys_t)];
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace pal */
|
||||||
|
} /* namespace ble */
|
||||||
|
|
||||||
|
#endif /*GENERIC_FILE_SECURITY_DB_H_*/
|
|
@ -50,7 +50,7 @@ public:
|
||||||
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
||||||
const Passkey_t passkey = NULL,
|
const Passkey_t passkey = NULL,
|
||||||
bool signing = true,
|
bool signing = true,
|
||||||
const uint8_t* db_path = NULL
|
const char* db_path = NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
virtual ble_error_t reset();
|
virtual ble_error_t reset();
|
||||||
|
@ -329,24 +329,22 @@ private:
|
||||||
* Returns the CSRK for the connection. Called by the security db.
|
* Returns the CSRK for the connection. Called by the security db.
|
||||||
*
|
*
|
||||||
* @param[in] connectionHandle Handle to identify the connection.
|
* @param[in] connectionHandle Handle to identify the connection.
|
||||||
* @param[in] csrk connection signature resolving key.
|
* @param[in] signing connection signature resolving key and counter.
|
||||||
*/
|
*/
|
||||||
void return_csrk_cb(
|
void return_csrk_cb(
|
||||||
SecurityDb::entry_handle_t connection,
|
SecurityDb::entry_handle_t connection,
|
||||||
const csrk_t *csrk,
|
const SecurityEntrySigning_t *signing
|
||||||
sign_count_t sign_counter
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the peer CSRK for the connection. Called by the security db.
|
* Set the peer CSRK for the connection. Called by the security db.
|
||||||
*
|
*
|
||||||
* @param[in] connectionHandle Handle to identify the connection.
|
* @param[in] connectionHandle Handle to identify the connection.
|
||||||
* @param[in] csrk connection signature resolving key.
|
* @param[in] signing connection signature resolving key and counter.
|
||||||
*/
|
*/
|
||||||
void set_peer_csrk_cb(
|
void set_peer_csrk_cb(
|
||||||
SecurityDb::entry_handle_t connection,
|
SecurityDb::entry_handle_t connection,
|
||||||
const csrk_t *csrk,
|
const SecurityEntrySigning_t *signing
|
||||||
sign_count_t sign_counter
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PAL_MEMORY_SECURITY_DB_H_
|
#ifndef GENERIC_MEMORY_SECURITY_DB_H_
|
||||||
#define PAL_MEMORY_SECURITY_DB_H_
|
#define GENERIC_MEMORY_SECURITY_DB_H_
|
||||||
|
|
||||||
#include "SecurityDb.h"
|
#include "SecurityDb.h"
|
||||||
|
|
||||||
|
@ -25,121 +25,54 @@ namespace generic {
|
||||||
/** Naive memory implementation for verification. */
|
/** Naive memory implementation for verification. */
|
||||||
class MemorySecurityDb : public SecurityDb {
|
class MemorySecurityDb : public SecurityDb {
|
||||||
private:
|
private:
|
||||||
enum state_t {
|
struct entry_t {
|
||||||
ENTRY_FREE,
|
entry_t() : peer_sign_counter(0) { };
|
||||||
ENTRY_RESERVED,
|
SecurityDistributionFlags_t flags;
|
||||||
ENTRY_WRITTEN,
|
SecurityEntryKeys_t local_keys;
|
||||||
ENTRY_DISCONNECTED
|
SecurityEntryKeys_t peer_keys;
|
||||||
|
SecurityEntryIdentity_t peer_identity;
|
||||||
|
SecurityEntrySigning_t peer_signing;
|
||||||
|
sign_count_t peer_sign_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct entry_t {
|
|
||||||
entry_t() : sign_counter(0), state(ENTRY_FREE) { };
|
|
||||||
SecurityDistributionFlags_t flags;
|
|
||||||
SecurityEntryKeys_t peer_keys;
|
|
||||||
SecurityEntryKeys_t local_keys;
|
|
||||||
SecurityEntryIdentity_t peer_identity;
|
|
||||||
csrk_t csrk;
|
|
||||||
sign_count_t sign_counter;
|
|
||||||
state_t state;
|
|
||||||
};
|
|
||||||
static const size_t MAX_ENTRIES = 5;
|
static const size_t MAX_ENTRIES = 5;
|
||||||
|
|
||||||
static entry_t* as_entry(entry_handle_t entry_handle)
|
static entry_t* as_entry(entry_handle_t db_handle)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<entry_t*>(entry_handle);
|
return reinterpret_cast<entry_t*>(db_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MemorySecurityDb() : _local_sign_counter(0) { }
|
MemorySecurityDb() : SecurityDb() { }
|
||||||
virtual ~MemorySecurityDb() { }
|
virtual ~MemorySecurityDb() { }
|
||||||
|
|
||||||
virtual const SecurityDistributionFlags_t* get_distribution_flags(
|
virtual SecurityDistributionFlags_t* get_distribution_flags(
|
||||||
entry_handle_t entry_handle
|
entry_handle_t db_handle
|
||||||
) {
|
) {
|
||||||
entry_t* entry = as_entry(entry_handle);
|
return reinterpret_cast<SecurityDistributionFlags_t*>(db_handle);
|
||||||
if (!entry) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &entry->flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the distribution flags of the DB entry
|
|
||||||
*/
|
|
||||||
virtual void set_distribution_flags(
|
|
||||||
entry_handle_t entry_handle,
|
|
||||||
const SecurityDistributionFlags_t& flags
|
|
||||||
) {
|
|
||||||
entry_t* entry = as_entry(entry_handle);
|
|
||||||
if (!entry) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry->state = ENTRY_WRITTEN;
|
|
||||||
entry->flags = flags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* local keys */
|
/* local keys */
|
||||||
|
|
||||||
/* get */
|
|
||||||
virtual void get_entry_local_keys(
|
|
||||||
SecurityEntryKeysDbCb_t cb,
|
|
||||||
entry_handle_t entry_handle,
|
|
||||||
const ediv_t &ediv,
|
|
||||||
const rand_t &rand
|
|
||||||
) {
|
|
||||||
entry_t* entry = as_entry(entry_handle);
|
|
||||||
if (!entry) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* validate we have the correct key */
|
|
||||||
if (ediv == entry->local_keys.ediv && rand == entry->local_keys.rand) {
|
|
||||||
cb(entry_handle, &entry->local_keys);
|
|
||||||
} else {
|
|
||||||
cb(entry_handle, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void get_entry_local_keys(
|
|
||||||
SecurityEntryKeysDbCb_t cb,
|
|
||||||
entry_handle_t entry_handle
|
|
||||||
) {
|
|
||||||
entry_t* entry = as_entry(entry_handle);
|
|
||||||
if (!entry) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* validate we have the correct key */
|
|
||||||
if (entry->flags.secure_connections_paired) {
|
|
||||||
cb(entry_handle, &entry->local_keys);
|
|
||||||
} else {
|
|
||||||
cb(entry_handle, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* set */
|
/* set */
|
||||||
virtual void set_entry_local_ltk(
|
virtual void set_entry_local_ltk(
|
||||||
entry_handle_t entry_handle,
|
entry_handle_t db_handle,
|
||||||
const ltk_t <k
|
const ltk_t <k
|
||||||
) {
|
) {
|
||||||
entry_t *entry = as_entry(entry_handle);
|
entry_t *entry = as_entry(db_handle);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry->state = ENTRY_WRITTEN;
|
entry->flags.ltk_sent = true;
|
||||||
entry->local_keys.ltk = ltk;
|
entry->local_keys.ltk = ltk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_entry_local_ediv_rand(
|
virtual void set_entry_local_ediv_rand(
|
||||||
entry_handle_t entry_handle,
|
entry_handle_t db_handle,
|
||||||
const ediv_t &ediv,
|
const ediv_t &ediv,
|
||||||
const rand_t &rand
|
const rand_t &rand
|
||||||
) {
|
) {
|
||||||
entry_t *entry = as_entry(entry_handle);
|
entry_t *entry = as_entry(db_handle);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry->state = ENTRY_WRITTEN;
|
|
||||||
entry->local_keys.ediv = ediv;
|
entry->local_keys.ediv = ediv;
|
||||||
entry->local_keys.rand = rand;
|
entry->local_keys.rand = rand;
|
||||||
}
|
}
|
||||||
|
@ -147,270 +80,118 @@ public:
|
||||||
|
|
||||||
/* peer's keys */
|
/* peer's keys */
|
||||||
|
|
||||||
/* get */
|
|
||||||
virtual void get_entry_peer_csrk(
|
|
||||||
SecurityEntryCsrkDbCb_t cb,
|
|
||||||
entry_handle_t entry_handle
|
|
||||||
) {
|
|
||||||
csrk_t csrk;
|
|
||||||
sign_count_t sign_counter = 0;
|
|
||||||
entry_t *entry = as_entry(entry_handle);
|
|
||||||
if (entry) {
|
|
||||||
csrk = entry->csrk;
|
|
||||||
sign_counter = entry->sign_counter;
|
|
||||||
}
|
|
||||||
cb(entry_handle, &csrk, sign_counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void get_entry_peer_keys(
|
|
||||||
SecurityEntryKeysDbCb_t cb,
|
|
||||||
entry_handle_t entry_handle
|
|
||||||
) {
|
|
||||||
SecurityEntryKeys_t *key = NULL;
|
|
||||||
entry_t *entry = as_entry(entry_handle);
|
|
||||||
if (entry) {
|
|
||||||
key = &entry->peer_keys;
|
|
||||||
}
|
|
||||||
cb(entry_handle, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void get_entry_identity(
|
|
||||||
SecurityEntryIdentityDbCb_t cb,
|
|
||||||
entry_handle_t entry_handle
|
|
||||||
) {
|
|
||||||
entry_t *entry = as_entry(entry_handle);
|
|
||||||
if (entry && entry->flags.irk_stored) {
|
|
||||||
cb(entry_handle, &entry->peer_identity);
|
|
||||||
} else {
|
|
||||||
cb(entry_handle, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void get_identity_list(
|
|
||||||
IdentitylistDbCb_t cb,
|
|
||||||
ArrayView<SecurityEntryIdentity_t*>& entries
|
|
||||||
) {
|
|
||||||
size_t count = 0;
|
|
||||||
for (size_t i = 0; i < MAX_ENTRIES && count < entries.size(); ++i) {
|
|
||||||
entry_t& e = _entries[i];
|
|
||||||
|
|
||||||
if (e.state == ENTRY_WRITTEN && e.flags.irk_stored) {
|
|
||||||
entries[count] = &e.peer_identity;
|
|
||||||
++count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(entries, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set */
|
/* set */
|
||||||
|
|
||||||
virtual void set_entry_peer_ltk(
|
virtual void set_entry_peer_ltk(
|
||||||
entry_handle_t entry_handle,
|
entry_handle_t db_handle,
|
||||||
const ltk_t <k
|
const ltk_t <k
|
||||||
) {
|
) {
|
||||||
entry_t *entry = as_entry(entry_handle);
|
entry_t *entry = as_entry(db_handle);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry->state = ENTRY_WRITTEN;
|
|
||||||
entry->peer_keys.ltk = ltk;
|
entry->peer_keys.ltk = ltk;
|
||||||
|
entry->flags.ltk_stored = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_entry_peer_ediv_rand(
|
virtual void set_entry_peer_ediv_rand(
|
||||||
entry_handle_t entry_handle,
|
entry_handle_t db_handle,
|
||||||
const ediv_t &ediv,
|
const ediv_t &ediv,
|
||||||
const rand_t &rand
|
const rand_t &rand
|
||||||
) {
|
) {
|
||||||
entry_t *entry = as_entry(entry_handle);
|
entry_t *entry = as_entry(db_handle);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry->state = ENTRY_WRITTEN;
|
|
||||||
entry->peer_keys.ediv = ediv;
|
entry->peer_keys.ediv = ediv;
|
||||||
entry->peer_keys.rand = rand;
|
entry->peer_keys.rand = rand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_entry_peer_irk(
|
virtual void set_entry_peer_irk(
|
||||||
entry_handle_t entry_handle,
|
entry_handle_t db_handle,
|
||||||
const irk_t &irk
|
const irk_t &irk
|
||||||
) {
|
) {
|
||||||
entry_t *entry = as_entry(entry_handle);
|
entry_t *entry = as_entry(db_handle);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry->state = ENTRY_WRITTEN;
|
|
||||||
entry->peer_identity.irk = irk;
|
entry->peer_identity.irk = irk;
|
||||||
entry->flags.irk_stored = true;
|
entry->flags.irk_stored = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_entry_peer_bdaddr(
|
virtual void set_entry_peer_bdaddr(
|
||||||
entry_handle_t entry_handle,
|
entry_handle_t db_handle,
|
||||||
bool address_is_public,
|
bool address_is_public,
|
||||||
const address_t &peer_address
|
const address_t &peer_address
|
||||||
) {
|
) {
|
||||||
entry_t *entry = as_entry(entry_handle);
|
entry_t *entry = as_entry(db_handle);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry->state = ENTRY_WRITTEN;
|
|
||||||
entry->peer_identity.identity_address = peer_address;
|
entry->peer_identity.identity_address = peer_address;
|
||||||
entry->peer_identity.identity_address_is_public = address_is_public;
|
entry->peer_identity.identity_address_is_public = address_is_public;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_entry_peer_csrk(
|
virtual void set_entry_peer_csrk(
|
||||||
entry_handle_t entry_handle,
|
entry_handle_t db_handle,
|
||||||
const csrk_t &csrk
|
const csrk_t &csrk
|
||||||
) {
|
) {
|
||||||
entry_t *entry = as_entry(entry_handle);
|
entry_t *entry = as_entry(db_handle);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry->state = ENTRY_WRITTEN;
|
entry->flags.csrk_stored = true;
|
||||||
entry->csrk = csrk;
|
entry->peer_signing.csrk = csrk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_entry_peer_sign_counter(
|
virtual void set_entry_peer_sign_counter(
|
||||||
entry_handle_t entry_handle,
|
entry_handle_t db_handle,
|
||||||
sign_count_t sign_counter
|
sign_count_t sign_counter
|
||||||
) {
|
) {
|
||||||
entry_t *entry = as_entry(entry_handle);
|
entry_t *entry = as_entry(db_handle);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
entry->state = ENTRY_WRITTEN;
|
entry->peer_signing.counter = sign_counter;
|
||||||
entry->sign_counter = sign_counter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* local csrk */
|
|
||||||
|
|
||||||
virtual const csrk_t* get_local_csrk() {
|
|
||||||
return &_local_csrk;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void set_local_csrk(const csrk_t &csrk) {
|
|
||||||
_local_csrk = csrk;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual sign_count_t get_local_sign_counter() {
|
|
||||||
return _local_sign_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void set_local_sign_counter(
|
|
||||||
sign_count_t sign_counter
|
|
||||||
) {
|
|
||||||
_local_sign_counter = sign_counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* list management */
|
|
||||||
|
|
||||||
virtual void close_entry(entry_handle_t entry_handle) {
|
|
||||||
entry_t *entry = as_entry(entry_handle);
|
|
||||||
if (entry) {
|
|
||||||
if (entry->state == ENTRY_RESERVED) {
|
|
||||||
entry->state = ENTRY_FREE;
|
|
||||||
} else {
|
|
||||||
entry->state = ENTRY_DISCONNECTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void remove_entry(const address_t peer_identity_address) {
|
|
||||||
for (size_t i = 0; i < MAX_ENTRIES; i++) {
|
|
||||||
if (_entries[i].state == ENTRY_FREE) {
|
|
||||||
continue;
|
|
||||||
} else if (peer_identity_address == _entries[i].peer_identity.identity_address) {
|
|
||||||
_entries[i] = entry_t();
|
|
||||||
_entries[i].state = ENTRY_FREE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void clear_entries() {
|
|
||||||
for (size_t i = 0; i < MAX_ENTRIES; i++) {
|
|
||||||
_entries[i] = entry_t();
|
|
||||||
}
|
|
||||||
_local_identity = SecurityEntryIdentity_t();
|
|
||||||
_local_csrk = csrk_t();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void get_whitelist(WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist) {
|
|
||||||
/*TODO: fill whitelist*/
|
|
||||||
cb(whitelist);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void generate_whitelist_from_bond_table(WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist) {
|
|
||||||
for (size_t i = 0; i < MAX_ENTRIES && i < whitelist->capacity; i++) {
|
|
||||||
if (_entries[i].flags.peer_address_is_public) {
|
|
||||||
whitelist->addresses[i].type = BLEProtocol::AddressType::PUBLIC;
|
|
||||||
} else {
|
|
||||||
whitelist->addresses[i].type = BLEProtocol::AddressType::RANDOM_STATIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(
|
|
||||||
whitelist->addresses[i].address,
|
|
||||||
_entries[i].peer_identity.identity_address.data(),
|
|
||||||
sizeof(BLEProtocol::AddressBytes_t)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(whitelist);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) { };
|
|
||||||
|
|
||||||
virtual void add_whitelist_entry(const address_t &address) { }
|
|
||||||
|
|
||||||
virtual void remove_whitelist_entry(const address_t &address) { }
|
|
||||||
|
|
||||||
virtual void clear_whitelist() { }
|
|
||||||
|
|
||||||
/* saving and loading from nvm */
|
|
||||||
|
|
||||||
virtual void restore() { }
|
|
||||||
|
|
||||||
virtual void sync() { }
|
|
||||||
|
|
||||||
virtual void set_restore(bool reload) { }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual uint8_t get_stored_entry_number() {
|
virtual uint8_t get_entry_count() {
|
||||||
return MAX_ENTRIES;
|
return MAX_ENTRIES;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual SecurityDistributionFlags_t* get_stored_entry_flags(uint8_t index) {
|
virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) {
|
||||||
return &_entries[index % MAX_ENTRIES].flags;
|
if (index < MAX_ENTRIES) {
|
||||||
}
|
return &_entries[index].flags;
|
||||||
|
} else {
|
||||||
virtual SecurityEntryIdentity_t* get_stored_entry_identity(uint8_t index) {
|
return NULL;
|
||||||
return &_entries[index % MAX_ENTRIES].peer_identity;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual SecurityDistributionFlags_t* get_free_entry_flags() {
|
|
||||||
/* get a free one if available */
|
|
||||||
for (size_t i = 0; i < MAX_ENTRIES; i++) {
|
|
||||||
if (_entries[i].state == ENTRY_FREE) {
|
|
||||||
_entries[i] = entry_t();
|
|
||||||
_entries[i].state = ENTRY_RESERVED;
|
|
||||||
return &_entries[i].flags;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get any disconnected one */
|
|
||||||
for (size_t i = 0; i < MAX_ENTRIES; i++) {
|
|
||||||
if (_entries[i].state == ENTRY_DISCONNECTED) {
|
|
||||||
_entries[i] = entry_t();
|
|
||||||
_entries[i].state = ENTRY_RESERVED;
|
|
||||||
return &_entries[i].flags;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void reset_entry(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||||
|
*entry = entry_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||||
|
return &entry->peer_identity;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||||
|
return &entry->peer_keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||||
|
return &entry->local_keys;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = reinterpret_cast<entry_t*>(db_entry);
|
||||||
|
return &entry->peer_signing;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
entry_t _entries[MAX_ENTRIES];
|
entry_t _entries[MAX_ENTRIES];
|
||||||
SecurityEntryIdentity_t _local_identity;
|
|
||||||
csrk_t _local_csrk;
|
|
||||||
sign_count_t _local_sign_counter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace pal */
|
} /* namespace pal */
|
||||||
} /* namespace ble */
|
} /* namespace ble */
|
||||||
|
|
||||||
#endif /*PAL_MEMORY_SECURITY_DB_H_*/
|
#endif /*GENERIC_MEMORY_SECURITY_DB_H_*/
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PAL_SECURITY_MANAGER_DB_H__
|
#ifndef GENERIC_SECURITY_MANAGER_DB_H__
|
||||||
#define PAL_SECURITY_MANAGER_DB_H__
|
#define GENERIC_SECURITY_MANAGER_DB_H__
|
||||||
|
|
||||||
#include "platform/Callback.h"
|
#include "platform/Callback.h"
|
||||||
#include "ble/pal/GapTypes.h"
|
#include "ble/pal/GapTypes.h"
|
||||||
|
@ -36,11 +36,15 @@ struct SecurityDistributionFlags_t {
|
||||||
encryption_key_size(0),
|
encryption_key_size(0),
|
||||||
peer_address_is_public(false),
|
peer_address_is_public(false),
|
||||||
csrk_stored(false),
|
csrk_stored(false),
|
||||||
csrk_mitm_protected(false),
|
csrk_sent(false),
|
||||||
ltk_stored(false),
|
ltk_stored(false),
|
||||||
|
ltk_sent(false),
|
||||||
|
irk_stored(false),
|
||||||
|
irk_sent(false),
|
||||||
|
csrk_mitm_protected(false),
|
||||||
ltk_mitm_protected(false),
|
ltk_mitm_protected(false),
|
||||||
secure_connections_paired(false),
|
secure_connections_paired(false),
|
||||||
irk_stored(false) {
|
connected(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** peer address */
|
/** peer address */
|
||||||
|
@ -53,16 +57,21 @@ struct SecurityDistributionFlags_t {
|
||||||
|
|
||||||
/** CSRK (Connection Signature Resolving Key) has been distributed and stored */
|
/** CSRK (Connection Signature Resolving Key) has been distributed and stored */
|
||||||
uint8_t csrk_stored:1;
|
uint8_t csrk_stored:1;
|
||||||
/** CSRK that is stored has MITM protection */
|
uint8_t csrk_sent:1;
|
||||||
uint8_t csrk_mitm_protected:1;
|
|
||||||
/** LTK (Long Term Key) has been distributed and stored */
|
/** LTK (Long Term Key) has been distributed and stored */
|
||||||
uint8_t ltk_stored:1;
|
uint8_t ltk_stored:1;
|
||||||
|
uint8_t ltk_sent:1;
|
||||||
|
/** the security entry has been distributed and stored */
|
||||||
|
uint8_t irk_stored:1;
|
||||||
|
uint8_t irk_sent:1;
|
||||||
|
|
||||||
|
/** CSRK that is stored has MITM protection */
|
||||||
|
uint8_t csrk_mitm_protected:1;
|
||||||
/** LTK that is stored has MITM protection */
|
/** LTK that is stored has MITM protection */
|
||||||
uint8_t ltk_mitm_protected:1;
|
uint8_t ltk_mitm_protected:1;
|
||||||
/** the current pairing was done using Secure Connections */
|
/** the current pairing was done using Secure Connections */
|
||||||
uint8_t secure_connections_paired:1;
|
uint8_t secure_connections_paired:1;
|
||||||
/** the security entry has been distributed and stored */
|
uint8_t connected:1;
|
||||||
uint8_t irk_stored:1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Long Term Key and data used to identify it */
|
/** Long Term Key and data used to identify it */
|
||||||
|
@ -75,6 +84,14 @@ struct SecurityEntryKeys_t {
|
||||||
rand_t rand;
|
rand_t rand;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** CSRK and sign counter used to verify messages */
|
||||||
|
struct SecurityEntrySigning_t {
|
||||||
|
/** Signing key */
|
||||||
|
csrk_t csrk;
|
||||||
|
/** counter used to verify message to guard from replay attacks */
|
||||||
|
sign_count_t counter;
|
||||||
|
};
|
||||||
|
|
||||||
/** Data for resolving random resolvable addresses */
|
/** Data for resolving random resolvable addresses */
|
||||||
struct SecurityEntryIdentity_t {
|
struct SecurityEntryIdentity_t {
|
||||||
/** identity address */
|
/** identity address */
|
||||||
|
@ -103,8 +120,8 @@ public:
|
||||||
|
|
||||||
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryKeys_t*)>
|
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryKeys_t*)>
|
||||||
SecurityEntryKeysDbCb_t;
|
SecurityEntryKeysDbCb_t;
|
||||||
typedef mbed::Callback<void(entry_handle_t, const csrk_t*, uint32_t sign_counter)>
|
typedef mbed::Callback<void(entry_handle_t, const SecurityEntrySigning_t*)>
|
||||||
SecurityEntryCsrkDbCb_t;
|
SecurityEntrySigningDbCb_t;
|
||||||
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryIdentity_t*)>
|
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryIdentity_t*)>
|
||||||
SecurityEntryIdentityDbCb_t;
|
SecurityEntryIdentityDbCb_t;
|
||||||
typedef mbed::Callback<void(ArrayView<SecurityEntryIdentity_t*>&, size_t count)>
|
typedef mbed::Callback<void(ArrayView<SecurityEntryIdentity_t*>&, size_t count)>
|
||||||
|
@ -112,30 +129,35 @@ public:
|
||||||
typedef mbed::Callback<void(::Gap::Whitelist_t*)>
|
typedef mbed::Callback<void(::Gap::Whitelist_t*)>
|
||||||
WhitelistDbCb_t;
|
WhitelistDbCb_t;
|
||||||
|
|
||||||
SecurityDb() { };
|
SecurityDb() : _local_sign_counter(0) { };
|
||||||
virtual ~SecurityDb() { };
|
virtual ~SecurityDb() { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return immediately security flags associated to a db entry.
|
* Return immediately security flags associated to a db entry.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry Entry of the database queried.
|
* @param[in] db_handle Entry of the database queried.
|
||||||
* @return pointer to the flags or NULL if the entry do not have any
|
* @return pointer to the flags or NULL if the entry do not have any
|
||||||
* associated flags.
|
* associated flags.
|
||||||
*/
|
*/
|
||||||
virtual const SecurityDistributionFlags_t* get_distribution_flags(
|
virtual SecurityDistributionFlags_t* get_distribution_flags(
|
||||||
entry_handle_t db_entry
|
entry_handle_t db_handle
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the distribution flags of a DB entry.
|
* Set the distribution flags of a DB entry.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry Entry of the database that will store the flags.
|
* @param[in] db_handle Entry of the database that will store the flags.
|
||||||
* @param[in] flags Distribution flags to store in @p db_entry.
|
* @param[in] flags Distribution flags to store in @p db_handle.
|
||||||
*/
|
*/
|
||||||
virtual void set_distribution_flags(
|
virtual void set_distribution_flags(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
const SecurityDistributionFlags_t& flags
|
const SecurityDistributionFlags_t& new_flags
|
||||||
) = 0;
|
) {
|
||||||
|
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||||
|
if (flags) {
|
||||||
|
*flags = new_flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* local keys */
|
/* local keys */
|
||||||
|
|
||||||
|
@ -143,49 +165,66 @@ public:
|
||||||
* Retrieve stored LTK based on passed in EDIV and RAND values.
|
* Retrieve stored LTK based on passed in EDIV and RAND values.
|
||||||
*
|
*
|
||||||
* @param[in] cb callback that will receive the LTK struct
|
* @param[in] cb callback that will receive the LTK struct
|
||||||
* @param[in] db_entry handle of the entry being queried.
|
* @param[in] db_handle handle of the entry being queried.
|
||||||
* @param[in] ediv one of the values used to identify the LTK
|
* @param[in] ediv one of the values used to identify the LTK
|
||||||
* @param[in] rand one of the values used to identify the LTK
|
* @param[in] rand one of the values used to identify the LTK
|
||||||
*/
|
*/
|
||||||
virtual void get_entry_local_keys(
|
virtual void get_entry_local_keys(
|
||||||
SecurityEntryKeysDbCb_t cb,
|
SecurityEntryKeysDbCb_t cb,
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
const ediv_t &ediv,
|
const ediv_t &ediv,
|
||||||
const rand_t &rand
|
const rand_t &rand
|
||||||
) = 0;
|
) {
|
||||||
|
SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle);
|
||||||
|
/* validate we have the correct key */
|
||||||
|
if (keys && ediv == keys->ediv && rand == keys->rand) {
|
||||||
|
cb(db_handle, keys);
|
||||||
|
} else {
|
||||||
|
cb(db_handle, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve stored LTK generated during secure connections pairing.
|
* Retrieve stored LTK generated during secure connections pairing.
|
||||||
*
|
*
|
||||||
* @param[in] cb callback that will receive the LTK struct
|
* @param[in] cb callback that will receive the LTK struct
|
||||||
* @param[in] db_entry handle of the entry being queried.
|
* @param[in] db_handle handle of the entry being queried.
|
||||||
*/
|
*/
|
||||||
virtual void get_entry_local_keys(
|
virtual void get_entry_local_keys(
|
||||||
SecurityEntryKeysDbCb_t cb,
|
SecurityEntryKeysDbCb_t cb,
|
||||||
entry_handle_t db_entry
|
entry_handle_t db_handle
|
||||||
) = 0;
|
) {
|
||||||
|
SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle);
|
||||||
|
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||||
|
/* validate we have the correct key */
|
||||||
|
if (flags && keys && flags->secure_connections_paired) {
|
||||||
|
cb(db_handle, keys);
|
||||||
|
} else {
|
||||||
|
cb(db_handle, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save new local LTK for a connection.
|
* Save new local LTK for a connection.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry handle of the entry being updated.
|
* @param[in] db_handle handle of the entry being updated.
|
||||||
* @param[in] ltk the new LTK, if the device is slave, this is the LTK that
|
* @param[in] ltk the new LTK, if the device is slave, this is the LTK that
|
||||||
* will be used when link is encrypted
|
* will be used when link is encrypted
|
||||||
*/
|
*/
|
||||||
virtual void set_entry_local_ltk(
|
virtual void set_entry_local_ltk(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
const ltk_t <k
|
const ltk_t <k
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update EDIV and RAND used to identify the LTK.
|
* Update EDIV and RAND used to identify the LTK.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry handle of the entry being updated.
|
* @param[in] db_handle handle of the entry being updated.
|
||||||
* @param[in] ediv new EDIV value
|
* @param[in] ediv new EDIV value
|
||||||
* @param[in] rand new RAND value
|
* @param[in] rand new RAND value
|
||||||
*/
|
*/
|
||||||
virtual void set_entry_local_ediv_rand(
|
virtual void set_entry_local_ediv_rand(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
const ediv_t &ediv,
|
const ediv_t &ediv,
|
||||||
const rand_t &rand
|
const rand_t &rand
|
||||||
) = 0;
|
) = 0;
|
||||||
|
@ -197,46 +236,52 @@ public:
|
||||||
* so that signed packets can be verified.
|
* so that signed packets can be verified.
|
||||||
*
|
*
|
||||||
* @param[in] cb callback which will receive the key
|
* @param[in] cb callback which will receive the key
|
||||||
* @param[in] db_entry handle of the entry being queried.
|
* @param[in] db_handle handle of the entry being queried.
|
||||||
*/
|
*/
|
||||||
virtual void get_entry_peer_csrk(
|
virtual void get_entry_peer_csrk(
|
||||||
SecurityEntryCsrkDbCb_t cb,
|
SecurityEntrySigningDbCb_t cb,
|
||||||
entry_handle_t db_entry
|
entry_handle_t db_handle
|
||||||
) = 0;
|
) {
|
||||||
|
SecurityEntrySigning_t* signing = read_in_entry_peer_signing(db_handle);
|
||||||
|
cb(db_handle, signing);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return asynchronously the peer encryption key through a callback
|
* Return asynchronously the peer encryption key through a callback
|
||||||
* so that encryption can be enabled.
|
* so that encryption can be enabled.
|
||||||
*
|
*
|
||||||
* @param[in] cb callback which will receive the key
|
* @param[in] cb callback which will receive the key
|
||||||
* @param[in] db_entry handle of the entry being queried.
|
* @param[in] db_handle handle of the entry being queried.
|
||||||
*/
|
*/
|
||||||
virtual void get_entry_peer_keys(
|
virtual void get_entry_peer_keys(
|
||||||
SecurityEntryKeysDbCb_t cb,
|
SecurityEntryKeysDbCb_t cb,
|
||||||
entry_handle_t db_entry
|
entry_handle_t db_handle
|
||||||
) = 0;
|
) {
|
||||||
|
SecurityEntryKeys_t* keys = read_in_entry_peer_keys(db_handle);
|
||||||
|
cb(db_handle, keys);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save new LTK received from the peer.
|
* Save new LTK received from the peer.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry handle of the entry being updated.
|
* @param[in] db_handle handle of the entry being updated.
|
||||||
* @param[in] ltk the new LTK, if the peer device is slave, this is the LTK
|
* @param[in] ltk the new LTK, if the peer device is slave, this is the LTK
|
||||||
* that will be used when link is encrypted
|
* that will be used when link is encrypted
|
||||||
*/
|
*/
|
||||||
virtual void set_entry_peer_ltk(
|
virtual void set_entry_peer_ltk(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
const ltk_t <k
|
const ltk_t <k
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update EDIV and RAND used to identify the LTK sent by the peer.
|
* Update EDIV and RAND used to identify the LTK sent by the peer.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry handle of the entry being updated.
|
* @param[in] db_handle handle of the entry being updated.
|
||||||
* @param[in] ediv new EDIV value
|
* @param[in] ediv new EDIV value
|
||||||
* @param[in] rand new RAND value
|
* @param[in] rand new RAND value
|
||||||
*/
|
*/
|
||||||
virtual void set_entry_peer_ediv_rand(
|
virtual void set_entry_peer_ediv_rand(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
const ediv_t &ediv,
|
const ediv_t &ediv,
|
||||||
const rand_t &rand
|
const rand_t &rand
|
||||||
) = 0;
|
) = 0;
|
||||||
|
@ -244,23 +289,23 @@ public:
|
||||||
/**
|
/**
|
||||||
* Update IRK for this connection.
|
* Update IRK for this connection.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry handle of the entry being updated.
|
* @param[in] db_handle handle of the entry being updated.
|
||||||
* @param[in] irk new IRK value
|
* @param[in] irk new IRK value
|
||||||
*/
|
*/
|
||||||
virtual void set_entry_peer_irk(
|
virtual void set_entry_peer_irk(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
const irk_t &irk
|
const irk_t &irk
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the identity address of the peer.
|
* Update the identity address of the peer.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry handle of the entry being updated.
|
* @param[in] db_handle handle of the entry being updated.
|
||||||
* @param[in] address_is_public is the identity address public or private
|
* @param[in] address_is_public is the identity address public or private
|
||||||
* @param[in] peer_address the new address
|
* @param[in] peer_address the new address
|
||||||
*/
|
*/
|
||||||
virtual void set_entry_peer_bdaddr(
|
virtual void set_entry_peer_bdaddr(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
bool address_is_public,
|
bool address_is_public,
|
||||||
const address_t &peer_address
|
const address_t &peer_address
|
||||||
) = 0;
|
) = 0;
|
||||||
|
@ -269,12 +314,23 @@ public:
|
||||||
* Retrieve stored identity address and IRK.
|
* Retrieve stored identity address and IRK.
|
||||||
*
|
*
|
||||||
* @param[in] cb callback that will receive the SecurityEntryIdentity_t struct
|
* @param[in] cb callback that will receive the SecurityEntryIdentity_t struct
|
||||||
* @param[in] db_entry handle of the entry being queried.
|
* @param[in] db_handle handle of the entry being queried.
|
||||||
*/
|
*/
|
||||||
virtual void get_entry_identity(
|
virtual void get_entry_identity(
|
||||||
SecurityEntryIdentityDbCb_t cb,
|
SecurityEntryIdentityDbCb_t cb,
|
||||||
entry_handle_t db_entry
|
entry_handle_t db_handle
|
||||||
) = 0;
|
) {
|
||||||
|
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||||
|
if (flags && flags->irk_stored) {
|
||||||
|
SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle);
|
||||||
|
if (peer_identity) {
|
||||||
|
cb(db_handle, peer_identity);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* avoid duplicate else */
|
||||||
|
cb(db_handle, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously return the identity list stored in NVM through a callback.
|
* Asynchronously return the identity list stored in NVM through a callback.
|
||||||
|
@ -288,27 +344,45 @@ public:
|
||||||
virtual void get_identity_list(
|
virtual void get_identity_list(
|
||||||
IdentitylistDbCb_t cb,
|
IdentitylistDbCb_t cb,
|
||||||
ArrayView<SecurityEntryIdentity_t*>& identity_list
|
ArrayView<SecurityEntryIdentity_t*>& identity_list
|
||||||
) = 0;
|
) {
|
||||||
|
size_t count = 0;
|
||||||
|
for (size_t i = 0; i < get_entry_count() && count < identity_list.size(); ++i) {
|
||||||
|
|
||||||
|
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||||
|
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||||
|
|
||||||
|
|
||||||
|
if (flags && flags->irk_stored) {
|
||||||
|
SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle);
|
||||||
|
if (peer_identity) {
|
||||||
|
identity_list[count] = *peer_identity;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(identity_list, count);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update peer signing key.
|
* Update peer signing key.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry handle of the entry being updated.
|
* @param[in] db_handle handle of the entry being updated.
|
||||||
* @param[in] csrk new CSRK value
|
* @param[in] csrk new CSRK value
|
||||||
*/
|
*/
|
||||||
virtual void set_entry_peer_csrk(
|
virtual void set_entry_peer_csrk(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
const csrk_t &csrk
|
const csrk_t &csrk
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update peer signing counter.
|
* Update peer signing counter.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry handle of the entry being updated.
|
* @param[in] db_handle handle of the entry being updated.
|
||||||
* @param[in] sign_counter new signing counter value
|
* @param[in] sign_counter new signing counter value
|
||||||
*/
|
*/
|
||||||
virtual void set_entry_peer_sign_counter(
|
virtual void set_entry_peer_sign_counter(
|
||||||
entry_handle_t db_entry,
|
entry_handle_t db_handle,
|
||||||
sign_count_t sign_counter
|
sign_count_t sign_counter
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
|
@ -319,14 +393,18 @@ public:
|
||||||
*
|
*
|
||||||
* @return pointer to local CSRK
|
* @return pointer to local CSRK
|
||||||
*/
|
*/
|
||||||
virtual const csrk_t* get_local_csrk() = 0;
|
virtual const csrk_t* get_local_csrk() {
|
||||||
|
return &_local_csrk;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return local signing counter.
|
* Return local signing counter.
|
||||||
*
|
*
|
||||||
* @return signing counter
|
* @return signing counter
|
||||||
*/
|
*/
|
||||||
virtual sign_count_t get_local_sign_counter() = 0;
|
virtual sign_count_t get_local_sign_counter() {
|
||||||
|
return _local_sign_counter;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update local signing key.
|
* Update local signing key.
|
||||||
|
@ -335,7 +413,9 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void set_local_csrk(
|
virtual void set_local_csrk(
|
||||||
const csrk_t &csrk
|
const csrk_t &csrk
|
||||||
) = 0;
|
) {
|
||||||
|
_local_csrk = csrk;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update local signing counter.
|
* Update local signing counter.
|
||||||
|
@ -344,7 +424,9 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void set_local_sign_counter(
|
virtual void set_local_sign_counter(
|
||||||
sign_count_t sign_counter
|
sign_count_t sign_counter
|
||||||
) = 0;
|
) {
|
||||||
|
_local_sign_counter = sign_counter;
|
||||||
|
}
|
||||||
|
|
||||||
/* list management */
|
/* list management */
|
||||||
|
|
||||||
|
@ -363,15 +445,50 @@ public:
|
||||||
virtual entry_handle_t open_entry(
|
virtual entry_handle_t open_entry(
|
||||||
BLEProtocol::AddressType_t peer_address_type,
|
BLEProtocol::AddressType_t peer_address_type,
|
||||||
const address_t &peer_address
|
const address_t &peer_address
|
||||||
|
) {
|
||||||
|
entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address);
|
||||||
|
if (db_handle) {
|
||||||
|
return db_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityDistributionFlags_t* flags = get_free_entry_flags();
|
||||||
|
if (flags) {
|
||||||
|
const bool peer_address_public =
|
||||||
|
(peer_address_type == BLEProtocol::AddressType::PUBLIC) ||
|
||||||
|
(peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY);
|
||||||
|
/* we need some address to store, so we store even random ones
|
||||||
|
* this address will be used as an id, possibly replaced later
|
||||||
|
* by identity address */
|
||||||
|
flags->peer_address = peer_address;
|
||||||
|
flags->peer_address_is_public = peer_address_public;
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a database entry based on peer address.
|
||||||
|
*
|
||||||
|
* @param[in] peer_address_type type of address
|
||||||
|
* @param[in] peer_address this address will be used to locate an existing entry.
|
||||||
|
*
|
||||||
|
* @return A handle to the entry.
|
||||||
|
*/
|
||||||
|
virtual entry_handle_t find_entry_by_peer_address(
|
||||||
|
BLEProtocol::AddressType_t peer_address_type,
|
||||||
|
const address_t &peer_address
|
||||||
) {
|
) {
|
||||||
const bool peer_address_public =
|
const bool peer_address_public =
|
||||||
(peer_address_type == BLEProtocol::AddressType::PUBLIC) ||
|
(peer_address_type == BLEProtocol::AddressType::PUBLIC) ||
|
||||||
(peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY);
|
(peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY);
|
||||||
|
|
||||||
for (size_t i = 0; i < get_stored_entry_number(); i++) {
|
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||||
SecurityDistributionFlags_t* flags = get_stored_entry_flags(i);
|
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||||
|
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||||
|
|
||||||
if (flags) {
|
/* only look among disconnected entries */
|
||||||
|
if (flags && !flags->connected) {
|
||||||
if (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY &&
|
if (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY &&
|
||||||
flags->irk_stored == false) {
|
flags->irk_stored == false) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -385,7 +502,7 @@ public:
|
||||||
|
|
||||||
/* look for the identity address if stored */
|
/* look for the identity address if stored */
|
||||||
if (flags->irk_stored) {
|
if (flags->irk_stored) {
|
||||||
SecurityEntryIdentity_t* identity = get_stored_entry_identity(i);
|
SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle);
|
||||||
|
|
||||||
if (identity &&
|
if (identity &&
|
||||||
identity->identity_address == peer_address &&
|
identity->identity_address == peer_address &&
|
||||||
|
@ -393,42 +510,55 @@ public:
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SecurityDistributionFlags_t* flags = get_free_entry_flags();
|
|
||||||
if (flags) {
|
|
||||||
/* we need some address to store, so we store even random ones
|
|
||||||
* this address will be used as an id, possibly replaced later
|
|
||||||
* by identity address */
|
|
||||||
flags->peer_address = peer_address;
|
|
||||||
flags->peer_address_is_public = peer_address_public;
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close a connection entry.
|
* Close a connection entry.
|
||||||
*
|
*
|
||||||
* @param[in] db_entry this handle will be freed up from the security db.
|
* @param[in] db_handle this handle will be freed up from the security db.
|
||||||
*/
|
*/
|
||||||
virtual void close_entry(entry_handle_t db_entry) = 0;
|
virtual void close_entry(entry_handle_t db_handle) {
|
||||||
|
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||||
|
if (flags) {
|
||||||
|
flags->connected = false;
|
||||||
|
}
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove entry for this peer from NVM.
|
* Remove entry for this peer from NVM.
|
||||||
*
|
*
|
||||||
* @param[in] peer_identity_address peer address that no longer needs NVM
|
* @param[in] peer_address_type type of address
|
||||||
* storage.
|
* @param[in] peer_address this address will be used to locate an existing
|
||||||
|
* entry.
|
||||||
|
*
|
||||||
|
* @return A handle to the entry.
|
||||||
*/
|
*/
|
||||||
virtual void remove_entry(const address_t peer_identity_address) = 0;
|
virtual void remove_entry(
|
||||||
|
BLEProtocol::AddressType_t peer_address_type,
|
||||||
|
const address_t &peer_address
|
||||||
|
) {
|
||||||
|
entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address);
|
||||||
|
if (db_handle) {
|
||||||
|
reset_entry(db_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all entries from the security DB.
|
* Remove all entries from the security DB.
|
||||||
*/
|
*/
|
||||||
virtual void clear_entries() = 0;
|
virtual void clear_entries() {
|
||||||
|
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||||
|
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||||
|
reset_entry(db_handle);
|
||||||
|
}
|
||||||
|
_local_identity = SecurityEntryIdentity_t();
|
||||||
|
_local_csrk = csrk_t();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously return the whitelist stored in NVM through a callback.
|
* Asynchronously return the whitelist stored in NVM through a callback.
|
||||||
|
@ -441,7 +571,10 @@ public:
|
||||||
virtual void get_whitelist(
|
virtual void get_whitelist(
|
||||||
WhitelistDbCb_t cb,
|
WhitelistDbCb_t cb,
|
||||||
::Gap::Whitelist_t *whitelist
|
::Gap::Whitelist_t *whitelist
|
||||||
) = 0;
|
) {
|
||||||
|
/*TODO: fill whitelist*/
|
||||||
|
cb(whitelist);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously return a whitelist through a callback, generated from the
|
* Asynchronously return a whitelist through a callback, generated from the
|
||||||
|
@ -453,61 +586,127 @@ public:
|
||||||
virtual void generate_whitelist_from_bond_table(
|
virtual void generate_whitelist_from_bond_table(
|
||||||
WhitelistDbCb_t cb,
|
WhitelistDbCb_t cb,
|
||||||
::Gap::Whitelist_t *whitelist
|
::Gap::Whitelist_t *whitelist
|
||||||
) = 0;
|
) {
|
||||||
|
for (size_t i = 0; i < get_entry_count() && i < whitelist->capacity; i++) {
|
||||||
|
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||||
|
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||||
|
|
||||||
|
if (!flags) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->peer_address_is_public) {
|
||||||
|
whitelist->addresses[i].type = BLEProtocol::AddressType::PUBLIC;
|
||||||
|
} else {
|
||||||
|
whitelist->addresses[i].type = BLEProtocol::AddressType::RANDOM_STATIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle);
|
||||||
|
if (identity) {
|
||||||
|
memcpy(
|
||||||
|
whitelist->addresses[i].address,
|
||||||
|
identity->identity_address.data(),
|
||||||
|
sizeof(BLEProtocol::AddressBytes_t)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(whitelist);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the whitelist stored in NVM by replacing it with new one.
|
* Update the whitelist stored in NVM by replacing it with new one.
|
||||||
*
|
*
|
||||||
* @param[in] whitelist
|
* @param[in] whitelist
|
||||||
*/
|
*/
|
||||||
virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) = 0;
|
virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new entry to the whitelist in the NVM.
|
* Add a new entry to the whitelist in the NVM.
|
||||||
*
|
*
|
||||||
* @param[in] address new whitelist entry
|
* @param[in] address new whitelist entry
|
||||||
*/
|
*/
|
||||||
virtual void add_whitelist_entry(const address_t &address) = 0;
|
virtual void add_whitelist_entry(const address_t &address) { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove whitelist entry from NVM.
|
* Remove whitelist entry from NVM.
|
||||||
*
|
*
|
||||||
* @param[in] address entry to be removed
|
* @param[in] address entry to be removed
|
||||||
*/
|
*/
|
||||||
virtual void remove_whitelist_entry(const address_t &address) = 0;
|
virtual void remove_whitelist_entry(const address_t &address) { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Remove all whitelist entries stored in the NVM.
|
*Remove all whitelist entries stored in the NVM.
|
||||||
*/
|
*/
|
||||||
virtual void clear_whitelist() = 0;
|
virtual void clear_whitelist() { };
|
||||||
|
|
||||||
/* saving and loading from nvm */
|
/* saving and loading from nvm */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read values from storage.
|
* Read values from storage.
|
||||||
*/
|
*/
|
||||||
virtual void restore() = 0;
|
virtual void restore() { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush all values which might be stored in memory into NVM.
|
* Flush all values which might be stored in memory into NVM.
|
||||||
*/
|
*/
|
||||||
virtual void sync() = 0;
|
virtual void sync() { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle whether values should be preserved across resets.
|
* Toggle whether values should be preserved across resets.
|
||||||
*
|
*
|
||||||
* @param[in] reload if true values will be preserved across resets.
|
* @param[in] reload if true values will be preserved across resets.
|
||||||
*/
|
*/
|
||||||
virtual void set_restore(bool reload) = 0;
|
virtual void set_restore(bool reload) { };
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
virtual uint8_t get_stored_entry_number() = 0;
|
virtual SecurityDistributionFlags_t* get_free_entry_flags() {
|
||||||
virtual SecurityDistributionFlags_t* get_stored_entry_flags(uint8_t index) = 0;
|
/* get a free one if available */
|
||||||
virtual SecurityEntryIdentity_t* get_stored_entry_identity(uint8_t index) = 0;
|
SecurityDistributionFlags_t* match = NULL;
|
||||||
virtual SecurityDistributionFlags_t* get_free_entry_flags() = 0;
|
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||||
|
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||||
|
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||||
|
|
||||||
|
if (flags && !flags->connected) {
|
||||||
|
/* we settle for any disconnected if we don't find an empty one */
|
||||||
|
match = flags;
|
||||||
|
if (!flags->csrk_stored
|
||||||
|
&& !flags->csrk_sent
|
||||||
|
&& !flags->ltk_stored
|
||||||
|
&& !flags->ltk_sent
|
||||||
|
&& !flags->irk_stored
|
||||||
|
&& !flags->irk_sent) {
|
||||||
|
/* empty one found, stop looking*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
reset_entry(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual uint8_t get_entry_count() = 0;
|
||||||
|
|
||||||
|
virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) = 0;
|
||||||
|
|
||||||
|
virtual void reset_entry(entry_handle_t db_handle) = 0;
|
||||||
|
|
||||||
|
virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle) = 0;
|
||||||
|
virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle) = 0;
|
||||||
|
virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle) = 0;
|
||||||
|
virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SecurityEntryIdentity_t _local_identity;
|
||||||
|
csrk_t _local_csrk;
|
||||||
|
sign_count_t _local_sign_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace pal */
|
} /* namespace pal */
|
||||||
} /* namespace ble */
|
} /* namespace ble */
|
||||||
|
|
||||||
#endif /*PAL_SECURITY_MANAGER_DB_H__*/
|
#endif /*GENERIC_SECURITY_MANAGER_DB_H__*/
|
||||||
|
|
|
@ -0,0 +1,357 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2018 ARM Limited
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FileSecurityDb.h"
|
||||||
|
|
||||||
|
namespace ble {
|
||||||
|
namespace generic {
|
||||||
|
|
||||||
|
const uint16_t DB_VERSION = 1;
|
||||||
|
|
||||||
|
#define DB_STORE_OFFSET_LOCAL_KEYS (0)
|
||||||
|
#define DB_STORE_OFFSET_PEER_KEYS (DB_STORE_OFFSET_LOCAL_KEYS + sizeof(SecurityEntryKeys_t))
|
||||||
|
#define DB_STORE_OFFSET_PEER_IDENTITY (DB_STORE_OFFSET_PEER_KEYS + sizeof(SecurityEntryKeys_t))
|
||||||
|
#define DB_STORE_OFFSET_PEER_SIGNING (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(SecurityEntryIdentity_t))
|
||||||
|
#define DB_SIZE_STORE_PEER_SIGN_COUNT (DB_STORE_OFFSET_PEER_SIGNING + sizeof(SecurityEntrySigning_t))
|
||||||
|
|
||||||
|
#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS (DB_STORE_OFFSET_PEER_IDENTITY)
|
||||||
|
#define DB_STORE_OFFSET_PEER_IDENTITY_IRK (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(address_t))
|
||||||
|
#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC (DB_STORE_OFFSET_PEER_IDENTITY_IRK + sizeof(irk_t))
|
||||||
|
|
||||||
|
#define DB_STORE_OFFSET_PEER_KEYS_LTK (DB_STORE_OFFSET_PEER_KEYS)
|
||||||
|
#define DB_STORE_OFFSET_PEER_KEYS_EDIV (DB_STORE_OFFSET_PEER_KEYS_LTK + sizeof(ltk_t))
|
||||||
|
#define DB_STORE_OFFSET_PEER_KEYS_RAND (DB_STORE_OFFSET_PEER_KEYS_EDIV + sizeof(ediv_t))
|
||||||
|
|
||||||
|
#define DB_STORE_OFFSET_LOCAL_KEYS_LTK (DB_STORE_OFFSET_LOCAL_KEYS)
|
||||||
|
#define DB_STORE_OFFSET_LOCAL_KEYS_EDIV (DB_STORE_OFFSET_LOCAL_KEYS_LTK + sizeof(ltk_t))
|
||||||
|
#define DB_STORE_OFFSET_LOCAL_KEYS_RAND (DB_STORE_OFFSET_LOCAL_KEYS_EDIV + sizeof(ediv_t))
|
||||||
|
|
||||||
|
#define DB_SIZE_STORE \
|
||||||
|
(sizeof(SecurityEntryKeys_t) + \
|
||||||
|
sizeof(SecurityEntryKeys_t) + \
|
||||||
|
sizeof(SecurityEntryIdentity_t) + \
|
||||||
|
sizeof(SecurityEntrySigning_t) + \
|
||||||
|
sizeof(sign_count_t))
|
||||||
|
|
||||||
|
/* without the size of the file offset as we don't store it */
|
||||||
|
#define DB_SIZE_ENTRY \
|
||||||
|
(sizeof(SecurityDistributionFlags_t) + sizeof(sign_count_t))
|
||||||
|
|
||||||
|
#define DB_SIZE_ENTRIES \
|
||||||
|
(FileSecurityDb::MAX_ENTRIES * DB_SIZE_ENTRY)
|
||||||
|
|
||||||
|
#define DB_SIZE_STORES \
|
||||||
|
(FileSecurityDb::MAX_ENTRIES * DB_SIZE_STORE)
|
||||||
|
|
||||||
|
#define DB_OFFSET_VERSION (0)
|
||||||
|
#define DB_OFFSET_RESTORE (DB_OFFSET_VERSION + sizeof(DB_VERSION))
|
||||||
|
#define DB_OFFSET_LOCAL_IDENTITY (DB_OFFSET_RESTORE + sizeof(bool))
|
||||||
|
#define DB_OFFSET_LOCAL_CSRK (DB_OFFSET_LOCAL_IDENTITY + sizeof(SecurityEntryIdentity_t))
|
||||||
|
#define DB_OFFSET_LOCAL_SIGN_COUNT (DB_OFFSET_LOCAL_CSRK + sizeof(csrk_t))
|
||||||
|
#define DB_OFFSET_ENTRIES (DB_OFFSET_LOCAL_SIGN_COUNT + sizeof(sign_count_t))
|
||||||
|
#define DB_OFFSET_STORES (DB_OFFSET_ENTRIES + DB_SIZE_ENTRIES)
|
||||||
|
#define DB_OFFSET_MAX (DB_OFFSET_STORES + DB_SIZE_STORES)
|
||||||
|
/* make size multiple of 4 */
|
||||||
|
#define DB_SIZE ((((DB_OFFSET_MAX - 1) / 4) * 4) + 4)
|
||||||
|
|
||||||
|
typedef SecurityDb::entry_handle_t entry_handle_t;
|
||||||
|
|
||||||
|
FileSecurityDb::FileSecurityDb(FILE *db_file)
|
||||||
|
: SecurityDb(),
|
||||||
|
_db_file(db_file) {
|
||||||
|
fseek(_db_file, DB_OFFSET_RESTORE, SEEK_SET);
|
||||||
|
|
||||||
|
/* restore if requested */
|
||||||
|
bool restore;
|
||||||
|
if ((fread(&restore, sizeof(bool), 1, _db_file) == 1) && restore) {
|
||||||
|
fseek(_db_file, DB_OFFSET_LOCAL_IDENTITY, SEEK_SET);
|
||||||
|
fread(&_local_identity, sizeof(_local_identity), 1, _db_file);
|
||||||
|
|
||||||
|
fseek(_db_file, DB_OFFSET_LOCAL_CSRK, SEEK_SET);
|
||||||
|
fread(&_local_csrk, sizeof(_local_csrk), 1, _db_file);
|
||||||
|
|
||||||
|
fseek(_db_file, DB_OFFSET_LOCAL_SIGN_COUNT, SEEK_SET);
|
||||||
|
fread(&_local_sign_counter, sizeof(_local_sign_counter), 1, _db_file);
|
||||||
|
|
||||||
|
fseek(_db_file, DB_OFFSET_ENTRIES, SEEK_SET);
|
||||||
|
/* we read the entries partially and fill the offsets ourselves*/
|
||||||
|
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||||
|
fread(&_entries[i], DB_SIZE_ENTRY, 1, _db_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init the offset in entries so they point to file positions */
|
||||||
|
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||||
|
_entries[i].file_offset = DB_OFFSET_STORES + i * DB_SIZE_STORE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSecurityDb::~FileSecurityDb() {
|
||||||
|
fclose(_db_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* FileSecurityDb::open_db_file(const char *db_path) {
|
||||||
|
FILE *db_file = fopen(db_path, "wb+");
|
||||||
|
if (db_file) {
|
||||||
|
/* we will check the db file and if the version or size doesn't match
|
||||||
|
* what we expect we will blank it */
|
||||||
|
bool init = false;
|
||||||
|
uint16_t version;
|
||||||
|
|
||||||
|
fseek(db_file, DB_OFFSET_VERSION, SEEK_SET);
|
||||||
|
|
||||||
|
if ((fread(&version, sizeof(version), 1, db_file) == 1) &&
|
||||||
|
(version == DB_VERSION)) {
|
||||||
|
/* version checks out, try the size */
|
||||||
|
fseek(db_file, DB_SIZE - 1, SEEK_SET);
|
||||||
|
/* read one byte and expect to hit EOF */
|
||||||
|
if ((fread(&version, 1, 1, db_file) != 1) || !feof(db_file)) {
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init) {
|
||||||
|
fseek(db_file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
/* zero the file */
|
||||||
|
const uint32_t zero = 0;
|
||||||
|
size_t count = DB_SIZE / 4;
|
||||||
|
while (count--) {
|
||||||
|
if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) {
|
||||||
|
fclose(db_file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fflush(db_file)) {
|
||||||
|
fclose(db_file);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return db_file;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityDistributionFlags_t* FileSecurityDb::get_distribution_flags(
|
||||||
|
entry_handle_t db_handle
|
||||||
|
) {
|
||||||
|
return reinterpret_cast<SecurityDistributionFlags_t*>(db_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* local keys */
|
||||||
|
|
||||||
|
/* set */
|
||||||
|
void FileSecurityDb::set_entry_local_ltk(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const ltk_t <k
|
||||||
|
) {
|
||||||
|
entry_t *entry = as_entry(db_handle);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK, SEEK_SET);
|
||||||
|
fwrite(<k, sizeof(ltk_t), 1, _db_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::set_entry_local_ediv_rand(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const ediv_t &ediv,
|
||||||
|
const rand_t &rand
|
||||||
|
) {
|
||||||
|
entry_t *entry = as_entry(db_handle);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_EDIV, SEEK_SET);
|
||||||
|
fwrite(&ediv, sizeof(ediv_t), 1, _db_file);
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_RAND, SEEK_SET);
|
||||||
|
fwrite(&rand, sizeof(rand_t), 1, _db_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* peer's keys */
|
||||||
|
|
||||||
|
/* set */
|
||||||
|
|
||||||
|
void FileSecurityDb::set_entry_peer_ltk(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const ltk_t <k
|
||||||
|
) {
|
||||||
|
entry_t *entry = as_entry(db_handle);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK, SEEK_SET);
|
||||||
|
fwrite(<k, sizeof(ltk_t), 1, _db_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::set_entry_peer_ediv_rand(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const ediv_t &ediv,
|
||||||
|
const rand_t &rand
|
||||||
|
) {
|
||||||
|
entry_t *entry = as_entry(db_handle);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_EDIV, SEEK_SET);
|
||||||
|
fwrite(&ediv, sizeof(ediv_t), 1, _db_file);
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_RAND, SEEK_SET);
|
||||||
|
fwrite(&rand, sizeof(rand_t), 1, _db_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::set_entry_peer_irk(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const irk_t &irk
|
||||||
|
) {
|
||||||
|
entry_t *entry = as_entry(db_handle);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->flags.irk_stored = true;
|
||||||
|
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_IRK, SEEK_SET);
|
||||||
|
fwrite(&irk, sizeof(irk_t), 1, _db_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::set_entry_peer_bdaddr(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
bool address_is_public,
|
||||||
|
const address_t &peer_address
|
||||||
|
) {
|
||||||
|
entry_t *entry = as_entry(db_handle);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS, SEEK_SET);
|
||||||
|
fwrite(&peer_address, sizeof(address_t), 1, _db_file);
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC, SEEK_SET);
|
||||||
|
fwrite(&address_is_public, sizeof(bool), 1, _db_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::set_entry_peer_csrk(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
const csrk_t &csrk
|
||||||
|
) {
|
||||||
|
entry_t *entry = as_entry(db_handle);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING, SEEK_SET);
|
||||||
|
/* only write in the csrk */
|
||||||
|
fwrite(&csrk, sizeof(csrk_t), 1, _db_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::set_entry_peer_sign_counter(
|
||||||
|
entry_handle_t db_handle,
|
||||||
|
sign_count_t sign_counter
|
||||||
|
) {
|
||||||
|
entry_t *entry = as_entry(db_handle);
|
||||||
|
if (entry) {
|
||||||
|
entry->peer_sign_counter = sign_counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* saving and loading from nvm */
|
||||||
|
|
||||||
|
void FileSecurityDb::restore() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::sync() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::set_restore(bool reload) {
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t FileSecurityDb::get_entry_count() {
|
||||||
|
return MAX_ENTRIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityDistributionFlags_t* FileSecurityDb::get_entry_handle_by_index(uint8_t index) {
|
||||||
|
if (index < MAX_ENTRIES) {
|
||||||
|
return &_entries[index].flags;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSecurityDb::reset_entry(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = as_entry(db_entry);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry->flags = SecurityDistributionFlags_t();
|
||||||
|
entry->peer_sign_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SecurityEntryIdentity_t* FileSecurityDb::read_in_entry_peer_identity(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = as_entry(db_entry);
|
||||||
|
if (!entry) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY, SEEK_SET);
|
||||||
|
fread(&_buffer, sizeof(SecurityEntryIdentity_t), 1, _db_file);
|
||||||
|
return reinterpret_cast<SecurityEntryIdentity_t*>(_buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
SecurityEntryKeys_t* FileSecurityDb::read_in_entry_peer_keys(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = as_entry(db_entry);
|
||||||
|
if (!entry) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS, SEEK_SET);
|
||||||
|
fread(&_buffer, sizeof(SecurityEntryKeys_t), 1, _db_file);
|
||||||
|
return reinterpret_cast<SecurityEntryKeys_t*>(_buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
SecurityEntryKeys_t* FileSecurityDb::read_in_entry_local_keys(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = as_entry(db_entry);
|
||||||
|
if (!entry) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS, SEEK_SET);
|
||||||
|
fread(&_buffer, sizeof(SecurityEntryKeys_t), 1, _db_file);
|
||||||
|
return reinterpret_cast<SecurityEntryKeys_t*>(_buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
SecurityEntrySigning_t* FileSecurityDb::read_in_entry_peer_signing(entry_handle_t db_entry) {
|
||||||
|
entry_t *entry = as_entry(db_entry);
|
||||||
|
if (!entry) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING, SEEK_SET);
|
||||||
|
|
||||||
|
/* only read in the csrk */
|
||||||
|
fread(&_buffer, sizeof(csrk_t), 1, _db_file);
|
||||||
|
SecurityEntrySigning_t* signing = reinterpret_cast<SecurityEntrySigning_t*>(_buffer);
|
||||||
|
/* use the counter held in memory */
|
||||||
|
signing->counter = entry->peer_sign_counter;
|
||||||
|
|
||||||
|
return signing;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace pal */
|
||||||
|
} /* namespace ble */
|
|
@ -40,16 +40,26 @@ ble_error_t GenericSecurityManager::init(
|
||||||
SecurityIOCapabilities_t iocaps,
|
SecurityIOCapabilities_t iocaps,
|
||||||
const Passkey_t passkey,
|
const Passkey_t passkey,
|
||||||
bool signing,
|
bool signing,
|
||||||
const uint8_t* db_path
|
const char* db_path
|
||||||
) {
|
) {
|
||||||
|
if (_db) {
|
||||||
|
return BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||||
|
}
|
||||||
|
|
||||||
ble_error_t err = _pal.initialize();
|
ble_error_t err = _pal.initialize();
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
_db = new (std::nothrow) MemorySecurityDb();
|
FILE* db_file = FileSecurityDb::open_db_file(db_path);
|
||||||
|
if (db_file) {
|
||||||
|
_db = new (std::nothrow) FileSecurityDb(db_file);
|
||||||
|
} else {
|
||||||
|
_db = new (std::nothrow) MemorySecurityDb();
|
||||||
|
}
|
||||||
|
|
||||||
_db->restore();
|
_db->restore();
|
||||||
|
|
||||||
_pal.set_io_capability((io_capability_t::type) iocaps);
|
_pal.set_io_capability((io_capability_t::type) iocaps);
|
||||||
|
|
||||||
if (passkey) {
|
if (passkey) {
|
||||||
|
@ -99,6 +109,7 @@ ble_error_t GenericSecurityManager::init(
|
||||||
}
|
}
|
||||||
|
|
||||||
ble_error_t GenericSecurityManager::reset(void) {
|
ble_error_t GenericSecurityManager::reset(void) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
_db->sync();
|
_db->sync();
|
||||||
_pal.reset();
|
_pal.reset();
|
||||||
SecurityManager::reset();
|
SecurityManager::reset();
|
||||||
|
@ -107,6 +118,7 @@ ble_error_t GenericSecurityManager::reset(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
|
ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
_db->set_restore(enabled);
|
_db->set_restore(enabled);
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
@ -116,11 +128,13 @@ ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
|
||||||
//
|
//
|
||||||
|
|
||||||
ble_error_t GenericSecurityManager::purgeAllBondingState(void) {
|
ble_error_t GenericSecurityManager::purgeAllBondingState(void) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
_db->clear_entries();
|
_db->clear_entries();
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const {
|
ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
if (eventHandler) {
|
if (eventHandler) {
|
||||||
_db->generate_whitelist_from_bond_table(
|
_db->generate_whitelist_from_bond_table(
|
||||||
mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable),
|
mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable),
|
||||||
|
@ -327,6 +341,7 @@ ble_error_t GenericSecurityManager::enableSigning(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
bool enabled
|
bool enabled
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
|
@ -468,6 +483,7 @@ ble_error_t GenericSecurityManager::setEncryptionKeyRequirements(
|
||||||
//
|
//
|
||||||
|
|
||||||
ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) {
|
ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
|
@ -663,6 +679,7 @@ ble_error_t GenericSecurityManager::oobReceived(
|
||||||
//
|
//
|
||||||
|
|
||||||
ble_error_t GenericSecurityManager::init_signing() {
|
ble_error_t GenericSecurityManager::init_signing() {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
const csrk_t *pcsrk = _db->get_local_csrk();
|
const csrk_t *pcsrk = _db->get_local_csrk();
|
||||||
sign_count_t local_sign_counter = _db->get_local_sign_counter();
|
sign_count_t local_sign_counter = _db->get_local_sign_counter();
|
||||||
|
|
||||||
|
@ -712,6 +729,7 @@ ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t c
|
||||||
}
|
}
|
||||||
|
|
||||||
ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) {
|
ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
|
@ -763,35 +781,33 @@ void GenericSecurityManager::set_ltk_cb(
|
||||||
|
|
||||||
void GenericSecurityManager::set_peer_csrk_cb(
|
void GenericSecurityManager::set_peer_csrk_cb(
|
||||||
SecurityDb::entry_handle_t db_entry,
|
SecurityDb::entry_handle_t db_entry,
|
||||||
const csrk_t *csrk,
|
const SecurityEntrySigning_t* signing
|
||||||
sign_count_t sign_counter
|
|
||||||
) {
|
) {
|
||||||
ControlBlock_t *cb = get_control_block(db_entry);
|
ControlBlock_t *cb = get_control_block(db_entry);
|
||||||
if (!cb) {
|
if (!cb || !signing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_pal.set_peer_csrk(
|
_pal.set_peer_csrk(
|
||||||
cb->connection,
|
cb->connection,
|
||||||
*csrk,
|
signing->csrk,
|
||||||
cb->csrk_mitm_protected,
|
cb->csrk_mitm_protected,
|
||||||
sign_counter
|
signing->counter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericSecurityManager::return_csrk_cb(
|
void GenericSecurityManager::return_csrk_cb(
|
||||||
SecurityDb::entry_handle_t db_entry,
|
SecurityDb::entry_handle_t db_entry,
|
||||||
const csrk_t *csrk,
|
const SecurityEntrySigning_t *signing
|
||||||
sign_count_t sign_counter
|
|
||||||
) {
|
) {
|
||||||
ControlBlock_t *cb = get_control_block(db_entry);
|
ControlBlock_t *cb = get_control_block(db_entry);
|
||||||
if (!cb) {
|
if (!cb || !signing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHandler->signingKey(
|
eventHandler->signingKey(
|
||||||
cb->connection,
|
cb->connection,
|
||||||
csrk,
|
&signing->csrk,
|
||||||
cb->csrk_mitm_protected
|
cb->csrk_mitm_protected
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -838,6 +854,7 @@ void GenericSecurityManager::on_connected(
|
||||||
const BLEProtocol::AddressBytes_t local_address,
|
const BLEProtocol::AddressBytes_t local_address,
|
||||||
const Gap::ConnectionParams_t *connection_params
|
const Gap::ConnectionParams_t *connection_params
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = acquire_control_block(connection);
|
ControlBlock_t *cb = acquire_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -876,6 +893,7 @@ void GenericSecurityManager::on_disconnected(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
Gap::DisconnectionReason_t reason
|
Gap::DisconnectionReason_t reason
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -994,6 +1012,7 @@ void GenericSecurityManager::on_pairing_timed_out(connection_handle_t connection
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericSecurityManager::on_pairing_completed(connection_handle_t connection) {
|
void GenericSecurityManager::on_pairing_completed(connection_handle_t connection) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (cb) {
|
if (cb) {
|
||||||
// set the distribution flags in the db
|
// set the distribution flags in the db
|
||||||
|
@ -1022,6 +1041,7 @@ void GenericSecurityManager::on_signed_write_received(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
sign_count_t sign_counter
|
sign_count_t sign_counter
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1055,6 +1075,7 @@ void GenericSecurityManager::on_signed_write_verification_failure(
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericSecurityManager::on_signed_write() {
|
void GenericSecurityManager::on_signed_write() {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
_db->set_local_sign_counter(_db->get_local_sign_counter() + 1);
|
_db->set_local_sign_counter(_db->get_local_sign_counter() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1226,6 +1247,7 @@ void GenericSecurityManager::on_secure_connections_ltk_generated(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
const ltk_t <k
|
const ltk_t <k
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1241,6 +1263,7 @@ void GenericSecurityManager::on_keys_distributed_ltk(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
const ltk_t <k
|
const ltk_t <k
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1254,6 +1277,7 @@ void GenericSecurityManager::on_keys_distributed_ediv_rand(
|
||||||
const ediv_t &ediv,
|
const ediv_t &ediv,
|
||||||
const rand_t &rand
|
const rand_t &rand
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1266,6 +1290,7 @@ void GenericSecurityManager::on_keys_distributed_local_ltk(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
const ltk_t <k
|
const ltk_t <k
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1279,6 +1304,7 @@ void GenericSecurityManager::on_keys_distributed_local_ediv_rand(
|
||||||
const ediv_t &ediv,
|
const ediv_t &ediv,
|
||||||
const rand_t &rand
|
const rand_t &rand
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1291,6 +1317,7 @@ void GenericSecurityManager::on_keys_distributed_irk(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
const irk_t &irk
|
const irk_t &irk
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1304,6 +1331,7 @@ void GenericSecurityManager::on_keys_distributed_bdaddr(
|
||||||
advertising_peer_address_type_t peer_address_type,
|
advertising_peer_address_type_t peer_address_type,
|
||||||
const address_t &peer_identity_address
|
const address_t &peer_identity_address
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1320,6 +1348,7 @@ void GenericSecurityManager::on_keys_distributed_csrk(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
const csrk_t &csrk
|
const csrk_t &csrk
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1341,6 +1370,7 @@ void GenericSecurityManager::on_ltk_request(
|
||||||
const ediv_t &ediv,
|
const ediv_t &ediv,
|
||||||
const rand_t &rand
|
const rand_t &rand
|
||||||
) {
|
) {
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
@ -1379,6 +1409,7 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
|
||||||
|
|
||||||
void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
|
void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
|
||||||
{
|
{
|
||||||
|
MBED_ASSERT(_db);
|
||||||
ControlBlock_t *cb = get_control_block(connection);
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
if (!cb) {
|
if (!cb) {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue