ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) { if (!btle_hasInitializedSecurity()) { return BLE_ERROR_INITIALIZATION_INCOMPLETE; } ret_code_t err = dm_whitelist_create(&applicationInstance, p_whitelist); if (err == NRF_SUCCESS) { return BLE_ERROR_NONE; } else if (err == NRF_ERROR_NULL) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } else { return BLE_ERROR_INVALID_STATE; } }
void pm_handler(pm_evt_t const *p_event) { nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); ret_code_t err_code; SecurityManager::SecurityMode_t resolvedSecurityMode; switch (p_event->evt_id) { case PM_EVT_CONN_SEC_START: /* started */ { const ble_gap_sec_params_t *peerParams = &securityParameters; securityManager.processSecuritySetupInitiatedEvent(p_event->conn_handle, peerParams->bond, peerParams->mitm, (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); _enc_in_progress = true; break; } case PM_EVT_CONN_SEC_SUCCEEDED: // Update the rank of the peer. if (p_event->params.conn_sec_succeeded.procedure == PM_LINK_SECURED_PROCEDURE_BONDING) { err_code = pm_peer_rank_highest(p_event->peer_id); } securityManager. processSecuritySetupCompletedEvent(p_event->conn_handle, SecurityManager::SEC_STATUS_SUCCESS);// SEC_STATUS_SUCCESS of SecurityCompletionStatus_t ble_gap_conn_sec_t conn_sec; sd_ble_gap_conn_sec_get(p_event->conn_handle, &conn_sec); resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; switch (conn_sec.sec_mode.sm) { case 1: switch (conn_sec.sec_mode.lv) { case 1: resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; break; case 2: resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; break; case 3: resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; break; } break; case 2: switch (conn_sec.sec_mode.lv) { case 1: resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; break; case 2: resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; break; } break; } securityManager.processLinkSecuredEvent(p_event->conn_handle, resolvedSecurityMode); _enc_in_progress = false; break; case PM_EVT_CONN_SEC_FAILED: SecurityManager::SecurityCompletionStatus_t securityCompletionStatus; if ((uint32_t)p_event->params.conn_sec_failed.error >= PM_CONN_SEC_ERROR_BASE ) { securityCompletionStatus = SecurityManager::SEC_STATUS_UNSPECIFIED; } else { securityCompletionStatus = (SecurityManager::SecurityCompletionStatus_t)p_event->params.conn_sec_failed.error; } securityManager. processSecuritySetupCompletedEvent(p_event->conn_handle, securityCompletionStatus); _enc_in_progress = false; break; case PM_EVT_BONDED_PEER_CONNECTED: pm_peer_rank_highest(p_event->peer_id); break; case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: if (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) { securityManager.processSecurityContextStoredEvent(p_event->conn_handle); } break; case PM_EVT_PEER_DATA_UPDATE_FAILED: break; case PM_EVT_PEERS_DELETE_SUCCEEDED: async_ret_code = NRF_SUCCESS; // respond SUCCESS to the busy-loop in f. btle_purgeAllBondingState break; case PM_EVT_PEERS_DELETE_FAILED: async_ret_code = NRF_ERROR_INTERNAL; // respond FAILURE to the busy-loop in f. btle_purgeAllBondingState break; case PM_EVT_STORAGE_FULL: // Run garbage collection on the flash. err_code = fds_gc(); if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES) { // Retry. } else { APP_ERROR_CHECK(err_code); } break;//PM_EVT_STORAGE_FULL case PM_EVT_CONN_SEC_CONFIG_REQ:{ // A connected peer (central) is trying to pair, but the Peer Manager already has a bond // for that peer. Setting allow_repairing to false rejects the pairing request. // If this event is ignored (pm_conn_sec_config_reply is not called in the event // handler), the Peer Manager assumes allow_repairing to be false. pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true}; pm_conn_sec_config_reply(p_event->conn_handle, &conn_sec_config); } break;//PM_EVT_CONN_SEC_CONFIG_REQ default: break; } } #if (NRF_SD_BLE_API_VERSION <= 2) ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) { if (!btle_hasInitializedSecurity()) { return BLE_ERROR_INITIALIZATION_INCOMPLETE; } ret_code_t err = pm_whitelist_create( NULL, BLE_GAP_WHITELIST_ADDR_MAX_COUNT, p_whitelist); if (err == NRF_SUCCESS) { return BLE_ERROR_NONE; } else if (err == NRF_ERROR_NULL) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } else { return BLE_ERROR_INVALID_STATE; } } #endif bool btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) { /* * Use a helper function from the Nordic SDK to test whether the BLE * address can be generated using the IRK. */ return im_address_resolve(p_addr, p_irk); } void btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) { /* Set type to resolvable */ address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; /* * Assign a random number to the most significant 3 bytes * of the address. */ address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; /* Calculate the hash and store it in the top half of the address */ ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); }