Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

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 #include "ble/generic/MemorySecurityDb.h"
00021 #include "ble/generic/FileSecurityDb.h"
00022 
00023 using ble::pal::advertising_peer_address_type_t;
00024 using ble::pal::AuthenticationMask;
00025 using ble::pal::KeyDistribution;
00026 using ble::pal::connection_peer_address_type_t;
00027 
00028 namespace ble {
00029 namespace generic {
00030 
00031 /* Implements SecurityManager */
00032 
00033 ////////////////////////////////////////////////////////////////////////////
00034 // SM lifecycle management
00035 //
00036 
00037 ble_error_t GenericSecurityManager::init(
00038     bool bondable,
00039     bool mitm,
00040     SecurityIOCapabilities_t iocaps,
00041     const Passkey_t passkey,
00042     bool signing,
00043     const char* db_path
00044 ) {
00045     ble_error_t result = _pal.initialize();
00046 
00047     if (result != BLE_ERROR_NONE) {
00048         return result;
00049     }
00050 
00051     result = init_database(db_path);
00052 
00053     if (result != BLE_ERROR_NONE) {
00054         return result;
00055     }
00056 
00057     _pal.set_io_capability((io_capability_t::type) iocaps);
00058 
00059     if (passkey) {
00060         _pal.set_display_passkey(PasskeyAscii::to_num(passkey));
00061     } else {
00062         _pal.set_display_passkey(0);
00063     }
00064 
00065     _legacy_pairing_allowed = true;
00066 
00067     bool secure_connections;
00068     _pal.get_secure_connections_support(secure_connections);
00069 
00070     _default_authentication.set_bondable(bondable);
00071     _default_authentication.set_mitm(mitm);
00072     _default_authentication.set_secure_connections(secure_connections);
00073     _default_authentication.set_keypress_notification(true);
00074 
00075     // FIXME: depends on BR/EDR support
00076     _default_key_distribution.set_link(false);
00077 
00078     _default_key_distribution.set_signing(signing);
00079     if (signing) {
00080         init_signing();
00081     }
00082 
00083     _connection_monitor.set_connection_event_handler(this);
00084     _signing_monitor.set_signing_event_handler(this);
00085     _pal.set_event_handler(this);
00086 
00087     result = init_resolving_list();
00088 
00089     if (result != BLE_ERROR_NONE) {
00090         delete _db;
00091         return result;
00092     }
00093 
00094     return BLE_ERROR_NONE;
00095 }
00096 
00097 ble_error_t GenericSecurityManager::setDatabaseFilepath(
00098     const char *db_path
00099 ) {
00100     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00101 
00102     /* operation only allowed with no connections active */
00103     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
00104         if (_control_blocks[i].connected) {
00105             return BLE_ERROR_OPERATION_NOT_PERMITTED;
00106         }
00107     }
00108 
00109     ble_error_t result = init_database(db_path);
00110     if (result != BLE_ERROR_NONE) {
00111         return result;
00112     }
00113 
00114     init_resolving_list();
00115 
00116     return BLE_ERROR_NONE;
00117 }
00118 
00119 ble_error_t GenericSecurityManager::reset(void) {
00120     _pal.reset();
00121     SecurityManager::reset();
00122 
00123     return BLE_ERROR_NONE;
00124 }
00125 
00126 ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
00127     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00128     _db->set_restore(enabled);
00129     return BLE_ERROR_NONE;
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////////////
00133 // List management
00134 //
00135 
00136 ble_error_t GenericSecurityManager::purgeAllBondingState(void) {
00137     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00138     _db->clear_entries();
00139     return BLE_ERROR_NONE;
00140 }
00141 
00142 ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const {
00143     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00144     if (eventHandler) {
00145         if (!whitelist) {
00146             return BLE_ERROR_INVALID_PARAM;
00147         }
00148         _db->generate_whitelist_from_bond_table(
00149             mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable),
00150             whitelist
00151         );
00152     }
00153     return BLE_ERROR_NONE;
00154 }
00155 
00156 ////////////////////////////////////////////////////////////////////////////
00157 // Pairing
00158 //
00159 
00160 ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connection) {
00161     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00162     ControlBlock_t *cb = get_control_block(connection);
00163     if (!cb) {
00164         return BLE_ERROR_INVALID_PARAM;
00165     }
00166 
00167     if (!_legacy_pairing_allowed && !_default_authentication.get_secure_connections()) {
00168         return BLE_ERROR_INVALID_STATE;
00169     }
00170 
00171     set_mitm_performed(connection, false);
00172     update_oob_presence(connection);
00173 
00174     AuthenticationMask link_authentication(_default_authentication);
00175 
00176     if (cb->mitm_requested) {
00177         link_authentication.set_mitm(true);
00178     }
00179 
00180     /* by default the initiator doesn't send any keys other then identity */
00181     KeyDistribution initiator_distribution(
00182         KeyDistribution::KEY_DISTRIBUTION_IDENTITY |
00183         _default_key_distribution.get_link()
00184     );
00185 
00186     initiator_distribution.set_signing(
00187         cb->signing_override_default ?
00188             cb->signing_requested :
00189             _default_key_distribution.get_signing()
00190     );
00191 
00192     /* if requested the initiator may send all the default keys for later
00193      * use when roles are changed */
00194     if (_master_sends_keys) {
00195         initiator_distribution = _default_key_distribution;
00196     }
00197 
00198     KeyDistribution responder_distribution(_default_key_distribution);
00199 
00200     if (cb->signing_override_default) {
00201         responder_distribution.set_signing(cb->signing_requested);
00202     }
00203 
00204     return _pal.send_pairing_request(
00205         connection,
00206         cb->oob_present,
00207         link_authentication,
00208         initiator_distribution,
00209         responder_distribution
00210     );
00211 }
00212 
00213 ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t connection) {
00214     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00215     ControlBlock_t *cb = get_control_block(connection);
00216     if (!cb) {
00217         return BLE_ERROR_INVALID_PARAM;
00218     }
00219 
00220     update_oob_presence(connection);
00221 
00222     AuthenticationMask link_authentication(_default_authentication);
00223     if (cb->mitm_requested) {
00224         link_authentication.set_mitm(true);
00225     }
00226 
00227     KeyDistribution initiator_distribution = cb->get_initiator_key_distribution();
00228 
00229     bool master_signing = initiator_distribution.get_signing();
00230 
00231     if (_master_sends_keys) {
00232         initiator_distribution &= _default_key_distribution;
00233     } else {
00234         initiator_distribution &= KeyDistribution(
00235             KeyDistribution::KEY_DISTRIBUTION_IDENTITY |
00236             KeyDistribution::KEY_DISTRIBUTION_LINK
00237         );
00238     }
00239 
00240     /* signing has to be offered and enabled on the link */
00241     if (master_signing) {
00242         initiator_distribution.set_signing(
00243             cb->signing_override_default ?
00244                 cb->signing_requested :
00245                 _default_key_distribution.get_signing()
00246         );
00247     }
00248 
00249     KeyDistribution responder_distribution(cb->get_responder_key_distribution());
00250 
00251     responder_distribution &= _default_key_distribution;
00252 
00253     /* signing has to be requested and enabled on the link */
00254     if (responder_distribution.get_signing()) {
00255         responder_distribution.set_signing(
00256             cb->signing_override_default ?
00257                 cb->signing_requested :
00258                 _default_key_distribution.get_signing()
00259         );
00260     }
00261 
00262     return _pal.send_pairing_response(
00263         connection,
00264         cb->oob_present,
00265         link_authentication,
00266         initiator_distribution,
00267         responder_distribution
00268     );
00269 }
00270 
00271 ble_error_t GenericSecurityManager::cancelPairingRequest(connection_handle_t connection) {
00272     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00273     return _pal.cancel_pairing(connection, pairing_failure_t::UNSPECIFIED_REASON);
00274 }
00275 
00276 ble_error_t GenericSecurityManager::setPairingRequestAuthorisation(bool required) {
00277     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00278     _pairing_authorisation_required = required;
00279     return BLE_ERROR_NONE;
00280 }
00281 
00282 ////////////////////////////////////////////////////////////////////////////
00283 // Feature support
00284 //
00285 
00286 ble_error_t GenericSecurityManager::allowLegacyPairing(bool allow) {
00287     _legacy_pairing_allowed = allow;
00288     return BLE_ERROR_NONE;
00289 }
00290 
00291 ble_error_t GenericSecurityManager::getSecureConnectionsSupport(bool *enabled) {
00292     return _pal.get_secure_connections_support(*enabled);
00293 }
00294 
00295 ////////////////////////////////////////////////////////////////////////////
00296 // Security settings
00297 //
00298 
00299 ble_error_t GenericSecurityManager::setIoCapability(SecurityIOCapabilities_t iocaps) {
00300     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00301     return _pal.set_io_capability((io_capability_t::type) iocaps);
00302 }
00303 
00304 ble_error_t GenericSecurityManager::setDisplayPasskey(const Passkey_t passkey) {
00305     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00306     return _pal.set_display_passkey(PasskeyAscii::to_num(passkey));
00307 }
00308 
00309 ble_error_t GenericSecurityManager::setAuthenticationTimeout(
00310     connection_handle_t connection,
00311     uint32_t timeout_in_ms
00312 ) {
00313     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00314     return _pal.set_authentication_timeout(connection, timeout_in_ms / 10);
00315 }
00316 
00317 ble_error_t GenericSecurityManager::getAuthenticationTimeout(
00318     connection_handle_t connection,
00319     uint32_t *timeout_in_ms
00320 ) {
00321     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00322     uint16_t timeout_in_10ms;
00323     ble_error_t status = _pal.get_authentication_timeout(connection, timeout_in_10ms);
00324     *timeout_in_ms = 10 * timeout_in_10ms;
00325     return status;
00326 }
00327 
00328 ble_error_t GenericSecurityManager::setLinkSecurity(
00329     connection_handle_t connection,
00330     SecurityMode_t securityMode
00331 ) {
00332     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00333     ControlBlock_t *cb = get_control_block(connection);
00334     if (!cb) {
00335         return BLE_ERROR_INVALID_PARAM;
00336     }
00337 
00338     if (cb->encryption_requested) {
00339         return BLE_ERROR_OPERATION_NOT_PERMITTED;
00340     }
00341 
00342     switch (securityMode) {
00343         case SECURITY_MODE_ENCRYPTION_OPEN_LINK:
00344             return setLinkEncryption(connection, link_encryption_t::NOT_ENCRYPTED);
00345 
00346         case SECURITY_MODE_ENCRYPTION_NO_MITM:
00347             return setLinkEncryption(connection, link_encryption_t::ENCRYPTED);
00348 
00349         case SECURITY_MODE_ENCRYPTION_WITH_MITM:
00350             return setLinkEncryption(connection, link_encryption_t::ENCRYPTED_WITH_MITM);
00351 
00352         case SECURITY_MODE_SIGNED_NO_MITM:
00353             return getSigningKey(connection, false);
00354 
00355         case SECURITY_MODE_SIGNED_WITH_MITM:
00356             return getSigningKey(connection, true);
00357 
00358         default:
00359             return BLE_ERROR_INVALID_PARAM;
00360     }
00361 }
00362 
00363 ble_error_t GenericSecurityManager::setKeypressNotification(bool enabled) {
00364     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00365     _default_authentication.set_keypress_notification(enabled);
00366     return BLE_ERROR_NONE;
00367 }
00368 
00369 ble_error_t GenericSecurityManager::enableSigning(
00370     connection_handle_t connection,
00371     bool enabled
00372 ) {
00373     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00374     ControlBlock_t *cb = get_control_block(connection);
00375     if (!cb) {
00376         return BLE_ERROR_INVALID_PARAM;
00377     }
00378 
00379     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00380     if (!flags) {
00381         return BLE_ERROR_INVALID_PARAM;
00382     }
00383 
00384     cb->signing_override_default = true;
00385 
00386     if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) {
00387         cb->signing_requested = true;
00388         if (flags->csrk_stored) {
00389             /* used the stored ones when available */
00390             _db->get_entry_peer_csrk(
00391                 mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
00392                 cb->db_entry
00393             );
00394         } else {
00395             /* create keys if needed and exchange them */
00396             init_signing();
00397             if (cb->is_master) {
00398                return requestPairing(connection);
00399             } else {
00400                return slave_security_request(connection);
00401             }
00402         }
00403     } else {
00404         cb->signing_requested = enabled;
00405     }
00406 
00407     return BLE_ERROR_NONE;
00408 }
00409 
00410 ble_error_t GenericSecurityManager::setHintFutureRoleReversal(bool enable) {
00411     _master_sends_keys = enable;
00412     return BLE_ERROR_NONE;
00413 }
00414 
00415 ////////////////////////////////////////////////////////////////////////////
00416 // Encryption
00417 //
00418 
00419 ble_error_t GenericSecurityManager::getLinkEncryption(
00420     connection_handle_t connection,
00421     link_encryption_t *encryption
00422 ) {
00423     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00424     ControlBlock_t *cb = get_control_block(connection);
00425     if (!cb) {
00426         return BLE_ERROR_INVALID_PARAM;
00427     }
00428 
00429     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00430     if (!flags) {
00431         return BLE_ERROR_INVALID_PARAM;
00432     }
00433 
00434     if (cb->encrypted) {
00435         if (flags->ltk_mitm_protected  || cb->mitm_performed) {
00436             if (flags->secure_connections_paired) {
00437                 *encryption = link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM;
00438             } else {
00439                 *encryption = link_encryption_t::ENCRYPTED_WITH_MITM;
00440             }
00441         } else {
00442             *encryption = link_encryption_t::ENCRYPTED;
00443         }
00444     } else if (cb->encryption_requested) {
00445         *encryption = link_encryption_t::ENCRYPTION_IN_PROGRESS;
00446     } else {
00447         *encryption = link_encryption_t::NOT_ENCRYPTED;
00448     }
00449 
00450     return BLE_ERROR_NONE;
00451 }
00452 
00453 ble_error_t GenericSecurityManager::setLinkEncryption(
00454     connection_handle_t connection,
00455     link_encryption_t encryption
00456 ) {
00457     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00458     ControlBlock_t *cb = get_control_block(connection);
00459     if (!cb) {
00460         return BLE_ERROR_INVALID_PARAM;
00461     }
00462 
00463     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00464     if (!flags) {
00465         return BLE_ERROR_INVALID_PARAM;
00466     }
00467 
00468     link_encryption_t current_encryption(link_encryption_t::NOT_ENCRYPTED);
00469     getLinkEncryption(connection, &current_encryption);
00470 
00471     if (current_encryption == link_encryption_t::ENCRYPTION_IN_PROGRESS) {
00472         return BLE_ERROR_OPERATION_NOT_PERMITTED;
00473     }
00474 
00475     if (current_encryption == encryption) {
00476 
00477         /* ignore if the link is already at required state*/
00478 
00479     } else if (encryption == link_encryption_t::NOT_ENCRYPTED) {
00480         // Fail as it is not permitted to turn down encryption
00481         return BLE_ERROR_OPERATION_NOT_PERMITTED;
00482     } else if (encryption == link_encryption_t::ENCRYPTED) {
00483 
00484         /* only change if we're not already encrypted with mitm */
00485         if (current_encryption != link_encryption_t::ENCRYPTED_WITH_MITM ||
00486             current_encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM
00487         ) {
00488             cb->encryption_requested = true;
00489             return enable_encryption(connection);
00490         }
00491 
00492     } else if (encryption == link_encryption_t::ENCRYPTED_WITH_MITM) {
00493 
00494         if (flags->ltk_mitm_protected && !cb->encrypted) {
00495             cb->encryption_requested = true;
00496             return enable_encryption(connection);
00497         } else {
00498             cb->encryption_requested = true;
00499             return requestAuthentication(connection);
00500         }
00501 
00502     } else if (encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) {
00503 
00504         if (flags->ltk_mitm_protected &&
00505             flags->secure_connections_paired &&
00506             !cb->encrypted
00507         ) {
00508             cb->encryption_requested = true;
00509             return enable_encryption(connection);
00510         } else {
00511             cb->encryption_requested = true;
00512             return requestAuthentication(connection);
00513         }
00514 
00515     } else {
00516         return BLE_ERROR_INVALID_PARAM;
00517     }
00518 
00519     eventHandler->linkEncryptionResult(connection, current_encryption);
00520 
00521     return BLE_ERROR_NONE;
00522 }
00523 
00524 ble_error_t GenericSecurityManager::getEncryptionKeySize(
00525     connection_handle_t connection,
00526     uint8_t *size
00527 ) {
00528     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00529     ControlBlock_t *cb = get_control_block(connection);
00530     if (!cb) {
00531         return BLE_ERROR_INVALID_PARAM;
00532     }
00533 
00534     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00535     if (!flags) {
00536         return BLE_ERROR_INVALID_PARAM;
00537     }
00538 
00539     *size = flags->encryption_key_size;
00540     return BLE_ERROR_NONE;
00541 }
00542 
00543 ble_error_t GenericSecurityManager::setEncryptionKeyRequirements(
00544     uint8_t minimumByteSize,
00545     uint8_t maximumByteSize
00546 ) {
00547     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00548     return _pal.set_encryption_key_requirements(minimumByteSize, maximumByteSize);
00549 }
00550 
00551 ////////////////////////////////////////////////////////////////////////////
00552 // Keys
00553 //
00554 
00555 ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) {
00556     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00557     ControlBlock_t *cb = get_control_block(connection);
00558     if (!cb) {
00559         return BLE_ERROR_INVALID_PARAM;
00560     }
00561 
00562     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00563     if (!flags) {
00564         return BLE_ERROR_INVALID_PARAM;
00565     }
00566 
00567     if (flags->csrk_stored && (flags->csrk_mitm_protected || !authenticated)) {
00568         /* we have a key that is either authenticated or we don't care if it is
00569          * so retrieve it from the db now */
00570         _db->get_entry_peer_csrk(
00571             mbed::callback(this, &GenericSecurityManager::return_csrk_cb),
00572             cb->db_entry
00573         );
00574         return BLE_ERROR_NONE;
00575 
00576     } else {
00577         /* we don't have the right key so we need to get it first
00578          * keys exchange will create the signingKey event */
00579         if (authenticated) {
00580             return requestAuthentication(connection);
00581         } else if (cb->is_master) {
00582             return requestPairing(connection);
00583         } else {
00584             return slave_security_request(connection);
00585         }
00586     }
00587 }
00588 
00589 ////////////////////////////////////////////////////////////////////////////
00590 // Privacy
00591 //
00592 
00593 ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds) {
00594     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00595    return _pal.set_private_address_timeout(timeout_in_seconds);
00596 }
00597 
00598 ////////////////////////////////////////////////////////////////////////////
00599 // Authentication
00600 //
00601 
00602 ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t connection) {
00603     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00604     ControlBlock_t *cb = get_control_block(connection);
00605     if (!cb) {
00606         return BLE_ERROR_INVALID_PARAM;
00607     }
00608 
00609     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00610     if (!flags) {
00611         return BLE_ERROR_INVALID_PARAM;
00612     }
00613 
00614     if (flags->ltk_mitm_protected) {
00615         if (cb->authenticated) {
00616             return BLE_ERROR_NONE;
00617         } else {
00618             cb->encryption_requested = true;
00619             return enable_encryption(connection);
00620         }
00621     } else {
00622         cb->mitm_requested = true;
00623         if (cb->is_master) {
00624             return requestPairing(connection);
00625         } else {
00626             return slave_security_request(connection);
00627         }
00628     }
00629 }
00630 
00631 ////////////////////////////////////////////////////////////////////////////
00632 // MITM
00633 //
00634 
00635 ble_error_t GenericSecurityManager::generateOOB(
00636     const address_t *address
00637 ) {
00638     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00639     /* legacy pairing */
00640     ble_error_t status = get_random_data(_oob_temporary_key.data(), 16);
00641 
00642     if (status == BLE_ERROR_NONE) {
00643         _oob_temporary_key_creator_address = *address;
00644 
00645         eventHandler->legacyPairingOobGenerated(
00646             &_oob_temporary_key_creator_address,
00647             &_oob_temporary_key
00648         );
00649     } else {
00650         return status;
00651     }
00652 
00653     /* Secure connections. Avoid generating if we're already waiting for it.
00654      * If a local random is set to 0 it means we're already calculating. */
00655     if (!is_all_zeros(_oob_local_random)) {
00656         status = _pal.generate_secure_connections_oob();
00657 
00658         if (status == BLE_ERROR_NONE) {
00659             _oob_local_address = *address;
00660             /* this will be updated when calculation completes,
00661              * a value of all zeros is an invalid random value */
00662             set_all_zeros(_oob_local_random);
00663         } else if (status != BLE_ERROR_NOT_IMPLEMENTED) {
00664             return status;
00665         }
00666     } else {
00667         return BLE_STACK_BUSY;
00668     }
00669 
00670     return BLE_ERROR_NONE;
00671 }
00672 
00673 ble_error_t GenericSecurityManager::setOOBDataUsage(
00674     connection_handle_t connection,
00675     bool useOOB,
00676     bool OOBProvidesMITM
00677 ) {
00678     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00679     ControlBlock_t *cb = get_control_block(connection);
00680     if (!cb) {
00681         return BLE_ERROR_INVALID_PARAM;
00682     }
00683 
00684     cb->attempt_oob = useOOB;
00685     cb->oob_mitm_protection = OOBProvidesMITM;
00686 
00687     if (useOOB) {
00688         return generateOOB(&cb->local_address);
00689     } else {
00690         return BLE_ERROR_NONE;
00691     }
00692 }
00693 
00694 ble_error_t GenericSecurityManager::confirmationEntered(
00695     connection_handle_t connection,
00696     bool confirmation
00697 ) {
00698     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00699     return _pal.confirmation_entered(connection, confirmation);
00700 }
00701 
00702 ble_error_t GenericSecurityManager::passkeyEntered(
00703     connection_handle_t connection,
00704     Passkey_t passkey
00705 ) {
00706     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00707     return _pal.passkey_request_reply(
00708         connection,
00709         PasskeyAscii::to_num(passkey)
00710     );
00711 }
00712 
00713 ble_error_t GenericSecurityManager::sendKeypressNotification(
00714     connection_handle_t connection,
00715     Keypress_t keypress
00716 ) {
00717     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00718     return _pal.send_keypress_notification(connection, keypress);
00719 }
00720 
00721 ble_error_t GenericSecurityManager::legacyPairingOobReceived(
00722     const address_t *address,
00723     const oob_tk_t *tk
00724 ) {
00725     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00726     if (address && tk) {
00727         ControlBlock_t *cb = get_control_block(*address);
00728         if (!cb) {
00729             return BLE_ERROR_INVALID_PARAM;
00730         }
00731 
00732         SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00733         if (!flags) {
00734             return BLE_ERROR_INVALID_PARAM;
00735         }
00736 
00737         _oob_temporary_key = *tk;
00738         _oob_temporary_key_creator_address = *address;
00739 
00740         if (flags->peer_address == _oob_temporary_key_creator_address) {
00741             cb->attempt_oob = true;
00742         }
00743 
00744         if (cb->legacy_pairing_oob_request_pending) {
00745             on_legacy_pairing_oob_request(cb->connection);
00746             /* legacy_pairing_oob_request_pending stops us from
00747              * going into a loop of asking the user for oob
00748              * so this reset needs to happen after the call above */
00749             cb->legacy_pairing_oob_request_pending = false;
00750         }
00751     }
00752     return BLE_ERROR_NONE;
00753 }
00754 
00755 ble_error_t GenericSecurityManager::oobReceived(
00756     const address_t *address,
00757     const oob_lesc_value_t *random,
00758     const oob_confirm_t *confirm
00759 ) {
00760     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00761     if (address && random && confirm) {
00762         _oob_peer_address = *address;
00763         _oob_peer_random = *random;
00764         _oob_peer_confirm = *confirm;
00765         return BLE_ERROR_NONE;
00766     }
00767 
00768     return BLE_ERROR_INVALID_PARAM;
00769 }
00770 
00771 ////////////////////////////////////////////////////////////////////////////
00772 // Helper functions
00773 //
00774 
00775 ble_error_t GenericSecurityManager::init_database(
00776     const char *db_path
00777 ) {
00778     delete _db;
00779 
00780     FILE* db_file = FileSecurityDb::open_db_file(db_path);
00781 
00782     if (db_file) {
00783         _db = new (std::nothrow) FileSecurityDb(db_file);
00784     } else {
00785         _db = new (std::nothrow) MemorySecurityDb();
00786     }
00787 
00788     if (!_db) {
00789         return BLE_ERROR_NO_MEM;
00790     }
00791 
00792     _db->restore();
00793 
00794     return BLE_ERROR_NONE;
00795 }
00796 
00797 ble_error_t GenericSecurityManager::init_resolving_list() {
00798     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00799 
00800     /* match the resolving list to the currently stored set of IRKs */
00801     uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity();
00802     SecurityEntryIdentity_t* identity_list_p =
00803         new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity];
00804 
00805     if (identity_list_p) {
00806         ArrayView<SecurityEntryIdentity_t> identity_list(
00807             identity_list_p,
00808             resolving_list_capacity
00809         );
00810 
00811         _db->get_identity_list(
00812             mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved),
00813             identity_list
00814         );
00815     } else {
00816         return BLE_ERROR_NO_MEM;
00817     }
00818 
00819     return BLE_ERROR_NONE;
00820 }
00821 
00822 ble_error_t GenericSecurityManager::init_signing() {
00823     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00824     const csrk_t *pcsrk = _db->get_local_csrk();
00825     sign_count_t local_sign_counter = _db->get_local_sign_counter();
00826 
00827     if (!pcsrk) {
00828         csrk_t csrk;
00829 
00830         ble_error_t ret = get_random_data(csrk.data(), csrk.size());
00831         if (ret != BLE_ERROR_NONE) {
00832             return ret;
00833         }
00834 
00835         pcsrk = &csrk;
00836         _db->set_local_csrk(csrk);
00837         _db->set_local_sign_counter(local_sign_counter);
00838     }
00839 
00840     return _pal.set_csrk(*pcsrk, local_sign_counter);
00841 }
00842 
00843 ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size) {
00844     byte_array_t<8> random_data;
00845 
00846     while (size) {
00847         /* fill out the buffer by reading the random data in chunks
00848          * and copying it until reaching the set size */
00849         size_t copy_size = std::max(size, random_data.size());
00850         ble_error_t ret = _pal.get_random_data(random_data);
00851         if (ret != BLE_ERROR_NONE) {
00852             return ret;
00853         }
00854         memcpy(buffer, random_data.data(), copy_size);
00855         size -= copy_size;
00856         buffer += copy_size;
00857     }
00858 
00859     return BLE_ERROR_NONE;
00860 }
00861 
00862 ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t connection) {
00863     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00864     ControlBlock_t *cb = get_control_block(connection);
00865     if (!cb) {
00866         return BLE_ERROR_INVALID_PARAM;
00867     }
00868     AuthenticationMask link_authentication(_default_authentication);
00869     link_authentication.set_mitm(cb->mitm_requested);
00870     return _pal.slave_security_request(connection, link_authentication);
00871 }
00872 
00873 ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) {
00874     if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00875     ControlBlock_t *cb = get_control_block(connection);
00876     if (!cb) {
00877         return BLE_ERROR_INVALID_PARAM;
00878     }
00879 
00880     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00881     if (!flags) {
00882         return BLE_ERROR_INVALID_PARAM;
00883     }
00884 
00885     if (cb->is_master) {
00886         if (flags->ltk_stored) {
00887             _db->get_entry_peer_keys(
00888                 mbed::callback(this, &GenericSecurityManager::enable_encryption_cb),
00889                 cb->db_entry
00890             );
00891             return BLE_ERROR_NONE;
00892         } else {
00893             return requestPairing(connection);
00894         }
00895     } else {
00896         return slave_security_request(connection);
00897     }
00898 }
00899 
00900 void GenericSecurityManager::enable_encryption_cb(
00901     SecurityDb::entry_handle_t db_entry,
00902     const SecurityEntryKeys_t* entryKeys
00903 ) {
00904     MBED_ASSERT(_db);
00905     ControlBlock_t *cb = get_control_block(db_entry);
00906     if (!cb) {
00907         return;
00908     }
00909 
00910     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00911     if (!flags) {
00912         return;
00913     }
00914 
00915     if (entryKeys) {
00916         if (flags->secure_connections_paired) {
00917             _pal.enable_encryption(cb->connection, entryKeys->ltk, flags->ltk_mitm_protected);
00918         } else {
00919             _pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, flags->ltk_mitm_protected);
00920         }
00921     }
00922 }
00923 
00924 void GenericSecurityManager::set_ltk_cb(
00925     SecurityDb::entry_handle_t db_entry,
00926     const SecurityEntryKeys_t* entryKeys
00927 ) {
00928     MBED_ASSERT(_db);
00929     ControlBlock_t *cb = get_control_block(db_entry);
00930     if (!cb) {
00931         return;
00932     }
00933 
00934     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00935     if (!flags) {
00936         return;
00937     }
00938 
00939     if (entryKeys) {
00940         _pal.set_ltk(
00941             cb->connection,
00942             entryKeys->ltk,
00943             flags->ltk_mitm_protected,
00944             flags->secure_connections_paired
00945         );
00946     } else {
00947         _pal.set_ltk_not_found(cb->connection);
00948     }
00949 }
00950 
00951 void GenericSecurityManager::set_peer_csrk_cb(
00952     SecurityDb::entry_handle_t db_entry,
00953     const SecurityEntrySigning_t* signing
00954 ) {
00955     ControlBlock_t *cb = get_control_block(db_entry);
00956     if (!cb || !signing) {
00957         return;
00958     }
00959 
00960     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00961     if (!flags) {
00962         return;
00963     }
00964 
00965     _pal.set_peer_csrk(
00966         cb->connection,
00967         signing->csrk,
00968         flags->csrk_mitm_protected,
00969         signing->counter
00970     );
00971 }
00972 
00973 void GenericSecurityManager::return_csrk_cb(
00974     SecurityDb::entry_handle_t db_entry,
00975     const SecurityEntrySigning_t *signing
00976 ) {
00977     MBED_ASSERT(_db);
00978     ControlBlock_t *cb = get_control_block(db_entry);
00979     if (!cb || !signing) {
00980         return;
00981     }
00982 
00983     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
00984     if (!flags) {
00985         return;
00986     }
00987 
00988     eventHandler->signingKey(
00989         cb->connection,
00990         &signing->csrk,
00991         flags->csrk_mitm_protected
00992     );
00993 }
00994 
00995 void GenericSecurityManager::update_oob_presence(connection_handle_t connection) {
00996     MBED_ASSERT(_db);
00997     ControlBlock_t *cb = get_control_block(connection);
00998     if (!cb) {
00999         return;
01000     }
01001 
01002     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01003     if (!flags) {
01004         return;
01005     }
01006 
01007     /* if we support secure connection we only care about secure connections oob data */
01008     if (_default_authentication.get_secure_connections()) {
01009         cb->oob_present = (flags->peer_address == _oob_peer_address);
01010     } else {
01011         /* otherwise for legacy pairing we first set the oob based on set preference */
01012         cb->oob_present = cb->attempt_oob;
01013 
01014         /* and also turn it on if we have oob data for legacy pairing */
01015         if (flags->peer_address == _oob_temporary_key_creator_address
01016             || cb->local_address == _oob_temporary_key_creator_address) {
01017             cb->oob_present = true;
01018         }
01019     }
01020 }
01021 
01022 void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, bool enable) {
01023     ControlBlock_t *cb = get_control_block(connection);
01024     if (cb) {
01025         cb->mitm_performed = enable;
01026         /* whenever we reset mitm performed we also reset pending requests
01027          * as this happens whenever a new pairing attempt happens */
01028         if (!enable) {
01029             cb->legacy_pairing_oob_request_pending = false;
01030         }
01031     }
01032 }
01033 
01034 void GenericSecurityManager::on_connected(
01035     connection_handle_t connection,
01036     Gap::Role_t role,
01037     peer_address_type_t peer_address_type,
01038     const BLEProtocol::AddressBytes_t peer_address,
01039     BLEProtocol::AddressType_t local_address_type,
01040     const BLEProtocol::AddressBytes_t local_address,
01041     const Gap::ConnectionParams_t *connection_params
01042 ) {
01043     MBED_ASSERT(_db);
01044     ControlBlock_t *cb = acquire_control_block(connection);
01045     if (!cb) {
01046         return;
01047     }
01048 
01049     // setup the control block
01050     cb->local_address = local_address;
01051     cb->is_master = (role == Gap::CENTRAL);
01052 
01053     // get the associated db handle and the distribution flags if any
01054     cb->db_entry = _db->open_entry(peer_address_type, peer_address);
01055 
01056     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01057 
01058     flags->peer_address = peer_address;
01059     flags->peer_address_is_public =
01060         (peer_address_type == peer_address_type_t::PUBLIC) ||
01061         (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY);
01062 
01063     const bool signing = cb->signing_override_default ?
01064                          cb->signing_requested :
01065                          _default_key_distribution.get_signing();
01066 
01067     if (signing && flags->csrk_stored) {
01068         _db->get_entry_peer_csrk(
01069             mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
01070             cb->db_entry
01071         );
01072     }
01073 }
01074 
01075 void GenericSecurityManager::on_disconnected(
01076     connection_handle_t connection,
01077     Gap::DisconnectionReason_t reason
01078 ) {
01079     MBED_ASSERT(_db);
01080     ControlBlock_t *cb = get_control_block(connection);
01081     if (!cb) {
01082         return;
01083     }
01084 
01085     _pal.remove_peer_csrk(connection);
01086 
01087     _db->close_entry(cb->db_entry);
01088     release_control_block(cb);
01089 }
01090 
01091 void GenericSecurityManager::on_security_entry_retrieved(
01092     SecurityDb::entry_handle_t entry,
01093     const SecurityEntryIdentity_t* identity
01094 ) {
01095     if (!identity) {
01096         return;
01097     }
01098 
01099     typedef advertising_peer_address_type_t address_type_t;
01100 
01101     _pal.add_device_to_resolving_list(
01102         identity->identity_address_is_public ?
01103             address_type_t::PUBLIC_ADDRESS :
01104             address_type_t::RANDOM_ADDRESS,
01105         identity->identity_address,
01106         identity->irk
01107     );
01108 }
01109 
01110 void GenericSecurityManager::on_identity_list_retrieved(
01111     ble::ArrayView<SecurityEntryIdentity_t>& identity_list,
01112     size_t count
01113 ) {
01114     typedef advertising_peer_address_type_t address_type_t;
01115 
01116     _pal.clear_resolving_list();
01117     for (size_t i = 0; i < count; ++i) {
01118         _pal.add_device_to_resolving_list(
01119             identity_list[i].identity_address_is_public ?
01120                 address_type_t::PUBLIC_ADDRESS :
01121                 address_type_t::RANDOM_ADDRESS,
01122             identity_list[i].identity_address,
01123             identity_list[i].irk
01124         );
01125     }
01126 
01127     delete [] identity_list.data();
01128 }
01129 
01130 
01131 /* Implements ble::pal::SecurityManagerEventHandler */
01132 
01133 ////////////////////////////////////////////////////////////////////////////
01134 // Pairing
01135 //
01136 
01137 void GenericSecurityManager::on_pairing_request(
01138     connection_handle_t connection,
01139     bool use_oob,
01140     AuthenticationMask authentication,
01141     KeyDistribution initiator_dist,
01142     KeyDistribution responder_dist
01143 ) {
01144     /* cancel pairing if secure connection paring is not possible */
01145     if (!_legacy_pairing_allowed && !authentication.get_secure_connections()) {
01146         cancelPairingRequest(connection);
01147         return;
01148     }
01149 
01150     ControlBlock_t *cb = get_control_block(connection);
01151     if (!cb) {
01152         return;
01153     }
01154 
01155     cb->set_initiator_key_distribution(initiator_dist);
01156     cb->set_responder_key_distribution(responder_dist);
01157 
01158     cb->mitm_performed = false;
01159 
01160     if (_pairing_authorisation_required) {
01161         eventHandler->pairingRequest(connection);
01162     } else {
01163         acceptPairingRequest(connection);
01164     }
01165 }
01166 
01167 void GenericSecurityManager::on_pairing_error(
01168     connection_handle_t connection,
01169     pairing_failure_t error
01170 ) {
01171     set_mitm_performed(connection, false);
01172 
01173     eventHandler->pairingResult(
01174         connection,
01175         (SecurityManager::SecurityCompletionStatus_t)(error.value() | 0x80)
01176     );
01177 
01178     /* if this pairing was triggered by a failed encryption attempt
01179      * inform the application of the encryption failure */
01180     ControlBlock_t *cb = get_control_block(connection);
01181     if (cb && cb->encryption_requested && cb->encryption_failed) {
01182         eventHandler->linkEncryptionResult(
01183             connection,
01184             link_encryption_t::NOT_ENCRYPTED
01185         );
01186     }
01187 }
01188 
01189 void GenericSecurityManager::on_pairing_timed_out(connection_handle_t connection) {
01190     set_mitm_performed(connection, false);
01191 
01192     eventHandler->pairingResult(
01193         connection,
01194         SecurityManager::SEC_STATUS_TIMEOUT
01195     );
01196 }
01197 
01198 void GenericSecurityManager::on_pairing_completed(connection_handle_t connection) {
01199     MBED_ASSERT(_db);
01200     ControlBlock_t *cb = get_control_block(connection);
01201     if (cb) {
01202         _db->get_entry_identity(
01203             mbed::callback(this, &GenericSecurityManager::on_security_entry_retrieved),
01204             cb->db_entry
01205         );
01206     }
01207 
01208     eventHandler->pairingResult(
01209         connection,
01210         SecurityManager::SEC_STATUS_SUCCESS
01211     );
01212 }
01213 
01214 ////////////////////////////////////////////////////////////////////////////
01215 // Security
01216 //
01217 
01218 void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection) {
01219     (void)connection;
01220 }
01221 
01222 void GenericSecurityManager::on_signed_write_received(
01223     connection_handle_t connection,
01224     sign_count_t sign_counter
01225 ) {
01226     MBED_ASSERT(_db);
01227     ControlBlock_t *cb = get_control_block(connection);
01228     if (!cb) {
01229         return;
01230     }
01231     _db->set_entry_peer_sign_counter(cb->db_entry, sign_counter);
01232 }
01233 
01234 void GenericSecurityManager::on_signed_write_verification_failure(
01235     connection_handle_t connection
01236 ) {
01237     ControlBlock_t *cb = get_control_block(connection);
01238     if (!cb) {
01239         return;
01240     }
01241 
01242     const bool signing = cb->signing_override_default ?
01243                          cb->signing_requested :
01244                          _default_key_distribution.get_signing();
01245 
01246     if (signing) {
01247         cb->csrk_failures++;
01248         if (cb->csrk_failures == 3) {
01249             cb->csrk_failures = 0;
01250             if (cb->is_master) {
01251                 requestPairing(connection);
01252             } else {
01253                 slave_security_request(connection);
01254             }
01255         }
01256     }
01257 }
01258 
01259 void GenericSecurityManager::on_signed_write() {
01260     MBED_ASSERT(_db);
01261     _db->set_local_sign_counter(_db->get_local_sign_counter() + 1);
01262 }
01263 
01264 void GenericSecurityManager::on_slave_security_request(
01265     connection_handle_t connection,
01266     AuthenticationMask authentication
01267 ) {
01268     MBED_ASSERT(_db);
01269     ControlBlock_t *cb = get_control_block(connection);
01270     if (!cb) {
01271         return;
01272     }
01273 
01274     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01275     if (!flags) {
01276         return;
01277     }
01278 
01279     bool pairing_required = false;
01280 
01281     if (authentication.get_secure_connections() && !flags->secure_connections_paired
01282         && _default_authentication.get_secure_connections()) {
01283         pairing_required = true;
01284     }
01285 
01286     if (authentication.get_mitm() && !flags->ltk_mitm_protected) {
01287         pairing_required = true;
01288         cb->mitm_requested = true;
01289     }
01290 
01291     if (pairing_required) {
01292         requestPairing(connection);
01293     } else if (!cb->encryption_requested) {
01294         /* this will refresh keys if encryption is already present */
01295         enable_encryption(connection);
01296     }
01297 }
01298 
01299 ////////////////////////////////////////////////////////////////////////////
01300 // Encryption
01301 //
01302 
01303 void GenericSecurityManager::on_link_encryption_result(
01304     connection_handle_t connection,
01305     link_encryption_t result
01306 ) {
01307 
01308     ControlBlock_t *cb = get_control_block(connection);
01309     if (!cb) {
01310         return;
01311     }
01312 
01313     if (result == link_encryption_t::ENCRYPTED) {
01314 
01315         cb->encryption_requested = false;
01316         cb->encryption_failed = false;
01317         cb->encrypted = true;
01318 
01319     } else if (
01320         result == link_encryption_t::ENCRYPTED_WITH_MITM ||
01321         result == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM
01322     ) {
01323 
01324         cb->encryption_requested = false;
01325         cb->encryption_failed = false;
01326         cb->authenticated = true;
01327         cb->encrypted = true;
01328 
01329     } else if (result == link_encryption_t::NOT_ENCRYPTED
01330                && cb->encryption_requested
01331                && !cb->encryption_failed) {
01332 
01333         /* if we failed encryption for the first time
01334          * retry repairing in case slave lost LTK */
01335         requestPairing(cb->connection);
01336         cb->encryption_failed = true;
01337         /* don't return an event yet since we are retrying */
01338         return;
01339     }
01340 
01341     eventHandler->linkEncryptionResult(connection, result);
01342 }
01343 
01344 void GenericSecurityManager::on_link_encryption_request_timed_out(
01345     connection_handle_t connection
01346 ) {
01347     eventHandler->linkEncryptionResult(
01348         connection,
01349         link_encryption_t::NOT_ENCRYPTED
01350     );
01351 }
01352 
01353 ////////////////////////////////////////////////////////////////////////////
01354 // MITM
01355 //
01356 
01357 void GenericSecurityManager::on_passkey_display(
01358     connection_handle_t connection,
01359     passkey_num_t passkey
01360 ) {
01361     set_mitm_performed(connection);
01362     eventHandler->passkeyDisplay(connection, PasskeyAscii(passkey).value());
01363 }
01364 
01365 void GenericSecurityManager::on_keypress_notification(
01366     connection_handle_t connection,
01367     SecurityManager::Keypress_t keypress
01368 ) {
01369     set_mitm_performed(connection);
01370     eventHandler->keypressNotification(connection, keypress);
01371 }
01372 
01373 void GenericSecurityManager::on_passkey_request(connection_handle_t connection) {
01374     set_mitm_performed(connection);
01375     eventHandler->passkeyRequest(connection);
01376 }
01377 
01378 void GenericSecurityManager::on_confirmation_request(connection_handle_t connection) {
01379     set_mitm_performed(connection);
01380     eventHandler->confirmationRequest(connection);
01381 }
01382 
01383 void GenericSecurityManager::on_secure_connections_oob_request(connection_handle_t connection) {
01384     set_mitm_performed(connection);
01385 
01386     ControlBlock_t *cb = get_control_block(connection);
01387     if (!cb) {
01388         return;
01389     }
01390 
01391     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01392     if (!flags) {
01393         return;
01394     }
01395 
01396     if (flags->peer_address == _oob_peer_address) {
01397         _pal.secure_connections_oob_request_reply(connection, _oob_local_random, _oob_peer_random, _oob_peer_confirm);
01398         /* do not re-use peer OOB */
01399         set_all_zeros(_oob_peer_address);
01400     } else {
01401         _pal.cancel_pairing(connection, pairing_failure_t::OOB_NOT_AVAILABLE);
01402     }
01403 }
01404 
01405 void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) {
01406     MBED_ASSERT(_db);
01407     ControlBlock_t *cb = get_control_block(connection);
01408     if (!cb) {
01409         return;
01410     }
01411 
01412     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01413     if (!flags) {
01414         return;
01415     }
01416 
01417     if (flags->peer_address == _oob_temporary_key_creator_address
01418         || cb->local_address == _oob_temporary_key_creator_address) {
01419 
01420         set_mitm_performed(connection);
01421         _pal.legacy_pairing_oob_request_reply(connection, _oob_temporary_key);
01422 
01423         /* do not re-use peer OOB */
01424         if (flags->peer_address == _oob_temporary_key_creator_address) {
01425             set_all_zeros(_oob_temporary_key_creator_address);
01426         }
01427 
01428     } else if (!cb->legacy_pairing_oob_request_pending) {
01429 
01430         cb->legacy_pairing_oob_request_pending = true;
01431         eventHandler->legacyPairingOobRequest(connection);
01432 
01433     }
01434 }
01435 
01436 void GenericSecurityManager::on_secure_connections_oob_generated(
01437     const oob_lesc_value_t &random,
01438     const oob_confirm_t &confirm
01439 ) {
01440     eventHandler->oobGenerated(&_oob_local_address, &random, &confirm);
01441     _oob_local_random = random;
01442 }
01443 
01444 ////////////////////////////////////////////////////////////////////////////
01445 // Keys
01446 //
01447 
01448 void GenericSecurityManager::on_secure_connections_ltk_generated(
01449     connection_handle_t connection,
01450     const ltk_t &ltk
01451 ) {
01452     MBED_ASSERT(_db);
01453     ControlBlock_t *cb = get_control_block(connection);
01454     if (!cb) {
01455         return;
01456     }
01457 
01458     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01459     if (!flags) {
01460         return;
01461     }
01462 
01463     flags->ltk_mitm_protected = cb->mitm_performed;
01464     flags->secure_connections_paired = true;
01465 
01466     _db->set_entry_peer_ltk(cb->db_entry, ltk);
01467     _db->set_entry_local_ltk(cb->db_entry, ltk);
01468 }
01469 
01470 void GenericSecurityManager::on_keys_distributed_ltk(
01471     connection_handle_t connection,
01472     const ltk_t &ltk
01473 ) {
01474     MBED_ASSERT(_db);
01475     ControlBlock_t *cb = get_control_block(connection);
01476     if (!cb) {
01477         return;
01478     }
01479 
01480     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01481     if (!flags) {
01482         return;
01483     }
01484 
01485     flags->ltk_mitm_protected = cb->mitm_performed;
01486 
01487     _db->set_entry_peer_ltk(cb->db_entry, ltk);
01488 }
01489 
01490 void GenericSecurityManager::on_keys_distributed_ediv_rand(
01491     connection_handle_t connection,
01492     const ediv_t &ediv,
01493     const rand_t &rand
01494 ) {
01495     MBED_ASSERT(_db);
01496     ControlBlock_t *cb = get_control_block(connection);
01497     if (!cb) {
01498         return;
01499     }
01500 
01501     _db->set_entry_peer_ediv_rand(cb->db_entry, ediv, rand);
01502 }
01503 
01504 void GenericSecurityManager::on_keys_distributed_local_ltk(
01505     connection_handle_t connection,
01506     const ltk_t &ltk
01507 ) {
01508     MBED_ASSERT(_db);
01509     ControlBlock_t *cb = get_control_block(connection);
01510     if (!cb) {
01511         return;
01512     }
01513 
01514     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01515     if (!flags) {
01516         return;
01517     }
01518 
01519     _db->set_entry_local_ltk(cb->db_entry, ltk);
01520 }
01521 
01522 void GenericSecurityManager::on_keys_distributed_local_ediv_rand(
01523     connection_handle_t connection,
01524     const ediv_t &ediv,
01525     const rand_t &rand
01526 ) {
01527     MBED_ASSERT(_db);
01528     ControlBlock_t *cb = get_control_block(connection);
01529     if (!cb) {
01530         return;
01531     }
01532 
01533     _db->set_entry_local_ediv_rand(cb->db_entry, ediv, rand);
01534 }
01535 
01536 void GenericSecurityManager::on_keys_distributed_irk(
01537     connection_handle_t connection,
01538     const irk_t &irk
01539 ) {
01540     MBED_ASSERT(_db);
01541     ControlBlock_t *cb = get_control_block(connection);
01542     if (!cb) {
01543         return;
01544     }
01545 
01546     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01547     if (!flags) {
01548         return;
01549     }
01550 
01551     _db->set_entry_peer_irk(cb->db_entry, irk);
01552 }
01553 
01554 void GenericSecurityManager::on_keys_distributed_bdaddr(
01555     connection_handle_t connection,
01556     advertising_peer_address_type_t peer_address_type,
01557     const address_t &peer_identity_address
01558 ) {
01559     MBED_ASSERT(_db);
01560     ControlBlock_t *cb = get_control_block(connection);
01561     if (!cb) {
01562         return;
01563     }
01564 
01565     _db->set_entry_peer_bdaddr(
01566         cb->db_entry,
01567         (peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS),
01568         peer_identity_address
01569     );
01570 }
01571 
01572 void GenericSecurityManager::on_keys_distributed_csrk(
01573     connection_handle_t connection,
01574     const csrk_t &csrk
01575 ) {
01576     MBED_ASSERT(_db);
01577     ControlBlock_t *cb = get_control_block(connection);
01578     if (!cb) {
01579         return;
01580     }
01581 
01582     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01583     if (!flags) {
01584         return;
01585     }
01586 
01587     flags->csrk_mitm_protected = cb->mitm_performed;
01588     _db->set_entry_peer_csrk(cb->db_entry, csrk);
01589 
01590     eventHandler->signingKey(
01591         connection,
01592         &csrk,
01593         flags->csrk_mitm_protected
01594     );
01595 }
01596 
01597 void GenericSecurityManager::on_ltk_request(
01598     connection_handle_t connection,
01599     const ediv_t &ediv,
01600     const rand_t &rand
01601 ) {
01602     MBED_ASSERT(_db);
01603     ControlBlock_t *cb = get_control_block(connection);
01604     if (!cb) {
01605         return;
01606     }
01607 
01608     SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01609     if (!flags) {
01610         return;
01611     }
01612 
01613     _db->get_entry_local_keys(
01614         mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
01615         cb->db_entry,
01616         ediv,
01617         rand
01618     );
01619 }
01620 
01621 /* control blocks list management */
01622 
01623 GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
01624     connection(0),
01625     db_entry(0),
01626     local_address(),
01627     connected(false),
01628     authenticated(false),
01629     is_master(false),
01630     encryption_requested(false),
01631     encryption_failed(false),
01632     encrypted(false),
01633     signing_requested(false),
01634     signing_override_default(false),
01635     mitm_requested(false),
01636     mitm_performed(false),
01637     attempt_oob(false),
01638     oob_mitm_protection(false),
01639     oob_present(false),
01640     legacy_pairing_oob_request_pending(false),
01641     csrk_failures(0) { }
01642 
01643 void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
01644 {
01645     MBED_ASSERT(_db);
01646     ControlBlock_t *cb = get_control_block(connection);
01647     if (!cb) {
01648         return;
01649     }
01650 
01651     _db->get_entry_local_keys(
01652         mbed::callback(this, &GenericSecurityManager::set_ltk_cb),
01653         cb->db_entry
01654     );
01655 }
01656 
01657 GenericSecurityManager::ControlBlock_t*
01658 GenericSecurityManager::acquire_control_block(connection_handle_t connection)
01659 {
01660     /* grab the first disconnected slot*/
01661     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
01662         if (!_control_blocks[i].connected) {
01663             ControlBlock_t* cb = &_control_blocks[i];
01664             cb->connected = true;
01665             cb->connection = connection;
01666             return cb;
01667         }
01668     }
01669 
01670     return NULL;
01671 }
01672 
01673 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
01674     connection_handle_t connection
01675 ) {
01676     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
01677         if (!_control_blocks[i].connected) {
01678             continue;
01679         } else if (connection == _control_blocks[i].connection) {
01680             return &_control_blocks[i];
01681         }
01682     }
01683     return NULL;
01684 }
01685 
01686 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
01687     const address_t &peer_address
01688 ) {
01689     MBED_ASSERT(_db);
01690     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
01691         ControlBlock_t *cb = &_control_blocks[i];
01692         if (cb->connected) {
01693             SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry);
01694             if (flags && (flags->peer_address == peer_address)) {
01695                 return cb;
01696             }
01697         }
01698     }
01699     return NULL;
01700 }
01701 
01702 GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block(
01703     SecurityDb::entry_handle_t db_entry
01704 ) {
01705     for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
01706         if (!_control_blocks[i].connected) {
01707             continue;
01708         } else if (db_entry == _control_blocks[i].db_entry) {
01709             return &_control_blocks[i];
01710         }
01711     }
01712     return NULL;
01713 }
01714 
01715 void GenericSecurityManager::release_control_block(ControlBlock_t* cb)
01716 {
01717     *cb = ControlBlock_t();
01718 }
01719 
01720 } /* namespace generic */
01721 } /* namespace ble */