NTSTATUS dc_create_close_irp(PDEVICE_OBJECT dev_obj, PIRP irp) { PIO_STACK_LOCATION irp_sp = IoGetCurrentIrpStackLocation(irp); NTSTATUS status = STATUS_SUCCESS; PEPROCESS process; PACCESS_TOKEN token; /* get requestor process */ process = IoGetRequestorProcess(irp); if (process == NULL) process = IoGetCurrentProcess(); if (irp_sp->MajorFunction == IRP_MJ_CREATE) { /* check process token */ if ( (token = PsReferencePrimaryToken(process)) == NULL || SeTokenIsAdmin(token) == FALSE ) { status = STATUS_ACCESS_DENIED; } if (token != NULL) PsDereferencePrimaryToken(token); } if (irp_sp->MajorFunction == IRP_MJ_CLOSE) { /* unlock all memory locked by this process */ mm_unlock_user_memory(NULL, process); /* syncronize all encryptions */ dc_sync_all_encs(); } return dc_complete_irp(irp, status, 0); }
static NTSTATUS dc_process_power_irp(dev_hook *hook, PIRP irp) { NTSTATUS status; PIO_STACK_LOCATION irp_sp; int no_pass = 0; irp_sp = IoGetCurrentIrpStackLocation(irp); if ( (irp_sp->MinorFunction == IRP_MN_SET_POWER) && (irp_sp->Parameters.Power.Type == SystemPowerState) ) { wait_object_infinity(&hook->busy_lock); if (irp_sp->Parameters.Power.State.SystemState == PowerSystemHibernate) { /* prevent device encryption to sync device and memory state */ hook->flags |= F_PREVENT_ENC; dc_send_sync_packet(hook->dev_name, S_OP_SYNC, 0); } if (irp_sp->Parameters.Power.State.SystemState == PowerSystemWorking) { /* allow encryption requests */ hook->flags &= ~F_PREVENT_ENC; } KeReleaseMutex(&hook->busy_lock, FALSE); } if ( (irp_sp->MinorFunction == IRP_MN_QUERY_POWER) && (irp_sp->Parameters.Power.Type == SystemPowerState) && (irp_sp->Parameters.Power.State.SystemState == PowerSystemHibernate) ) { if ( (dc_is_vista_or_later == 0) && (dump_is_pverent_hibernate() != 0) ) { PoStartNextPowerIrp(irp); status = dc_complete_irp(irp, STATUS_UNSUCCESSFUL, 0); no_pass = 1; } } if (no_pass == 0) { PoStartNextPowerIrp(irp); IoSkipCurrentIrpStackLocation(irp); status = PoCallDriver(hook->orig_dev, irp); } IoReleaseRemoveLock(&hook->remv_lock, irp); return status; }
NTSTATUS dc_release_irp(dev_hook *hook, PIRP irp, NTSTATUS status) { dc_complete_irp(irp, status, 0); IoReleaseRemoveLock(&hook->remv_lock, irp); return status; }
NTSTATUS dc_drv_control_irp(PDEVICE_OBJECT dev_obj, PIRP irp) { PIO_STACK_LOCATION irp_sp = IoGetCurrentIrpStackLocation(irp); NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; // returned status ULONG length = 0; // returned length // void *data = irp->AssociatedIrp.SystemBuffer; u32 in_len = irp_sp->Parameters.DeviceIoControl.InputBufferLength; u32 out_len = irp_sp->Parameters.DeviceIoControl.OutputBufferLength; switch (irp_sp->Parameters.DeviceIoControl.IoControlCode) { case DC_GET_VERSION: if (irp_sp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG)) { status = STATUS_INVALID_PARAMETER; break; } *((PULONG)irp->AssociatedIrp.SystemBuffer) = DC_DRIVER_VER; status = STATUS_SUCCESS; length = sizeof(ULONG); break; case DC_CTL_CLEAR_PASS: dc_clean_pass_cache(); status = STATUS_SUCCESS; break; case DC_CTL_ADD_SEED: if (irp_sp->Parameters.DeviceIoControl.InputBufferLength == 0) { status = STATUS_INVALID_PARAMETER; break; } cp_rand_add_seed(irp->AssociatedIrp.SystemBuffer, irp_sp->Parameters.DeviceIoControl.InputBufferLength); status = STATUS_SUCCESS; // prevent leaks RtlSecureZeroMemory(irp->AssociatedIrp.SystemBuffer, irp_sp->Parameters.DeviceIoControl.InputBufferLength); break; case DC_CTL_GET_RAND: if (irp_sp->Parameters.DeviceIoControl.OutputBufferLength == 0) { status = STATUS_INVALID_PARAMETER; break; } if ( (data = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority)) == NULL ) { status = STATUS_INSUFFICIENT_RESOURCES; break; } if (cp_rand_bytes(data, irp_sp->Parameters.DeviceIoControl.OutputBufferLength) == 0) { status = STATUS_INTERNAL_ERROR; break; } status = STATUS_SUCCESS; length = irp_sp->Parameters.DeviceIoControl.OutputBufferLength; break; case DC_CTL_LOCK_MEM: if (irp_sp->Parameters.DeviceIoControl.InputBufferLength != sizeof(DC_LOCK_MEMORY)) { status = STATUS_INVALID_PARAMETER; break; } status = mm_lock_user_memory( PsGetProcessId(IoGetRequestorProcess(irp)), ((PDC_LOCK_MEMORY)irp->AssociatedIrp.SystemBuffer)->ptr, ((PDC_LOCK_MEMORY)irp->AssociatedIrp.SystemBuffer)->length ); break; case DC_CTL_UNLOCK_MEM: if (irp_sp->Parameters.DeviceIoControl.InputBufferLength != sizeof(PVOID*)) { status = STATUS_INVALID_PARAMETER; break; } status = mm_unlock_user_memory( PsGetProcessId(IoGetRequestorProcess(irp)), *((PVOID*)irp->AssociatedIrp.SystemBuffer) ); break; case DC_CTL_GET_FLAGS: if (irp_sp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(DC_FLAGS)) { status = STATUS_INVALID_PARAMETER; break; } ((PDC_FLAGS)irp->AssociatedIrp.SystemBuffer)->conf_flags = dc_conf_flags; ((PDC_FLAGS)irp->AssociatedIrp.SystemBuffer)->load_flags = dc_load_flags; status = STATUS_SUCCESS; length = sizeof(DC_FLAGS); break; case DC_CTL_SET_FLAGS: if (irp_sp->Parameters.DeviceIoControl.InputBufferLength != sizeof(DC_FLAGS)) { status = STATUS_INVALID_PARAMETER; break; } dc_conf_flags = ((PDC_FLAGS)irp->AssociatedIrp.SystemBuffer)->conf_flags; if ( !(dc_conf_flags & CONF_CACHE_PASSWORD) ) dc_clean_pass_cache(); dc_init_encryption(); status = STATUS_SUCCESS; break; case DC_CTL_BSOD: mm_clean_secure_memory(); dc_clean_keys(); KeBugCheck(IRQL_NOT_LESS_OR_EQUAL); break; case DC_GET_DUMP_HELPERS: // This IOCTL is allowed only from kernel mode if (irp->RequestorMode != KernelMode) { status = STATUS_ACCESS_DENIED; break; } if (irp_sp->Parameters.DeviceIoControl.OutputBufferLength != sizeof(DC_DUMP_HELPERS)) { status = STATUS_INVALID_PARAMETER; break; } memcpy(irp->UserBuffer, &dc_dump_helpers, sizeof(DC_DUMP_HELPERS)); status = STATUS_SUCCESS; length = sizeof(DC_DUMP_HELPERS); break; // case DC_CTL_STATUS: { dc_ioctl *dctl = data; dc_status *stat = data; dev_hook *hook; if ( (in_len == sizeof(dc_ioctl)) && (out_len == sizeof(dc_status)) ) { dctl->device[MAX_DEVICE] = 0; if (hook = dc_find_hook(dctl->device)) { if (hook->pdo_dev->Flags & DO_SYSTEM_BOOT_PARTITION) { hook->flags |= F_SYSTEM; } dc_get_mount_point(hook, stat->mnt_point, sizeof(stat->mnt_point)); stat->crypt = hook->crypt; stat->dsk_size = hook->dsk_size; stat->tmp_size = hook->tmp_size; stat->flags = hook->flags; stat->mnt_flags = hook->mnt_flags; stat->disk_id = hook->disk_id; stat->paging_count = hook->paging_count; stat->vf_version = hook->vf_version; status = STATUS_SUCCESS; length = sizeof(dc_status); dc_deref_hook(hook); } } } break; case DC_CTL_BENCHMARK: { if ( (in_len == sizeof(int)) && (out_len == sizeof(dc_bench_info)) ) { if (dc_k_benchmark(p32(data)[0], pv(data)) == ST_OK) { status = STATUS_SUCCESS; length = sizeof(dc_bench_info); } } } break; case DC_BACKUP_HEADER: { dc_backup_ctl *back = data; if ( (in_len == sizeof(dc_backup_ctl)) && (out_len == in_len) ) { back->device[MAX_DEVICE] = 0; back->status = dc_backup_header(back->device, &back->pass, back->backup); /* prevent leaks */ burn(&back->pass, sizeof(back->pass)); status = STATUS_SUCCESS; length = sizeof(dc_backup_ctl); } } break; case DC_RESTORE_HEADER: { dc_backup_ctl *back = data; if ( (in_len == sizeof(dc_backup_ctl)) && (out_len == in_len) ) { back->device[MAX_DEVICE] = 0; back->status = dc_restore_header(back->device, &back->pass, back->backup); /* prevent leaks */ burn(&back->pass, sizeof(back->pass)); status = STATUS_SUCCESS; length = sizeof(dc_backup_ctl); } } break; default: { dc_ioctl *dctl = data; if ( (in_len == sizeof(dc_ioctl)) && (out_len == sizeof(dc_ioctl)) ) { /* limit null-terminated string length */ dctl->device[MAX_DEVICE] = 0; /* process IOCTL */ dctl->status = dc_ioctl_process(irp_sp->Parameters.DeviceIoControl.IoControlCode, dctl); /* prevent leaks */ burn(&dctl->passw1, sizeof(dctl->passw1)); burn(&dctl->passw2, sizeof(dctl->passw2)); status = STATUS_SUCCESS; length = sizeof(dc_ioctl); } } break; } return dc_complete_irp(irp, status, length); }