diff options
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/Crypto.c | 47 | ||||
-rw-r--r-- | src/Common/Crypto.h | 23 | ||||
-rw-r--r-- | src/Common/Pkcs5.c | 162 | ||||
-rw-r--r-- | src/Common/Pkcs5.h | 3 | ||||
-rw-r--r-- | src/Common/Volumes.c | 24 |
5 files changed, 234 insertions, 25 deletions
diff --git a/src/Common/Crypto.c b/src/Common/Crypto.c index a63bc954..9fc69022 100644 --- a/src/Common/Crypto.c +++ b/src/Common/Crypto.c @@ -90,11 +90,12 @@ static EncryptionAlgorithm EncryptionAlgorithms[] = // Hash algorithms
static Hash Hashes[] =
{ // ID Name Deprecated System Encryption
- { RIPEMD160, "RIPEMD-160", FALSE, TRUE },
#ifndef TC_WINDOWS_BOOT
{ SHA512, "SHA-512", FALSE, FALSE },
{ WHIRLPOOL, "Whirlpool", FALSE, FALSE },
#endif
+ { SHA256, "SHA-256", FALSE, TRUE },
+ { RIPEMD160, "RIPEMD-160", TRUE, TRUE },
{ 0, 0, 0 }
};
@@ -651,17 +652,42 @@ char *HashGetName (int hashId) #endif
}
+#ifndef TC_WINDOWS_BOOT
+void HashGetName2 (char *buf, int hashId)
+{
+ Hash* pHash = HashGet(hashId);
+ if (pHash)
+ strcpy(buf, pHash -> Name);
+ else
+ buf[0] = '\0';
+}
BOOL HashIsDeprecated (int hashId)
{
-#ifdef TC_WINDOWS_BOOT
- return HashGet(hashId) -> Deprecated;
-#else
Hash* pHash = HashGet(hashId);
return pHash? pHash -> Deprecated : FALSE;
-#endif
+
}
+BOOL HashForSystemEncryption (int hashId)
+{
+ Hash* pHash = HashGet(hashId);
+ return pHash? pHash -> SystemEncryption : FALSE;
+
+}
+
+// Returns the maximum number of bytes necessary to be generated by the PBKDF2 (PKCS #5)
+int GetMaxPkcs5OutSize (void)
+{
+ int size = 32;
+
+ size = max (size, EAGetLargestKeyForMode (XTS) * 2); // Sizes of primary + secondary keys
+
+ return size;
+}
+
+#endif
+
#endif // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
@@ -904,17 +930,6 @@ void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *s }
-// Returns the maximum number of bytes necessary to be generated by the PBKDF2 (PKCS #5)
-int GetMaxPkcs5OutSize (void)
-{
- int size = 32;
-
- size = max (size, EAGetLargestKeyForMode (XTS) * 2); // Sizes of primary + secondary keys
-
- return size;
-}
-
-
#else // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
diff --git a/src/Common/Crypto.h b/src/Common/Crypto.h index 651da737..7875e1a5 100644 --- a/src/Common/Crypto.h +++ b/src/Common/Crypto.h @@ -48,11 +48,10 @@ extern "C" { // Hash algorithms (pseudorandom functions).
enum
{
- RIPEMD160 = FIRST_PRF_ID,
-#ifndef TC_WINDOWS_BOOT
- SHA512,
+ SHA512 = FIRST_PRF_ID,
WHIRLPOOL,
-#endif
+ SHA256,
+ RIPEMD160,
HASH_ENUM_END_ID
};
@@ -62,6 +61,9 @@ enum #define RIPEMD160_BLOCKSIZE 64
#define RIPEMD160_DIGESTSIZE 20
+#define SHA256_BLOCKSIZE 64
+#define SHA256_DIGESTSIZE 32
+
#define SHA512_BLOCKSIZE 128
#define SHA512_DIGESTSIZE 64
@@ -71,7 +73,7 @@ enum #define MAX_DIGESTSIZE WHIRLPOOL_DIGESTSIZE
#define DEFAULT_HASH_ALGORITHM FIRST_PRF_ID
-#define DEFAULT_HASH_ALGORITHM_BOOT RIPEMD160
+#define DEFAULT_HASH_ALGORITHM_BOOT SHA256
// The mode of operation used for newly created volumes and first to try when mounting
#define FIRST_MODE_OF_OPERATION_ID 1
@@ -207,8 +209,7 @@ typedef struct CRYPTO_INFO_t 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. */
unsigned __int8 salt[PKCS5_SALT_SIZE];
- int noIterations;
- int pkcs5;
+ int noIterations;
uint64 volume_creation_time; // Legacy
uint64 header_creation_time; // Legacy
@@ -239,6 +240,7 @@ typedef struct CRYPTO_INFO_t UINT64_STRUCT EncryptedAreaLength;
uint32 HeaderFlags;
+ int pkcs5;
} CRYPTO_INFO, *PCRYPTO_INFO;
@@ -292,9 +294,14 @@ BOOL EAIsModeSupported (int ea, int testedMode); const
#endif
char *HashGetName (int hash_algo_id);
-BOOL HashIsDeprecated (int hashId);
+#ifndef TC_WINDOWS_BOOT
+void HashGetName2 (char *buf, int hashId);
+BOOL HashIsDeprecated (int hashId);
+BOOL HashForSystemEncryption (int hashId);
int GetMaxPkcs5OutSize (void);
+#endif
+
void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, uint32 nbrUnits, PCRYPTO_INFO ci);
void EncryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci);
diff --git a/src/Common/Pkcs5.c b/src/Common/Pkcs5.c index c1222a03..2901d6a1 100644 --- a/src/Common/Pkcs5.c +++ b/src/Common/Pkcs5.c @@ -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
}
diff --git a/src/Common/Pkcs5.h b/src/Common/Pkcs5.h index 148a3e2d..aff36cc4 100644 --- a/src/Common/Pkcs5.h +++ b/src/Common/Pkcs5.h @@ -18,6 +18,9 @@ extern "C"
{
#endif
+void hmac_sha256 (char *k, int lk, char *d, int ld, char *out);
+void derive_u_sha256 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b);
+void derive_key_sha256 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen);
void hmac_sha512 (char *k, int lk, char *d, int ld, char *out, int t);
void derive_u_sha512 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b);
diff --git a/src/Common/Volumes.c b/src/Common/Volumes.c index 9a0d3efc..2b7b01ab 100644 --- a/src/Common/Volumes.c +++ b/src/Common/Volumes.c @@ -316,6 +316,11 @@ KeyReady: ; PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
+ case SHA256:
+ derive_key_sha256 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
+ PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
+ break;
+
default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
@@ -561,8 +566,13 @@ int ReadVolumeHeader (BOOL bBoot, char *header, Password *password, PCRYPTO_INFO cryptoInfo = *retInfo = crypto_open ();
// PKCS5 PRF
+#ifdef TC_WINDOWS_BOOT_SHA2
+ derive_key_sha256 (password->Text, (int) password->Length, header + HEADER_SALT_OFFSET,
+ PKCS5_SALT_SIZE, bBoot ? 2000 : 5000, dk, sizeof (dk));
+#else
derive_key_ripemd160 (TRUE, password->Text, (int) password->Length, header + HEADER_SALT_OFFSET,
PKCS5_SALT_SIZE, bBoot ? 16384 : 32767, dk, sizeof (dk));
+#endif
// Mode of operation
cryptoInfo->mode = FIRST_MODE_OF_OPERATION_ID;
@@ -606,6 +616,12 @@ int ReadVolumeHeader (BOOL bBoot, char *header, Password *password, PCRYPTO_INFO // Flags
cryptoInfo->HeaderFlags = GetHeaderField32 (header, TC_HEADER_OFFSET_FLAGS);
+#ifdef TC_WINDOWS_BOOT_SHA2
+ cryptoInfo->pkcs5 = SHA256;
+#else
+ cryptoInfo->pkcs5 = RIPEMD160;
+#endif
+
memcpy (masterKey, header + HEADER_MASTER_KEYDATA_OFFSET, sizeof (masterKey));
EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
@@ -703,6 +719,9 @@ int CreateVolumeHeaderInMemory (BOOL bBoot, char *header, int ea, int mode, Pass // User selected encryption algorithm
cryptoInfo->ea = ea;
+ // User selected PRF
+ cryptoInfo->pkcs5 = pkcs5_prf;
+
// Mode of operation
cryptoInfo->mode = mode;
@@ -718,6 +737,11 @@ int CreateVolumeHeaderInMemory (BOOL bBoot, char *header, int ea, int mode, Pass PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
break;
+ case SHA256:
+ derive_key_sha256 (keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
+ PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
+ break;
+
case RIPEMD160:
derive_key_ripemd160 (TRUE, keyInfo.userKey, keyInfo.keyLength, keyInfo.salt,
PKCS5_SALT_SIZE, keyInfo.noIterations, dk, GetMaxPkcs5OutSize());
|