Denislam Valeev / Mbed OS Nucleo_rtos_basic
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GenericSecurityManager.cpp Source File

GenericSecurityManager.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017-2018 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "ble/SecurityManager.h"
00018 #include "ble/pal/PalSecurityManager.h"
00019 #include "ble/generic/GenericSecurityManager.h"
00020 #if defined(MBEDTLS_CMAC_C)
00021 #include "mbedtls/cmac.h"
00022 #endif
00023 
00024 using ble::pal::advertising_peer_address_type_t;
00025 using ble::pal::AuthenticationMask;
00026 using ble::pal::KeyDistribution;
00027 using ble::pal::connection_peer_address_type_t;
00028 
00029 namespace ble {
00030 namespace generic {
00031 
00032 /* Implements SecurityManager */
00033 
00034 ////////////////////////////////////////////////////////////////////////////
00035 // SM lifecycle management
00036 //
00037 
00038 ble_error_t GenericSecurityManager::init(
00039     bool bondable,
00040     bool mitm,
00041     SecurityIOCapabilities_t iocaps,
00042     const Passkey_t passkey,
00043     bool signing
00044 ) {
00045     _db.restore();
00046     _pal.set_io_capability((io_capability_t::type) iocaps);
00047 
00048     if (passkey) {
00049         _pal.set_display_passkey(PasskeyAscii::to_num(passkey));
00050     } else {
00051         _pal.set_display_passkey(0);
00052     }
00053 
00054     _legacy_pairing_allowed = true;
00055 
00056     bool secure_connections;
00057     _pal.get_secure_connections_support(secure_connections);
00058 
00059     _default_authentication.set_bondable(bondable);
00060     _default_authentication.set_mitm(mitm);
00061     _default_authentication.set_secure_connections(secure_connections);
00062     _default_authentication.set_keypress_notification(true);
00063 
00064     _default_key_distribution.set_link(secure_connections);
00065 
00066     _default_key_distribution.set_signing(signing);
00067     if (signing) {
00068         init_signing();
00069     }
00070 
00071     _connection_monitor.set_connection_event_handler(this);
00072     _pal.set_event_handler(this);
00073 
00074     _pal.generate_public_key();
00075 
00076     return BLE_ERROR_NONE;
00077 }
00078 
00079 ble_error_t GenericSecurityManager::reset(void) {
00080     _db.sync();
00081     _public_keys_generated = false;
00082     SecurityManager::reset();
00083 
00084     return BLE_ERROR_NONE;
00085 }
00086 
00087 ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
00088     _db.set_restore(enabled);
00089     return BLE_ERROR_NONE;
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////////////
00093 // List management
00094 //
00095 
00096 ble_error_t GenericSecurityManager::purgeAllBondingState(void) {
00097     _db.clear_entries();
00098     return BLE_ERROR_NONE;
00099 }
00100 
00101 ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const {
00102     if (eventHandler) {
00103         _db.generate_whitelist_from_bond_table(
00104             mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable),
00105             whitelist
00106         );
00107     }
00108     return BLE_ERROR_NONE;
00109 }
00110 
00111 ////////////////////////////////////////////////////////////////////////////
00112 // Pairing
00113 //
00114 
00115 ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connection) {
00116     ControlBlock_t *cb = get_control_block(connection);
00117     if (!cb) {
00118         return BLE_ERROR_INVALID_PARAM;
00119     }
00120 
00121     if (!_legacy_pairing_allowed && !_default_authentication.get_secure_connections()) {
00122         return BLE_ERROR_INVALID_STATE;
00123     }
00124 
00125     set_mitm_performed(connection, false);
00126     update_oob_presence(connection);
00127 
00128     AuthenticationMask link_authentication(_default_authentication);
00129 
00130     if (cb->mitm_requested) {
00131         link_authentication.set_mitm(true);
00132     }
00133 
00134     /* by default the initiator doesn't send any keys other then identity */
00135     KeyDistribution initiator_distribution(
00136         KeyDistribution::KEY_DISTRIBUTION_IDENTITY | _default_key_distribution.get_link()
00137     );
00138 
00139     /* if requested the initiator may send all the default keys for later
00140      * use when roles are changed */
00141     if (_master_sends_keys) {
00142         initiator_distribution = _default_key_distribution;
00143     }
00144 
00145     /* override default if requested */
00146     if (cb->signing_override_default) {
00147         initiator_distribution.set_signing(cb->signing_requested);
00148     } else {
00149         /* because _master_sends_keys might be false so we need to set this */
00150         initiator_distribution.set_signing(_default_key_distribution.get_signing());
00151     }
00152 
00153     KeyDistribution responder_distribution(_default_key_distribution);
00154 
00155     if (cb->signing_override_default) {
00156         responder_distribution.set_signing(cb->signing_requested);
00157     }
00158 
00159     return _pal.send_pairing_request(
00160         connection,
00161         cb->oob_present,
00162         link_authentication,
00163         initiator_distribution,
00164         responder_distribution
00165     );
00166 }
00167 
00168 ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t connection) {
00169     ControlBlock_t *cb = get_control_block(connection);
00170     if (!cb) {
00171         return BLE_ERROR_INVALID_PARAM;
00172     }
00173 
00174     update_oob_presence(connection);
00175 
00176     AuthenticationMask link_authentication(_default_authentication);
00177     if (cb->mitm_requested) {
00178         link_authentication.set_mitm(true);
00179     }
00180 
00181     KeyDistribution initiator_distribution = cb->get_initiator_key_distribution();
00182 
00183     if (_master_sends_keys) {
00184         initiator_distribution &= _default_key_distribution;
00185     } else {
00186         initiator_distribution &= KeyDistribution(KeyDistribution::KEY_DISTRIBUTION_IDENTITY | KeyDistribution::KEY_DISTRIBUTION_LINK);
00187     }
00188 
00189     /* signing has to be offered and enabled on the link */
00190     if (initiator_distribution.get_signing()) {
00191         initiator_distribution.set_signing(
00192             cb->signing_override_default ? cb->signing_requested : _default_key_distribution.get_signing()
00193         );
00194     }
00195 
00196     KeyDistribution responder_distribution(cb->get_responder_key_distribution());
00197 
00198     responder_distribution &= _default_key_distribution;
00199 
00200     /* signing has to be requested and enabled on the link */
00201     if (responder_distribution.get_signing()) {
00202         responder_distribution.set_signing(
00203             cb->signing_override_default ? cb->signing_requested : _default_key_distribution.get_signing()
00204         );
00205     }
00206 
00207     return _pal.send_pairing_response(
00208         connection,
00209         cb->oob_present,
00210         link_authentication,
00211         initiator_distribution,
00212         responder_distribution
00213     );
00214 }
00215 
00216 ble_error_t GenericSecurityManager::cancelPairingRequest(connection_handle_t connection) {
00217     return _pal.cancel_pairing(connection, pairing_failure_t::UNSPECIFIED_REASON);
00218 }
00219 
00220 ble_error_t GenericSecurityManager::setPairingRequestAuthorisation(bool required) {
00221     _pairing_authorisation_required = required;
00222     return BLE_ERROR_NONE;
00223 }
00224 
00225 ////////////////////////////////////////////////////////////////////////////
00226 // Feature support
00227 //
00228 
00229 ble_error_t GenericSecurityManager::allowLegacyPairing(bool allow) {
00230     _legacy_pairing_allowed = allow;
00231     return BLE_ERROR_NONE;
00232 }
00233 
00234 ble_error_t GenericSecurityManager::getSecureConnectionsSupport(bool *enabled) {
00235     return _pal.get_secure_connections_support(*enabled);
00236 }
00237 
00238 ////////////////////////////////////////////////////////////////////////////
00239 // Security settings
00240 //
00241 
00242 ble_error_t GenericSecurityManager::setIoCapability(SecurityIOCapabilities_t iocaps) {
00243     return _pal.set_io_capability((io_capability_t::type) iocaps);
00244 }
00245 
00246 ble_error_t GenericSecurityManager::setDisplayPasskey(const Passkey_t passkey) {
00247     return _pal.set_display_passkey(PasskeyAscii::to_num(passkey));
00248 }
00249 
00250 ble_error_t GenericSecurityManager::setAuthenticationTimeout(
00251     connection_handle_t connection,
00252     uint32_t timeout_in_ms
00253 ) {
00254     return _pal.set_authentication_timeout(connection, timeout_in_ms / 10);
00255 }
00256 
00257 ble_error_t GenericSecurityManager::getAuthenticationTimeout(
00258     connection_handle_t connection,
00259     uint32_t *timeout_in_ms
00260 ) {
00261     uint16_t timeout_in_10ms;
00262     ble_error_t status = _pal.get_authentication_timeout(connection, timeout_in_10ms);
00263     *timeout_in_ms = 10 * timeout_in_10ms;
00264     return status;
00265 }
00266 
00267 ble_error_t GenericSecurityManager::setLinkSecurity(
00268     connection_handle_t connection,
00269     SecurityMode_t securityMode
00270 ) {
00271     ControlBlock_t *cb = get_control_block(connection);
00272     if (!cb) {
00273         return BLE_ERROR_INVALID_PARAM;
00274     }
00275 
00276     if (cb->encryption_requested) {
00277         return BLE_ERROR_OPERATION_NOT_PERMITTED;
00278     }
00279 
00280     switch (securityMode) {
00281         case SECURITY_MODE_ENCRYPTION_OPEN_LINK:
00282             return setLinkEncryption(connection, link_encryption_t::NOT_ENCRYPTED);
00283 
00284         case SECURITY_MODE_ENCRYPTION_NO_MITM:
00285             return setLinkEncryption(connection, link_encryption_t::ENCRYPTED);
00286 
00287         case SECURITY_MODE_ENCRYPTION_WITH_MITM:
00288             return setLinkEncryption(connection, link_encryption_t::ENCRYPTED_WITH_MITM);
00289 
00290         case SECURITY_MODE_SIGNED_NO_MITM:
00291             return getSigningKey(connection, false);
00292 
00293         case SECURITY_MODE_SIGNED_WITH_MITM:
00294             return getSigningKey(connection, true);
00295 
00296         default:
00297             return BLE_ERROR_INVALID_PARAM;
00298     }
00299 }
00300 
00301 ble_error_t GenericSecurityManager::setKeypressNotification(bool enabled) {
00302     _default_authentication.set_keypress_notification(enabled);
00303     return BLE_ERROR_NONE;
00304 }
00305 
00306 ble_error_t GenericSecurityManager::enableSigning(
00307     connection_handle_t connection,
00308     bool enabled
00309 ) {
00310     ControlBlock_t *cb = get_control_block(connection);
00311     if (!cb) {
00312         return BLE_ERROR_INVALID_PARAM;
00313     }
00314 
00315     cb->signing_requested = enabled;
00316     cb->signing_override_default = false;
00317 
00318     if (cb->encrypted) {
00319         return BLE_ERROR_INVALID_STATE;
00320     }
00321     if (!cb->csrk_stored && cb->signing_requested) {
00322         init_signing();
00323         if (cb->is_master) {
00324             return requestPairing(connection);
00325         } else {
00326             return slave_security_request(connection);
00327         }
00328     }
00329 
00330     return BLE_ERROR_NONE;
00331 }
00332 
00333 ble_error_t GenericSecurityManager::setHintFutureRoleReversal(bool enable) {
00334     _master_sends_keys = enable;
00335     return BLE_ERROR_NONE;
00336 }
00337 
00338 ////////////////////////////////////////////////////////////////////////////
00339 // Encryption
00340 //
00341 
00342 ble_error_t GenericSecurityManager::getLinkEncryption(
00343     connection_handle_t connection,
00344     link_encryption_t *encryption
00345 ) {
00346 
00347     ControlBlock_t *cb = get_control_block(connection);
00348     if (!cb) {
00349         return BLE_ERROR_INVALID_PARAM;
00350     }
00351 
00352     if (cb->encrypted) {
00353         if (cb->ltk_mitm_protected  || cb->mitm_performed) {
00354             *encryption = link_encryption_t::ENCRYPTED_WITH_MITM;
00355         } else {
00356             *encryption = link_encryption_t::ENCRYPTED;
00357         }
00358     } else if (cb->encryption_requested) {
00359         *encryption = link_encryption_t::ENCRYPTION_IN_PROGRESS;
00360     } else {
00361         *encryption = link_encryption_t::NOT_ENCRYPTED;
00362     }
00363 
00364     return BLE_ERROR_NONE;
00365 }
00366 
00367 ble_error_t GenericSecurityManager::setLinkEncryption(
00368     connection_handle_t connection,
00369     link_encryption_t encryption
00370 ) {
00371     ControlBlock_t *cb = get_control_block(connection);
00372     if (!cb) {
00373         return BLE_ERROR_INVALID_PARAM;
00374     }
00375 
00376     link_encryption_t current_encryption(link_encryption_t::NOT_ENCRYPTED);
00377     getLinkEncryption(connection, &current_encryption);
00378 
00379     if (current_encryption == link_encryption_t::ENCRYPTION_IN_PROGRESS) {
00380         return BLE_ERROR_OPERATION_NOT_PERMITTED;
00381     }
00382 
00383     if (current_encryption == encryption) {
00384 
00385         /* ignore if the link is already at required state*/
00386 
00387     } else if (encryption == link_encryption_t::NOT_ENCRYPTED) {
00388 
00389         /* ignore if we are requesting an open link on an already encrypted link */
00390 
00391     } else if (encryption == link_encryption_t::ENCRYPTED) {
00392 
00393         /* only change if we're not already encrypted with mitm */
00394         if (current_encryption != link_encryption_t::ENCRYPTED_WITH_MITM) {
00395             cb->encryption_requested = true;
00396             return enable_encryption(connection);
00397         }
00398 
00399     } else if (encryption == link_encryption_t::ENCRYPTED_WITH_MITM) {
00400 
00401         if (cb->ltk_mitm_protected && !cb->encrypted) {
00402             cb->encryption_requested = true;
00403             return enable_encryption(connection);
00404         } else {
00405             cb->encryption_requested = true;
00406             return requestAuthentication(connection);
00407         }
00408 
00409     } else {
00410         return BLE_ERROR_INVALID_PARAM;
00411     }
00412 
00413     eventHandler->linkEncryptionResult(connection, current_encryption);
00414 
00415     return BLE_ERROR_NONE;
00416 }
00417 
00418 ble_error_t GenericSecurityManager::getEncryptionKeySize(
00419     connection_handle_t connection,
00420     uint8_t *size
00421 ) {
00422     ControlBlock_t *cb = get_control_block(connection);
00423     if (cb) {
00424         *size = cb->encryption_key_size;
00425         return BLE_ERROR_NONE;
00426     } else {
00427         return BLE_ERROR_INVALID_PARAM;
00428     }
00429 }
00430 
00431 ble_error_t GenericSecurityManager::setEncryptionKeyRequirements(
00432     uint8_t minimumByteSize,
00433     uint8_t maximumByteSize
00434 ) {
00435     return _pal.set_encryption_key_requirements(minimumByteSize, maximumByteSize);
00436 }
00437 
00438 ////////////////////////////////////////////////////////////////////////////
00439 // Keys
00440 //
00441 
00442 ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) {
00443     ControlBlock_t *cb = get_control_block(connection);
00444     if (!cb) {
00445         return BLE_ERROR_INVALID_PARAM;
00446     }
00447 
00448     if (cb->csrk_stored && (cb->csrk_mitm_protected || !authenticated)) {
00449         /* we have a key that is either authenticated or we don't care if it is
00450          * so retrieve it from the db now */
00451         _db.get_entry_peer_csrk(
00452             mbed::callback(this, &GenericSecurityManager::return_csrk_cb),
00453             cb->db_entry
00454         );
00455         return BLE_ERROR_NONE;
00456 
00457     } else {
00458         /* we don't have the right key so we need to get it first
00459          * keys exchange will create the signingKey event */
00460         if (authenticated) {
00461             return requestAuthentication(connection);
00462         } else if (cb->is_master) {
00463             return requestPairing(connection);
00464         } else {
00465             return slave_security_request(connection);
00466         }
00467     }
00468 }
00469 
00470 ////////////////////////////////////////////////////////////////////////////
00471 // Privacy
00472 //
00473 
00474 ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds) {
00475    return _pal.set_private_address_timeout(timeout_in_seconds);
00476 }
00477 
00478 ////////////////////////////////////////////////////////////////////////////
00479 // Authentication
00480 //
00481 
00482 ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t connection) {
00483     ControlBlock_t *cb = get_control_block(connection);
00484     if (!cb) {
00485         return BLE_ERROR_INVALID_PARAM;
00486     }
00487 
00488     if (cb->ltk_mitm_protected) {
00489         if (cb->authenticated) {
00490             return BLE_ERROR_NONE;
00491         } else {
00492             cb->encryption_requested = true;
00493             return enable_encryption(connection);
00494         }
00495     } else {
00496         cb->mitm_requested = true;
00497         if (cb->is_master) {
00498             return requestPairing(connection);
00499         } else {
00500             return slave_security_request(connection);
00501         }
00502     }
00503 }
00504 
00505 ////////////////////////////////////////////////////////////////////////////
00506 // MITM
00507 //
00508 
00509 ble_error_t GenericSecurityManager::setOOBDataUsage(
00510     connection_handle_t connection,
00511     bool useOOB,
00512     bool OOBProvidesMITM
00513 ) {
00514     ControlBlock_t *cb = get_control_block(connection);
00515     if (!cb) {
00516         return BLE_ERROR_INVALID_PARAM;
00517     }
00518 
00519     cb->attempt_oob = useOOB;
00520     cb->oob_mitm_protection = OOBProvidesMITM;
00521 
00522 #if defined(MBEDTLS_CMAC_C)
00523     if (_public_keys_generated) {
00524         generate_secure_connections_oob(connection);
00525     }
00526 #endif
00527 
00528     return BLE_ERROR_NONE;
00529 }
00530 
00531 ble_error_t GenericSecurityManager::confirmationEntered(
00532     connection_handle_t connection,
00533     bool confirmation
00534 ) {
00535     return _pal.confirmation_entered(connection, confirmation);
00536 }
00537 
00538 ble_error_t GenericSecurityManager::passkeyEntered(
00539     connection_handle_t connection,
00540     Passkey_t passkey
00541 ) {
00542     return _pal.passkey_request_reply(
00543         connection,
00544         PasskeyAscii::to_num(passkey)
00545     );
00546 }
00547 
00548 ble_error_t GenericSecurityManager::sendKeypressNotification(
00549     connection_handle_t connection,
00550     Keypress_t keypress
00551 ) {
00552     return _pal.send_keypress_notification(connection, keypress);
00553 }
00554 
00555 ble_error_t GenericSecurityManager::legacyPairingOobReceived(
00556     const address_t *address,
00557     const oob_tk_t *tk
00558 ) {
00559     if (address && tk) {
00560         ControlBlock_t *cb = get_control_block(*address);
00561         if (!cb) {
00562             return BLE_ERROR_INVALID_PARAM;
00563         }
00564 
00565         return _pal.legacy_pairing_oob_data_request_reply(cb->connection, *tk);
00566     }
00567     return BLE_ERROR_NONE;
00568 }
00569 
00570 ble_error_t GenericSecurityManager::oobReceived(
00571     const address_t *address,
00572     const oob_lesc_value_t *random,
00573     const oob_confirm_t *confirm
00574 ) {
00575     if (address && random && confirm) {
00576         _peer_sc_oob_address = *address;
00577         _peer_sc_oob_random = *random;
00578         _peer_sc_oob_confirm = *confirm;
00579         return BLE_ERROR_NONE;
00580     }
00581 
00582     return BLE_ERROR_INVALID_PARAM;
00583 }
00584 
00585 ////////////////////////////////////////////////////////////////////////////
00586 // Helper functions
00587 //
00588 
00589 ble_error_t GenericSecurityManager::init_signing() {
00590     const csrk_t *pcsrk = _db.get_local_csrk();
00591     if (!pcsrk) {
00592         csrk_t csrk;
00593 
00594         ble_error_t ret = get_random_data(csrk.buffer(), csrk.size());
00595         if (ret != BLE_ERROR_NONE) {
00596             return ret;
00597         }
00598 
00599         pcsrk = &csrk;
00600         _db.set_local_csrk(csrk);
00601     }
00602     return _pal.set_csrk(*pcsrk);
00603 }
00604 
00605 ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size) {
00606     byte_array_t<8> random_data;
00607 
00608     while (size) {
00609         /* fill out the buffer by reading the random data in chunks
00610          * and copying it until reaching the set size */
00611         size_t copy_size = std::max(size, random_data.size());
00612         ble_error_t ret = _pal.get_random_data(random_data);
00613         if (ret != BLE_ERROR_NONE) {
00614             return ret;
00615         }
00616         memcpy(buffer, random_data.buffer(), copy_size);
00617         size -= copy_size;
00618         buffer += copy_size;
00619     }
00620 
00621     return BLE_ERROR_NONE;
00622 }
00623 
00624 ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t connection) {
00625     ControlBlock_t *cb = get_control_block(connection);
00626     if (!cb) {
00627         return BLE_ERROR_INVALID_PARAM;
00628     }
00629     AuthenticationMask link_authentication(_default_authentication);
00630     link_authentication.set_mitm(cb->mitm_requested);
00631     return _pal.slave_security_request(connection, link_authentication);
00632 }
00633 
00634 ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) {
00635     ControlBlock_t *cb = get_control_block(connection);
00636     if (!cb) {
00637         return BLE_ERROR_INVALID_PARAM;
00638     }
00639     if (cb->is_master) {
00640         if (cb->ltk_stored) {
00641             _db.get_entry_peer_keys(
00642                 mbed::callback(this, &GenericSecurityManager::enable_encryption_cb),
00643                 cb->db_entry
00644             );
00645             return BLE_ERROR_NONE;
00646         } else {
00647             return requestPairing(connection);
00648         }
00649     } else {
00650         return slave_security_request(connection);
00651     }
00652 }
00653 
00654 void GenericSecurityManager::enable_encryption_cb(
00655     pal::SecurityDb::entry_handle_t db_entry,
00656     const SecurityEntryKeys_t* entryKeys
00657 ) {
00658     ControlBlock_t *cb = get_control_block(db_entry);
00659 
00660     if (cb && entryKeys) {
00661         if (cb->secure_connections_paired) {
00662             _pal.enable_encryption(cb->connection, entryKeys->ltk, cb->ltk_mitm_protected);
00663         } else {
00664             _pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, cb->ltk_mitm_protected);
00665         }
00666     }
00667 }
00668 
00669 void GenericSecurityManager::set_ltk_cb(
00670     pal::SecurityDb::entry_handle_t db_entry,
00671     const SecurityEntryKeys_t* entryKeys
00672 ) {
00673     ControlBlock_t *cb = get_control_block(db_entry);
00674 
00675     if (cb) {
00676         if (entryKeys) {
00677             _pal.set_ltk(cb->connection, entryKeys->ltk, cb->ltk_mitm_protected, cb->secure_connections_paired);
00678         } else {
00679             _pal.set_ltk_not_found(cb->connection);
00680         }
00681     }
00682 }
00683 
00684 void GenericSecurityManager::return_csrk_cb(
00685     pal::SecurityDb::entry_handle_t db_entry,
00686     const csrk_t *csrk
00687 ) {
00688     ControlBlock_t *cb = get_control_block(db_entry);
00689     if (!cb) {
00690         return;
00691     }
00692 
00693     eventHandler->signingKey(
00694         cb->connection,
00695         csrk,
00696         cb->csrk_mitm_protected
00697     );
00698 }
00699 
00700 #if defined(MBEDTLS_CMAC_C)
00701 void GenericSecurityManager::generate_secure_connections_oob(
00702     connection_handle_t connection
00703 ) {
00704      oob_confirm_t confirm;
00705      oob_lesc_value_t random;
00706 
00707      ControlBlock_t *cb = get_control_block(connection);
00708      if (!cb) {
00709          return;
00710      }
00711 
00712      ble_error_t ret = get_random_data(random.buffer(), random.size());
00713      if (ret != BLE_ERROR_NONE) {
00714          return;
00715      }
00716 
00717      crypto_toolbox_f4(
00718          _db.get_public_key_x(),
00719          _db.get_public_key_y(),
00720          random,
00721          confirm
00722      );
00723 
00724     eventHandler->oobGenerated(
00725         &cb->local_address,
00726         &random,
00727         &confirm
00728     );
00729 
00730     _local_sc_oob_random = random;
00731 }
00732 #endif
00733 
00734 void GenericSecurityManager::update_oob_presence(connection_handle_t connection) {
00735     ControlBlock_t *cb = get_control_block(connection);
00736     if (!cb) {
00737         return;
00738     }
00739 
00740     /* only update the oob state if we support secure connections,
00741      * otherwise follow the user set preference for providing legacy
00742      * pairing oob data */
00743     cb->oob_present = cb->attempt_oob;
00744 
00745     if (_default_authentication.get_secure_connections()) {
00746         cb->oob_present = false;
00747 #if defined(MBEDTLS_CMAC_C)
00748         if (cb->peer_address == _peer_sc_oob_address) {
00749             cb->oob_present = true;
00750         }
00751 #endif
00752     }
00753 }
00754 
00755 #if defined(MBEDTLS_CMAC_C)
00756 bool GenericSecurityManager::crypto_toolbox_f4(
00757     const public_key_coord_t& U,
00758     const public_key_coord_t& V,
00759     const oob_lesc_value_t& X,
00760     oob_confirm_t& confirm
00761 ) {
00762 
00763     mbedtls_cipher_context_t context;
00764     const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
00765     const unsigned char Z = 0;
00766     bool success = false;
00767 
00768     mbedtls_cipher_init(&context);
00769 
00770     /* it's either this chaining or a goto */
00771     if (mbedtls_cipher_setup(&context, info) == 0
00772         && mbedtls_cipher_cmac_starts(&context, X.data(), 128) == 0
00773         && mbedtls_cipher_cmac_update(&context, U.data(), 16) == 0
00774         && mbedtls_cipher_cmac_update(&context, V.data(), 16) == 0
00775         && mbedtls_cipher_cmac_update(&context, &Z, 1) == 0
00776         && mbedtls_cipher_cmac_finish(&context, &confirm[0]) == 0) {
00777         success = true;
00778     }
00779 
00780     mbedtls_cipher_free(&context);
00781     return success;
00782 }
00783 #endif
00784 
00785 void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, bool enable) {
00786     ControlBlock_t *cb = get_control_block(connection);
00787     if (cb) {
00788         cb->mitm_performed = enable;
00789     }
00790 }
00791 
00792 void GenericSecurityManager::on_connected(
00793     connection_handle_t connection,
00794     Gap::Role_t role,
00795     BLEProtocol::AddressType_t peer_address_type,
00796     const BLEProtocol::AddressBytes_t peer_address,
00797     BLEProtocol::AddressType_t local_address_type,
00798     const BLEProtocol::AddressBytes_t local_address,
00799     const Gap::ConnectionParams_t *connection_params
00800 ) {
00801     ControlBlock_t *cb = acquire_control_block(connection);
00802     if (!cb) {
00803         return;
00804     }
00805 
00806     // setup the control block
00807     cb->peer_address = peer_address;
00808     cb->local_address = local_address;
00809     cb->peer_address_is_public =
00810         (peer_address_type == BLEProtocol::AddressType::PUBLIC);
00811     cb->is_master = (role == Gap::CENTRAL);
00812 
00813     // get the associated db handle and the distribution flags if any
00814     cb->db_entry = _db.open_entry(peer_address_type, peer_address);
00815 
00816     const pal::SecurityDistributionFlags_t* dist_flags =
00817         _db.get_distribution_flags(cb->db_entry);
00818 
00819     if (dist_flags) {
00820         *static_cast<pal::SecurityDistributionFlags_t*>(cb) = *dist_flags;
00821     }
00822 }
00823 
00824 void GenericSecurityManager::on_disconnected(
00825     connection_handle_t connection,
00826     Gap::DisconnectionReason_t reason
00827 ) {
00828     ControlBlock_t *cb = get_control_block(connection);
00829     if (!cb) {
00830         return;
00831     }
00832 
00833     _db.close_entry(cb->db_entry);
00834     release_control_block(cb);
00835 
00836     _db.sync();
00837 }
00838 
00839 /* Implements ble::pal::SecurityManagerEventHandler */
00840 
00841 ////////////////////////////////////////////////////////////////////////////
00842 // Pairing
00843 //
00844 
00845 void GenericSecurityManager::on_pairing_request(
00846     connection_handle_t connection,
00847     bool use_oob,
00848     AuthenticationMask authentication,
00849     KeyDistribution initiator_dist,
00850     KeyDistribution responder_dist
00851 ) {
00852     /* cancel pairing if secure connection paring is not possible */
00853     if (!_legacy_pairing_allowed && !authentication.get_secure_connections()) {
00854         cancelPairingRequest(connection);
00855     }
00856 
00857     ControlBlock_t *cb = get_control_block(connection);
00858     if (!cb) {
00859         return;
00860     }
00861 
00862     cb->set_initiator_key_distribution(initiator_dist);
00863     cb->set_responder_key_distribution(responder_dist);
00864 
00865     cb->mitm_performed = false;
00866 
00867     if (_pairing_authorisation_required) {
00868         eventHandler->pairingRequest(connection);
00869     } else {
00870         acceptPairingRequest(connection);
00871     }
00872 }
00873 
00874 void GenericSecurityManager::on_pairing_error(
00875     connection_handle_t connection,
00876     pairing_failure_t error
00877 ) {
00878     set_mitm_performed(connection, false);
00879 
00880     eventHandler->pairingResult(
00881         connection,
00882         (SecurityManager::SecurityCompletionStatus_t)(error.value() | 0x80)
00883     );
00884 
00885     /* if this pairing was triggered by a failed encryption attempt
00886      * inform the application of the encryption failure */
00887     ControlBlock_t *cb = get_control_block(connection);
00888     if (cb && cb->encryption_requested && cb->encryption_failed) {
00889         eventHandler->linkEncryptionResult(
00890             connection,
00891             link_encryption_t::NOT_ENCRYPTED
00892         );
00893     }
00894 }
00895 
00896 void GenericSecurityManager::on_pairing_timed_out(connection_handle_t connection) {
00897     set_mitm_performed(connection, false);
00898 
00899     eventHandler->pairingResult(
00900         connection,
00901         SecurityManager::SEC_STATUS_TIMEOUT
00902     );
00903 }
00904 
00905 void GenericSecurityManager::on_pairing_completed(connection_handle_t connection) {
00906     ControlBlock_t *cb = get_control_block(connection);
00907     if (cb) {
00908         // set the distribution flags in the db
00909         _db.set_distribution_flags(cb->db_entry, *cb);
00910     }
00911 
00912     eventHandler->pairingResult(
00913         connection,
00914         SecurityManager::SEC_STATUS_SUCCESS
00915     );
00916 }
00917 
00918 ////////////////////////////////////////////////////////////////////////////
00919 // Security
00920 //
00921 
00922 void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection) {
00923     (void)connection;
00924 }
00925 
00926 void GenericSecurityManager::on_slave_security_request(
00927     connection_handle_t connection,
00928     AuthenticationMask authentication
00929 ) {
00930     ControlBlock_t *cb = get_control_block(connection);
00931     if (!cb) {
00932         return;
00933     }
00934 
00935     if (authentication.get_secure_connections()
00936         && _default_authentication.get_secure_connections()
00937         && !cb->secure_connections_paired) {
00938         requestPairing(connection);
00939     }
00940 
00941     if (authentication.get_mitm()
00942         && !cb->ltk_mitm_protected) {
00943         cb->mitm_requested = true;
00944         requestPairing(connection);
00945     }
00946 }
00947 
00948 ////////////////////////////////////////////////////////////////////////////
00949 // Encryption
00950 //
00951 
00952 void GenericSecurityManager::on_link_encryption_result(
00953     connection_handle_t connection,
00954     link_encryption_t result
00955 ) {
00956 
00957     ControlBlock_t *cb = get_control_block(connection);
00958     if (!cb) {
00959         return;
00960     }
00961 
00962     if (result == link_encryption_t::ENCRYPTED) {
00963 
00964         cb->encryption_requested = false;
00965         cb->encryption_failed = false;
00966         cb->encrypted = true;
00967 
00968     } else if (result == link_encryption_t::ENCRYPTED_WITH_MITM) {
00969 
00970         cb->encryption_requested = false;
00971         cb->encryption_failed = false;
00972         cb->authenticated = true;
00973         cb->encrypted = true;
00974 
00975     } else if (result == link_encryption_t::NOT_ENCRYPTED
00976                && cb->encryption_requested
00977                && !cb->encryption_failed) {
00978 
00979         /* if we failed encryption for the first time
00980          * retry repairing in case slave lost LTK */
00981         requestPairing(cb->connection);
00982         cb->encryption_failed = true;
00983         /* don't return an event yet since we are retrying */
00984         return;
00985     }
00986 
00987     eventHandler->linkEncryptionResult(connection, result);
00988 }
00989 
00990 void GenericSecurityManager::on_link_encryption_request_timed_out(
00991     connection_handle_t connection
00992 ) {
00993     eventHandler->linkEncryptionResult(
00994         connection,
00995         link_encryption_t::NOT_ENCRYPTED
00996     );
00997 }
00998 
00999 ////////////////////////////////////////////////////////////////////////////
01000 // MITM
01001 //
01002 
01003 void GenericSecurityManager::on_passkey_display(
01004     connection_handle_t connection,
01005     passkey_num_t passkey
01006 ) {
01007     set_mitm_performed(connection);
01008     eventHandler->passkeyDisplay(connection, PasskeyAscii(passkey).value());
01009 }
01010 
01011 void GenericSecurityManager::on_keypress_notification(
01012     connection_handle_t connection,
01013     SecurityManager::Keypress_t keypress
01014 ) {
01015     set_mitm_performed(connection);
01016     eventHandler->keypressNotification(connection, keypress);
01017 }
01018 
01019 void GenericSecurityManager::on_passkey_request(connection_handle_t connection) {
01020     set_mitm_performed(connection);
01021     eventHandler->passkeyRequest(connection);
01022 }
01023 
01024 void GenericSecurityManager::on_confirmation_request(connection_handle_t connection) {
01025     set_mitm_performed(connection);
01026     eventHandler->confirmationRequest(connection);
01027 }
01028 
01029 void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) {
01030     set_mitm_performed(connection);
01031     eventHandler->legacyPairingOobRequest(connection);
01032 }
01033 
01034 void GenericSecurityManager::on_oob_data_verification_request(
01035     connection_handle_t connection,
01036     const public_key_coord_t &peer_public_key_x,
01037     const public_key_coord_t &peer_public_key_y
01038 ) {
01039 #if defined(MBEDTLS_CMAC_C)
01040     ControlBlock_t *cb = get_control_block(connection);
01041 
01042     oob_confirm_t confirm_verify;
01043 
01044     crypto_toolbox_f4(
01045         peer_public_key_x,
01046         peer_public_key_y,
01047         _peer_sc_oob_random,
01048         confirm_verify
01049     );
01050 
01051     if (cb && (cb->peer_address == _peer_sc_oob_address)
01052         && (confirm_verify == _peer_sc_oob_confirm)) {
01053         _pal.oob_data_verified(connection, _local_sc_oob_random, _peer_sc_oob_random);
01054     } else {
01055         _pal.cancel_pairing(connection, pairing_failure_t::CONFIRM_VALUE_FAILED);
01056     }
01057 #endif
01058 }
01059 
01060 ////////////////////////////////////////////////////////////////////////////
01061 // Keys
01062 //
01063 
01064 void GenericSecurityManager::on_public_key_generated(
01065     const public_key_coord_t &public_key_x,
01066     const public_key_coord_t &public_key_y
01067 ) {
01068     _db.set_public_key(public_key_x, public_key_y);
01069     _public_keys_generated = true;
01070 }
01071 
01072 void GenericSecurityManager::on_secure_connections_ltk_generated(
01073     connection_handle_t connection,
01074     const ltk_t &ltk
01075 ) {
01076     ControlBlock_t *cb = get_control_block(connection);
01077     if (!cb) {
01078         return;
01079     }
01080 
01081     cb->ltk_mitm_protected = cb->mitm_performed;
01082     cb->secure_connections_paired = true;
01083 
01084     _db.set_entry_peer_ltk(cb->db_entry, ltk);
01085 }
01086 
01087 void GenericSecurityManager::on_keys_distributed_ltk(
01088     connection_handle_t connection,
01089     const ltk_t &ltk
01090 ) {
01091     ControlBlock_t *cb = get_control_block(connection);
01092     if (!cb) {
01093         return;
01094     }
01095     cb->ltk_mitm_protected = cb->mitm_performed;
01096     _db.set_entry_peer_ltk(cb->db_entry, ltk);
01097 }
01098 
01099 void GenericSecurityManager::on_keys_distributed_ediv_rand(
01100     connection_handle_t connection,
01101     const ediv_t &ediv,
01102     const rand_t &rand
01103 ) {
01104     ControlBlock_t *cb = get_control_block(connection);
01105     if (!cb) {
01106         return;
01107     }
01108 
01109     _db.set_entry_peer_ediv_rand(cb->db_entry, ediv, rand);
01110 }
01111 
01112 void GenericSecurityManager::on_keys_distributed_local_ltk(
01113     connection_handle_t connection,
01114     const ltk_t &ltk
01115 ) {
01116     ControlBlock_t *cb = get_control_block(connection);
01117     if (!cb) {
01118         return;
01119     }
01120 
01121     _db.set_entry_local_ltk(cb->db_entry, ltk);
01122 }
01123 
01124 void GenericSecurityManager::on_keys_distributed_local_ediv_rand(
01125     connection_handle_t connection,
01126     const ediv_t &ediv,
01127     const rand_t &rand
01128 ) {
01129     ControlBlock_t *cb = get_control_block(connection);
01130     if (!cb) {
01131         return;
01132     }
01133 
01134     _db.set_entry_local_ediv_rand(cb->db_entry, ediv, rand);
01135 }
01136 
01137 void GenericSecurityManager::on_keys_distributed_irk(
01138     connection_handle_t connection,
01139     const irk_t &irk
01140 ) {
01141     ControlBlock_t *cb = get_control_block(connection);
01142     if (!cb) {
01143         return;
01144     }
01145 
01146     _db.set_entry_peer_irk(cb->db_entry, irk);
01147 }
01148 
01149 void GenericSecurityManager::on_keys_distributed_bdaddr(
01150     connection_handle_t connection,
01151     advertising_peer_address_type_t peer_address_type,
01152     const address_t &peer_identity_address
01153 ) {
01154     ControlBlock_t *cb = get_control_block(connection);
01155     if (!cb) {
01156         return;
01157     }
01158 
01159     _db.set_entry_peer_bdaddr(
01160         cb->db_entry,
01161         (peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS),
01162         peer_identity_address
01163     );
01164 }
01165 
01166 void GenericSecurityManager::on_keys_distributed_csrk(
01167     connection_handle_t connection,
01168     const csrk_t &csrk
01169 ) {
01170     ControlBlock_t *cb = get_control_block(connection);
01171     if (!cb) {
01172         return;
01173     }
01174 
01175     cb->csrk_mitm_protected = cb->mitm_performed;
01176 
01177     _db.set_entry_peer_csrk(cb->db_entry, csrk);
01178 
01179     eventHandler->signingKey(
01180         connection,
01181         &csrk,
01182         cb->csrk_mitm_protected
01183     );
01184 }
01185 
01186 void GenericSecurityManager::on_ltk_request(
01187     connection_handle_t connection,
01188     const ediv_t &ediv,
01189     const rand_t &rand
01190 ) {
01191     ControlBlock_t *cb = get_control_block(connection);
01192     if (!cb) {
01193         return;
01194     }
01195 
01196     _db.get_entry_local_keys(
01197         mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
01198         cb->db_entry,
01199         ediv,
01200         rand
01201     );
01202 }
01203 
01204 /* control blocks list management */
01205 
01206 GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
01207     pal::SecurityDistributionFlags_t(),
01208     connection(0),
01209     db_entry(0),
01210     local_address(),
01211     connected(false),
01212     authenticated(false),
01213     is_master(false),
01214     encryption_requested(false),
01215     encryption_failed(false),
01216     encrypted(false),
01217     signing_requested(false),
01218     signing_override_default(false),
01219     mitm_requested(false),
01220     mitm_performed(false),
01221     attempt_oob(false),
01222     oob_mitm_protection(false),
01223     oob_present(false) { }
01224 
01225 void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
01226 {
01227     ControlBlock_t *cb = get_control_block(connection);
01228     if (!cb) {
01229         return;
01230     }
01231 
01232     _db.get_entry_local_keys(
01233         mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
01234         cb->db_entry
01235     );
01236 }
01237 
01238 GenericSecurityManager::ControlBlock_t*
01239 GenericSecurityManager::acquire_control_block(connection_handle_t connection)
01240 {
01241     /* grab the first disconnected slot*/
01242     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
01243         if (!_control_blocks[i].connected) {
01244             ControlBlock_t* cb = &_control_blocks[i];
01245             cb->connected = true;
01246             cb->connection = connection;
01247             return cb;
01248         }
01249     }
01250 
01251     return NULL;
01252 }
01253 
01254 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
01255     connection_handle_t connection
01256 ) {
01257     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
01258         if (!_control_blocks[i].connected) {
01259             continue;
01260         } else if (connection == _control_blocks[i].connection) {
01261             return &_control_blocks[i];
01262         }
01263     }
01264     return NULL;
01265 }
01266 
01267 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
01268     const address_t &peer_address
01269 ) {
01270     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
01271         if (!_control_blocks[i].connected) {
01272             continue;
01273         } else if (peer_address == _control_blocks[i].peer_address) {
01274             return &_control_blocks[i];
01275         }
01276     }
01277     return NULL;
01278 }
01279 
01280 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
01281     pal::SecurityDb::entry_handle_t db_entry
01282 ) {
01283     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
01284         if (!_control_blocks[i].connected) {
01285             continue;
01286         } else if (db_entry == _control_blocks[i].db_entry) {
01287             return &_control_blocks[i];
01288         }
01289     }
01290     return NULL;
01291 }
01292 
01293 void GenericSecurityManager::release_control_block(ControlBlock_t* cb)
01294 {
01295     *cb = ControlBlock_t();
01296 }
01297 
01298 } /* namespace generic */
01299 } /* namespace ble */