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

Windows: Add support for Argon2id as an alternative to PBKDF2 key derivation

This commit is contained in:
Mounir IDRASSI
2025-06-25 15:44:31 +09:00
parent 228129362a
commit 3c17b8ced2
35 changed files with 4609 additions and 72 deletions
+6
View File
@@ -1721,6 +1721,8 @@ namespace VeraCrypt
pkcs5_prf = WHIRLPOOL;
else if (_stricmp(request.BootPrfAlgorithmName, "Streebog") == 0)
pkcs5_prf = STREEBOG;
else if (_stricmp(request.BootPrfAlgorithmName, "Argon2") == 0)
pkcs5_prf = ARGON2;
#endif
else if (strlen(request.BootPrfAlgorithmName) == 0) // case of version < 1.0f
pkcs5_prf = BLAKE2S;
@@ -1753,6 +1755,10 @@ namespace VeraCrypt
if (!bIsGPT && pkcs5_prf != BLAKE2S && pkcs5_prf != SHA256)
throw ParameterIncorrect (SRC_POS);
// we don't support Argon2 for system encryption for now
if (pkcs5_prf == ARGON2)
throw ParameterIncorrect (SRC_POS);
int bootSectorId = 0;
int bootLoaderId = 0;
+6
View File
@@ -133,6 +133,7 @@ static Hash Hashes[] =
{ BLAKE2S, L"BLAKE2s-256", FALSE, TRUE },
{ WHIRLPOOL, L"Whirlpool", FALSE, FALSE },
{ STREEBOG, L"Streebog", FALSE, FALSE },
{ ARGON2, L"Argon2", FALSE, FALSE },
#endif
{ 0, 0, 0 }
};
@@ -777,6 +778,11 @@ BOOL HashForSystemEncryption (int hashId)
}
BOOL HashIsAvailable (int hashId)
{
return (hashId != ARGON2) && (HashGet(hashId) != 0); // Argon2 is not a hash function
}
// Returns the largest key size needed by an EA for the specified mode of operation
int EAGetLargestKeyForMode (int mode)
{
+5
View File
@@ -55,6 +55,7 @@ enum
SHA256,
BLAKE2S,
STREEBOG,
ARGON2,
HASH_ENUM_END_ID
};
@@ -203,6 +204,7 @@ typedef struct
#ifndef TC_WINDOWS_BOOT
# include "Sha2.h"
# include "Whirlpool.h"
# include "argon2.h"
# include "Streebog.h"
# include "kuznyechik.h"
# include "Camellia.h"
@@ -224,6 +226,7 @@ typedef struct
typedef struct keyInfo_t
{
int noIterations; /* Number of times to iterate (PKCS-5) */
int memoryCost; /* Memory cost factor (PKCS-5) */
int keyLength; /* Length of the key */
uint64 dummy; /* Dummy field to ensure 16-byte alignment of this structure */
unsigned __int8 salt[PKCS5_SALT_SIZE]; /* PKCS-5 salt */
@@ -255,6 +258,7 @@ typedef struct CRYPTO_INFO_t
#endif
int noIterations;
int memoryCost;
int volumePim;
BOOL bProtectHiddenVolume; // Indicates whether the volume contains a hidden volume to be protected against overwriting
@@ -373,6 +377,7 @@ Hash *HashGet (int id);
void HashGetName2 (wchar_t *buf, size_t bufLen, int hashId);
BOOL HashIsDeprecated (int hashId);
BOOL HashForSystemEncryption (int hashId);
BOOL HashIsAvailable (int hashId);
int GetMaxPkcs5OutSize (void);
#endif
+36 -9
View File
@@ -369,6 +369,8 @@ typedef struct
unsigned __int64 encSpeed;
unsigned __int64 decSpeed;
unsigned __int64 meanBytesPerSec;
unsigned __int64 iterations;
unsigned __int64 memoryCost;
} BENCHMARK_REC;
BENCHMARK_REC benchmarkTable [BENCHMARK_MAX_ITEMS];
@@ -6154,6 +6156,11 @@ static void ResetBenchmarkList (HWND hwndDlg)
LvCol.cx = CompensateXDPI (80);
LvCol.fmt = LVCFMT_RIGHT;
SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol);
LvCol.pszText = GetString ("MEMORY_COST");
LvCol.cx = CompensateXDPI (80);
LvCol.fmt = LVCFMT_RIGHT;
SendMessageW (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol);
break;
}
}
@@ -6251,10 +6258,14 @@ static void DisplayBenchmarkResults (HWND hwndDlg)
LvItem.iSubItem = 1;
LvItem.pszText = item1;
SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem);
swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d", (int) benchmarkTable[i].decSpeed);
swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d", (int) benchmarkTable[i].iterations);
LvItem.iSubItem = 2;
LvItem.pszText = item1;
SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem);
swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d", (int) benchmarkTable[i].memoryCost);
LvItem.iSubItem = 3;
LvItem.pszText = item1;
SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem);
break;
}
}
@@ -6343,6 +6354,9 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++)
{
// Skip Argon2 since it is not a hash function
if (hid == ARGON2)
continue;
if (QueryPerformanceCounter (&performanceCountStart) == 0)
goto counter_error;
@@ -6408,44 +6422,56 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
int thid, i;
unsigned char dk[MASTER_KEYDATA_SIZE];
char *tmp_salt = {"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"};
int memoryCost = 0;
int iterations = 0;
for (thid = FIRST_PRF_ID; thid <= LAST_PRF_ID; thid++)
{
if (benchmarkPreBoot && !benchmarkGPT && !HashForSystemEncryption (thid))
continue;
// we don't support Argon2 for system encryption
if (benchmarkPreBoot && thid == ARGON2)
continue;
if (QueryPerformanceCounter (&performanceCountStart) == 0)
goto counter_error;
for (i = 1; i <= 2; i++)
{
iterations = get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot, &memoryCost);
switch (thid)
{
case SHA512:
/* PKCS-5 test with HMAC-SHA-512 used as the PRF */
derive_key_sha512 ((unsigned char*) "passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
derive_key_sha512 ((const unsigned char*) "passphrase-1234567890", 21, (const unsigned char*) tmp_salt, 64, iterations, dk, MASTER_KEYDATA_SIZE);
break;
case SHA256:
/* PKCS-5 test with HMAC-SHA-256 used as the PRF */
derive_key_sha256 ((unsigned char*)"passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
derive_key_sha256 ((const unsigned char*)"passphrase-1234567890", 21, (const unsigned char*)tmp_salt, 64, iterations, dk, MASTER_KEYDATA_SIZE);
break;
#ifndef WOLFCRYPT_BACKEND
case BLAKE2S:
/* PKCS-5 test with HMAC-BLAKE2s used as the PRF */
derive_key_blake2s ((unsigned char*)"passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
derive_key_blake2s ((const unsigned char*)"passphrase-1234567890", 21, (const unsigned char*)tmp_salt, 64, iterations, dk, MASTER_KEYDATA_SIZE);
break;
case WHIRLPOOL:
/* PKCS-5 test with HMAC-Whirlpool used as the PRF */
derive_key_whirlpool ((unsigned char*)"passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
derive_key_whirlpool ((const unsigned char*)"passphrase-1234567890", 21, (const unsigned char*)tmp_salt, 64, iterations, dk, MASTER_KEYDATA_SIZE);
break;
case STREEBOG:
/* PKCS-5 test with HMAC-STREEBOG used as the PRF */
derive_key_streebog((unsigned char*)"passphrase-1234567890", 21, (unsigned char*) tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
derive_key_streebog((const unsigned char*)"passphrase-1234567890", 21, (const unsigned char*)tmp_salt, 64, iterations, dk, MASTER_KEYDATA_SIZE);
break;
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);
break;
}
#endif
}
@@ -6455,7 +6481,8 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart;
benchmarkTable[benchmarkTotalItems].id = thid;
benchmarkTable[benchmarkTotalItems].decSpeed = get_pkcs5_iteration_count(thid, benchmarkPim, benchmarkPreBoot);
benchmarkTable[benchmarkTotalItems].iterations = iterations;
benchmarkTable[benchmarkTotalItems].memoryCost = memoryCost;
benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (unsigned __int64) (1000 * ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart / 2));
if (benchmarkPreBoot)
{
@@ -6909,7 +6936,7 @@ static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARA
SendMessage (hComboBox, CB_RESETCONTENT, 0, 0);
for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++)
{
if (!HashIsDeprecated (hid))
if (!HashIsDeprecated (hid) && HashIsAvailable (hid))
AddComboPair (hComboBox, HashGetName(hid), hid);
}
SelectAlgo (hComboBox, &hash_algo);
@@ -7107,7 +7134,7 @@ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LP
SendMessage (hComboBox, CB_RESETCONTENT, 0, 0);
for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++)
{
if (!HashIsDeprecated (hid))
if (!HashIsDeprecated (hid) && HashIsAvailable (hid))
AddComboPair (hComboBox, HashGetName(hid), hid);
}
SelectAlgo (hComboBox, &hash_algo);
+8 -1
View File
@@ -100,6 +100,7 @@ typedef struct EncryptionThreadPoolWorkItemStruct
LONG *CompletionFlag;
unsigned char *DerivedKey;
int IterationCount;
int Memorycost;
TC_EVENT *NoOutstandingWorkItemEvent;
LONG *OutstandingWorkItemCount;
unsigned char *Password;
@@ -267,6 +268,11 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
break;
case ARGON2:
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());
break;
default:
TC_THROW_FATAL_EXCEPTION;
}
@@ -527,7 +533,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, unsigned char *derivedKey)
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)
{
EncryptionThreadPoolWorkItem *workItem;
@@ -550,6 +556,7 @@ void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT
workItem->KeyDerivation.CompletionFlag = completionFlag;
workItem->KeyDerivation.DerivedKey = derivedKey;
workItem->KeyDerivation.IterationCount = iterationCount;
workItem->KeyDerivation.Memorycost = memoryCost;
workItem->KeyDerivation.NoOutstandingWorkItemEvent = noOutstandingWorkItemEvent;
workItem->KeyDerivation.OutstandingWorkItemCount = outstandingWorkItemCount;
workItem->KeyDerivation.Password = password;
+1 -1
View File
@@ -32,7 +32,7 @@ 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, unsigned char *derivedKey);
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);
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);
+120 -2
View File
@@ -1169,6 +1169,9 @@ wchar_t *get_pkcs5_prf_name (int pkcs5_prf_id)
case STREEBOG:
return L"HMAC-STREEBOG";
case ARGON2:
return L"Argon2";
default:
return L"(Unknown)";
}
@@ -1176,9 +1179,10 @@ wchar_t *get_pkcs5_prf_name (int pkcs5_prf_id)
int get_pkcs5_iteration_count(int pkcs5_prf_id, int pim, BOOL bBoot)
int get_pkcs5_iteration_count(int pkcs5_prf_id, int pim, BOOL bBoot, int* pMemoryCost)
{
int iteration_count = 0;
*pMemoryCost = 0;
if (pim >= 0)
{
@@ -1213,6 +1217,10 @@ int get_pkcs5_iteration_count(int pkcs5_prf_id, int pim, BOOL bBoot)
iteration_count = bBoot ? pim * 2048 : 15000 + pim * 1000;
break;
case ARGON2:
get_argon2_params (pim, &iteration_count, pMemoryCost);
break;
default:
TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID
}
@@ -1230,9 +1238,119 @@ int is_pkcs5_prf_supported (int pkcs5_prf_id, PRF_BOOT_TYPE bootType)
|| (bootType != PRF_BOOT_MBR && (pkcs5_prf_id < FIRST_PRF_ID || pkcs5_prf_id > LAST_PRF_ID))
)
return 0;
// we don't support Argon2 in pre-boot authentication
if ((bootType == PRF_BOOT_MBR || bootType == PRF_BOOT_GPT) && pkcs5_prf_id == ARGON2)
return 0;
return 1;
}
void derive_key_argon2(const unsigned char *pwd, int pwd_len, const unsigned char *salt, int salt_len, uint32 iterations, uint32 memcost, unsigned char *dk, int dklen)
{
#if defined (DEVICE_DRIVER) && !defined(_M_ARM64)
NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
XSTATE_SAVE SaveState;
if (IsCpuIntel() && HasSAVX())
saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
#endif
if (0 != argon2id_hash_raw(
iterations, // number of iterations
memcost, // memory cost in KiB
1, // parallelism factor (number of threads)
pwd, pwd_len, // password and its length
salt, salt_len, // salt and its length
dk, dklen// derived key and its length
))
{
// If the Argon2 derivation fails, we fill the derived key with zeroes
memset(dk, 0, dklen);
}
#if defined (DEVICE_DRIVER) && !defined(_M_ARM64)
if (NT_SUCCESS(saveStatus))
KeRestoreExtendedProcessorState(&SaveState);
#endif
}
/**
* get_argon2_params
*
* This function calculates the memory cost (in KiB) and time cost (iterations) for
* the Argon2id key derivation function based on the Personal Iteration Multiplier (PIM) value.
*
* Parameters:
* - pim: The Personal Iteration Multiplier (PIM), which controls the memory and time costs.
* If pim < 0, it is clamped to 0.
* If pim == 0, the default value of 12 is used.
* - pIterations: Pointer to an integer where the calculated time cost (iterations) will be stored.
* - pMemcost: Pointer to an integer where the calculated memory cost (in KiB) will be stored.
*
* Formulas:
* - Memory Cost (m_cost) in MiB:
* m_cost(pim) = min(64 MiB + (pim - 1) * 32 MiB, 1024 MiB)
* This formula increases the memory cost by 32 MiB for each increment of PIM, starting from 64 MiB.
* The memory cost is capped at 1024 MiB when PIM reaches 31 or higher.
* The result is converted to KiB before being stored in *pMemcost:
* *pMemcost = m_cost(pim) * 1024
*
* - Time Cost (t_cost) in iterations:
* If PIM <= 31:
* t_cost(pim) = 3 + floor((pim - 1) / 3)
* If PIM > 31:
* t_cost(pim) = 13 + (pim - 31)
* This formula increases the time cost by 1 iteration for every 3 increments of PIM when PIM <= 31.
* For PIM > 31, the time cost increases by 1 iteration for each increment in PIM.
* The calculated time cost is stored in *pIterations.
*
* Example:
* - For PIM = 12:
* Memory Cost = 64 + (12 - 1) * 32 = 416 MiB (425,984 KiB)
* Time Cost = 3 + floor((12 - 1) / 3) = 6 iterations
*
* - For PIM = 31:
* Memory Cost = 64 + (31 - 1) * 32 = 1024 MiB (capped)
* Time Cost = 3 + floor((31 - 1) / 3) = 13 iterations
*
* - For PIM = 32:
* Memory Cost = 1024 MiB (capped)
* Time Cost = 13 + (32 - 31) = 14 iterations
*
*/
void get_argon2_params(int pim, int* pIterations, int* pMemcost)
{
// Ensure PIM is at least 0
if (pim < 0)
{
pim = 0;
}
// Default PIM value is 12
// which leads to 416 MiB memory cost and 6 iterations
if (pim == 0)
{
pim = 12;
}
// Compute the memory cost (m_cost) in MiB
int m_cost_mib = 64 + (pim - 1) * 32;
// Cap the memory cost at 1024 MiB
if (m_cost_mib > 1024)
{
m_cost_mib = 1024;
}
// Convert memory cost to KiB for Argon2
*pMemcost = m_cost_mib * 1024; // m_cost in KiB
// Compute the time cost (t_cost)
if (pim <= 31)
{
*pIterations = 3 + ((pim - 1) / 3);
}
else
{
*pIterations = 13 + (pim - 31);
}
}
#endif //!TC_WINDOWS_BOOT
+4 -1
View File
@@ -40,9 +40,12 @@ void derive_key_whirlpool (const unsigned char *pwd, int pwd_len, const unsigned
void hmac_streebog (unsigned char *k, int lk, unsigned char *d, int ld);
void derive_key_streebog (const unsigned char *pwd, int pwd_len, const unsigned char *salt, int salt_len, uint32 iterations, unsigned char *dk, int dklen);
int get_pkcs5_iteration_count (int pkcs5_prf_id, int pim, BOOL bBoot);
int get_pkcs5_iteration_count (int pkcs5_prf_id, int pim, BOOL bBoot, int* pMemoryCost);
wchar_t *get_pkcs5_prf_name (int pkcs5_prf_id);
void derive_key_argon2(const unsigned char *pwd, int pwd_len, const unsigned char *salt, int salt_len, uint32 iterations, uint32 memcost, unsigned char *dk, int dklen);
void get_argon2_params(int pim, int* pIterations, int* pMemcost);
/* check if given PRF supported.*/
typedef enum
{
+3
View File
@@ -278,6 +278,7 @@ BOOL Randmix ()
#ifndef WOLFCRYPT_BACKEND
case BLAKE2S:
case ARGON2: // in case of Argon2, we use Blake2s
digestSize = BLAKE2S_DIGESTSIZE;
break;
@@ -315,6 +316,7 @@ BOOL Randmix ()
#ifndef WOLFCRYPT_BACKEND
case BLAKE2S:
case ARGON2: // in case of Argon2, we use Blake2s
blake2s_init(&bctx);
blake2s_update(&bctx, pRandPool, RNG_POOL_SIZE);
blake2s_final(&bctx, hashOutputBuffer);
@@ -358,6 +360,7 @@ BOOL Randmix ()
#ifndef WOLFCRYPT_BACKEND
case BLAKE2S:
case ARGON2: // in case of Argon2, we use Blake2s
burn (&bctx, sizeof(bctx));
break;
+4
View File
@@ -1425,6 +1425,10 @@ static BOOL DoAutoTestAlgorithms (void)
if (!test_pkcs5 ())
bFailed = TRUE;
/* Argon2id */
if (0 != argon2id_selftest())
bFailed = TRUE;
/* CRC-32 */
if (!crc32_selftests ())
bFailed = TRUE;
+42 -9
View File
@@ -192,6 +192,8 @@ int ReadVolumeHeader (BOOL bBoot, unsigned char *encryptedHeader, Password *pass
size_t encryptionThreadCount = GetEncryptionThreadCount();
LONG *outstandingWorkItemCount = NULL;
int i;
int iterationsCount = 0;
int memoryCost = 0;
#endif
size_t queuedWorkItems = 0;
@@ -307,6 +309,10 @@ int ReadVolumeHeader (BOOL bBoot, unsigned char *encryptedHeader, Password *pass
if (selected_pkcs5_prf != 0 && enqPkcs5Prf != selected_pkcs5_prf)
continue;
// we don't support Argon2 in pre-boot authentication
if (bBoot && (enqPkcs5Prf == ARGON2))
continue;
#if !defined(_UEFI)
if ((selected_pkcs5_prf == 0) && (encryptionThreadCount > 1))
{
@@ -322,9 +328,10 @@ int ReadVolumeHeader (BOOL bBoot, unsigned char *encryptedHeader, Password *pass
item->KeyReady = FALSE;
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, get_pkcs5_iteration_count (enqPkcs5Prf, pim, bBoot), item->DerivedKey);
keyInfo->keyLength, keyInfo->salt, iterationsCount, memoryCost, item->DerivedKey);
++queuedWorkItems;
break;
@@ -346,7 +353,9 @@ int ReadVolumeHeader (BOOL bBoot, unsigned char *encryptedHeader, Password *pass
if (!item->Free && InterlockedExchangeAdd (&item->KeyReady, 0) == TRUE)
{
pkcs5_prf = item->Pkcs5Prf;
keyInfo->noIterations = get_pkcs5_iteration_count (pkcs5_prf, pim, bBoot);
iterationsCount = get_pkcs5_iteration_count (pkcs5_prf, pim, bBoot, &memoryCost);
keyInfo->noIterations = iterationsCount;
keyInfo->memoryCost = memoryCost;
memcpy (dk, item->DerivedKey, sizeof (dk));
item->Free = TRUE;
@@ -365,7 +374,9 @@ KeyReady: ;
#endif // !defined(_UEFI)
{
pkcs5_prf = enqPkcs5Prf;
keyInfo->noIterations = get_pkcs5_iteration_count (enqPkcs5Prf, pim, bBoot);
iterationsCount = get_pkcs5_iteration_count (enqPkcs5Prf, pim, bBoot, &memoryCost);
keyInfo->noIterations = iterationsCount;
keyInfo->memoryCost = memoryCost;
switch (pkcs5_prf)
{
@@ -379,23 +390,29 @@ KeyReady: ;
PKCS5_SALT_SIZE, keyInfo->noIterations, dk, GetMaxPkcs5OutSize());
break;
#ifndef WOLFCRYPT_BACKEND
case BLAKE2S:
#ifndef WOLFCRYPT_BACKEND
case BLAKE2S:
derive_key_blake2s (keyInfo->userKey, keyInfo->keyLength, keyInfo->salt,
PKCS5_SALT_SIZE, keyInfo->noIterations, dk, GetMaxPkcs5OutSize());
break;
case WHIRLPOOL:
case WHIRLPOOL:
derive_key_whirlpool (keyInfo->userKey, keyInfo->keyLength, keyInfo->salt,
PKCS5_SALT_SIZE, keyInfo->noIterations, dk, GetMaxPkcs5OutSize());
break;
case STREEBOG:
case STREEBOG:
derive_key_streebog(keyInfo->userKey, keyInfo->keyLength, keyInfo->salt,
PKCS5_SALT_SIZE, keyInfo->noIterations, dk, GetMaxPkcs5OutSize());
break;
#endif
case ARGON2:
derive_key_argon2(keyInfo->userKey, keyInfo->keyLength, keyInfo->salt,
PKCS5_SALT_SIZE, keyInfo->noIterations, keyInfo->memoryCost, dk, GetMaxPkcs5OutSize());
break;
#endif
default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
@@ -540,6 +557,7 @@ KeyReady: ;
{
cryptoInfo->pkcs5 = pkcs5_prf;
cryptoInfo->noIterations = keyInfo->noIterations;
cryptoInfo->memoryCost = keyInfo->memoryCost;
cryptoInfo->volumePim = pim;
goto ret;
}
@@ -571,6 +589,7 @@ KeyReady: ;
// PKCS #5
cryptoInfo->pkcs5 = pkcs5_prf;
cryptoInfo->noIterations = keyInfo->noIterations;
cryptoInfo->memoryCost = keyInfo->memoryCost;
cryptoInfo->volumePim = pim;
// Init the cipher with the decrypted master key
@@ -900,6 +919,13 @@ int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, unsigned char *header,
if (pim < 0)
pim = 0;
// we don't support Argon2 in pre-boot authentication
if (bBoot && (pkcs5_prf == ARGON2))
{
crypto_close (cryptoInfo);
return ERR_PARAMETER_INCORRECT;
}
memset (header, 0, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
#if !defined(_UEFI)
VirtualLock (&keyInfo, sizeof (keyInfo));
@@ -952,12 +978,13 @@ int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, unsigned char *header,
{
memcpy (keyInfo.userKey, password->Text, nUserKeyLen);
keyInfo.keyLength = nUserKeyLen;
keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, pim, bBoot);
keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5_prf, pim, bBoot, &keyInfo.memoryCost);
}
else
{
keyInfo.keyLength = 0;
keyInfo.noIterations = 0;
keyInfo.memoryCost = 0;
}
// User selected encryption algorithm
@@ -966,6 +993,7 @@ int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, unsigned char *header,
// User selected PRF
cryptoInfo->pkcs5 = pkcs5_prf;
cryptoInfo->noIterations = keyInfo.noIterations;
cryptoInfo->memoryCost = keyInfo.memoryCost;
cryptoInfo->volumePim = pim;
// Mode of operation
@@ -1013,6 +1041,11 @@ int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, unsigned char *header,
derive_key_streebog(keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
case ARGON2:
derive_key_argon2(keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, keyInfo.memoryCost, dk, GetMaxPkcs5OutSize());
break;
#endif
default:
// Unknown/wrong ID