mirror of
https://github.com/veracrypt/VeraCrypt
synced 2024-11-24 12:03:28 +01:00
Windows: Add support for Streebog (hash) and kuznyechik (encryption)
This commit is contained in:
parent
0b2c8b09c6
commit
e90e24b30b
@ -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
|
||||
{
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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
2393
src/Crypto/Streebog.c
Normal file
File diff suppressed because it is too large
Load Diff
33
src/Crypto/Streebog.h
Normal file
33
src/Crypto/Streebog.h
Normal 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
2453
src/Crypto/kuznyechik.c
Normal file
File diff suppressed because it is too large
Load Diff
26
src/Crypto/kuznyechik.h
Normal file
26
src/Crypto/kuznyechik.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 ()));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user