1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2026-06-09 22:36:59 -05:00

Windows: handle Argon2 derivation failures

This commit is contained in:
Mounir IDRASSI
2026-04-20 16:22:50 +09:00
parent e59eb421fb
commit 49c68ea1ab
49 changed files with 153 additions and 12 deletions
+27 -1
View File
@@ -5729,6 +5729,11 @@ void handleError (HWND hwndDlg, int code, const char* srcPos)
case ERR_CIPHER_INIT_WEAK_KEY:
MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_WEAK_KEY"), srcPos).c_str(), lpszTitle, ICON_HAND);
break;
case ERR_KEY_DERIVATION_FAILED:
MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_KEY_DERIVATION_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND);
break;
case ERR_VOL_ALREADY_MOUNTED:
MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_ALREADY_MOUNTED"), srcPos).c_str(), lpszTitle, ICON_HAND);
break;
@@ -6512,7 +6517,8 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
case ARGON2:
/* test with ARGON2 used as the PRF */
derive_key_argon2 ((const unsigned char*) "passphrase-1234567890", 21, (const unsigned char*)tmp_salt, 64, iterations, memoryCost, dk, MASTER_KEYDATA_SIZE, NULL);
if (derive_key_argon2 ((const unsigned char*) "passphrase-1234567890", 21, (const unsigned char*)tmp_salt, 64, iterations, memoryCost, dk, MASTER_KEYDATA_SIZE, NULL) != 0)
goto key_derivation_error;
break;
}
#endif
@@ -6639,6 +6645,26 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
NormalCursor ();
return TRUE;
key_derivation_error:
if (ci)
crypto_close (ci);
if (lpTestBuffer)
{
VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16));
_aligned_free(lpTestBuffer);
}
NormalCursor ();
EnableWindow (GetDlgItem (hBenchDlg, IDC_PERFORM_BENCHMARK), TRUE);
EnableWindow (GetDlgItem (hBenchDlg, IDCLOSE), TRUE);
MessageBoxW (hwndDlg, GetString ("ERR_KEY_DERIVATION_FAILED"), lpszTitle, ICON_HAND);
return FALSE;
counter_error:
if (ci)
+11 -2
View File
@@ -98,6 +98,7 @@ typedef struct EncryptionThreadPoolWorkItemStruct
{
TC_EVENT *CompletionEvent;
LONG *CompletionFlag;
LONG *DerivationResult;
unsigned char *DerivedKey;
int IterationCount;
int Memorycost;
@@ -244,6 +245,9 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
break;
case DeriveKeyWork:
{
int derivationResult = 0;
switch (workItem->KeyDerivation.Pkcs5Prf)
{
case BLAKE2S:
@@ -272,7 +276,7 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
break;
case ARGON2:
derive_key_argon2(workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
derivationResult = derive_key_argon2(workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.Memorycost, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize(), workItem->KeyDerivation.pAbortKeyDerivation);
break;
@@ -280,6 +284,9 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
TC_THROW_FATAL_EXCEPTION;
}
if (workItem->KeyDerivation.DerivationResult)
InterlockedExchange (workItem->KeyDerivation.DerivationResult, derivationResult);
InterlockedExchange (workItem->KeyDerivation.CompletionFlag, TRUE);
TC_SET_EVENT (*workItem->KeyDerivation.CompletionEvent);
@@ -289,6 +296,7 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
SetWorkItemState (workItem, WorkItemFree);
TC_SET_EVENT (WorkItemCompletedEvent);
continue;
}
case ReadVolumeHeaderFinalizationWork:
TC_WAIT_EVENT (*(workItem->ReadVolumeHeaderFinalization.NoOutstandingWorkItemEvent));
@@ -536,7 +544,7 @@ void EncryptionThreadPoolStop ()
}
void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, unsigned char *password, int passwordLength, unsigned char *salt, int iterationCount, int memoryCost, unsigned char *derivedKey, LONG volatile *pAbortKeyDerivation)
void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, unsigned char *password, int passwordLength, unsigned char *salt, int iterationCount, int memoryCost, unsigned char *derivedKey, LONG *derivationResult, LONG volatile *pAbortKeyDerivation)
{
EncryptionThreadPoolWorkItem *workItem;
@@ -557,6 +565,7 @@ void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT
workItem->Type = DeriveKeyWork;
workItem->KeyDerivation.CompletionEvent = completionEvent;
workItem->KeyDerivation.CompletionFlag = completionFlag;
workItem->KeyDerivation.DerivationResult = derivationResult;
workItem->KeyDerivation.DerivedKey = derivedKey;
workItem->KeyDerivation.IterationCount = iterationCount;
workItem->KeyDerivation.Memorycost = memoryCost;
+2 -1
View File
@@ -32,7 +32,8 @@ typedef enum
size_t GetCpuCount (WORD* pGroupCount);
#endif
void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, unsigned char *password, int passwordLength, unsigned char *salt, int iterationCount, int memoryCost, unsigned char *derivedKey, LONG volatile *pAbortKeyDerivation);
/* derivationResult receives 0 on success; PRFs that can fail store their native nonzero result. */
void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, unsigned char *password, int passwordLength, unsigned char *salt, int iterationCount, int memoryCost, unsigned char *derivedKey, LONG *derivationResult, LONG volatile *pAbortKeyDerivation);
void EncryptionThreadPoolBeginReadVolumeHeaderFinalization (TC_EVENT *keyDerivationCompletedEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG* outstandingWorkItemCount, void* keyInfoBuffer, int keyInfoBufferSize, void* keyDerivationWorkItems, int keyDerivationWorkItemsSize);
void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, uint8 *data, const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo);
BOOL EncryptionThreadPoolStart (size_t encryptionFreeCpuCount);
+1
View File
@@ -1657,6 +1657,7 @@
<entry lang="en" key="IDD_PREFERENCES_TAB_PASSWORD">Password</entry>
<entry lang="en" key="IDC_SECURE_DESKTOP_ENABLE_IME">Enable Input Method Editor (IME) in Secure Desktop</entry>
<entry lang="en" key="ENABLE_IME_IN_SECURE_DESKTOP_WARNING">WARNING: Enable this option only if you are encountering issues when selecting Keyfiles/Tokens under Secure Desktop.</entry>
<entry lang="en" key="ERR_KEY_DERIVATION_FAILED">Key derivation failed. This may be caused by insufficient memory or an interrupted operation.</entry>
</localization>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="VeraCrypt">
+2 -1
View File
@@ -456,7 +456,8 @@ enum
ERR_RAND_INIT_FAILED = 34,
ERR_CAPI_INIT_FAILED = 35,
ERR_XTS_MASTERKEY_VULNERABLE = 36,
ERR_SYSENC_XTS_MASTERKEY_VULNERABLE = 37
ERR_SYSENC_XTS_MASTERKEY_VULNERABLE = 37,
ERR_KEY_DERIVATION_FAILED = 38
};
#endif // #ifndef TCDEFS_H
+66 -7
View File
@@ -161,11 +161,28 @@ UINT64_STRUCT GetHeaderField64 (uint8 *header, int offset)
typedef struct
{
unsigned char DerivedKey[MASTER_KEYDATA_SIZE];
LONG DerivationResult;
BOOL Free;
LONG KeyReady;
int Pkcs5Prf;
} KeyDerivationWorkItem;
#ifndef VC_DCS_DISABLE_ARGON2
static int MapArgon2ResultToVcError (int result)
{
if (result == 0)
return ERR_SUCCESS;
if (result == ARGON2_MEMORY_ALLOCATION_ERROR)
return ERR_OUTOFMEMORY;
if (result == ARGON2_OPERATION_CANCELLED)
return ERR_USER_ABORT;
return ERR_KEY_DERIVATION_FAILED;
}
#endif
BOOL ReadVolumeHeaderRecoveryMode = FALSE;
@@ -186,6 +203,9 @@ int ReadVolumeHeader (BOOL bBoot, unsigned char *encryptedHeader, Password *pass
int iterationsCount = 0;
int memoryCost = 0;
LONG volatile abortKeyDerivation = 0;
#ifndef VC_DCS_DISABLE_ARGON2
int lastArgon2DerivationResult = 0;
#endif
#if !defined(_UEFI)
TC_EVENT *keyDerivationCompletedEvent = NULL;
TC_EVENT *noOutstandingWorkItemEvent = NULL;
@@ -329,12 +349,13 @@ int ReadVolumeHeader (BOOL bBoot, unsigned char *encryptedHeader, Password *pass
{
item->Free = FALSE;
item->KeyReady = FALSE;
item->DerivationResult = 0;
item->Pkcs5Prf = enqPkcs5Prf;
iterationsCount = get_pkcs5_iteration_count (enqPkcs5Prf, pim, bBoot, &memoryCost);
EncryptionThreadPoolBeginKeyDerivation (keyDerivationCompletedEvent, noOutstandingWorkItemEvent,
&item->KeyReady, outstandingWorkItemCount, enqPkcs5Prf, keyInfo->userKey,
keyInfo->keyLength, keyInfo->salt, iterationsCount, memoryCost, item->DerivedKey, &abortKeyDerivation);
keyInfo->keyLength, keyInfo->salt, iterationsCount, memoryCost, item->DerivedKey, &item->DerivationResult, &abortKeyDerivation);
++queuedWorkItems;
break;
@@ -355,6 +376,18 @@ int ReadVolumeHeader (BOOL bBoot, unsigned char *encryptedHeader, Password *pass
item = &keyDerivationWorkItems[i];
if (!item->Free && InterlockedExchangeAdd (&item->KeyReady, 0) == TRUE)
{
LONG derivationResult = InterlockedExchangeAdd (&item->DerivationResult, 0);
if (derivationResult != 0)
{
#ifndef VC_DCS_DISABLE_ARGON2
if (item->Pkcs5Prf == ARGON2)
lastArgon2DerivationResult = (int) derivationResult;
#endif
item->Free = TRUE;
--queuedWorkItems;
continue;
}
pkcs5_prf = item->Pkcs5Prf;
iterationsCount = get_pkcs5_iteration_count (pkcs5_prf, pim, bBoot, &memoryCost);
keyInfo->noIterations = iterationsCount;
@@ -413,8 +446,21 @@ KeyReady: ;
#ifndef VC_DCS_DISABLE_ARGON2
case ARGON2:
derive_key_argon2(keyInfo->userKey, keyInfo->keyLength, keyInfo->salt,
PKCS5_SALT_SIZE, keyInfo->noIterations, keyInfo->memoryCost, dk, GetMaxPkcs5OutSize(), &abortKeyDerivation);
{
int derivationResult = derive_key_argon2(keyInfo->userKey, keyInfo->keyLength, keyInfo->salt,
PKCS5_SALT_SIZE, keyInfo->noIterations, keyInfo->memoryCost, dk, GetMaxPkcs5OutSize(), &abortKeyDerivation);
if (derivationResult != 0)
{
if (selected_pkcs5_prf == 0)
{
lastArgon2DerivationResult = derivationResult;
continue;
}
status = MapArgon2ResultToVcError (derivationResult);
goto err;
}
}
break;
#endif
#endif
@@ -632,7 +678,12 @@ KeyReady: ;
}
}
}
status = ERR_PASSWORD_WRONG;
#ifndef VC_DCS_DISABLE_ARGON2
if (lastArgon2DerivationResult != 0)
status = MapArgon2ResultToVcError (lastArgon2DerivationResult);
else
#endif
status = ERR_PASSWORD_WRONG;
err:
#if !defined(_UEFI)
@@ -1077,8 +1128,16 @@ int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, unsigned char *header,
#ifndef VC_DCS_DISABLE_ARGON2
case ARGON2:
derive_key_argon2(keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, keyInfo.memoryCost, dk, GetMaxPkcs5OutSize(), NULL);
{
int derivationResult = derive_key_argon2(keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, keyInfo.memoryCost, dk, GetMaxPkcs5OutSize(), NULL);
if (derivationResult != 0)
{
crypto_close (cryptoInfo);
retVal = MapArgon2ResultToVcError (derivationResult);
goto err;
}
}
break;
#endif
#endif
@@ -1276,7 +1335,7 @@ err:
VirtualUnlock (&dk, sizeof (dk));
#endif // !defined(_UEFI)
return 0;
return retVal;
}
#if !defined(_UEFI)