From 5640de3584aa5d3ab327ecd7345ded2e0096b464 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Mon, 20 Dec 2021 00:14:24 +0100 Subject: Windows Driver: Add registry settings to control driver internal encryption queue Under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\veracrypt: - VeraCryptEncryptionFragmentSize (REG_DWORD): size of encryption data fragment in KiB. Default is 256. - VeraCryptEncryptionIoRequestCount (REG_DWORD): maximum number of parallel I/O requests. Default is 16. - VeraCryptEncryptionItemCount (REG_DWORD): maximum number of encryption queue items processed in parallel. Default is 8. --- src/Driver/EncryptedIoQueue.c | 97 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 19 deletions(-) (limited to 'src/Driver/EncryptedIoQueue.c') diff --git a/src/Driver/EncryptedIoQueue.c b/src/Driver/EncryptedIoQueue.c index 85b9a330..6900fc0d 100644 --- a/src/Driver/EncryptedIoQueue.c +++ b/src/Driver/EncryptedIoQueue.c @@ -775,9 +775,10 @@ static VOID MainThreadProc (PVOID threadArg) while (dataRemaining > 0) { - BOOL isLastFragment = dataRemaining <= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + ULONG queueFragmentSize = queue->FragmentSize; + BOOL isLastFragment = dataRemaining <= queueFragmentSize; - ULONG dataFragmentLength = isLastFragment ? dataRemaining : TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + ULONG dataFragmentLength = isLastFragment ? dataRemaining : queueFragmentSize; activeFragmentBuffer = (activeFragmentBuffer == queue->FragmentBufferA ? queue->FragmentBufferB : queue->FragmentBufferA); InterlockedIncrement (&queue->IoThreadPendingRequestCount); @@ -847,9 +848,9 @@ static VOID MainThreadProc (PVOID threadArg) if (isLastFragment) break; - dataRemaining -= TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; - dataBuffer += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; - fragmentOffset.QuadPart += TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + dataRemaining -= queueFragmentSize; + dataBuffer += queueFragmentSize; + fragmentOffset.QuadPart += queueFragmentSize; } } } @@ -971,7 +972,11 @@ NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue) { NTSTATUS status; EncryptedIoQueueBuffer *buffer; - int i; + int i, preallocatedIoRequestCount, preallocatedItemCount, fragmentSize; + + preallocatedIoRequestCount = EncryptionIoRequestCount; + preallocatedItemCount = EncryptionItemCount; + fragmentSize = EncryptionFragmentSize; queue->StartPending = TRUE; queue->ThreadExitRequested = FALSE; @@ -986,30 +991,84 @@ NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue) KeInitializeEvent (&queue->PoolBufferFreeEvent, SynchronizationEvent, FALSE); KeInitializeEvent (&queue->QueueResumedEvent, SynchronizationEvent, FALSE); - queue->FragmentBufferA = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); +retry_fragmentAllocate: + queue->FragmentBufferA = TCalloc (fragmentSize); if (!queue->FragmentBufferA) - goto noMemory; + { + if (fragmentSize > TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE) + { + fragmentSize = TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + goto retry_fragmentAllocate; + } + else + goto noMemory; + } - queue->FragmentBufferB = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); + queue->FragmentBufferB = TCalloc (fragmentSize); if (!queue->FragmentBufferB) - goto noMemory; - - KeInitializeEvent (&queue->FragmentBufferAFreeEvent, SynchronizationEvent, TRUE); - KeInitializeEvent (&queue->FragmentBufferBFreeEvent, SynchronizationEvent, TRUE); + { + if (fragmentSize > TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE) + { + fragmentSize = TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + TCfree (queue->FragmentBufferA); + queue->FragmentBufferA = NULL; + goto retry_fragmentAllocate; + } + else + goto noMemory; + } queue->ReadAheadBufferValid = FALSE; - queue->ReadAheadBuffer = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE); + queue->ReadAheadBuffer = TCalloc (fragmentSize); if (!queue->ReadAheadBuffer) - goto noMemory; + { + if (fragmentSize > TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE) + { + fragmentSize = TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE; + TCfree (queue->FragmentBufferA); + TCfree (queue->FragmentBufferB); + queue->FragmentBufferA = NULL; + queue->FragmentBufferB = NULL; + goto retry_fragmentAllocate; + } + else + goto noMemory; + } + + queue->FragmentSize = fragmentSize; + + KeInitializeEvent (&queue->FragmentBufferAFreeEvent, SynchronizationEvent, TRUE); + KeInitializeEvent (&queue->FragmentBufferBFreeEvent, SynchronizationEvent, TRUE); +retry_preallocated: // Preallocate buffers - for (i = 0; i < TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT; ++i) + for (i = 0; i < preallocatedIoRequestCount; ++i) { - if (i < TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT && !GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem))) - goto noMemory; + if (i < preallocatedItemCount && !GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem))) + { + if (preallocatedItemCount > TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT) + { + preallocatedItemCount = TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT; + preallocatedIoRequestCount = TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT; + FreePoolBuffers (queue); + goto retry_preallocated; + } + else + goto noMemory; + } if (!GetPoolBuffer (queue, sizeof (EncryptedIoRequest))) - goto noMemory; + { + if (preallocatedIoRequestCount > TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT) + { + preallocatedItemCount = TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT; + preallocatedIoRequestCount = TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT; + FreePoolBuffers (queue); + goto retry_preallocated; + } + else + goto noMemory; + } } for (buffer = queue->FirstPoolBuffer; buffer != NULL; buffer = buffer->NextBuffer) -- cgit v1.2.3