/* * Prevent security lock state changes to the dimm until the next reboot */ int nvm_freezelock_device(const NVM_UID device_uid) { COMMON_LOG_ENTRY(); int rc = NVM_SUCCESS; struct device_discovery discovery; // check user has permission to make changes if (check_caller_permissions() != COMMON_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else if (!is_supported_driver_available()) { rc = NVM_ERR_BADDRIVER; } else if ((rc = IS_NVM_FEATURE_SUPPORTED(modify_device_security)) != NVM_SUCCESS) { COMMON_LOG_ERROR("Modifying "NVM_DIMM_NAME" security is not supported."); } else if (device_uid == NULL) { COMMON_LOG_ERROR("Invalid parameter, device_uid is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if ((rc = exists_and_manageable(device_uid, &discovery, 1)) == NVM_SUCCESS) { if ((rc = check_lock_state(&discovery)) == NVM_SUCCESS) { rc = freeze_security(&discovery); } } COMMON_LOG_EXIT_RETURN_I(rc); return rc; }
/* * Clear an injected error into the device specified. */ int nvm_clear_injected_device_error(const NVM_UID device_uid, const struct device_error *p_error) { COMMON_LOG_ENTRY(); int rc = NVM_SUCCESS; struct device_discovery discovery; if (device_uid == NULL) { COMMON_LOG_ERROR("Invalid parameter, device_uid is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if (p_error == NULL) { COMMON_LOG_ERROR("Invalid parameter, p_error is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if (check_caller_permissions() != NVM_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else if (!is_supported_driver_available()) { rc = NVM_ERR_BADDRIVER; } else if ((rc = IS_NVM_FEATURE_SUPPORTED(error_injection)) != NVM_SUCCESS) { COMMON_LOG_ERROR("Error injection is not supported."); } else if ((rc = exists_and_manageable(device_uid, &discovery, 1)) == NVM_SUCCESS) { if ((rc = enable_error_injection_functionality(discovery.device_handle.handle)) == NVM_SUCCESS) { switch (p_error->type) { case ERROR_TYPE_TEMPERATURE: rc = inject_temperature_error(discovery.device_handle.handle, 0, 0); break; case ERROR_TYPE_POISON: rc = inject_poison_error(&discovery, p_error->dpa, 0); break; case ERROR_TYPE_DIE_SPARING: rc = inject_software_trigger(&discovery, p_error->type, 0); break; case ERROR_TYPE_SPARE_ALARM: case ERROR_TYPE_MEDIA_FATAL_ERROR: rc = NVM_ERR_NOTSUPPORTED; break; default: break; } } } COMMON_LOG_EXIT_RETURN_I(rc); return rc; }
/* * Unlocks the device with the passphrase specified. */ int nvm_unlock_device(const NVM_UID device_uid, const NVM_PASSPHRASE passphrase, const NVM_SIZE passphrase_len) { COMMON_LOG_ENTRY(); int rc = NVM_SUCCESS; struct device_discovery discovery; // check user has permission to make changes if (check_caller_permissions() != COMMON_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else if (!is_supported_driver_available()) { rc = NVM_ERR_BADDRIVER; } else if ((rc = IS_NVM_FEATURE_SUPPORTED(modify_device_security)) != NVM_SUCCESS) { COMMON_LOG_ERROR("Modifying " NVM_DIMM_NAME " security is not supported."); } else if (device_uid == NULL) { COMMON_LOG_ERROR("Invalid parameter, device_uid is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if (((rc = check_passphrase(passphrase, passphrase_len)) == NVM_SUCCESS) && ((rc = exists_and_manageable(device_uid, &discovery, 1)) == NVM_SUCCESS) && ((rc = check_unlock_device_capable(device_uid)) == NVM_SUCCESS)) { if ((rc = security_change_prepare(&discovery, passphrase, passphrase_len)) == NVM_SUCCESS) { // send a pass through command to unlock the device struct pt_payload_passphrase input_payload; memset(&input_payload, 0, sizeof (input_payload)); s_strncpy(input_payload.passphrase_current, NVM_PASSPHRASE_LEN, passphrase, passphrase_len); struct fw_cmd cmd; memset(&cmd, 0, sizeof (struct fw_cmd)); cmd.device_handle = discovery.device_handle.handle; cmd.opcode = PT_SET_SEC_INFO; cmd.sub_opcode = SUBOP_UNLOCK_UNIT; cmd.input_payload_size = sizeof (input_payload); cmd.input_payload = &input_payload; rc = ioctl_passthrough_cmd(&cmd); s_memset(&input_payload, sizeof (input_payload)); // clear any device context - security state has likely changed invalidate_devices(); } } COMMON_LOG_EXIT_RETURN_I(rc); return rc; }
/* * Erases the data on the device specified. */ int nvm_erase_device(const NVM_UID device_uid, const NVM_PASSPHRASE passphrase, const NVM_SIZE passphrase_len) { COMMON_LOG_ENTRY(); int rc = NVM_SUCCESS; struct device_discovery discovery; // check user has permission to make changes if (check_caller_permissions() != COMMON_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else if (!is_supported_driver_available()) { rc = NVM_ERR_BADDRIVER; } else if ((rc = IS_NVM_FEATURE_SUPPORTED(modify_device_security)) != NVM_SUCCESS) { COMMON_LOG_ERROR("Modifying " NVM_DIMM_NAME " security is not supported."); } else if (device_uid == NULL) { COMMON_LOG_ERROR("Invalid parameter, device_uid is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if ((rc = exists_and_manageable(device_uid, &discovery, 1)) == NVM_SUCCESS) { if (discovery.security_capabilities.passphrase_capable) { // check passphrase length if (check_passphrase(passphrase, passphrase_len) != NVM_SUCCESS) { rc = NVM_ERR_BADPASSPHRASE; } // verify device is in the right state to accept a secure erase else if ((rc = security_change_prepare(&discovery, passphrase, passphrase_len)) == NVM_SUCCESS) { rc = secure_erase(passphrase, passphrase_len, &discovery); // clear any device context - security state has likely changed invalidate_devices(); } } else { COMMON_LOG_ERROR("Invalid parameter. " "Crypto scramble erase is not valid in the current security state"); rc = NVM_ERR_INVALIDPARAMETER; } } COMMON_LOG_EXIT_RETURN_I(rc); return rc; }
int nvm_get_job_count() { COMMON_LOG_ENTRY(); int rc = NVM_ERR_UNKNOWN; if (check_caller_permissions() != NVM_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else { rc = get_job_count(); } COMMON_LOG_EXIT_RETURN_I(rc); return rc; }
/* * Run a diagnostic test on the device specified. */ int nvm_run_diagnostic(const NVM_GUID device_guid, const struct diagnostic *p_diagnostic, NVM_UINT32 *p_results) { COMMON_LOG_ENTRY(); int rc = NVM_SUCCESS; if (p_diagnostic == NULL) { COMMON_LOG_ERROR("Invalid parameter, p_diagnostic is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if (p_results == NULL) { COMMON_LOG_ERROR("Invalid parameter, p_results is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if (check_caller_permissions() != NVM_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else { switch (p_diagnostic->test) { case DIAG_TYPE_QUICK: rc = diag_quick_health_check(device_guid, p_diagnostic, p_results); break; case DIAG_TYPE_PLATFORM_CONFIG: rc = diag_platform_config_check(p_diagnostic, p_results); break; case DIAG_TYPE_PM_META: rc = diag_pm_metadata_check(p_results); break; case DIAG_TYPE_FW_CONSISTENCY: rc = diag_firmware_check(p_diagnostic, p_results); break; case DIAG_TYPE_SECURITY: rc = diag_security_check(p_diagnostic, p_results); break; } } COMMON_LOG_EXIT_RETURN_I(rc); return rc; }
int nvm_get_job_count() { COMMON_LOG_ENTRY(); int rc = NVM_ERR_UNKNOWN; if (check_caller_permissions() != NVM_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else if (!is_supported_driver_available()) { rc = NVM_ERR_BADDRIVER; } else { rc = get_job_count(); } COMMON_LOG_EXIT_RETURN_I(rc); return rc; }
/* * Disables data at rest security and removes the passphrase. * The device will be unlocked if it is currently locked. */ int nvm_remove_passphrase(const NVM_UID device_uid, const NVM_PASSPHRASE passphrase, const NVM_SIZE passphrase_len) { COMMON_LOG_ENTRY(); int rc = NVM_SUCCESS; struct device_discovery discovery; // check user has permission to make changes if (check_caller_permissions() != COMMON_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else if (!is_supported_driver_available()) { rc = NVM_ERR_BADDRIVER; } else if ((rc = IS_NVM_FEATURE_SUPPORTED(modify_device_security)) != NVM_SUCCESS) { COMMON_LOG_ERROR("Modifying " NVM_DIMM_NAME " security is not supported."); } else if (device_uid == NULL) { COMMON_LOG_ERROR("Invalid parameter, device_uid is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if (((rc = check_passphrase(passphrase, passphrase_len)) == NVM_SUCCESS) && ((rc = exists_and_manageable(device_uid, &discovery, 1)) == NVM_SUCCESS) && ((rc = check_passphrase_capable(device_uid)) == NVM_SUCCESS) && ((rc = security_change_prepare(&discovery, passphrase, passphrase_len)) == NVM_SUCCESS)) { // send a pass through command to disable security struct pt_payload_passphrase input_payload; memset(&input_payload, 0, sizeof (input_payload)); s_strncpy(input_payload.passphrase_current, NVM_PASSPHRASE_LEN, passphrase, passphrase_len); struct fw_cmd cmd; memset(&cmd, 0, sizeof (struct fw_cmd)); cmd.device_handle = discovery.device_handle.handle; cmd.opcode = PT_SET_SEC_INFO; cmd.sub_opcode = SUBOP_DISABLE_PASS; cmd.input_payload_size = sizeof (input_payload); cmd.input_payload = &input_payload; rc = ioctl_passthrough_cmd(&cmd); if (rc == NVM_SUCCESS) { // Log an event indicating we successfully removed the passphrase NVM_EVENT_ARG uid_arg; uid_to_event_arg(device_uid, uid_arg); log_mgmt_event(EVENT_SEVERITY_INFO, EVENT_CODE_MGMT_SECURITY_PASSWORD_REMOVED, device_uid, 0, // no action required uid_arg, NULL, NULL); } s_memset(&input_payload, sizeof (input_payload)); // clear any device context - security state has likely changed invalidate_devices(); } COMMON_LOG_EXIT_RETURN_I(rc); return rc; }
int nvm_get_jobs(struct job *p_jobs, const NVM_UINT32 count) { COMMON_LOG_ENTRY(); int rc = NVM_SUCCESS; int job_index = 0; if (check_caller_permissions() != NVM_SUCCESS) { rc = NVM_ERR_INVALIDPERMISSIONS; } else if (!is_supported_driver_available()) { rc = NVM_ERR_BADDRIVER; } else if (p_jobs == NULL) { COMMON_LOG_ERROR("Invalid parameter, p_jobs is NULL"); rc = NVM_ERR_INVALIDPARAMETER; } else if ((rc = get_job_count()) < 0) { COMMON_LOG_ERROR("Failed to retrieve job count."); } else if (rc > 0) { // clear the structure memset(p_jobs, 0, sizeof (struct job) * count); if ((rc = nvm_get_device_count()) >= 0) { int device_count = rc; struct device_discovery devices[rc]; if ((rc = nvm_get_devices(devices, device_count)) > 0) { // iterate through all devices and add up the capacities for (int i = 0; i < device_count; i++) { if (job_index >= count) { rc = NVM_ERR_ARRAYTOOSMALL; COMMON_LOG_ERROR("Invalid parameter, " "count is smaller than number of jobs"); break; } if (devices[i].manageability == MANAGEMENT_VALIDCONFIG) { struct pt_payload_sanitize_dimm_status sanitize_status; struct fw_cmd cmd; memset(&cmd, 0, sizeof (struct fw_cmd)); cmd.device_handle = devices[i].device_handle.handle; cmd.opcode = PT_GET_SEC_INFO; cmd.sub_opcode = SUBOP_GET_SAN_STATE; cmd.output_payload_size = sizeof (sanitize_status); cmd.output_payload = &sanitize_status; if (NVM_SUCCESS != ioctl_passthrough_cmd(&cmd)) { COMMON_LOG_ERROR_F( "Unable to get sanitize status for handle: [%d]", devices[i].device_handle.handle); } else { if (sanitize_status.state != SAN_IDLE) { if (sanitize_status.state == SAN_INPROGRESS) { p_jobs[job_index].status = NVM_JOB_STATUS_RUNNING; } else if (sanitize_status.state == SAN_COMPLETED) { p_jobs[job_index].status = NVM_JOB_STATUS_COMPLETE; } else { p_jobs[job_index].status = NVM_JOB_STATUS_UNKNOWN; } p_jobs[job_index].type = NVM_JOB_TYPE_SANITIZE; p_jobs[job_index].percent_complete = sanitize_status.progress; memmove(p_jobs[job_index].uid, devices[i].uid, NVM_MAX_UID_LEN); memmove(p_jobs[job_index].affected_element, devices[i].uid, NVM_MAX_UID_LEN); p_jobs[job_index].result = NULL; job_index++; } } } rc = job_index; } } else { COMMON_LOG_ERROR_F("Unable to get device discovery: rc = %d", rc); } } else { COMMON_LOG_ERROR_F("Unable to get device count: rc = %d", rc); } } return rc; }