takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2017-2018 ARM Limited
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kadonotakashi 0:8fdf9a60065b 5 * you may not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kadonotakashi 0:8fdf9a60065b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16
kadonotakashi 0:8fdf9a60065b 17 #include "ble/SecurityManager.h"
kadonotakashi 0:8fdf9a60065b 18 #include "ble/pal/PalSecurityManager.h"
kadonotakashi 0:8fdf9a60065b 19 #include "ble/generic/GenericSecurityManager.h"
kadonotakashi 0:8fdf9a60065b 20 #include "ble/generic/MemorySecurityDb.h"
kadonotakashi 0:8fdf9a60065b 21 #include "ble/generic/FileSecurityDb.h"
kadonotakashi 0:8fdf9a60065b 22
kadonotakashi 0:8fdf9a60065b 23 using ble::pal::advertising_peer_address_type_t;
kadonotakashi 0:8fdf9a60065b 24 using ble::pal::AuthenticationMask;
kadonotakashi 0:8fdf9a60065b 25 using ble::pal::KeyDistribution;
kadonotakashi 0:8fdf9a60065b 26 using ble::pal::connection_peer_address_type_t;
kadonotakashi 0:8fdf9a60065b 27
kadonotakashi 0:8fdf9a60065b 28 namespace ble {
kadonotakashi 0:8fdf9a60065b 29 namespace generic {
kadonotakashi 0:8fdf9a60065b 30
kadonotakashi 0:8fdf9a60065b 31 /* Implements SecurityManager */
kadonotakashi 0:8fdf9a60065b 32
kadonotakashi 0:8fdf9a60065b 33 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 34 // SM lifecycle management
kadonotakashi 0:8fdf9a60065b 35 //
kadonotakashi 0:8fdf9a60065b 36
kadonotakashi 0:8fdf9a60065b 37 ble_error_t GenericSecurityManager::init(
kadonotakashi 0:8fdf9a60065b 38 bool bondable,
kadonotakashi 0:8fdf9a60065b 39 bool mitm,
kadonotakashi 0:8fdf9a60065b 40 SecurityIOCapabilities_t iocaps,
kadonotakashi 0:8fdf9a60065b 41 const Passkey_t passkey,
kadonotakashi 0:8fdf9a60065b 42 bool signing,
kadonotakashi 0:8fdf9a60065b 43 const char* db_path
kadonotakashi 0:8fdf9a60065b 44 ) {
kadonotakashi 0:8fdf9a60065b 45 ble_error_t result = _pal.initialize();
kadonotakashi 0:8fdf9a60065b 46
kadonotakashi 0:8fdf9a60065b 47 if (result != BLE_ERROR_NONE) {
kadonotakashi 0:8fdf9a60065b 48 return result;
kadonotakashi 0:8fdf9a60065b 49 }
kadonotakashi 0:8fdf9a60065b 50
kadonotakashi 0:8fdf9a60065b 51 result = init_database(db_path);
kadonotakashi 0:8fdf9a60065b 52
kadonotakashi 0:8fdf9a60065b 53 if (result != BLE_ERROR_NONE) {
kadonotakashi 0:8fdf9a60065b 54 return result;
kadonotakashi 0:8fdf9a60065b 55 }
kadonotakashi 0:8fdf9a60065b 56
kadonotakashi 0:8fdf9a60065b 57 _pal.set_io_capability((io_capability_t::type) iocaps);
kadonotakashi 0:8fdf9a60065b 58
kadonotakashi 0:8fdf9a60065b 59 if (passkey) {
kadonotakashi 0:8fdf9a60065b 60 _pal.set_display_passkey(PasskeyAscii::to_num(passkey));
kadonotakashi 0:8fdf9a60065b 61 } else {
kadonotakashi 0:8fdf9a60065b 62 _pal.set_display_passkey(0);
kadonotakashi 0:8fdf9a60065b 63 }
kadonotakashi 0:8fdf9a60065b 64
kadonotakashi 0:8fdf9a60065b 65 _legacy_pairing_allowed = true;
kadonotakashi 0:8fdf9a60065b 66
kadonotakashi 0:8fdf9a60065b 67 bool secure_connections;
kadonotakashi 0:8fdf9a60065b 68 _pal.get_secure_connections_support(secure_connections);
kadonotakashi 0:8fdf9a60065b 69
kadonotakashi 0:8fdf9a60065b 70 _default_authentication.set_bondable(bondable);
kadonotakashi 0:8fdf9a60065b 71 _default_authentication.set_mitm(mitm);
kadonotakashi 0:8fdf9a60065b 72 _default_authentication.set_secure_connections(secure_connections);
kadonotakashi 0:8fdf9a60065b 73 _default_authentication.set_keypress_notification(true);
kadonotakashi 0:8fdf9a60065b 74
kadonotakashi 0:8fdf9a60065b 75 // FIXME: depends on BR/EDR support
kadonotakashi 0:8fdf9a60065b 76 _default_key_distribution.set_link(false);
kadonotakashi 0:8fdf9a60065b 77
kadonotakashi 0:8fdf9a60065b 78 _default_key_distribution.set_signing(signing);
kadonotakashi 0:8fdf9a60065b 79 if (signing) {
kadonotakashi 0:8fdf9a60065b 80 init_signing();
kadonotakashi 0:8fdf9a60065b 81 }
kadonotakashi 0:8fdf9a60065b 82
kadonotakashi 0:8fdf9a60065b 83 _connection_monitor.set_connection_event_handler(this);
kadonotakashi 0:8fdf9a60065b 84 _signing_monitor.set_signing_event_handler(this);
kadonotakashi 0:8fdf9a60065b 85 _pal.set_event_handler(this);
kadonotakashi 0:8fdf9a60065b 86
kadonotakashi 0:8fdf9a60065b 87 result = init_resolving_list();
kadonotakashi 0:8fdf9a60065b 88
kadonotakashi 0:8fdf9a60065b 89 if (result != BLE_ERROR_NONE) {
kadonotakashi 0:8fdf9a60065b 90 delete _db;
kadonotakashi 0:8fdf9a60065b 91 return result;
kadonotakashi 0:8fdf9a60065b 92 }
kadonotakashi 0:8fdf9a60065b 93
kadonotakashi 0:8fdf9a60065b 94 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 95 }
kadonotakashi 0:8fdf9a60065b 96
kadonotakashi 0:8fdf9a60065b 97 ble_error_t GenericSecurityManager::setDatabaseFilepath(
kadonotakashi 0:8fdf9a60065b 98 const char *db_path
kadonotakashi 0:8fdf9a60065b 99 ) {
kadonotakashi 0:8fdf9a60065b 100 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 101
kadonotakashi 0:8fdf9a60065b 102 /* operation only allowed with no connections active */
kadonotakashi 0:8fdf9a60065b 103 for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
kadonotakashi 0:8fdf9a60065b 104 if (_control_blocks[i].connected) {
kadonotakashi 0:8fdf9a60065b 105 return BLE_ERROR_OPERATION_NOT_PERMITTED;
kadonotakashi 0:8fdf9a60065b 106 }
kadonotakashi 0:8fdf9a60065b 107 }
kadonotakashi 0:8fdf9a60065b 108
kadonotakashi 0:8fdf9a60065b 109 ble_error_t result = init_database(db_path);
kadonotakashi 0:8fdf9a60065b 110 if (result != BLE_ERROR_NONE) {
kadonotakashi 0:8fdf9a60065b 111 return result;
kadonotakashi 0:8fdf9a60065b 112 }
kadonotakashi 0:8fdf9a60065b 113
kadonotakashi 0:8fdf9a60065b 114 init_resolving_list();
kadonotakashi 0:8fdf9a60065b 115
kadonotakashi 0:8fdf9a60065b 116 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 117 }
kadonotakashi 0:8fdf9a60065b 118
kadonotakashi 0:8fdf9a60065b 119 ble_error_t GenericSecurityManager::reset(void) {
kadonotakashi 0:8fdf9a60065b 120 _pal.reset();
kadonotakashi 0:8fdf9a60065b 121 SecurityManager::reset();
kadonotakashi 0:8fdf9a60065b 122
kadonotakashi 0:8fdf9a60065b 123 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 124 }
kadonotakashi 0:8fdf9a60065b 125
kadonotakashi 0:8fdf9a60065b 126 ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
kadonotakashi 0:8fdf9a60065b 127 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 128 _db->set_restore(enabled);
kadonotakashi 0:8fdf9a60065b 129 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 130 }
kadonotakashi 0:8fdf9a60065b 131
kadonotakashi 0:8fdf9a60065b 132 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 133 // List management
kadonotakashi 0:8fdf9a60065b 134 //
kadonotakashi 0:8fdf9a60065b 135
kadonotakashi 0:8fdf9a60065b 136 ble_error_t GenericSecurityManager::purgeAllBondingState(void) {
kadonotakashi 0:8fdf9a60065b 137 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 138 _db->clear_entries();
kadonotakashi 0:8fdf9a60065b 139 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 140 }
kadonotakashi 0:8fdf9a60065b 141
kadonotakashi 0:8fdf9a60065b 142 ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const {
kadonotakashi 0:8fdf9a60065b 143 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 144 if (eventHandler) {
kadonotakashi 0:8fdf9a60065b 145 if (!whitelist) {
kadonotakashi 0:8fdf9a60065b 146 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 147 }
kadonotakashi 0:8fdf9a60065b 148 _db->generate_whitelist_from_bond_table(
kadonotakashi 0:8fdf9a60065b 149 mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable),
kadonotakashi 0:8fdf9a60065b 150 whitelist
kadonotakashi 0:8fdf9a60065b 151 );
kadonotakashi 0:8fdf9a60065b 152 }
kadonotakashi 0:8fdf9a60065b 153 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 154 }
kadonotakashi 0:8fdf9a60065b 155
kadonotakashi 0:8fdf9a60065b 156 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 157 // Pairing
kadonotakashi 0:8fdf9a60065b 158 //
kadonotakashi 0:8fdf9a60065b 159
kadonotakashi 0:8fdf9a60065b 160 ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 161 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 162 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 163 if (!cb) {
kadonotakashi 0:8fdf9a60065b 164 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 165 }
kadonotakashi 0:8fdf9a60065b 166
kadonotakashi 0:8fdf9a60065b 167 if (!_legacy_pairing_allowed && !_default_authentication.get_secure_connections()) {
kadonotakashi 0:8fdf9a60065b 168 return BLE_ERROR_INVALID_STATE;
kadonotakashi 0:8fdf9a60065b 169 }
kadonotakashi 0:8fdf9a60065b 170
kadonotakashi 0:8fdf9a60065b 171 set_mitm_performed(connection, false);
kadonotakashi 0:8fdf9a60065b 172 update_oob_presence(connection);
kadonotakashi 0:8fdf9a60065b 173
kadonotakashi 0:8fdf9a60065b 174 AuthenticationMask link_authentication(_default_authentication);
kadonotakashi 0:8fdf9a60065b 175
kadonotakashi 0:8fdf9a60065b 176 if (cb->mitm_requested) {
kadonotakashi 0:8fdf9a60065b 177 link_authentication.set_mitm(true);
kadonotakashi 0:8fdf9a60065b 178 }
kadonotakashi 0:8fdf9a60065b 179
kadonotakashi 0:8fdf9a60065b 180 /* by default the initiator doesn't send any keys other then identity */
kadonotakashi 0:8fdf9a60065b 181 KeyDistribution initiator_distribution(
kadonotakashi 0:8fdf9a60065b 182 KeyDistribution::KEY_DISTRIBUTION_IDENTITY |
kadonotakashi 0:8fdf9a60065b 183 _default_key_distribution.get_link()
kadonotakashi 0:8fdf9a60065b 184 );
kadonotakashi 0:8fdf9a60065b 185
kadonotakashi 0:8fdf9a60065b 186 initiator_distribution.set_signing(
kadonotakashi 0:8fdf9a60065b 187 cb->signing_override_default ?
kadonotakashi 0:8fdf9a60065b 188 cb->signing_requested :
kadonotakashi 0:8fdf9a60065b 189 _default_key_distribution.get_signing()
kadonotakashi 0:8fdf9a60065b 190 );
kadonotakashi 0:8fdf9a60065b 191
kadonotakashi 0:8fdf9a60065b 192 /* if requested the initiator may send all the default keys for later
kadonotakashi 0:8fdf9a60065b 193 * use when roles are changed */
kadonotakashi 0:8fdf9a60065b 194 if (_master_sends_keys) {
kadonotakashi 0:8fdf9a60065b 195 initiator_distribution = _default_key_distribution;
kadonotakashi 0:8fdf9a60065b 196 }
kadonotakashi 0:8fdf9a60065b 197
kadonotakashi 0:8fdf9a60065b 198 KeyDistribution responder_distribution(_default_key_distribution);
kadonotakashi 0:8fdf9a60065b 199
kadonotakashi 0:8fdf9a60065b 200 if (cb->signing_override_default) {
kadonotakashi 0:8fdf9a60065b 201 responder_distribution.set_signing(cb->signing_requested);
kadonotakashi 0:8fdf9a60065b 202 }
kadonotakashi 0:8fdf9a60065b 203
kadonotakashi 0:8fdf9a60065b 204 return _pal.send_pairing_request(
kadonotakashi 0:8fdf9a60065b 205 connection,
kadonotakashi 0:8fdf9a60065b 206 cb->oob_present,
kadonotakashi 0:8fdf9a60065b 207 link_authentication,
kadonotakashi 0:8fdf9a60065b 208 initiator_distribution,
kadonotakashi 0:8fdf9a60065b 209 responder_distribution
kadonotakashi 0:8fdf9a60065b 210 );
kadonotakashi 0:8fdf9a60065b 211 }
kadonotakashi 0:8fdf9a60065b 212
kadonotakashi 0:8fdf9a60065b 213 ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 214 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 215 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 216 if (!cb) {
kadonotakashi 0:8fdf9a60065b 217 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 218 }
kadonotakashi 0:8fdf9a60065b 219
kadonotakashi 0:8fdf9a60065b 220 update_oob_presence(connection);
kadonotakashi 0:8fdf9a60065b 221
kadonotakashi 0:8fdf9a60065b 222 AuthenticationMask link_authentication(_default_authentication);
kadonotakashi 0:8fdf9a60065b 223 if (cb->mitm_requested) {
kadonotakashi 0:8fdf9a60065b 224 link_authentication.set_mitm(true);
kadonotakashi 0:8fdf9a60065b 225 }
kadonotakashi 0:8fdf9a60065b 226
kadonotakashi 0:8fdf9a60065b 227 KeyDistribution initiator_distribution = cb->get_initiator_key_distribution();
kadonotakashi 0:8fdf9a60065b 228
kadonotakashi 0:8fdf9a60065b 229 bool master_signing = initiator_distribution.get_signing();
kadonotakashi 0:8fdf9a60065b 230
kadonotakashi 0:8fdf9a60065b 231 if (_master_sends_keys) {
kadonotakashi 0:8fdf9a60065b 232 initiator_distribution &= _default_key_distribution;
kadonotakashi 0:8fdf9a60065b 233 } else {
kadonotakashi 0:8fdf9a60065b 234 initiator_distribution &= KeyDistribution(
kadonotakashi 0:8fdf9a60065b 235 KeyDistribution::KEY_DISTRIBUTION_IDENTITY |
kadonotakashi 0:8fdf9a60065b 236 KeyDistribution::KEY_DISTRIBUTION_LINK
kadonotakashi 0:8fdf9a60065b 237 );
kadonotakashi 0:8fdf9a60065b 238 }
kadonotakashi 0:8fdf9a60065b 239
kadonotakashi 0:8fdf9a60065b 240 /* signing has to be offered and enabled on the link */
kadonotakashi 0:8fdf9a60065b 241 if (master_signing) {
kadonotakashi 0:8fdf9a60065b 242 initiator_distribution.set_signing(
kadonotakashi 0:8fdf9a60065b 243 cb->signing_override_default ?
kadonotakashi 0:8fdf9a60065b 244 cb->signing_requested :
kadonotakashi 0:8fdf9a60065b 245 _default_key_distribution.get_signing()
kadonotakashi 0:8fdf9a60065b 246 );
kadonotakashi 0:8fdf9a60065b 247 }
kadonotakashi 0:8fdf9a60065b 248
kadonotakashi 0:8fdf9a60065b 249 KeyDistribution responder_distribution(cb->get_responder_key_distribution());
kadonotakashi 0:8fdf9a60065b 250
kadonotakashi 0:8fdf9a60065b 251 responder_distribution &= _default_key_distribution;
kadonotakashi 0:8fdf9a60065b 252
kadonotakashi 0:8fdf9a60065b 253 /* signing has to be requested and enabled on the link */
kadonotakashi 0:8fdf9a60065b 254 if (responder_distribution.get_signing()) {
kadonotakashi 0:8fdf9a60065b 255 responder_distribution.set_signing(
kadonotakashi 0:8fdf9a60065b 256 cb->signing_override_default ?
kadonotakashi 0:8fdf9a60065b 257 cb->signing_requested :
kadonotakashi 0:8fdf9a60065b 258 _default_key_distribution.get_signing()
kadonotakashi 0:8fdf9a60065b 259 );
kadonotakashi 0:8fdf9a60065b 260 }
kadonotakashi 0:8fdf9a60065b 261
kadonotakashi 0:8fdf9a60065b 262 return _pal.send_pairing_response(
kadonotakashi 0:8fdf9a60065b 263 connection,
kadonotakashi 0:8fdf9a60065b 264 cb->oob_present,
kadonotakashi 0:8fdf9a60065b 265 link_authentication,
kadonotakashi 0:8fdf9a60065b 266 initiator_distribution,
kadonotakashi 0:8fdf9a60065b 267 responder_distribution
kadonotakashi 0:8fdf9a60065b 268 );
kadonotakashi 0:8fdf9a60065b 269 }
kadonotakashi 0:8fdf9a60065b 270
kadonotakashi 0:8fdf9a60065b 271 ble_error_t GenericSecurityManager::cancelPairingRequest(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 272 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 273 return _pal.cancel_pairing(connection, pairing_failure_t::UNSPECIFIED_REASON);
kadonotakashi 0:8fdf9a60065b 274 }
kadonotakashi 0:8fdf9a60065b 275
kadonotakashi 0:8fdf9a60065b 276 ble_error_t GenericSecurityManager::setPairingRequestAuthorisation(bool required) {
kadonotakashi 0:8fdf9a60065b 277 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 278 _pairing_authorisation_required = required;
kadonotakashi 0:8fdf9a60065b 279 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 280 }
kadonotakashi 0:8fdf9a60065b 281
kadonotakashi 0:8fdf9a60065b 282 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 283 // Feature support
kadonotakashi 0:8fdf9a60065b 284 //
kadonotakashi 0:8fdf9a60065b 285
kadonotakashi 0:8fdf9a60065b 286 ble_error_t GenericSecurityManager::allowLegacyPairing(bool allow) {
kadonotakashi 0:8fdf9a60065b 287 _legacy_pairing_allowed = allow;
kadonotakashi 0:8fdf9a60065b 288 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 289 }
kadonotakashi 0:8fdf9a60065b 290
kadonotakashi 0:8fdf9a60065b 291 ble_error_t GenericSecurityManager::getSecureConnectionsSupport(bool *enabled) {
kadonotakashi 0:8fdf9a60065b 292 return _pal.get_secure_connections_support(*enabled);
kadonotakashi 0:8fdf9a60065b 293 }
kadonotakashi 0:8fdf9a60065b 294
kadonotakashi 0:8fdf9a60065b 295 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 296 // Security settings
kadonotakashi 0:8fdf9a60065b 297 //
kadonotakashi 0:8fdf9a60065b 298
kadonotakashi 0:8fdf9a60065b 299 ble_error_t GenericSecurityManager::setIoCapability(SecurityIOCapabilities_t iocaps) {
kadonotakashi 0:8fdf9a60065b 300 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 301 return _pal.set_io_capability((io_capability_t::type) iocaps);
kadonotakashi 0:8fdf9a60065b 302 }
kadonotakashi 0:8fdf9a60065b 303
kadonotakashi 0:8fdf9a60065b 304 ble_error_t GenericSecurityManager::setDisplayPasskey(const Passkey_t passkey) {
kadonotakashi 0:8fdf9a60065b 305 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 306 return _pal.set_display_passkey(PasskeyAscii::to_num(passkey));
kadonotakashi 0:8fdf9a60065b 307 }
kadonotakashi 0:8fdf9a60065b 308
kadonotakashi 0:8fdf9a60065b 309 ble_error_t GenericSecurityManager::setAuthenticationTimeout(
kadonotakashi 0:8fdf9a60065b 310 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 311 uint32_t timeout_in_ms
kadonotakashi 0:8fdf9a60065b 312 ) {
kadonotakashi 0:8fdf9a60065b 313 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 314 return _pal.set_authentication_timeout(connection, timeout_in_ms / 10);
kadonotakashi 0:8fdf9a60065b 315 }
kadonotakashi 0:8fdf9a60065b 316
kadonotakashi 0:8fdf9a60065b 317 ble_error_t GenericSecurityManager::getAuthenticationTimeout(
kadonotakashi 0:8fdf9a60065b 318 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 319 uint32_t *timeout_in_ms
kadonotakashi 0:8fdf9a60065b 320 ) {
kadonotakashi 0:8fdf9a60065b 321 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 322 uint16_t timeout_in_10ms;
kadonotakashi 0:8fdf9a60065b 323 ble_error_t status = _pal.get_authentication_timeout(connection, timeout_in_10ms);
kadonotakashi 0:8fdf9a60065b 324 *timeout_in_ms = 10 * timeout_in_10ms;
kadonotakashi 0:8fdf9a60065b 325 return status;
kadonotakashi 0:8fdf9a60065b 326 }
kadonotakashi 0:8fdf9a60065b 327
kadonotakashi 0:8fdf9a60065b 328 ble_error_t GenericSecurityManager::setLinkSecurity(
kadonotakashi 0:8fdf9a60065b 329 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 330 SecurityMode_t securityMode
kadonotakashi 0:8fdf9a60065b 331 ) {
kadonotakashi 0:8fdf9a60065b 332 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 333 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 334 if (!cb) {
kadonotakashi 0:8fdf9a60065b 335 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 336 }
kadonotakashi 0:8fdf9a60065b 337
kadonotakashi 0:8fdf9a60065b 338 if (cb->encryption_requested) {
kadonotakashi 0:8fdf9a60065b 339 return BLE_ERROR_OPERATION_NOT_PERMITTED;
kadonotakashi 0:8fdf9a60065b 340 }
kadonotakashi 0:8fdf9a60065b 341
kadonotakashi 0:8fdf9a60065b 342 switch (securityMode) {
kadonotakashi 0:8fdf9a60065b 343 case SECURITY_MODE_ENCRYPTION_OPEN_LINK:
kadonotakashi 0:8fdf9a60065b 344 return setLinkEncryption(connection, link_encryption_t::NOT_ENCRYPTED);
kadonotakashi 0:8fdf9a60065b 345
kadonotakashi 0:8fdf9a60065b 346 case SECURITY_MODE_ENCRYPTION_NO_MITM:
kadonotakashi 0:8fdf9a60065b 347 return setLinkEncryption(connection, link_encryption_t::ENCRYPTED);
kadonotakashi 0:8fdf9a60065b 348
kadonotakashi 0:8fdf9a60065b 349 case SECURITY_MODE_ENCRYPTION_WITH_MITM:
kadonotakashi 0:8fdf9a60065b 350 return setLinkEncryption(connection, link_encryption_t::ENCRYPTED_WITH_MITM);
kadonotakashi 0:8fdf9a60065b 351
kadonotakashi 0:8fdf9a60065b 352 case SECURITY_MODE_SIGNED_NO_MITM:
kadonotakashi 0:8fdf9a60065b 353 return getSigningKey(connection, false);
kadonotakashi 0:8fdf9a60065b 354
kadonotakashi 0:8fdf9a60065b 355 case SECURITY_MODE_SIGNED_WITH_MITM:
kadonotakashi 0:8fdf9a60065b 356 return getSigningKey(connection, true);
kadonotakashi 0:8fdf9a60065b 357
kadonotakashi 0:8fdf9a60065b 358 default:
kadonotakashi 0:8fdf9a60065b 359 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 360 }
kadonotakashi 0:8fdf9a60065b 361 }
kadonotakashi 0:8fdf9a60065b 362
kadonotakashi 0:8fdf9a60065b 363 ble_error_t GenericSecurityManager::setKeypressNotification(bool enabled) {
kadonotakashi 0:8fdf9a60065b 364 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 365 _default_authentication.set_keypress_notification(enabled);
kadonotakashi 0:8fdf9a60065b 366 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 367 }
kadonotakashi 0:8fdf9a60065b 368
kadonotakashi 0:8fdf9a60065b 369 ble_error_t GenericSecurityManager::enableSigning(
kadonotakashi 0:8fdf9a60065b 370 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 371 bool enabled
kadonotakashi 0:8fdf9a60065b 372 ) {
kadonotakashi 0:8fdf9a60065b 373 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 374 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 375 if (!cb) {
kadonotakashi 0:8fdf9a60065b 376 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 377 }
kadonotakashi 0:8fdf9a60065b 378
kadonotakashi 0:8fdf9a60065b 379 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 380 if (!flags) {
kadonotakashi 0:8fdf9a60065b 381 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 382 }
kadonotakashi 0:8fdf9a60065b 383
kadonotakashi 0:8fdf9a60065b 384 cb->signing_override_default = true;
kadonotakashi 0:8fdf9a60065b 385
kadonotakashi 0:8fdf9a60065b 386 if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) {
kadonotakashi 0:8fdf9a60065b 387 cb->signing_requested = true;
kadonotakashi 0:8fdf9a60065b 388 if (flags->csrk_stored) {
kadonotakashi 0:8fdf9a60065b 389 /* used the stored ones when available */
kadonotakashi 0:8fdf9a60065b 390 _db->get_entry_peer_csrk(
kadonotakashi 0:8fdf9a60065b 391 mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
kadonotakashi 0:8fdf9a60065b 392 cb->db_entry
kadonotakashi 0:8fdf9a60065b 393 );
kadonotakashi 0:8fdf9a60065b 394 } else {
kadonotakashi 0:8fdf9a60065b 395 /* create keys if needed and exchange them */
kadonotakashi 0:8fdf9a60065b 396 init_signing();
kadonotakashi 0:8fdf9a60065b 397 if (cb->is_master) {
kadonotakashi 0:8fdf9a60065b 398 return requestPairing(connection);
kadonotakashi 0:8fdf9a60065b 399 } else {
kadonotakashi 0:8fdf9a60065b 400 return slave_security_request(connection);
kadonotakashi 0:8fdf9a60065b 401 }
kadonotakashi 0:8fdf9a60065b 402 }
kadonotakashi 0:8fdf9a60065b 403 } else {
kadonotakashi 0:8fdf9a60065b 404 cb->signing_requested = enabled;
kadonotakashi 0:8fdf9a60065b 405 }
kadonotakashi 0:8fdf9a60065b 406
kadonotakashi 0:8fdf9a60065b 407 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 408 }
kadonotakashi 0:8fdf9a60065b 409
kadonotakashi 0:8fdf9a60065b 410 ble_error_t GenericSecurityManager::setHintFutureRoleReversal(bool enable) {
kadonotakashi 0:8fdf9a60065b 411 _master_sends_keys = enable;
kadonotakashi 0:8fdf9a60065b 412 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 413 }
kadonotakashi 0:8fdf9a60065b 414
kadonotakashi 0:8fdf9a60065b 415 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 416 // Encryption
kadonotakashi 0:8fdf9a60065b 417 //
kadonotakashi 0:8fdf9a60065b 418
kadonotakashi 0:8fdf9a60065b 419 ble_error_t GenericSecurityManager::getLinkEncryption(
kadonotakashi 0:8fdf9a60065b 420 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 421 link_encryption_t *encryption
kadonotakashi 0:8fdf9a60065b 422 ) {
kadonotakashi 0:8fdf9a60065b 423 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 424 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 425 if (!cb) {
kadonotakashi 0:8fdf9a60065b 426 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 427 }
kadonotakashi 0:8fdf9a60065b 428
kadonotakashi 0:8fdf9a60065b 429 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 430 if (!flags) {
kadonotakashi 0:8fdf9a60065b 431 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 432 }
kadonotakashi 0:8fdf9a60065b 433
kadonotakashi 0:8fdf9a60065b 434 if (cb->encrypted) {
kadonotakashi 0:8fdf9a60065b 435 if (flags->ltk_mitm_protected || cb->mitm_performed) {
kadonotakashi 0:8fdf9a60065b 436 if (flags->secure_connections_paired) {
kadonotakashi 0:8fdf9a60065b 437 *encryption = link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM;
kadonotakashi 0:8fdf9a60065b 438 } else {
kadonotakashi 0:8fdf9a60065b 439 *encryption = link_encryption_t::ENCRYPTED_WITH_MITM;
kadonotakashi 0:8fdf9a60065b 440 }
kadonotakashi 0:8fdf9a60065b 441 } else {
kadonotakashi 0:8fdf9a60065b 442 *encryption = link_encryption_t::ENCRYPTED;
kadonotakashi 0:8fdf9a60065b 443 }
kadonotakashi 0:8fdf9a60065b 444 } else if (cb->encryption_requested) {
kadonotakashi 0:8fdf9a60065b 445 *encryption = link_encryption_t::ENCRYPTION_IN_PROGRESS;
kadonotakashi 0:8fdf9a60065b 446 } else {
kadonotakashi 0:8fdf9a60065b 447 *encryption = link_encryption_t::NOT_ENCRYPTED;
kadonotakashi 0:8fdf9a60065b 448 }
kadonotakashi 0:8fdf9a60065b 449
kadonotakashi 0:8fdf9a60065b 450 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 451 }
kadonotakashi 0:8fdf9a60065b 452
kadonotakashi 0:8fdf9a60065b 453 ble_error_t GenericSecurityManager::setLinkEncryption(
kadonotakashi 0:8fdf9a60065b 454 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 455 link_encryption_t encryption
kadonotakashi 0:8fdf9a60065b 456 ) {
kadonotakashi 0:8fdf9a60065b 457 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 458 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 459 if (!cb) {
kadonotakashi 0:8fdf9a60065b 460 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 461 }
kadonotakashi 0:8fdf9a60065b 462
kadonotakashi 0:8fdf9a60065b 463 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 464 if (!flags) {
kadonotakashi 0:8fdf9a60065b 465 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 466 }
kadonotakashi 0:8fdf9a60065b 467
kadonotakashi 0:8fdf9a60065b 468 link_encryption_t current_encryption(link_encryption_t::NOT_ENCRYPTED);
kadonotakashi 0:8fdf9a60065b 469 getLinkEncryption(connection, &current_encryption);
kadonotakashi 0:8fdf9a60065b 470
kadonotakashi 0:8fdf9a60065b 471 if (current_encryption == link_encryption_t::ENCRYPTION_IN_PROGRESS) {
kadonotakashi 0:8fdf9a60065b 472 return BLE_ERROR_OPERATION_NOT_PERMITTED;
kadonotakashi 0:8fdf9a60065b 473 }
kadonotakashi 0:8fdf9a60065b 474
kadonotakashi 0:8fdf9a60065b 475 if (current_encryption == encryption) {
kadonotakashi 0:8fdf9a60065b 476
kadonotakashi 0:8fdf9a60065b 477 /* ignore if the link is already at required state*/
kadonotakashi 0:8fdf9a60065b 478
kadonotakashi 0:8fdf9a60065b 479 } else if (encryption == link_encryption_t::NOT_ENCRYPTED) {
kadonotakashi 0:8fdf9a60065b 480 // Fail as it is not permitted to turn down encryption
kadonotakashi 0:8fdf9a60065b 481 return BLE_ERROR_OPERATION_NOT_PERMITTED;
kadonotakashi 0:8fdf9a60065b 482 } else if (encryption == link_encryption_t::ENCRYPTED) {
kadonotakashi 0:8fdf9a60065b 483
kadonotakashi 0:8fdf9a60065b 484 /* only change if we're not already encrypted with mitm */
kadonotakashi 0:8fdf9a60065b 485 if (current_encryption != link_encryption_t::ENCRYPTED_WITH_MITM ||
kadonotakashi 0:8fdf9a60065b 486 current_encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM
kadonotakashi 0:8fdf9a60065b 487 ) {
kadonotakashi 0:8fdf9a60065b 488 cb->encryption_requested = true;
kadonotakashi 0:8fdf9a60065b 489 return enable_encryption(connection);
kadonotakashi 0:8fdf9a60065b 490 }
kadonotakashi 0:8fdf9a60065b 491
kadonotakashi 0:8fdf9a60065b 492 } else if (encryption == link_encryption_t::ENCRYPTED_WITH_MITM) {
kadonotakashi 0:8fdf9a60065b 493
kadonotakashi 0:8fdf9a60065b 494 if (flags->ltk_mitm_protected && !cb->encrypted) {
kadonotakashi 0:8fdf9a60065b 495 cb->encryption_requested = true;
kadonotakashi 0:8fdf9a60065b 496 return enable_encryption(connection);
kadonotakashi 0:8fdf9a60065b 497 } else {
kadonotakashi 0:8fdf9a60065b 498 cb->encryption_requested = true;
kadonotakashi 0:8fdf9a60065b 499 return requestAuthentication(connection);
kadonotakashi 0:8fdf9a60065b 500 }
kadonotakashi 0:8fdf9a60065b 501
kadonotakashi 0:8fdf9a60065b 502 } else if (encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) {
kadonotakashi 0:8fdf9a60065b 503
kadonotakashi 0:8fdf9a60065b 504 if (flags->ltk_mitm_protected &&
kadonotakashi 0:8fdf9a60065b 505 flags->secure_connections_paired &&
kadonotakashi 0:8fdf9a60065b 506 !cb->encrypted
kadonotakashi 0:8fdf9a60065b 507 ) {
kadonotakashi 0:8fdf9a60065b 508 cb->encryption_requested = true;
kadonotakashi 0:8fdf9a60065b 509 return enable_encryption(connection);
kadonotakashi 0:8fdf9a60065b 510 } else {
kadonotakashi 0:8fdf9a60065b 511 cb->encryption_requested = true;
kadonotakashi 0:8fdf9a60065b 512 return requestAuthentication(connection);
kadonotakashi 0:8fdf9a60065b 513 }
kadonotakashi 0:8fdf9a60065b 514
kadonotakashi 0:8fdf9a60065b 515 } else {
kadonotakashi 0:8fdf9a60065b 516 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 517 }
kadonotakashi 0:8fdf9a60065b 518
kadonotakashi 0:8fdf9a60065b 519 eventHandler->linkEncryptionResult(connection, current_encryption);
kadonotakashi 0:8fdf9a60065b 520
kadonotakashi 0:8fdf9a60065b 521 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 522 }
kadonotakashi 0:8fdf9a60065b 523
kadonotakashi 0:8fdf9a60065b 524 ble_error_t GenericSecurityManager::getEncryptionKeySize(
kadonotakashi 0:8fdf9a60065b 525 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 526 uint8_t *size
kadonotakashi 0:8fdf9a60065b 527 ) {
kadonotakashi 0:8fdf9a60065b 528 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 529 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 530 if (!cb) {
kadonotakashi 0:8fdf9a60065b 531 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 532 }
kadonotakashi 0:8fdf9a60065b 533
kadonotakashi 0:8fdf9a60065b 534 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 535 if (!flags) {
kadonotakashi 0:8fdf9a60065b 536 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 537 }
kadonotakashi 0:8fdf9a60065b 538
kadonotakashi 0:8fdf9a60065b 539 *size = flags->encryption_key_size;
kadonotakashi 0:8fdf9a60065b 540 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 541 }
kadonotakashi 0:8fdf9a60065b 542
kadonotakashi 0:8fdf9a60065b 543 ble_error_t GenericSecurityManager::setEncryptionKeyRequirements(
kadonotakashi 0:8fdf9a60065b 544 uint8_t minimumByteSize,
kadonotakashi 0:8fdf9a60065b 545 uint8_t maximumByteSize
kadonotakashi 0:8fdf9a60065b 546 ) {
kadonotakashi 0:8fdf9a60065b 547 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 548 return _pal.set_encryption_key_requirements(minimumByteSize, maximumByteSize);
kadonotakashi 0:8fdf9a60065b 549 }
kadonotakashi 0:8fdf9a60065b 550
kadonotakashi 0:8fdf9a60065b 551 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 552 // Keys
kadonotakashi 0:8fdf9a60065b 553 //
kadonotakashi 0:8fdf9a60065b 554
kadonotakashi 0:8fdf9a60065b 555 ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) {
kadonotakashi 0:8fdf9a60065b 556 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 557 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 558 if (!cb) {
kadonotakashi 0:8fdf9a60065b 559 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 560 }
kadonotakashi 0:8fdf9a60065b 561
kadonotakashi 0:8fdf9a60065b 562 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 563 if (!flags) {
kadonotakashi 0:8fdf9a60065b 564 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 565 }
kadonotakashi 0:8fdf9a60065b 566
kadonotakashi 0:8fdf9a60065b 567 if (flags->csrk_stored && (flags->csrk_mitm_protected || !authenticated)) {
kadonotakashi 0:8fdf9a60065b 568 /* we have a key that is either authenticated or we don't care if it is
kadonotakashi 0:8fdf9a60065b 569 * so retrieve it from the db now */
kadonotakashi 0:8fdf9a60065b 570 _db->get_entry_peer_csrk(
kadonotakashi 0:8fdf9a60065b 571 mbed::callback(this, &GenericSecurityManager::return_csrk_cb),
kadonotakashi 0:8fdf9a60065b 572 cb->db_entry
kadonotakashi 0:8fdf9a60065b 573 );
kadonotakashi 0:8fdf9a60065b 574 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 575
kadonotakashi 0:8fdf9a60065b 576 } else {
kadonotakashi 0:8fdf9a60065b 577 /* we don't have the right key so we need to get it first
kadonotakashi 0:8fdf9a60065b 578 * keys exchange will create the signingKey event */
kadonotakashi 0:8fdf9a60065b 579 if (authenticated) {
kadonotakashi 0:8fdf9a60065b 580 return requestAuthentication(connection);
kadonotakashi 0:8fdf9a60065b 581 } else if (cb->is_master) {
kadonotakashi 0:8fdf9a60065b 582 return requestPairing(connection);
kadonotakashi 0:8fdf9a60065b 583 } else {
kadonotakashi 0:8fdf9a60065b 584 return slave_security_request(connection);
kadonotakashi 0:8fdf9a60065b 585 }
kadonotakashi 0:8fdf9a60065b 586 }
kadonotakashi 0:8fdf9a60065b 587 }
kadonotakashi 0:8fdf9a60065b 588
kadonotakashi 0:8fdf9a60065b 589 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 590 // Privacy
kadonotakashi 0:8fdf9a60065b 591 //
kadonotakashi 0:8fdf9a60065b 592
kadonotakashi 0:8fdf9a60065b 593 ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds) {
kadonotakashi 0:8fdf9a60065b 594 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 595 return _pal.set_private_address_timeout(timeout_in_seconds);
kadonotakashi 0:8fdf9a60065b 596 }
kadonotakashi 0:8fdf9a60065b 597
kadonotakashi 0:8fdf9a60065b 598 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 599 // Authentication
kadonotakashi 0:8fdf9a60065b 600 //
kadonotakashi 0:8fdf9a60065b 601
kadonotakashi 0:8fdf9a60065b 602 ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 603 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 604 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 605 if (!cb) {
kadonotakashi 0:8fdf9a60065b 606 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 607 }
kadonotakashi 0:8fdf9a60065b 608
kadonotakashi 0:8fdf9a60065b 609 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 610 if (!flags) {
kadonotakashi 0:8fdf9a60065b 611 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 612 }
kadonotakashi 0:8fdf9a60065b 613
kadonotakashi 0:8fdf9a60065b 614 if (flags->ltk_mitm_protected) {
kadonotakashi 0:8fdf9a60065b 615 if (cb->authenticated) {
kadonotakashi 0:8fdf9a60065b 616 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 617 } else {
kadonotakashi 0:8fdf9a60065b 618 cb->encryption_requested = true;
kadonotakashi 0:8fdf9a60065b 619 return enable_encryption(connection);
kadonotakashi 0:8fdf9a60065b 620 }
kadonotakashi 0:8fdf9a60065b 621 } else {
kadonotakashi 0:8fdf9a60065b 622 cb->mitm_requested = true;
kadonotakashi 0:8fdf9a60065b 623 if (cb->is_master) {
kadonotakashi 0:8fdf9a60065b 624 return requestPairing(connection);
kadonotakashi 0:8fdf9a60065b 625 } else {
kadonotakashi 0:8fdf9a60065b 626 return slave_security_request(connection);
kadonotakashi 0:8fdf9a60065b 627 }
kadonotakashi 0:8fdf9a60065b 628 }
kadonotakashi 0:8fdf9a60065b 629 }
kadonotakashi 0:8fdf9a60065b 630
kadonotakashi 0:8fdf9a60065b 631 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 632 // MITM
kadonotakashi 0:8fdf9a60065b 633 //
kadonotakashi 0:8fdf9a60065b 634
kadonotakashi 0:8fdf9a60065b 635 ble_error_t GenericSecurityManager::generateOOB(
kadonotakashi 0:8fdf9a60065b 636 const address_t *address
kadonotakashi 0:8fdf9a60065b 637 ) {
kadonotakashi 0:8fdf9a60065b 638 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 639 /* legacy pairing */
kadonotakashi 0:8fdf9a60065b 640 ble_error_t status = get_random_data(_oob_temporary_key.data(), 16);
kadonotakashi 0:8fdf9a60065b 641
kadonotakashi 0:8fdf9a60065b 642 if (status == BLE_ERROR_NONE) {
kadonotakashi 0:8fdf9a60065b 643 _oob_temporary_key_creator_address = *address;
kadonotakashi 0:8fdf9a60065b 644
kadonotakashi 0:8fdf9a60065b 645 eventHandler->legacyPairingOobGenerated(
kadonotakashi 0:8fdf9a60065b 646 &_oob_temporary_key_creator_address,
kadonotakashi 0:8fdf9a60065b 647 &_oob_temporary_key
kadonotakashi 0:8fdf9a60065b 648 );
kadonotakashi 0:8fdf9a60065b 649 } else {
kadonotakashi 0:8fdf9a60065b 650 return status;
kadonotakashi 0:8fdf9a60065b 651 }
kadonotakashi 0:8fdf9a60065b 652
kadonotakashi 0:8fdf9a60065b 653 /* Secure connections. Avoid generating if we're already waiting for it.
kadonotakashi 0:8fdf9a60065b 654 * If a local random is set to 0 it means we're already calculating. */
kadonotakashi 0:8fdf9a60065b 655 if (!is_all_zeros(_oob_local_random)) {
kadonotakashi 0:8fdf9a60065b 656 status = _pal.generate_secure_connections_oob();
kadonotakashi 0:8fdf9a60065b 657
kadonotakashi 0:8fdf9a60065b 658 if (status == BLE_ERROR_NONE) {
kadonotakashi 0:8fdf9a60065b 659 _oob_local_address = *address;
kadonotakashi 0:8fdf9a60065b 660 /* this will be updated when calculation completes,
kadonotakashi 0:8fdf9a60065b 661 * a value of all zeros is an invalid random value */
kadonotakashi 0:8fdf9a60065b 662 set_all_zeros(_oob_local_random);
kadonotakashi 0:8fdf9a60065b 663 } else if (status != BLE_ERROR_NOT_IMPLEMENTED) {
kadonotakashi 0:8fdf9a60065b 664 return status;
kadonotakashi 0:8fdf9a60065b 665 }
kadonotakashi 0:8fdf9a60065b 666 } else {
kadonotakashi 0:8fdf9a60065b 667 return BLE_STACK_BUSY;
kadonotakashi 0:8fdf9a60065b 668 }
kadonotakashi 0:8fdf9a60065b 669
kadonotakashi 0:8fdf9a60065b 670 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 671 }
kadonotakashi 0:8fdf9a60065b 672
kadonotakashi 0:8fdf9a60065b 673 ble_error_t GenericSecurityManager::setOOBDataUsage(
kadonotakashi 0:8fdf9a60065b 674 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 675 bool useOOB,
kadonotakashi 0:8fdf9a60065b 676 bool OOBProvidesMITM
kadonotakashi 0:8fdf9a60065b 677 ) {
kadonotakashi 0:8fdf9a60065b 678 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 679 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 680 if (!cb) {
kadonotakashi 0:8fdf9a60065b 681 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 682 }
kadonotakashi 0:8fdf9a60065b 683
kadonotakashi 0:8fdf9a60065b 684 cb->attempt_oob = useOOB;
kadonotakashi 0:8fdf9a60065b 685 cb->oob_mitm_protection = OOBProvidesMITM;
kadonotakashi 0:8fdf9a60065b 686
kadonotakashi 0:8fdf9a60065b 687 if (useOOB) {
kadonotakashi 0:8fdf9a60065b 688 return generateOOB(&cb->local_address);
kadonotakashi 0:8fdf9a60065b 689 } else {
kadonotakashi 0:8fdf9a60065b 690 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 691 }
kadonotakashi 0:8fdf9a60065b 692 }
kadonotakashi 0:8fdf9a60065b 693
kadonotakashi 0:8fdf9a60065b 694 ble_error_t GenericSecurityManager::confirmationEntered(
kadonotakashi 0:8fdf9a60065b 695 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 696 bool confirmation
kadonotakashi 0:8fdf9a60065b 697 ) {
kadonotakashi 0:8fdf9a60065b 698 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 699 return _pal.confirmation_entered(connection, confirmation);
kadonotakashi 0:8fdf9a60065b 700 }
kadonotakashi 0:8fdf9a60065b 701
kadonotakashi 0:8fdf9a60065b 702 ble_error_t GenericSecurityManager::passkeyEntered(
kadonotakashi 0:8fdf9a60065b 703 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 704 Passkey_t passkey
kadonotakashi 0:8fdf9a60065b 705 ) {
kadonotakashi 0:8fdf9a60065b 706 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 707 return _pal.passkey_request_reply(
kadonotakashi 0:8fdf9a60065b 708 connection,
kadonotakashi 0:8fdf9a60065b 709 PasskeyAscii::to_num(passkey)
kadonotakashi 0:8fdf9a60065b 710 );
kadonotakashi 0:8fdf9a60065b 711 }
kadonotakashi 0:8fdf9a60065b 712
kadonotakashi 0:8fdf9a60065b 713 ble_error_t GenericSecurityManager::sendKeypressNotification(
kadonotakashi 0:8fdf9a60065b 714 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 715 Keypress_t keypress
kadonotakashi 0:8fdf9a60065b 716 ) {
kadonotakashi 0:8fdf9a60065b 717 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 718 return _pal.send_keypress_notification(connection, keypress);
kadonotakashi 0:8fdf9a60065b 719 }
kadonotakashi 0:8fdf9a60065b 720
kadonotakashi 0:8fdf9a60065b 721 ble_error_t GenericSecurityManager::legacyPairingOobReceived(
kadonotakashi 0:8fdf9a60065b 722 const address_t *address,
kadonotakashi 0:8fdf9a60065b 723 const oob_tk_t *tk
kadonotakashi 0:8fdf9a60065b 724 ) {
kadonotakashi 0:8fdf9a60065b 725 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 726 if (address && tk) {
kadonotakashi 0:8fdf9a60065b 727 ControlBlock_t *cb = get_control_block(*address);
kadonotakashi 0:8fdf9a60065b 728 if (!cb) {
kadonotakashi 0:8fdf9a60065b 729 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 730 }
kadonotakashi 0:8fdf9a60065b 731
kadonotakashi 0:8fdf9a60065b 732 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 733 if (!flags) {
kadonotakashi 0:8fdf9a60065b 734 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 735 }
kadonotakashi 0:8fdf9a60065b 736
kadonotakashi 0:8fdf9a60065b 737 _oob_temporary_key = *tk;
kadonotakashi 0:8fdf9a60065b 738 _oob_temporary_key_creator_address = *address;
kadonotakashi 0:8fdf9a60065b 739
kadonotakashi 0:8fdf9a60065b 740 if (flags->peer_address == _oob_temporary_key_creator_address) {
kadonotakashi 0:8fdf9a60065b 741 cb->attempt_oob = true;
kadonotakashi 0:8fdf9a60065b 742 }
kadonotakashi 0:8fdf9a60065b 743
kadonotakashi 0:8fdf9a60065b 744 if (cb->legacy_pairing_oob_request_pending) {
kadonotakashi 0:8fdf9a60065b 745 on_legacy_pairing_oob_request(cb->connection);
kadonotakashi 0:8fdf9a60065b 746 /* legacy_pairing_oob_request_pending stops us from
kadonotakashi 0:8fdf9a60065b 747 * going into a loop of asking the user for oob
kadonotakashi 0:8fdf9a60065b 748 * so this reset needs to happen after the call above */
kadonotakashi 0:8fdf9a60065b 749 cb->legacy_pairing_oob_request_pending = false;
kadonotakashi 0:8fdf9a60065b 750 }
kadonotakashi 0:8fdf9a60065b 751 }
kadonotakashi 0:8fdf9a60065b 752 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 753 }
kadonotakashi 0:8fdf9a60065b 754
kadonotakashi 0:8fdf9a60065b 755 ble_error_t GenericSecurityManager::oobReceived(
kadonotakashi 0:8fdf9a60065b 756 const address_t *address,
kadonotakashi 0:8fdf9a60065b 757 const oob_lesc_value_t *random,
kadonotakashi 0:8fdf9a60065b 758 const oob_confirm_t *confirm
kadonotakashi 0:8fdf9a60065b 759 ) {
kadonotakashi 0:8fdf9a60065b 760 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 761 if (address && random && confirm) {
kadonotakashi 0:8fdf9a60065b 762 _oob_peer_address = *address;
kadonotakashi 0:8fdf9a60065b 763 _oob_peer_random = *random;
kadonotakashi 0:8fdf9a60065b 764 _oob_peer_confirm = *confirm;
kadonotakashi 0:8fdf9a60065b 765 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 766 }
kadonotakashi 0:8fdf9a60065b 767
kadonotakashi 0:8fdf9a60065b 768 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 769 }
kadonotakashi 0:8fdf9a60065b 770
kadonotakashi 0:8fdf9a60065b 771 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 772 // Helper functions
kadonotakashi 0:8fdf9a60065b 773 //
kadonotakashi 0:8fdf9a60065b 774
kadonotakashi 0:8fdf9a60065b 775 ble_error_t GenericSecurityManager::init_database(
kadonotakashi 0:8fdf9a60065b 776 const char *db_path
kadonotakashi 0:8fdf9a60065b 777 ) {
kadonotakashi 0:8fdf9a60065b 778 delete _db;
kadonotakashi 0:8fdf9a60065b 779
kadonotakashi 0:8fdf9a60065b 780 FILE* db_file = FileSecurityDb::open_db_file(db_path);
kadonotakashi 0:8fdf9a60065b 781
kadonotakashi 0:8fdf9a60065b 782 if (db_file) {
kadonotakashi 0:8fdf9a60065b 783 _db = new (std::nothrow) FileSecurityDb(db_file);
kadonotakashi 0:8fdf9a60065b 784 } else {
kadonotakashi 0:8fdf9a60065b 785 _db = new (std::nothrow) MemorySecurityDb();
kadonotakashi 0:8fdf9a60065b 786 }
kadonotakashi 0:8fdf9a60065b 787
kadonotakashi 0:8fdf9a60065b 788 if (!_db) {
kadonotakashi 0:8fdf9a60065b 789 return BLE_ERROR_NO_MEM;
kadonotakashi 0:8fdf9a60065b 790 }
kadonotakashi 0:8fdf9a60065b 791
kadonotakashi 0:8fdf9a60065b 792 _db->restore();
kadonotakashi 0:8fdf9a60065b 793
kadonotakashi 0:8fdf9a60065b 794 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 795 }
kadonotakashi 0:8fdf9a60065b 796
kadonotakashi 0:8fdf9a60065b 797 ble_error_t GenericSecurityManager::init_resolving_list() {
kadonotakashi 0:8fdf9a60065b 798 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 799
kadonotakashi 0:8fdf9a60065b 800 /* match the resolving list to the currently stored set of IRKs */
kadonotakashi 0:8fdf9a60065b 801 uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity();
kadonotakashi 0:8fdf9a60065b 802 SecurityEntryIdentity_t* identity_list_p =
kadonotakashi 0:8fdf9a60065b 803 new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity];
kadonotakashi 0:8fdf9a60065b 804
kadonotakashi 0:8fdf9a60065b 805 if (identity_list_p) {
kadonotakashi 0:8fdf9a60065b 806 ArrayView<SecurityEntryIdentity_t> identity_list(
kadonotakashi 0:8fdf9a60065b 807 identity_list_p,
kadonotakashi 0:8fdf9a60065b 808 resolving_list_capacity
kadonotakashi 0:8fdf9a60065b 809 );
kadonotakashi 0:8fdf9a60065b 810
kadonotakashi 0:8fdf9a60065b 811 _db->get_identity_list(
kadonotakashi 0:8fdf9a60065b 812 mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved),
kadonotakashi 0:8fdf9a60065b 813 identity_list
kadonotakashi 0:8fdf9a60065b 814 );
kadonotakashi 0:8fdf9a60065b 815 } else {
kadonotakashi 0:8fdf9a60065b 816 return BLE_ERROR_NO_MEM;
kadonotakashi 0:8fdf9a60065b 817 }
kadonotakashi 0:8fdf9a60065b 818
kadonotakashi 0:8fdf9a60065b 819 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 820 }
kadonotakashi 0:8fdf9a60065b 821
kadonotakashi 0:8fdf9a60065b 822 ble_error_t GenericSecurityManager::init_signing() {
kadonotakashi 0:8fdf9a60065b 823 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 824 const csrk_t *pcsrk = _db->get_local_csrk();
kadonotakashi 0:8fdf9a60065b 825 sign_count_t local_sign_counter = _db->get_local_sign_counter();
kadonotakashi 0:8fdf9a60065b 826
kadonotakashi 0:8fdf9a60065b 827 if (!pcsrk) {
kadonotakashi 0:8fdf9a60065b 828 csrk_t csrk;
kadonotakashi 0:8fdf9a60065b 829
kadonotakashi 0:8fdf9a60065b 830 ble_error_t ret = get_random_data(csrk.data(), csrk.size());
kadonotakashi 0:8fdf9a60065b 831 if (ret != BLE_ERROR_NONE) {
kadonotakashi 0:8fdf9a60065b 832 return ret;
kadonotakashi 0:8fdf9a60065b 833 }
kadonotakashi 0:8fdf9a60065b 834
kadonotakashi 0:8fdf9a60065b 835 pcsrk = &csrk;
kadonotakashi 0:8fdf9a60065b 836 _db->set_local_csrk(csrk);
kadonotakashi 0:8fdf9a60065b 837 _db->set_local_sign_counter(local_sign_counter);
kadonotakashi 0:8fdf9a60065b 838 }
kadonotakashi 0:8fdf9a60065b 839
kadonotakashi 0:8fdf9a60065b 840 return _pal.set_csrk(*pcsrk, local_sign_counter);
kadonotakashi 0:8fdf9a60065b 841 }
kadonotakashi 0:8fdf9a60065b 842
kadonotakashi 0:8fdf9a60065b 843 ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size) {
kadonotakashi 0:8fdf9a60065b 844 byte_array_t<8> random_data;
kadonotakashi 0:8fdf9a60065b 845
kadonotakashi 0:8fdf9a60065b 846 while (size) {
kadonotakashi 0:8fdf9a60065b 847 /* fill out the buffer by reading the random data in chunks
kadonotakashi 0:8fdf9a60065b 848 * and copying it until reaching the set size */
kadonotakashi 0:8fdf9a60065b 849 size_t copy_size = std::max(size, random_data.size());
kadonotakashi 0:8fdf9a60065b 850 ble_error_t ret = _pal.get_random_data(random_data);
kadonotakashi 0:8fdf9a60065b 851 if (ret != BLE_ERROR_NONE) {
kadonotakashi 0:8fdf9a60065b 852 return ret;
kadonotakashi 0:8fdf9a60065b 853 }
kadonotakashi 0:8fdf9a60065b 854 memcpy(buffer, random_data.data(), copy_size);
kadonotakashi 0:8fdf9a60065b 855 size -= copy_size;
kadonotakashi 0:8fdf9a60065b 856 buffer += copy_size;
kadonotakashi 0:8fdf9a60065b 857 }
kadonotakashi 0:8fdf9a60065b 858
kadonotakashi 0:8fdf9a60065b 859 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 860 }
kadonotakashi 0:8fdf9a60065b 861
kadonotakashi 0:8fdf9a60065b 862 ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 863 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 864 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 865 if (!cb) {
kadonotakashi 0:8fdf9a60065b 866 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 867 }
kadonotakashi 0:8fdf9a60065b 868 AuthenticationMask link_authentication(_default_authentication);
kadonotakashi 0:8fdf9a60065b 869 link_authentication.set_mitm(cb->mitm_requested);
kadonotakashi 0:8fdf9a60065b 870 return _pal.slave_security_request(connection, link_authentication);
kadonotakashi 0:8fdf9a60065b 871 }
kadonotakashi 0:8fdf9a60065b 872
kadonotakashi 0:8fdf9a60065b 873 ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 874 if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
kadonotakashi 0:8fdf9a60065b 875 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 876 if (!cb) {
kadonotakashi 0:8fdf9a60065b 877 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 878 }
kadonotakashi 0:8fdf9a60065b 879
kadonotakashi 0:8fdf9a60065b 880 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 881 if (!flags) {
kadonotakashi 0:8fdf9a60065b 882 return BLE_ERROR_INVALID_PARAM;
kadonotakashi 0:8fdf9a60065b 883 }
kadonotakashi 0:8fdf9a60065b 884
kadonotakashi 0:8fdf9a60065b 885 if (cb->is_master) {
kadonotakashi 0:8fdf9a60065b 886 if (flags->ltk_stored) {
kadonotakashi 0:8fdf9a60065b 887 _db->get_entry_peer_keys(
kadonotakashi 0:8fdf9a60065b 888 mbed::callback(this, &GenericSecurityManager::enable_encryption_cb),
kadonotakashi 0:8fdf9a60065b 889 cb->db_entry
kadonotakashi 0:8fdf9a60065b 890 );
kadonotakashi 0:8fdf9a60065b 891 return BLE_ERROR_NONE;
kadonotakashi 0:8fdf9a60065b 892 } else {
kadonotakashi 0:8fdf9a60065b 893 return requestPairing(connection);
kadonotakashi 0:8fdf9a60065b 894 }
kadonotakashi 0:8fdf9a60065b 895 } else {
kadonotakashi 0:8fdf9a60065b 896 return slave_security_request(connection);
kadonotakashi 0:8fdf9a60065b 897 }
kadonotakashi 0:8fdf9a60065b 898 }
kadonotakashi 0:8fdf9a60065b 899
kadonotakashi 0:8fdf9a60065b 900 void GenericSecurityManager::enable_encryption_cb(
kadonotakashi 0:8fdf9a60065b 901 SecurityDb::entry_handle_t db_entry,
kadonotakashi 0:8fdf9a60065b 902 const SecurityEntryKeys_t* entryKeys
kadonotakashi 0:8fdf9a60065b 903 ) {
kadonotakashi 0:8fdf9a60065b 904 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 905 ControlBlock_t *cb = get_control_block(db_entry);
kadonotakashi 0:8fdf9a60065b 906 if (!cb) {
kadonotakashi 0:8fdf9a60065b 907 return;
kadonotakashi 0:8fdf9a60065b 908 }
kadonotakashi 0:8fdf9a60065b 909
kadonotakashi 0:8fdf9a60065b 910 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 911 if (!flags) {
kadonotakashi 0:8fdf9a60065b 912 return;
kadonotakashi 0:8fdf9a60065b 913 }
kadonotakashi 0:8fdf9a60065b 914
kadonotakashi 0:8fdf9a60065b 915 if (entryKeys) {
kadonotakashi 0:8fdf9a60065b 916 if (flags->secure_connections_paired) {
kadonotakashi 0:8fdf9a60065b 917 _pal.enable_encryption(cb->connection, entryKeys->ltk, flags->ltk_mitm_protected);
kadonotakashi 0:8fdf9a60065b 918 } else {
kadonotakashi 0:8fdf9a60065b 919 _pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, flags->ltk_mitm_protected);
kadonotakashi 0:8fdf9a60065b 920 }
kadonotakashi 0:8fdf9a60065b 921 }
kadonotakashi 0:8fdf9a60065b 922 }
kadonotakashi 0:8fdf9a60065b 923
kadonotakashi 0:8fdf9a60065b 924 void GenericSecurityManager::set_ltk_cb(
kadonotakashi 0:8fdf9a60065b 925 SecurityDb::entry_handle_t db_entry,
kadonotakashi 0:8fdf9a60065b 926 const SecurityEntryKeys_t* entryKeys
kadonotakashi 0:8fdf9a60065b 927 ) {
kadonotakashi 0:8fdf9a60065b 928 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 929 ControlBlock_t *cb = get_control_block(db_entry);
kadonotakashi 0:8fdf9a60065b 930 if (!cb) {
kadonotakashi 0:8fdf9a60065b 931 return;
kadonotakashi 0:8fdf9a60065b 932 }
kadonotakashi 0:8fdf9a60065b 933
kadonotakashi 0:8fdf9a60065b 934 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 935 if (!flags) {
kadonotakashi 0:8fdf9a60065b 936 return;
kadonotakashi 0:8fdf9a60065b 937 }
kadonotakashi 0:8fdf9a60065b 938
kadonotakashi 0:8fdf9a60065b 939 if (entryKeys) {
kadonotakashi 0:8fdf9a60065b 940 _pal.set_ltk(
kadonotakashi 0:8fdf9a60065b 941 cb->connection,
kadonotakashi 0:8fdf9a60065b 942 entryKeys->ltk,
kadonotakashi 0:8fdf9a60065b 943 flags->ltk_mitm_protected,
kadonotakashi 0:8fdf9a60065b 944 flags->secure_connections_paired
kadonotakashi 0:8fdf9a60065b 945 );
kadonotakashi 0:8fdf9a60065b 946 } else {
kadonotakashi 0:8fdf9a60065b 947 _pal.set_ltk_not_found(cb->connection);
kadonotakashi 0:8fdf9a60065b 948 }
kadonotakashi 0:8fdf9a60065b 949 }
kadonotakashi 0:8fdf9a60065b 950
kadonotakashi 0:8fdf9a60065b 951 void GenericSecurityManager::set_peer_csrk_cb(
kadonotakashi 0:8fdf9a60065b 952 SecurityDb::entry_handle_t db_entry,
kadonotakashi 0:8fdf9a60065b 953 const SecurityEntrySigning_t* signing
kadonotakashi 0:8fdf9a60065b 954 ) {
kadonotakashi 0:8fdf9a60065b 955 ControlBlock_t *cb = get_control_block(db_entry);
kadonotakashi 0:8fdf9a60065b 956 if (!cb || !signing) {
kadonotakashi 0:8fdf9a60065b 957 return;
kadonotakashi 0:8fdf9a60065b 958 }
kadonotakashi 0:8fdf9a60065b 959
kadonotakashi 0:8fdf9a60065b 960 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 961 if (!flags) {
kadonotakashi 0:8fdf9a60065b 962 return;
kadonotakashi 0:8fdf9a60065b 963 }
kadonotakashi 0:8fdf9a60065b 964
kadonotakashi 0:8fdf9a60065b 965 _pal.set_peer_csrk(
kadonotakashi 0:8fdf9a60065b 966 cb->connection,
kadonotakashi 0:8fdf9a60065b 967 signing->csrk,
kadonotakashi 0:8fdf9a60065b 968 flags->csrk_mitm_protected,
kadonotakashi 0:8fdf9a60065b 969 signing->counter
kadonotakashi 0:8fdf9a60065b 970 );
kadonotakashi 0:8fdf9a60065b 971 }
kadonotakashi 0:8fdf9a60065b 972
kadonotakashi 0:8fdf9a60065b 973 void GenericSecurityManager::return_csrk_cb(
kadonotakashi 0:8fdf9a60065b 974 SecurityDb::entry_handle_t db_entry,
kadonotakashi 0:8fdf9a60065b 975 const SecurityEntrySigning_t *signing
kadonotakashi 0:8fdf9a60065b 976 ) {
kadonotakashi 0:8fdf9a60065b 977 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 978 ControlBlock_t *cb = get_control_block(db_entry);
kadonotakashi 0:8fdf9a60065b 979 if (!cb || !signing) {
kadonotakashi 0:8fdf9a60065b 980 return;
kadonotakashi 0:8fdf9a60065b 981 }
kadonotakashi 0:8fdf9a60065b 982
kadonotakashi 0:8fdf9a60065b 983 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 984 if (!flags) {
kadonotakashi 0:8fdf9a60065b 985 return;
kadonotakashi 0:8fdf9a60065b 986 }
kadonotakashi 0:8fdf9a60065b 987
kadonotakashi 0:8fdf9a60065b 988 eventHandler->signingKey(
kadonotakashi 0:8fdf9a60065b 989 cb->connection,
kadonotakashi 0:8fdf9a60065b 990 &signing->csrk,
kadonotakashi 0:8fdf9a60065b 991 flags->csrk_mitm_protected
kadonotakashi 0:8fdf9a60065b 992 );
kadonotakashi 0:8fdf9a60065b 993 }
kadonotakashi 0:8fdf9a60065b 994
kadonotakashi 0:8fdf9a60065b 995 void GenericSecurityManager::update_oob_presence(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 996 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 997 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 998 if (!cb) {
kadonotakashi 0:8fdf9a60065b 999 return;
kadonotakashi 0:8fdf9a60065b 1000 }
kadonotakashi 0:8fdf9a60065b 1001
kadonotakashi 0:8fdf9a60065b 1002 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1003 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1004 return;
kadonotakashi 0:8fdf9a60065b 1005 }
kadonotakashi 0:8fdf9a60065b 1006
kadonotakashi 0:8fdf9a60065b 1007 /* if we support secure connection we only care about secure connections oob data */
kadonotakashi 0:8fdf9a60065b 1008 if (_default_authentication.get_secure_connections()) {
kadonotakashi 0:8fdf9a60065b 1009 cb->oob_present = (flags->peer_address == _oob_peer_address);
kadonotakashi 0:8fdf9a60065b 1010 } else {
kadonotakashi 0:8fdf9a60065b 1011 /* otherwise for legacy pairing we first set the oob based on set preference */
kadonotakashi 0:8fdf9a60065b 1012 cb->oob_present = cb->attempt_oob;
kadonotakashi 0:8fdf9a60065b 1013
kadonotakashi 0:8fdf9a60065b 1014 /* and also turn it on if we have oob data for legacy pairing */
kadonotakashi 0:8fdf9a60065b 1015 if (flags->peer_address == _oob_temporary_key_creator_address
kadonotakashi 0:8fdf9a60065b 1016 || cb->local_address == _oob_temporary_key_creator_address) {
kadonotakashi 0:8fdf9a60065b 1017 cb->oob_present = true;
kadonotakashi 0:8fdf9a60065b 1018 }
kadonotakashi 0:8fdf9a60065b 1019 }
kadonotakashi 0:8fdf9a60065b 1020 }
kadonotakashi 0:8fdf9a60065b 1021
kadonotakashi 0:8fdf9a60065b 1022 void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, bool enable) {
kadonotakashi 0:8fdf9a60065b 1023 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1024 if (cb) {
kadonotakashi 0:8fdf9a60065b 1025 cb->mitm_performed = enable;
kadonotakashi 0:8fdf9a60065b 1026 /* whenever we reset mitm performed we also reset pending requests
kadonotakashi 0:8fdf9a60065b 1027 * as this happens whenever a new pairing attempt happens */
kadonotakashi 0:8fdf9a60065b 1028 if (!enable) {
kadonotakashi 0:8fdf9a60065b 1029 cb->legacy_pairing_oob_request_pending = false;
kadonotakashi 0:8fdf9a60065b 1030 }
kadonotakashi 0:8fdf9a60065b 1031 }
kadonotakashi 0:8fdf9a60065b 1032 }
kadonotakashi 0:8fdf9a60065b 1033
kadonotakashi 0:8fdf9a60065b 1034 void GenericSecurityManager::on_connected(
kadonotakashi 0:8fdf9a60065b 1035 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1036 Gap::Role_t role,
kadonotakashi 0:8fdf9a60065b 1037 peer_address_type_t peer_address_type,
kadonotakashi 0:8fdf9a60065b 1038 const BLEProtocol::AddressBytes_t peer_address,
kadonotakashi 0:8fdf9a60065b 1039 BLEProtocol::AddressType_t local_address_type,
kadonotakashi 0:8fdf9a60065b 1040 const BLEProtocol::AddressBytes_t local_address,
kadonotakashi 0:8fdf9a60065b 1041 const Gap::ConnectionParams_t *connection_params
kadonotakashi 0:8fdf9a60065b 1042 ) {
kadonotakashi 0:8fdf9a60065b 1043 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1044 ControlBlock_t *cb = acquire_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1045 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1046 return;
kadonotakashi 0:8fdf9a60065b 1047 }
kadonotakashi 0:8fdf9a60065b 1048
kadonotakashi 0:8fdf9a60065b 1049 // setup the control block
kadonotakashi 0:8fdf9a60065b 1050 cb->local_address = local_address;
kadonotakashi 0:8fdf9a60065b 1051 cb->is_master = (role == Gap::CENTRAL);
kadonotakashi 0:8fdf9a60065b 1052
kadonotakashi 0:8fdf9a60065b 1053 // get the associated db handle and the distribution flags if any
kadonotakashi 0:8fdf9a60065b 1054 cb->db_entry = _db->open_entry(peer_address_type, peer_address);
kadonotakashi 0:8fdf9a60065b 1055
kadonotakashi 0:8fdf9a60065b 1056 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1057
kadonotakashi 0:8fdf9a60065b 1058 flags->peer_address = peer_address;
kadonotakashi 0:8fdf9a60065b 1059 flags->peer_address_is_public =
kadonotakashi 0:8fdf9a60065b 1060 (peer_address_type == peer_address_type_t::PUBLIC) ||
kadonotakashi 0:8fdf9a60065b 1061 (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY);
kadonotakashi 0:8fdf9a60065b 1062
kadonotakashi 0:8fdf9a60065b 1063 const bool signing = cb->signing_override_default ?
kadonotakashi 0:8fdf9a60065b 1064 cb->signing_requested :
kadonotakashi 0:8fdf9a60065b 1065 _default_key_distribution.get_signing();
kadonotakashi 0:8fdf9a60065b 1066
kadonotakashi 0:8fdf9a60065b 1067 if (signing && flags->csrk_stored) {
kadonotakashi 0:8fdf9a60065b 1068 _db->get_entry_peer_csrk(
kadonotakashi 0:8fdf9a60065b 1069 mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
kadonotakashi 0:8fdf9a60065b 1070 cb->db_entry
kadonotakashi 0:8fdf9a60065b 1071 );
kadonotakashi 0:8fdf9a60065b 1072 }
kadonotakashi 0:8fdf9a60065b 1073 }
kadonotakashi 0:8fdf9a60065b 1074
kadonotakashi 0:8fdf9a60065b 1075 void GenericSecurityManager::on_disconnected(
kadonotakashi 0:8fdf9a60065b 1076 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1077 Gap::DisconnectionReason_t reason
kadonotakashi 0:8fdf9a60065b 1078 ) {
kadonotakashi 0:8fdf9a60065b 1079 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1080 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1081 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1082 return;
kadonotakashi 0:8fdf9a60065b 1083 }
kadonotakashi 0:8fdf9a60065b 1084
kadonotakashi 0:8fdf9a60065b 1085 _pal.remove_peer_csrk(connection);
kadonotakashi 0:8fdf9a60065b 1086
kadonotakashi 0:8fdf9a60065b 1087 _db->close_entry(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1088 release_control_block(cb);
kadonotakashi 0:8fdf9a60065b 1089 }
kadonotakashi 0:8fdf9a60065b 1090
kadonotakashi 0:8fdf9a60065b 1091 void GenericSecurityManager::on_security_entry_retrieved(
kadonotakashi 0:8fdf9a60065b 1092 SecurityDb::entry_handle_t entry,
kadonotakashi 0:8fdf9a60065b 1093 const SecurityEntryIdentity_t* identity
kadonotakashi 0:8fdf9a60065b 1094 ) {
kadonotakashi 0:8fdf9a60065b 1095 if (!identity) {
kadonotakashi 0:8fdf9a60065b 1096 return;
kadonotakashi 0:8fdf9a60065b 1097 }
kadonotakashi 0:8fdf9a60065b 1098
kadonotakashi 0:8fdf9a60065b 1099 typedef advertising_peer_address_type_t address_type_t;
kadonotakashi 0:8fdf9a60065b 1100
kadonotakashi 0:8fdf9a60065b 1101 _pal.add_device_to_resolving_list(
kadonotakashi 0:8fdf9a60065b 1102 identity->identity_address_is_public ?
kadonotakashi 0:8fdf9a60065b 1103 address_type_t::PUBLIC_ADDRESS :
kadonotakashi 0:8fdf9a60065b 1104 address_type_t::RANDOM_ADDRESS,
kadonotakashi 0:8fdf9a60065b 1105 identity->identity_address,
kadonotakashi 0:8fdf9a60065b 1106 identity->irk
kadonotakashi 0:8fdf9a60065b 1107 );
kadonotakashi 0:8fdf9a60065b 1108 }
kadonotakashi 0:8fdf9a60065b 1109
kadonotakashi 0:8fdf9a60065b 1110 void GenericSecurityManager::on_identity_list_retrieved(
kadonotakashi 0:8fdf9a60065b 1111 ble::ArrayView<SecurityEntryIdentity_t>& identity_list,
kadonotakashi 0:8fdf9a60065b 1112 size_t count
kadonotakashi 0:8fdf9a60065b 1113 ) {
kadonotakashi 0:8fdf9a60065b 1114 typedef advertising_peer_address_type_t address_type_t;
kadonotakashi 0:8fdf9a60065b 1115
kadonotakashi 0:8fdf9a60065b 1116 _pal.clear_resolving_list();
kadonotakashi 0:8fdf9a60065b 1117 for (size_t i = 0; i < count; ++i) {
kadonotakashi 0:8fdf9a60065b 1118 _pal.add_device_to_resolving_list(
kadonotakashi 0:8fdf9a60065b 1119 identity_list[i].identity_address_is_public ?
kadonotakashi 0:8fdf9a60065b 1120 address_type_t::PUBLIC_ADDRESS :
kadonotakashi 0:8fdf9a60065b 1121 address_type_t::RANDOM_ADDRESS,
kadonotakashi 0:8fdf9a60065b 1122 identity_list[i].identity_address,
kadonotakashi 0:8fdf9a60065b 1123 identity_list[i].irk
kadonotakashi 0:8fdf9a60065b 1124 );
kadonotakashi 0:8fdf9a60065b 1125 }
kadonotakashi 0:8fdf9a60065b 1126
kadonotakashi 0:8fdf9a60065b 1127 delete [] identity_list.data();
kadonotakashi 0:8fdf9a60065b 1128 }
kadonotakashi 0:8fdf9a60065b 1129
kadonotakashi 0:8fdf9a60065b 1130
kadonotakashi 0:8fdf9a60065b 1131 /* Implements ble::pal::SecurityManagerEventHandler */
kadonotakashi 0:8fdf9a60065b 1132
kadonotakashi 0:8fdf9a60065b 1133 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 1134 // Pairing
kadonotakashi 0:8fdf9a60065b 1135 //
kadonotakashi 0:8fdf9a60065b 1136
kadonotakashi 0:8fdf9a60065b 1137 void GenericSecurityManager::on_pairing_request(
kadonotakashi 0:8fdf9a60065b 1138 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1139 bool use_oob,
kadonotakashi 0:8fdf9a60065b 1140 AuthenticationMask authentication,
kadonotakashi 0:8fdf9a60065b 1141 KeyDistribution initiator_dist,
kadonotakashi 0:8fdf9a60065b 1142 KeyDistribution responder_dist
kadonotakashi 0:8fdf9a60065b 1143 ) {
kadonotakashi 0:8fdf9a60065b 1144 /* cancel pairing if secure connection paring is not possible */
kadonotakashi 0:8fdf9a60065b 1145 if (!_legacy_pairing_allowed && !authentication.get_secure_connections()) {
kadonotakashi 0:8fdf9a60065b 1146 cancelPairingRequest(connection);
kadonotakashi 0:8fdf9a60065b 1147 return;
kadonotakashi 0:8fdf9a60065b 1148 }
kadonotakashi 0:8fdf9a60065b 1149
kadonotakashi 0:8fdf9a60065b 1150 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1151 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1152 return;
kadonotakashi 0:8fdf9a60065b 1153 }
kadonotakashi 0:8fdf9a60065b 1154
kadonotakashi 0:8fdf9a60065b 1155 cb->set_initiator_key_distribution(initiator_dist);
kadonotakashi 0:8fdf9a60065b 1156 cb->set_responder_key_distribution(responder_dist);
kadonotakashi 0:8fdf9a60065b 1157
kadonotakashi 0:8fdf9a60065b 1158 cb->mitm_performed = false;
kadonotakashi 0:8fdf9a60065b 1159
kadonotakashi 0:8fdf9a60065b 1160 if (_pairing_authorisation_required) {
kadonotakashi 0:8fdf9a60065b 1161 eventHandler->pairingRequest(connection);
kadonotakashi 0:8fdf9a60065b 1162 } else {
kadonotakashi 0:8fdf9a60065b 1163 acceptPairingRequest(connection);
kadonotakashi 0:8fdf9a60065b 1164 }
kadonotakashi 0:8fdf9a60065b 1165 }
kadonotakashi 0:8fdf9a60065b 1166
kadonotakashi 0:8fdf9a60065b 1167 void GenericSecurityManager::on_pairing_error(
kadonotakashi 0:8fdf9a60065b 1168 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1169 pairing_failure_t error
kadonotakashi 0:8fdf9a60065b 1170 ) {
kadonotakashi 0:8fdf9a60065b 1171 set_mitm_performed(connection, false);
kadonotakashi 0:8fdf9a60065b 1172
kadonotakashi 0:8fdf9a60065b 1173 eventHandler->pairingResult(
kadonotakashi 0:8fdf9a60065b 1174 connection,
kadonotakashi 0:8fdf9a60065b 1175 (SecurityManager::SecurityCompletionStatus_t)(error.value() | 0x80)
kadonotakashi 0:8fdf9a60065b 1176 );
kadonotakashi 0:8fdf9a60065b 1177
kadonotakashi 0:8fdf9a60065b 1178 /* if this pairing was triggered by a failed encryption attempt
kadonotakashi 0:8fdf9a60065b 1179 * inform the application of the encryption failure */
kadonotakashi 0:8fdf9a60065b 1180 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1181 if (cb && cb->encryption_requested && cb->encryption_failed) {
kadonotakashi 0:8fdf9a60065b 1182 eventHandler->linkEncryptionResult(
kadonotakashi 0:8fdf9a60065b 1183 connection,
kadonotakashi 0:8fdf9a60065b 1184 link_encryption_t::NOT_ENCRYPTED
kadonotakashi 0:8fdf9a60065b 1185 );
kadonotakashi 0:8fdf9a60065b 1186 }
kadonotakashi 0:8fdf9a60065b 1187 }
kadonotakashi 0:8fdf9a60065b 1188
kadonotakashi 0:8fdf9a60065b 1189 void GenericSecurityManager::on_pairing_timed_out(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 1190 set_mitm_performed(connection, false);
kadonotakashi 0:8fdf9a60065b 1191
kadonotakashi 0:8fdf9a60065b 1192 eventHandler->pairingResult(
kadonotakashi 0:8fdf9a60065b 1193 connection,
kadonotakashi 0:8fdf9a60065b 1194 SecurityManager::SEC_STATUS_TIMEOUT
kadonotakashi 0:8fdf9a60065b 1195 );
kadonotakashi 0:8fdf9a60065b 1196 }
kadonotakashi 0:8fdf9a60065b 1197
kadonotakashi 0:8fdf9a60065b 1198 void GenericSecurityManager::on_pairing_completed(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 1199 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1200 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1201 if (cb) {
kadonotakashi 0:8fdf9a60065b 1202 _db->get_entry_identity(
kadonotakashi 0:8fdf9a60065b 1203 mbed::callback(this, &GenericSecurityManager::on_security_entry_retrieved),
kadonotakashi 0:8fdf9a60065b 1204 cb->db_entry
kadonotakashi 0:8fdf9a60065b 1205 );
kadonotakashi 0:8fdf9a60065b 1206 }
kadonotakashi 0:8fdf9a60065b 1207
kadonotakashi 0:8fdf9a60065b 1208 eventHandler->pairingResult(
kadonotakashi 0:8fdf9a60065b 1209 connection,
kadonotakashi 0:8fdf9a60065b 1210 SecurityManager::SEC_STATUS_SUCCESS
kadonotakashi 0:8fdf9a60065b 1211 );
kadonotakashi 0:8fdf9a60065b 1212 }
kadonotakashi 0:8fdf9a60065b 1213
kadonotakashi 0:8fdf9a60065b 1214 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 1215 // Security
kadonotakashi 0:8fdf9a60065b 1216 //
kadonotakashi 0:8fdf9a60065b 1217
kadonotakashi 0:8fdf9a60065b 1218 void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 1219 (void)connection;
kadonotakashi 0:8fdf9a60065b 1220 }
kadonotakashi 0:8fdf9a60065b 1221
kadonotakashi 0:8fdf9a60065b 1222 void GenericSecurityManager::on_signed_write_received(
kadonotakashi 0:8fdf9a60065b 1223 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1224 sign_count_t sign_counter
kadonotakashi 0:8fdf9a60065b 1225 ) {
kadonotakashi 0:8fdf9a60065b 1226 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1227 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1228 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1229 return;
kadonotakashi 0:8fdf9a60065b 1230 }
kadonotakashi 0:8fdf9a60065b 1231 _db->set_entry_peer_sign_counter(cb->db_entry, sign_counter);
kadonotakashi 0:8fdf9a60065b 1232 }
kadonotakashi 0:8fdf9a60065b 1233
kadonotakashi 0:8fdf9a60065b 1234 void GenericSecurityManager::on_signed_write_verification_failure(
kadonotakashi 0:8fdf9a60065b 1235 connection_handle_t connection
kadonotakashi 0:8fdf9a60065b 1236 ) {
kadonotakashi 0:8fdf9a60065b 1237 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1238 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1239 return;
kadonotakashi 0:8fdf9a60065b 1240 }
kadonotakashi 0:8fdf9a60065b 1241
kadonotakashi 0:8fdf9a60065b 1242 const bool signing = cb->signing_override_default ?
kadonotakashi 0:8fdf9a60065b 1243 cb->signing_requested :
kadonotakashi 0:8fdf9a60065b 1244 _default_key_distribution.get_signing();
kadonotakashi 0:8fdf9a60065b 1245
kadonotakashi 0:8fdf9a60065b 1246 if (signing) {
kadonotakashi 0:8fdf9a60065b 1247 cb->csrk_failures++;
kadonotakashi 0:8fdf9a60065b 1248 if (cb->csrk_failures == 3) {
kadonotakashi 0:8fdf9a60065b 1249 cb->csrk_failures = 0;
kadonotakashi 0:8fdf9a60065b 1250 if (cb->is_master) {
kadonotakashi 0:8fdf9a60065b 1251 requestPairing(connection);
kadonotakashi 0:8fdf9a60065b 1252 } else {
kadonotakashi 0:8fdf9a60065b 1253 slave_security_request(connection);
kadonotakashi 0:8fdf9a60065b 1254 }
kadonotakashi 0:8fdf9a60065b 1255 }
kadonotakashi 0:8fdf9a60065b 1256 }
kadonotakashi 0:8fdf9a60065b 1257 }
kadonotakashi 0:8fdf9a60065b 1258
kadonotakashi 0:8fdf9a60065b 1259 void GenericSecurityManager::on_signed_write() {
kadonotakashi 0:8fdf9a60065b 1260 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1261 _db->set_local_sign_counter(_db->get_local_sign_counter() + 1);
kadonotakashi 0:8fdf9a60065b 1262 }
kadonotakashi 0:8fdf9a60065b 1263
kadonotakashi 0:8fdf9a60065b 1264 void GenericSecurityManager::on_slave_security_request(
kadonotakashi 0:8fdf9a60065b 1265 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1266 AuthenticationMask authentication
kadonotakashi 0:8fdf9a60065b 1267 ) {
kadonotakashi 0:8fdf9a60065b 1268 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1269 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1270 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1271 return;
kadonotakashi 0:8fdf9a60065b 1272 }
kadonotakashi 0:8fdf9a60065b 1273
kadonotakashi 0:8fdf9a60065b 1274 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1275 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1276 return;
kadonotakashi 0:8fdf9a60065b 1277 }
kadonotakashi 0:8fdf9a60065b 1278
kadonotakashi 0:8fdf9a60065b 1279 bool pairing_required = false;
kadonotakashi 0:8fdf9a60065b 1280
kadonotakashi 0:8fdf9a60065b 1281 if (authentication.get_secure_connections() && !flags->secure_connections_paired
kadonotakashi 0:8fdf9a60065b 1282 && _default_authentication.get_secure_connections()) {
kadonotakashi 0:8fdf9a60065b 1283 pairing_required = true;
kadonotakashi 0:8fdf9a60065b 1284 }
kadonotakashi 0:8fdf9a60065b 1285
kadonotakashi 0:8fdf9a60065b 1286 if (authentication.get_mitm() && !flags->ltk_mitm_protected) {
kadonotakashi 0:8fdf9a60065b 1287 pairing_required = true;
kadonotakashi 0:8fdf9a60065b 1288 cb->mitm_requested = true;
kadonotakashi 0:8fdf9a60065b 1289 }
kadonotakashi 0:8fdf9a60065b 1290
kadonotakashi 0:8fdf9a60065b 1291 if (pairing_required) {
kadonotakashi 0:8fdf9a60065b 1292 requestPairing(connection);
kadonotakashi 0:8fdf9a60065b 1293 } else if (!cb->encryption_requested) {
kadonotakashi 0:8fdf9a60065b 1294 /* this will refresh keys if encryption is already present */
kadonotakashi 0:8fdf9a60065b 1295 enable_encryption(connection);
kadonotakashi 0:8fdf9a60065b 1296 }
kadonotakashi 0:8fdf9a60065b 1297 }
kadonotakashi 0:8fdf9a60065b 1298
kadonotakashi 0:8fdf9a60065b 1299 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 1300 // Encryption
kadonotakashi 0:8fdf9a60065b 1301 //
kadonotakashi 0:8fdf9a60065b 1302
kadonotakashi 0:8fdf9a60065b 1303 void GenericSecurityManager::on_link_encryption_result(
kadonotakashi 0:8fdf9a60065b 1304 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1305 link_encryption_t result
kadonotakashi 0:8fdf9a60065b 1306 ) {
kadonotakashi 0:8fdf9a60065b 1307
kadonotakashi 0:8fdf9a60065b 1308 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1309 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1310 return;
kadonotakashi 0:8fdf9a60065b 1311 }
kadonotakashi 0:8fdf9a60065b 1312
kadonotakashi 0:8fdf9a60065b 1313 if (result == link_encryption_t::ENCRYPTED) {
kadonotakashi 0:8fdf9a60065b 1314
kadonotakashi 0:8fdf9a60065b 1315 cb->encryption_requested = false;
kadonotakashi 0:8fdf9a60065b 1316 cb->encryption_failed = false;
kadonotakashi 0:8fdf9a60065b 1317 cb->encrypted = true;
kadonotakashi 0:8fdf9a60065b 1318
kadonotakashi 0:8fdf9a60065b 1319 } else if (
kadonotakashi 0:8fdf9a60065b 1320 result == link_encryption_t::ENCRYPTED_WITH_MITM ||
kadonotakashi 0:8fdf9a60065b 1321 result == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM
kadonotakashi 0:8fdf9a60065b 1322 ) {
kadonotakashi 0:8fdf9a60065b 1323
kadonotakashi 0:8fdf9a60065b 1324 cb->encryption_requested = false;
kadonotakashi 0:8fdf9a60065b 1325 cb->encryption_failed = false;
kadonotakashi 0:8fdf9a60065b 1326 cb->authenticated = true;
kadonotakashi 0:8fdf9a60065b 1327 cb->encrypted = true;
kadonotakashi 0:8fdf9a60065b 1328
kadonotakashi 0:8fdf9a60065b 1329 } else if (result == link_encryption_t::NOT_ENCRYPTED
kadonotakashi 0:8fdf9a60065b 1330 && cb->encryption_requested
kadonotakashi 0:8fdf9a60065b 1331 && !cb->encryption_failed) {
kadonotakashi 0:8fdf9a60065b 1332
kadonotakashi 0:8fdf9a60065b 1333 /* if we failed encryption for the first time
kadonotakashi 0:8fdf9a60065b 1334 * retry repairing in case slave lost LTK */
kadonotakashi 0:8fdf9a60065b 1335 requestPairing(cb->connection);
kadonotakashi 0:8fdf9a60065b 1336 cb->encryption_failed = true;
kadonotakashi 0:8fdf9a60065b 1337 /* don't return an event yet since we are retrying */
kadonotakashi 0:8fdf9a60065b 1338 return;
kadonotakashi 0:8fdf9a60065b 1339 }
kadonotakashi 0:8fdf9a60065b 1340
kadonotakashi 0:8fdf9a60065b 1341 eventHandler->linkEncryptionResult(connection, result);
kadonotakashi 0:8fdf9a60065b 1342 }
kadonotakashi 0:8fdf9a60065b 1343
kadonotakashi 0:8fdf9a60065b 1344 void GenericSecurityManager::on_link_encryption_request_timed_out(
kadonotakashi 0:8fdf9a60065b 1345 connection_handle_t connection
kadonotakashi 0:8fdf9a60065b 1346 ) {
kadonotakashi 0:8fdf9a60065b 1347 eventHandler->linkEncryptionResult(
kadonotakashi 0:8fdf9a60065b 1348 connection,
kadonotakashi 0:8fdf9a60065b 1349 link_encryption_t::NOT_ENCRYPTED
kadonotakashi 0:8fdf9a60065b 1350 );
kadonotakashi 0:8fdf9a60065b 1351 }
kadonotakashi 0:8fdf9a60065b 1352
kadonotakashi 0:8fdf9a60065b 1353 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 1354 // MITM
kadonotakashi 0:8fdf9a60065b 1355 //
kadonotakashi 0:8fdf9a60065b 1356
kadonotakashi 0:8fdf9a60065b 1357 void GenericSecurityManager::on_passkey_display(
kadonotakashi 0:8fdf9a60065b 1358 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1359 passkey_num_t passkey
kadonotakashi 0:8fdf9a60065b 1360 ) {
kadonotakashi 0:8fdf9a60065b 1361 set_mitm_performed(connection);
kadonotakashi 0:8fdf9a60065b 1362 eventHandler->passkeyDisplay(connection, PasskeyAscii(passkey).value());
kadonotakashi 0:8fdf9a60065b 1363 }
kadonotakashi 0:8fdf9a60065b 1364
kadonotakashi 0:8fdf9a60065b 1365 void GenericSecurityManager::on_keypress_notification(
kadonotakashi 0:8fdf9a60065b 1366 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1367 SecurityManager::Keypress_t keypress
kadonotakashi 0:8fdf9a60065b 1368 ) {
kadonotakashi 0:8fdf9a60065b 1369 set_mitm_performed(connection);
kadonotakashi 0:8fdf9a60065b 1370 eventHandler->keypressNotification(connection, keypress);
kadonotakashi 0:8fdf9a60065b 1371 }
kadonotakashi 0:8fdf9a60065b 1372
kadonotakashi 0:8fdf9a60065b 1373 void GenericSecurityManager::on_passkey_request(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 1374 set_mitm_performed(connection);
kadonotakashi 0:8fdf9a60065b 1375 eventHandler->passkeyRequest(connection);
kadonotakashi 0:8fdf9a60065b 1376 }
kadonotakashi 0:8fdf9a60065b 1377
kadonotakashi 0:8fdf9a60065b 1378 void GenericSecurityManager::on_confirmation_request(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 1379 set_mitm_performed(connection);
kadonotakashi 0:8fdf9a60065b 1380 eventHandler->confirmationRequest(connection);
kadonotakashi 0:8fdf9a60065b 1381 }
kadonotakashi 0:8fdf9a60065b 1382
kadonotakashi 0:8fdf9a60065b 1383 void GenericSecurityManager::on_secure_connections_oob_request(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 1384 set_mitm_performed(connection);
kadonotakashi 0:8fdf9a60065b 1385
kadonotakashi 0:8fdf9a60065b 1386 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1387 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1388 return;
kadonotakashi 0:8fdf9a60065b 1389 }
kadonotakashi 0:8fdf9a60065b 1390
kadonotakashi 0:8fdf9a60065b 1391 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1392 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1393 return;
kadonotakashi 0:8fdf9a60065b 1394 }
kadonotakashi 0:8fdf9a60065b 1395
kadonotakashi 0:8fdf9a60065b 1396 if (flags->peer_address == _oob_peer_address) {
kadonotakashi 0:8fdf9a60065b 1397 _pal.secure_connections_oob_request_reply(connection, _oob_local_random, _oob_peer_random, _oob_peer_confirm);
kadonotakashi 0:8fdf9a60065b 1398 /* do not re-use peer OOB */
kadonotakashi 0:8fdf9a60065b 1399 set_all_zeros(_oob_peer_address);
kadonotakashi 0:8fdf9a60065b 1400 } else {
kadonotakashi 0:8fdf9a60065b 1401 _pal.cancel_pairing(connection, pairing_failure_t::OOB_NOT_AVAILABLE);
kadonotakashi 0:8fdf9a60065b 1402 }
kadonotakashi 0:8fdf9a60065b 1403 }
kadonotakashi 0:8fdf9a60065b 1404
kadonotakashi 0:8fdf9a60065b 1405 void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) {
kadonotakashi 0:8fdf9a60065b 1406 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1407 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1408 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1409 return;
kadonotakashi 0:8fdf9a60065b 1410 }
kadonotakashi 0:8fdf9a60065b 1411
kadonotakashi 0:8fdf9a60065b 1412 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1413 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1414 return;
kadonotakashi 0:8fdf9a60065b 1415 }
kadonotakashi 0:8fdf9a60065b 1416
kadonotakashi 0:8fdf9a60065b 1417 if (flags->peer_address == _oob_temporary_key_creator_address
kadonotakashi 0:8fdf9a60065b 1418 || cb->local_address == _oob_temporary_key_creator_address) {
kadonotakashi 0:8fdf9a60065b 1419
kadonotakashi 0:8fdf9a60065b 1420 set_mitm_performed(connection);
kadonotakashi 0:8fdf9a60065b 1421 _pal.legacy_pairing_oob_request_reply(connection, _oob_temporary_key);
kadonotakashi 0:8fdf9a60065b 1422
kadonotakashi 0:8fdf9a60065b 1423 /* do not re-use peer OOB */
kadonotakashi 0:8fdf9a60065b 1424 if (flags->peer_address == _oob_temporary_key_creator_address) {
kadonotakashi 0:8fdf9a60065b 1425 set_all_zeros(_oob_temporary_key_creator_address);
kadonotakashi 0:8fdf9a60065b 1426 }
kadonotakashi 0:8fdf9a60065b 1427
kadonotakashi 0:8fdf9a60065b 1428 } else if (!cb->legacy_pairing_oob_request_pending) {
kadonotakashi 0:8fdf9a60065b 1429
kadonotakashi 0:8fdf9a60065b 1430 cb->legacy_pairing_oob_request_pending = true;
kadonotakashi 0:8fdf9a60065b 1431 eventHandler->legacyPairingOobRequest(connection);
kadonotakashi 0:8fdf9a60065b 1432
kadonotakashi 0:8fdf9a60065b 1433 }
kadonotakashi 0:8fdf9a60065b 1434 }
kadonotakashi 0:8fdf9a60065b 1435
kadonotakashi 0:8fdf9a60065b 1436 void GenericSecurityManager::on_secure_connections_oob_generated(
kadonotakashi 0:8fdf9a60065b 1437 const oob_lesc_value_t &random,
kadonotakashi 0:8fdf9a60065b 1438 const oob_confirm_t &confirm
kadonotakashi 0:8fdf9a60065b 1439 ) {
kadonotakashi 0:8fdf9a60065b 1440 eventHandler->oobGenerated(&_oob_local_address, &random, &confirm);
kadonotakashi 0:8fdf9a60065b 1441 _oob_local_random = random;
kadonotakashi 0:8fdf9a60065b 1442 }
kadonotakashi 0:8fdf9a60065b 1443
kadonotakashi 0:8fdf9a60065b 1444 ////////////////////////////////////////////////////////////////////////////
kadonotakashi 0:8fdf9a60065b 1445 // Keys
kadonotakashi 0:8fdf9a60065b 1446 //
kadonotakashi 0:8fdf9a60065b 1447
kadonotakashi 0:8fdf9a60065b 1448 void GenericSecurityManager::on_secure_connections_ltk_generated(
kadonotakashi 0:8fdf9a60065b 1449 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1450 const ltk_t &ltk
kadonotakashi 0:8fdf9a60065b 1451 ) {
kadonotakashi 0:8fdf9a60065b 1452 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1453 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1454 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1455 return;
kadonotakashi 0:8fdf9a60065b 1456 }
kadonotakashi 0:8fdf9a60065b 1457
kadonotakashi 0:8fdf9a60065b 1458 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1459 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1460 return;
kadonotakashi 0:8fdf9a60065b 1461 }
kadonotakashi 0:8fdf9a60065b 1462
kadonotakashi 0:8fdf9a60065b 1463 flags->ltk_mitm_protected = cb->mitm_performed;
kadonotakashi 0:8fdf9a60065b 1464 flags->secure_connections_paired = true;
kadonotakashi 0:8fdf9a60065b 1465
kadonotakashi 0:8fdf9a60065b 1466 _db->set_entry_peer_ltk(cb->db_entry, ltk);
kadonotakashi 0:8fdf9a60065b 1467 _db->set_entry_local_ltk(cb->db_entry, ltk);
kadonotakashi 0:8fdf9a60065b 1468 }
kadonotakashi 0:8fdf9a60065b 1469
kadonotakashi 0:8fdf9a60065b 1470 void GenericSecurityManager::on_keys_distributed_ltk(
kadonotakashi 0:8fdf9a60065b 1471 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1472 const ltk_t &ltk
kadonotakashi 0:8fdf9a60065b 1473 ) {
kadonotakashi 0:8fdf9a60065b 1474 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1475 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1476 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1477 return;
kadonotakashi 0:8fdf9a60065b 1478 }
kadonotakashi 0:8fdf9a60065b 1479
kadonotakashi 0:8fdf9a60065b 1480 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1481 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1482 return;
kadonotakashi 0:8fdf9a60065b 1483 }
kadonotakashi 0:8fdf9a60065b 1484
kadonotakashi 0:8fdf9a60065b 1485 flags->ltk_mitm_protected = cb->mitm_performed;
kadonotakashi 0:8fdf9a60065b 1486
kadonotakashi 0:8fdf9a60065b 1487 _db->set_entry_peer_ltk(cb->db_entry, ltk);
kadonotakashi 0:8fdf9a60065b 1488 }
kadonotakashi 0:8fdf9a60065b 1489
kadonotakashi 0:8fdf9a60065b 1490 void GenericSecurityManager::on_keys_distributed_ediv_rand(
kadonotakashi 0:8fdf9a60065b 1491 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1492 const ediv_t &ediv,
kadonotakashi 0:8fdf9a60065b 1493 const rand_t &rand
kadonotakashi 0:8fdf9a60065b 1494 ) {
kadonotakashi 0:8fdf9a60065b 1495 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1496 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1497 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1498 return;
kadonotakashi 0:8fdf9a60065b 1499 }
kadonotakashi 0:8fdf9a60065b 1500
kadonotakashi 0:8fdf9a60065b 1501 _db->set_entry_peer_ediv_rand(cb->db_entry, ediv, rand);
kadonotakashi 0:8fdf9a60065b 1502 }
kadonotakashi 0:8fdf9a60065b 1503
kadonotakashi 0:8fdf9a60065b 1504 void GenericSecurityManager::on_keys_distributed_local_ltk(
kadonotakashi 0:8fdf9a60065b 1505 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1506 const ltk_t &ltk
kadonotakashi 0:8fdf9a60065b 1507 ) {
kadonotakashi 0:8fdf9a60065b 1508 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1509 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1510 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1511 return;
kadonotakashi 0:8fdf9a60065b 1512 }
kadonotakashi 0:8fdf9a60065b 1513
kadonotakashi 0:8fdf9a60065b 1514 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1515 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1516 return;
kadonotakashi 0:8fdf9a60065b 1517 }
kadonotakashi 0:8fdf9a60065b 1518
kadonotakashi 0:8fdf9a60065b 1519 _db->set_entry_local_ltk(cb->db_entry, ltk);
kadonotakashi 0:8fdf9a60065b 1520 }
kadonotakashi 0:8fdf9a60065b 1521
kadonotakashi 0:8fdf9a60065b 1522 void GenericSecurityManager::on_keys_distributed_local_ediv_rand(
kadonotakashi 0:8fdf9a60065b 1523 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1524 const ediv_t &ediv,
kadonotakashi 0:8fdf9a60065b 1525 const rand_t &rand
kadonotakashi 0:8fdf9a60065b 1526 ) {
kadonotakashi 0:8fdf9a60065b 1527 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1528 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1529 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1530 return;
kadonotakashi 0:8fdf9a60065b 1531 }
kadonotakashi 0:8fdf9a60065b 1532
kadonotakashi 0:8fdf9a60065b 1533 _db->set_entry_local_ediv_rand(cb->db_entry, ediv, rand);
kadonotakashi 0:8fdf9a60065b 1534 }
kadonotakashi 0:8fdf9a60065b 1535
kadonotakashi 0:8fdf9a60065b 1536 void GenericSecurityManager::on_keys_distributed_irk(
kadonotakashi 0:8fdf9a60065b 1537 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1538 const irk_t &irk
kadonotakashi 0:8fdf9a60065b 1539 ) {
kadonotakashi 0:8fdf9a60065b 1540 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1541 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1542 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1543 return;
kadonotakashi 0:8fdf9a60065b 1544 }
kadonotakashi 0:8fdf9a60065b 1545
kadonotakashi 0:8fdf9a60065b 1546 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1547 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1548 return;
kadonotakashi 0:8fdf9a60065b 1549 }
kadonotakashi 0:8fdf9a60065b 1550
kadonotakashi 0:8fdf9a60065b 1551 _db->set_entry_peer_irk(cb->db_entry, irk);
kadonotakashi 0:8fdf9a60065b 1552 }
kadonotakashi 0:8fdf9a60065b 1553
kadonotakashi 0:8fdf9a60065b 1554 void GenericSecurityManager::on_keys_distributed_bdaddr(
kadonotakashi 0:8fdf9a60065b 1555 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1556 advertising_peer_address_type_t peer_address_type,
kadonotakashi 0:8fdf9a60065b 1557 const address_t &peer_identity_address
kadonotakashi 0:8fdf9a60065b 1558 ) {
kadonotakashi 0:8fdf9a60065b 1559 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1560 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1561 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1562 return;
kadonotakashi 0:8fdf9a60065b 1563 }
kadonotakashi 0:8fdf9a60065b 1564
kadonotakashi 0:8fdf9a60065b 1565 _db->set_entry_peer_bdaddr(
kadonotakashi 0:8fdf9a60065b 1566 cb->db_entry,
kadonotakashi 0:8fdf9a60065b 1567 (peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS),
kadonotakashi 0:8fdf9a60065b 1568 peer_identity_address
kadonotakashi 0:8fdf9a60065b 1569 );
kadonotakashi 0:8fdf9a60065b 1570 }
kadonotakashi 0:8fdf9a60065b 1571
kadonotakashi 0:8fdf9a60065b 1572 void GenericSecurityManager::on_keys_distributed_csrk(
kadonotakashi 0:8fdf9a60065b 1573 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1574 const csrk_t &csrk
kadonotakashi 0:8fdf9a60065b 1575 ) {
kadonotakashi 0:8fdf9a60065b 1576 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1577 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1578 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1579 return;
kadonotakashi 0:8fdf9a60065b 1580 }
kadonotakashi 0:8fdf9a60065b 1581
kadonotakashi 0:8fdf9a60065b 1582 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1583 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1584 return;
kadonotakashi 0:8fdf9a60065b 1585 }
kadonotakashi 0:8fdf9a60065b 1586
kadonotakashi 0:8fdf9a60065b 1587 flags->csrk_mitm_protected = cb->mitm_performed;
kadonotakashi 0:8fdf9a60065b 1588 _db->set_entry_peer_csrk(cb->db_entry, csrk);
kadonotakashi 0:8fdf9a60065b 1589
kadonotakashi 0:8fdf9a60065b 1590 eventHandler->signingKey(
kadonotakashi 0:8fdf9a60065b 1591 connection,
kadonotakashi 0:8fdf9a60065b 1592 &csrk,
kadonotakashi 0:8fdf9a60065b 1593 flags->csrk_mitm_protected
kadonotakashi 0:8fdf9a60065b 1594 );
kadonotakashi 0:8fdf9a60065b 1595 }
kadonotakashi 0:8fdf9a60065b 1596
kadonotakashi 0:8fdf9a60065b 1597 void GenericSecurityManager::on_ltk_request(
kadonotakashi 0:8fdf9a60065b 1598 connection_handle_t connection,
kadonotakashi 0:8fdf9a60065b 1599 const ediv_t &ediv,
kadonotakashi 0:8fdf9a60065b 1600 const rand_t &rand
kadonotakashi 0:8fdf9a60065b 1601 ) {
kadonotakashi 0:8fdf9a60065b 1602 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1603 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1604 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1605 return;
kadonotakashi 0:8fdf9a60065b 1606 }
kadonotakashi 0:8fdf9a60065b 1607
kadonotakashi 0:8fdf9a60065b 1608 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1609 if (!flags) {
kadonotakashi 0:8fdf9a60065b 1610 return;
kadonotakashi 0:8fdf9a60065b 1611 }
kadonotakashi 0:8fdf9a60065b 1612
kadonotakashi 0:8fdf9a60065b 1613 _db->get_entry_local_keys(
kadonotakashi 0:8fdf9a60065b 1614 mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
kadonotakashi 0:8fdf9a60065b 1615 cb->db_entry,
kadonotakashi 0:8fdf9a60065b 1616 ediv,
kadonotakashi 0:8fdf9a60065b 1617 rand
kadonotakashi 0:8fdf9a60065b 1618 );
kadonotakashi 0:8fdf9a60065b 1619 }
kadonotakashi 0:8fdf9a60065b 1620
kadonotakashi 0:8fdf9a60065b 1621 /* control blocks list management */
kadonotakashi 0:8fdf9a60065b 1622
kadonotakashi 0:8fdf9a60065b 1623 GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
kadonotakashi 0:8fdf9a60065b 1624 connection(0),
kadonotakashi 0:8fdf9a60065b 1625 db_entry(0),
kadonotakashi 0:8fdf9a60065b 1626 local_address(),
kadonotakashi 0:8fdf9a60065b 1627 connected(false),
kadonotakashi 0:8fdf9a60065b 1628 authenticated(false),
kadonotakashi 0:8fdf9a60065b 1629 is_master(false),
kadonotakashi 0:8fdf9a60065b 1630 encryption_requested(false),
kadonotakashi 0:8fdf9a60065b 1631 encryption_failed(false),
kadonotakashi 0:8fdf9a60065b 1632 encrypted(false),
kadonotakashi 0:8fdf9a60065b 1633 signing_requested(false),
kadonotakashi 0:8fdf9a60065b 1634 signing_override_default(false),
kadonotakashi 0:8fdf9a60065b 1635 mitm_requested(false),
kadonotakashi 0:8fdf9a60065b 1636 mitm_performed(false),
kadonotakashi 0:8fdf9a60065b 1637 attempt_oob(false),
kadonotakashi 0:8fdf9a60065b 1638 oob_mitm_protection(false),
kadonotakashi 0:8fdf9a60065b 1639 oob_present(false),
kadonotakashi 0:8fdf9a60065b 1640 legacy_pairing_oob_request_pending(false),
kadonotakashi 0:8fdf9a60065b 1641 csrk_failures(0) { }
kadonotakashi 0:8fdf9a60065b 1642
kadonotakashi 0:8fdf9a60065b 1643 void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
kadonotakashi 0:8fdf9a60065b 1644 {
kadonotakashi 0:8fdf9a60065b 1645 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1646 ControlBlock_t *cb = get_control_block(connection);
kadonotakashi 0:8fdf9a60065b 1647 if (!cb) {
kadonotakashi 0:8fdf9a60065b 1648 return;
kadonotakashi 0:8fdf9a60065b 1649 }
kadonotakashi 0:8fdf9a60065b 1650
kadonotakashi 0:8fdf9a60065b 1651 _db->get_entry_local_keys(
kadonotakashi 0:8fdf9a60065b 1652 mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
kadonotakashi 0:8fdf9a60065b 1653 cb->db_entry
kadonotakashi 0:8fdf9a60065b 1654 );
kadonotakashi 0:8fdf9a60065b 1655 }
kadonotakashi 0:8fdf9a60065b 1656
kadonotakashi 0:8fdf9a60065b 1657 GenericSecurityManager::ControlBlock_t*
kadonotakashi 0:8fdf9a60065b 1658 GenericSecurityManager::acquire_control_block(connection_handle_t connection)
kadonotakashi 0:8fdf9a60065b 1659 {
kadonotakashi 0:8fdf9a60065b 1660 /* grab the first disconnected slot*/
kadonotakashi 0:8fdf9a60065b 1661 for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
kadonotakashi 0:8fdf9a60065b 1662 if (!_control_blocks[i].connected) {
kadonotakashi 0:8fdf9a60065b 1663 ControlBlock_t* cb = &_control_blocks[i];
kadonotakashi 0:8fdf9a60065b 1664 cb->connected = true;
kadonotakashi 0:8fdf9a60065b 1665 cb->connection = connection;
kadonotakashi 0:8fdf9a60065b 1666 return cb;
kadonotakashi 0:8fdf9a60065b 1667 }
kadonotakashi 0:8fdf9a60065b 1668 }
kadonotakashi 0:8fdf9a60065b 1669
kadonotakashi 0:8fdf9a60065b 1670 return NULL;
kadonotakashi 0:8fdf9a60065b 1671 }
kadonotakashi 0:8fdf9a60065b 1672
kadonotakashi 0:8fdf9a60065b 1673 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
kadonotakashi 0:8fdf9a60065b 1674 connection_handle_t connection
kadonotakashi 0:8fdf9a60065b 1675 ) {
kadonotakashi 0:8fdf9a60065b 1676 for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
kadonotakashi 0:8fdf9a60065b 1677 if (!_control_blocks[i].connected) {
kadonotakashi 0:8fdf9a60065b 1678 continue;
kadonotakashi 0:8fdf9a60065b 1679 } else if (connection == _control_blocks[i].connection) {
kadonotakashi 0:8fdf9a60065b 1680 return &_control_blocks[i];
kadonotakashi 0:8fdf9a60065b 1681 }
kadonotakashi 0:8fdf9a60065b 1682 }
kadonotakashi 0:8fdf9a60065b 1683 return NULL;
kadonotakashi 0:8fdf9a60065b 1684 }
kadonotakashi 0:8fdf9a60065b 1685
kadonotakashi 0:8fdf9a60065b 1686 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
kadonotakashi 0:8fdf9a60065b 1687 const address_t &peer_address
kadonotakashi 0:8fdf9a60065b 1688 ) {
kadonotakashi 0:8fdf9a60065b 1689 MBED_ASSERT(_db);
kadonotakashi 0:8fdf9a60065b 1690 for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
kadonotakashi 0:8fdf9a60065b 1691 ControlBlock_t *cb = &_control_blocks[i];
kadonotakashi 0:8fdf9a60065b 1692 if (cb->connected) {
kadonotakashi 0:8fdf9a60065b 1693 SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
kadonotakashi 0:8fdf9a60065b 1694 if (flags && (flags->peer_address == peer_address)) {
kadonotakashi 0:8fdf9a60065b 1695 return cb;
kadonotakashi 0:8fdf9a60065b 1696 }
kadonotakashi 0:8fdf9a60065b 1697 }
kadonotakashi 0:8fdf9a60065b 1698 }
kadonotakashi 0:8fdf9a60065b 1699 return NULL;
kadonotakashi 0:8fdf9a60065b 1700 }
kadonotakashi 0:8fdf9a60065b 1701
kadonotakashi 0:8fdf9a60065b 1702 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
kadonotakashi 0:8fdf9a60065b 1703 SecurityDb::entry_handle_t db_entry
kadonotakashi 0:8fdf9a60065b 1704 ) {
kadonotakashi 0:8fdf9a60065b 1705 for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
kadonotakashi 0:8fdf9a60065b 1706 if (!_control_blocks[i].connected) {
kadonotakashi 0:8fdf9a60065b 1707 continue;
kadonotakashi 0:8fdf9a60065b 1708 } else if (db_entry == _control_blocks[i].db_entry) {
kadonotakashi 0:8fdf9a60065b 1709 return &_control_blocks[i];
kadonotakashi 0:8fdf9a60065b 1710 }
kadonotakashi 0:8fdf9a60065b 1711 }
kadonotakashi 0:8fdf9a60065b 1712 return NULL;
kadonotakashi 0:8fdf9a60065b 1713 }
kadonotakashi 0:8fdf9a60065b 1714
kadonotakashi 0:8fdf9a60065b 1715 void GenericSecurityManager::release_control_block(ControlBlock_t* cb)
kadonotakashi 0:8fdf9a60065b 1716 {
kadonotakashi 0:8fdf9a60065b 1717 *cb = ControlBlock_t();
kadonotakashi 0:8fdf9a60065b 1718 }
kadonotakashi 0:8fdf9a60065b 1719
kadonotakashi 0:8fdf9a60065b 1720 } /* namespace generic */
kadonotakashi 0:8fdf9a60065b 1721 } /* namespace ble */