1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2025-11-11 19:08:26 -06:00

Add support for SHA-256 in key derivation for bootloader encryption. Create separate bootloader images for SHA-256 and RIPEMD-160. Set SHA-256 as the default PRF for boot encryption and SHA-512 as default PRF for all other cases. Depricate RIPEMD-160.

This commit is contained in:
Mounir IDRASSI
2014-10-14 17:09:18 +02:00
parent bd7d151abf
commit f38cf0b694
7 changed files with 252 additions and 28 deletions

View File

@@ -16,6 +16,8 @@
#ifndef TC_WINDOWS_BOOT
#include "Sha2.h"
#include "Whirlpool.h"
#else
#include "Sha2Small.h"
#endif
#include "Pkcs5.h"
#include "Crypto.h"
@@ -32,6 +34,155 @@ void hmac_truncate
d2[i] = d1[i];
}
#if !defined(TC_WINDOWS_BOOT) || defined(TC_WINDOWS_BOOT_SHA2)
void hmac_sha256
(
char *k, /* secret key */
int lk, /* length of the key in bytes */
char *d, /* data */
int ld, /* length of data in bytes */
char *out /* output buffer, at least "t" bytes */
)
{
sha256_ctx ictx, octx;
char isha[SHA256_DIGESTSIZE], osha[SHA256_DIGESTSIZE];
char key[SHA256_DIGESTSIZE];
char buf[SHA256_BLOCKSIZE];
int i;
/* If the key is longer than the hash algorithm block size,
let key = sha256(key), as per HMAC specifications. */
if (lk > SHA256_BLOCKSIZE)
{
sha256_ctx tctx;
sha256_begin (&tctx);
sha256_hash ((unsigned char *) k, lk, &tctx);
sha256_end ((unsigned char *) key, &tctx);
k = key;
lk = SHA256_DIGESTSIZE;
burn (&tctx, sizeof(tctx)); // Prevent leaks
}
/**** Inner Digest ****/
sha256_begin (&ictx);
/* Pad the key for inner digest */
for (i = 0; i < lk; ++i)
buf[i] = (char) (k[i] ^ 0x36);
for (i = lk; i < SHA256_BLOCKSIZE; ++i)
buf[i] = 0x36;
sha256_hash ((unsigned char *) buf, SHA256_BLOCKSIZE, &ictx);
sha256_hash ((unsigned char *) d, ld, &ictx);
sha256_end ((unsigned char *) isha, &ictx);
/**** Outer Digest ****/
sha256_begin (&octx);
for (i = 0; i < lk; ++i)
buf[i] = (char) (k[i] ^ 0x5C);
for (i = lk; i < SHA256_BLOCKSIZE; ++i)
buf[i] = 0x5C;
sha256_hash ((unsigned char *) buf, SHA256_BLOCKSIZE, &octx);
sha256_hash ((unsigned char *) isha, SHA256_DIGESTSIZE, &octx);
sha256_end ((unsigned char *) osha, &octx);
/* truncate and print the results */
hmac_truncate (osha, out, SHA256_DIGESTSIZE);
/* Prevent leaks */
burn (&ictx, sizeof(ictx));
burn (&octx, sizeof(octx));
burn (isha, sizeof(isha));
burn (osha, sizeof(osha));
burn (buf, sizeof(buf));
burn (key, sizeof(key));
}
void derive_u_sha256 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b)
{
char j[SHA256_DIGESTSIZE], k[SHA256_DIGESTSIZE];
char init[128];
char counter[4];
uint32 c;
int i;
if (iterations == 2000)
c = 200000;
else
c = 500000;
/* iteration 1 */
memset (counter, 0, 4);
counter[3] = (char) b;
memcpy (init, salt, salt_len); /* salt */
memcpy (&init[salt_len], counter, 4); /* big-endian block number */
hmac_sha256 (pwd, pwd_len, init, salt_len + 4, j);
memcpy (u, j, SHA256_DIGESTSIZE);
/* remaining iterations */
while (c > 1)
{
hmac_sha256 (pwd, pwd_len, j, SHA256_DIGESTSIZE, k);
for (i = 0; i < SHA256_DIGESTSIZE; i++)
{
u[i] ^= k[i];
j[i] = k[i];
}
c--;
}
/* Prevent possible leaks. */
burn (j, sizeof(j));
burn (k, sizeof(k));
}
void derive_key_sha256 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen)
{
char u[SHA256_DIGESTSIZE];
int b, l, r;
if (dklen % SHA256_DIGESTSIZE)
{
l = 1 + dklen / SHA256_DIGESTSIZE;
}
else
{
l = dklen / SHA256_DIGESTSIZE;
}
r = dklen - (l - 1) * SHA256_DIGESTSIZE;
/* first l - 1 blocks */
for (b = 1; b < l; b++)
{
derive_u_sha256 (pwd, pwd_len, salt, salt_len, iterations, u, b);
memcpy (dk, u, SHA256_DIGESTSIZE);
dk += SHA256_DIGESTSIZE;
}
/* last block */
derive_u_sha256 (pwd, pwd_len, salt, salt_len, iterations, u, b);
memcpy (dk, u, r);
/* Prevent possible leaks. */
burn (u, sizeof(u));
}
#endif
#ifndef TC_WINDOWS_BOOT
void hmac_sha512
@@ -176,6 +327,8 @@ void derive_key_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int it
#endif // TC_WINDOWS_BOOT
#if !defined(TC_WINDOWS_BOOT) || defined(TC_WINDOWS_BOOT_RIPEMD160)
void hmac_ripemd160 (char *key, int keylen, char *input, int len, char *digest)
{
RMD160_CTX context;
@@ -319,6 +472,7 @@ void derive_key_ripemd160 (BOOL bNotTest, char *pwd, int pwd_len, char *salt, in
/* Prevent possible leaks. */
burn (u, sizeof(u));
}
#endif // TC_WINDOWS_BOOT
#ifndef TC_WINDOWS_BOOT
@@ -468,6 +622,9 @@ char *get_pkcs5_prf_name (int pkcs5_prf_id)
case SHA512:
return "HMAC-SHA-512";
case SHA256:
return "HMAC-SHA-256";
case RIPEMD160:
return "HMAC-RIPEMD-160";
@@ -488,7 +645,7 @@ int get_pkcs5_iteration_count (int pkcs5_prf_id, BOOL bBoot)
{
case RIPEMD160:
return bBoot? 16384 : 32767; /* we multiply this number by 10 inside derive_u_ripemd160 */
return bBoot? 16384 : 32767; /* it will be changed to 327661 and 655331 respectively inside derive_u_ripemd160 */
#ifndef TC_WINDOWS_BOOT
@@ -499,6 +656,9 @@ int get_pkcs5_iteration_count (int pkcs5_prf_id, BOOL bBoot)
return 500000;
#endif
case SHA256:
return bBoot? 2000 : 5000; /* it will be changed to 200000 and 500000 respectively inside derive_u_sha256 */
default:
TC_THROW_FATAL_EXCEPTION; // Unknown/wrong ID
}