mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-12 19:38:26 -06:00
Windows: Add support for Streebog (hash) and kuznyechik (encryption)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user