/** * @file ble_quick_security.c * @brief Ultra-simple BLE Security Configuration Implementation * * Compatible with existing debug_print.h system. */ #include "ble_quick_security.h" #include "peer_manager_handler.h" #include "app_error.h" #include // Use existing debug system #include "debug_print.h" // Module state static struct { bool dev_mode; bool bonds_delete_pending; } m_state = {0}; /** * @brief Initialize BLE security */ void ble_security_quick_init(bool development_mode) { ret_code_t err_code; ble_gap_sec_params_t sec_params; // Save mode m_state.dev_mode = development_mode; m_state.bonds_delete_pending = false; // Initialize Peer Manager FIRST err_code = pm_init(); APP_ERROR_CHECK(err_code); // Configure security parameters memset(&sec_params, 0, sizeof(ble_gap_sec_params_t)); if (development_mode) { // ===== DEVELOPMENT MODE: No security ===== sec_params.bond = 0; // No bonding sec_params.mitm = 0; // No MITM sec_params.lesc = 0; // No LESC sec_params.keypress = 0; sec_params.io_caps = BLE_GAP_IO_CAPS_NONE; // No passkey sec_params.oob = 0; sec_params.min_key_size = 7; sec_params.max_key_size = 16; DBG_PRINTF("DEV MODE: Security DISABLED - Fast connection\r\n"); // Delete all bonds (async) err_code = pm_peers_delete(); if (err_code == NRF_SUCCESS) { m_state.bonds_delete_pending = true; DBG_PRINTF("DEV MODE: Deleting all bonds...\r\n"); } } else { // ===== PRODUCTION MODE: Full security ===== sec_params.bond = 1; // Enable bonding sec_params.mitm = 1; // Enable MITM sec_params.lesc = 0; // Standard pairing sec_params.keypress = 0; sec_params.io_caps = BLE_GAP_IO_CAPS_DISPLAY_ONLY; // Show passkey sec_params.oob = 0; sec_params.min_key_size = 7; sec_params.max_key_size = 16; sec_params.kdist_own.enc = 1; sec_params.kdist_own.id = 1; sec_params.kdist_peer.enc = 1; sec_params.kdist_peer.id = 1; DBG_PRINTF("PROD MODE: Security ENABLED - Full protection\r\n"); } // Apply security parameters err_code = pm_sec_params_set(&sec_params); APP_ERROR_CHECK(err_code); } /** * @brief Get current mode */ bool ble_security_is_dev_mode(void) { return m_state.dev_mode; } /** * @brief PM event handler */ void ble_security_quick_pm_handler(pm_evt_t const *p_evt) { ret_code_t err_code; // Call standard handlers (required) pm_handler_on_pm_evt(p_evt); pm_handler_flash_clean(p_evt); // Handle events switch (p_evt->evt_id) { case PM_EVT_CONN_SEC_SUCCEEDED: if (m_state.dev_mode) { DBG_PRINTF("DEV: Connected (no security)\r\n"); } else { DBG_PRINTF("PROD: Link secured (bonded)\r\n"); } break; case PM_EVT_CONN_SEC_FAILED: DBG_PRINTF("Security failed: error=%d\r\n", p_evt->params.conn_sec_failed.error); if (p_evt->params.conn_sec_failed.error == PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING) { // Key missing: 재페어링 시도, 실패 시 disconnect로 폴백 err_code = pm_conn_secure(p_evt->conn_handle, true); if (err_code != NRF_ERROR_INVALID_STATE && err_code != NRF_ERROR_BUSY && err_code != BLE_ERROR_INVALID_CONN_HANDLE) { APP_ERROR_CHECK(err_code); } if (err_code != NRF_SUCCESS) { // 재페어링 불가 → disconnect pm_handler_disconnect_on_sec_failure(p_evt); } } else { // 기타 보안 실패 → disconnect pm_handler_disconnect_on_sec_failure(p_evt); } break; case PM_EVT_CONN_SEC_CONFIG_REQ: { pm_conn_sec_config_t config = { .allow_repairing = m_state.dev_mode }; pm_conn_sec_config_reply(p_evt->conn_handle, &config); } break; case PM_EVT_PEERS_DELETE_SUCCEEDED: if (m_state.bonds_delete_pending) { m_state.bonds_delete_pending = false; DBG_PRINTF("DEV MODE: Bonds cleared!\r\n"); } break; default: break; } }