address types added, secure connectins oob added

pull/6188/head
paul-szczepanek-arm 2018-02-06 10:17:31 +00:00
parent 32e91ac168
commit 9bc8c56df3
6 changed files with 117 additions and 32 deletions

View File

@ -340,11 +340,17 @@ typedef octet_type_t<8> rand_t;
typedef octet_type_t<8> random_data_t;
/** Out of band data exchanged during pairing */
typedef octet_type_t<16> oob_data_t;
typedef octet_type_t<16> oob_tk_t; /**< legacy pairing TK */
typedef octet_type_t<16> oob_rand_t; /**< secure connections oob random 128 value */
typedef octet_type_t<16> oob_confirm_t; /**< secure connections oob confirmation value */
/** data to be encrypted */
typedef octet_type_t<16> encryption_block_t;
typedef octet_type_t<32> public_key_t;
typedef octet_type_t<32> private_key_t;
typedef octet_type_t<32> dhkey_t;
} // namespace ble
/**

View File

@ -612,8 +612,8 @@ public:
* Set the requirements for encryption key size. If the peer cannot comply with the requirements
* paring will fail.
*
* @param[in] minimumByteSize Smallest allowed encryption key size in bytes.
* @param[in] maximumByteSize Largest allowed encryption key size in bytes.
* @param[in] minimumByteSize Smallest allowed encryption key size in bytes. (no smaller than 7)
* @param[in] maximumByteSize Largest allowed encryption key size in bytes. (no larger than 16)
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
virtual ble_error_t setEncryptionKeyRequirements(uint8_t minimumByteSize, uint8_t maximumByteSize) {

View File

@ -31,6 +31,7 @@ using ble::csrk_t;
using ble::ltk_t;
using ble::ediv_t;
using ble::rand_t;
using ble::pal::connection_peer_address_type_t;
/* separate structs for keys to allow db implementation
* to minimise memory usage, only holding live connection
@ -39,8 +40,9 @@ using ble::rand_t;
struct SecurityEntry_t {
SecurityEntry_t()
: handle(0),
encryption_key_size (0),
encryption_key_size(0),
peer_address_public(false),
local_address_public(false),
csrk_stored(false),
mitm_csrk(false),
ltk_stored(false),
@ -77,6 +79,7 @@ struct SecurityEntry_t {
connection_handle_t handle;
uint8_t encryption_key_size;
uint8_t peer_address_public:1;
uint8_t local_address_public:1;
uint8_t csrk_stored:1;
uint8_t mitm_csrk:1;
@ -110,7 +113,9 @@ struct SecurityEntryKeys_t {
struct SecurityEntryIdentity_t {
address_t peer_identity_address;
irk_t irk;
irk_t peer_irk;
address_t local_identity_address;
irk_t local_irk;
};
/* callbacks for asynchronous data retrieval from the security db */
@ -319,13 +324,15 @@ public:
* synchronously through connection handle.
*
* @param[in] connection this will be the index for live entries.
* @param[in] peer_address_type type of address
* @param[in] peer_address this address will be used to locate existing entry.
*
* @return pointer to entry newly created or located existing entry.
*/
virtual SecurityEntry_t* connect_entry(
connection_handle_t connection,
const address_t peer_address
connection_peer_address_type_t::type peer_address_type,
const address_t& peer_address
) = 0;
/**
@ -546,7 +553,7 @@ public:
store->key.rand = *rand;
store->csrk = *csrk;
size_t index = store - _db;
_identities[index].irk = *irk;
_identities[index].peer_irk = *irk;
_identities[index].peer_identity_address = peer_address;
}
}
@ -580,7 +587,7 @@ public:
db_store_t *store = get_store(connection);
if (store) {
size_t index = store - _db;
_identities[index].irk = *irk;
_identities[index].peer_irk = *irk;
}
}
@ -618,11 +625,19 @@ public:
/* list management */
virtual SecurityEntry_t* connect_entry(connection_handle_t connection, address_t peer_address) {
virtual SecurityEntry_t* connect_entry(
connection_handle_t connection,
connection_peer_address_type_t::type peer_address_type,
const address_t& peer_address
) {
const bool peer_address_public =
(peer_address_type == connection_peer_address_type_t::PUBLIC_ADDRESS);
for (size_t i = 0; i < MAX_ENTRIES; i++) {
if (_db[i].entry.connected) {
continue;
} else if (peer_address == _identities[i].peer_identity_address) {
} else if (peer_address == _identities[i].peer_identity_address
&& _db[i].entry.peer_address_public == peer_address_public) {
return &_db[i].entry;
}
}
@ -632,6 +647,8 @@ public:
if (!_db[i].entry.connected) {
_db[i] = db_store_t();
_identities[i] = SecurityEntryIdentity_t();
_identities[i].peer_identity_address = peer_address;
_db[i].entry.peer_address_public = peer_address_public;
return &_db[i].entry;
}
}

View File

@ -29,6 +29,7 @@ using ble::pal::address_t;
using ble::pal::advertising_peer_address_type_t;
using ble::pal::AuthenticationMask;
using ble::pal::KeyDistribution;
using ble::pal::connection_peer_address_type_t;
using ble::irk_t;
using ble::csrk_t;
@ -191,6 +192,19 @@ public:
Keypress_t keypress
);
virtual ble_error_t set_peer_oob(
const address_t& peer_address,
const oob_rand_t& random,
const oob_confirm_t& confirm
);
virtual ble_error_t get_local_oob(
connection_handle_t connection,
address_t& peer_address,
oob_rand_t& random,
oob_confirm_t& confirm
) const;
protected:
GenericSecurityManager(ble::pal::SecurityManager& palImpl, GenericSecurityDb& dbImpl)
: _pal(palImpl),
@ -443,11 +457,17 @@ public:
* Called by GAP.
*
* @param[in] connectionHandle Handle to identify the connection.
* @param peer_address Address of the connected device.
* @param is_master True if device is the master.
* @param[in] is_master True if device is the master.
* @param[in] peer_address_type type of address
* @param[in] peer_address Address of the connected device.
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
virtual void on_connected(connection_handle_t connection, address_t peer_address, bool is_master);
virtual void on_connected(
connection_handle_t connection,
bool is_master,
connection_peer_address_type_t::type peer_address_type,
const address_t &peer_address
);
private:
/* handler is always a valid pointer */

View File

@ -354,24 +354,14 @@ public:
/**
* Request OOB data from the user application.
*
* @param[in] connection connection handle
* @param[in] connection connection handlendle
* @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_data_request_reply
* or a cancellation of the procedure.
*/
virtual void on_legacy_pairing_oob_request(
connection_handle_t connection
) = 0;
/**
* Request oob data entered during pairing.
*
* @param[in] connection connection handle
* @note shall be followed by: pal::SecurityManager::oob_data_request_reply
* or a cancellation of the procedure.
*/
virtual void on_oob_request(
connection_handle_t connection
) = 0;
////////////////////////////////////////////////////////////////////////////
// Keys
//
@ -499,6 +489,35 @@ public:
const ediv_t *ediv,
const rand_t *rand
) = 0;
/**
* Store the peer's public keys.
*
* @param[in] connection connection handle
* @param[in] public_key_x peer public key (x coordinate) received during pairing
* @param[in] public_key_y peer public key (y coordinate) received during pairing
*/
virtual void on_keys_distributed_public_key(
connection_handle_t connection,
const public_key_t &public_key_x,
const public_key_t &public_key_y
) = 0;
/**
* Provide the local public key.
*
* @param[in] public_key_x newly generated public key (x coordinate)
* @param[in] public_key_y newly generated public key (y coordinate)
*/
virtual void on_public_key_generated(
const public_key_t &public_key_x,
const public_key_t &public_key_y
) = 0;
virtual void on_local_secure_connections_oob_data_generated(
const oob_confirm_t &confirm,
const oob_rand_t &random
) = 0;
};
/**
@ -769,6 +788,12 @@ public:
const csrk_t *csrk
) = 0;
/**
* Generate the Public key. This will also generate the private key.
* Public key will be returned as an event handler callback when it's ready.
*/
virtual void generate_public_key() = 0;
////////////////////////////////////////////////////////////////////////////
// Authentication
//
@ -866,7 +891,7 @@ public:
* @param[in] passkey Set the passkey that shall be used by the security
* manager when SecurityManagerEvent::on_passkey_display is called. If
* passkey is a null pointer then the security manager generates a random
* passkey everytime it calls SecurityManagerEvent::on_passkey_display.
* passkey every time it calls SecurityManagerEvent::on_passkey_display.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
@ -891,9 +916,9 @@ public:
* @param[in] oob_data pointer to out of band data
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t oob_data_request_reply(
virtual ble_error_t legacy_pairing_oob_data_request_reply(
connection_handle_t connection,
const oob_data_t *oob_data
const oob_tk_t *oob_data
) = 0;
/**
@ -921,6 +946,14 @@ public:
Keypress_t keypress
) = 0;
virtual ble_error_t get_local_secure_connections_oob_data() = 0;
virtual ble_error_t set_peer_secure_connections_oob_data(
const address_t &peer_address,
const oob_rand_t &random,
const oob_confirm_t &confirm
) = 0;
/* Entry points for the underlying stack to report events back to the user. */
public:
/**

View File

@ -933,8 +933,18 @@ void GenericSecurityManager::on_disconnected(connection_handle_t connection) {
_db.sync();
}
void GenericSecurityManager::on_connected(connection_handle_t connection, address_t peer_address, bool is_master) {
SecurityEntry_t *entry = _db.connect_entry(connection, peer_address);
void GenericSecurityManager::on_connected(
connection_handle_t connection,
bool is_master,
connection_peer_address_type_t::type peer_address_type,
const address_t &peer_address
) {
SecurityEntry_t *entry = _db.connect_entry(
connection,
peer_address_type,
peer_address
);
if (!entry) {
return;
}
@ -943,6 +953,5 @@ void GenericSecurityManager::on_connected(connection_handle_t connection, addres
entry->master = is_master;
}
} /* namespace generic */
} /* namespace ble */