mirror of https://github.com/ARMmbed/mbed-os.git
commit
b43f27a7c7
|
@ -417,6 +417,9 @@ public:
|
|||
* support out-of-band exchanges of security data.
|
||||
* @param[in] passkey To specify a static passkey.
|
||||
* @param[in] signing Generate and distribute signing key during pairing
|
||||
* @param[in] dbPath Path to the folder used to store keys in the filesystem,
|
||||
* if NULL keys will be only stored in memory
|
||||
*
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
|
@ -424,12 +427,14 @@ public:
|
|||
bool requireMITM = true,
|
||||
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
||||
const Passkey_t passkey = NULL,
|
||||
bool signing = true) {
|
||||
bool signing = true,
|
||||
const char *dbPath = NULL) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)enableBonding;
|
||||
(void)requireMITM;
|
||||
(void)iocaps;
|
||||
(void)passkey;
|
||||
(void)dbPath;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */
|
||||
}
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/* 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);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void db_read(T *value, long int offset) {
|
||||
fseek(_db_file, offset, SEEK_SET);
|
||||
fread(value, sizeof(T), 1, _db_file);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void db_write(T *value, long int offset) {
|
||||
fseek(_db_file, offset, SEEK_SET);
|
||||
fwrite(value, sizeof(T), 1, _db_file);
|
||||
}
|
||||
|
||||
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(entry_handle_t db_handle);
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* Zero the db file.
|
||||
* @param db_file filehandle for file to erase
|
||||
* @return filehandle when successful, otherwise NULL
|
||||
*/
|
||||
static FILE* erase_db_file(FILE* db_file);
|
||||
|
||||
private:
|
||||
entry_t _entries[MAX_ENTRIES];
|
||||
FILE *_db_file;
|
||||
uint8_t _buffer[sizeof(SecurityEntryKeys_t)];
|
||||
};
|
||||
|
||||
} /* namespace pal */
|
||||
} /* namespace ble */
|
||||
|
||||
#endif /*GENERIC_FILE_SECURITY_DB_H_*/
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "ble/pal/GapTypes.h"
|
||||
#include "ble/BLETypes.h"
|
||||
#include "ble/pal/SecurityDb.h"
|
||||
#include "ble/generic/SecurityDb.h"
|
||||
#include "platform/Callback.h"
|
||||
#include "ble/pal/ConnectionEventMonitor.h"
|
||||
#include "ble/pal/SigningEventMonitor.h"
|
||||
|
@ -37,8 +37,6 @@ class GenericSecurityManager : public SecurityManager,
|
|||
public pal::ConnectionEventMonitor::EventHandler,
|
||||
public pal::SigningEventMonitor::EventHandler {
|
||||
public:
|
||||
typedef ble::pal::SecurityDistributionFlags_t SecurityDistributionFlags_t;
|
||||
typedef ble::pal::SecurityEntryKeys_t SecurityEntryKeys_t;
|
||||
|
||||
/* implements SecurityManager */
|
||||
|
||||
|
@ -51,7 +49,8 @@ public:
|
|||
bool mitm = true,
|
||||
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
||||
const Passkey_t passkey = NULL,
|
||||
bool signing = true
|
||||
bool signing = true,
|
||||
const char* db_path = NULL
|
||||
);
|
||||
|
||||
virtual ble_error_t reset();
|
||||
|
@ -236,13 +235,12 @@ public:
|
|||
public:
|
||||
GenericSecurityManager(
|
||||
pal::SecurityManager &palImpl,
|
||||
pal::SecurityDb &dbImpl,
|
||||
pal::ConnectionEventMonitor &connMonitorImpl,
|
||||
pal::SigningEventMonitor &signingMonitorImpl
|
||||
) : _pal(palImpl),
|
||||
_db(dbImpl),
|
||||
_connection_monitor(connMonitorImpl),
|
||||
_signing_monitor(signingMonitorImpl),
|
||||
_db(NULL),
|
||||
_default_authentication(0),
|
||||
_default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL),
|
||||
_pairing_authorisation_required(false),
|
||||
|
@ -256,6 +254,10 @@ public:
|
|||
_oob_local_random[0] = 1;
|
||||
}
|
||||
|
||||
~GenericSecurityManager() {
|
||||
delete _db;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Helper functions
|
||||
//
|
||||
|
@ -308,7 +310,7 @@ private:
|
|||
* @param[in] entryKeys security entry containing keys.
|
||||
*/
|
||||
void enable_encryption_cb(
|
||||
pal::SecurityDb::entry_handle_t entry,
|
||||
SecurityDb::entry_handle_t entry,
|
||||
const SecurityEntryKeys_t* entryKeys
|
||||
);
|
||||
|
||||
|
@ -319,7 +321,7 @@ private:
|
|||
* @param[in] entryKeys security entry containing keys.
|
||||
*/
|
||||
void set_ltk_cb(
|
||||
pal::SecurityDb::entry_handle_t entry,
|
||||
SecurityDb::entry_handle_t entry,
|
||||
const SecurityEntryKeys_t* entryKeys
|
||||
);
|
||||
|
||||
|
@ -327,24 +329,22 @@ private:
|
|||
* Returns the CSRK for the connection. Called by the security db.
|
||||
*
|
||||
* @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(
|
||||
pal::SecurityDb::entry_handle_t connection,
|
||||
const csrk_t *csrk,
|
||||
sign_count_t sign_counter
|
||||
SecurityDb::entry_handle_t connection,
|
||||
const SecurityEntrySigning_t *signing
|
||||
);
|
||||
|
||||
/**
|
||||
* Set the peer CSRK for the connection. Called by the security db.
|
||||
*
|
||||
* @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(
|
||||
pal::SecurityDb::entry_handle_t connection,
|
||||
const csrk_t *csrk,
|
||||
sign_count_t sign_counter
|
||||
SecurityDb::entry_handle_t connection,
|
||||
const SecurityEntrySigning_t *signing
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -407,8 +407,8 @@ private:
|
|||
* @param identity The identity associated with the entry; may be NULL.
|
||||
*/
|
||||
void on_security_entry_retrieved(
|
||||
pal::SecurityDb::entry_handle_t entry,
|
||||
const pal::SecurityEntryIdentity_t* identity
|
||||
SecurityDb::entry_handle_t entry,
|
||||
const SecurityEntryIdentity_t* identity
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -421,12 +421,12 @@ private:
|
|||
* @param count Number of identities entries retrieved.
|
||||
*/
|
||||
void on_identity_list_retrieved(
|
||||
ble::ArrayView<pal::SecurityEntryIdentity_t*>& identity_list,
|
||||
ble::ArrayView<SecurityEntryIdentity_t>& identity_list,
|
||||
size_t count
|
||||
);
|
||||
|
||||
private:
|
||||
struct ControlBlock_t : public pal::SecurityDistributionFlags_t {
|
||||
struct ControlBlock_t {
|
||||
ControlBlock_t();
|
||||
|
||||
pal::KeyDistribution get_initiator_key_distribution() {
|
||||
|
@ -443,7 +443,7 @@ private:
|
|||
};
|
||||
|
||||
connection_handle_t connection;
|
||||
pal::SecurityDb::entry_handle_t db_entry;
|
||||
SecurityDb::entry_handle_t db_entry;
|
||||
|
||||
address_t local_address; /**< address used for connection, possibly different from identity */
|
||||
|
||||
|
@ -473,10 +473,11 @@ private:
|
|||
};
|
||||
|
||||
pal::SecurityManager &_pal;
|
||||
pal::SecurityDb &_db;
|
||||
pal::ConnectionEventMonitor &_connection_monitor;
|
||||
pal::SigningEventMonitor &_signing_monitor;
|
||||
|
||||
SecurityDb *_db;
|
||||
|
||||
/* OOB data */
|
||||
address_t _oob_local_address;
|
||||
address_t _oob_peer_address;
|
||||
|
@ -718,7 +719,7 @@ public:
|
|||
|
||||
ControlBlock_t* get_control_block(const address_t &peer_address);
|
||||
|
||||
ControlBlock_t* get_control_block(pal::SecurityDb::entry_handle_t db_entry);
|
||||
ControlBlock_t* get_control_block(SecurityDb::entry_handle_t db_entry);
|
||||
|
||||
void release_control_block(ControlBlock_t* entry);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
/* 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_MEMORY_SECURITY_DB_H_
|
||||
#define GENERIC_MEMORY_SECURITY_DB_H_
|
||||
|
||||
#include "SecurityDb.h"
|
||||
|
||||
namespace ble {
|
||||
namespace generic {
|
||||
|
||||
/** Naive memory implementation for verification. */
|
||||
class MemorySecurityDb : public SecurityDb {
|
||||
private:
|
||||
struct entry_t {
|
||||
entry_t() { };
|
||||
SecurityDistributionFlags_t flags;
|
||||
SecurityEntryKeys_t local_keys;
|
||||
SecurityEntryKeys_t peer_keys;
|
||||
SecurityEntryIdentity_t peer_identity;
|
||||
SecurityEntrySigning_t peer_signing;
|
||||
};
|
||||
|
||||
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:
|
||||
MemorySecurityDb() : SecurityDb() { }
|
||||
virtual ~MemorySecurityDb() { }
|
||||
|
||||
virtual SecurityDistributionFlags_t* get_distribution_flags(
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
return reinterpret_cast<SecurityDistributionFlags_t*>(db_handle);
|
||||
}
|
||||
|
||||
/* local keys */
|
||||
|
||||
/* set */
|
||||
virtual void set_entry_local_ltk(
|
||||
entry_handle_t db_handle,
|
||||
const ltk_t <k
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->flags.ltk_sent = true;
|
||||
entry->local_keys.ltk = ltk;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void 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) {
|
||||
entry->local_keys.ediv = ediv;
|
||||
entry->local_keys.rand = rand;
|
||||
}
|
||||
}
|
||||
|
||||
/* peer's keys */
|
||||
|
||||
/* set */
|
||||
|
||||
virtual void set_entry_peer_ltk(
|
||||
entry_handle_t db_handle,
|
||||
const ltk_t <k
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->peer_keys.ltk = ltk;
|
||||
entry->flags.ltk_stored = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void 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) {
|
||||
entry->peer_keys.ediv = ediv;
|
||||
entry->peer_keys.rand = rand;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_entry_peer_irk(
|
||||
entry_handle_t db_handle,
|
||||
const irk_t &irk
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->peer_identity.irk = irk;
|
||||
entry->flags.irk_stored = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void 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) {
|
||||
entry->peer_identity.identity_address = peer_address;
|
||||
entry->peer_identity.identity_address_is_public = address_is_public;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_entry_peer_csrk(
|
||||
entry_handle_t db_handle,
|
||||
const csrk_t &csrk
|
||||
) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (entry) {
|
||||
entry->flags.csrk_stored = true;
|
||||
entry->peer_signing.csrk = csrk;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void 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_signing.counter = sign_counter;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
virtual uint8_t get_entry_count() {
|
||||
return MAX_ENTRIES;
|
||||
}
|
||||
|
||||
virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) {
|
||||
if (index < MAX_ENTRIES) {
|
||||
return &_entries[index].flags;
|
||||
} else {
|
||||
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:
|
||||
entry_t _entries[MAX_ENTRIES];
|
||||
};
|
||||
|
||||
} /* namespace pal */
|
||||
} /* namespace ble */
|
||||
|
||||
#endif /*GENERIC_MEMORY_SECURITY_DB_H_*/
|
|
@ -0,0 +1,752 @@
|
|||
/* 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_SECURITY_MANAGER_DB_H__
|
||||
#define GENERIC_SECURITY_MANAGER_DB_H__
|
||||
|
||||
#include "platform/Callback.h"
|
||||
#include "ble/pal/GapTypes.h"
|
||||
#include "ble/BLETypes.h"
|
||||
#include "ble/Gap.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace ble {
|
||||
namespace generic {
|
||||
|
||||
|
||||
/**
|
||||
* Security flags associated with a bond.
|
||||
*/
|
||||
struct SecurityDistributionFlags_t {
|
||||
SecurityDistributionFlags_t() :
|
||||
peer_address(),
|
||||
encryption_key_size(0),
|
||||
peer_address_is_public(false),
|
||||
csrk_stored(false),
|
||||
ltk_stored(false),
|
||||
ltk_sent(false),
|
||||
irk_stored(false),
|
||||
csrk_mitm_protected(false),
|
||||
ltk_mitm_protected(false),
|
||||
secure_connections_paired(false),
|
||||
connected(false) {
|
||||
}
|
||||
|
||||
/** peer address */
|
||||
address_t peer_address;
|
||||
|
||||
/** encryption key size */
|
||||
uint8_t encryption_key_size;
|
||||
/** true if peer address is public, false if it's static random */
|
||||
uint8_t peer_address_is_public:1;
|
||||
|
||||
/** CSRK (Connection Signature Resolving Key) has been distributed and stored */
|
||||
uint8_t csrk_stored:1;
|
||||
/** LTK (Long Term Key) has been distributed and stored */
|
||||
uint8_t ltk_stored:1;
|
||||
uint8_t ltk_sent:1;
|
||||
/** the security entry has been distributed and stored */
|
||||
uint8_t irk_stored:1;
|
||||
|
||||
/** CSRK that is stored has MITM protection */
|
||||
uint8_t csrk_mitm_protected:1;
|
||||
/** LTK that is stored has MITM protection */
|
||||
uint8_t ltk_mitm_protected:1;
|
||||
/** the current pairing was done using Secure Connections */
|
||||
uint8_t secure_connections_paired:1;
|
||||
uint8_t connected:1;
|
||||
};
|
||||
|
||||
/** Long Term Key and data used to identify it */
|
||||
struct SecurityEntryKeys_t {
|
||||
/** Long Term Key */
|
||||
ltk_t ltk;
|
||||
/** EDIV (Encryption diversifier) used to identify LTK during legacy pairing */
|
||||
ediv_t ediv;
|
||||
/** Rand (random number) used to identify LTK during legacy pairing */
|
||||
rand_t rand;
|
||||
};
|
||||
|
||||
/** CSRK and sign counter used to verify messages */
|
||||
struct SecurityEntrySigning_t {
|
||||
SecurityEntrySigning_t() : counter(0) { };
|
||||
/** 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 */
|
||||
struct SecurityEntryIdentity_t {
|
||||
/** identity address */
|
||||
address_t identity_address;
|
||||
/** Identity Resolving Key */
|
||||
irk_t irk;
|
||||
/** true if peer identity address is public, false if it's static random */
|
||||
uint8_t identity_address_is_public:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* SecurityDb holds the state for active connections and bonded devices.
|
||||
* Keys can be stored in NVM and are returned via callbacks.
|
||||
* SecurityDb is responsible for serialising any requests and keeping
|
||||
* the store in a consistent state.
|
||||
* Active connections state must be returned immediately.
|
||||
*/
|
||||
class SecurityDb {
|
||||
public:
|
||||
/**
|
||||
* Opaque type representing a handle to a database entry.
|
||||
*/
|
||||
typedef void* entry_handle_t;
|
||||
|
||||
/* callbacks for asynchronous data retrieval from the security db */
|
||||
|
||||
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryKeys_t*)>
|
||||
SecurityEntryKeysDbCb_t;
|
||||
typedef mbed::Callback<void(entry_handle_t, const SecurityEntrySigning_t*)>
|
||||
SecurityEntrySigningDbCb_t;
|
||||
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryIdentity_t*)>
|
||||
SecurityEntryIdentityDbCb_t;
|
||||
typedef mbed::Callback<void(ArrayView<SecurityEntryIdentity_t>&, size_t count)>
|
||||
IdentitylistDbCb_t;
|
||||
typedef mbed::Callback<void(::Gap::Whitelist_t*)>
|
||||
WhitelistDbCb_t;
|
||||
|
||||
SecurityDb() : _local_sign_counter(0) { };
|
||||
virtual ~SecurityDb() { };
|
||||
|
||||
/**
|
||||
* Return immediately security flags associated to a db entry.
|
||||
*
|
||||
* @param[in] db_handle Entry of the database queried.
|
||||
* @return pointer to the flags or NULL if the entry do not have any
|
||||
* associated flags.
|
||||
*/
|
||||
virtual SecurityDistributionFlags_t* get_distribution_flags(
|
||||
entry_handle_t db_handle
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Set the distribution flags of a DB entry.
|
||||
*
|
||||
* @param[in] db_handle Entry of the database that will store the flags.
|
||||
* @param[in] flags Distribution flags to store in @p db_handle.
|
||||
*/
|
||||
virtual void set_distribution_flags(
|
||||
entry_handle_t db_handle,
|
||||
const SecurityDistributionFlags_t& new_flags
|
||||
) {
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags) {
|
||||
*flags = new_flags;
|
||||
}
|
||||
}
|
||||
|
||||
/* local keys */
|
||||
|
||||
/**
|
||||
* Retrieve stored LTK based on passed in EDIV and RAND values.
|
||||
*
|
||||
* @param[in] cb callback that will receive the LTK struct
|
||||
* @param[in] db_handle handle of the entry being queried.
|
||||
* @param[in] ediv 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(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
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.
|
||||
*
|
||||
* @param[in] cb callback that will receive the LTK struct
|
||||
* @param[in] db_handle handle of the entry being queried.
|
||||
*/
|
||||
virtual void get_entry_local_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
* will be used when link is encrypted
|
||||
*/
|
||||
virtual void set_entry_local_ltk(
|
||||
entry_handle_t db_handle,
|
||||
const ltk_t <k
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update EDIV and RAND used to identify the LTK.
|
||||
*
|
||||
* @param[in] db_handle handle of the entry being updated.
|
||||
* @param[in] ediv new EDIV value
|
||||
* @param[in] rand new RAND value
|
||||
*/
|
||||
virtual void set_entry_local_ediv_rand(
|
||||
entry_handle_t db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) = 0;
|
||||
|
||||
/* peer's keys */
|
||||
|
||||
/**
|
||||
* Return asynchronously the peer signing key through a callback
|
||||
* so that signed packets can be verified.
|
||||
*
|
||||
* @param[in] cb callback which will receive the key
|
||||
* @param[in] db_handle handle of the entry being queried.
|
||||
*/
|
||||
virtual void get_entry_peer_csrk(
|
||||
SecurityEntrySigningDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
SecurityEntrySigning_t* signing = read_in_entry_peer_signing(db_handle);
|
||||
cb(db_handle, signing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return asynchronously the peer encryption key through a callback
|
||||
* so that encryption can be enabled.
|
||||
*
|
||||
* @param[in] cb callback which will receive the key
|
||||
* @param[in] db_handle handle of the entry being queried.
|
||||
*/
|
||||
virtual void get_entry_peer_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
SecurityEntryKeys_t* keys = read_in_entry_peer_keys(db_handle);
|
||||
cb(db_handle, keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save new LTK received from the peer.
|
||||
*
|
||||
* @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
|
||||
* that will be used when link is encrypted
|
||||
*/
|
||||
virtual void set_entry_peer_ltk(
|
||||
entry_handle_t db_handle,
|
||||
const ltk_t <k
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update EDIV and RAND used to identify the LTK sent by the peer.
|
||||
*
|
||||
* @param[in] db_handle handle of the entry being updated.
|
||||
* @param[in] ediv new EDIV value
|
||||
* @param[in] rand new RAND value
|
||||
*/
|
||||
virtual void set_entry_peer_ediv_rand(
|
||||
entry_handle_t db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update IRK for this connection.
|
||||
*
|
||||
* @param[in] db_handle handle of the entry being updated.
|
||||
* @param[in] irk new IRK value
|
||||
*/
|
||||
virtual void set_entry_peer_irk(
|
||||
entry_handle_t db_handle,
|
||||
const irk_t &irk
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update the identity address of the peer.
|
||||
*
|
||||
* @param[in] db_handle handle of the entry being updated.
|
||||
* @param[in] address_is_public is the identity address public or private
|
||||
* @param[in] peer_address the new address
|
||||
*/
|
||||
virtual void set_entry_peer_bdaddr(
|
||||
entry_handle_t db_handle,
|
||||
bool address_is_public,
|
||||
const address_t &peer_address
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve stored identity address and IRK.
|
||||
*
|
||||
* @param[in] cb callback that will receive the SecurityEntryIdentity_t struct
|
||||
* @param[in] db_handle handle of the entry being queried.
|
||||
*/
|
||||
virtual void get_entry_identity(
|
||||
SecurityEntryIdentityDbCb_t cb,
|
||||
entry_handle_t db_handle
|
||||
) {
|
||||
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.
|
||||
* Function takes ownership of the memory. The identity list and the
|
||||
* ownership will be returned in the callback.
|
||||
*
|
||||
* @param[in] cb callback that will receive the whitelist
|
||||
* @param[in] identity_list preallocated identity_list that will be filled
|
||||
* in.
|
||||
*/
|
||||
virtual void get_identity_list(
|
||||
IdentitylistDbCb_t cb,
|
||||
ArrayView<SecurityEntryIdentity_t>& identity_list
|
||||
) {
|
||||
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.
|
||||
*
|
||||
* @param[in] db_handle handle of the entry being updated.
|
||||
* @param[in] csrk new CSRK value
|
||||
*/
|
||||
virtual void set_entry_peer_csrk(
|
||||
entry_handle_t db_handle,
|
||||
const csrk_t &csrk
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update peer signing counter.
|
||||
*
|
||||
* @param[in] db_handle handle of the entry being updated.
|
||||
* @param[in] sign_counter new signing counter value
|
||||
*/
|
||||
virtual void set_entry_peer_sign_counter(
|
||||
entry_handle_t db_handle,
|
||||
sign_count_t sign_counter
|
||||
) = 0;
|
||||
|
||||
/* local csrk */
|
||||
|
||||
/**
|
||||
* Return local signing key used for signing packets.
|
||||
*
|
||||
* @return pointer to local CSRK
|
||||
*/
|
||||
virtual const csrk_t* get_local_csrk() {
|
||||
return &_local_csrk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return local signing counter.
|
||||
*
|
||||
* @return signing counter
|
||||
*/
|
||||
virtual sign_count_t get_local_sign_counter() {
|
||||
return _local_sign_counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update local signing key.
|
||||
*
|
||||
* @param[in] csrk new CSRK value
|
||||
*/
|
||||
virtual void set_local_csrk(
|
||||
const csrk_t &csrk
|
||||
) {
|
||||
_local_csrk = csrk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update local signing counter.
|
||||
*
|
||||
* @param[in] sign_counter new signing counter value
|
||||
*/
|
||||
virtual void set_local_sign_counter(
|
||||
sign_count_t sign_counter
|
||||
) {
|
||||
_local_sign_counter = sign_counter;
|
||||
}
|
||||
|
||||
/* list management */
|
||||
|
||||
/**
|
||||
* Open a database entry.
|
||||
*
|
||||
* While this entry is opened; it can be queried and updated with the help
|
||||
* of the database setter and getter functions.
|
||||
*
|
||||
* @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 open_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) {
|
||||
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 =
|
||||
(peer_address_type == BLEProtocol::AddressType::PUBLIC) ||
|
||||
(peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY);
|
||||
|
||||
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);
|
||||
|
||||
/* only look among disconnected entries */
|
||||
if (flags && !flags->connected) {
|
||||
if (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY &&
|
||||
flags->irk_stored == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* lookup for connection address used during bonding */
|
||||
if (flags->peer_address == peer_address &&
|
||||
flags->peer_address_is_public == peer_address_public) {
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* look for the identity address if stored */
|
||||
if (flags->irk_stored) {
|
||||
SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle);
|
||||
|
||||
if (identity &&
|
||||
identity->identity_address == peer_address &&
|
||||
identity->identity_address_is_public == peer_address_public) {
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a connection entry.
|
||||
*
|
||||
* @param[in] db_handle this handle will be freed up from the security db.
|
||||
*/
|
||||
virtual void close_entry(entry_handle_t db_handle) {
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags) {
|
||||
flags->connected = false;
|
||||
}
|
||||
sync(db_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove entry for this peer from NVM.
|
||||
*
|
||||
* @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 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.
|
||||
*/
|
||||
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.
|
||||
* Function takes ownership of the memory. The whitelist and the ownership
|
||||
* will be returned in the callback.
|
||||
*
|
||||
* @param[in] cb callback that will receive the whitelist
|
||||
* @param[in] whitelist preallocated whitelist that will be filled in
|
||||
*/
|
||||
virtual void get_whitelist(
|
||||
WhitelistDbCb_t cb,
|
||||
::Gap::Whitelist_t *whitelist
|
||||
) {
|
||||
/*TODO: fill whitelist*/
|
||||
cb(whitelist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously return a whitelist through a callback, generated from the
|
||||
* bond table.
|
||||
*
|
||||
* @param[in] cb callback that will receive the whitelist
|
||||
* @param[in] whitelist preallocated whitelist that will be filled in
|
||||
*/
|
||||
virtual void generate_whitelist_from_bond_table(
|
||||
WhitelistDbCb_t cb,
|
||||
::Gap::Whitelist_t *whitelist
|
||||
) {
|
||||
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.
|
||||
*
|
||||
* @param[in] whitelist
|
||||
*/
|
||||
virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) { };
|
||||
|
||||
/**
|
||||
* Add a new entry to the whitelist in the NVM.
|
||||
*
|
||||
* @param[in] address new whitelist entry
|
||||
*/
|
||||
virtual void add_whitelist_entry(const address_t &address) { };
|
||||
|
||||
/**
|
||||
* Remove whitelist entry from NVM.
|
||||
*
|
||||
* @param[in] address entry to be removed
|
||||
*/
|
||||
virtual void remove_whitelist_entry(const address_t &address) { };
|
||||
|
||||
/**
|
||||
*Remove all whitelist entries stored in the NVM.
|
||||
*/
|
||||
virtual void clear_whitelist() { };
|
||||
|
||||
/* saving and loading from nvm */
|
||||
|
||||
/**
|
||||
* Read values from storage.
|
||||
*/
|
||||
virtual void restore() { };
|
||||
|
||||
/**
|
||||
* Flush all values which might be stored in memory into NVM.
|
||||
*/
|
||||
virtual void sync(entry_handle_t db_handle) { };
|
||||
|
||||
/**
|
||||
* Toggle whether values should be preserved across resets.
|
||||
*
|
||||
* @param[in] reload if true values will be preserved across resets.
|
||||
*/
|
||||
virtual void set_restore(bool reload) { };
|
||||
|
||||
private:
|
||||
/**
|
||||
* Get an entry for a new connection not present in the db yet. This will find a free entry
|
||||
* or use a disconnected entry by reseting all the stored information.
|
||||
* @return empty entry for the new connection
|
||||
*/
|
||||
virtual SecurityDistributionFlags_t* get_free_entry_flags() {
|
||||
/* get a free one if available */
|
||||
SecurityDistributionFlags_t* match = NULL;
|
||||
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->ltk_stored
|
||||
&& !flags->ltk_sent
|
||||
&& !flags->irk_stored) {
|
||||
/* empty one found, stop looking*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
reset_entry(match);
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* How many entries can be stored in the databes.
|
||||
* @return max number of entries
|
||||
*/
|
||||
virtual uint8_t get_entry_count() = 0;
|
||||
|
||||
/**
|
||||
* Return database entry based on its index.
|
||||
* @param index index from 0 to get_entry_count()
|
||||
* @return databse entry stored at index
|
||||
*/
|
||||
virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) = 0;
|
||||
|
||||
/**
|
||||
* Delete all the information.
|
||||
* @param db_handle handle for the entry to be reset
|
||||
*/
|
||||
virtual void reset_entry(entry_handle_t db_handle) = 0;
|
||||
|
||||
/**
|
||||
* This will read in the requested information into a buffer that will remain valid
|
||||
* until another read_in call is made.
|
||||
* @param db_handle handle of the entry to be read
|
||||
* @return pointer to buffer holding the query result, NULL when not found
|
||||
*/
|
||||
virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle) = 0;
|
||||
|
||||
/**
|
||||
* This will read in the requested information into a buffer that will remain valid
|
||||
* until another read_in call is made.
|
||||
* @param db_handle handle of the entry to be read
|
||||
* @return pointer to buffer holding the query result, NULL when not found
|
||||
*/
|
||||
virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle) = 0;
|
||||
|
||||
/**
|
||||
* This will read in the requested information into a buffer that will remain valid
|
||||
* until another read_in call is made.
|
||||
* @param db_handle handle of the entry to be read
|
||||
* @return pointer to buffer holding the query result, NULL when not found
|
||||
*/
|
||||
virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle) = 0;
|
||||
|
||||
/**
|
||||
* This will read in the requested information into a buffer that will remain valid
|
||||
* until another read_in call is made.
|
||||
* @param db_handle handle of the entry to be read
|
||||
* @return pointer to buffer holding the query result, NULL when not found
|
||||
*/
|
||||
virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle) = 0;
|
||||
|
||||
protected:
|
||||
SecurityEntryIdentity_t _local_identity;
|
||||
csrk_t _local_csrk;
|
||||
sign_count_t _local_sign_counter;
|
||||
};
|
||||
|
||||
} /* namespace pal */
|
||||
} /* namespace ble */
|
||||
|
||||
#endif /*GENERIC_SECURITY_MANAGER_DB_H__*/
|
|
@ -1,446 +0,0 @@
|
|||
/* 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 PAL_MEMORY_SECURITY_DB_H_
|
||||
#define PAL_MEMORY_SECURITY_DB_H_
|
||||
|
||||
#include "SecurityDb.h"
|
||||
|
||||
namespace ble {
|
||||
namespace pal {
|
||||
|
||||
/** Naive memory implementation for verification. */
|
||||
class MemorySecurityDb : public SecurityDb {
|
||||
private:
|
||||
enum state_t {
|
||||
ENTRY_FREE,
|
||||
ENTRY_RESERVED,
|
||||
ENTRY_WRITTEN
|
||||
};
|
||||
|
||||
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 entry_t* as_entry(entry_handle_t entry_handle)
|
||||
{
|
||||
return reinterpret_cast<entry_t*>(entry_handle);
|
||||
}
|
||||
|
||||
public:
|
||||
MemorySecurityDb() : _local_sign_counter(0) { }
|
||||
virtual ~MemorySecurityDb() { }
|
||||
|
||||
virtual const SecurityDistributionFlags_t* get_distribution_flags(
|
||||
entry_handle_t entry_handle
|
||||
) {
|
||||
entry_t* entry = as_entry(entry_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 */
|
||||
|
||||
/* 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 */
|
||||
virtual void set_entry_local_ltk(
|
||||
entry_handle_t entry_handle,
|
||||
const ltk_t <k
|
||||
) {
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry) {
|
||||
entry->state = ENTRY_WRITTEN;
|
||||
entry->local_keys.ltk = ltk;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_entry_local_ediv_rand(
|
||||
entry_handle_t entry_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry) {
|
||||
entry->state = ENTRY_WRITTEN;
|
||||
entry->local_keys.ediv = ediv;
|
||||
entry->local_keys.rand = rand;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
virtual void set_entry_peer_ltk(
|
||||
entry_handle_t entry_handle,
|
||||
const ltk_t <k
|
||||
) {
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry) {
|
||||
entry->state = ENTRY_WRITTEN;
|
||||
entry->peer_keys.ltk = ltk;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_entry_peer_ediv_rand(
|
||||
entry_handle_t entry_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry) {
|
||||
entry->state = ENTRY_WRITTEN;
|
||||
entry->peer_keys.ediv = ediv;
|
||||
entry->peer_keys.rand = rand;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_entry_peer_irk(
|
||||
entry_handle_t entry_handle,
|
||||
const irk_t &irk
|
||||
) {
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry) {
|
||||
entry->state = ENTRY_WRITTEN;
|
||||
entry->peer_identity.irk = irk;
|
||||
entry->flags.irk_stored = true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_entry_peer_bdaddr(
|
||||
entry_handle_t entry_handle,
|
||||
bool address_is_public,
|
||||
const address_t &peer_address
|
||||
) {
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry) {
|
||||
entry->state = ENTRY_WRITTEN;
|
||||
entry->peer_identity.identity_address = peer_address;
|
||||
entry->peer_identity.identity_address_is_public = address_is_public;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_entry_peer_csrk(
|
||||
entry_handle_t entry_handle,
|
||||
const csrk_t &csrk
|
||||
) {
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry) {
|
||||
entry->state = ENTRY_WRITTEN;
|
||||
entry->csrk = csrk;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_entry_peer_sign_counter(
|
||||
entry_handle_t entry_handle,
|
||||
sign_count_t sign_counter
|
||||
) {
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry) {
|
||||
entry->state = ENTRY_WRITTEN;
|
||||
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 entry_handle_t open_entry(
|
||||
BLEProtocol::AddressType_t peer_address_type,
|
||||
const address_t &peer_address
|
||||
) {
|
||||
const bool peer_address_public =
|
||||
(peer_address_type == BLEProtocol::AddressType::PUBLIC) ||
|
||||
(peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY);
|
||||
|
||||
for (size_t i = 0; i < MAX_ENTRIES; i++) {
|
||||
entry_t& e = _entries[i];
|
||||
|
||||
if (e.state == ENTRY_FREE) {
|
||||
continue;
|
||||
} else {
|
||||
if (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY &&
|
||||
e.flags.irk_stored == false
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// lookup for the identity address then the connection address.
|
||||
if (e.flags.irk_stored &&
|
||||
e.peer_identity.identity_address == peer_address &&
|
||||
e.peer_identity.identity_address_is_public == peer_address_public
|
||||
) {
|
||||
return &e;
|
||||
// lookup for connection address used during bonding
|
||||
} else if (e.flags.peer_address == peer_address &&
|
||||
e.flags.peer_address_is_public == peer_address_public
|
||||
) {
|
||||
return &e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// determine if the address in input is private or not.
|
||||
bool is_private_address = false;
|
||||
if (peer_address_type == BLEProtocol::AddressType::RANDOM) {
|
||||
::Gap::RandomAddressType_t random_type(::Gap::RandomAddressType_t::STATIC);
|
||||
ble_error_t err = ::Gap::getRandomAddressType(peer_address.data(), &random_type);
|
||||
if (err) {
|
||||
return NULL;
|
||||
}
|
||||
if (random_type != ::Gap::RandomAddressType_t::STATIC) {
|
||||
is_private_address = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we din't find one grab the first disconnected slot*/
|
||||
for (size_t i = 0; i < MAX_ENTRIES; i++) {
|
||||
if (_entries[i].state == ENTRY_FREE) {
|
||||
_entries[i] = entry_t();
|
||||
// do not store private addresses in the flags; just store public
|
||||
// or random static address so it can be reused latter.
|
||||
if (is_private_address == false) {
|
||||
_entries[i].flags.peer_address = peer_address;
|
||||
_entries[i].flags.peer_address_is_public = peer_address_public;
|
||||
} else {
|
||||
_entries[i].flags.peer_address = address_t();
|
||||
}
|
||||
_entries[i].state = ENTRY_RESERVED;
|
||||
return &_entries[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void close_entry(entry_handle_t entry_handle)
|
||||
{
|
||||
entry_t *entry = as_entry(entry_handle);
|
||||
if (entry && entry->state == ENTRY_RESERVED) {
|
||||
entry->state = ENTRY_FREE;
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
entry_t _entries[MAX_ENTRIES];
|
||||
SecurityEntryIdentity_t _local_identity;
|
||||
csrk_t _local_csrk;
|
||||
sign_count_t _local_sign_counter;
|
||||
};
|
||||
|
||||
} /* namespace pal */
|
||||
} /* namespace ble */
|
||||
|
||||
#endif /*PAL_MEMORY_SECURITY_DB_H_*/
|
|
@ -1,462 +0,0 @@
|
|||
/* 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 PAL_SECURITY_MANAGER_DB_H__
|
||||
#define PAL_SECURITY_MANAGER_DB_H__
|
||||
|
||||
#include "platform/Callback.h"
|
||||
#include "ble/pal/GapTypes.h"
|
||||
#include "ble/BLETypes.h"
|
||||
#include "ble/Gap.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace ble {
|
||||
namespace pal {
|
||||
|
||||
|
||||
/**
|
||||
* Security flags associated with a bond.
|
||||
*/
|
||||
struct SecurityDistributionFlags_t {
|
||||
SecurityDistributionFlags_t() :
|
||||
peer_address(),
|
||||
encryption_key_size(0),
|
||||
peer_address_is_public(false),
|
||||
csrk_stored(false),
|
||||
csrk_mitm_protected(false),
|
||||
ltk_stored(false),
|
||||
ltk_mitm_protected(false),
|
||||
secure_connections_paired(false),
|
||||
irk_stored(false) {
|
||||
}
|
||||
|
||||
/** peer address */
|
||||
address_t peer_address;
|
||||
|
||||
/** encryption key size */
|
||||
uint8_t encryption_key_size;
|
||||
/** true if peer address is public, false if it's static random */
|
||||
uint8_t peer_address_is_public:1;
|
||||
|
||||
/** CSRK (Connection Signature Resolving Key) has been distributed and stored */
|
||||
uint8_t csrk_stored:1;
|
||||
/** CSRK that is stored has MITM protection */
|
||||
uint8_t csrk_mitm_protected:1;
|
||||
/** LTK (Long Term Key) has been distributed and stored */
|
||||
uint8_t ltk_stored:1;
|
||||
/** LTK that is stored has MITM protection */
|
||||
uint8_t ltk_mitm_protected:1;
|
||||
/** the current pairing was done using Secure Connections */
|
||||
uint8_t secure_connections_paired:1;
|
||||
/** the security entry has been distributed and stored */
|
||||
uint8_t irk_stored:1;
|
||||
};
|
||||
|
||||
/** Long Term Key and data used to identify it */
|
||||
struct SecurityEntryKeys_t {
|
||||
/** Long Term Key */
|
||||
ltk_t ltk;
|
||||
/** EDIV (Encryption diversifier) used to identify LTK during legacy pairing */
|
||||
ediv_t ediv;
|
||||
/** Rand (random number) used to identify LTK during legacy pairing */
|
||||
rand_t rand;
|
||||
};
|
||||
|
||||
/** Data for resolving random resolvable addresses */
|
||||
struct SecurityEntryIdentity_t {
|
||||
/** identity address */
|
||||
address_t identity_address;
|
||||
/** Identity Resolving Key */
|
||||
irk_t irk;
|
||||
/** true if peer identity address is public, false if it's static random */
|
||||
uint8_t identity_address_is_public:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* SecurityDb holds the state for active connections and bonded devices.
|
||||
* Keys can be stored in NVM and are returned via callbacks.
|
||||
* SecurityDb is responsible for serialising any requests and keeping
|
||||
* the store in a consistent state.
|
||||
* Active connections state must be returned immediately.
|
||||
*/
|
||||
class SecurityDb {
|
||||
public:
|
||||
/**
|
||||
* Opaque type representing a handle to a database entry.
|
||||
*/
|
||||
typedef void* entry_handle_t;
|
||||
|
||||
/* callbacks for asynchronous data retrieval from the security db */
|
||||
|
||||
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryKeys_t*)>
|
||||
SecurityEntryKeysDbCb_t;
|
||||
typedef mbed::Callback<void(entry_handle_t, const csrk_t*, uint32_t sign_counter)>
|
||||
SecurityEntryCsrkDbCb_t;
|
||||
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryIdentity_t*)>
|
||||
SecurityEntryIdentityDbCb_t;
|
||||
typedef mbed::Callback<void(ArrayView<SecurityEntryIdentity_t*>&, size_t count)>
|
||||
IdentitylistDbCb_t;
|
||||
typedef mbed::Callback<void(::Gap::Whitelist_t*)>
|
||||
WhitelistDbCb_t;
|
||||
|
||||
SecurityDb() { };
|
||||
virtual ~SecurityDb() { };
|
||||
|
||||
/**
|
||||
* Return immediately security flags associated to a db entry.
|
||||
*
|
||||
* @param[in] db_entry Entry of the database queried.
|
||||
* @return pointer to the flags or NULL if the entry do not have any
|
||||
* associated flags.
|
||||
*/
|
||||
virtual const SecurityDistributionFlags_t* get_distribution_flags(
|
||||
entry_handle_t db_entry
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Set the distribution flags of a DB entry.
|
||||
*
|
||||
* @param[in] db_entry Entry of the database that will store the flags.
|
||||
* @param[in] flags Distribution flags to store in @p db_entry.
|
||||
*/
|
||||
virtual void set_distribution_flags(
|
||||
entry_handle_t db_entry,
|
||||
const SecurityDistributionFlags_t& flags
|
||||
) = 0;
|
||||
|
||||
/* local keys */
|
||||
|
||||
/**
|
||||
* Retrieve stored LTK based on passed in EDIV and RAND values.
|
||||
*
|
||||
* @param[in] cb callback that will receive the LTK struct
|
||||
* @param[in] db_entry handle of the entry being queried.
|
||||
* @param[in] ediv 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(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_entry,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve stored LTK generated during secure connections pairing.
|
||||
*
|
||||
* @param[in] cb callback that will receive the LTK struct
|
||||
* @param[in] db_entry handle of the entry being queried.
|
||||
*/
|
||||
virtual void get_entry_local_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_entry
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Save new local LTK for a connection.
|
||||
*
|
||||
* @param[in] db_entry handle of the entry being updated.
|
||||
* @param[in] ltk the new LTK, if the device is slave, this is the LTK that
|
||||
* will be used when link is encrypted
|
||||
*/
|
||||
virtual void set_entry_local_ltk(
|
||||
entry_handle_t db_entry,
|
||||
const ltk_t <k
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update EDIV and RAND used to identify the LTK.
|
||||
*
|
||||
* @param[in] db_entry handle of the entry being updated.
|
||||
* @param[in] ediv new EDIV value
|
||||
* @param[in] rand new RAND value
|
||||
*/
|
||||
virtual void set_entry_local_ediv_rand(
|
||||
entry_handle_t db_entry,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) = 0;
|
||||
|
||||
/* peer's keys */
|
||||
|
||||
/**
|
||||
* Return asynchronously the peer signing key through a callback
|
||||
* so that signed packets can be verified.
|
||||
*
|
||||
* @param[in] cb callback which will receive the key
|
||||
* @param[in] db_entry handle of the entry being queried.
|
||||
*/
|
||||
virtual void get_entry_peer_csrk(
|
||||
SecurityEntryCsrkDbCb_t cb,
|
||||
entry_handle_t db_entry
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Return asynchronously the peer encryption key through a callback
|
||||
* so that encryption can be enabled.
|
||||
*
|
||||
* @param[in] cb callback which will receive the key
|
||||
* @param[in] db_entry handle of the entry being queried.
|
||||
*/
|
||||
virtual void get_entry_peer_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_entry
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Save new LTK received from the peer.
|
||||
*
|
||||
* @param[in] db_entry handle of the entry being updated.
|
||||
* @param[in] ltk the new LTK, if the peer device is slave, this is the LTK
|
||||
* that will be used when link is encrypted
|
||||
*/
|
||||
virtual void set_entry_peer_ltk(
|
||||
entry_handle_t db_entry,
|
||||
const ltk_t <k
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* 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] ediv new EDIV value
|
||||
* @param[in] rand new RAND value
|
||||
*/
|
||||
virtual void set_entry_peer_ediv_rand(
|
||||
entry_handle_t db_entry,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update IRK for this connection.
|
||||
*
|
||||
* @param[in] db_entry handle of the entry being updated.
|
||||
* @param[in] irk new IRK value
|
||||
*/
|
||||
virtual void set_entry_peer_irk(
|
||||
entry_handle_t db_entry,
|
||||
const irk_t &irk
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update the identity address of the peer.
|
||||
*
|
||||
* @param[in] db_entry handle of the entry being updated.
|
||||
* @param[in] address_is_public is the identity address public or private
|
||||
* @param[in] peer_address the new address
|
||||
*/
|
||||
virtual void set_entry_peer_bdaddr(
|
||||
entry_handle_t db_entry,
|
||||
bool address_is_public,
|
||||
const address_t &peer_address
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve stored identity address and IRK.
|
||||
*
|
||||
* @param[in] cb callback that will receive the SecurityEntryIdentity_t struct
|
||||
* @param[in] db_entry handle of the entry being queried.
|
||||
*/
|
||||
virtual void get_entry_identity(
|
||||
SecurityEntryIdentityDbCb_t cb,
|
||||
entry_handle_t db_entry
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Asynchronously return the identity list stored in NVM through a callback.
|
||||
* Function takes ownership of the memory. The identity list and the
|
||||
* ownership will be returned in the callback.
|
||||
*
|
||||
* @param[in] cb callback that will receive the whitelist
|
||||
* @param[in] identity_list preallocated identity_list that will be filled
|
||||
* in.
|
||||
*/
|
||||
virtual void get_identity_list(
|
||||
IdentitylistDbCb_t cb,
|
||||
ArrayView<SecurityEntryIdentity_t*>& identity_list
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update peer signing key.
|
||||
*
|
||||
* @param[in] db_entry handle of the entry being updated.
|
||||
* @param[in] csrk new CSRK value
|
||||
*/
|
||||
virtual void set_entry_peer_csrk(
|
||||
entry_handle_t db_entry,
|
||||
const csrk_t &csrk
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update peer signing counter.
|
||||
*
|
||||
* @param[in] db_entry handle of the entry being updated.
|
||||
* @param[in] sign_counter new signing counter value
|
||||
*/
|
||||
virtual void set_entry_peer_sign_counter(
|
||||
entry_handle_t db_entry,
|
||||
sign_count_t sign_counter
|
||||
) = 0;
|
||||
|
||||
/* local csrk */
|
||||
|
||||
/**
|
||||
* Return local signing key used for signing packets.
|
||||
*
|
||||
* @return pointer to local CSRK
|
||||
*/
|
||||
virtual const csrk_t* get_local_csrk() = 0;
|
||||
|
||||
/**
|
||||
* Return local signing counter.
|
||||
*
|
||||
* @return signing counter
|
||||
*/
|
||||
virtual sign_count_t get_local_sign_counter() = 0;
|
||||
|
||||
/**
|
||||
* Update local signing key.
|
||||
*
|
||||
* @param[in] csrk new CSRK value
|
||||
*/
|
||||
virtual void set_local_csrk(
|
||||
const csrk_t &csrk
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update local signing counter.
|
||||
*
|
||||
* @param[in] sign_counter new signing counter value
|
||||
*/
|
||||
virtual void set_local_sign_counter(
|
||||
sign_count_t sign_counter
|
||||
) = 0;
|
||||
|
||||
/* list management */
|
||||
|
||||
/**
|
||||
* Open a database entry.
|
||||
*
|
||||
* While this entry is opened; it can be queried and updated with the help
|
||||
* of the database setter and getter functions.
|
||||
*
|
||||
* @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 open_entry(
|
||||
BLEProtocol::AddressType_t peer_address_type,
|
||||
const address_t &peer_address
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Close a connection entry.
|
||||
*
|
||||
* @param[in] db_entry this handle will be freed up from the security db.
|
||||
*/
|
||||
virtual void close_entry(entry_handle_t db_entry) = 0;
|
||||
|
||||
/**
|
||||
* Remove entry for this peer from NVM.
|
||||
*
|
||||
* @param[in] peer_identity_address peer address that no longer needs NVM
|
||||
* storage.
|
||||
*/
|
||||
virtual void remove_entry(const address_t peer_identity_address) = 0;
|
||||
|
||||
/**
|
||||
* Remove all entries from the security DB.
|
||||
*/
|
||||
virtual void clear_entries() = 0;
|
||||
|
||||
/**
|
||||
* Asynchronously return the whitelist stored in NVM through a callback.
|
||||
* Function takes ownership of the memory. The whitelist and the ownership
|
||||
* will be returned in the callback.
|
||||
*
|
||||
* @param[in] cb callback that will receive the whitelist
|
||||
* @param[in] whitelist preallocated whitelist that will be filled in
|
||||
*/
|
||||
virtual void get_whitelist(
|
||||
WhitelistDbCb_t cb,
|
||||
::Gap::Whitelist_t *whitelist
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Asynchronously return a whitelist through a callback, generated from the
|
||||
* bond table.
|
||||
*
|
||||
* @param[in] cb callback that will receive the whitelist
|
||||
* @param[in] whitelist preallocated whitelist that will be filled in
|
||||
*/
|
||||
virtual void generate_whitelist_from_bond_table(
|
||||
WhitelistDbCb_t cb,
|
||||
::Gap::Whitelist_t *whitelist
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Update the whitelist stored in NVM by replacing it with new one.
|
||||
*
|
||||
* @param[in] whitelist
|
||||
*/
|
||||
virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) = 0;
|
||||
|
||||
/**
|
||||
* Add a new entry to the whitelist in the NVM.
|
||||
*
|
||||
* @param[in] address new whitelist entry
|
||||
*/
|
||||
virtual void add_whitelist_entry(const address_t &address) = 0;
|
||||
|
||||
/**
|
||||
* Remove whitelist entry from NVM.
|
||||
*
|
||||
* @param[in] address entry to be removed
|
||||
*/
|
||||
virtual void remove_whitelist_entry(const address_t &address) = 0;
|
||||
|
||||
/**
|
||||
*Remove all whitelist entries stored in the NVM.
|
||||
*/
|
||||
virtual void clear_whitelist() = 0;
|
||||
|
||||
/* saving and loading from nvm */
|
||||
|
||||
/**
|
||||
* Read values from storage.
|
||||
*/
|
||||
virtual void restore() = 0;
|
||||
|
||||
/**
|
||||
* Flush all values which might be stored in memory into NVM.
|
||||
*/
|
||||
virtual void sync() = 0;
|
||||
|
||||
/**
|
||||
* Toggle whether values should be preserved across resets.
|
||||
*
|
||||
* @param[in] reload if true values will be preserved across resets.
|
||||
*/
|
||||
virtual void set_restore(bool reload) = 0;
|
||||
};
|
||||
|
||||
} /* namespace pal */
|
||||
} /* namespace ble */
|
||||
|
||||
#endif /*PAL_SECURITY_MANAGER_DB_H__*/
|
|
@ -0,0 +1,393 @@
|
|||
/* 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_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_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_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_SIGNING_COUNT (DB_STORE_OFFSET_PEER_SIGNING + sizeof(csrk_t))
|
||||
|
||||
/* make size multiple of 4 */
|
||||
#define PAD4(value) ((((value - 1) / 4) * 4) + 4)
|
||||
|
||||
#define DB_SIZE_STORE \
|
||||
PAD4(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)
|
||||
#define DB_SIZE PAD4(DB_OFFSET_MAX)
|
||||
|
||||
typedef SecurityDb::entry_handle_t entry_handle_t;
|
||||
|
||||
FileSecurityDb::FileSecurityDb(FILE *db_file)
|
||||
: SecurityDb(),
|
||||
_db_file(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) {
|
||||
if (!db_path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE *db_file = fopen(db_path, "wb+");
|
||||
|
||||
if (!db_file) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
return erase_db_file(db_file);
|
||||
}
|
||||
|
||||
return db_file;
|
||||
}
|
||||
|
||||
FILE* FileSecurityDb::erase_db_file(FILE* db_file) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
entry->flags.ltk_sent = true;
|
||||
|
||||
db_write(<k, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_EDIV);
|
||||
db_write(&rand, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_RAND);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
entry->flags.ltk_stored = true;
|
||||
|
||||
db_write(<k, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_EDIV);
|
||||
db_write(&rand, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_RAND);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
db_write(&irk, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_IRK);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
db_write(&peer_address, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS);
|
||||
db_write(&address_is_public, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
entry->flags.csrk_stored = true;
|
||||
|
||||
db_write(&csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING);
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
fseek(_db_file, DB_OFFSET_RESTORE, SEEK_SET);
|
||||
|
||||
/* restore if requested */
|
||||
bool restore_toggle;
|
||||
if (fread(&restore_toggle, sizeof(bool), 1, _db_file) == 1) {
|
||||
if (!restore_toggle) {
|
||||
erase_db_file(_db_file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
db_read(&_local_identity, DB_OFFSET_LOCAL_IDENTITY);
|
||||
db_read(&_local_csrk, DB_OFFSET_LOCAL_CSRK);
|
||||
db_read(&_local_sign_counter, DB_OFFSET_LOCAL_SIGN_COUNT);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FileSecurityDb::sync(entry_handle_t db_handle) {
|
||||
entry_t *entry = as_entry(db_handle);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
db_write(&entry->peer_sign_counter, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT);
|
||||
}
|
||||
|
||||
void FileSecurityDb::set_restore(bool reload) {
|
||||
db_write(&reload, DB_OFFSET_RESTORE);
|
||||
}
|
||||
|
||||
/* helper functions */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
fseek(_db_file, entry->file_offset, SEEK_SET);
|
||||
const uint32_t zero = 0;
|
||||
size_t count = DB_SIZE_STORE / 4;
|
||||
while (count--) {
|
||||
fwrite(&zero, sizeof(zero), 1, _db_file);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
SecurityEntryIdentity_t* identity = reinterpret_cast<SecurityEntryIdentity_t*>(_buffer);
|
||||
db_read(identity, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY);
|
||||
|
||||
return identity;
|
||||
};
|
||||
|
||||
SecurityEntryKeys_t* FileSecurityDb::read_in_entry_peer_keys(entry_handle_t db_entry) {
|
||||
entry_t *entry = as_entry(db_entry);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SecurityEntryKeys_t* keys = reinterpret_cast<SecurityEntryKeys_t*>(_buffer);
|
||||
db_read(keys, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS);
|
||||
|
||||
return keys;
|
||||
};
|
||||
|
||||
SecurityEntryKeys_t* FileSecurityDb::read_in_entry_local_keys(entry_handle_t db_entry) {
|
||||
entry_t *entry = as_entry(db_entry);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SecurityEntryKeys_t* keys = reinterpret_cast<SecurityEntryKeys_t*>(_buffer);
|
||||
db_read(keys, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS);
|
||||
|
||||
return keys;
|
||||
};
|
||||
|
||||
SecurityEntrySigning_t* FileSecurityDb::read_in_entry_peer_signing(entry_handle_t db_entry) {
|
||||
entry_t *entry = as_entry(db_entry);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* only read in the csrk */
|
||||
csrk_t* csrk = reinterpret_cast<csrk_t*>(_buffer);
|
||||
db_read(csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING);
|
||||
|
||||
|
||||
/* use the counter held in memory */
|
||||
SecurityEntrySigning_t* signing = reinterpret_cast<SecurityEntrySigning_t*>(_buffer);
|
||||
signing->counter = entry->peer_sign_counter;
|
||||
|
||||
return signing;
|
||||
};
|
||||
|
||||
} /* namespace pal */
|
||||
} /* namespace ble */
|
|
@ -17,6 +17,8 @@
|
|||
#include "ble/SecurityManager.h"
|
||||
#include "ble/pal/PalSecurityManager.h"
|
||||
#include "ble/generic/GenericSecurityManager.h"
|
||||
#include "ble/generic/MemorySecurityDb.h"
|
||||
#include "ble/generic/FileSecurityDb.h"
|
||||
|
||||
using ble::pal::advertising_peer_address_type_t;
|
||||
using ble::pal::AuthenticationMask;
|
||||
|
@ -37,14 +39,33 @@ ble_error_t GenericSecurityManager::init(
|
|||
bool mitm,
|
||||
SecurityIOCapabilities_t iocaps,
|
||||
const Passkey_t passkey,
|
||||
bool signing
|
||||
bool signing,
|
||||
const char* db_path
|
||||
) {
|
||||
|
||||
ble_error_t err = _pal.initialize();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
_db.restore();
|
||||
if (_db) {
|
||||
delete _db;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (!_db) {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
_db->restore();
|
||||
|
||||
_pal.set_io_capability((io_capability_t::type) iocaps);
|
||||
|
||||
if (passkey) {
|
||||
|
@ -76,16 +97,16 @@ ble_error_t GenericSecurityManager::init(
|
|||
_pal.set_event_handler(this);
|
||||
|
||||
uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity();
|
||||
pal::SecurityEntryIdentity_t** identity_list_p =
|
||||
new (std::nothrow) pal::SecurityEntryIdentity_t*[resolving_list_capacity];
|
||||
SecurityEntryIdentity_t* identity_list_p =
|
||||
new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity];
|
||||
|
||||
if (identity_list_p) {
|
||||
ArrayView<pal::SecurityEntryIdentity_t*> identity_list(
|
||||
ArrayView<SecurityEntryIdentity_t> identity_list(
|
||||
identity_list_p,
|
||||
resolving_list_capacity
|
||||
);
|
||||
|
||||
_db.get_identity_list(
|
||||
_db->get_identity_list(
|
||||
mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved),
|
||||
identity_list
|
||||
);
|
||||
|
@ -95,7 +116,6 @@ ble_error_t GenericSecurityManager::init(
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::reset(void) {
|
||||
_db.sync();
|
||||
_pal.reset();
|
||||
SecurityManager::reset();
|
||||
|
||||
|
@ -103,7 +123,8 @@ ble_error_t GenericSecurityManager::reset(void) {
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
|
||||
_db.set_restore(enabled);
|
||||
MBED_ASSERT(_db);
|
||||
_db->set_restore(enabled);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
@ -112,13 +133,15 @@ ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::purgeAllBondingState(void) {
|
||||
_db.clear_entries();
|
||||
MBED_ASSERT(_db);
|
||||
_db->clear_entries();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const {
|
||||
MBED_ASSERT(_db);
|
||||
if (eventHandler) {
|
||||
_db.generate_whitelist_from_bond_table(
|
||||
_db->generate_whitelist_from_bond_table(
|
||||
mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable),
|
||||
whitelist
|
||||
);
|
||||
|
@ -333,18 +356,24 @@ ble_error_t GenericSecurityManager::enableSigning(
|
|||
connection_handle_t connection,
|
||||
bool enabled
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cb->signing_override_default = true;
|
||||
|
||||
if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) {
|
||||
cb->signing_requested = true;
|
||||
if (cb->csrk_stored) {
|
||||
if (flags->csrk_stored) {
|
||||
/* used the stored ones when available */
|
||||
_db.get_entry_peer_csrk(
|
||||
_db->get_entry_peer_csrk(
|
||||
mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
|
||||
cb->db_entry
|
||||
);
|
||||
|
@ -377,15 +406,20 @@ ble_error_t GenericSecurityManager::getLinkEncryption(
|
|||
connection_handle_t connection,
|
||||
link_encryption_t *encryption
|
||||
) {
|
||||
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (cb->encrypted) {
|
||||
if (cb->ltk_mitm_protected || cb->mitm_performed) {
|
||||
if (cb->secure_connections_paired) {
|
||||
if (flags->ltk_mitm_protected || cb->mitm_performed) {
|
||||
if (flags->secure_connections_paired) {
|
||||
*encryption = link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM;
|
||||
} else {
|
||||
*encryption = link_encryption_t::ENCRYPTED_WITH_MITM;
|
||||
|
@ -406,11 +440,17 @@ ble_error_t GenericSecurityManager::setLinkEncryption(
|
|||
connection_handle_t connection,
|
||||
link_encryption_t encryption
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
link_encryption_t current_encryption(link_encryption_t::NOT_ENCRYPTED);
|
||||
getLinkEncryption(connection, ¤t_encryption);
|
||||
|
||||
|
@ -437,7 +477,7 @@ ble_error_t GenericSecurityManager::setLinkEncryption(
|
|||
|
||||
} else if (encryption == link_encryption_t::ENCRYPTED_WITH_MITM) {
|
||||
|
||||
if (cb->ltk_mitm_protected && !cb->encrypted) {
|
||||
if (flags->ltk_mitm_protected && !cb->encrypted) {
|
||||
cb->encryption_requested = true;
|
||||
return enable_encryption(connection);
|
||||
} else {
|
||||
|
@ -447,8 +487,8 @@ ble_error_t GenericSecurityManager::setLinkEncryption(
|
|||
|
||||
} else if (encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) {
|
||||
|
||||
if (cb->ltk_mitm_protected &&
|
||||
cb->secure_connections_paired &&
|
||||
if (flags->ltk_mitm_protected &&
|
||||
flags->secure_connections_paired &&
|
||||
!cb->encrypted
|
||||
) {
|
||||
cb->encryption_requested = true;
|
||||
|
@ -471,13 +511,19 @@ ble_error_t GenericSecurityManager::getEncryptionKeySize(
|
|||
connection_handle_t connection,
|
||||
uint8_t *size
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (cb) {
|
||||
*size = cb->encryption_key_size;
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
*size = flags->encryption_key_size;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::setEncryptionKeyRequirements(
|
||||
|
@ -492,15 +538,21 @@ ble_error_t GenericSecurityManager::setEncryptionKeyRequirements(
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (cb->csrk_stored && (cb->csrk_mitm_protected || !authenticated)) {
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (flags->csrk_stored && (flags->csrk_mitm_protected || !authenticated)) {
|
||||
/* we have a key that is either authenticated or we don't care if it is
|
||||
* so retrieve it from the db now */
|
||||
_db.get_entry_peer_csrk(
|
||||
_db->get_entry_peer_csrk(
|
||||
mbed::callback(this, &GenericSecurityManager::return_csrk_cb),
|
||||
cb->db_entry
|
||||
);
|
||||
|
@ -532,12 +584,18 @@ ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t connection) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (cb->ltk_mitm_protected) {
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (flags->ltk_mitm_protected) {
|
||||
if (cb->authenticated) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
|
@ -643,16 +701,22 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived(
|
|||
const address_t *address,
|
||||
const oob_tk_t *tk
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
if (address && tk) {
|
||||
ControlBlock_t *cb = get_control_block(*address);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
_oob_temporary_key = *tk;
|
||||
_oob_temporary_key_creator_address = *address;
|
||||
|
||||
if (cb->peer_address == _oob_temporary_key_creator_address) {
|
||||
if (flags->peer_address == _oob_temporary_key_creator_address) {
|
||||
cb->attempt_oob = true;
|
||||
}
|
||||
|
||||
|
@ -687,8 +751,9 @@ ble_error_t GenericSecurityManager::oobReceived(
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::init_signing() {
|
||||
const csrk_t *pcsrk = _db.get_local_csrk();
|
||||
sign_count_t local_sign_counter = _db.get_local_sign_counter();
|
||||
MBED_ASSERT(_db);
|
||||
const csrk_t *pcsrk = _db->get_local_csrk();
|
||||
sign_count_t local_sign_counter = _db->get_local_sign_counter();
|
||||
|
||||
if (!pcsrk) {
|
||||
csrk_t csrk;
|
||||
|
@ -699,8 +764,8 @@ ble_error_t GenericSecurityManager::init_signing() {
|
|||
}
|
||||
|
||||
pcsrk = &csrk;
|
||||
_db.set_local_csrk(csrk);
|
||||
_db.set_local_sign_counter(local_sign_counter);
|
||||
_db->set_local_csrk(csrk);
|
||||
_db->set_local_sign_counter(local_sign_counter);
|
||||
}
|
||||
|
||||
return _pal.set_csrk(*pcsrk, local_sign_counter);
|
||||
|
@ -736,13 +801,20 @@ ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t c
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (cb->is_master) {
|
||||
if (cb->ltk_stored) {
|
||||
_db.get_entry_peer_keys(
|
||||
if (flags->ltk_stored) {
|
||||
_db->get_entry_peer_keys(
|
||||
mbed::callback(this, &GenericSecurityManager::enable_encryption_cb),
|
||||
cb->db_entry
|
||||
);
|
||||
|
@ -756,90 +828,121 @@ ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connec
|
|||
}
|
||||
|
||||
void GenericSecurityManager::enable_encryption_cb(
|
||||
pal::SecurityDb::entry_handle_t db_entry,
|
||||
SecurityDb::entry_handle_t db_entry,
|
||||
const SecurityEntryKeys_t* entryKeys
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(db_entry);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb && entryKeys) {
|
||||
if (cb->secure_connections_paired) {
|
||||
_pal.enable_encryption(cb->connection, entryKeys->ltk, cb->ltk_mitm_protected);
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entryKeys) {
|
||||
if (flags->secure_connections_paired) {
|
||||
_pal.enable_encryption(cb->connection, entryKeys->ltk, flags->ltk_mitm_protected);
|
||||
} else {
|
||||
_pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, cb->ltk_mitm_protected);
|
||||
_pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, flags->ltk_mitm_protected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GenericSecurityManager::set_ltk_cb(
|
||||
pal::SecurityDb::entry_handle_t db_entry,
|
||||
SecurityDb::entry_handle_t db_entry,
|
||||
const SecurityEntryKeys_t* entryKeys
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(db_entry);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb) {
|
||||
if (entryKeys) {
|
||||
_pal.set_ltk(
|
||||
cb->connection,
|
||||
entryKeys->ltk,
|
||||
cb->ltk_mitm_protected,
|
||||
cb->secure_connections_paired
|
||||
);
|
||||
} else {
|
||||
_pal.set_ltk_not_found(cb->connection);
|
||||
}
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entryKeys) {
|
||||
_pal.set_ltk(
|
||||
cb->connection,
|
||||
entryKeys->ltk,
|
||||
flags->ltk_mitm_protected,
|
||||
flags->secure_connections_paired
|
||||
);
|
||||
} else {
|
||||
_pal.set_ltk_not_found(cb->connection);
|
||||
}
|
||||
}
|
||||
|
||||
void GenericSecurityManager::set_peer_csrk_cb(
|
||||
pal::SecurityDb::entry_handle_t db_entry,
|
||||
const csrk_t *csrk,
|
||||
sign_count_t sign_counter
|
||||
SecurityDb::entry_handle_t db_entry,
|
||||
const SecurityEntrySigning_t* signing
|
||||
) {
|
||||
ControlBlock_t *cb = get_control_block(db_entry);
|
||||
if (!cb) {
|
||||
if (!cb || !signing) {
|
||||
return;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pal.set_peer_csrk(
|
||||
cb->connection,
|
||||
*csrk,
|
||||
cb->csrk_mitm_protected,
|
||||
sign_counter
|
||||
signing->csrk,
|
||||
flags->csrk_mitm_protected,
|
||||
signing->counter
|
||||
);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::return_csrk_cb(
|
||||
pal::SecurityDb::entry_handle_t db_entry,
|
||||
const csrk_t *csrk,
|
||||
sign_count_t sign_counter
|
||||
SecurityDb::entry_handle_t db_entry,
|
||||
const SecurityEntrySigning_t *signing
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(db_entry);
|
||||
if (!cb) {
|
||||
if (!cb || !signing) {
|
||||
return;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
eventHandler->signingKey(
|
||||
cb->connection,
|
||||
csrk,
|
||||
cb->csrk_mitm_protected
|
||||
&signing->csrk,
|
||||
flags->csrk_mitm_protected
|
||||
);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::update_oob_presence(connection_handle_t connection) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we support secure connection we only care about secure connections oob data */
|
||||
if (_default_authentication.get_secure_connections()) {
|
||||
cb->oob_present = (cb->peer_address == _oob_peer_address);
|
||||
cb->oob_present = (flags->peer_address == _oob_peer_address);
|
||||
} else {
|
||||
/* otherwise for legacy pairing we first set the oob based on set preference */
|
||||
cb->oob_present = cb->attempt_oob;
|
||||
|
||||
/* and also turn it on if we have oob data for legacy pairing */
|
||||
if (cb->peer_address == _oob_temporary_key_creator_address
|
||||
if (flags->peer_address == _oob_temporary_key_creator_address
|
||||
|| cb->local_address == _oob_temporary_key_creator_address) {
|
||||
cb->oob_present = true;
|
||||
}
|
||||
|
@ -867,34 +970,30 @@ void GenericSecurityManager::on_connected(
|
|||
const BLEProtocol::AddressBytes_t local_address,
|
||||
const Gap::ConnectionParams_t *connection_params
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = acquire_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
// setup the control block
|
||||
cb->peer_address = peer_address;
|
||||
cb->local_address = local_address;
|
||||
cb->peer_address_is_public =
|
||||
(peer_address_type == BLEProtocol::AddressType::PUBLIC);
|
||||
cb->is_master = (role == Gap::CENTRAL);
|
||||
|
||||
// get the associated db handle and the distribution flags if any
|
||||
cb->db_entry = _db.open_entry(peer_address_type, peer_address);
|
||||
cb->db_entry = _db->open_entry(peer_address_type, peer_address);
|
||||
|
||||
const pal::SecurityDistributionFlags_t* dist_flags =
|
||||
_db.get_distribution_flags(cb->db_entry);
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
|
||||
if (dist_flags) {
|
||||
*static_cast<pal::SecurityDistributionFlags_t*>(cb) = *dist_flags;
|
||||
}
|
||||
flags->peer_address = peer_address;
|
||||
flags->peer_address_is_public = (peer_address_type == BLEProtocol::AddressType::PUBLIC);
|
||||
|
||||
const bool signing = cb->signing_override_default ?
|
||||
cb->signing_requested :
|
||||
_default_key_distribution.get_signing();
|
||||
|
||||
if (signing && cb->csrk_stored) {
|
||||
_db.get_entry_peer_csrk(
|
||||
if (signing && flags->csrk_stored) {
|
||||
_db->get_entry_peer_csrk(
|
||||
mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
|
||||
cb->db_entry
|
||||
);
|
||||
|
@ -905,6 +1004,7 @@ void GenericSecurityManager::on_disconnected(
|
|||
connection_handle_t connection,
|
||||
Gap::DisconnectionReason_t reason
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
|
@ -912,15 +1012,13 @@ void GenericSecurityManager::on_disconnected(
|
|||
|
||||
_pal.remove_peer_csrk(connection);
|
||||
|
||||
_db.close_entry(cb->db_entry);
|
||||
_db->close_entry(cb->db_entry);
|
||||
release_control_block(cb);
|
||||
|
||||
_db.sync();
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_security_entry_retrieved(
|
||||
pal::SecurityDb::entry_handle_t entry,
|
||||
const pal::SecurityEntryIdentity_t* identity
|
||||
SecurityDb::entry_handle_t entry,
|
||||
const SecurityEntryIdentity_t* identity
|
||||
) {
|
||||
if (!identity) {
|
||||
return;
|
||||
|
@ -938,7 +1036,7 @@ void GenericSecurityManager::on_security_entry_retrieved(
|
|||
}
|
||||
|
||||
void GenericSecurityManager::on_identity_list_retrieved(
|
||||
ble::ArrayView<pal::SecurityEntryIdentity_t*>& identity_list,
|
||||
ble::ArrayView<SecurityEntryIdentity_t>& identity_list,
|
||||
size_t count
|
||||
) {
|
||||
typedef advertising_peer_address_type_t address_type_t;
|
||||
|
@ -946,11 +1044,11 @@ void GenericSecurityManager::on_identity_list_retrieved(
|
|||
_pal.clear_resolving_list();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
_pal.add_device_to_resolving_list(
|
||||
identity_list[i]->identity_address_is_public ?
|
||||
identity_list[i].identity_address_is_public ?
|
||||
address_type_t::PUBLIC_ADDRESS :
|
||||
address_type_t::RANDOM_ADDRESS,
|
||||
identity_list[i]->identity_address,
|
||||
identity_list[i]->irk
|
||||
identity_list[i].identity_address,
|
||||
identity_list[i].irk
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1025,11 +1123,10 @@ void GenericSecurityManager::on_pairing_timed_out(connection_handle_t connection
|
|||
}
|
||||
|
||||
void GenericSecurityManager::on_pairing_completed(connection_handle_t connection) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (cb) {
|
||||
// set the distribution flags in the db
|
||||
_db.set_distribution_flags(cb->db_entry, *cb);
|
||||
_db.get_entry_identity(
|
||||
_db->get_entry_identity(
|
||||
mbed::callback(this, &GenericSecurityManager::on_security_entry_retrieved),
|
||||
cb->db_entry
|
||||
);
|
||||
|
@ -1053,11 +1150,12 @@ void GenericSecurityManager::on_signed_write_received(
|
|||
connection_handle_t connection,
|
||||
sign_count_t sign_counter
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
_db.set_entry_peer_sign_counter(cb->db_entry, sign_counter);
|
||||
_db->set_entry_peer_sign_counter(cb->db_entry, sign_counter);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_signed_write_verification_failure(
|
||||
|
@ -1086,26 +1184,33 @@ void GenericSecurityManager::on_signed_write_verification_failure(
|
|||
}
|
||||
|
||||
void GenericSecurityManager::on_signed_write() {
|
||||
_db.set_local_sign_counter(_db.get_local_sign_counter() + 1);
|
||||
MBED_ASSERT(_db);
|
||||
_db->set_local_sign_counter(_db->get_local_sign_counter() + 1);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_slave_security_request(
|
||||
connection_handle_t connection,
|
||||
AuthenticationMask authentication
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool pairing_required = false;
|
||||
|
||||
if (authentication.get_secure_connections() && !cb->secure_connections_paired
|
||||
if (authentication.get_secure_connections() && !flags->secure_connections_paired
|
||||
&& _default_authentication.get_secure_connections()) {
|
||||
pairing_required = true;
|
||||
}
|
||||
|
||||
if (authentication.get_mitm() && !cb->ltk_mitm_protected) {
|
||||
if (authentication.get_mitm() && !flags->ltk_mitm_protected) {
|
||||
pairing_required = true;
|
||||
cb->mitm_requested = true;
|
||||
}
|
||||
|
@ -1210,7 +1315,12 @@ void GenericSecurityManager::on_secure_connections_oob_request(connection_handle
|
|||
return;
|
||||
}
|
||||
|
||||
if (cb->peer_address == _oob_peer_address) {
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags->peer_address == _oob_peer_address) {
|
||||
_pal.secure_connections_oob_request_reply(connection, _oob_local_random, _oob_peer_random, _oob_peer_confirm);
|
||||
/* do not re-use peer OOB */
|
||||
set_all_zeros(_oob_peer_address);
|
||||
|
@ -1220,19 +1330,25 @@ void GenericSecurityManager::on_secure_connections_oob_request(connection_handle
|
|||
}
|
||||
|
||||
void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb->peer_address == _oob_temporary_key_creator_address
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags->peer_address == _oob_temporary_key_creator_address
|
||||
|| cb->local_address == _oob_temporary_key_creator_address) {
|
||||
|
||||
set_mitm_performed(connection);
|
||||
_pal.legacy_pairing_oob_request_reply(connection, _oob_temporary_key);
|
||||
|
||||
/* do not re-use peer OOB */
|
||||
if (cb->peer_address == _oob_temporary_key_creator_address) {
|
||||
if (flags->peer_address == _oob_temporary_key_creator_address) {
|
||||
set_all_zeros(_oob_temporary_key_creator_address);
|
||||
}
|
||||
|
||||
|
@ -1260,29 +1376,41 @@ void GenericSecurityManager::on_secure_connections_ltk_generated(
|
|||
connection_handle_t connection,
|
||||
const ltk_t <k
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
cb->ltk_mitm_protected = cb->mitm_performed;
|
||||
cb->secure_connections_paired = true;
|
||||
cb->ltk_stored = true;
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.set_entry_peer_ltk(cb->db_entry, ltk);
|
||||
flags->ltk_mitm_protected = cb->mitm_performed;
|
||||
flags->secure_connections_paired = true;
|
||||
|
||||
_db->set_entry_peer_ltk(cb->db_entry, ltk);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_keys_distributed_ltk(
|
||||
connection_handle_t connection,
|
||||
const ltk_t <k
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
cb->ltk_mitm_protected = cb->mitm_performed;
|
||||
cb->ltk_stored = true;
|
||||
_db.set_entry_peer_ltk(cb->db_entry, ltk);
|
||||
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
flags->ltk_mitm_protected = cb->mitm_performed;
|
||||
|
||||
_db->set_entry_peer_ltk(cb->db_entry, ltk);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_keys_distributed_ediv_rand(
|
||||
|
@ -1290,24 +1418,31 @@ void GenericSecurityManager::on_keys_distributed_ediv_rand(
|
|||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.set_entry_peer_ediv_rand(cb->db_entry, ediv, rand);
|
||||
_db->set_entry_peer_ediv_rand(cb->db_entry, ediv, rand);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_keys_distributed_local_ltk(
|
||||
connection_handle_t connection,
|
||||
const ltk_t <k
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.set_entry_local_ltk(cb->db_entry, ltk);
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db->set_entry_local_ltk(cb->db_entry, ltk);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_keys_distributed_local_ediv_rand(
|
||||
|
@ -1315,24 +1450,31 @@ void GenericSecurityManager::on_keys_distributed_local_ediv_rand(
|
|||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.set_entry_local_ediv_rand(cb->db_entry, ediv, rand);
|
||||
_db->set_entry_local_ediv_rand(cb->db_entry, ediv, rand);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_keys_distributed_irk(
|
||||
connection_handle_t connection,
|
||||
const irk_t &irk
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.set_entry_peer_irk(cb->db_entry, irk);
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db->set_entry_peer_irk(cb->db_entry, irk);
|
||||
}
|
||||
|
||||
void GenericSecurityManager::on_keys_distributed_bdaddr(
|
||||
|
@ -1340,12 +1482,13 @@ void GenericSecurityManager::on_keys_distributed_bdaddr(
|
|||
advertising_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.set_entry_peer_bdaddr(
|
||||
_db->set_entry_peer_bdaddr(
|
||||
cb->db_entry,
|
||||
(peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS),
|
||||
peer_identity_address
|
||||
|
@ -1356,20 +1499,24 @@ void GenericSecurityManager::on_keys_distributed_csrk(
|
|||
connection_handle_t connection,
|
||||
const csrk_t &csrk
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
cb->csrk_mitm_protected = cb->mitm_performed;
|
||||
cb->csrk_stored = true;
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.set_entry_peer_csrk(cb->db_entry, csrk);
|
||||
flags->csrk_mitm_protected = cb->mitm_performed;
|
||||
_db->set_entry_peer_csrk(cb->db_entry, csrk);
|
||||
|
||||
eventHandler->signingKey(
|
||||
connection,
|
||||
&csrk,
|
||||
cb->csrk_mitm_protected
|
||||
flags->csrk_mitm_protected
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1378,23 +1525,30 @@ void GenericSecurityManager::on_ltk_request(
|
|||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.get_entry_local_keys(
|
||||
mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
|
||||
cb->db_entry,
|
||||
ediv,
|
||||
rand
|
||||
);
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (!flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags->ltk_stored) {
|
||||
_db->get_entry_local_keys(
|
||||
mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
|
||||
cb->db_entry,
|
||||
ediv,
|
||||
rand
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* control blocks list management */
|
||||
|
||||
GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
|
||||
pal::SecurityDistributionFlags_t(),
|
||||
connection(0),
|
||||
db_entry(0),
|
||||
local_address(),
|
||||
|
@ -1416,12 +1570,13 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
|
|||
|
||||
void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
|
||||
{
|
||||
MBED_ASSERT(_db);
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return;
|
||||
}
|
||||
|
||||
_db.get_entry_local_keys(
|
||||
_db->get_entry_local_keys(
|
||||
mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
|
||||
cb->db_entry
|
||||
);
|
||||
|
@ -1459,18 +1614,21 @@ GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_bloc
|
|||
GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
|
||||
const address_t &peer_address
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
|
||||
if (!_control_blocks[i].connected) {
|
||||
continue;
|
||||
} else if (peer_address == _control_blocks[i].peer_address) {
|
||||
return &_control_blocks[i];
|
||||
ControlBlock_t *cb = &_control_blocks[i];
|
||||
if (cb->connected) {
|
||||
SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
|
||||
if (flags && (flags->peer_address == peer_address)) {
|
||||
return cb;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
|
||||
pal::SecurityDb::entry_handle_t db_entry
|
||||
SecurityDb::entry_handle_t db_entry
|
||||
) {
|
||||
for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
|
||||
if (!_control_blocks[i].connected) {
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include "CordioPalGenericAccessService.h"
|
||||
#include "ble/generic/GenericGap.h"
|
||||
#include "ble/generic/GenericSecurityManager.h"
|
||||
#include "ble/pal/MemorySecurityDb.h"
|
||||
#include "ble/pal/SimpleEventQueue.h"
|
||||
|
||||
namespace ble {
|
||||
|
|
|
@ -204,11 +204,9 @@ generic::GenericGattClient& BLE::getGattClient()
|
|||
|
||||
SecurityManager& BLE::getSecurityManager()
|
||||
{
|
||||
static pal::MemorySecurityDb m_db;
|
||||
static SigningEventMonitorProxy signing_event_monitor(*this);
|
||||
static generic::GenericSecurityManager m_instance(
|
||||
pal::vendor::cordio::CordioSecurityManager::get_security_manager(),
|
||||
m_db,
|
||||
getGap(),
|
||||
signing_event_monitor
|
||||
);
|
||||
|
|
|
@ -208,7 +208,6 @@ SecurityManager& nRF5xn::getSecurityManager()
|
|||
|
||||
const SecurityManager& nRF5xn::getSecurityManager() const
|
||||
{
|
||||
static ble::pal::MemorySecurityDb m_db;
|
||||
ble::pal::vendor::nordic::nRF5xSecurityManager &m_pal =
|
||||
ble::pal::vendor::nordic::nRF5xSecurityManager::get_security_manager();
|
||||
static struct : ble::pal::SigningEventMonitor {
|
||||
|
@ -217,7 +216,6 @@ const SecurityManager& nRF5xn::getSecurityManager() const
|
|||
|
||||
static ble::generic::GenericSecurityManager m_instance(
|
||||
m_pal,
|
||||
m_db,
|
||||
const_cast<nRF5xGap&>(getGap()),
|
||||
dummy_signing_event_monitor
|
||||
);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "ble/BLEInstanceBase.h"
|
||||
#include "ble/generic/GenericGattClient.h"
|
||||
#include "ble/generic/GenericSecurityManager.h"
|
||||
#include "ble/pal/MemorySecurityDb.h"
|
||||
#include "ble/pal/SimpleEventQueue.h"
|
||||
#include "nRF5xPalSecurityManager.h"
|
||||
|
||||
|
|
|
@ -214,7 +214,6 @@ SecurityManager& nRF5xn::getSecurityManager()
|
|||
|
||||
const SecurityManager& nRF5xn::getSecurityManager() const
|
||||
{
|
||||
static ble::pal::MemorySecurityDb m_db;
|
||||
ble::pal::vendor::nordic::nRF5xSecurityManager &m_pal =
|
||||
ble::pal::vendor::nordic::nRF5xSecurityManager::get_security_manager();
|
||||
static struct : ble::pal::SigningEventMonitor {
|
||||
|
@ -223,7 +222,6 @@ const SecurityManager& nRF5xn::getSecurityManager() const
|
|||
|
||||
static ble::generic::GenericSecurityManager m_instance(
|
||||
m_pal,
|
||||
m_db,
|
||||
const_cast<nRF5xGap&>(getGap()),
|
||||
dummy_signing_event_monitor
|
||||
);
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "ble/BLEInstanceBase.h"
|
||||
#include "ble/generic/GenericGattClient.h"
|
||||
#include "ble/generic/GenericSecurityManager.h"
|
||||
#include "ble/pal/MemorySecurityDb.h"
|
||||
#include "ble/pal/SimpleEventQueue.h"
|
||||
#include "nRF5xPalSecurityManager.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue