From fdf7888ab3675a267e06e2f3acceeedfa5b74f62 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Wed, 14 Jul 2021 23:57:00 +0200 Subject: Windows: Reduce time of mount with PRF auto-detection --- src/Common/EncryptionThreadPool.c | 69 ++++++++++++++++++++++++++++++++++++--- src/Common/EncryptionThreadPool.h | 4 ++- src/Common/Volumes.c | 68 ++++++++++++++++++++++++-------------- 3 files changed, 112 insertions(+), 29 deletions(-) (limited to 'src/Common') diff --git a/src/Common/EncryptionThreadPool.c b/src/Common/EncryptionThreadPool.c index 10052796..32782bdc 100644 --- a/src/Common/EncryptionThreadPool.c +++ b/src/Common/EncryptionThreadPool.c @@ -102,12 +102,22 @@ typedef struct EncryptionThreadPoolWorkItemStruct int IterationCount; TC_EVENT *NoOutstandingWorkItemEvent; LONG *OutstandingWorkItemCount; - char *Password; + CRYPTOPP_ALIGN_DATA(16) char Password[MAX_PASSWORD]; int PasswordLength; int Pkcs5Prf; - char *Salt; + char Salt[PKCS5_SALT_SIZE]; } KeyDerivation; + + struct + { + TC_EVENT *KeyDerivationCompletedEvent; + TC_EVENT *NoOutstandingWorkItemEvent; + LONG *outstandingWorkItemCount; + void* keyDerivationWorkItems; + int keyDerivationWorkItemsSize; + + } ReadVolumeHeaderFinalization; }; } EncryptionThreadPoolWorkItem; @@ -275,6 +285,25 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg) TC_SET_EVENT (WorkItemCompletedEvent); continue; + case ReadVolumeHeaderFinalizationWork: + TC_WAIT_EVENT (*(workItem->ReadVolumeHeaderFinalization.NoOutstandingWorkItemEvent)); + + if (workItem->ReadVolumeHeaderFinalization.keyDerivationWorkItems) + { + burn (workItem->ReadVolumeHeaderFinalization.keyDerivationWorkItems, workItem->ReadVolumeHeaderFinalization.keyDerivationWorkItemsSize); + TCfree (workItem->ReadVolumeHeaderFinalization.keyDerivationWorkItems); + } + +#if !defined(DEVICE_DRIVER) + CloseHandle (*(workItem->ReadVolumeHeaderFinalization.KeyDerivationCompletedEvent)); + CloseHandle (*(workItem->ReadVolumeHeaderFinalization.NoOutstandingWorkItemEvent)); +#endif + TCfree (workItem->ReadVolumeHeaderFinalization.KeyDerivationCompletedEvent); + TCfree (workItem->ReadVolumeHeaderFinalization.NoOutstandingWorkItemEvent); + TCfree (workItem->ReadVolumeHeaderFinalization.outstandingWorkItemCount); + SetWorkItemState (workItem, WorkItemFree); + TC_SET_EVENT (WorkItemCompletedEvent); + continue; default: TC_THROW_FATAL_EXCEPTION; } @@ -515,10 +544,10 @@ void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT workItem->KeyDerivation.IterationCount = iterationCount; workItem->KeyDerivation.NoOutstandingWorkItemEvent = noOutstandingWorkItemEvent; workItem->KeyDerivation.OutstandingWorkItemCount = outstandingWorkItemCount; - workItem->KeyDerivation.Password = password; + memcpy (workItem->KeyDerivation.Password, password, passwordLength); workItem->KeyDerivation.PasswordLength = passwordLength; workItem->KeyDerivation.Pkcs5Prf = pkcs5Prf; - workItem->KeyDerivation.Salt = salt; + memcpy (workItem->KeyDerivation.Salt, salt, PKCS5_SALT_SIZE); InterlockedIncrement (outstandingWorkItemCount); TC_CLEAR_EVENT (*noOutstandingWorkItemEvent); @@ -528,6 +557,38 @@ void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT TC_RELEASE_MUTEX (&EnqueueMutex); } +void EncryptionThreadPoolBeginReadVolumeHeaderFinalization (TC_EVENT *keyDerivationCompletedEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG* outstandingWorkItemCount, void* keyDerivationWorkItems, int keyDerivationWorkItemsSize) +{ + EncryptionThreadPoolWorkItem *workItem; + + if (!ThreadPoolRunning) + TC_THROW_FATAL_EXCEPTION; + + TC_ACQUIRE_MUTEX (&EnqueueMutex); + + workItem = &WorkItemQueue[EnqueuePosition++]; + if (EnqueuePosition >= ThreadQueueSize) + EnqueuePosition = 0; + + while (GetWorkItemState (workItem) != WorkItemFree) + { + TC_WAIT_EVENT (WorkItemCompletedEvent); + } + + workItem->Type = ReadVolumeHeaderFinalizationWork; + workItem->ReadVolumeHeaderFinalization.NoOutstandingWorkItemEvent = noOutstandingWorkItemEvent; +#if !defined(DEVICE_DRIVER) + workItem->ReadVolumeHeaderFinalization.KeyDerivationCompletedEvent = keyDerivationCompletedEvent; +#endif + workItem->ReadVolumeHeaderFinalization.keyDerivationWorkItems = keyDerivationWorkItems; + workItem->ReadVolumeHeaderFinalization.keyDerivationWorkItemsSize = keyDerivationWorkItemsSize; + workItem->ReadVolumeHeaderFinalization.outstandingWorkItemCount = outstandingWorkItemCount; + + SetWorkItemState (workItem, WorkItemReady); + TC_SET_EVENT (WorkItemReadyEvent); + TC_RELEASE_MUTEX (&EnqueueMutex); +} + void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo) { diff --git a/src/Common/EncryptionThreadPool.h b/src/Common/EncryptionThreadPool.h index 161fb7ce..9cb3ffa7 100644 --- a/src/Common/EncryptionThreadPool.h +++ b/src/Common/EncryptionThreadPool.h @@ -24,7 +24,8 @@ typedef enum { EncryptDataUnitsWork, DecryptDataUnitsWork, - DeriveKeyWork + DeriveKeyWork, + ReadVolumeHeaderFinalizationWork } EncryptionThreadPoolWorkType; #ifndef DEVICE_DRIVER @@ -32,6 +33,7 @@ size_t GetCpuCount (WORD* pGroupCount); #endif void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, char *password, int passwordLength, char *salt, int iterationCount, char *derivedKey); +void EncryptionThreadPoolBeginReadVolumeHeaderFinalization (TC_EVENT *keyDerivationCompletedEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG* outstandingWorkItemCount, void* keyDerivationWorkItems, int keyDerivationWorkItemsSize); void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo); BOOL EncryptionThreadPoolStart (size_t encryptionFreeCpuCount); void EncryptionThreadPoolStop (); diff --git a/src/Common/Volumes.c b/src/Common/Volumes.c index d3001a94..37fa481c 100644 --- a/src/Common/Volumes.c +++ b/src/Common/Volumes.c @@ -179,12 +179,12 @@ int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, int int primaryKeyOffset; int pkcs5PrfCount = LAST_PRF_ID - FIRST_PRF_ID + 1; #if !defined(_UEFI) - TC_EVENT keyDerivationCompletedEvent; - TC_EVENT noOutstandingWorkItemEvent; + TC_EVENT *keyDerivationCompletedEvent = NULL; + TC_EVENT *noOutstandingWorkItemEvent = NULL; KeyDerivationWorkItem *keyDerivationWorkItems = NULL; KeyDerivationWorkItem *item; size_t encryptionThreadCount = GetEncryptionThreadCount(); - LONG outstandingWorkItemCount = 0; + LONG *outstandingWorkItemCount = NULL; int i; #endif size_t queuedWorkItems = 0; @@ -218,29 +218,60 @@ int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, int /* use thread pool only if no PRF was specified */ if ((selected_pkcs5_prf == 0) && (encryptionThreadCount > 1)) { + keyDerivationCompletedEvent = TCalloc (sizeof (TC_EVENT)); + if (!keyDerivationCompletedEvent) + return ERR_OUTOFMEMORY; + + noOutstandingWorkItemEvent = TCalloc (sizeof (TC_EVENT)); + if (!noOutstandingWorkItemEvent) + { + TCfree(keyDerivationCompletedEvent); + return ERR_OUTOFMEMORY; + } + + outstandingWorkItemCount = TCalloc (sizeof (LONG)); + if (!outstandingWorkItemCount) + { + TCfree(keyDerivationCompletedEvent); + TCfree(noOutstandingWorkItemEvent); + return ERR_OUTOFMEMORY; + } + keyDerivationWorkItems = TCalloc (sizeof (KeyDerivationWorkItem) * pkcs5PrfCount); if (!keyDerivationWorkItems) + { + TCfree(keyDerivationCompletedEvent); + TCfree(noOutstandingWorkItemEvent); + TCfree(outstandingWorkItemCount); return ERR_OUTOFMEMORY; + } for (i = 0; i < pkcs5PrfCount; ++i) keyDerivationWorkItems[i].Free = TRUE; + *outstandingWorkItemCount = 0; #ifdef DEVICE_DRIVER - KeInitializeEvent (&keyDerivationCompletedEvent, SynchronizationEvent, FALSE); - KeInitializeEvent (&noOutstandingWorkItemEvent, SynchronizationEvent, TRUE); + KeInitializeEvent (keyDerivationCompletedEvent, SynchronizationEvent, FALSE); + KeInitializeEvent (noOutstandingWorkItemEvent, SynchronizationEvent, TRUE); #else - keyDerivationCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - if (!keyDerivationCompletedEvent) + *keyDerivationCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + if (!*keyDerivationCompletedEvent) { TCfree (keyDerivationWorkItems); + TCfree(keyDerivationCompletedEvent); + TCfree(noOutstandingWorkItemEvent); + TCfree(outstandingWorkItemCount); return ERR_OUTOFMEMORY; } - noOutstandingWorkItemEvent = CreateEvent (NULL, FALSE, TRUE, NULL); - if (!noOutstandingWorkItemEvent) + *noOutstandingWorkItemEvent = CreateEvent (NULL, FALSE, TRUE, NULL); + if (!*noOutstandingWorkItemEvent) { CloseHandle (keyDerivationCompletedEvent); TCfree (keyDerivationWorkItems); + TCfree(keyDerivationCompletedEvent); + TCfree(noOutstandingWorkItemEvent); + TCfree(outstandingWorkItemCount); return ERR_OUTOFMEMORY; } #endif @@ -283,8 +314,8 @@ int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, int item->KeyReady = FALSE; item->Pkcs5Prf = enqPkcs5Prf; - EncryptionThreadPoolBeginKeyDerivation (&keyDerivationCompletedEvent, &noOutstandingWorkItemEvent, - &item->KeyReady, &outstandingWorkItemCount, enqPkcs5Prf, keyInfo.userKey, + EncryptionThreadPoolBeginKeyDerivation (keyDerivationCompletedEvent, noOutstandingWorkItemEvent, + &item->KeyReady, outstandingWorkItemCount, enqPkcs5Prf, keyInfo.userKey, keyInfo.keyLength, keyInfo.salt, get_pkcs5_iteration_count (enqPkcs5Prf, pim, truecryptMode, bBoot), item->DerivedKey); ++queuedWorkItems; @@ -317,7 +348,7 @@ int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, int } if (queuedWorkItems > 0) - TC_WAIT_EVENT (keyDerivationCompletedEvent); + TC_WAIT_EVENT (*keyDerivationCompletedEvent); } continue; KeyReady: ; @@ -587,18 +618,7 @@ ret: #if !defined(_UEFI) if ((selected_pkcs5_prf == 0) && (encryptionThreadCount > 1)) { - TC_WAIT_EVENT (noOutstandingWorkItemEvent); - - if (keyDerivationWorkItems) - { - burn (keyDerivationWorkItems, sizeof (KeyDerivationWorkItem) * pkcs5PrfCount); - TCfree (keyDerivationWorkItems); - } - -#if !defined(DEVICE_DRIVER) - CloseHandle (keyDerivationCompletedEvent); - CloseHandle (noOutstandingWorkItemEvent); -#endif + EncryptionThreadPoolBeginReadVolumeHeaderFinalization (keyDerivationCompletedEvent, noOutstandingWorkItemEvent, outstandingWorkItemCount, keyDerivationWorkItems, sizeof (KeyDerivationWorkItem) * pkcs5PrfCount); } #endif return status; -- cgit v1.2.3