VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/Crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/Crypto.c')
-rw-r--r--src/Common/Crypto.c161
1 files changed, 119 insertions, 42 deletions
diff --git a/src/Common/Crypto.c b/src/Common/Crypto.c
index e5a3218e..f3045d0c 100644
--- a/src/Common/Crypto.c
+++ b/src/Common/Crypto.c
@@ -1,11 +1,11 @@
/*
Legal Notice: Some portions of the source code contained in this file were
- derived from the source code of TrueCrypt 7.1a, which is
- Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
+ derived from the source code of TrueCrypt 7.1a, which is
+ Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
governed by the TrueCrypt License 3.0, also from the source code of
Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
- and which is governed by the 'License Agreement for Encryption for the Masses'
- Modifications and additions to the original source code (contained in this file)
+ and which is governed by the 'License Agreement for Encryption for the Masses'
+ Modifications and additions to the original source code (contained in this file)
and all other portions of this file are Copyright (c) 2013-2016 IDRIX
and are governed by the Apache License 2.0 the full text of which is
contained in the file License.txt included in VeraCrypt binary and source
@@ -16,12 +16,16 @@
#include "Xts.h"
#include "Crc.h"
#include "Common/Endian.h"
+#if !defined(_UEFI)
#include <string.h>
#ifndef TC_WINDOWS_BOOT
#include "EncryptionThreadPool.h"
#endif
+#endif
#include "Volumes.h"
+#include "cpu.h"
+#pragma warning (disable:4706) // assignment within conditional expression
/* Update the following when adding a new cipher or EA:
Crypto.h:
@@ -52,6 +56,11 @@ static Cipher Ciphers[] =
{ AES, L"AES", 16, 32, AES_KS },
{ SERPENT, L"Serpent", 16, 32, 140*4 },
{ TWOFISH, L"Twofish", 16, 32, TWOFISH_KS },
+ { CAMELLIA, L"Camellia", 16, 32, CAMELLIA_KS },
+#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 }
};
@@ -64,16 +73,21 @@ static EncryptionAlgorithm EncryptionAlgorithms[] =
#ifndef TC_WINDOWS_BOOT
- { { 0, 0 }, { 0, 0}, 0 }, // Must be all-zero
- { { AES, 0 }, { XTS, 0 }, 1 },
- { { SERPENT, 0 }, { XTS, 0 }, 1 },
- { { TWOFISH, 0 }, { XTS, 0 }, 1 },
- { { TWOFISH, AES, 0 }, { XTS, 0 }, 1 },
- { { SERPENT, TWOFISH, AES, 0 }, { XTS, 0 }, 1 },
- { { AES, SERPENT, 0 }, { XTS, 0 }, 1 },
- { { AES, TWOFISH, SERPENT, 0 }, { XTS, 0 }, 1 },
- { { SERPENT, TWOFISH, 0 }, { XTS, 0 }, 1 },
- { { 0, 0 }, { 0, 0}, 0 } // Must be all-zero
+ { { 0, 0 }, { 0, 0}, 0, 0 }, // Must be all-zero
+ { { AES, 0 }, { XTS, 0 }, 1, 1 },
+ { { SERPENT, 0 }, { XTS, 0 }, 1, 1 },
+ { { TWOFISH, 0 }, { XTS, 0 }, 1, 1 },
+ { { CAMELLIA, 0 }, { XTS, 0 }, 1, 1 },
+#if defined(CIPHER_GOST89)
+ { { GOST89, 0 }, { XTS, 0 }, 0, 1 },
+#endif // defined(CIPHER_GOST89)
+ { { KUZNYECHIK, 0 }, { XTS, 0 }, 0, 1 },
+ { { TWOFISH, AES, 0 }, { XTS, 0 }, 1, 1 },
+ { { SERPENT, TWOFISH, AES, 0 }, { XTS, 0 }, 1, 1 },
+ { { AES, SERPENT, 0 }, { XTS, 0 }, 1, 1 },
+ { { AES, TWOFISH, SERPENT, 0 }, { XTS, 0 }, 1, 1 },
+ { { SERPENT, TWOFISH, 0 }, { XTS, 0 }, 1, 1 },
+ { { 0, 0 }, { 0, 0}, 0, 0 } // Must be all-zero
#else // TC_WINDOWS_BOOT
@@ -97,11 +111,12 @@ static EncryptionAlgorithm EncryptionAlgorithms[] =
#ifndef TC_WINDOWS_BOOT
// Hash algorithms
static Hash Hashes[] =
-{ // ID Name Deprecated System Encryption
- { SHA512, L"SHA-512", FALSE, FALSE },
- { WHIRLPOOL, L"Whirlpool", FALSE, FALSE },
- { SHA256, L"SHA-256", FALSE, TRUE },
- { RIPEMD160, L"RIPEMD-160", TRUE, TRUE },
+{ // ID Name Deprecated System Encryption
+ { SHA512, L"SHA-512", FALSE, FALSE },
+ { 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
@@ -129,11 +144,28 @@ int CipherInit (int cipher, unsigned char *key, unsigned __int8 *ks)
case SERPENT:
serpent_set_key (key, ks);
break;
-
+
case TWOFISH:
twofish_set_key ((TwofishInstance *)ks, (const u4byte *)key);
break;
+#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_CAMELLIA)
+ case CAMELLIA:
+ camellia_set_key (key, ks);
+ break;
+#endif
+
+#if !defined(TC_WINDOWS_BOOT)
+#if defined(CIPHER_GOST89)
+ case GOST89:
+ 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:
// Unknown/wrong cipher ID
return ERR_CIPHER_INIT_FAILURE;
@@ -146,7 +178,7 @@ void EncipherBlock(int cipher, void *data, void *ks)
{
switch (cipher)
{
- case AES:
+ case AES:
// In 32-bit kernel mode, due to KeSaveFloatingPointState() overhead, AES instructions can be used only when processing the whole data unit.
#if (defined (_WIN64) || !defined (TC_WINDOWS_DRIVER)) && !defined (TC_WINDOWS_BOOT)
if (IsAesHwCpuSupported())
@@ -158,6 +190,15 @@ void EncipherBlock(int cipher, void *data, void *ks)
case TWOFISH: twofish_encrypt (ks, data, data); break;
case SERPENT: serpent_encrypt (data, data, ks); break;
+#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_CAMELLIA)
+ case CAMELLIA: camellia_encrypt (data, data, ks); break;
+#endif
+#if !defined(TC_WINDOWS_BOOT)
+#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
}
}
@@ -191,6 +232,9 @@ void EncipherBlocks (int cipher, void *dataPtr, void *ks, size_t blockCount)
KeRestoreFloatingPointState (&floatingPointState);
#endif
}
+ else if (cipher == GOST89) {
+ gost_encrypt(data, data, ks, (int)blockCount);
+ }
else
{
size_t blockSize = CipherGetBlockSize (cipher);
@@ -210,6 +254,17 @@ void DecipherBlock(int cipher, void *data, void *ks)
{
case SERPENT: serpent_decrypt (data, data, ks); break;
case TWOFISH: twofish_decrypt (ks, data, data); break;
+#if !defined (TC_WINDOWS_BOOT) || defined (TC_WINDOWS_BOOT_CAMELLIA)
+ case CAMELLIA: camellia_decrypt (data, data, ks); break;
+#endif
+#if !defined(TC_WINDOWS_BOOT)
+#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)
+
+
#ifndef TC_WINDOWS_BOOT
case AES:
@@ -257,6 +312,9 @@ void DecipherBlocks (int cipher, void *dataPtr, void *ks, size_t blockCount)
KeRestoreFloatingPointState (&floatingPointState);
#endif
}
+ else if (cipher == GOST89) {
+ gost_decrypt(data, data, ks, (int)blockCount);
+ }
else
{
size_t blockSize = CipherGetBlockSize (cipher);
@@ -325,7 +383,8 @@ int CipherGetKeyScheduleSize (int cipherId)
BOOL CipherSupportsIntraDataUnitParallelization (int cipher)
{
- return cipher == AES && IsAesHwCpuSupported();
+ return cipher == AES && IsAesHwCpuSupported() ||
+ cipher == GOST89;
}
#endif
@@ -399,11 +458,11 @@ BOOL EAInitMode (PCRYPTO_INFO ci)
/* Note: XTS mode could potentially be initialized with a weak key causing all blocks in one data unit
on the volume to be tweaked with zero tweaks (i.e. 512 bytes of the volume would be encrypted in ECB
mode). However, to create a TrueCrypt volume with such a weak key, each human being on Earth would have
- to create approximately 11,378,125,361,078,862 (about eleven quadrillion) TrueCrypt volumes (provided
+ to create approximately 11,378,125,361,078,862 (about eleven quadrillion) TrueCrypt volumes (provided
that the size of each of the volumes is 1024 terabytes). */
break;
- default:
+ default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
}
@@ -450,8 +509,12 @@ int EAGetByName (wchar_t *name)
do
{
- EAGetName (n, ea, 1);
- if (_wcsicmp (n, name) == 0)
+ EAGetName(n, ea, 1);
+#if defined(_UEFI)
+ if (wcscmp(n, name) == 0)
+#else
+ if (_wcsicmp(n, name) == 0)
+#endif
return ea;
}
while (ea = EAGetNext (ea));
@@ -488,7 +551,7 @@ int EAGetNextMode (int ea, int previousModeId)
int c, i = 0;
while (c = EncryptionAlgorithms[ea].Modes[i++])
{
- if (c == previousModeId)
+ if (c == previousModeId)
return EncryptionAlgorithms[ea].Modes[i];
}
@@ -591,7 +654,7 @@ int EAGetNextCipher (int ea, int previousCipherId)
int c, i = 0;
while (c = EncryptionAlgorithms[ea].Ciphers[i++])
{
- if (c == previousCipherId)
+ if (c == previousCipherId)
return EncryptionAlgorithms[ea].Ciphers[i];
}
@@ -608,7 +671,7 @@ int EAGetPreviousCipher (int ea, int previousCipherId)
while (c = EncryptionAlgorithms[ea].Ciphers[i++])
{
- if (c == previousCipherId)
+ if (c == previousCipherId)
return EncryptionAlgorithms[ea].Ciphers[i - 2];
}
@@ -621,6 +684,12 @@ int EAIsFormatEnabled (int ea)
return EncryptionAlgorithms[ea].FormatEnabled;
}
+#ifndef TC_WINDOWS_BOOT
+int EAIsMbrSysEncEnabled (int ea)
+{
+ return EncryptionAlgorithms[ea].MbrSysEncEnabled;
+}
+#endif
// Returns TRUE if the mode of operation is supported for the encryption algorithm
BOOL EAIsModeSupported (int ea, int testedMode)
@@ -720,7 +789,7 @@ PCRYPTO_INFO crypto_open ()
memset (cryptoInfo, 0, sizeof (CRYPTO_INFO));
-#ifndef DEVICE_DRIVER
+#if !defined(DEVICE_DRIVER) && !defined(_UEFI)
VirtualLock (cryptoInfo, sizeof (CRYPTO_INFO));
#endif
@@ -755,7 +824,7 @@ void crypto_close (PCRYPTO_INFO cryptoInfo)
if (cryptoInfo != NULL)
{
burn (cryptoInfo, sizeof (CRYPTO_INFO));
-#ifndef DEVICE_DRIVER
+#if !defined(DEVICE_DRIVER) && !defined(_UEFI)
VirtualUnlock (cryptoInfo, sizeof (CRYPTO_INFO));
#endif
TCfree (cryptoInfo);
@@ -777,7 +846,7 @@ void crypto_close (PCRYPTO_INFO cryptoInfo)
// EncryptBuffer
//
// buf: data to be encrypted; the start of the buffer is assumed to be aligned with the start of a data unit.
-// len: number of bytes to encrypt; must be divisible by the block size (for cascaded ciphers, divisible
+// len: number of bytes to encrypt; must be divisible by the block size (for cascaded ciphers, divisible
// by the largest block size used within the cascade)
void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo)
{
@@ -808,7 +877,7 @@ void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_
}
break;
- default:
+ default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
}
@@ -819,7 +888,7 @@ void EncryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_
// unitNo: sequential number of the data unit with which the buffer starts
// nbrUnits: number of data units in the buffer
void EncryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, uint32 nbrUnits, PCRYPTO_INFO ci)
-#ifndef TC_WINDOWS_BOOT
+#if !defined(TC_WINDOWS_BOOT) && !defined(_UEFI)
{
EncryptionThreadPoolDoWork (EncryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci);
}
@@ -850,7 +919,7 @@ void EncryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *s
}
break;
- default:
+ default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
}
@@ -859,7 +928,7 @@ void EncryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *s
// DecryptBuffer
//
// buf: data to be decrypted; the start of the buffer is assumed to be aligned with the start of a data unit.
-// len: number of bytes to decrypt; must be divisible by the block size (for cascaded ciphers, divisible
+// len: number of bytes to decrypt; must be divisible by the block size (for cascaded ciphers, divisible
// by the largest block size used within the cascade)
void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo)
{
@@ -890,7 +959,7 @@ void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_
}
break;
- default:
+ default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
}
@@ -900,7 +969,7 @@ void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_
// unitNo: sequential number of the data unit with which the buffer starts
// nbrUnits: number of data units in the buffer
void DecryptDataUnits (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, uint32 nbrUnits, PCRYPTO_INFO ci)
-#ifndef TC_WINDOWS_BOOT
+#if !defined(TC_WINDOWS_BOOT) && !defined(_UEFI)
{
EncryptionThreadPoolDoWork (DecryptDataUnitsWork, buf, structUnitNo, nbrUnits, ci);
}
@@ -935,7 +1004,7 @@ void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *s
}
break;
- default:
+ default:
// Unknown/wrong ID
TC_THROW_FATAL_EXCEPTION;
}
@@ -945,7 +1014,7 @@ void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *s
#else // TC_WINDOWS_BOOT_SINGLE_CIPHER_MODE
-#if !defined (TC_WINDOWS_BOOT_AES) && !defined (TC_WINDOWS_BOOT_SERPENT) && !defined (TC_WINDOWS_BOOT_TWOFISH)
+#if !defined (TC_WINDOWS_BOOT_AES) && !defined (TC_WINDOWS_BOOT_SERPENT) && !defined (TC_WINDOWS_BOOT_TWOFISH) && !defined (TC_WINDOWS_BOOT_CAMELLIA)
#error No cipher defined
#endif
@@ -955,11 +1024,13 @@ void EncipherBlock(int cipher, void *data, void *ks)
if (IsAesHwCpuSupported())
aes_hw_cpu_encrypt ((byte *) ks, data);
else
- aes_encrypt (data, data, ks);
+ aes_encrypt (data, data, ks);
#elif defined (TC_WINDOWS_BOOT_SERPENT)
serpent_encrypt (data, data, ks);
#elif defined (TC_WINDOWS_BOOT_TWOFISH)
twofish_encrypt (ks, data, data);
+#elif defined (TC_WINDOWS_BOOT_CAMELLIA)
+ camellia_encrypt (data, data, ks);
#endif
}
@@ -969,11 +1040,13 @@ void DecipherBlock(int cipher, void *data, void *ks)
if (IsAesHwCpuSupported())
aes_hw_cpu_decrypt ((byte *) ks + sizeof (aes_encrypt_ctx) + 14 * 16, data);
else
- aes_decrypt (data, data, (aes_decrypt_ctx *) ((byte *) ks + sizeof(aes_encrypt_ctx)));
+ aes_decrypt (data, data, (aes_decrypt_ctx *) ((byte *) ks + sizeof(aes_encrypt_ctx)));
#elif defined (TC_WINDOWS_BOOT_SERPENT)
serpent_decrypt (data, data, ks);
#elif defined (TC_WINDOWS_BOOT_TWOFISH)
twofish_decrypt (ks, data, data);
+#elif defined (TC_WINDOWS_BOOT_CAMELLIA)
+ camellia_decrypt (data, data, ks);
#endif
}
@@ -1033,7 +1106,11 @@ BOOL IsAesHwCpuSupported ()
if (!stateValid)
{
+#ifdef TC_WINDOWS_BOOT_AES
state = is_aes_hw_cpu_supported() ? TRUE : FALSE;
+#else
+ state = g_hasAESNI ? TRUE : FALSE;
+#endif
stateValid = TRUE;
}