mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2026-07-23 16:42:49 +00:00
Linux: parallelize header KDF autodetection
Extend the Unix encryption thread pool to run key-derivation work items and use it when mounting volumes without an explicitly selected KDF. This brings Linux/macOS header PRF autodetection closer to the Windows path while keeping selected-KDF mounts unchanged. Fixes #1610.
This commit is contained in:
@@ -23,9 +23,62 @@
|
||||
#include "Platform/SystemLog.h"
|
||||
#include "Common/Crypto.h"
|
||||
#include "EncryptionThreadPool.h"
|
||||
#include "Pkcs5Kdf.h"
|
||||
|
||||
namespace VeraCrypt
|
||||
{
|
||||
EncryptionThreadPool::KeyDerivationWorkItem::KeyDerivationWorkItem (shared_ptr <Pkcs5Kdf> kdf, size_t derivedKeySize)
|
||||
: Completed (false), DerivedKey (derivedKeySize), Kdf (kdf), Processed (false), Result (0)
|
||||
{
|
||||
}
|
||||
|
||||
EncryptionThreadPool::KeyDerivationWorkItem::~KeyDerivationWorkItem ()
|
||||
{
|
||||
}
|
||||
|
||||
void EncryptionThreadPool::BeginKeyDerivation (KeyDerivationWorkItem &keyDerivationWorkItem, const VolumePassword &password, int pim, const ConstBufferPtr &salt, SyncEvent &completionEvent, SyncEvent &noOutstandingWorkItemEvent, SharedVal <size_t> &outstandingWorkItemCount, long volatile *abortFlag)
|
||||
{
|
||||
if (!ThreadPoolRunning)
|
||||
throw NotInitialized (SRC_POS);
|
||||
|
||||
ScopeLock lock (EnqueueMutex);
|
||||
|
||||
WorkItem *workItem = &WorkItemQueue[EnqueuePosition++];
|
||||
|
||||
if (EnqueuePosition >= QueueSize)
|
||||
EnqueuePosition = 0;
|
||||
|
||||
while (workItem->State != WorkItem::State::Free)
|
||||
{
|
||||
WorkItemCompletedEvent.Wait();
|
||||
}
|
||||
|
||||
keyDerivationWorkItem.Completed.Set (false);
|
||||
keyDerivationWorkItem.ItemException.reset();
|
||||
keyDerivationWorkItem.Processed = false;
|
||||
keyDerivationWorkItem.Result = 0;
|
||||
|
||||
workItem->Type = WorkType::DeriveKey;
|
||||
workItem->KeyDerivation.AbortFlag = abortFlag;
|
||||
workItem->KeyDerivation.CompletionEvent = &completionEvent;
|
||||
workItem->KeyDerivation.NoOutstandingWorkItemEvent = &noOutstandingWorkItemEvent;
|
||||
workItem->KeyDerivation.OutstandingWorkItemCount = &outstandingWorkItemCount;
|
||||
workItem->KeyDerivation.Password = &password;
|
||||
workItem->KeyDerivation.Pim = pim;
|
||||
workItem->KeyDerivation.Salt = salt.Get();
|
||||
workItem->KeyDerivation.SaltSize = salt.Size();
|
||||
workItem->KeyDerivation.WorkItem = &keyDerivationWorkItem;
|
||||
|
||||
{
|
||||
ScopeLock outstandingWorkItemLock (KeyDerivationCompletionMutex);
|
||||
if (outstandingWorkItemCount.Increment() == 1)
|
||||
noOutstandingWorkItemEvent.Reset();
|
||||
}
|
||||
|
||||
workItem->State.Set (WorkItem::State::Ready);
|
||||
WorkItemReadyEvent.Signal();
|
||||
}
|
||||
|
||||
void EncryptionThreadPool::DoWork (WorkType::Enum type, const EncryptionMode *encryptionMode, uint8 *data, uint64 startUnitNo, uint64 unitCount, size_t sectorSize)
|
||||
{
|
||||
size_t fragmentCount;
|
||||
@@ -272,21 +325,54 @@ namespace VeraCrypt
|
||||
workItem->Encryption.Mode->EncryptSectorsCurrentThread (workItem->Encryption.Data, workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.SectorSize);
|
||||
break;
|
||||
|
||||
case WorkType::DeriveKey:
|
||||
{
|
||||
KeyDerivationWorkItem *keyDerivationWorkItem = workItem->KeyDerivation.WorkItem;
|
||||
if (workItem->KeyDerivation.AbortFlag && *workItem->KeyDerivation.AbortFlag)
|
||||
keyDerivationWorkItem->Result = ERR_USER_ABORT;
|
||||
else
|
||||
keyDerivationWorkItem->Result = keyDerivationWorkItem->Kdf->DeriveKey (keyDerivationWorkItem->DerivedKey, *workItem->KeyDerivation.Password, workItem->KeyDerivation.Pim, ConstBufferPtr (workItem->KeyDerivation.Salt, workItem->KeyDerivation.SaltSize), workItem->KeyDerivation.AbortFlag);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ParameterIncorrect (SRC_POS);
|
||||
}
|
||||
}
|
||||
catch (Exception &e)
|
||||
{
|
||||
workItem->FirstFragment->ItemException.reset (e.CloneNew());
|
||||
if (workItem->Type == WorkType::DeriveKey)
|
||||
workItem->KeyDerivation.WorkItem->ItemException.reset (e.CloneNew());
|
||||
else
|
||||
workItem->FirstFragment->ItemException.reset (e.CloneNew());
|
||||
}
|
||||
catch (exception &e)
|
||||
{
|
||||
workItem->FirstFragment->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
|
||||
if (workItem->Type == WorkType::DeriveKey)
|
||||
workItem->KeyDerivation.WorkItem->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
|
||||
else
|
||||
workItem->FirstFragment->ItemException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
workItem->FirstFragment->ItemException.reset (new UnknownException (SRC_POS));
|
||||
if (workItem->Type == WorkType::DeriveKey)
|
||||
workItem->KeyDerivation.WorkItem->ItemException.reset (new UnknownException (SRC_POS));
|
||||
else
|
||||
workItem->FirstFragment->ItemException.reset (new UnknownException (SRC_POS));
|
||||
}
|
||||
|
||||
if (workItem->Type == WorkType::DeriveKey)
|
||||
{
|
||||
workItem->KeyDerivation.WorkItem->Completed.Set (true);
|
||||
workItem->KeyDerivation.CompletionEvent->Signal();
|
||||
{
|
||||
ScopeLock outstandingWorkItemLock (KeyDerivationCompletionMutex);
|
||||
if (workItem->KeyDerivation.OutstandingWorkItemCount->Decrement() == 0)
|
||||
workItem->KeyDerivation.NoOutstandingWorkItemEvent->Signal();
|
||||
}
|
||||
workItem->State.Set (WorkItem::State::Free);
|
||||
WorkItemCompletedEvent.Signal();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (workItem != workItem->FirstFragment)
|
||||
@@ -321,6 +407,7 @@ namespace VeraCrypt
|
||||
|
||||
Mutex EncryptionThreadPool::EnqueueMutex;
|
||||
Mutex EncryptionThreadPool::DequeueMutex;
|
||||
Mutex EncryptionThreadPool::KeyDerivationCompletionMutex;
|
||||
|
||||
SyncEvent EncryptionThreadPool::WorkItemReadyEvent;
|
||||
SyncEvent EncryptionThreadPool::WorkItemCompletedEvent;
|
||||
|
||||
Reference in New Issue
Block a user