Windows: Add support for Streebog (hash) and kuznyechik (encryption)

This commit is contained in:
Mounir IDRASSI 2016-08-09 14:25:52 +02:00
parent 0b2c8b09c6
commit e90e24b30b
No known key found for this signature in database
GPG Key ID: DD0C382D5FCFB8FC
28 changed files with 5597 additions and 14 deletions

View File

@ -1082,11 +1082,23 @@ namespace VeraCrypt
ea = SERPENT;
else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0)
ea = TWOFISH;
else if (_stricmp (request.BootEncryptionAlgorithmName, "Camellia") == 0)
ea = CAMELLIA;
#if defined(CIPHER_GOST89)
else if (_stricmp (request.BootEncryptionAlgorithmName, "GOST89") == 0)
ea = GOST89;
#endif
if (_stricmp(request.BootPrfAlgorithmName, "SHA-256") == 0)
pkcs5_prf = SHA256;
else if (_stricmp(request.BootPrfAlgorithmName, "RIPEMD-160") == 0)
pkcs5_prf = RIPEMD160;
else if (_stricmp(request.BootPrfAlgorithmName, "SHA-512") == 0)
pkcs5_prf = SHA512;
else if (_stricmp(request.BootPrfAlgorithmName, "Whirlpool") == 0)
pkcs5_prf = WHIRLPOOL;
else if (_stricmp(request.BootPrfAlgorithmName, "Streebog") == 0)
pkcs5_prf = STREEBOG;
else if (strlen(request.BootPrfAlgorithmName) == 0) // case of version < 1.0f
pkcs5_prf = RIPEMD160;
}
@ -1101,6 +1113,9 @@ namespace VeraCrypt
}
catch (...) { }
}
if (pkcs5_prf == 0)
throw ParameterIncorrect (SRC_POS);
}
else
{

View File

@ -58,6 +58,7 @@ static Cipher Ciphers[] =
#if defined(CIPHER_GOST89)
{ GOST89, L"GOST89", 16, 32, GOST_KS },
#endif // defined(CIPHER_GOST89)
{ KUZNYECHIK, L"Kuznyechik",16, 32, KUZNYECHIK_KS },
#endif
{ 0, 0, 0, 0, 0 }
};
@ -78,6 +79,7 @@ static EncryptionAlgorithm EncryptionAlgorithms[] =
#if defined(CIPHER_GOST89)
{ { GOST89, 0 }, { XTS, 0 }, 1 },
#endif // defined(CIPHER_GOST89)
{ { KUZNYECHIK, 0 }, { XTS, 0 }, 1 },
{ { TWOFISH, AES, 0 }, { XTS, 0 }, 1 },
{ { SERPENT, TWOFISH, AES, 0 }, { XTS, 0 }, 1 },
{ { AES, SERPENT, 0 }, { XTS, 0 }, 1 },
@ -112,6 +114,7 @@ static Hash Hashes[] =
{ WHIRLPOOL, L"Whirlpool", FALSE, FALSE },
{ SHA256, L"SHA-256", FALSE, TRUE },
{ RIPEMD160, L"RIPEMD-160", TRUE, TRUE },
{ STREEBOG, L"Streebog", FALSE, FALSE },
{ 0, 0, 0 }
};
#endif
@ -156,6 +159,9 @@ int CipherInit (int cipher, unsigned char *key, unsigned __int8 *ks)
gost_set_key(key, (gost_kds*)ks);
break;
#endif // && defined(CIPHER_GOST89)
case KUZNYECHIK:
kuznyechik_set_key(key, (kuznyechik_kds*)ks);
break;
#endif // !defined(TC_WINDOWS_BOOT)
default:
@ -189,6 +195,7 @@ void EncipherBlock(int cipher, void *data, void *ks)
#if defined(CIPHER_GOST89)
case GOST89: gost_encrypt(data, data, ks, 1); break;
#endif // defined(CIPHER_GOST89)
case KUZNYECHIK: kuznyechik_encrypt_block(data, data, ks); break;
#endif // !defined(TC_WINDOWS_BOOT)
default: TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID
}
@ -252,6 +259,7 @@ void DecipherBlock(int cipher, void *data, void *ks)
#if defined(CIPHER_GOST89)
case GOST89: gost_decrypt(data, data, ks, 1); break;
#endif // defined(CIPHER_GOST89)
case KUZNYECHIK: kuznyechik_decrypt_block(data, data, ks); break;
#endif // !defined(TC_WINDOWS_BOOT)

View File

@ -54,6 +54,7 @@ enum
WHIRLPOOL,
SHA256,
RIPEMD160,
STREEBOG,
HASH_ENUM_END_ID
};
@ -72,6 +73,9 @@ enum
#define WHIRLPOOL_BLOCKSIZE 64
#define WHIRLPOOL_DIGESTSIZE 64
#define STREEBOG_BLOCKSIZE 64
#define STREEBOG_DIGESTSIZE 64
#define MAX_DIGESTSIZE WHIRLPOOL_DIGESTSIZE
#define DEFAULT_HASH_ALGORITHM FIRST_PRF_ID
@ -108,7 +112,8 @@ enum
SERPENT,
TWOFISH,
CAMELLIA,
GOST89
GOST89,
KUZNYECHIK
};
typedef struct
@ -162,9 +167,11 @@ typedef struct
# endif
#else
#define MAX_EXPANDED_KEY (AES_KS + SERPENT_KS + TWOFISH_KS)
#ifdef TC_WINDOWS_BOOT
#define MAX_EXPANDED_KEY max((AES_KS + SERPENT_KS + TWOFISH_KS), CAMELLIA_KS)
#else
#define MAX_EXPANDED_KEY max(max(max((AES_KS + SERPENT_KS + TWOFISH_KS), GOST_KS), CAMELLIA_KS), KUZNYECHIK_KS)
#endif
#endif
#ifdef DEBUG
@ -190,7 +197,9 @@ typedef struct
#ifndef TC_WINDOWS_BOOT
# include "Sha2.h"
# include "Whirlpool.h"
# include "Streebog.h"
# include "GostCipher.h"
# include "kuznyechik.h"
# include "Camellia.h"
#else
# include "CamelliaSmall.h"
@ -209,7 +218,7 @@ typedef struct keyInfo_t
int keyLength; /* Length of the key */
uint64 dummy; /* Dummy field to ensure 16-byte alignment of this structure */
__int8 salt[PKCS5_SALT_SIZE]; /* PKCS-5 salt */
__int8 master_keydata[MASTER_KEYDATA_SIZE]; /* Concatenated master primary and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */
CRYPTOPP_ALIGN_DATA(16) __int8 master_keydata[MASTER_KEYDATA_SIZE]; /* Concatenated master primary and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */
CRYPTOPP_ALIGN_DATA(16) __int8 userKey[MAX_PASSWORD]; /* Password (to which keyfiles may have been applied). WITHOUT +1 for the null terminator. */
} KEY_INFO, *PKEY_INFO;
@ -231,8 +240,8 @@ typedef struct CRYPTO_INFO_t
GfCtx gf_ctx;
unsigned __int8 master_keydata[MASTER_KEYDATA_SIZE]; /* This holds the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */
unsigned __int8 k2[MASTER_KEYDATA_SIZE]; /* For XTS, this contains the secondary key (if cascade, multiple concatenated). For LRW (deprecated/legacy), it contains the tweak key. For CBC (deprecated/legacy), it contains the IV seed. */
CRYPTOPP_ALIGN_DATA(16) unsigned __int8 master_keydata[MASTER_KEYDATA_SIZE]; /* This holds the volume header area containing concatenated master key(s) and secondary key(s) (XTS mode). For LRW (deprecated/legacy), it contains the tweak key before the master key(s). For CBC (deprecated/legacy), it contains the IV seed before the master key(s). */
CRYPTOPP_ALIGN_DATA(16) unsigned __int8 k2[MASTER_KEYDATA_SIZE]; /* For XTS, this contains the secondary key (if cascade, multiple concatenated). For LRW (deprecated/legacy), it contains the tweak key. For CBC (deprecated/legacy), it contains the IV seed. */
unsigned __int8 salt[PKCS5_SALT_SIZE];
int noIterations;
BOOL bTrueCryptMode;

View File

@ -5154,6 +5154,7 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
RMD160_CTX rctx;
sha512_ctx s2ctx;
sha256_ctx s256ctx;
STREEBOG_CTX stctx;
int hid, i;
@ -5190,6 +5191,13 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
WHIRLPOOL_add (lpTestBuffer, benchmarkBufferSize, &wctx);
WHIRLPOOL_finalize (&wctx, (unsigned char *) digest);
break;
case STREEBOG:
STREEBOG_init(&stctx);
STREEBOG_add(&stctx, lpTestBuffer, benchmarkBufferSize);
STREEBOG_finalize(&stctx, (unsigned char *)digest);
break;
}
}
@ -5249,6 +5257,11 @@ static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg)
/* PKCS-5 test with HMAC-Whirlpool used as the PRF */
derive_key_whirlpool ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
break;
case STREEBOG:
/* PKCS-5 test with HMAC-STREEBOG used as the PRF */
derive_key_streebog("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE);
break;
}
}
@ -6612,7 +6625,12 @@ ResetCipherTest(HWND hwndDlg, int idTestCipher)
SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), L"0000000000000000");
SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), L"0000000000000000");
if (idTestCipher == AES || idTestCipher == SERPENT || idTestCipher == TWOFISH || idTestCipher == CAMELLIA)
if (idTestCipher == AES || idTestCipher == SERPENT || idTestCipher == TWOFISH || idTestCipher == CAMELLIA
#if defined(CIPHER_GOST89)
|| idTestCipher == GOST89
#endif
|| idTestCipher == KUZNYECHIK
)
{
ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) L"256");
SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 32);
@ -10186,6 +10204,14 @@ void Applink (char *dest, BOOL bSendOS, char *extraOutput)
{
StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Twofish");
}
else if (strcmp(dest, "gost89") == 0)
{
StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=GOST89");
}
else if (strcmp(dest, "kuznyechik") == 0)
{
StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Kuznyechik");
}
else if (strcmp(dest, "camellia") == 0)
{
StringCbCopyA (url, sizeof (url),"https://veracrypt.codeplex.com/wikipage?title=Camellia");

View File

@ -182,6 +182,11 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
break;
case STREEBOG:
derive_key_streebog(workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE,
workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize());
break;
default:
TC_THROW_FATAL_EXCEPTION;
}

View File

@ -912,6 +912,222 @@ void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, uin
}
typedef struct hmac_streebog_ctx_struct
{
STREEBOG_CTX ctx;
STREEBOG_CTX inner_digest_ctx; /*pre-computed inner digest context */
STREEBOG_CTX outer_digest_ctx; /*pre-computed outer digest context */
CRYPTOPP_ALIGN_DATA(16) char k[PKCS5_SALT_SIZE + 4]; /* enough to hold (salt_len + 4) and also the Streebog hash */
char u[STREEBOG_DIGESTSIZE];
} hmac_streebog_ctx;
void hmac_streebog_internal
(
char *k, /* secret key */
int lk, /* length of the key in bytes */
char *d, /* input/output data. d pointer is guaranteed to be at least 64-bytes long */
int ld, /* length of input data in bytes */
hmac_streebog_ctx* hmac /* HMAC-Whirlpool context which holds temporary variables */
)
{
STREEBOG_CTX* ctx = &(hmac->ctx);
/**** Restore Precomputed Inner Digest Context ****/
memcpy (ctx, &(hmac->inner_digest_ctx), sizeof (STREEBOG_CTX));
STREEBOG_add (ctx, (unsigned char *) d, ld);
STREEBOG_finalize (ctx, (unsigned char *) d);
/**** Restore Precomputed Outer Digest Context ****/
memcpy (ctx, &(hmac->outer_digest_ctx), sizeof (STREEBOG_CTX));
STREEBOG_add (ctx, (unsigned char *) d, STREEBOG_DIGESTSIZE);
STREEBOG_finalize (ctx, (unsigned char *) d);
}
void hmac_streebog
(
char *k, /* secret key */
int lk, /* length of the key in bytes */
char *d, /* input data. d pointer is guaranteed to be at least 32-bytes long */
int ld /* length of data in bytes */
)
{
hmac_streebog_ctx hmac;
STREEBOG_CTX* ctx;
char* buf = hmac.k;
int b;
CRYPTOPP_ALIGN_DATA(16) char key[STREEBOG_DIGESTSIZE];
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
KFLOATING_SAVE floatingPointState;
NTSTATUS saveStatus = STATUS_SUCCESS;
if (HasSSE2() || HasSSE41())
saveStatus = KeSaveFloatingPointState (&floatingPointState);
#endif
/* If the key is longer than the hash algorithm block size,
let key = streebog(key), as per HMAC specifications. */
if (lk > STREEBOG_BLOCKSIZE)
{
STREEBOG_CTX tctx;
STREEBOG_init (&tctx);
STREEBOG_add (&tctx, (unsigned char *) k, lk);
STREEBOG_finalize (&tctx, (unsigned char *) key);
k = key;
lk = STREEBOG_DIGESTSIZE;
burn (&tctx, sizeof(tctx)); // Prevent leaks
}
/**** Precompute HMAC Inner Digest ****/
ctx = &(hmac.inner_digest_ctx);
STREEBOG_init (ctx);
/* Pad the key for inner digest */
for (b = 0; b < lk; ++b)
buf[b] = (char) (k[b] ^ 0x36);
memset (&buf[lk], 0x36, STREEBOG_BLOCKSIZE - lk);
STREEBOG_add (ctx, (unsigned char *) buf, STREEBOG_BLOCKSIZE);
/**** Precompute HMAC Outer Digest ****/
ctx = &(hmac.outer_digest_ctx);
STREEBOG_init (ctx);
for (b = 0; b < lk; ++b)
buf[b] = (char) (k[b] ^ 0x5C);
memset (&buf[lk], 0x5C, STREEBOG_BLOCKSIZE - lk);
STREEBOG_add (ctx, (unsigned char *) buf, STREEBOG_BLOCKSIZE);
hmac_streebog_internal(k, lk, d, ld, &hmac);
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
if (NT_SUCCESS (saveStatus) && (HasSSE2() || HasSSE41()))
KeRestoreFloatingPointState (&floatingPointState);
#endif
/* Prevent leaks */
burn(&hmac, sizeof(hmac));
}
static void derive_u_streebog (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, int b, hmac_streebog_ctx* hmac)
{
char* u = hmac->u;
char* k = hmac->k;
uint32 c, i;
/* iteration 1 */
memcpy (k, salt, salt_len); /* salt */
/* big-endian block number */
memset (&k[salt_len], 0, 3);
k[salt_len + 3] = (char) b;
hmac_streebog_internal (pwd, pwd_len, k, salt_len + 4, hmac);
memcpy (u, k, STREEBOG_DIGESTSIZE);
/* remaining iterations */
for (c = 1; c < iterations; c++)
{
hmac_streebog_internal (pwd, pwd_len, k, STREEBOG_DIGESTSIZE, hmac);
for (i = 0; i < STREEBOG_DIGESTSIZE; i++)
{
u[i] ^= k[i];
}
}
}
void derive_key_streebog (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen)
{
hmac_streebog_ctx hmac;
STREEBOG_CTX* ctx;
char* buf = hmac.k;
char key[STREEBOG_DIGESTSIZE];
int b, l, r;
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
KFLOATING_SAVE floatingPointState;
NTSTATUS saveStatus = STATUS_SUCCESS;
if (HasSSE2() || HasSSE41())
saveStatus = KeSaveFloatingPointState (&floatingPointState);
#endif
/* If the password is longer than the hash algorithm block size,
let pwd = streebog(pwd), as per HMAC specifications. */
if (pwd_len > STREEBOG_BLOCKSIZE)
{
STREEBOG_CTX tctx;
STREEBOG_init (&tctx);
STREEBOG_add (&tctx, (unsigned char *) pwd, pwd_len);
STREEBOG_finalize (&tctx, (unsigned char *) key);
pwd = key;
pwd_len = STREEBOG_DIGESTSIZE;
burn (&tctx, sizeof(tctx)); // Prevent leaks
}
if (dklen % STREEBOG_DIGESTSIZE)
{
l = 1 + dklen / STREEBOG_DIGESTSIZE;
}
else
{
l = dklen / STREEBOG_DIGESTSIZE;
}
r = dklen - (l - 1) * STREEBOG_DIGESTSIZE;
/**** Precompute HMAC Inner Digest ****/
ctx = &(hmac.inner_digest_ctx);
STREEBOG_init (ctx);
/* Pad the key for inner digest */
for (b = 0; b < pwd_len; ++b)
buf[b] = (char) (pwd[b] ^ 0x36);
memset (&buf[pwd_len], 0x36, STREEBOG_BLOCKSIZE - pwd_len);
STREEBOG_add (ctx, (unsigned char *) buf, STREEBOG_BLOCKSIZE);
/**** Precompute HMAC Outer Digest ****/
ctx = &(hmac.outer_digest_ctx);
STREEBOG_init (ctx);
for (b = 0; b < pwd_len; ++b)
buf[b] = (char) (pwd[b] ^ 0x5C);
memset (&buf[pwd_len], 0x5C, STREEBOG_BLOCKSIZE - pwd_len);
STREEBOG_add (ctx, (unsigned char *) buf, STREEBOG_BLOCKSIZE);
/* first l - 1 blocks */
for (b = 1; b < l; b++)
{
derive_u_streebog (pwd, pwd_len, salt, salt_len, iterations, b, &hmac);
memcpy (dk, hmac.u, STREEBOG_DIGESTSIZE);
dk += STREEBOG_DIGESTSIZE;
}
/* last block */
derive_u_streebog (pwd, pwd_len, salt, salt_len, iterations, b, &hmac);
memcpy (dk, hmac.u, r);
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
if (NT_SUCCESS (saveStatus) && (HasSSE2() || HasSSE41()))
KeRestoreFloatingPointState (&floatingPointState);
#endif
/* Prevent possible leaks. */
burn (&hmac, sizeof(hmac));
burn (key, sizeof(key));
}
wchar_t *get_pkcs5_prf_name (int pkcs5_prf_id)
{
switch (pkcs5_prf_id)
@ -928,6 +1144,9 @@ wchar_t *get_pkcs5_prf_name (int pkcs5_prf_id)
case WHIRLPOOL:
return L"HMAC-Whirlpool";
case STREEBOG:
return L"HMAC-STREEBOG";
default:
return L"(Unknown)";
}
@ -973,6 +1192,16 @@ int get_pkcs5_iteration_count (int pkcs5_prf_id, int pim, BOOL truecryptMode, BO
return bBoot? pim * 2048 : 15000 + pim * 1000;
}
case STREEBOG:
if (truecryptMode)
return 1000;
else if (pim == 0)
return bBoot? 200000 : 500000;
else
{
return bBoot? pim * 2048 : 15000 + pim * 1000;
}
default:
TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID
}

View File

@ -37,6 +37,9 @@ void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, uint32
void hmac_whirlpool (char *k, int lk, char *d, int ld);
void derive_key_whirlpool (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen);
void hmac_streebog (char *k, int32 lk, char *d, int32 ld);
void derive_key_streebog (char *pwd, int pwd_len, char *salt, int salt_len, uint32 iterations, char *dk, int dklen);
int get_pkcs5_iteration_count (int pkcs5_prf_id, int pim, BOOL truecryptMode, BOOL bBoot);
wchar_t *get_pkcs5_prf_name (int pkcs5_prf_id);
#endif

View File

@ -247,6 +247,7 @@ BOOL Randmix ()
RMD160_CTX rctx;
sha512_ctx sctx;
sha256_ctx s256ctx;
STREEBOG_CTX stctx;
int poolIndex, digestIndex, digestSize;
switch (HashFunction)
@ -267,6 +268,10 @@ BOOL Randmix ()
digestSize = WHIRLPOOL_DIGESTSIZE;
break;
case STREEBOG:
digestSize = STREEBOG_DIGESTSIZE;
break;
default:
TC_THROW_FATAL_EXCEPTION;
}
@ -303,6 +308,12 @@ BOOL Randmix ()
WHIRLPOOL_finalize (&wctx, hashOutputBuffer);
break;
case STREEBOG:
STREEBOG_init (&stctx);
STREEBOG_add (&stctx, pRandPool, RNG_POOL_SIZE);
STREEBOG_finalize (&stctx, hashOutputBuffer);
break;
default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
@ -335,6 +346,10 @@ BOOL Randmix ()
burn (&wctx, sizeof(wctx));
break;
case STREEBOG:
burn (&stctx, sizeof(sctx));
break;
default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;

View File

@ -19,10 +19,11 @@
#include "Xts.h"
#include <string.h>
#include "Pkcs5.h"
#include "cpu.h"
typedef struct {
unsigned __int8 key1[32];
unsigned __int8 key2[32];
CRYPTOPP_ALIGN_DATA(16) unsigned __int8 key1[32];
CRYPTOPP_ALIGN_DATA(16) unsigned __int8 key2[32];
unsigned __int8 dataUnitNo[8];
unsigned int blockNo;
unsigned __int8 plaintext[ENCRYPTION_DATA_UNIT_SIZE];
@ -475,6 +476,95 @@ char *hmac_whirlpool_test_vectors =
"\x6a\xbf\xa4\x02"
};
typedef struct _HashTestVector
{
const char* hexInput;
const char* hexOutput;
} HashTestVector;
typedef int (__cdecl HashFunction) (unsigned char* input, unsigned long inputLen, unsigned char* output);
unsigned char HexCharToByte (char c)
{
if (c >= ('0') && c <= ('9'))
return c - ('0');
else if (c >= ('A') && c <= ('F'))
return c - ('A') + 10;
else if (c >= ('a') && c <= ('f'))
return c - ('a') + 10;
else
return 0xFF;
}
unsigned long HexStringToByteArray(const char* hexStr, unsigned char* pbData)
{
unsigned long count = 0;
while (*hexStr)
{
*pbData++ = (HexCharToByte(hexStr[0]) << 4) | HexCharToByte(hexStr[1]);
hexStr += 2;
count++;
}
return count;
}
BOOL RunHashTest (HashFunction fn, HashTestVector* vector, BOOL bUseSSE)
{
ALIGN (16) unsigned char input[256];
unsigned char output[64];
unsigned char digest[64];
unsigned long i = 0, inputLen, outputLen, digestLen;
BOOL bRet = TRUE;
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
KFLOATING_SAVE floatingPointState;
NTSTATUS saveStatus = STATUS_SUCCESS;
if (bUseSSE && (HasSSE2() || HasSSE41()))
saveStatus = KeSaveFloatingPointState (&floatingPointState);
#endif
while (vector[i].hexInput && vector[i].hexOutput)
{
inputLen = HexStringToByteArray (vector[i].hexInput, input);
outputLen = HexStringToByteArray (vector[i].hexOutput, output);
digestLen = fn (input, inputLen, digest);
if ((digestLen != outputLen) || (0 != memcmp (digest, output, digestLen)))
{
bRet = FALSE;
break;
}
i++;
}
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
if (NT_SUCCESS (saveStatus) && bUseSSE && (HasSSE2() || HasSSE41()))
KeRestoreFloatingPointState (&floatingPointState);
#endif
return bRet;
}
/* https://www.streebog.net/src/trunk/examples/ */
HashTestVector Streebog512TestVectors[] = {
/* M1 */
{"303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132",
"1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48"
},
/* M2 */
{"d1e520e2e5f2f0e82c20d1f2f0e8e1eee6e820e2edf3f6e82c20e2e5fef2fa20f120eceef0ff20f1f2f0e5ebe0ece820ede020f5f0e0e1f0fbff20efebfaeafb20c8e3eef0e5e2fb",
"1e88e62226bfca6f9994f1f2d51569e0daf8475a3b0fe61a5300eee46d961376035fe83549ada2b8620fcd7c496ce5b33f0cb9dddc2b6460143b03dabac9fb28"
},
/* M3 */
{"",
"8e945da209aa869f0455928529bcae4679e9873ab707b55315f56ceb98bef0a7362f715528356ee83cda5f2aac4c6ad2ba3a715c1bcd81cb8e9f90bf4c1c1a8a"
},
/* M4 */
{"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"b0fd29ac1b0df441769ff3fdb8dc564df67721d6ac06fb28ceffb7bbaa7948c6c014ac999235b58cb26fb60fb112a145d7b4ade9ae566bf2611402c552d20db7"
},
{NULL, NULL}
};
unsigned char ks_tmp[MAX_EXPANDED_KEY];
void CipherInit2(int cipher, void* key, void* ks, int key_len)
@ -502,6 +592,9 @@ void CipherInit2(int cipher, void* key, void* ks, int key_len)
CipherInit(cipher,key,ks);
break;
#endif // defined(CIPHER_GOST89)
case KUZNYECHIK:
CipherInit(cipher, key, ks);
break;
default:
/* Unknown/wrong ID */
TC_THROW_FATAL_EXCEPTION;
@ -521,7 +614,7 @@ BOOL TestSectorBufEncryption (PCRYPTO_INFO ci)
int testCase = 0;
int nTestsPerformed = 0;
static unsigned char key1[] =
static CRYPTOPP_ALIGN_DATA(16) unsigned char key1[] =
{
0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
@ -939,7 +1032,7 @@ BOOL TestSectorBufEncryption (PCRYPTO_INFO ci)
static BOOL DoAutoTestAlgorithms (void)
{
PCRYPTO_INFO ci;
char key[32];
CRYPTOPP_ALIGN_DATA(16) char key[32];
unsigned char tmp[16];
BOOL bFailed = FALSE;
int i;
@ -1172,6 +1265,50 @@ BOOL test_hmac_whirlpool ()
return TRUE;
}
/* http://www.tc26.ru/methods/recommendation/%D0%A2%D0%9A26%D0%90%D0%9B%D0%93.pdf */
/* https://tools.ietf.org/html/draft-smyshlyaev-gost-usage-00 */
/* https://datatracker.ietf.org/doc/rfc7836/?include_text=1 */
static const unsigned char gost3411_2012_hmac_k1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
static const unsigned char gost3411_2012_hmac_m1[] = {
0x01, 0x26, 0xbd, 0xb8, 0x78, 0x00, 0xaf, 0x21,
0x43, 0x41, 0x45, 0x65, 0x63, 0x78, 0x01, 0x00
};
static const unsigned char gost3411_2012_hmac_r1[] = {
0xA5, 0x9B, 0xAB, 0x22, 0xEC, 0xAE, 0x19, 0xC6, 0x5F, 0xBD, 0xE6, 0xE5,
0xF4, 0xE9, 0xF5, 0xD8, 0x54, 0x9D, 0x31, 0xF0, 0x37, 0xF9, 0xDF, 0x9B,
0x90, 0x55, 0x00, 0xE1, 0x71, 0x92, 0x3A, 0x77, 0x3D, 0x5F, 0x15, 0x30,
0xF2, 0xED, 0x7E, 0x96, 0x4C, 0xB2, 0xEE, 0xDC, 0x29, 0xE9, 0xAD, 0x2F,
0x3A, 0xFE, 0x93, 0xB2, 0x81, 0x4F, 0x79, 0xF5, 0x00, 0x0F, 0xFC, 0x03,
0x66, 0xC2, 0x51, 0xE6
};
BOOL test_hmac_streebog ()
{
ALIGN(16) char digest[64]; /* large enough to hold digets and test vector inputs */
memcpy (digest, gost3411_2012_hmac_m1, sizeof (gost3411_2012_hmac_m1));
hmac_streebog ((char*) gost3411_2012_hmac_k1, sizeof(gost3411_2012_hmac_k1), digest, (int) sizeof (gost3411_2012_hmac_m1));
if (memcmp (digest, gost3411_2012_hmac_r1, STREEBOG_DIGESTSIZE) != 0)
return FALSE;
return TRUE;
}
int __cdecl StreebogHash (unsigned char* input, unsigned long inputLen, unsigned char* output)
{
STREEBOG_CTX ctx;
STREEBOG_init (&ctx);
STREEBOG_add (&ctx, input, inputLen);
STREEBOG_finalize (&ctx, output);
return STREEBOG_DIGESTSIZE;
}
BOOL test_pkcs5 ()
{
char dk[144];
@ -1192,6 +1329,14 @@ BOOL test_pkcs5 ()
if (test_hmac_whirlpool() == FALSE)
return FALSE;
/* HMAC-STREEBOG tests */
if (test_hmac_streebog() == FALSE)
return FALSE;
/* STREEBOG hash tests */
if (RunHashTest (StreebogHash, Streebog512TestVectors, TRUE) == FALSE)
return FALSE;
/* PKCS-5 test 1 with HMAC-SHA-256 used as the PRF (https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00) */
derive_key_sha256 ("passwd", 6, "\x73\x61\x6C\x74", 4, 1, dk, 64);
if (memcmp (dk, "\x55\xac\x04\x6e\x56\xe3\x08\x9f\xec\x16\x91\xc2\x25\x44\xb6\x05\xf9\x41\x85\x21\x6d\xde\x04\x65\xe6\x8b\x9d\x57\xc2\x0d\xac\xbc\x49\xca\x9c\xcc\xf1\x79\xb6\x45\x99\x16\x64\xb3\x9d\x77\xef\x31\x7c\x71\xb8\x45\xb1\xe3\x0b\xd5\x09\x11\x20\x41\xd3\xa1\x97\x83", 64) != 0)
@ -1243,5 +1388,15 @@ BOOL test_pkcs5 ()
if (memcmp (dk, "\x50\x7c\x36\x6f\xee\x10\x2e\x9a\xe2\x8a\xd5\x82\x72\x7d\x27\x0f\xe8\x4d\x7f\x68\x7a\xcf\xb5\xe7\x43\x67\xaa\x98\x93\x52\x2b\x09\x6e\x42\xdf\x2c\x59\x4a\x91\x6d\x7e\x10\xae\xb2\x1a\x89\x8f\xb9\x8f\xe6\x31\xa9\xd8\x9f\x98\x26\xf4\xda\xcd\x7d\x65\x65\xde\x10\x95\x91\xb4\x84\x26\xae\x43\xa1\x00\x5b\x1e\xb8\x38\x97\xa4\x1e\x4b\xd2\x65\x64\xbc\xfa\x1f\x35\x85\xdb\x4f\x97\x65\x6f\xbd\x24", 96) != 0)
return FALSE;
/* PKCS-5 test 1 with HMAC-STREEBOG used as the PRF */
derive_key_streebog ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
if (memcmp (dk, "\xd0\x53\xa2\x30", 4) != 0)
return FALSE;
/* PKCS-5 test 2 with HMAC-STREEBOG used as the PRF (derives a key longer than the underlying hash) */
derive_key_streebog ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 96);
if (memcmp (dk, "\xd0\x53\xa2\x30\x6f\x45\x81\xeb\xbc\x06\x81\xc5\xe7\x53\xa8\x5d\xc7\xf1\x23\x33\x1e\xbe\x64\x2c\x3b\x0f\x26\xd7\x00\xe1\x95\xc9\x65\x26\xb1\x85\xbe\x1e\xe2\xf4\x9b\xfc\x6b\x14\x84\xda\x24\x61\xa0\x1b\x9e\x79\x5c\xee\x69\x6e\xf9\x25\xb1\x1d\xca\xa0\x31\xba\x02\x6f\x9e\x99\x0f\xdb\x25\x01\x5b\xf1\xc7\x10\x19\x53\x3b\x29\x3f\x18\x00\xd6\xfc\x85\x03\xdc\xf2\xe5\xe9\x5a\xb1\x1e\x61\xde", 96) != 0)
return FALSE;
return TRUE;
}

View File

@ -171,7 +171,7 @@ int ReadVolumeHeader (BOOL bBoot, char *encryptedHeader, Password *password, int
char header[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
CRYPTOPP_ALIGN_DATA(16) KEY_INFO keyInfo;
PCRYPTO_INFO cryptoInfo;
char dk[MASTER_KEYDATA_SIZE];
CRYPTOPP_ALIGN_DATA(16) char dk[MASTER_KEYDATA_SIZE];
int enqPkcs5Prf, pkcs5_prf;
uint16 headerVersion;
int status = ERR_PARAMETER_INCORRECT;
@ -345,6 +345,10 @@ KeyReady: ;
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
case STREEBOG:
derive_key_streebog(keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
@ -912,6 +916,10 @@ int CreateVolumeHeaderInMemory (HWND hwndDlg, BOOL bBoot, char *header, int ea,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
case STREEBOG:
derive_key_streebog(keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
default:
// Unknown/wrong ID

View File

@ -219,9 +219,11 @@
<ClCompile Include="Camellia.c" />
<ClCompile Include="cpu.c" />
<ClCompile Include="GostCipher.c" />
<ClCompile Include="kuznyechik.c" />
<ClCompile Include="Rmd160.c" />
<ClCompile Include="Serpent.c" />
<ClCompile Include="Sha2.c" />
<ClCompile Include="Streebog.c" />
<ClCompile Include="Twofish.c" />
<ClCompile Include="Whirlpool.c" />
</ItemGroup>
@ -234,10 +236,12 @@
<ClInclude Include="config.h" />
<ClInclude Include="cpu.h" />
<ClInclude Include="GostCipher.h" />
<ClInclude Include="kuznyechik.h" />
<ClInclude Include="misc.h" />
<ClInclude Include="Rmd160.h" />
<ClInclude Include="Serpent.h" />
<ClInclude Include="Sha2.h" />
<ClInclude Include="Streebog.h" />
<ClInclude Include="Twofish.h" />
<ClInclude Include="Whirlpool.h" />
</ItemGroup>

View File

@ -45,6 +45,12 @@
<ClCompile Include="GostCipher.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="kuznyechik.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Streebog.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Aes.h">
@ -89,6 +95,12 @@
<ClInclude Include="GostCipher.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="kuznyechik.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Streebog.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="Aes_hw_cpu.asm">

View File

@ -20,5 +20,7 @@ SOURCES = \
Sha2.c \
Twofish.c \
GostCipher.c \
Streebog.c \
kuznyechik.c \
Whirlpool.c \
Camellia.c

2393
src/Crypto/Streebog.c Normal file

File diff suppressed because it is too large Load Diff

33
src/Crypto/Streebog.h Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2013, Alexey Degtyarev.
* All rights reserved.
*/
/* Adapted to VeraCrypt */
#ifndef STREEBOG_H
#define STREEBOG_H
#include "Common/Tcdefs.h"
#include "config.h"
#define ALIGN(a) CRYPTOPP_ALIGN_DATA(a)
typedef ALIGN(16) struct _STREEBOG_CTX
{
ALIGN(16) unsigned char buffer[64];
ALIGN(16) unsigned long long hash[8];
ALIGN(16) unsigned long long h[8];
ALIGN(16) unsigned long long N[8];
ALIGN(16) unsigned long long Sigma[8];
size_t bufsize;
unsigned int digest_size;
} STREEBOG_CTX;
void STREEBOG_init(STREEBOG_CTX *ctx);
void STREEBOG_init256(STREEBOG_CTX *ctx);
void STREEBOG_add(STREEBOG_CTX *ctx, byte *msg, size_t len);
void STREEBOG_finalize(STREEBOG_CTX *ctx, byte *out);
#endif

2453
src/Crypto/kuznyechik.c Normal file

File diff suppressed because it is too large Load Diff

26
src/Crypto/kuznyechik.h Normal file
View File

@ -0,0 +1,26 @@
/*
This code is written by kerukuro for cppcrypto library (http://cppcrypto.sourceforge.net/)
and released into public domain.
*/
/* Adapted to VeraCrypt */
#ifndef CPPCRYPTO_KUZNYECHIK_H
#define CPPCRYPTO_KUZNYECHIK_H
#include "Common/Tcdefs.h"
typedef struct _kuznyechik_kds
{
uint64 rke[10][2];
uint64 rkd[10][2];
} kuznyechik_kds;
#define KUZNYECHIK_KS (sizeof(kuznyechik_kds))
void kuznyechik_encrypt_block(byte* out, const byte* in, kuznyechik_kds* kds);
void kuznyechik_decrypt_block(byte* out, const byte* in, kuznyechik_kds* kds);
void kuznyechik_set_key(const byte* key, kuznyechik_kds *kds);
#endif

View File

@ -16,6 +16,8 @@
#include "Crypto/Serpent.h"
#include "Crypto/Twofish.h"
#include "Crypto/Camellia.h"
#include "Crypto/GostCipher.h"
#include "Crypto/kuznyechik.h"
#ifdef TC_AES_HW_CPU
# include "Crypto/Aes_hw_cpu.h"
@ -80,6 +82,8 @@ namespace VeraCrypt
l.push_back (shared_ptr <Cipher> (new CipherSerpent ()));
l.push_back (shared_ptr <Cipher> (new CipherTwofish ()));
l.push_back (shared_ptr <Cipher> (new CipherCamellia ()));
l.push_back (shared_ptr <Cipher> (new CipherGost89 ()));
l.push_back (shared_ptr <Cipher> (new CipherKuznyechik ()));
return l;
}
@ -264,6 +268,46 @@ namespace VeraCrypt
camellia_set_key (key, ScheduledKey.Ptr());
}
// GOST89
void CipherGost89::Decrypt (byte *data) const
{
gost_decrypt (data, data, (gost_kds *) ScheduledKey.Ptr(), 1);
}
void CipherGost89::Encrypt (byte *data) const
{
gost_encrypt (data, data, (gost_kds *) ScheduledKey.Ptr(), 1);
}
size_t CipherGost89::GetScheduledKeySize () const
{
return GOST_KS;
}
void CipherGost89::SetCipherKey (const byte *key)
{
gost_set_key (key, (gost_kds *) ScheduledKey.Ptr());
}
// Kuznyechik
void CipherKuznyechik::Decrypt (byte *data) const
{
kuznyechik_decrypt_block (data, data, (kuznyechik_kds *) ScheduledKey.Ptr());
}
void CipherKuznyechik::Encrypt (byte *data) const
{
kuznyechik_encrypt_block (data, data, (kuznyechik_kds *) ScheduledKey.Ptr());
}
size_t CipherKuznyechik::GetScheduledKeySize () const
{
return KUZNYECHIK_KS;
}
void CipherKuznyechik::SetCipherKey (const byte *key)
{
kuznyechik_set_key (key, (kuznyechik_kds *) ScheduledKey.Ptr());
}
bool Cipher::HwSupportEnabled = true;
}

View File

@ -107,6 +107,8 @@ namespace VeraCrypt
TC_CIPHER (Serpent, 16, 32);
TC_CIPHER (Twofish, 16, 32);
TC_CIPHER (Camellia, 16, 32);
TC_CIPHER (Gost89, 16, 32);
TC_CIPHER (Kuznyechik, 16, 32);
#undef TC_CIPHER

View File

@ -65,6 +65,8 @@ namespace VeraCrypt
l.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new Camellia ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new GOST89 ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new Kuznyechik ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
l.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
@ -293,4 +295,21 @@ namespace VeraCrypt
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
}
// GOST89
GOST89::GOST89 ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherGost89()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
}
// Kuznyechik
Kuznyechik::Kuznyechik ()
{
Ciphers.push_back (shared_ptr <Cipher> (new CipherKuznyechik()));
SupportedModes.push_back (shared_ptr <EncryptionMode> (new EncryptionModeXTS ()));
}
}

View File

@ -86,6 +86,8 @@ namespace VeraCrypt
TC_ENCRYPTION_ALGORITHM (TwofishSerpent);
TC_ENCRYPTION_ALGORITHM (SerpentTwofishAES);
TC_ENCRYPTION_ALGORITHM (Camellia);
TC_ENCRYPTION_ALGORITHM (GOST89);
TC_ENCRYPTION_ALGORITHM (Kuznyechik);
#undef TC_ENCRYPTION_ALGORITHM
}

View File

@ -847,7 +847,7 @@ namespace VeraCrypt
nTestsPerformed++;
}
if (nTestsPerformed != 90)
if (nTestsPerformed != 100)
throw TestFailed (SRC_POS);
}
@ -872,5 +872,15 @@ namespace VeraCrypt
pkcs5HmacWhirlpool.DeriveKey (derivedKey, password, salt, 5);
if (memcmp (derivedKey.Ptr(), "\x50\x7c\x36\x6f", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacSha256 pkcs5HmacSha256;
pkcs5HmacSha256.DeriveKey (derivedKey, password, salt, 5);
if (memcmp (derivedKey.Ptr(), "\xf2\xa0\x4f\xb2", 4) != 0)
throw TestFailed (SRC_POS);
Pkcs5HmacStreebog pkcs5HmacStreebog;
pkcs5HmacStreebog.DeriveKey (derivedKey, password, salt, 5);
if (memcmp (derivedKey.Ptr(), "\xd0\x53\xa2\x30", 4) != 0)
throw TestFailed (SRC_POS);
}
}

View File

@ -15,6 +15,7 @@
#include "Crypto/Rmd160.h"
#include "Crypto/Sha2.h"
#include "Crypto/Whirlpool.h"
#include "Crypto/Streebog.h"
namespace VeraCrypt
{
@ -138,4 +139,28 @@ namespace VeraCrypt
if_debug (ValidateDataParameters (data));
WHIRLPOOL_add (data.Get(), (int) data.Size(), (WHIRLPOOL_CTX *) Context.Ptr());
}
// Streebog
Streebog::Streebog ()
{
Context.Allocate (sizeof (STREEBOG_CTX));
Init();
}
void Streebog::GetDigest (const BufferPtr &buffer)
{
if_debug (ValidateDigestParameters (buffer));
STREEBOG_finalize ((STREEBOG_CTX *) Context.Ptr(), buffer);
}
void Streebog::Init ()
{
STREEBOG_init ((STREEBOG_CTX *) Context.Ptr());
}
void Streebog::ProcessData (const ConstBufferPtr &data)
{
if_debug (ValidateDataParameters (data));
STREEBOG_add (data.Get(), (int) data.Size(), (STREEBOG_CTX *) Context.Ptr());
}
}

View File

@ -139,6 +139,29 @@ namespace VeraCrypt
Whirlpool (const Whirlpool &);
Whirlpool &operator= (const Whirlpool &);
};
// Streebog
class Streebog : public Hash
{
public:
Streebog ();
virtual ~Streebog () { }
virtual void GetDigest (const BufferPtr &buffer);
virtual size_t GetBlockSize () const { return 64; }
virtual size_t GetDigestSize () const { return 512 / 8; }
virtual wstring GetName () const { return L"Streebog"; }
virtual wstring GetAltName () const { return L"Streebog"; }
virtual shared_ptr <Hash> GetNew () const { return shared_ptr <Hash> (new Streebog); }
virtual void Init ();
virtual void ProcessData (const ConstBufferPtr &data);
protected:
private:
Streebog (const Streebog &);
Streebog &operator= (const Streebog &);
};
}
#endif // TC_HEADER_Encryption_Hash

View File

@ -66,6 +66,7 @@ namespace VeraCrypt
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacWhirlpool (false)));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacSha256 ()));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacRipemd160 (false)));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacStreebog ()));
}
return l;
@ -112,4 +113,16 @@ namespace VeraCrypt
ValidateParameters (key, password, salt, iterationCount);
derive_key_whirlpool ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size());
}
void Pkcs5HmacStreebog::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
ValidateParameters (key, password, salt, iterationCount);
derive_key_streebog ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size());
}
void Pkcs5HmacStreebog_Boot::DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const
{
ValidateParameters (key, password, salt, iterationCount);
derive_key_streebog ((char *) password.DataPtr(), (int) password.Size(), (char *) salt.Get(), (int) salt.Size(), iterationCount, (char *) key.Get(), (int) key.Size());
}
}

View File

@ -152,6 +152,40 @@ namespace VeraCrypt
Pkcs5HmacWhirlpool (const Pkcs5HmacWhirlpool &);
Pkcs5HmacWhirlpool &operator= (const Pkcs5HmacWhirlpool &);
};
class Pkcs5HmacStreebog : public Pkcs5Kdf
{
public:
Pkcs5HmacStreebog () : Pkcs5Kdf(false) { }
virtual ~Pkcs5HmacStreebog () { }
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Streebog); }
virtual int GetIterationCount (int pim) const { return pim <= 0 ? 500000 : (15000 + (pim * 1000)); }
virtual wstring GetName () const { return L"HMAC-Streebog"; }
virtual Pkcs5Kdf* Clone () const { return new Pkcs5HmacStreebog(m_truecryptMode); }
private:
Pkcs5HmacStreebog (const Pkcs5HmacStreebog &);
Pkcs5HmacStreebog &operator= (const Pkcs5HmacStreebog &);
};
class Pkcs5HmacStreebog_Boot : public Pkcs5Kdf
{
public:
Pkcs5HmacStreebog_Boot () : Pkcs5Kdf(false) { }
virtual ~Pkcs5HmacStreebog_Boot () { }
virtual void DeriveKey (const BufferPtr &key, const VolumePassword &password, const ConstBufferPtr &salt, int iterationCount) const;
virtual shared_ptr <Hash> GetHash () const { return shared_ptr <Hash> (new Streebog); }
virtual int GetIterationCount (int pim) const { return pim <= 0 ? 200000 : pim * 2048; }
virtual wstring GetName () const { return L"HMAC-Streebog"; }
virtual Pkcs5Kdf* Clone () const { return new Pkcs5HmacStreebog_Boot(m_truecryptMode); }
private:
Pkcs5HmacStreebog_Boot (const Pkcs5HmacStreebog_Boot &);
Pkcs5HmacStreebog_Boot &operator= (const Pkcs5HmacStreebog_Boot &);
};
}
#endif // TC_HEADER_Encryption_Pkcs5

View File

@ -52,6 +52,9 @@ OBJS += ../Crypto/Sha2.o
OBJS += ../Crypto/Twofish.o
OBJS += ../Crypto/Whirlpool.o
OBJS += ../Crypto/Camellia.o
OBJS += ../Crypto/GostCipher.o
OBJS += ../Crypto/Streebog.o
OBJS += ../Crypto/kuznyechik.o
OBJS += ../Common/Crc.o
OBJS += ../Common/Endian.o

View File

@ -100,6 +100,8 @@ namespace VeraCrypt
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Camellia ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new GOST89 ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Kuznyechik ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
@ -139,6 +141,8 @@ namespace VeraCrypt
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Camellia ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new GOST89 ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Kuznyechik ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
@ -185,6 +189,8 @@ namespace VeraCrypt
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Serpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Twofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Camellia ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new GOST89 ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new Kuznyechik ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofish ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new AESTwofishSerpent ()));
SupportedEncryptionAlgorithms.push_back (shared_ptr <EncryptionAlgorithm> (new SerpentAES ()));
@ -210,6 +216,12 @@ namespace VeraCrypt
if (!truecryptMode)
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacSha256_Boot ()));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacRipemd160_1000 (truecryptMode)));
if (!truecryptMode)
{
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacSha512 (false)));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacWhirlpool (false)));
l.push_back (shared_ptr <Pkcs5Kdf> (new Pkcs5HmacStreebog ()));
}
return l;
}
}