diff options
Diffstat (limited to 'src/Driver/Ntdriver.c')
-rw-r--r-- | src/Driver/Ntdriver.c | 388 |
1 files changed, 295 insertions, 93 deletions
diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c index 1327c12a..b337ad86 100644 --- a/src/Driver/Ntdriver.c +++ b/src/Driver/Ntdriver.c @@ -13,6 +13,8 @@ #include "TCdefs.h" #include <ntddk.h> +#include <initguid.h> +#include <Ntddstor.h> #include "Crypto.h" #include "Fat.h" #include "Tests.h" @@ -133,6 +135,7 @@ BOOL CacheBootPim = FALSE; BOOL NonAdminSystemFavoritesAccessDisabled = FALSE; BOOL BlockSystemTrimCommand = FALSE; BOOL AllowWindowsDefrag = FALSE; +BOOL EraseKeysOnShutdown = TRUE; // by default, we erase encryption keys on system shutdown static size_t EncryptionThreadPoolFreeCpuCountLimit = 0; static BOOL SystemFavoriteVolumeDirty = FALSE; static BOOL PagingFileCreationPrevented = FALSE; @@ -142,13 +145,43 @@ static BOOL RamEncryptionActivated = FALSE; static KeSaveExtendedProcessorStateFn KeSaveExtendedProcessorStatePtr = NULL; static KeRestoreExtendedProcessorStateFn KeRestoreExtendedProcessorStatePtr = NULL; static ExGetFirmwareEnvironmentVariableFn ExGetFirmwareEnvironmentVariablePtr = NULL; +static KeQueryInterruptTimePreciseFn KeQueryInterruptTimePrecisePtr = NULL; static KeAreAllApcsDisabledFn KeAreAllApcsDisabledPtr = NULL; +static KeSetSystemGroupAffinityThreadFn KeSetSystemGroupAffinityThreadPtr = NULL; +static KeQueryActiveGroupCountFn KeQueryActiveGroupCountPtr = NULL; +static KeQueryActiveProcessorCountExFn KeQueryActiveProcessorCountExPtr = NULL; +int EncryptionIoRequestCount = 0; +int EncryptionItemCount = 0; +int EncryptionFragmentSize = 0; POOL_TYPE ExDefaultNonPagedPoolType = NonPagedPool; ULONG ExDefaultMdlProtection = 0; PDEVICE_OBJECT VirtualVolumeDeviceObjects[MAX_MOUNTED_VOLUME_DRIVE_NUMBER + 1]; +BOOL AlignValue (ULONG ulValue, ULONG ulAlignment, ULONG *pulResult) +{ + BOOL bRet = FALSE; + HRESULT hr; + if (ulAlignment == 0) + { + *pulResult = ulValue; + bRet = TRUE; + } + else + { + ulAlignment -= 1; + hr = ULongAdd (ulValue, ulAlignment, &ulValue); + if (S_OK == hr) + { + *pulResult = ulValue & (~ulAlignment); + bRet = TRUE; + } + } + + return bRet; +} + BOOL IsUefiBoot () { BOOL bStatus = FALSE; @@ -206,8 +239,17 @@ void GetDriverRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed) iSeed = KeQueryPerformanceCounter (&iSeed2); WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); WHIRLPOOL_add ((unsigned char *) &(iSeed2.QuadPart), sizeof(iSeed2.QuadPart), &tctx); - iSeed.QuadPart = KeQueryInterruptTime (); - WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); + if (KeQueryInterruptTimePrecisePtr) + { + iSeed.QuadPart = KeQueryInterruptTimePrecisePtr (&iSeed2.QuadPart); + WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); + WHIRLPOOL_add ((unsigned char *) &(iSeed2.QuadPart), sizeof(iSeed2.QuadPart), &tctx); + } + else + { + iSeed.QuadPart = KeQueryInterruptTime (); + WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); + } /* use JitterEntropy library to get good quality random bytes based on CPU timing jitter */ if (0 == jent_entropy_init ()) @@ -283,13 +325,20 @@ NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) } // KeSaveExtendedProcessorState/KeRestoreExtendedProcessorState are available starting from Windows 7 + // KeQueryActiveGroupCount/KeQueryActiveProcessorCountEx/KeSetSystemGroupAffinityThread are available starting from Windows 7 if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 1)) { - UNICODE_STRING saveFuncName, restoreFuncName; + UNICODE_STRING saveFuncName, restoreFuncName, groupCountFuncName, procCountFuncName, setAffinityFuncName; RtlInitUnicodeString(&saveFuncName, L"KeSaveExtendedProcessorState"); RtlInitUnicodeString(&restoreFuncName, L"KeRestoreExtendedProcessorState"); + RtlInitUnicodeString(&groupCountFuncName, L"KeQueryActiveGroupCount"); + RtlInitUnicodeString(&procCountFuncName, L"KeQueryActiveProcessorCountEx"); + RtlInitUnicodeString(&setAffinityFuncName, L"KeSetSystemGroupAffinityThread"); KeSaveExtendedProcessorStatePtr = (KeSaveExtendedProcessorStateFn) MmGetSystemRoutineAddress(&saveFuncName); KeRestoreExtendedProcessorStatePtr = (KeRestoreExtendedProcessorStateFn) MmGetSystemRoutineAddress(&restoreFuncName); + KeSetSystemGroupAffinityThreadPtr = (KeSetSystemGroupAffinityThreadFn) MmGetSystemRoutineAddress(&setAffinityFuncName); + KeQueryActiveGroupCountPtr = (KeQueryActiveGroupCountFn) MmGetSystemRoutineAddress(&groupCountFuncName); + KeQueryActiveProcessorCountExPtr = (KeQueryActiveProcessorCountExFn) MmGetSystemRoutineAddress(&procCountFuncName); } // ExGetFirmwareEnvironmentVariable is available starting from Windows 8 @@ -300,6 +349,14 @@ NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) ExGetFirmwareEnvironmentVariablePtr = (ExGetFirmwareEnvironmentVariableFn) MmGetSystemRoutineAddress(&funcName); } + // KeQueryInterruptTimePrecise is available starting from Windows 8.1 + if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 3)) + { + UNICODE_STRING funcName; + RtlInitUnicodeString(&funcName, L"KeQueryInterruptTimePrecise"); + KeQueryInterruptTimePrecisePtr = (KeQueryInterruptTimePreciseFn) MmGetSystemRoutineAddress(&funcName); + } + // Load dump filter if the main driver is already loaded if (NT_SUCCESS (TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &version, sizeof (version)))) return DumpFilterEntry ((PFILTER_EXTENSION) DriverObject, (PFILTER_INITIALIZATION_DATA) RegistryPath); @@ -976,8 +1033,8 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION outputBuffer->Geometry.TracksPerCylinder = Extension->TracksPerCylinder; outputBuffer->Geometry.SectorsPerTrack = Extension->SectorsPerTrack; outputBuffer->Geometry.BytesPerSector = Extension->BytesPerSector; - /* add one sector to DiskLength since our partition size is DiskLength and its offset if BytesPerSector */ - outputBuffer->DiskSize.QuadPart = Extension->DiskLength + Extension->BytesPerSector; + // Add 1MB to the disk size to emulate the geometry of a real MBR disk + outputBuffer->DiskSize.QuadPart = Extension->DiskLength + BYTES_PER_MB; if (bFullBuffer) { @@ -1248,7 +1305,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION outputBuffer->BootIndicator = FALSE; outputBuffer->RecognizedPartition = TRUE; outputBuffer->RewritePartition = FALSE; - outputBuffer->StartingOffset.QuadPart = Extension->BytesPerSector; + outputBuffer->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk outputBuffer->PartitionLength.QuadPart= Extension->DiskLength; outputBuffer->PartitionNumber = 1; outputBuffer->HiddenSectors = 0; @@ -1265,7 +1322,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION outputBuffer->PartitionStyle = PARTITION_STYLE_MBR; outputBuffer->RewritePartition = FALSE; - outputBuffer->StartingOffset.QuadPart = Extension->BytesPerSector; + outputBuffer->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk outputBuffer->PartitionLength.QuadPart= Extension->DiskLength; outputBuffer->PartitionNumber = 1; outputBuffer->Mbr.PartitionType = Extension->PartitionType; @@ -1293,7 +1350,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION outputBuffer->PartitionEntry->BootIndicator = FALSE; outputBuffer->PartitionEntry->RecognizedPartition = TRUE; outputBuffer->PartitionEntry->RewritePartition = FALSE; - outputBuffer->PartitionEntry->StartingOffset.QuadPart = Extension->BytesPerSector; + outputBuffer->PartitionEntry->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength; outputBuffer->PartitionEntry->PartitionNumber = 1; outputBuffer->PartitionEntry->HiddenSectors = 0; @@ -1329,7 +1386,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION outputBuffer->PartitionEntry->Mbr.BootIndicator = FALSE; outputBuffer->PartitionEntry->Mbr.RecognizedPartition = TRUE; outputBuffer->PartitionEntry->RewritePartition = FALSE; - outputBuffer->PartitionEntry->StartingOffset.QuadPart = Extension->BytesPerSector; + outputBuffer->PartitionEntry->StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk outputBuffer->PartitionEntry->PartitionLength.QuadPart = Extension->DiskLength; outputBuffer->PartitionEntry->PartitionNumber = 1; outputBuffer->PartitionEntry->Mbr.HiddenSectors = 0; @@ -1384,7 +1441,8 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION else { IO_STATUS_BLOCK ioStatus; - PVOID buffer = TCalloc (max (pVerifyInformation->Length, PAGE_SIZE)); + DWORD dwBuffersize = min (pVerifyInformation->Length, 16 * PAGE_SIZE); + PVOID buffer = TCalloc (dwBuffersize); if (!buffer) { @@ -1392,14 +1450,29 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION } else { - LARGE_INTEGER offset = pVerifyInformation->StartingOffset; + LARGE_INTEGER offset; + DWORD dwRemainingBytes = pVerifyInformation->Length, dwReadCount; offset.QuadPart = ullNewOffset; - Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, pVerifyInformation->Length, &offset, NULL); - TCfree (buffer); + while (dwRemainingBytes) + { + dwReadCount = min (dwBuffersize, dwRemainingBytes); + Irp->IoStatus.Status = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &ioStatus, buffer, dwReadCount, &offset, NULL); - if (NT_SUCCESS (Irp->IoStatus.Status) && ioStatus.Information != pVerifyInformation->Length) - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + if (NT_SUCCESS (Irp->IoStatus.Status) && ioStatus.Information != dwReadCount) + { + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + break; + } + else if (!NT_SUCCESS (Irp->IoStatus.Status)) + break; + + dwRemainingBytes -= dwReadCount; + offset.QuadPart += (ULONGLONG) dwReadCount; + } + + burn (buffer, dwBuffersize); + TCfree (buffer); } } @@ -1474,7 +1547,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION // of the underlaying physical disk and we report a single extent extents->NumberOfDiskExtents = 1; extents->Extents[0].DiskNumber = Extension->DeviceNumber; - extents->Extents[0].StartingOffset.QuadPart = Extension->BytesPerSector; + extents->Extents[0].StartingOffset.QuadPart = BYTES_PER_MB; // Set offset to 1MB to emulate the partition offset on a real MBR disk extents->Extents[0].ExtentLength.QuadPart = Extension->DiskLength; } else @@ -1502,8 +1575,8 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION capacity->Version = sizeof (STORAGE_READ_CAPACITY); capacity->Size = sizeof (STORAGE_READ_CAPACITY); capacity->BlockLength = Extension->BytesPerSector; - capacity->NumberOfBlocks.QuadPart = (Extension->DiskLength / Extension->BytesPerSector) + 1; - capacity->DiskLength.QuadPart = Extension->DiskLength + Extension->BytesPerSector; + capacity->DiskLength.QuadPart = Extension->DiskLength + BYTES_PER_MB; // Add 1MB to the disk size to emulate the geometry of a real MBR disk + capacity->NumberOfBlocks.QuadPart = capacity->DiskLength.QuadPart / capacity->BlockLength; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof (STORAGE_READ_CAPACITY); @@ -1662,7 +1735,7 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION ULONG ulNewInputLength = 0; BOOL bForwardIoctl = FALSE; - if (inputLength >= minSizeGeneric && inputLength >= minSizedataSet && inputLength >= minSizeParameter) + if (((ULONGLONG) inputLength) >= minSizeGeneric && ((ULONGLONG) inputLength) >= minSizedataSet && ((ULONGLONG) inputLength) >= minSizeParameter) { if (bEntireSet) { @@ -1674,36 +1747,53 @@ NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION } else { - DWORD dwDataSetOffset = ALIGN_VALUE (inputLength, sizeof(DEVICE_DATA_SET_RANGE)); + DWORD dwDataSetOffset; DWORD dwDataSetLength = sizeof(DEVICE_DATA_SET_RANGE); - Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set. Setting data range to all volume.\n"); - - ulNewInputLength = dwDataSetOffset + dwDataSetLength; - pNewSetAttrs = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES) TCalloc (ulNewInputLength); - if (pNewSetAttrs) + if (AlignValue (inputLength, sizeof(DEVICE_DATA_SET_RANGE), &dwDataSetOffset)) { - PDEVICE_DATA_SET_RANGE pRange = (PDEVICE_DATA_SET_RANGE) (((unsigned char*) pNewSetAttrs) + dwDataSetOffset); + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set. Setting data range to all volume.\n"); - memcpy (pNewSetAttrs, pInputAttrs, inputLength); + if (S_OK == ULongAdd(dwDataSetOffset, dwDataSetLength, &ulNewInputLength)) + { + pNewSetAttrs = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES) TCalloc (ulNewInputLength); + if (pNewSetAttrs) + { + PDEVICE_DATA_SET_RANGE pRange = (PDEVICE_DATA_SET_RANGE) (((unsigned char*) pNewSetAttrs) + dwDataSetOffset); - pRange->StartingOffset = (ULONGLONG) Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset; - pRange->LengthInBytes = Extension->DiskLength; + memcpy (pNewSetAttrs, pInputAttrs, inputLength); - pNewSetAttrs->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES); - pNewSetAttrs->Action = action; - pNewSetAttrs->Flags = pInputAttrs->Flags & (~DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE); - pNewSetAttrs->ParameterBlockOffset = pInputAttrs->ParameterBlockOffset; - pNewSetAttrs->ParameterBlockLength = pInputAttrs->ParameterBlockLength; - pNewSetAttrs->DataSetRangesOffset = dwDataSetOffset; - pNewSetAttrs->DataSetRangesLength = dwDataSetLength; + pRange->StartingOffset = (ULONGLONG) Extension->cryptoInfo->hiddenVolume ? Extension->cryptoInfo->hiddenVolumeOffset : Extension->cryptoInfo->volDataAreaOffset; + pRange->LengthInBytes = Extension->DiskLength; - bForwardIoctl = TRUE; + pNewSetAttrs->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES); + pNewSetAttrs->Action = action; + pNewSetAttrs->Flags = pInputAttrs->Flags & (~DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE); + pNewSetAttrs->ParameterBlockOffset = pInputAttrs->ParameterBlockOffset; + pNewSetAttrs->ParameterBlockLength = pInputAttrs->ParameterBlockLength; + pNewSetAttrs->DataSetRangesOffset = dwDataSetOffset; + pNewSetAttrs->DataSetRangesLength = dwDataSetLength; + + bForwardIoctl = TRUE; + } + else + { + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - Failed to allocate memory.\n"); + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Irp->IoStatus.Information = 0; + } + } + else + { + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set but data range length computation overflowed.\n"); + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + } } else { - Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - Failed to allocate memory.\n"); - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + Dump ("ProcessVolumeDeviceControlIrp: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE set but data set offset computation overflowed.\n"); + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; } } @@ -1869,7 +1959,7 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex switch (irpSp->Parameters.DeviceIoControl.IoControlCode) { case TC_IOCTL_GET_DRIVER_VERSION: - case TC_IOCTL_LEGACY_GET_DRIVER_VERSION: + if (ValidateIOBufferSize (Irp, sizeof (LONG), ValidateOutput)) { LONG tmp = VERSION_NUM; @@ -2303,7 +2393,6 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_OUTER; // Normal/outer volume (hidden volume protected) else list->volumeType[ListExtension->nDosDriveNo] = PROP_VOL_TYPE_NORMAL; // Normal volume - list->truecryptMode[ListExtension->nDosDriveNo] = ListExtension->cryptoInfo->bTrueCryptMode; } } @@ -2312,21 +2401,6 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex } break; - case TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES: - if (ValidateIOBufferSize (Irp, sizeof (uint32), ValidateOutput)) - { - // Prevent the user from downgrading to versions lower than 5.0 by faking mounted volumes. - // The user could render the system unbootable by downgrading when boot encryption - // is active or being set up. - - memset (Irp->AssociatedIrp.SystemBuffer, 0, irpSp->Parameters.DeviceIoControl.OutputBufferLength); - *(uint32 *) Irp->AssociatedIrp.SystemBuffer = 0xffffFFFF; - - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = irpSp->Parameters.DeviceIoControl.OutputBufferLength; - } - break; - case TC_IOCTL_GET_VOLUME_PROPERTIES: if (ValidateIOBufferSize (Irp, sizeof (VOLUME_PROPERTIES_STRUCT), ValidateInputOutput)) { @@ -2602,7 +2676,6 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex || mount->pkcs5_prf < 0 || mount->pkcs5_prf > LAST_PRF_ID || mount->VolumePim < -1 || mount->VolumePim == INT_MAX || mount->ProtectedHidVolPkcs5Prf < 0 || mount->ProtectedHidVolPkcs5Prf > LAST_PRF_ID - || (mount->bTrueCryptMode != FALSE && mount->bTrueCryptMode != TRUE) ) { Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; @@ -2620,7 +2693,6 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex burn (&mount->ProtectedHidVolPassword, sizeof (mount->ProtectedHidVolPassword)); burn (&mount->pkcs5_prf, sizeof (mount->pkcs5_prf)); burn (&mount->VolumePim, sizeof (mount->VolumePim)); - burn (&mount->bTrueCryptMode, sizeof (mount->bTrueCryptMode)); burn (&mount->ProtectedHidVolPkcs5Prf, sizeof (mount->ProtectedHidVolPkcs5Prf)); burn (&mount->ProtectedHidVolPim, sizeof (mount->ProtectedHidVolPim)); } @@ -2815,6 +2887,18 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex } break; + case VC_IOCTL_ENCRYPTION_QUEUE_PARAMS: + if (ValidateIOBufferSize (Irp, sizeof (EncryptionQueueParameters), ValidateOutput)) + { + EncryptionQueueParameters* pParams = (EncryptionQueueParameters*) Irp->AssociatedIrp.SystemBuffer; + pParams->EncryptionFragmentSize = EncryptionFragmentSize; + pParams->EncryptionIoRequestCount = EncryptionIoRequestCount; + pParams->EncryptionItemCount = EncryptionItemCount; + Irp->IoStatus.Information = sizeof (EncryptionQueueParameters); + Irp->IoStatus.Status = STATUS_SUCCESS; + } + break; + default: return TCCompleteIrp (Irp, STATUS_INVALID_DEVICE_REQUEST, 0); } @@ -3090,6 +3174,21 @@ VOID VolumeThreadProc (PVOID Context) Extension->Queue.HostFileHandle = Extension->hDeviceFile; Extension->Queue.VirtualDeviceLength = Extension->DiskLength; Extension->Queue.MaxReadAheadOffset.QuadPart = Extension->HostLength; + if (bDevice && pThreadBlock->mount->bPartitionInInactiveSysEncScope + && (!Extension->cryptoInfo->hiddenVolume) + && (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) + ) + { + // Support partial encryption only in the case of system encryption + Extension->Queue.EncryptedAreaStart = 0; + Extension->Queue.EncryptedAreaEnd = Extension->cryptoInfo->EncryptedAreaLength.Value - 1; + if (Extension->Queue.CryptoInfo->EncryptedAreaLength.Value == 0) + { + Extension->Queue.EncryptedAreaStart = -1; + Extension->Queue.EncryptedAreaEnd = -1; + } + Extension->Queue.bSupportPartialEncryption = TRUE; + } if (Extension->SecurityClientContextValid) Extension->Queue.SecurityClientContext = &Extension->SecurityClientContext; @@ -3225,6 +3324,7 @@ LPWSTR TCTranslateCode (ULONG ulCode) TC_CASE_RET_NAME (VC_IOCTL_GET_DRIVE_GEOMETRY_EX); TC_CASE_RET_NAME (VC_IOCTL_EMERGENCY_CLEAR_ALL_KEYS); TC_CASE_RET_NAME (VC_IOCTL_IS_RAM_ENCRYPTION_ENABLED); + TC_CASE_RET_NAME (VC_IOCTL_ENCRYPTION_QUEUE_PARAMS); TC_CASE_RET_NAME (IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS); @@ -3353,6 +3453,8 @@ LPWSTR TCTranslateCode (ULONG ulCode) return (LPWSTR) _T ("IOCTL_STORAGE_CHECK_PRIORITY_HINT_SUPPORT"); else if (ulCode == IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES) return (LPWSTR) _T ("IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES"); + else if (ulCode == IOCTL_DISK_GROW_PARTITION) + return (LPWSTR) _T ("IOCTL_DISK_GROW_PARTITION"); else if (ulCode == IRP_MJ_READ) return (LPWSTR) _T ("IRP_MJ_READ"); else if (ulCode == IRP_MJ_WRITE) @@ -3403,31 +3505,21 @@ void TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) if (Extension->SecurityClientContextValid) { - if (OsMajorVersion == 5 && OsMinorVersion == 0) - { - ObDereferenceObject (Extension->SecurityClientContext.ClientToken); - } - else - { - // Windows 2000 does not support PsDereferenceImpersonationToken() used by SeDeleteClientSecurity(). - // TODO: Use only SeDeleteClientSecurity() once support for Windows 2000 is dropped. - - VOID (*PsDereferenceImpersonationTokenD) (PACCESS_TOKEN ImpersonationToken); - UNICODE_STRING name; - RtlInitUnicodeString (&name, L"PsDereferenceImpersonationToken"); + VOID (*PsDereferenceImpersonationTokenD) (PACCESS_TOKEN ImpersonationToken); + UNICODE_STRING name; + RtlInitUnicodeString (&name, L"PsDereferenceImpersonationToken"); - PsDereferenceImpersonationTokenD = MmGetSystemRoutineAddress (&name); - if (!PsDereferenceImpersonationTokenD) - TC_BUG_CHECK (STATUS_NOT_IMPLEMENTED); + PsDereferenceImpersonationTokenD = MmGetSystemRoutineAddress (&name); + if (!PsDereferenceImpersonationTokenD) + TC_BUG_CHECK (STATUS_NOT_IMPLEMENTED); -# define PsDereferencePrimaryToken -# define PsDereferenceImpersonationToken PsDereferenceImpersonationTokenD +# define PsDereferencePrimaryToken +# define PsDereferenceImpersonationToken PsDereferenceImpersonationTokenD - SeDeleteClientSecurity (&Extension->SecurityClientContext); + SeDeleteClientSecurity (&Extension->SecurityClientContext); -# undef PsDereferencePrimaryToken -# undef PsDereferenceImpersonationToken - } +# undef PsDereferencePrimaryToken +# undef PsDereferenceImpersonationToken } VirtualVolumeDeviceObjects[Extension->nDosDriveNo] = NULL; @@ -3627,11 +3719,16 @@ NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *dr LARGE_INTEGER offset; byte *sectorBuffer; ULONGLONG startTime; + ULONG sectorSize; if (!UserCanAccessDriveDevice()) return STATUS_ACCESS_DENIED; - sectorBuffer = TCalloc (TC_SECTOR_SIZE_BIOS); + status = GetDeviceSectorSize (driveDeviceObject, §orSize); + if (!NT_SUCCESS (status)) + return status; + + sectorBuffer = TCalloc (sectorSize); if (!sectorBuffer) return STATUS_INSUFFICIENT_RESOURCES; @@ -3646,12 +3743,12 @@ NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *dr } startTime = KeQueryInterruptTime (); - for (offset.QuadPart = sysLength.QuadPart; ; offset.QuadPart += TC_SECTOR_SIZE_BIOS) + for (offset.QuadPart = sysLength.QuadPart; ; offset.QuadPart += sectorSize) { - status = TCReadDevice (driveDeviceObject, sectorBuffer, offset, TC_SECTOR_SIZE_BIOS); + status = TCReadDevice (driveDeviceObject, sectorBuffer, offset, sectorSize); if (NT_SUCCESS (status)) - status = TCWriteDevice (driveDeviceObject, sectorBuffer, offset, TC_SECTOR_SIZE_BIOS); + status = TCWriteDevice (driveDeviceObject, sectorBuffer, offset, sectorSize); if (!NT_SUCCESS (status)) { @@ -4470,18 +4567,35 @@ NTSTATUS TCCompleteDiskIrp (PIRP irp, NTSTATUS status, ULONG_PTR information) } -size_t GetCpuCount () +size_t GetCpuCount (WORD* pGroupCount) { - KAFFINITY activeCpuMap = KeQueryActiveProcessors(); - size_t mapSize = sizeof (activeCpuMap) * 8; size_t cpuCount = 0; + if (KeQueryActiveGroupCountPtr && KeQueryActiveProcessorCountExPtr) + { + USHORT i, groupCount = KeQueryActiveGroupCountPtr (); + for (i = 0; i < groupCount; i++) + { + cpuCount += (size_t) KeQueryActiveProcessorCountExPtr (i); + } - while (mapSize--) + if (pGroupCount) + *pGroupCount = groupCount; + } + else { - if (activeCpuMap & 1) - ++cpuCount; + KAFFINITY activeCpuMap = KeQueryActiveProcessors(); + size_t mapSize = sizeof (activeCpuMap) * 8; + + while (mapSize--) + { + if (activeCpuMap & 1) + ++cpuCount; + + activeCpuMap >>= 1; + } - activeCpuMap >>= 1; + if (pGroupCount) + *pGroupCount = 1; } if (cpuCount == 0) @@ -4490,6 +4604,35 @@ size_t GetCpuCount () return cpuCount; } +USHORT GetCpuGroup (size_t index) +{ + if (KeQueryActiveGroupCountPtr && KeQueryActiveProcessorCountExPtr) + { + USHORT i, groupCount = KeQueryActiveGroupCountPtr (); + size_t cpuCount = 0; + for (i = 0; i < groupCount; i++) + { + cpuCount += (size_t) KeQueryActiveProcessorCountExPtr (i); + if (cpuCount >= index) + { + return i; + } + } + } + + return 0; +} + +void SetThreadCpuGroupAffinity (USHORT index) +{ + if (KeSetSystemGroupAffinityThreadPtr) + { + GROUP_AFFINITY groupAffinity = {0}; + groupAffinity.Mask = ~0ULL; + groupAffinity.Group = index; + KeSetSystemGroupAffinityThreadPtr (&groupAffinity, NULL); + } +} void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes) { @@ -4501,7 +4644,7 @@ void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes) void *AllocateMemoryWithTimeout (size_t size, int retryDelay, int timeout) { LARGE_INTEGER waitInterval; - waitInterval.QuadPart = retryDelay * -10000; + waitInterval.QuadPart = ((LONGLONG)retryDelay) * -10000; ASSERT (KeGetCurrentIrql() <= APC_LEVEL); ASSERT (retryDelay > 0 && retryDelay <= timeout); @@ -4684,6 +4827,65 @@ NTSTATUS ReadRegistryConfigFlags (BOOL driverEntry) TCfree (data); } + if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, VC_ENCRYPTION_IO_REQUEST_COUNT, &data))) + { + if (data->Type == REG_DWORD) + EncryptionIoRequestCount = *(uint32 *) data->Data; + + TCfree (data); + } + + if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, VC_ENCRYPTION_ITEM_COUNT, &data))) + { + if (data->Type == REG_DWORD) + EncryptionItemCount = *(uint32 *) data->Data; + + TCfree (data); + } + + if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, VC_ENCRYPTION_FRAGMENT_SIZE, &data))) + { + if (data->Type == REG_DWORD) + EncryptionFragmentSize = *(uint32 *) data->Data; + + TCfree (data); + } + + if (driverEntry) + { + if (EncryptionIoRequestCount < TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT) + EncryptionIoRequestCount = TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT; + else if (EncryptionIoRequestCount > TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_MAX_COUNT) + EncryptionIoRequestCount = TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_MAX_COUNT; + + if ((EncryptionItemCount == 0) || (EncryptionItemCount > (EncryptionIoRequestCount / 2))) + EncryptionItemCount = EncryptionIoRequestCount / 2; + + /* EncryptionFragmentSize value in registry is expressed in KiB */ + /* Maximum allowed value for EncryptionFragmentSize is 2048 KiB */ + EncryptionFragmentSize *= 1024; + if (EncryptionFragmentSize == 0) + EncryptionFragmentSize = TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + else if (EncryptionFragmentSize > (8 * TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE)) + EncryptionFragmentSize = 8 * TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + + + } + + if (driverEntry && NT_SUCCESS (TCReadRegistryKey (&name, VC_ERASE_KEYS_SHUTDOWN, &data))) + { + if (data->Type == REG_DWORD) + { + if (*((uint32 *) data->Data)) + EraseKeysOnShutdown = TRUE; + else + EraseKeysOnShutdown = FALSE; + } + + TCfree (data); + } + + return status; } @@ -4873,7 +5075,7 @@ BOOL IsOSAtLeast (OSVersionEnum reqMinOS) >= (major << 16 | minor << 8)); } -NTSTATUS NTAPI KeSaveExtendedProcessorState ( +NTSTATUS NTAPI KeSaveExtendedProcessorStateVC ( __in ULONG64 Mask, PXSTATE_SAVE XStateSave ) @@ -4888,7 +5090,7 @@ NTSTATUS NTAPI KeSaveExtendedProcessorState ( } } -VOID NTAPI KeRestoreExtendedProcessorState ( +VOID NTAPI KeRestoreExtendedProcessorStateVC ( PXSTATE_SAVE XStateSave ) { |