Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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, ¤t_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 <k 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 <k 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 <k 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 */
Generated on Tue Jul 12 2022 18:18:36 by
