mirror of https://github.com/ARMmbed/mbed-os.git
keeping state of connection, storing mitm quality of keys
parent
f635555a74
commit
bc1e809ca3
|
@ -41,25 +41,24 @@ struct SecurityEntry_t {
|
||||||
|
|
||||||
uint8_t mitm_requested:1;
|
uint8_t mitm_requested:1;
|
||||||
uint8_t mitm_performed:1;
|
uint8_t mitm_performed:1;
|
||||||
uint8_t mitm_provided:1; /**< does the key provide mitm */
|
uint8_t mitm_pairing:1; /**< keys exchange will have mitm protection */
|
||||||
|
uint8_t mitm_ltk:1;
|
||||||
|
uint8_t mitm_csrk:1;
|
||||||
|
|
||||||
uint8_t connected:1;
|
uint8_t connected:1;
|
||||||
uint8_t authenticated:1; /**< have we authenticated during this connection */
|
uint8_t authenticated:1; /**< have we turned encryption on during this connection */
|
||||||
uint8_t master:1;
|
uint8_t master:1;
|
||||||
|
uint8_t secure_connections:1;
|
||||||
uint8_t sign_data:1;
|
|
||||||
|
|
||||||
uint8_t encryption_requested:1;
|
uint8_t encryption_requested:1;
|
||||||
uint8_t encrypted:1;
|
uint8_t encrypted:1;
|
||||||
|
uint8_t signing_requested:1;
|
||||||
|
|
||||||
uint8_t oob:1;
|
uint8_t oob:1;
|
||||||
uint8_t oob_mitm_protection:1;
|
uint8_t oob_mitm_protection:1;
|
||||||
|
|
||||||
uint8_t secure_connections:1;
|
uint8_t csrk_stored:1;
|
||||||
|
uint8_t ltk_stored:1;
|
||||||
uint8_t signing_key:1;
|
|
||||||
uint8_t signing_requested:1;
|
|
||||||
uint8_t encryption_key:1;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,7 +184,28 @@ public:
|
||||||
|
|
||||||
/* list management */
|
/* list management */
|
||||||
|
|
||||||
virtual void remove_entry( address_t peer_identity_address);
|
/**
|
||||||
|
* Create a new entry or retrieve existing stored entry
|
||||||
|
* and put it in the live connections store to be retrieved
|
||||||
|
* synchronously through connection handle.
|
||||||
|
*
|
||||||
|
* @param connection this will be the index for live entries.
|
||||||
|
* @param 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, address_t peer_address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new entry or retrieve existing stored entry
|
||||||
|
* and put it in the live connections store to be retrieved
|
||||||
|
* synchronously through connection handle.
|
||||||
|
*
|
||||||
|
* @param connection this handle will be freed up from the security db
|
||||||
|
*/
|
||||||
|
virtual SecurityEntry_t* disconnect_entry(connection_handle_t connection);
|
||||||
|
|
||||||
|
virtual void remove_entry(address_t peer_identity_address);
|
||||||
virtual void clear_entries();
|
virtual void clear_entries();
|
||||||
|
|
||||||
virtual void get_whitelist(WhitelistDbCb_t cb);
|
virtual void get_whitelist(WhitelistDbCb_t cb);
|
||||||
|
|
|
@ -267,7 +267,7 @@ public:
|
||||||
if (entry->encrypted) {
|
if (entry->encrypted) {
|
||||||
return BLE_ERROR_INVALID_STATE;
|
return BLE_ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
if (!entry->signing_key && entry->signing_requested) {
|
if (!entry->csrk_stored && entry->signing_requested) {
|
||||||
init_signing();
|
init_signing();
|
||||||
if (entry->master) {
|
if (entry->master) {
|
||||||
return requestPairing(connection);
|
return requestPairing(connection);
|
||||||
|
@ -317,7 +317,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry->encrypted) {
|
if (entry->encrypted) {
|
||||||
if (entry->mitm_provided) {
|
if (entry->mitm_ltk) {
|
||||||
*encryption = link_encryption_t::ENCRYPTED_WITH_MITM;
|
*encryption = link_encryption_t::ENCRYPTED_WITH_MITM;
|
||||||
} else {
|
} else {
|
||||||
*encryption = link_encryption_t::ENCRYPTED;
|
*encryption = link_encryption_t::ENCRYPTED;
|
||||||
|
@ -369,7 +369,7 @@ public:
|
||||||
|
|
||||||
} else if (encryption == link_encryption_t::ENCRYPTED_WITH_MITM) {
|
} else if (encryption == link_encryption_t::ENCRYPTED_WITH_MITM) {
|
||||||
|
|
||||||
if (entry->mitm_provided && !entry->encrypted) {
|
if (entry->mitm_ltk && !entry->encrypted) {
|
||||||
entry->encryption_requested = true;
|
entry->encryption_requested = true;
|
||||||
return enable_encryption(connection);
|
return enable_encryption(connection);
|
||||||
} else {
|
} else {
|
||||||
|
@ -410,7 +410,7 @@ public:
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
if (entry->master) {
|
if (entry->master) {
|
||||||
if (entry->encryption_key) {
|
if (entry->ltk_stored) {
|
||||||
db.get_entry_peer_keys(
|
db.get_entry_peer_keys(
|
||||||
mbed::callback(this, &GenericSecurityManager::enable_encryption_cb),
|
mbed::callback(this, &GenericSecurityManager::enable_encryption_cb),
|
||||||
connection
|
connection
|
||||||
|
@ -458,7 +458,7 @@ public:
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry->signing_key && (entry->mitm_provided || !authenticated)) {
|
if (entry->csrk_stored && (entry->mitm_csrk || !authenticated)) {
|
||||||
/* we have a key that is either authenticated or we don't care if it is
|
/* we have a key that is either authenticated or we don't care if it is
|
||||||
* so retrieve it from the db now */
|
* so retrieve it from the db now */
|
||||||
db.get_entry_csrk(
|
db.get_entry_csrk(
|
||||||
|
@ -503,7 +503,7 @@ public:
|
||||||
_app_event_handler->signingKey(
|
_app_event_handler->signingKey(
|
||||||
connection,
|
connection,
|
||||||
csrk,
|
csrk,
|
||||||
db.get_entry(connection)->mitm_provided
|
db.get_entry(connection)->mitm_pairing
|
||||||
);
|
);
|
||||||
return DB_CB_ACTION_NO_UPDATE_REQUIRED;
|
return DB_CB_ACTION_NO_UPDATE_REQUIRED;
|
||||||
}
|
}
|
||||||
|
@ -518,7 +518,7 @@ public:
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry->mitm_provided) {
|
if (entry->mitm_pairing) {
|
||||||
if (entry->authenticated) {
|
if (entry->authenticated) {
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -671,8 +671,15 @@ public:
|
||||||
if (entry->encryption_requested) {
|
if (entry->encryption_requested) {
|
||||||
enable_encryption(connection);
|
enable_encryption(connection);
|
||||||
}
|
}
|
||||||
entry->mitm_provided = entry->mitm_performed;
|
|
||||||
|
/* keys exchanged from now on will share this mitm status */
|
||||||
|
entry->mitm_pairing = entry->mitm_performed;
|
||||||
entry->mitm_performed = false;
|
entry->mitm_performed = false;
|
||||||
|
|
||||||
|
/* sc doesn't need to exchange ltk */
|
||||||
|
if (entry->secure_connections) {
|
||||||
|
entry->mitm_ltk = entry->mitm_performed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_app_event_handler->pairingResult(
|
_app_event_handler->pairingResult(
|
||||||
|
@ -693,7 +700,22 @@ public:
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
AuthenticationMask authentication
|
AuthenticationMask authentication
|
||||||
) {
|
) {
|
||||||
|
SecurityEntry_t *entry = db.get_entry(connection);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authentication.get_secure_connections()
|
||||||
|
&& default_authentication.get_secure_connections()
|
||||||
|
&& !entry->secure_connections) {
|
||||||
|
requestPairing(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authentication.get_mitm()
|
||||||
|
&& !entry->mitm_ltk) {
|
||||||
|
entry->mitm_requested = true;
|
||||||
|
requestPairing(connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -704,13 +726,21 @@ public:
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
link_encryption_t result
|
link_encryption_t result
|
||||||
) {
|
) {
|
||||||
if (result == link_encryption_t::ENCRYPTED
|
|
||||||
|| result == link_encryption_t::ENCRYPTED_WITH_MITM) {
|
SecurityEntry_t *entry = db.get_entry(connection);
|
||||||
SecurityEntry_t *entry = db.get_entry(connection);
|
if (!entry) {
|
||||||
if (entry) {
|
return;
|
||||||
entry->encryption_requested = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result == link_encryption_t::ENCRYPTED) {
|
||||||
|
entry->encryption_requested = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == link_encryption_t::ENCRYPTED_WITH_MITM) {
|
||||||
|
entry->encryption_requested = false;
|
||||||
|
entry->authenticated = true;
|
||||||
|
}
|
||||||
|
|
||||||
_app_event_handler->linkEncryptionResult(connection, result);
|
_app_event_handler->linkEncryptionResult(connection, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,6 +813,14 @@ public:
|
||||||
const irk_t irk,
|
const irk_t irk,
|
||||||
const csrk_t csrk
|
const csrk_t csrk
|
||||||
) {
|
) {
|
||||||
|
SecurityEntry_t *entry = db.get_entry(connection);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->mitm_ltk = entry->mitm_performed;
|
||||||
|
entry->mitm_csrk = entry->mitm_performed;
|
||||||
|
|
||||||
db.set_entry_peer(
|
db.set_entry_peer(
|
||||||
connection,
|
connection,
|
||||||
(peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS),
|
(peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS),
|
||||||
|
@ -797,7 +835,7 @@ public:
|
||||||
_app_event_handler->signingKey(
|
_app_event_handler->signingKey(
|
||||||
connection,
|
connection,
|
||||||
csrk,
|
csrk,
|
||||||
db.get_entry(connection)->mitm_provided
|
db.get_entry(connection)->mitm_pairing
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -805,6 +843,11 @@ public:
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
const ltk_t ltk
|
const ltk_t ltk
|
||||||
) {
|
) {
|
||||||
|
SecurityEntry_t *entry = db.get_entry(connection);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry->mitm_ltk = entry->mitm_performed;
|
||||||
db.set_entry_peer_ltk(connection, ltk);
|
db.set_entry_peer_ltk(connection, ltk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,12 +897,19 @@ public:
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
const csrk_t csrk
|
const csrk_t csrk
|
||||||
) {
|
) {
|
||||||
|
SecurityEntry_t *entry = db.get_entry(connection);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->mitm_csrk = entry->mitm_performed;
|
||||||
|
|
||||||
db.set_entry_peer_csrk(connection, csrk);
|
db.set_entry_peer_csrk(connection, csrk);
|
||||||
|
|
||||||
_app_event_handler->signingKey(
|
_app_event_handler->signingKey(
|
||||||
connection,
|
connection,
|
||||||
csrk,
|
csrk,
|
||||||
db.get_entry(connection)->mitm_provided
|
entry->mitm_csrk
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,6 +926,33 @@ public:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void on_disconnected(connection_handle_t connection) {
|
||||||
|
SecurityEntry_t *entry = db.get_entry(connection);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry->connected = false;
|
||||||
|
db.sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void on_connected(connection_handle_t connection, address_t peer_address) {
|
||||||
|
SecurityEntry_t *entry = db.connect_entry(connection, peer_address);
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->mitm_requested = false;
|
||||||
|
entry->mitm_performed = false;
|
||||||
|
entry->mitm_pairing = false;
|
||||||
|
|
||||||
|
entry->connected = true;
|
||||||
|
entry->authenticated = false;
|
||||||
|
|
||||||
|
entry->encryption_requested = false;
|
||||||
|
entry->encrypted = false;
|
||||||
|
entry->signing_requested = false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* handler is always a valid pointer */
|
/* handler is always a valid pointer */
|
||||||
::SecurityManager::SecurityManagerEventHandler *_app_event_handler;
|
::SecurityManager::SecurityManagerEventHandler *_app_event_handler;
|
||||||
|
|
Loading…
Reference in New Issue