diff --git a/src/Driver/DriveFilter.c b/src/Driver/DriveFilter.c index eefddb63..0e5b5730 100644 --- a/src/Driver/DriveFilter.c +++ b/src/Driver/DriveFilter.c @@ -74,6 +74,82 @@ static NTSTATUS DecoySystemWipeResult; static uint64 BootArgsRegionsDefault[] = { EFI_BOOTARGS_REGIONS_DEFAULT }; static uint64 BootArgsRegionsEFI[] = { EFI_BOOTARGS_REGIONS_EFI }; +static BOOL GetHiddenSystemPartitionOffset (uint64 *hiddenPartitionOffset) +{ + uint64 hiddenOffset = BootArgs.HiddenSystemPartitionStart; + + if (hiddenOffset == 0 + || hiddenOffset > (uint64) _I64_MAX + || (hiddenOffset % TC_SECTOR_SIZE_BIOS) != 0) + return FALSE; + + *hiddenPartitionOffset = hiddenOffset; + return TRUE; +} + +static BOOL GetHiddenSystemPartitionOffsets (uint64 *hiddenPartitionOffset, uint64 *decoyPartitionOffset) +{ + uint64 hiddenOffset; + uint64 decoyOffset = BootArgs.DecoySystemPartitionStart; + + if (!GetHiddenSystemPartitionOffset (&hiddenOffset) + || decoyOffset > (uint64) _I64_MAX + || (decoyOffset % TC_SECTOR_SIZE_BIOS) != 0 + || decoyOffset >= hiddenOffset) + return FALSE; + + *hiddenPartitionOffset = hiddenOffset; + *decoyPartitionOffset = decoyOffset; + return TRUE; +} + +static BOOL GetHiddenVolumeHeaderOffset (LARGE_INTEGER *offset) +{ + uint64 hiddenPartitionOffset; + uint64 hiddenHeaderOffset; + + if (!GetHiddenSystemPartitionOffset (&hiddenPartitionOffset) + || hiddenPartitionOffset > ((uint64) _I64_MAX - TC_HIDDEN_VOLUME_HEADER_OFFSET)) + return FALSE; + + hiddenHeaderOffset = hiddenPartitionOffset + TC_HIDDEN_VOLUME_HEADER_OFFSET; + if (hiddenHeaderOffset > ((uint64) _I64_MAX - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE)) + return FALSE; + + offset->QuadPart = (LONGLONG) hiddenHeaderOffset; + return TRUE; +} + +static BOOL GetHiddenSystemRemapOffsets (PCRYPTO_INFO cryptoInfo, int64 *hiddenVolumeStartOffset, int64 *remappedAreaOffset, int64 *remappedAreaDataUnitOffset) +{ + uint64 hiddenOffset; + uint64 decoyOffset; + uint64 encryptedAreaStart = cryptoInfo->EncryptedAreaStart.Value; + uint64 encryptedAreaLength = cryptoInfo->EncryptedAreaLength.Value; + uint64 hiddenToDecoyDistance; + uint64 hiddenVolumeStart; + + if (!GetHiddenSystemPartitionOffsets (&hiddenOffset, &decoyOffset) + || encryptedAreaStart > (uint64) _I64_MAX + || encryptedAreaLength > (uint64) _I64_MAX + || cryptoInfo->VolumeSize.Value > (uint64) _I64_MAX + || (encryptedAreaStart % ENCRYPTION_DATA_UNIT_SIZE) != 0) + return FALSE; + + hiddenToDecoyDistance = hiddenOffset - decoyOffset; + if (cryptoInfo->VolumeSize.Value > hiddenToDecoyDistance + || encryptedAreaLength > hiddenToDecoyDistance + || encryptedAreaStart > ((uint64) _I64_MAX - hiddenOffset)) + return FALSE; + + hiddenVolumeStart = hiddenOffset + encryptedAreaStart; + + *hiddenVolumeStartOffset = (int64) hiddenVolumeStart; + *remappedAreaOffset = (int64) (hiddenVolumeStart - decoyOffset); + *remappedAreaDataUnitOffset = (int64) (encryptedAreaStart / ENCRYPTION_DATA_UNIT_SIZE) - (int64) (decoyOffset / ENCRYPTION_DATA_UNIT_SIZE); + return TRUE; +} + NTSTATUS LoadBootArguments (BOOL bIsEfi) { NTSTATUS status = STATUS_UNSUCCESSFUL; @@ -410,7 +486,6 @@ static void ComputeBootLoaderFingerprint(PDEVICE_OBJECT LowerDeviceObject, uint8 static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, __unaligned uint32 *headerSaltCrc32) { BOOL hiddenVolume = (BootArgs.HiddenSystemPartitionStart != 0); - int64 hiddenHeaderOffset = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; NTSTATUS status; LARGE_INTEGER offset; unsigned char *header; @@ -462,7 +537,17 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, if (!header) return STATUS_INSUFFICIENT_RESOURCES; - offset.QuadPart = hiddenVolume ? hiddenHeaderOffset : TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; + if (hiddenVolume) + { + if (!GetHiddenVolumeHeaderOffset (&offset)) + { + status = STATUS_INVALID_PARAMETER; + goto ret; + } + } + else + offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; + Dump ("Reading volume header at %I64u\n", offset.QuadPart); status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); @@ -527,22 +612,25 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, if (Extension->Queue.CryptoInfo->hiddenVolume) { - int64 hiddenPartitionOffset = BootArgs.HiddenSystemPartitionStart; - Dump ("Hidden volume start offset = %I64d\n", Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + hiddenPartitionOffset); + int64 hiddenVolumeStartOffset; + int64 remappedAreaOffset; + int64 remappedAreaDataUnitOffset; + + if (!GetHiddenSystemRemapOffsets (Extension->Queue.CryptoInfo, &hiddenVolumeStartOffset, &remappedAreaOffset, &remappedAreaDataUnitOffset)) + { + // We have already erased boot loader scheduled keys. + TC_THROW_FATAL_EXCEPTION; + } + + Dump ("Hidden volume start offset = %I64d\n", hiddenVolumeStartOffset); Extension->HiddenSystem = TRUE; Extension->Queue.RemapEncryptedArea = TRUE; - Extension->Queue.RemappedAreaOffset = hiddenPartitionOffset + Extension->Queue.CryptoInfo->EncryptedAreaStart.Value - BootArgs.DecoySystemPartitionStart; - Extension->Queue.RemappedAreaDataUnitOffset = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value / ENCRYPTION_DATA_UNIT_SIZE - BootArgs.DecoySystemPartitionStart / ENCRYPTION_DATA_UNIT_SIZE; + Extension->Queue.RemappedAreaOffset = remappedAreaOffset; + Extension->Queue.RemappedAreaDataUnitOffset = remappedAreaDataUnitOffset; Extension->Queue.CryptoInfo->EncryptedAreaStart.Value = BootArgs.DecoySystemPartitionStart; - - if (Extension->Queue.CryptoInfo->VolumeSize.Value > hiddenPartitionOffset - BootArgs.DecoySystemPartitionStart) - { - // we have already erased boot loader scheduled keys - TC_THROW_FATAL_EXCEPTION; - } Dump ("RemappedAreaOffset = %I64d\n", Extension->Queue.RemappedAreaOffset); Dump ("RemappedAreaDataUnitOffset = %I64d\n", Extension->Queue.RemappedAreaDataUnitOffset); @@ -585,17 +673,24 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, if(crc == crcSaved){ if(DeList->DE[DE_IDX_PWDCACHE].Type == DE_PwdCache) { uint64 sector = 0; - DCS_DEP_PWD_CACHE* pwdCache = (DCS_DEP_PWD_CACHE*)(BootSecRegionData + DeList->DE[DE_IDX_PWDCACHE].Sectors.Offset); - DecryptDataUnits((unsigned char*)pwdCache, (UINT64_STRUCT*)§or, 1, Extension->Queue.CryptoInfo); - crcSaved = pwdCache->CRC; - pwdCache->CRC = 0; - crc = GetCrc32((unsigned char*)pwdCache, 512); - if(crcSaved == crc && pwdCache->Count < CACHE_SIZE){ - uint32 i; - for(i = 0; iCount; ++i){ - if (CacheBootPassword && pwdCache->Pwd[i].Length > 0) { - int cachedPim = CacheBootPim? (int) (pwdCache->Pim[i]) : 0; - AddLegacyPasswordToCache (&pwdCache->Pwd[i], cachedPim); + uint32 pwdCacheOffset = DeList->DE[DE_IDX_PWDCACHE].Offset; + if ((DeList->DE[DE_IDX_PWDCACHE].Length >= sizeof(DCS_DEP_PWD_CACHE)) + && ((pwdCacheOffset % TC_SECTOR_SIZE_BIOS) == 0) + && (pwdCacheOffset <= BootSecRegionSize) + && ((BootSecRegionSize - pwdCacheOffset) >= sizeof(DCS_DEP_PWD_CACHE))) + { + DCS_DEP_PWD_CACHE* pwdCache = (DCS_DEP_PWD_CACHE*)(BootSecRegionData + pwdCacheOffset); + DecryptDataUnits((unsigned char*)pwdCache, (UINT64_STRUCT*)§or, 1, Extension->Queue.CryptoInfo); + crcSaved = pwdCache->CRC; + pwdCache->CRC = 0; + crc = GetCrc32((unsigned char*)pwdCache, 512); + if(crcSaved == crc && pwdCache->Count < CACHE_SIZE){ + uint32 i; + for(i = 0; iCount; ++i){ + if (CacheBootPassword && pwdCache->Pwd[i].Length > 0) { + int cachedPim = CacheBootPim? (int) (pwdCache->Pim[i]) : 0; + AddLegacyPasswordToCache (&pwdCache->Pwd[i], cachedPim); + } } } burn(pwdCache, sizeof(*pwdCache)); @@ -1155,7 +1250,13 @@ void ReopenBootVolumeHeader (PIRP irp) } if (BootDriveFilterExtension->HiddenSystem) - offset.QuadPart = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET; + { + if (!GetHiddenVolumeHeaderOffset (&offset)) + { + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + goto ret; + } + } else offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET; @@ -2378,5 +2479,11 @@ NTSTATUS WriteBootDriveSector (PIRP irp, PIO_STACK_LOCATION irpSp) return STATUS_INVALID_PARAMETER; request = (WriteBootDriveSectorRequest *) irp->AssociatedIrp.SystemBuffer; + if (request->Offset.QuadPart < 0 + || (request->Offset.QuadPart % TC_SECTOR_SIZE_BIOS) != 0 + || BootDriveLength.QuadPart < (LONGLONG) sizeof (request->Data) + || request->Offset.QuadPart > BootDriveLength.QuadPart - (LONGLONG) sizeof (request->Data)) + return STATUS_INVALID_PARAMETER; + return TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, request->Data, request->Offset, sizeof (request->Data)); } diff --git a/src/Driver/EncryptedIoQueue.c b/src/Driver/EncryptedIoQueue.c index 48138208..51a9600c 100644 --- a/src/Driver/EncryptedIoQueue.c +++ b/src/Driver/EncryptedIoQueue.c @@ -1250,10 +1250,15 @@ NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue) NTSTATUS status; EncryptedIoQueueBuffer *buffer; int i, j, preallocatedIoRequestCount, preallocatedItemCount, fragmentSize; + int maxWorkItems; + SIZE_T workItemPoolSize; preallocatedIoRequestCount = EncryptionIoRequestCount; preallocatedItemCount = EncryptionItemCount; fragmentSize = EncryptionFragmentSize; + maxWorkItems = EncryptionMaxWorkItems; + if (maxWorkItems <= 0 || maxWorkItems > VC_MAX_WORK_ITEMS) + maxWorkItems = VC_MAX_WORK_ITEMS; queue->StartPending = TRUE; queue->ThreadExitRequested = FALSE; @@ -1355,11 +1360,16 @@ retry_preallocated: // Initialize the free work item list InitializeListHead(&queue->FreeWorkItemsList); - KeInitializeSemaphore(&queue->WorkItemSemaphore, EncryptionMaxWorkItems, EncryptionMaxWorkItems); + KeInitializeSemaphore(&queue->WorkItemSemaphore, maxWorkItems, maxWorkItems); KeInitializeSpinLock(&queue->WorkItemLock); - queue->MaxWorkItems = EncryptionMaxWorkItems; - queue->WorkItemPool = (PCOMPLETE_IRP_WORK_ITEM)TCalloc(sizeof(COMPLETE_IRP_WORK_ITEM) * queue->MaxWorkItems); + queue->MaxWorkItems = maxWorkItems; + if (FAILED(SizeTMult(sizeof(COMPLETE_IRP_WORK_ITEM), queue->MaxWorkItems, &workItemPoolSize))) + { + goto noMemory; + } + + queue->WorkItemPool = (PCOMPLETE_IRP_WORK_ITEM)TCalloc(workItemPoolSize); if (!queue->WorkItemPool) { goto noMemory; diff --git a/src/Driver/Ntdriver.c b/src/Driver/Ntdriver.c index 417a2a20..ed30903f 100644 --- a/src/Driver/Ntdriver.c +++ b/src/Driver/Ntdriver.c @@ -4704,6 +4704,8 @@ NTSTATUS ReadRegistryConfigFlags (BOOL driverEntry) if (EncryptionMaxWorkItems == 0) EncryptionMaxWorkItems = VC_MAX_WORK_ITEMS; + else if (EncryptionMaxWorkItems < 0 || EncryptionMaxWorkItems > VC_MAX_WORK_ITEMS) + EncryptionMaxWorkItems = VC_MAX_WORK_ITEMS; }